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