GRASS GIS 8 Programmer's Manual 8.2.1RC1(2022)-exported
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 level functions)
5
6 GRASS OpenGL gsurf OGSF Library
7
8 (C) 1999-2008 by the GRASS Development Team
9
10 This program is free software under the
11 GNU General Public License (>=v2).
12 Read the file COPYING that comes with GRASS
13 for details.
14
15 \author Bill Brown USACERL, GMSL/University of Illinois
16 \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
17 */
18
19#include <stdlib.h>
20#include <math.h>
21
22#include <grass/gis.h>
23#include <grass/glocale.h>
24#include <grass/ogsf.h>
25
26static float spl3(float, double, double, double, double, double, double,
27 double);
28
29static float spl3(float tension, double data0, double data1, double x,
30 double x2, double x3, double lderiv, double rderiv)
31{
32 return ((float)
33 (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 startpos = keys->pos;
90 endpos = k->pos;
91 curpos = startpos + time * (endpos - startpos);
92
93 for (k = keys; k->next; k = k->next) {
94 if (k->pos <= curpos) {
95 mask &= k->fieldmask; /* (else break) */
96 }
97 }
98 }
99
100 return (mask);
101}
102
103/*!
104 \brief ADD
105
106 \param mask mask value
107 \param keys list of keyframes
108 \param[out] keyret output list of keyframes
109
110 \return number of output keyframes
111 */
112int gk_viable_keys_for_mask(unsigned long mask, Keylist * keys,
113 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 = (Keylist **) G_malloc(keysteps * sizeof(Keylist *)); /* G_fatal_error */
312 if (!tkeys) {
313 return (NULL);
314 }
315
316 correct_twist(keys);
317
318 if (keys && keysteps) {
319 if (keysteps < 3) {
320 G_warning(_("Need at least 3 keyframes for spline"));
321 G_free(tkeys);
322 return (NULL);
323 }
324
325 /* find end key */
326 for (k = keys; k->next; k = k->next) ;
327
328 startpos = keys->pos;
329 endpos = k->pos;
330 range = endpos - startpos;
331 time_step = range / (newsteps - 1);
332
333 newview = (Viewnode *) G_malloc(newsteps * sizeof(Viewnode)); /* G_fatal_error */
334 if (!newview) { /* not used */
335 G_free(tkeys);
336 return (NULL);
337 }
338
339 for (i = 0; i < newsteps; i++) {
340 int field = 0;
341
342 v = &newview[i];
343
344 time = startpos + i * time_step;
345
346 if (i == newsteps - 1) {
347 time = endpos; /*to ensure no roundoff errors */
348 }
349
350 for (field = 0; field < KF_NUMFIELDS; field++) {
351 int nvk = 0; /* number of viable keyframes for this field */
352
353 /* now need to do for each field to look at mask */
354 k = kp1 = kp2 = km1 = NULL;
355 nvk = gk_viable_keys_for_mask((unsigned long)(1 << field),
356 keys, tkeys);
357 if (nvk) {
358 len = get_key_neighbors(nvk, time, range,
359 loop, tkeys, &k, &kp1, &kp2, &km1,
360 &dt1, &dt2);
361 }
362
363 /* ACS 1 line: was if (len == 0.0) {
364 when disabling a channel no calculation must be made at all (otherwise core dump)
365 */
366 if (len == 0.0 || nvk == 0) {
367 if (!k) {
368 /* none valid - use first.
369 (when showing , will be ignored anyway) */
370 v->fields[field] = keys->fields[field];
371 }
372 else if (!kp1) {
373 /* none on right - use left */
374 v->fields[field] = k->fields[field];
375 }
376
377 continue;
378 }
379 else if (!km1 && !kp2) {
380 /* only two valid - use linear */
381 v->fields[field] = lin_interp((time - k->pos) / len,
382 k->fields[field],
383 kp1->fields[field]);
384 continue;
385 }
386
387 x = (time - k->pos) / len;
388 x2 = x * x;
389 x3 = x2 * x;
390
391 if (!km1) {
392 /* leftmost interval */
393 rderiv = (kp2->fields[field] - k->fields[field]) / dt2;
394 lderiv = (3 * (kp1->fields[field] -
395 k->fields[field]) / dt1 - rderiv) / 2.0;
396 v->fields[field] = spl3(t, k->fields[field],
397 kp1->fields[field], x, x2, x3,
398 lderiv, rderiv);
399 }
400 else if (!kp2) {
401 /* rightmost interval */
402 lderiv = (kp1->fields[field] - km1->fields[field]) / dt1;
403 rderiv = (3 * (kp1->fields[field] -
404 k->fields[field]) / dt2 - lderiv) / 2.0;
405 v->fields[field] = spl3(t, k->fields[field],
406 kp1->fields[field], x, x2, x3,
407 lderiv, rderiv);
408 }
409 else {
410 /* not on ends */
411 lderiv = (kp1->fields[field] - km1->fields[field]) / dt1;
412 rderiv = (kp2->fields[field] - k->fields[field]) / dt2;
413 v->fields[field] = spl3(t, k->fields[field],
414 kp1->fields[field], x, x2, x3,
415 lderiv, rderiv);
416 }
417 }
418 }
419
420 G_free(tkeys);
421 return (newview);
422 }
423 else {
424 G_free(tkeys);
425 return (NULL);
426 }
427}
428
429/*!
430 \brief Find interval containing time
431
432 Changed June 94 to handle masks - now need to have called get_viable_keys
433 for appropriate mask first to build the ARRAY of viable keyframes.
434
435 Putting left (or equal) key
436 at km1, right at kp1, 2nd to right at kp2, and second to left at km2.
437 dt1 is given the length of the current + left intervals
438 dt2 is given the length of the current + right intervals
439
440 \param nvk
441 \param time
442 \param range
443 \param loop
444 \param karray
445 \param km1
446 \param kp1
447 \param kp2
448 \param km2
449 \param dt1
450 \param dt2
451
452 \return the length of the current interval
453 \return 0 on error
454 */
455double get_key_neighbors(int nvk, double time, double range, int loop,
456 Keylist * karray[], Keylist ** km1, Keylist ** kp1,
457 Keylist ** kp2, Keylist ** km2, double *dt1,
458 double *dt2)
459{
460 int i;
461 double len;
462
463 *km1 = *kp1 = *kp2 = *km2 = NULL;
464 *dt1 = *dt2 = 0.0;
465
466 for (i = 0; i < nvk; i++) {
467 if (time < karray[i]->pos) {
468 break;
469 }
470 }
471
472 if (!i) {
473 return (0.0); /* before first keyframe or nvk == 0 */
474 }
475
476 if (i == nvk) {
477 /* past or == last keyframe! */
478 *km1 = karray[nvk - 1];
479 return (0.0);
480 }
481
482 /* there's at least 2 */
483 *km1 = karray[i - 1];
484 *kp1 = karray[i];
485 len = karray[i]->pos - karray[i - 1]->pos;
486
487 if (i == 1) {
488 /* first interval */
489 if (loop) {
490 *km2 = karray[nvk - 2];
491 *kp2 = karray[(i + 1) % nvk];
492 }
493 else {
494 if (nvk > 2) {
495 *kp2 = karray[i + 1];
496 }
497 }
498 }
499 else if (i == nvk - 1) {
500 /* last interval */
501 if (loop) {
502 *km2 = nvk > 2 ? karray[i - 2] : karray[1];
503 *kp2 = karray[1];
504 }
505 else {
506 if (nvk > 2) {
507 *km2 = karray[i - 2];
508 }
509 }
510 }
511 else {
512 *km2 = karray[i - 2];
513 *kp2 = karray[i + 1];
514 }
515
516 *dt1 = (*km2) ? (*kp1)->pos - (*km2)->pos : len;
517 *dt2 = (*kp2) ? (*kp2)->pos - (*km1)->pos : len;
518
519 if (i == 1 && loop) {
520 *dt1 += range;
521 }
522
523 if (i == nvk - 1 && loop) {
524 *dt2 += range;
525 }
526
527 return (len);
528}
529
530/*!
531 \brief Linear interpolation
532
533 \param dt coeficient
534 \param val2 value 2
535 \param val1 value 1
536
537 \return val1 + dt * (val2 - val1)
538 */
539double lin_interp(float dt, float val1, float val2)
540{
541 return ((double)(val1 + dt * (val2 - val1)));
542}
543
544/*!
545 \brief Finds interval containing time, putting left (or equal) key
546 at km1, right at kp1
547
548 \param nvk
549 \param time
550 \param range
551 \param loop
552 \param karray
553 \param km1
554 \param km2
555
556 \return interval value
557 */
558double get_2key_neighbors(int nvk, float time, float range, int loop,
559 Keylist * karray[], Keylist ** km1, Keylist ** kp1)
560{
561 int i;
562 double len;
563
564 *km1 = *kp1 = NULL;
565
566 for (i = 0; i < nvk; i++) {
567 if (time < karray[i]->pos) {
568 break;
569 }
570 }
571
572 if (!i) {
573 return (0.0); /* before first keyframe or nvk == 0 */
574 }
575
576 if (i == nvk) {
577 /* past or == last keyframe! */
578 *km1 = karray[nvk - 1];
579 return (0.0);
580 }
581
582 /* there's at least 2 */
583 *km1 = karray[i - 1];
584 *kp1 = karray[i];
585 len = karray[i]->pos - karray[i - 1]->pos;
586
587 return (len);
588}
589
590/*!
591 \brief Generate viewnode from keyframe list (linear interpolation)
592
593 Here we use linear interpolation. Loop variable isn't used, but left
594 in for use in possible "linear interp with smoothing" version.
595
596 \param kesy keyframe list
597 \param keysteps step value
598 \param newsteps new step value
599 \param loop loop indicator
600
601 \param pointer to viewnode struct
602 \param NULL on failure
603 */
604Viewnode *gk_make_linear_framesfromkeys(Keylist * keys, int keysteps,
605 int newsteps, int loop)
606{
607 int i, nvk;
608 Viewnode *v, *newview;
609 Keylist *k, *k1, *k2, **tkeys;
610 float startpos, endpos, dt, range, time, time_step, len;
611
612 /* allocate tmp keys to hold valid keys for fields */
613 tkeys = (Keylist **) G_malloc(keysteps * sizeof(Keylist *)); /* G_fatal_error */
614 if (!tkeys) {
615 return (NULL);
616 }
617
618 correct_twist(keys);
619
620 if (keys && keysteps) {
621 if (keysteps < 2) {
622 G_warning(_("Need at least 2 keyframes for interpolation"));
623 G_free(tkeys);
624 return (NULL);
625 }
626
627 /* find end key */
628 for (k = keys; k->next; k = k->next) ;
629
630 startpos = keys->pos;
631 endpos = k->pos;
632 range = endpos - startpos;
633 time_step = range / (newsteps - 1);
634
635 newview = (Viewnode *) G_malloc(newsteps * sizeof(Viewnode)); /* G_fatal_error */
636 if (!newview) { /* not used */
637 G_free(tkeys);
638 return (NULL);
639 }
640
641 for (i = 0; i < newsteps; i++) {
642 int field = 0;
643
644 v = &newview[i];
645
646 time = startpos + i * time_step;
647 if (i == newsteps - 1) {
648 time = endpos; /*to ensure no roundoff errors */
649 }
650
651 for (field = 0; field < KF_NUMFIELDS; field++) {
652
653 nvk = gk_viable_keys_for_mask((unsigned long)(1 << field),
654 keys, tkeys);
655 if (!nvk) {
656 v->fields[field] = keys->fields[field]; /*default-not used */
657 }
658 else {
659 len = get_2key_neighbors(nvk, time, range, loop,
660 tkeys, &k1, &k2);
661 }
662
663 /* ACS 1 line: was if (len == 0.0) {
664 when disabling a channel no calculation must be made at all (otherwise core dump)
665 */
666 if (len == 0.0 || nvk == 0) {
667 if (!k1) {
668 /* none valid - use first.
669 (when showing , will be ignored anyway) */
670 v->fields[field] = keys->fields[field];
671 }
672 else if (!k2) {
673 /* none on right - use left */
674 v->fields[field] = k1->fields[field];
675 }
676 }
677 else {
678 dt = (time - k1->pos) / len;
679 v->fields[field] = lin_interp(dt,
680 k1->fields[field],
681 k2->fields[field]);
682 }
683 }
684 }
685
686 G_free(tkeys);
687 return (newview);
688 }
689 else {
690 G_free(tkeys);
691 return (NULL);
692 }
693}
694
695/*!
696 \brief Correct twist value
697
698 \param k keyframe list
699 */
700void correct_twist(Keylist * k)
701{
702 Keylist *c, *p, *t;
703 int cnt, j;
704
705 p = NULL;
706 cnt = 0;
707 for (c = k; c; c = c->next) {
708 if (p) {
709 if ((c->fields[KF_TWIST] - p->fields[KF_TWIST]) > 1800.) {
710 for (t = c; t; t = t->next) {
711 t->fields[KF_TWIST] -= 3600.;
712 }
713 }
714 else if ((p->fields[KF_TWIST] - c->fields[KF_TWIST]) > 1800.) {
715 for (t = k, j = 0; j < cnt; j++, t = t->next) {
716 t->fields[KF_TWIST] -= 3600.;
717 }
718 }
719 }
720
721 p = c;
722 ++cnt;
723 }
724
725 return;
726}
727
728/*!
729 \brief Draw path
730
731 \param views Viewnode struct
732 \param steps step value
733 \param keys keyframe list
734
735 \return 0 on failure
736 \return 1 on success
737 */
738int gk_draw_path(Viewnode * views, int steps, Keylist * keys)
739{
740 Viewnode *v;
741 Keylist *k;
742 int frame;
743 float siz, from[3];
744
745 if (!views || !keys) {
746 return (0);
747 }
748
749 GS_get_longdim(&siz);
750 siz /= 200.;
751
752 gsd_colormode(CM_COLOR);
753 gsd_linewidth(2);
756
757 gsd_bgnline();
758
759 for (frame = 0; frame < steps; frame++) {
760 v = &views[frame];
761 gsd_vert_func(&(v->fields[KF_FROMX]));
762 }
763
764 gsd_endline();
765
766 gsd_linewidth(1);
767
768
769 for (k = keys; k; k = k->next) {
770 gsd_x(NULL, &(k->fields[KF_FROMX]),
771 ~(GS_background_color() | 0xFF0000), siz);
772 }
773
774 /* draw viewer position for inset images */
775 GS_get_from(from);
776 gsd_x(NULL, from, ~(GS_default_draw_color() | 0xFFFF00), 3.0 * siz);
777
778 gsd_zwritemask(0xffffffff);
779
780 return (1);
781}
void G_free(void *buf)
Free allocated memory.
Definition: alloc.c:149
#define NULL
Definition: ccmath.h:32
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition: debug.c:65
double t
void G_warning(const char *msg,...)
Print a warning message to stderr.
Definition: gis/error.c:204
double lin_interp(float dt, float val1, float val2)
Linear interpolation.
Definition: gk.c:539
void correct_twist(Keylist *k)
Correct twist value.
Definition: gk.c:700
double get_2key_neighbors(int nvk, float time, float range, int loop, Keylist *karray[], Keylist **km1, Keylist **kp1)
Finds interval containing time, putting left (or equal) key at km1, right at kp1.
Definition: gk.c:558
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:455
void gk_free_key(Keylist *ok)
Free keyframe list.
Definition: gk.c:271
int gk_draw_path(Viewnode *views, int steps, Keylist *keys)
Draw path.
Definition: gk.c:738
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:604
int gk_viable_keys_for_mask(unsigned long mask, Keylist *keys, Keylist **keyret)
ADD.
Definition: gk.c:112
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:607
void GS_alldraw_cplane_fences(void)
Draw all cplace fences ?
Definition: gs2.c:3195
void GS_draw_all_list(void)
Draw all glLists.
Definition: gs2.c:879
unsigned int GS_default_draw_color(void)
Get default draw color.
Definition: gs2.c:2439
void GS_get_from(float *fr)
Get viewpoint 'from' position.
Definition: gs2.c:2725
void GS_get_viewdir(float *dir)
Get viewdir.
Definition: gs2.c:2809
void GS_alldraw_wire(void)
Draw all wires.
Definition: gs2.c:1919
void GS_clear(int col)
Clear view.
Definition: gs2.c:3418
void GS_set_viewdir(float *dir)
Set viewdir.
Definition: gs2.c:2823
void GS_moveto(float *pt)
Move viewpoint.
Definition: gs2.c:2617
void GS_ready_draw(void)
Definition: gs2.c:2488
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:2452
void GS_alldraw_surf(void)
Draw all surfaces.
Definition: gs2.c:1936
void GS_set_draw(int where)
Sets which buffer to draw to.
Definition: gs2.c:2462
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:335
void GS_done_draw(void)
Draw done, swap buffers.
Definition: gs2.c:2501
void GS_set_fov(int fov)
Set field of view.
Definition: gs2.c:2843
void GS_set_twist(int t)
Set viewpoint twist value.
Definition: gs2.c:2877
void gsd_x(geosurf *gs, float *center, int colr, float siz)
Draw X symbol.
Definition: gsd_objs.c:278
void gsd_zwritemask(unsigned long n)
Write out z-mask.
Definition: gsd_prim.c:240
void gsd_vert_func(float *pt)
ADD.
Definition: gsd_prim.c:689
void gsd_colormode(int cm)
Set color mode.
Definition: gsd_prim.c:97
void gsd_endline(void)
End line.
Definition: gsd_prim.c:406
void gsd_bgnline(void)
Begin line.
Definition: gsd_prim.c:396
void gsd_color_func(unsigned int col)
Set current color.
Definition: gsd_prim.c:701
void gsd_linewidth(short n)
Set width of rasterized lines.
Definition: gsd_prim.c:266
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)