GRASS GIS 8 Programmer's Manual  8.4.0dev(2024)-f8115df121
gk2.c
Go to the documentation of this file.
1 /*!
2  \file lib/ogsf/gk2.c
3 
4  \brief OGSF library - setting and manipulating keyframes animation
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 
21 #include <grass/gis.h>
22 #include <grass/glocale.h>
23 #include <grass/ogsf.h>
24 
25 static int _add_key(Keylist *, int, float);
26 static void _remove_key(Keylist *);
27 
28 static Keylist *Keys = NULL;
29 static Keylist *Keytail = NULL;
30 static Viewnode *Views = NULL;
31 static float Keystartpos = 0.0;
32 static float Keyendpos = 1.0;
33 static float Tension = 0.8;
34 static int Viewsteps = 0;
35 static int Numkeys = 0;
36 static int Interpmode = KF_SPLINE;
37 static int Fmode = 0;
38 
39 /* next & prior already initialized to NULL */
40 static int _add_key(Keylist *newk, int force_replace, float precis)
41 {
42  Keylist *k, *tempk, *prev;
43  int found;
44 
45  found = 0;
46  prev = NULL;
47 
48  /* if(Viewsteps) precis = 0.5/Viewsteps; */
49  for (k = Keys; k; k = k->next) {
50  if (k->pos >= newk->pos - precis && k->pos <= newk->pos + precis) {
51  if (force_replace) {
52 
53  if (k->prior) {
54  k->prior->next = newk;
55  newk->prior = prev;
56  }
57  else {
58  Keys = newk;
59  }
60 
61  newk->next = k->next;
62  newk->prior = k->prior;
63  tempk = k;
64  k = newk;
65  free(tempk);
66  }
67  else {
68  free(newk);
69  }
70 
71  return (-1);
72  }
73  }
74 
75  if (Keys) {
76  if (newk->pos < Keys->pos) {
77  /* new will be first */
78  newk->next = Keys;
79  Keys->prior = newk;
80  Keys = newk;
81  }
82  else {
83  prev = k = Keys;
84  while (k && !found) {
85  if (k->pos > newk->pos) {
86  prev->next = newk;
87  newk->next = k;
88  newk->prior = prev;
89  k->prior = newk;
90  found = 1;
91  }
92 
93  prev = k;
94  k = k->next;
95  }
96  if (!found) {
97  Keytail = prev->next = newk;
98  newk->prior = prev;
99  }
100  }
101  }
102  else {
103  Keys = Keytail = newk;
104  }
105 
106  ++Numkeys;
107  return (1);
108 }
109 
110 static void _remove_key(Keylist *k)
111 {
112  if (k->prior) {
113  k->prior->next = k->next;
114  if (k->next) {
115  k->next->prior = k->prior;
116  }
117  else {
118  Keytail = k->prior;
119  }
120  }
121  else {
122  Keys = k->next;
123  if (k->next) {
124  k->next->prior = NULL;
125  }
126  }
127  k->next = k->prior = NULL;
128 
129  return;
130 }
131 
132 /*!
133  \brief Set interpolation mode
134 
135  \param mode interpolation mode (KF_LINEAR or KF_SPLINE)
136 
137  \return 1 on success
138  \return -1 on error (invalid interpolation mode)
139  */
140 int GK_set_interpmode(int mode)
141 {
142  if (KF_LEGAL_MODE(mode)) {
143  Interpmode = mode;
144  return (1);
145  }
146 
147  return (-1);
148 }
149 
150 /*!
151  \brief Set value for tension when interpmode is KF_SPLINE.
152 
153  \param tens value tens should be between 0.0; 1.0.
154  */
155 void GK_set_tension(float tens)
156 {
157  Tension = tens > 1.0 ? 1.0 : (tens < 0.0 ? 0.0 : tens);
158 
159  /* for now */
160  if (Views) {
163  GS_ready_draw();
165  GS_alldraw_wire();
166 
167  gk_draw_path(Views, Viewsteps, Keys);
168 
169  GS_done_draw();
170  }
171 
172  return;
173 }
174 
176 {
177  return;
178 }
179 
180 /*!
181  \brief Show tension stop ?
182 
183  Use GK_showtension_start/GK_update_tension/GK_showtension_stop to
184  initialize and stop multi-view display of path when changing
185  tension.
186  */
188 {
189  return;
190 }
191 
192 /*!
193  \brief Update tension
194  */
196 {
197  if (Views) {
199  }
200 
201  return;
202 }
203 
204 /*!
205  \brief Print keyframe info
206 
207  \param name filename
208  */
209 void GK_print_keys(const char *name)
210 {
211  Keylist *k;
212  FILE *fp;
213  int cnt = 1;
214 
215  if (NULL == (fp = fopen(name, "w"))) {
216  G_fatal_error(_("Unable to open file <%s> for writing"), name);
217  }
218  /* write a default frame rate of 30 at top of file */
219  fprintf(fp, "30 \n");
220 
221  for (k = Keys; k; k = k->next) {
222 
223  fprintf(fp,
224  "{%f {{FromX %f} {FromY %f} {FromZ %f} {DirX %f} {DirY %f} "
225  "{DirZ %f} {FOV %f} {TWIST %f} {cplane-0 {{pos_x 0.000000} "
226  "{pos_y 0.000000} {pos_z 0.000000} {blend_type OFF} {rot "
227  "0.000000} {tilt 0.000000}}}} keyanimtag%d 0} ",
228  k->pos, k->fields[KF_FROMX], k->fields[KF_FROMY],
229  k->fields[KF_FROMZ], k->fields[KF_DIRX], k->fields[KF_DIRY],
230  k->fields[KF_DIRZ], k->fields[KF_FOV] / 10.,
231  k->fields[KF_TWIST], cnt);
232  cnt++;
233  }
234 
235  fclose(fp);
236  return;
237 }
238 
239 /*!
240  \brief Recalculate path using the current number of frames requested.
241 
242  Call after changing number of frames or when
243  Keyframes change.
244  */
246 {
247  Keylist *k;
248  int loop = 0;
249 
250  if (Keys) {
251  if (Numkeys > 1) {
252  k = Keytail;
253  Keyendpos = k->pos;
254 
255  if (k->fields[KF_FROMX] == Keys->fields[KF_FROMX] &&
256  k->fields[KF_FROMY] == Keys->fields[KF_FROMY] &&
257  k->fields[KF_FROMZ] == Keys->fields[KF_FROMZ]) {
258  loop = 1;
259  }
260  }
261 
262  Keystartpos = Keys->pos;
263  }
264 
265  if (Interpmode == KF_LINEAR && Numkeys > 1) {
266  if (Views) {
267  free(Views);
268  Views = NULL;
269  }
270 
271  Views = gk_make_linear_framesfromkeys(Keys, Numkeys, Viewsteps, loop);
272 
273  if (!Views) {
274  G_warning(_("Check no. of frames requested and keyframes marked"));
275  }
276  }
277  else if (Numkeys > 2) {
278  if (Views) {
279  free(Views);
280  Views = NULL;
281  }
282 
283  Views = gk_make_framesfromkeys(Keys, Numkeys, Viewsteps, loop,
284  1.0 - Tension);
285 
286  if (!Views) {
287  G_warning(_("Check no. of frames requested and keyframes marked"));
288  }
289  }
290 
291  return;
292 }
293 
294 /*!
295  \brief Set the number of frames to be interpolated from keyframes
296 
297  \param newsteps number of frames
298  */
299 void GK_set_numsteps(int newsteps)
300 {
301  Viewsteps = newsteps;
303 
304  return;
305 }
306 
307 /*!
308  \brief Deletes all keyframes, resets field masks.
309 
310  Doesn't change number of frames requested.
311  */
312 void GK_clear_keys(void)
313 {
314  gk_free_key(Keys);
315  Keys = NULL;
316  Numkeys = 0;
317  free(Views);
318  Views = NULL;
319 
320  Keystartpos = 0.0;
321  Keyendpos = 1.0;
322 
323  return;
324 }
325 
326 /*!
327  \brief Move keyframe
328 
329  Precis works as in other functions - to identify keyframe to move.
330  Only the first keyframe in the precis range will be moved.
331 
332  \param oldpos old position
333  \param precis precision value
334  \param newpos new position
335 
336  \return number of keys moved (1 or 0)
337  */
338 int GK_move_key(float oldpos, float precis, float newpos)
339 {
340  Keylist *k;
341 
342  for (k = Keys; k; k = k->next) {
343  if (k->pos >= oldpos - precis && k->pos <= oldpos + precis) {
344  _remove_key(k);
345  k->pos = newpos;
346  _add_key(k, 1, precis);
348  return (1);
349  }
350  }
351 
352  return (0);
353 }
354 
355 /*!
356  Delete keyframe
357 
358  The values pos and precis are used to determine which keyframes to
359  delete. Any keyframes with their position within precis of pos will
360  be deleted if justone is zero. If justone is non-zero, only the first
361  (lowest pos) keyframe in the range will be deleted.
362 
363  \param pos position
364  \param precis precision
365  \param justone delete only one keyframe
366 
367  \return number of keys deleted.
368  */
369 int GK_delete_key(float pos, float precis, int justone)
370 {
371  Keylist *k, *next;
372  int cnt;
373 
374  for (cnt = 0, k = Keys; k;) {
375  next = k->next;
376 
377  if (k->pos >= pos - precis && k->pos <= pos + precis) {
378  cnt++;
379  _remove_key(k);
380  free(k);
381  if (justone) {
382  break;
383  }
384  }
385 
386  k = next;
387  }
388 
390  return (cnt);
391 }
392 
393 /*!
394  \brief Add keyframe
395 
396  The pos value is the relative position in the animation for this
397  particular keyframe - used to compare relative distance to neighboring
398  keyframes, it can be any floating point value.
399 
400  The fmask value can be any of the following or'd together:
401  - KF_FROMX_MASK
402  - KF_FROMY_MASK
403  - KF_FROMZ_MASK
404  - KF_FROM_MASK (KF_FROMX_MASK | KF_FROMY_MASK | KF_FROMZ_MASK)
405 
406  - KF_DIRX_MASK
407  - KF_DIRY_MASK
408  - KF_DIRZ_MASK
409  - KF_DIR_MASK (KF_DIRX_MASK | KF_DIRY_MASK | KF_DIRZ_MASK)
410 
411  - KF_FOV_MASK
412  - KF_TWIST_MASK
413 
414  - KF_ALL_MASK (KF_FROM_MASK | KF_DIR_MASK | KF_FOV_MASK | KF_TWIST_MASK)
415 
416  Other fields will be added later.
417 
418  The value precis and the boolean force_replace are used to determine
419  if a keyframe should be considered to be at the same position as a
420  pre-existing keyframe. e.g., if anykey.pos - newkey.pos &lt;= precis,
421  GK_add_key() will fail unless force_replace is TRUE.
422 
423  \param pos position
424  \param fmaks
425  \param force_replace
426  \param precis precision value
427 
428  \return 1 if key is added
429  \return -1 key not added
430  */
431 int GK_add_key(float pos, unsigned long fmask, int force_replace, float precis)
432 {
433  Keylist *newk;
434  float tmp[3];
435 
436  if (NULL == (newk = (Keylist *)malloc(sizeof(Keylist)))) {
437  fprintf(stderr, "Out of memory\n");
438  return (-1);
439  }
440 
441  /* All fields set, don't use mask until making Views */
442 
443  GS_get_from(tmp);
444  newk->fields[KF_FROMX] = tmp[X];
445  newk->fields[KF_FROMY] = tmp[Y];
446  newk->fields[KF_FROMZ] = tmp[Z];
447 
448  G_debug(3, "KEY FROM: %f %f %f", tmp[X], tmp[Y], tmp[Z]);
449 
450  /* Instead of View Dir try get_focus (view center) */
451  /* View Dir is implied from eye and center position */
452  /* GS_get_viewdir(tmp); */
453 
454  /* ACS 1 line: was GS_get_focus(tmp);
455  with this kanimator works also for flythrough navigation
456  also changed in gk.c
457  */
458  GS_get_viewdir(tmp);
459  newk->fields[KF_DIRX] = tmp[X];
460  newk->fields[KF_DIRY] = tmp[Y];
461  newk->fields[KF_DIRZ] = tmp[Z];
462 
463  newk->fields[KF_FOV] = GS_get_fov();
464  newk->fields[KF_TWIST] = GS_get_twist();
465  newk->pos = pos;
466  newk->fieldmask = fmask;
467  newk->next = NULL;
468  newk->prior = NULL;
469 
470  if (0 < _add_key(newk, force_replace, precis)) {
472  return (1);
473  }
474 
475  return (-1);
476 }
477 
478 /*!
479  \brief Moves the animation to frame number "step".
480 
481  Step should be a value between 1 and the number of frames. If
482  render is non-zero, calls draw_all.
483 
484  \param step step value
485  \param render
486  */
487 void GK_do_framestep(int step, int render)
488 {
489  if (Views) {
490  if (step > 0 && step <= Viewsteps) {
491  gk_follow_frames(Views, Viewsteps, Keys, step, 1, render, Fmode);
492  }
493  }
494 
495  return;
496 }
497 
498 /*!
499  \brief Draw the current path
500 
501  \param flag
502  */
503 void GK_show_path(int flag)
504 {
505  if (flag) {
506  Fmode |= FM_PATH;
507 
508  if (Views) {
510  GS_ready_draw();
511 
512  gk_draw_path(Views, Viewsteps, Keys);
513 
514  GS_done_draw();
515  }
516  }
517  else {
518  Fmode &= ~FM_PATH;
519  }
520 
521  return;
522 }
523 
524 /*!
525  \brief Show vector sets
526 
527  \param flag
528  */
529 void GK_show_vect(int flag)
530 {
531  if (flag) {
532  Fmode |= FM_VECT;
533  if (Views) {
534 
536  GS_ready_draw();
537 
538  GV_alldraw_vect();
539 
540  GS_done_draw();
541  }
542  }
543  else {
544  Fmode &= ~FM_VECT;
545  }
546 
547  return;
548 }
549 
550 /*!
551  \brief Show point sets
552 
553  \param flag
554  */
555 void GK_show_site(int flag)
556 {
557  if (flag) {
558  Fmode |= FM_SITE;
559 
560  if (Views) {
561 
563  GS_ready_draw();
564 
565  GP_alldraw_site();
566 
567  GS_done_draw();
568  }
569  }
570  else {
571  Fmode &= ~FM_SITE;
572  }
573 
574  return;
575 }
576 
577 /*!
578  \brief Show volumes
579 
580  \param flag
581  */
582 void GK_show_vol(int flag)
583 {
584  if (flag) {
585  Fmode |= FM_VOL;
586 
587  if (Views) {
588 
590  GS_ready_draw();
591 
592  GVL_alldraw_vol();
593 
594  GS_done_draw();
595  }
596  }
597  else {
598  Fmode &= ~FM_VOL;
599  }
600 
601  return;
602 }
603 
604 /*!
605  \brief Show list
606 
607  \param flag
608  */
609 void GK_show_list(int flag)
610 {
611  if (flag) {
612  Fmode |= FM_LABEL;
613 
614  if (Views) {
616  }
617  }
618  else {
619  Fmode &= ~FM_LABEL;
620  }
621 
622  return;
623 }
#define NULL
Definition: ccmath.h:32
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
int G_debug(int, const char *,...) __attribute__((format(printf
int GS_get_twist(void)
Get twist value.
Definition: gs2.c:2860
int gk_draw_path(Viewnode *, int, Keylist *)
Draw path.
Definition: gk.c:749
Viewnode * gk_make_linear_framesfromkeys(Keylist *, int, int, int)
Generate viewnode from keyframe list (linear interpolation)
Definition: gk.c:611
void GS_draw_all_list(void)
Draw all glLists.
Definition: gs2.c:872
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
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
int GS_get_fov(void)
Get field of view.
Definition: gs2.c:2850
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
void gk_free_key(Keylist *)
Free keyframe list.
Definition: gk.c:271
Viewnode * gk_make_framesfromkeys(Keylist *, int, int, int, float)
Generate viewnode from keyframes.
Definition: gk.c:301
void GS_ready_draw(void)
Definition: gs2.c:2485
unsigned int GS_background_color(void)
Get background color.
Definition: gs2.c:2449
void GS_clear(int)
Clear view.
Definition: gs2.c:3414
void GS_done_draw(void)
Draw done, swap buffers.
Definition: gs2.c:2498
void gk_follow_frames(Viewnode *, int, Keylist *, int, int, int, unsigned long)
Checks key masks.
Definition: gk.c:141
void GP_alldraw_site(void)
Draw all available point sets.
Definition: gp2.c:611
void GK_set_tension(float tens)
Set value for tension when interpmode is KF_SPLINE.
Definition: gk2.c:155
int GK_set_interpmode(int mode)
Set interpolation mode.
Definition: gk2.c:140
void GK_show_vol(int flag)
Show volumes.
Definition: gk2.c:582
void GK_do_framestep(int step, int render)
Moves the animation to frame number "step".
Definition: gk2.c:487
void GK_show_vect(int flag)
Show vector sets.
Definition: gk2.c:529
void GK_update_tension(void)
Update tension.
Definition: gk2.c:195
void GK_showtension_stop(void)
Show tension stop ?
Definition: gk2.c:187
void GK_showtension_start(void)
Definition: gk2.c:175
void GK_show_path(int flag)
Draw the current path.
Definition: gk2.c:503
void GK_show_list(int flag)
Show list.
Definition: gk2.c:609
void GK_print_keys(const char *name)
Print keyframe info.
Definition: gk2.c:209
void GK_show_site(int flag)
Show point sets.
Definition: gk2.c:555
int GK_delete_key(float pos, float precis, int justone)
Definition: gk2.c:369
void GK_set_numsteps(int newsteps)
Set the number of frames to be interpolated from keyframes.
Definition: gk2.c:299
void GK_update_frames(void)
Recalculate path using the current number of frames requested.
Definition: gk2.c:245
int GK_move_key(float oldpos, float precis, float newpos)
Move keyframe.
Definition: gk2.c:338
int GK_add_key(float pos, unsigned long fmask, int force_replace, float precis)
Add keyframe.
Definition: gk2.c:431
void GK_clear_keys(void)
Deletes all keyframes, resets field masks.
Definition: gk2.c:312
#define _(str)
Definition: glocale.h:10
const char * name
Definition: named_colr.c:6
#define KF_DIRY
Definition: ogsf.h:516
#define KF_LINEAR
Definition: ogsf.h:508
#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 Z
Definition: ogsf.h:142
#define KF_TWIST
Definition: ogsf.h:519
#define GSD_FRONT
Definition: ogsf.h:104
#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 KF_DIRZ
Definition: ogsf.h:517
#define GSD_BACK
Definition: ogsf.h:105
#define KF_FOV
Definition: ogsf.h:518
#define KF_LEGAL_MODE(m)
Definition: ogsf.h:510
#define KF_FROMY
Definition: ogsf.h:513
#define FM_LABEL
Definition: ogsf.h:525
#define KF_SPLINE
Definition: ogsf.h:509
void * malloc(YYSIZE_T)
void free(void *)
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