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