GRASS GIS 8 Programmer's Manual  8.4.0dev(2024)-112dd97adf
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 
27 static float spl3(float, double, double, double, double, double, double,
28  double);
29 
30 static 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  */
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  */
79 unsigned 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  */
113 int 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  */
141 void 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) {
219  }
220  else {
222  }
223 
224  GS_ready_draw();
226 
227  if (render) {
228  GS_alldraw_surf();
229  }
230  else {
231  GS_alldraw_wire();
232  }
233 
235 
236  if (mode & FM_PATH) {
237  gk_draw_path(view, numsteps, keys);
238  }
239 
240  if (mode & FM_VECT) {
241  GV_alldraw_vect();
242  }
243 
244  if (mode & FM_SITE) {
245  GP_alldraw_site();
246  }
247 
248  if (mode & FM_VOL) {
249  GVL_alldraw_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  */
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  */
301 Viewnode *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  */
462 double 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  */
545 double 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  */
564 double 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  */
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  */
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  */
749 int 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 
764  gsd_linewidth(2);
766  gsd_zwritemask(0);
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 }
#define NULL
Definition: ccmath.h:32
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:150
void G_warning(const char *,...) __attribute__((format(printf
#define G_malloc(n)
Definition: defs/gis.h:94
int G_debug(int, const char *,...) __attribute__((format(printf
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
void GS_set_fov(int)
Set field of view.
Definition: gs2.c:2838
void GS_get_viewdir(float *)
Get viewdir.
Definition: gs2.c:2804
void GS_set_draw(int)
Sets which buffer to draw to.
Definition: gs2.c:2459
unsigned int GS_default_draw_color(void)
Get default draw color.
Definition: gs2.c:2436
void GS_get_from(float *)
Get viewpoint 'from' position.
Definition: gs2.c:2721
void GS_alldraw_wire(void)
Draw all wires.
Definition: gs2.c:1917
void gsd_x(geosurf *, float *, int, float)
Draw X symbol.
Definition: gsd_objs.c:256
int GS_get_longdim(float *)
Get largest dimension.
Definition: gs2.c:140
void GS_set_twist(int)
Set viewpoint twist value.
Definition: gs2.c:2872
void GS_setlight_position(int, float, float, float, int)
Set light position.
Definition: gs2.c:309
void GS_getlight_position(int, float *, float *, float *, int *)
Get light position.
Definition: gs2.c:334
void GS_set_viewdir(float *)
Set viewdir.
Definition: gs2.c:2818
void GS_moveto(float *)
Move viewpoint.
Definition: gs2.c:2613
void GV_alldraw_vect(void)
Draw all loaded vector sets.
Definition: gv2.c:506
void gsd_color_func(unsigned int)
Set current color.
Definition: gsd_prim.c:698
void GVL_alldraw_vol(void)
Draw all volume sets.
Definition: gvl2.c:441
void GS_ready_draw(void)
Definition: gs2.c:2485
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 gsd_zwritemask(unsigned long)
Write out z-mask.
Definition: gsd_prim.c:241
void gsd_linewidth(short)
Set width of rasterized lines.
Definition: gsd_prim.c:267
void gsd_endline(void)
End line.
Definition: gsd_prim.c:407
void gsd_colormode(int)
Set color mode.
Definition: gsd_prim.c:98
void GS_clear(int)
Clear view.
Definition: gs2.c:3414
void gsd_bgnline(void)
Begin line.
Definition: gsd_prim.c:397
void GS_done_draw(void)
Draw done, swap buffers.
Definition: gs2.c:2498
void gsd_vert_func(float *)
ADD.
Definition: gsd_prim.c:686
void GP_alldraw_site(void)
Draw all available point sets.
Definition: gp2.c:611
#define UNUSED
A macro for an attribute, if attached to a variable, indicating that the variable is not used.
Definition: gis.h:47
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
Keylist * gk_copy_key(Keylist *k)
Copy keyframes.
Definition: gk.c:45
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
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
#define _(str)
Definition: glocale.h:10
#define KF_DIRY
Definition: ogsf.h:516
#define KF_FOV_MASK
Definition: ogsf.h:501
#define KF_FROMX_MASK
Definition: ogsf.h:491
#define KF_FROMY_MASK
Definition: ogsf.h:492
#define X
Definition: ogsf.h:140
#define FM_VOL
Definition: ogsf.h:524
#define KF_DIRX
Definition: ogsf.h:515
#define KF_FROMX
Definition: ogsf.h:512
#define KF_DIRZ_MASK
Definition: ogsf.h:498
#define Z
Definition: ogsf.h:142
#define KF_TWIST
Definition: ogsf.h:519
#define GSD_FRONT
Definition: ogsf.h:104
#define KF_FROMZ_MASK
Definition: ogsf.h:493
#define Y
Definition: ogsf.h:141
#define FM_PATH
Definition: ogsf.h:523
#define KF_FROMZ
Definition: ogsf.h:514
#define FM_SITE
Definition: ogsf.h:522
#define FM_VECT
Definition: ogsf.h:521
#define CM_COLOR
Definition: ogsf.h:148
#define KF_DIRZ
Definition: ogsf.h:517
#define GSD_BACK
Definition: ogsf.h:105
#define KF_FOV
Definition: ogsf.h:518
#define KF_FROMY
Definition: ogsf.h:513
#define KF_DIRX_MASK
Definition: ogsf.h:496
#define KF_DIRY_MASK
Definition: ogsf.h:497
#define KF_TWIST_MASK
Definition: ogsf.h:502
#define KF_NUMFIELDS
Definition: ogsf.h:506
#define FM_LABEL
Definition: ogsf.h:525
double t
Definition: r_raster.c:39
Definition: ogsf.h:531
unsigned long fieldmask
Definition: ogsf.h:534
struct key_node * prior
Definition: ogsf.h:535
float pos
Definition: ogsf.h:532
struct key_node * next
Definition: ogsf.h:535
float fields[KF_NUMFIELDS]
Definition: ogsf.h:532
int look_ahead
Definition: ogsf.h:533
float fields[KF_NUMFIELDS]
Definition: ogsf.h:528
#define x