GRASS GIS 8 Programmer's Manual  8.2.2dev(2023)-3d2c704037
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} {DirZ %f} {FOV %f} {TWIST %f} {cplane-0 {{pos_x 0.000000} {pos_y 0.000000} {pos_z 0.000000} {blend_type OFF} {rot 0.000000} {tilt 0.000000}}}} keyanimtag%d 0} ",
225  k->pos, k->fields[KF_FROMX], k->fields[KF_FROMY],
226  k->fields[KF_FROMZ], k->fields[KF_DIRX], k->fields[KF_DIRY],
227  k->fields[KF_DIRZ], k->fields[KF_FOV] / 10.,
228  k->fields[KF_TWIST], cnt);
229  cnt++;
230  }
231 
232  fclose(fp);
233  return;
234 
235 }
236 
237 /*!
238  \brief Recalculate path using the current number of frames requested.
239 
240  Call after changing number of frames or when
241  Keyframes change.
242  */
244 {
245  Keylist *k;
246  int loop = 0;
247 
248  if (Keys) {
249  if (Numkeys > 1) {
250  k = Keytail;
251  Keyendpos = k->pos;
252 
253  if (k->fields[KF_FROMX] == Keys->fields[KF_FROMX] &&
254  k->fields[KF_FROMY] == Keys->fields[KF_FROMY] &&
255  k->fields[KF_FROMZ] == Keys->fields[KF_FROMZ]) {
256  loop = 1;
257  }
258  }
259 
260  Keystartpos = Keys->pos;
261  }
262 
263  if (Interpmode == KF_LINEAR && Numkeys > 1) {
264  if (Views) {
265  free(Views);
266  Views = NULL;
267  }
268 
269  Views = gk_make_linear_framesfromkeys(Keys, Numkeys, Viewsteps, loop);
270 
271  if (!Views) {
272  G_warning(_("Check no. of frames requested and keyframes marked"));
273  }
274  }
275  else if (Numkeys > 2) {
276  if (Views) {
277  free(Views);
278  Views = NULL;
279  }
280 
281  Views = gk_make_framesfromkeys
282  (Keys, Numkeys, Viewsteps, loop, 1.0 - Tension);
283 
284  if (!Views) {
285  G_warning(_("Check no. of frames requested and keyframes marked"));
286  }
287  }
288 
289  return;
290 }
291 
292 /*!
293  \brief Set the number of frames to be interpolated from keyframes
294 
295  \param newsteps number of frames
296  */
297 void GK_set_numsteps(int newsteps)
298 {
299  Viewsteps = newsteps;
301 
302  return;
303 }
304 
305 /*!
306  \brief Deletes all keyframes, resets field masks.
307 
308  Doesn't change number of frames requested.
309  */
310 void GK_clear_keys(void)
311 {
312  gk_free_key(Keys);
313  Keys = NULL;
314  Numkeys = 0;
315  free(Views);
316  Views = NULL;
317 
318  Keystartpos = 0.0;
319  Keyendpos = 1.0;
320 
321  return;
322 }
323 
324 /*!
325  \brief Move keyframe
326 
327  Precis works as in other functions - to identify keyframe to move.
328  Only the first keyframe in the precis range will be moved.
329 
330  \param oldpos old position
331  \param precis precision value
332  \param newpos new position
333 
334  \return number of keys moved (1 or 0)
335  */
336 int GK_move_key(float oldpos, float precis, float newpos)
337 {
338  Keylist *k;
339 
340  for (k = Keys; k; k = k->next) {
341  if (k->pos >= oldpos - precis && k->pos <= oldpos + precis) {
342  _remove_key(k);
343  k->pos = newpos;
344  _add_key(k, 1, precis);
346  return (1);
347  }
348  }
349 
350  return (0);
351 }
352 
353 /*!
354  Delete keyframe
355 
356  The values pos and precis are used to determine which keyframes to
357  delete. Any keyframes with their position within precis of pos will
358  be deleted if justone is zero. If justone is non-zero, only the first
359  (lowest pos) keyframe in the range will be deleted.
360 
361  \param pos position
362  \param precis precision
363  \param justone delete only one keyframe
364 
365  \return number of keys deleted.
366  */
367 int GK_delete_key(float pos, float precis, int justone)
368 {
369  Keylist *k, *next;
370  int cnt;
371 
372  for (cnt = 0, k = Keys; k;) {
373  next = k->next;
374 
375  if (k->pos >= pos - precis && k->pos <= pos + precis) {
376  cnt++;
377  _remove_key(k);
378  free(k);
379  if (justone) {
380  break;
381  }
382  }
383 
384  k = next;
385  }
386 
388  return (cnt);
389 }
390 
391 /*!
392  \brief Add keyframe
393 
394  The pos value is the relative position in the animation for this
395  particular keyframe - used to compare relative distance to neighboring
396  keyframes, it can be any floating point value.
397 
398  The fmask value can be any of the following or'd together:
399  - KF_FROMX_MASK
400  - KF_FROMY_MASK
401  - KF_FROMZ_MASK
402  - KF_FROM_MASK (KF_FROMX_MASK | KF_FROMY_MASK | KF_FROMZ_MASK)
403 
404  - KF_DIRX_MASK
405  - KF_DIRY_MASK
406  - KF_DIRZ_MASK
407  - KF_DIR_MASK (KF_DIRX_MASK | KF_DIRY_MASK | KF_DIRZ_MASK)
408 
409  - KF_FOV_MASK
410  - KF_TWIST_MASK
411 
412  - KF_ALL_MASK (KF_FROM_MASK | KF_DIR_MASK | KF_FOV_MASK | KF_TWIST_MASK)
413 
414  Other fields will be added later.
415 
416  The value precis and the boolean force_replace are used to determine
417  if a keyframe should be considered to be at the same position as a
418  pre-existing keyframe. e.g., if anykey.pos - newkey.pos &lt;= precis,
419  GK_add_key() will fail unless force_replace is TRUE.
420 
421  \param pos position
422  \param fmaks
423  \param force_replace
424  \param precis precision value
425 
426  \return 1 if key is added
427  \return -1 key not added
428  */
429 int GK_add_key(float pos, unsigned long fmask, int force_replace,
430  float precis)
431 {
432  Keylist *newk;
433  float tmp[3];
434 
435  if (NULL == (newk = (Keylist *) malloc(sizeof(Keylist)))) {
436  fprintf(stderr, "Out of memory\n");
437  return (-1);
438  }
439 
440  /* All fields set, don't use mask until making Views */
441 
442  GS_get_from(tmp);
443  newk->fields[KF_FROMX] = tmp[X];
444  newk->fields[KF_FROMY] = tmp[Y];
445  newk->fields[KF_FROMZ] = tmp[Z];
446 
447  G_debug(3, "KEY FROM: %f %f %f", tmp[X], tmp[Y], tmp[Z]);
448 
449  /* Instead of View Dir try get_focus (view center) */
450  /* View Dir is implied from eye and center position */
451  /* GS_get_viewdir(tmp); */
452 
453  /* ACS 1 line: was GS_get_focus(tmp);
454  with this kanimator works also for flythrough navigation
455  also changed in gk.c
456  */
457  GS_get_viewdir(tmp);
458  newk->fields[KF_DIRX] = tmp[X];
459  newk->fields[KF_DIRY] = tmp[Y];
460  newk->fields[KF_DIRZ] = tmp[Z];
461 
462  newk->fields[KF_FOV] = GS_get_fov();
463  newk->fields[KF_TWIST] = GS_get_twist();
464  newk->pos = pos;
465  newk->fieldmask = fmask;
466  newk->next = NULL;
467  newk->prior = NULL;
468 
469  if (0 < _add_key(newk, force_replace, precis)) {
471  return (1);
472  }
473 
474  return (-1);
475 }
476 
477 /*!
478  \brief Moves the animation to frame number "step".
479 
480  Step should be a value between 1 and the number of frames. If
481  render is non-zero, calls draw_all.
482 
483  \param step step value
484  \param render
485  */
486 void GK_do_framestep(int step, int render)
487 {
488  if (Views) {
489  if (step > 0 && step <= Viewsteps) {
490  gk_follow_frames(Views, Viewsteps, Keys, step, 1, render, Fmode);
491  }
492  }
493 
494  return;
495 }
496 
497 /*!
498  \brief Draw the current path
499 
500  \param flag
501  */
502 void GK_show_path(int flag)
503 {
504  if (flag) {
505  Fmode |= FM_PATH;
506 
507  if (Views) {
509  GS_ready_draw();
510 
511  gk_draw_path(Views, Viewsteps, Keys);
512 
513  GS_done_draw();
514 
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  }
571  else {
572  Fmode &= ~FM_SITE;
573  }
574 
575  return;
576 }
577 
578 /*!
579  \brief Show volumes
580 
581  \param flag
582  */
583 void GK_show_vol(int flag)
584 {
585  if (flag) {
586  Fmode |= FM_VOL;
587 
588  if (Views) {
589 
591  GS_ready_draw();
592 
593  GVL_alldraw_vol();
594 
595  GS_done_draw();
596 
597  }
598  }
599  else {
600  Fmode &= ~FM_VOL;
601  }
602 
603  return;
604 }
605 
606 /*!
607  \brief Show list
608 
609  \param flag
610  */
611 void GK_show_list(int flag)
612 {
613  if (flag) {
614  Fmode |= FM_LABEL;
615 
616  if (Views) {
618  }
619  }
620  else {
621  Fmode &= ~FM_LABEL;
622  }
623 
624  return;
625 }
#define KF_TWIST
Definition: ogsf.h:532
#define KF_LINEAR
Definition: ogsf.h:521
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
int GS_get_fov(void)
Get fied of view.
Definition: gs2.c:2855
void GK_clear_keys(void)
Deletes all keyframes, resets field masks.
Definition: gk2.c:310
void GK_show_vect(int flag)
Show vector sets.
Definition: gk2.c:529
Viewnode * gk_make_linear_framesfromkeys(Keylist *, int, int, int)
Generate viewnode from keyframe list (linear interpolation)
Definition: gk.c:604
void GK_update_tension(void)
Update tension.
Definition: gk2.c:195
#define KF_FOV
Definition: ogsf.h:531
void GS_ready_draw(void)
Definition: gs2.c:2488
void GS_draw_all_list(void)
Draw all glLists.
Definition: gs2.c:879
void GVL_alldraw_vol(void)
Draw all volume sets.
Definition: gvl2.c:441
void GK_show_vol(int flag)
Show volumes.
Definition: gk2.c:583
#define KF_FROMX
Definition: ogsf.h:525
void GK_set_tension(float tens)
Set value for tension when interpmode is KF_SPLINE.
Definition: gk2.c:155
#define KF_FROMY
Definition: ogsf.h:526
int GK_delete_key(float pos, float precis, int justone)
Definition: gk2.c:367
#define FM_VOL
Definition: ogsf.h:537
void free(void *)
#define NULL
Definition: ccmath.h:32
unsigned int GS_background_color(void)
Get background color.
Definition: gs2.c:2452
void GS_get_from(float *)
Get viewpoint &#39;from&#39; position.
Definition: gs2.c:2725
void GS_clear(int)
Clear view.
Definition: gs2.c:3418
int gk_draw_path(Viewnode *, int, Keylist *)
Draw path.
Definition: gk.c:738
void GS_alldraw_wire(void)
Draw all wires.
Definition: gs2.c:1919
void * malloc(YYSIZE_T)
unsigned long fieldmask
Definition: ogsf.h:549
struct key_node * prior
Definition: ogsf.h:550
#define FM_VECT
Definition: ogsf.h:534
void gk_free_key(Keylist *)
Free keyframe list.
Definition: gk.c:271
void GK_do_framestep(int step, int render)
Moves the animation to frame number "step".
Definition: gk2.c:486
#define KF_DIRX
Definition: ogsf.h:528
int GK_set_interpmode(int mode)
Set interpolation mode.
Definition: gk2.c:140
#define FM_SITE
Definition: ogsf.h:535
void GP_alldraw_site(void)
Draw all available point sets.
Definition: gp2.c:607
float fields[KF_NUMFIELDS]
Definition: ogsf.h:547
void GK_show_path(int flag)
Draw the current path.
Definition: gk2.c:502
void GK_showtension_stop(void)
Show tension stop ?
Definition: gk2.c:187
void GS_done_draw(void)
Draw done, swap buffers.
Definition: gs2.c:2501
#define KF_DIRY
Definition: ogsf.h:529
#define Z
Definition: ogsf.h:139
#define KF_DIRZ
Definition: ogsf.h:530
Definition: ogsf.h:545
#define GSD_BACK
Definition: ogsf.h:102
void gk_follow_frames(Viewnode *, int, Keylist *, int, int, int, unsigned long)
Checks key masks.
Definition: gk.c:141
#define Y
Definition: ogsf.h:138
Viewnode * gk_make_framesfromkeys(Keylist *, int, int, int, float)
Generate viewnode from keyframes.
Definition: gk.c:301
#define KF_FROMZ
Definition: ogsf.h:527
#define FM_PATH
Definition: ogsf.h:536
#define KF_LEGAL_MODE(m)
Definition: ogsf.h:523
void GK_show_site(int flag)
Show point sets.
Definition: gk2.c:555
struct key_node * next
Definition: ogsf.h:550
int GK_add_key(float pos, unsigned long fmask, int force_replace, float precis)
Add keyframe.
Definition: gk2.c:429
float pos
Definition: ogsf.h:547
void GS_get_viewdir(float *)
Get viewdir.
Definition: gs2.c:2809
void G_warning(const char *,...) __attribute__((format(printf
#define GSD_FRONT
Definition: ogsf.h:101
void GK_set_numsteps(int newsteps)
Set the number of frames to be interpolated from keyframes.
Definition: gk2.c:297
#define _(str)
Definition: glocale.h:10
#define KF_SPLINE
Definition: ogsf.h:522
void GK_print_keys(const char *name)
Print keyframe info.
Definition: gk2.c:209
void GK_show_list(int flag)
Show list.
Definition: gk2.c:611
#define X
Definition: ogsf.h:137
int GS_get_twist(void)
Get twist value.
Definition: gs2.c:2865
const char * name
Definition: named_colr.c:7
#define FM_LABEL
Definition: ogsf.h:538
void GS_set_draw(int)
Sets which buffer to draw to.
Definition: gs2.c:2462
void GK_showtension_start(void)
Definition: gk2.c:175
int G_debug(int, const char *,...) __attribute__((format(printf
void GK_update_frames(void)
Recalculate path using the current number of frames requested.
Definition: gk2.c:243
int GK_move_key(float oldpos, float precis, float newpos)
Move keyframe.
Definition: gk2.c:336
void GV_alldraw_vect(void)
Draw all loaded vector sets.
Definition: gv2.c:506