GRASS GIS 8 Programmer's Manual 8.3.2(2024)-exported
Loading...
Searching...
No Matches
gk.c
Go to the documentation of this file.
1/*!
2 \file lib/ogsf/gk.c
3
4 \brief OGSF library - setting and manipulating keyframes animation (lower
5 level functions)
6
7 GRASS OpenGL gsurf OGSF Library
8
9 (C) 1999-2008 by the GRASS Development Team
10
11 This program is free software under the
12 GNU General Public License (>=v2).
13 Read the file COPYING that comes with GRASS
14 for details.
15
16 \author Bill Brown USACERL, GMSL/University of Illinois
17 \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
18 */
19
20#include <stdlib.h>
21#include <math.h>
22
23#include <grass/gis.h>
24#include <grass/glocale.h>
25#include <grass/ogsf.h>
26
27static float spl3(float, double, double, double, double, double, double,
28 double);
29
30static float spl3(float tension, double data0, double data1, double x,
31 double x2, double x3, double lderiv, double rderiv)
32{
33 return ((float)(data0 * (2 * x3 - 3 * x2 + 1) + data1 * (-2 * x3 + 3 * x2) +
34 (double)tension * lderiv * (x3 - 2 * x2 + x) +
35 (double)tension * rderiv * (x3 - x2)));
36}
37
38/*!
39 \brief Copy keyframes
40
41 \param k source keyframes
42
43 \return pointer to Keylist struct (target)
44 */
45Keylist *gk_copy_key(Keylist *k)
46{
47 Keylist *newk;
48 int i;
49
50 newk = (Keylist *)G_malloc(sizeof(Keylist)); /* G_fatal_error */
51 if (!newk) {
52 return (NULL);
53 }
54
55 for (i = 0; i < KF_NUMFIELDS; i++) {
56 newk->fields[i] = k->fields[i];
57 }
58
59 newk->pos = k->pos;
60 newk->look_ahead = k->look_ahead;
61 newk->fieldmask = k->fieldmask;
62 newk->next = newk->prior = NULL;
63
64 return (newk);
65}
66
67/*!
68 \brief Get mask value
69
70 Get begin & end pos, AND all masks in keys <= pos
71
72 Time must be between 0.0 & 1.0
73
74 \param time timestamp
75 \param keys list of keyframes
76
77 \return mask value
78 */
79unsigned long gk_get_mask_sofar(float time, Keylist *keys)
80{
81 Keylist *k;
82 float startpos, endpos, curpos;
83 unsigned long mask = 0xFFFFFFFF;
84
85 if (keys) {
86 /* find end key */
87 for (k = keys; k->next; k = k->next)
88 ;
89
90 startpos = keys->pos;
91 endpos = k->pos;
92 curpos = startpos + time * (endpos - startpos);
93
94 for (k = keys; k->next; k = k->next) {
95 if (k->pos <= curpos) {
96 mask &= k->fieldmask; /* (else break) */
97 }
98 }
99 }
100
101 return (mask);
102}
103
104/*!
105 \brief ADD
106
107 \param mask mask value
108 \param keys list of keyframes
109 \param[out] keyret output list of keyframes
110
111 \return number of output keyframes
112 */
113int gk_viable_keys_for_mask(unsigned long mask, Keylist *keys, Keylist **keyret)
114{
115 Keylist *k;
116 int cnt = 0;
117
118 for (k = keys; k; k = k->next) {
119 if ((mask & k->fieldmask) == mask) {
120 keyret[cnt++] = k;
121 }
122 }
123
124 return (cnt);
125}
126
127/*!
128 \brief Checks key masks
129
130 Because if they're masked up until the current position,
131 pre-existing (or current) field should be used.
132
133 \param view pointer to Viewmode struct
134 \param numsteps number of steps
135 \param keys list of keyframes
136 \param step step value
137 \param onestep
138 \param render
139 \param mode
140 */
141void gk_follow_frames(Viewnode *view, int numsteps, Keylist *keys, int step,
142 int onestep, int render, unsigned long mode)
143{
144 Viewnode *v;
145 int frame; /* frame is index into viewnode array */
146 float tmp[3];
147 float x, y, z;
148 int num, w;
149 unsigned long mask;
150
151 for (frame = step - 1; frame < numsteps; frame++) {
152
153 v = &view[frame];
154 mask = gk_get_mask_sofar((float)frame / numsteps, keys);
155
156 /* TODO?: set view field to current settings if not set,
157 thereby keeping view structure up to date for easier saving of
158 animation? */
159
160 GS_get_from(tmp);
161 if ((mask & KF_FROMX_MASK)) {
162 tmp[X] = v->fields[KF_FROMX];
163 }
164 if ((mask & KF_FROMY_MASK)) {
165 tmp[Y] = v->fields[KF_FROMY];
166 }
167 if ((mask & KF_FROMZ_MASK)) {
168 tmp[Z] = v->fields[KF_FROMZ];
169 }
170
171 GS_moveto(tmp);
172
173 GS_get_from(tmp);
174 G_debug(3, "gk_follow_frames():");
175 G_debug(3, " MASK: %lx", mask);
176 G_debug(3, " FROM: %f %f %f", tmp[X], tmp[Y], tmp[Z]);
177
178 /* ACS 1 line: was GS_get_focus(tmp);
179 with this kanimator works also for flythrough navigation
180 also changed in GK2.c
181 */
182 GS_get_viewdir(tmp);
183 if ((mask & KF_DIRX_MASK)) {
184 tmp[X] = v->fields[KF_DIRX];
185 }
186 if ((mask & KF_DIRY_MASK)) {
187 tmp[Y] = v->fields[KF_DIRY];
188 }
189 if ((mask & KF_DIRZ_MASK)) {
190 tmp[Z] = v->fields[KF_DIRZ];
191 }
192 /* ACS 1 line: was GS_set_focus(tmp);
193 with this kanimator works also for flythrough navigation
194 also changed in GK2.c
195 */
196 GS_set_viewdir(tmp);
197
198 G_debug(3, "gk_follow_frames():");
199 GS_get_viewdir(tmp);
200 G_debug(3, " DIR: %f %f %f\n", tmp[X], tmp[Y], tmp[Z]);
201
202 if ((mask & KF_TWIST_MASK)) {
203 GS_set_twist((int)v->fields[KF_TWIST]);
204 }
205
206 if ((mask & KF_FOV_MASK)) {
207 GS_set_fov((int)v->fields[KF_FOV]);
208 }
209
210 /* Initilaize lights before drawing */
211 num = 1;
212 GS_getlight_position(num, &x, &y, &z, &w);
213 GS_setlight_position(num, x, y, z, w);
214 num = 2; /* Top light */
215 GS_setlight_position(num, 0., 0., 1., 0);
216
217 if (render) {
218 GS_set_draw(GSD_FRONT);
219 }
220 else {
221 GS_set_draw(GSD_BACK);
222 }
223
226
227 if (render) {
229 }
230 else {
232 }
233
235
236 if (mode & FM_PATH) {
237 gk_draw_path(view, numsteps, keys);
238 }
239
240 if (mode & FM_VECT) {
242 }
243
244 if (mode & FM_SITE) {
246 }
247
248 if (mode & FM_VOL) {
250 }
251
252 GS_done_draw();
253
254 if (mode & FM_LABEL) {
255 GS_draw_all_list(); /* draw labels and legend */
256 }
257
258 if (onestep) {
259 return;
260 }
261 }
262
263 return;
264}
265
266/*!
267 \brief Free keyframe list
268
269 \param ok pointer to Keylist struct
270 */
271void gk_free_key(Keylist *ok)
272{
273 Keylist *k, *prev;
274
275 if (ok) {
276 k = ok;
277 while (k) {
278 prev = k;
279 k = k->next;
280 G_free(prev);
281 }
282 }
283
284 return;
285}
286
287/*!
288 \brief Generate viewnode from keyframes
289
290 Here we use a cardinal cubic spline
291
292 \param keys list of keyframes
293 \param keysteps keyframe step
294 \param newsteps new step value
295 \param loop loop indicator
296 \param t
297
298 \return pointer to Viewnode
299 \return NULL on failure
300 */
301Viewnode *gk_make_framesfromkeys(Keylist *keys, int keysteps, int newsteps,
302 int loop, float t)
303{
304 int i;
305 Viewnode *v, *newview;
306 Keylist *k, *kp1, *kp2, *km1, **tkeys;
307 float startpos, endpos;
308 double dt1, dt2, x, x2, x3, range, time, time_step, len, rderiv, lderiv;
309
310 /* allocate tmp keys to hold valid keys for fields */
311 tkeys =
312 (Keylist **)G_malloc(keysteps * sizeof(Keylist *)); /* G_fatal_error */
313 if (!tkeys) {
314 return (NULL);
315 }
316
317 correct_twist(keys);
318
319 if (keys && keysteps) {
320 if (keysteps < 3) {
321 G_warning(_("Need at least 3 keyframes for spline"));
322 G_free(tkeys);
323 return (NULL);
324 }
325
326 /* find end key */
327 for (k = keys; k->next; k = k->next)
328 ;
329
330 startpos = keys->pos;
331 endpos = k->pos;
332 range = endpos - startpos;
333 time_step = range / (newsteps - 1);
334
335 newview = (Viewnode *)G_malloc(newsteps *
336 sizeof(Viewnode)); /* G_fatal_error */
337 if (!newview) { /* not used */
338 G_free(tkeys);
339 return (NULL);
340 }
341
342 for (i = 0; i < newsteps; i++) {
343 int field = 0;
344
345 v = &newview[i];
346
347 time = startpos + i * time_step;
348
349 if (i == newsteps - 1) {
350 time = endpos; /*to ensure no roundoff errors */
351 }
352
353 for (field = 0; field < KF_NUMFIELDS; field++) {
354 int nvk = 0; /* number of viable keyframes for this field */
355
356 /* now need to do for each field to look at mask */
357 k = kp1 = kp2 = km1 = NULL;
358 nvk = gk_viable_keys_for_mask((unsigned long)(1 << field), keys,
359 tkeys);
360 if (nvk) {
361 len = get_key_neighbors(nvk, time, range, loop, tkeys, &k,
362 &kp1, &kp2, &km1, &dt1, &dt2);
363 }
364
365 /* ACS 1 line: was if (len == 0.0) {
366 when disabling a channel no calculation must be made at all
367 (otherwise core dump)
368 */
369 if (len == 0.0 || nvk == 0) {
370 if (!k) {
371 /* none valid - use first.
372 (when showing , will be ignored anyway) */
373 v->fields[field] = keys->fields[field];
374 }
375 else if (!kp1) {
376 /* none on right - use left */
377 v->fields[field] = k->fields[field];
378 }
379
380 continue;
381 }
382 else if (!km1 && !kp2) {
383 /* only two valid - use linear */
384 v->fields[field] =
385 lin_interp((time - k->pos) / len, k->fields[field],
386 kp1->fields[field]);
387 continue;
388 }
389
390 x = (time - k->pos) / len;
391 x2 = x * x;
392 x3 = x2 * x;
393
394 if (!km1) {
395 /* leftmost interval */
396 rderiv = (kp2->fields[field] - k->fields[field]) / dt2;
397 lderiv =
398 (3 * (kp1->fields[field] - k->fields[field]) / dt1 -
399 rderiv) /
400 2.0;
401 v->fields[field] =
402 spl3(t, k->fields[field], kp1->fields[field], x, x2, x3,
403 lderiv, rderiv);
404 }
405 else if (!kp2) {
406 /* rightmost interval */
407 lderiv = (kp1->fields[field] - km1->fields[field]) / dt1;
408 rderiv =
409 (3 * (kp1->fields[field] - k->fields[field]) / dt2 -
410 lderiv) /
411 2.0;
412 v->fields[field] =
413 spl3(t, k->fields[field], kp1->fields[field], x, x2, x3,
414 lderiv, rderiv);
415 }
416 else {
417 /* not on ends */
418 lderiv = (kp1->fields[field] - km1->fields[field]) / dt1;
419 rderiv = (kp2->fields[field] - k->fields[field]) / dt2;
420 v->fields[field] =
421 spl3(t, k->fields[field], kp1->fields[field], x, x2, x3,
422 lderiv, rderiv);
423 }
424 }
425 }
426
427 G_free(tkeys);
428 return (newview);
429 }
430 else {
431 G_free(tkeys);
432 return (NULL);
433 }
434}
435
436/*!
437 \brief Find interval containing time
438
439 Changed June 94 to handle masks - now need to have called get_viable_keys
440 for appropriate mask first to build the ARRAY of viable keyframes.
441
442 Putting left (or equal) key
443 at km1, right at kp1, 2nd to right at kp2, and second to left at km2.
444 dt1 is given the length of the current + left intervals
445 dt2 is given the length of the current + right intervals
446
447 \param nvk
448 \param time
449 \param range
450 \param loop
451 \param karray
452 \param km1
453 \param kp1
454 \param kp2
455 \param km2
456 \param dt1
457 \param dt2
458
459 \return the length of the current interval
460 \return 0 on error
461 */
462double get_key_neighbors(int nvk, double time, double range, int loop,
463 Keylist *karray[], Keylist **km1, Keylist **kp1,
464 Keylist **kp2, Keylist **km2, double *dt1, double *dt2)
465{
466 int i;
467 double len;
468
469 *km1 = *kp1 = *kp2 = *km2 = NULL;
470 *dt1 = *dt2 = 0.0;
471
472 for (i = 0; i < nvk; i++) {
473 if (time < karray[i]->pos) {
474 break;
475 }
476 }
477
478 if (!i) {
479 return (0.0); /* before first keyframe or nvk == 0 */
480 }
481
482 if (i == nvk) {
483 /* past or == last keyframe! */
484 *km1 = karray[nvk - 1];
485 return (0.0);
486 }
487
488 /* there's at least 2 */
489 *km1 = karray[i - 1];
490 *kp1 = karray[i];
491 len = karray[i]->pos - karray[i - 1]->pos;
492
493 if (i == 1) {
494 /* first interval */
495 if (loop) {
496 *km2 = karray[nvk - 2];
497 *kp2 = karray[(i + 1) % nvk];
498 }
499 else {
500 if (nvk > 2) {
501 *kp2 = karray[i + 1];
502 }
503 }
504 }
505 else if (i == nvk - 1) {
506 /* last interval */
507 if (loop) {
508 *km2 = nvk > 2 ? karray[i - 2] : karray[1];
509 *kp2 = karray[1];
510 }
511 else {
512 if (nvk > 2) {
513 *km2 = karray[i - 2];
514 }
515 }
516 }
517 else {
518 *km2 = karray[i - 2];
519 *kp2 = karray[i + 1];
520 }
521
522 *dt1 = (*km2) ? (*kp1)->pos - (*km2)->pos : len;
523 *dt2 = (*kp2) ? (*kp2)->pos - (*km1)->pos : len;
524
525 if (i == 1 && loop) {
526 *dt1 += range;
527 }
528
529 if (i == nvk - 1 && loop) {
530 *dt2 += range;
531 }
532
533 return (len);
534}
535
536/*!
537 \brief Linear interpolation
538
539 \param dt coefficient
540 \param val2 value 2
541 \param val1 value 1
542
543 \return val1 + dt * (val2 - val1)
544 */
545double lin_interp(float dt, float val1, float val2)
546{
547 return ((double)(val1 + dt * (val2 - val1)));
548}
549
550/*!
551 \brief Finds interval containing time, putting left (or equal) key
552 at km1, right at kp1
553
554 \param nvk
555 \param time
556 \param range
557 \param loop
558 \param karray
559 \param km1
560 \param km2
561
562 \return interval value
563 */
564double get_2key_neighbors(int nvk, float time, float range UNUSED,
565 int loop UNUSED, Keylist *karray[], Keylist **km1,
566 Keylist **kp1)
567{
568 int i;
569 double len;
570
571 *km1 = *kp1 = NULL;
572
573 for (i = 0; i < nvk; i++) {
574 if (time < karray[i]->pos) {
575 break;
576 }
577 }
578
579 if (!i) {
580 return (0.0); /* before first keyframe or nvk == 0 */
581 }
582
583 if (i == nvk) {
584 /* past or == last keyframe! */
585 *km1 = karray[nvk - 1];
586 return (0.0);
587 }
588
589 /* there's at least 2 */
590 *km1 = karray[i - 1];
591 *kp1 = karray[i];
592 len = karray[i]->pos - karray[i - 1]->pos;
593
594 return (len);
595}
596
597/*!
598 \brief Generate viewnode from keyframe list (linear interpolation)
599
600 Here we use linear interpolation. Loop variable isn't used, but left
601 in for use in possible "linear interp with smoothing" version.
602
603 \param kesy keyframe list
604 \param keysteps step value
605 \param newsteps new step value
606 \param loop loop indicator
607
608 \param pointer to viewnode struct
609 \param NULL on failure
610 */
611Viewnode *gk_make_linear_framesfromkeys(Keylist *keys, int keysteps,
612 int newsteps, int loop)
613{
614 int i, nvk;
615 Viewnode *v, *newview;
616 Keylist *k, *k1, *k2, **tkeys;
617 float startpos, endpos, dt, range, time, time_step, len;
618
619 /* allocate tmp keys to hold valid keys for fields */
620 tkeys =
621 (Keylist **)G_malloc(keysteps * sizeof(Keylist *)); /* G_fatal_error */
622 if (!tkeys) {
623 return (NULL);
624 }
625
626 correct_twist(keys);
627
628 if (keys && keysteps) {
629 if (keysteps < 2) {
630 G_warning(_("Need at least 2 keyframes for interpolation"));
631 G_free(tkeys);
632 return (NULL);
633 }
634
635 /* find end key */
636 for (k = keys; k->next; k = k->next)
637 ;
638
639 startpos = keys->pos;
640 endpos = k->pos;
641 range = endpos - startpos;
642 time_step = range / (newsteps - 1);
643
644 newview = (Viewnode *)G_malloc(newsteps *
645 sizeof(Viewnode)); /* G_fatal_error */
646 if (!newview) { /* not used */
647 G_free(tkeys);
648 return (NULL);
649 }
650
651 for (i = 0; i < newsteps; i++) {
652 int field = 0;
653
654 v = &newview[i];
655
656 time = startpos + i * time_step;
657 if (i == newsteps - 1) {
658 time = endpos; /*to ensure no roundoff errors */
659 }
660
661 for (field = 0; field < KF_NUMFIELDS; field++) {
662
663 nvk = gk_viable_keys_for_mask((unsigned long)(1 << field), keys,
664 tkeys);
665 if (!nvk) {
666 v->fields[field] =
667 keys->fields[field]; /*default-not used */
668 }
669 else {
670 len = get_2key_neighbors(nvk, time, range, loop, tkeys, &k1,
671 &k2);
672 }
673
674 /* ACS 1 line: was if (len == 0.0) {
675 when disabling a channel no calculation must be made at all
676 (otherwise core dump)
677 */
678 if (len == 0.0 || nvk == 0) {
679 if (!k1) {
680 /* none valid - use first.
681 (when showing , will be ignored anyway) */
682 v->fields[field] = keys->fields[field];
683 }
684 else if (!k2) {
685 /* none on right - use left */
686 v->fields[field] = k1->fields[field];
687 }
688 }
689 else {
690 dt = (time - k1->pos) / len;
691 v->fields[field] =
692 lin_interp(dt, k1->fields[field], k2->fields[field]);
693 }
694 }
695 }
696
697 G_free(tkeys);
698 return (newview);
699 }
700 else {
701 G_free(tkeys);
702 return (NULL);
703 }
704}
705
706/*!
707 \brief Correct twist value
708
709 \param k keyframe list
710 */
711void correct_twist(Keylist *k)
712{
713 Keylist *c, *p, *t;
714 int cnt, j;
715
716 p = NULL;
717 cnt = 0;
718 for (c = k; c; c = c->next) {
719 if (p) {
720 if ((c->fields[KF_TWIST] - p->fields[KF_TWIST]) > 1800.) {
721 for (t = c; t; t = t->next) {
722 t->fields[KF_TWIST] -= 3600.;
723 }
724 }
725 else if ((p->fields[KF_TWIST] - c->fields[KF_TWIST]) > 1800.) {
726 for (t = k, j = 0; j < cnt; j++, t = t->next) {
727 t->fields[KF_TWIST] -= 3600.;
728 }
729 }
730 }
731
732 p = c;
733 ++cnt;
734 }
735
736 return;
737}
738
739/*!
740 \brief Draw path
741
742 \param views Viewnode struct
743 \param steps step value
744 \param keys keyframe list
745
746 \return 0 on failure
747 \return 1 on success
748 */
749int gk_draw_path(Viewnode *views, int steps, Keylist *keys)
750{
751 Viewnode *v;
752 Keylist *k;
753 int frame;
754 float siz, from[3];
755
756 if (!views || !keys) {
757 return (0);
758 }
759
760 GS_get_longdim(&siz);
761 siz /= 200.;
762
763 gsd_colormode(CM_COLOR);
764 gsd_linewidth(2);
767
768 gsd_bgnline();
769
770 for (frame = 0; frame < steps; frame++) {
771 v = &views[frame];
772 gsd_vert_func(&(v->fields[KF_FROMX]));
773 }
774
775 gsd_endline();
776
777 gsd_linewidth(1);
778
779 for (k = keys; k; k = k->next) {
780 gsd_x(NULL, &(k->fields[KF_FROMX]), ~(GS_background_color() | 0xFF0000),
781 siz);
782 }
783
784 /* draw viewer position for inset images */
785 GS_get_from(from);
786 gsd_x(NULL, from, ~(GS_default_draw_color() | 0xFFFF00), 3.0 * siz);
787
788 gsd_zwritemask(0xffffffff);
789
790 return (1);
791}
void G_free(void *buf)
Free allocated memory.
Definition alloc.c:150
#define NULL
Definition ccmath.h:32
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition debug.c:66
double t
void G_warning(const char *msg,...)
Print a warning message to stderr.
Definition gis/error.c:203
double lin_interp(float dt, float val1, float val2)
Linear interpolation.
Definition gk.c:545
void correct_twist(Keylist *k)
Correct twist value.
Definition gk.c:711
unsigned long gk_get_mask_sofar(float time, Keylist *keys)
Get mask value.
Definition gk.c:79
double get_key_neighbors(int nvk, double time, double range, int loop, Keylist *karray[], Keylist **km1, Keylist **kp1, Keylist **kp2, Keylist **km2, double *dt1, double *dt2)
Find interval containing time.
Definition gk.c:462
void gk_free_key(Keylist *ok)
Free keyframe list.
Definition gk.c:271
double get_2key_neighbors(int nvk, float time, float range UNUSED, int loop UNUSED, Keylist *karray[], Keylist **km1, Keylist **kp1)
Finds interval containing time, putting left (or equal) key at km1, right at kp1.
Definition gk.c:564
int gk_draw_path(Viewnode *views, int steps, Keylist *keys)
Draw path.
Definition gk.c:749
Keylist * gk_copy_key(Keylist *k)
Copy keyframes.
Definition gk.c:45
Viewnode * gk_make_framesfromkeys(Keylist *keys, int keysteps, int newsteps, int loop, float t)
Generate viewnode from keyframes.
Definition gk.c:301
Viewnode * gk_make_linear_framesfromkeys(Keylist *keys, int keysteps, int newsteps, int loop)
Generate viewnode from keyframe list (linear interpolation)
Definition gk.c:611
int gk_viable_keys_for_mask(unsigned long mask, Keylist *keys, Keylist **keyret)
ADD.
Definition gk.c:113
void gk_follow_frames(Viewnode *view, int numsteps, Keylist *keys, int step, int onestep, int render, unsigned long mode)
Checks key masks.
Definition gk.c:141
void GP_alldraw_site(void)
Draw all available point sets.
Definition gp2.c:611
void GS_alldraw_cplane_fences(void)
Draw all cplace fences ?
Definition gs2.c:3191
void GS_draw_all_list(void)
Draw all glLists.
Definition gs2.c:872
unsigned int GS_default_draw_color(void)
Get default draw color.
Definition gs2.c:2436
void GS_get_from(float *fr)
Get viewpoint 'from' position.
Definition gs2.c:2721
void GS_get_viewdir(float *dir)
Get viewdir.
Definition gs2.c:2804
void GS_alldraw_wire(void)
Draw all wires.
Definition gs2.c:1917
void GS_clear(int col)
Clear view.
Definition gs2.c:3414
void GS_set_viewdir(float *dir)
Set viewdir.
Definition gs2.c:2818
void GS_moveto(float *pt)
Move viewpoint.
Definition gs2.c:2613
void GS_ready_draw(void)
Definition gs2.c:2485
void GS_setlight_position(int num, float xpos, float ypos, float zpos, int local)
Set light position.
Definition gs2.c:309
unsigned int GS_background_color(void)
Get background color.
Definition gs2.c:2449
void GS_alldraw_surf(void)
Draw all surfaces.
Definition gs2.c:1934
void GS_set_draw(int where)
Sets which buffer to draw to.
Definition gs2.c:2459
int GS_get_longdim(float *dim)
Get largest dimension.
Definition gs2.c:140
void GS_getlight_position(int num, float *xpos, float *ypos, float *zpos, int *local)
Get light position.
Definition gs2.c:334
void GS_done_draw(void)
Draw done, swap buffers.
Definition gs2.c:2498
void GS_set_fov(int fov)
Set field of view.
Definition gs2.c:2838
void GS_set_twist(int t)
Set viewpoint twist value.
Definition gs2.c:2872
void gsd_x(geosurf *gs, float *center, int colr, float siz)
Draw X symbol.
Definition gsd_objs.c:256
void gsd_zwritemask(unsigned long n)
Write out z-mask.
Definition gsd_prim.c:241
void gsd_vert_func(float *pt)
ADD.
Definition gsd_prim.c:686
void gsd_colormode(int cm)
Set color mode.
Definition gsd_prim.c:98
void gsd_endline(void)
End line.
Definition gsd_prim.c:407
void gsd_bgnline(void)
Begin line.
Definition gsd_prim.c:397
void gsd_color_func(unsigned int col)
Set current color.
Definition gsd_prim.c:698
void gsd_linewidth(short n)
Set width of rasterized lines.
Definition gsd_prim.c:267
void GV_alldraw_vect(void)
Draw all loaded vector sets.
Definition gv2.c:506
void GVL_alldraw_vol(void)
Draw all volume sets.
Definition gvl2.c:441
#define X(j)
#define x
#define Y(j)