Loading...
Searching...
No Matches
gk2.c
Go to the documentation of this file.
/*!
\file lib/ogsf/gk2.c
\brief OGSF library - setting and manipulating keyframes animation
GRASS OpenGL gsurf OGSF Library
(C) 1999-2008 by the GRASS Development Team
This program is free software under the
GNU General Public License (>=v2).
Read the file COPYING that comes with GRASS
for details.
\author Bill Brown USACERL, GMSL/University of Illinois
\author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
*/
#include <stdlib.h>
#include <grass/gis.h>
#include <grass/glocale.h>
#include <grass/ogsf.h>
static int _add_key(Keylist *, int, float);
static void _remove_key(Keylist *);
static Keylist *Keys = NULL;
static Keylist *Keytail = NULL;
static Viewnode *Views = NULL;
static float Keystartpos = 0.0;
static float Keyendpos = 1.0;
static float Tension = 0.8;
static int Viewsteps = 0;
static int Numkeys = 0;
static int Interpmode = KF_SPLINE;
static int Fmode = 0;
/* next & prior already initialized to NULL */
static int _add_key(Keylist *newk, int force_replace, float precis)
{
Keylist *k, *tempk, *prev;
int found;
found = 0;
prev = NULL;
/* if(Viewsteps) precis = 0.5/Viewsteps; */
for (k = Keys; k; k = k->next) {
if (k->pos >= newk->pos - precis && k->pos <= newk->pos + precis) {
if (force_replace) {
if (k->prior) {
k->prior->next = newk;
newk->prior = prev;
}
else {
Keys = newk;
}
newk->next = k->next;
newk->prior = k->prior;
tempk = k;
k = newk;
free(tempk);
}
else {
free(newk);
}
return (-1);
}
}
if (Keys) {
if (newk->pos < Keys->pos) {
/* new will be first */
newk->next = Keys;
Keys->prior = newk;
Keys = newk;
}
else {
prev = k = Keys;
while (k && !found) {
if (k->pos > newk->pos) {
prev->next = newk;
newk->next = k;
newk->prior = prev;
k->prior = newk;
found = 1;
}
prev = k;
k = k->next;
}
if (!found) {
Keytail = prev->next = newk;
newk->prior = prev;
}
}
}
else {
Keys = Keytail = newk;
}
++Numkeys;
return (1);
}
static void _remove_key(Keylist *k)
{
if (k->prior) {
k->prior->next = k->next;
if (k->next) {
k->next->prior = k->prior;
}
else {
Keytail = k->prior;
}
}
else {
Keys = k->next;
if (k->next) {
k->next->prior = NULL;
}
}
k->next = k->prior = NULL;
return;
}
/*!
\brief Set interpolation mode
\param mode interpolation mode (KF_LINEAR or KF_SPLINE)
\return 1 on success
\return -1 on error (invalid interpolation mode)
*/
int GK_set_interpmode(int mode)
{
if (KF_LEGAL_MODE(mode)) {
Interpmode = mode;
return (1);
}
return (-1);
}
/*!
\brief Set value for tension when interpmode is KF_SPLINE.
\param tens value tens should be between 0.0; 1.0.
*/
void GK_set_tension(float tens)
{
Tension = tens > 1.0 ? 1.0 : (tens < 0.0 ? 0.0 : tens);
/* for now */
if (Views) {
GK_update_frames();
GS_set_draw(GSD_BACK);
GS_ready_draw();
GS_clear(GS_background_color());
GS_alldraw_wire();
gk_draw_path(Views, Viewsteps, Keys);
GS_done_draw();
}
return;
}
void GK_showtension_start(void)
{
return;
}
/*!
\brief Show tension stop ?
Use GK_showtension_start/GK_update_tension/GK_showtension_stop to
initialize and stop multi-view display of path when changing
tension.
*/
void GK_showtension_stop(void)
{
return;
}
/*!
\brief Update tension
*/
void GK_update_tension(void)
{
if (Views) {
GK_update_frames();
}
return;
}
/*!
\brief Print keyframe info
\param name filename
*/
void GK_print_keys(const char *name)
{
Keylist *k;
FILE *fp;
int cnt = 1;
if (NULL == (fp = fopen(name, "w"))) {
G_fatal_error(_("Unable to open file <%s> for writing"), name);
}
/* write a default frame rate of 30 at top of file */
fprintf(fp, "30 \n");
for (k = Keys; k; k = k->next) {
fprintf(fp,
"{%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} ",
k->pos, k->fields[KF_FROMX], k->fields[KF_FROMY],
k->fields[KF_FROMZ], k->fields[KF_DIRX], k->fields[KF_DIRY],
k->fields[KF_DIRZ], k->fields[KF_FOV] / 10.,
k->fields[KF_TWIST], cnt);
cnt++;
}
fclose(fp);
return;
}
/*!
\brief Recalculate path using the current number of frames requested.
Call after changing number of frames or when
Keyframes change.
*/
void GK_update_frames(void)
{
Keylist *k;
int loop = 0;
if (Keys) {
if (Numkeys > 1) {
k = Keytail;
Keyendpos = k->pos;
if (k->fields[KF_FROMX] == Keys->fields[KF_FROMX] &&
k->fields[KF_FROMY] == Keys->fields[KF_FROMY] &&
k->fields[KF_FROMZ] == Keys->fields[KF_FROMZ]) {
loop = 1;
}
}
Keystartpos = Keys->pos;
}
if (Interpmode == KF_LINEAR && Numkeys > 1) {
if (Views) {
free(Views);
Views = NULL;
}
Views = gk_make_linear_framesfromkeys(Keys, Numkeys, Viewsteps, loop);
if (!Views) {
G_warning(_("Check no. of frames requested and keyframes marked"));
}
}
else if (Numkeys > 2) {
if (Views) {
free(Views);
Views = NULL;
}
Views = gk_make_framesfromkeys(Keys, Numkeys, Viewsteps, loop,
1.0 - Tension);
if (!Views) {
G_warning(_("Check no. of frames requested and keyframes marked"));
}
}
return;
}
/*!
\brief Set the number of frames to be interpolated from keyframes
\param newsteps number of frames
*/
void GK_set_numsteps(int newsteps)
{
Viewsteps = newsteps;
GK_update_frames();
return;
}
/*!
\brief Deletes all keyframes, resets field masks.
Doesn't change number of frames requested.
*/
void GK_clear_keys(void)
{
gk_free_key(Keys);
Keys = NULL;
Numkeys = 0;
free(Views);
Views = NULL;
Keystartpos = 0.0;
Keyendpos = 1.0;
return;
}
/*!
\brief Move keyframe
Precis works as in other functions - to identify keyframe to move.
Only the first keyframe in the precis range will be moved.
\param oldpos old position
\param precis precision value
\param newpos new position
\return number of keys moved (1 or 0)
*/
int GK_move_key(float oldpos, float precis, float newpos)
{
Keylist *k;
for (k = Keys; k; k = k->next) {
if (k->pos >= oldpos - precis && k->pos <= oldpos + precis) {
_remove_key(k);
k->pos = newpos;
_add_key(k, 1, precis);
GK_update_frames();
return (1);
}
}
return (0);
}
/*!
Delete keyframe
The values pos and precis are used to determine which keyframes to
delete. Any keyframes with their position within precis of pos will
be deleted if justone is zero. If justone is non-zero, only the first
(lowest pos) keyframe in the range will be deleted.
\param pos position
\param precis precision
\param justone delete only one keyframe
\return number of keys deleted.
*/
int GK_delete_key(float pos, float precis, int justone)
{
Keylist *k, *next;
int cnt;
for (cnt = 0, k = Keys; k;) {
next = k->next;
if (k->pos >= pos - precis && k->pos <= pos + precis) {
cnt++;
_remove_key(k);
free(k);
if (justone) {
break;
}
}
k = next;
}
GK_update_frames();
return (cnt);
}
/*!
\brief Add keyframe
The pos value is the relative position in the animation for this
particular keyframe - used to compare relative distance to neighboring
keyframes, it can be any floating point value.
The fmask value can be any of the following or'd together:
- KF_FROMX_MASK
- KF_FROMY_MASK
- KF_FROMZ_MASK
- KF_FROM_MASK (KF_FROMX_MASK | KF_FROMY_MASK | KF_FROMZ_MASK)
- KF_DIRX_MASK
- KF_DIRY_MASK
- KF_DIRZ_MASK
- KF_DIR_MASK (KF_DIRX_MASK | KF_DIRY_MASK | KF_DIRZ_MASK)
- KF_FOV_MASK
- KF_TWIST_MASK
- KF_ALL_MASK (KF_FROM_MASK | KF_DIR_MASK | KF_FOV_MASK | KF_TWIST_MASK)
Other fields will be added later.
The value precis and the boolean force_replace are used to determine
if a keyframe should be considered to be at the same position as a
pre-existing keyframe. e.g., if anykey.pos - newkey.pos &lt;= precis,
GK_add_key() will fail unless force_replace is TRUE.
\param pos position
\param fmask
\param force_replace
\param precis precision value
\return 1 if key is added
\return -1 key not added
*/
int GK_add_key(float pos, unsigned long fmask, int force_replace, float precis)
{
Keylist *newk;
float tmp[3];
if (NULL == (newk = (Keylist *)malloc(sizeof(Keylist)))) {
fprintf(stderr, "Out of memory\n");
return (-1);
}
/* All fields set, don't use mask until making Views */
GS_get_from(tmp);
newk->fields[KF_FROMX] = tmp[X];
newk->fields[KF_FROMY] = tmp[Y];
newk->fields[KF_FROMZ] = tmp[Z];
G_debug(3, "KEY FROM: %f %f %f", tmp[X], tmp[Y], tmp[Z]);
/* Instead of View Dir try get_focus (view center) */
/* View Dir is implied from eye and center position */
/* GS_get_viewdir(tmp); */
/* ACS 1 line: was GS_get_focus(tmp);
with this kanimator works also for flythrough navigation
also changed in gk.c
*/
GS_get_viewdir(tmp);
newk->fields[KF_DIRX] = tmp[X];
newk->fields[KF_DIRY] = tmp[Y];
newk->fields[KF_DIRZ] = tmp[Z];
newk->fields[KF_FOV] = GS_get_fov();
newk->fields[KF_TWIST] = GS_get_twist();
newk->pos = pos;
newk->fieldmask = fmask;
newk->next = NULL;
newk->prior = NULL;
if (0 < _add_key(newk, force_replace, precis)) {
GK_update_frames();
return (1);
}
return (-1);
}
/*!
\brief Moves the animation to frame number "step".
Step should be a value between 1 and the number of frames. If
render is non-zero, calls draw_all.
\param step step value
\param render
*/
void GK_do_framestep(int step, int render)
{
if (Views) {
if (step > 0 && step <= Viewsteps) {
gk_follow_frames(Views, Viewsteps, Keys, step, 1, render, Fmode);
}
}
return;
}
/*!
\brief Draw the current path
\param flag
*/
void GK_show_path(int flag)
{
if (flag) {
Fmode |= FM_PATH;
if (Views) {
GS_set_draw(GSD_FRONT);
GS_ready_draw();
gk_draw_path(Views, Viewsteps, Keys);
GS_done_draw();
}
}
else {
Fmode &= ~FM_PATH;
}
return;
}
/*!
\brief Show vector sets
\param flag
*/
void GK_show_vect(int flag)
{
if (flag) {
Fmode |= FM_VECT;
if (Views) {
GS_set_draw(GSD_FRONT);
GS_ready_draw();
GV_alldraw_vect();
GS_done_draw();
}
}
else {
Fmode &= ~FM_VECT;
}
return;
}
/*!
\brief Show point sets
\param flag
*/
void GK_show_site(int flag)
{
if (flag) {
Fmode |= FM_SITE;
if (Views) {
GS_set_draw(GSD_FRONT);
GS_ready_draw();
GP_alldraw_site();
GS_done_draw();
}
}
else {
Fmode &= ~FM_SITE;
}
return;
}
/*!
\brief Show volumes
\param flag
*/
void GK_show_vol(int flag)
{
if (flag) {
Fmode |= FM_VOL;
if (Views) {
GS_set_draw(GSD_FRONT);
GS_ready_draw();
GVL_alldraw_vol();
GS_done_draw();
}
}
else {
Fmode &= ~FM_VOL;
}
return;
}
/*!
\brief Show list
\param flag
*/
void GK_show_list(int flag)
{
if (flag) {
Fmode |= FM_LABEL;
if (Views) {
GS_draw_all_list();
}
}
else {
Fmode &= ~FM_LABEL;
}
return;
}
NULL
#define NULL
Definition ccmath.h:32
G_debug
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition debug.c:66
G_fatal_error
void G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
Definition gis/error.c:159
G_warning
void G_warning(const char *msg,...)
Print a warning message to stderr.
Definition gis/error.c:203
GK_set_tension
void GK_set_tension(float tens)
Set value for tension when interpmode is KF_SPLINE.
Definition gk2.c:155
GK_set_interpmode
int GK_set_interpmode(int mode)
Set interpolation mode.
Definition gk2.c:140
GK_show_vol
void GK_show_vol(int flag)
Show volumes.
Definition gk2.c:582
GK_do_framestep
void GK_do_framestep(int step, int render)
Moves the animation to frame number "step".
Definition gk2.c:487
GK_show_vect
void GK_show_vect(int flag)
Show vector sets.
Definition gk2.c:529
GK_update_tension
void GK_update_tension(void)
Update tension.
Definition gk2.c:195
GK_showtension_stop
void GK_showtension_stop(void)
Show tension stop ?
Definition gk2.c:187
GK_showtension_start
void GK_showtension_start(void)
Definition gk2.c:175
GK_show_path
void GK_show_path(int flag)
Draw the current path.
Definition gk2.c:503
GK_show_list
void GK_show_list(int flag)
Show list.
Definition gk2.c:609
GK_print_keys
void GK_print_keys(const char *name)
Print keyframe info.
Definition gk2.c:209
GK_show_site
void GK_show_site(int flag)
Show point sets.
Definition gk2.c:555
GK_delete_key
int GK_delete_key(float pos, float precis, int justone)
Definition gk2.c:369
GK_set_numsteps
void GK_set_numsteps(int newsteps)
Set the number of frames to be interpolated from keyframes.
Definition gk2.c:299
GK_update_frames
void GK_update_frames(void)
Recalculate path using the current number of frames requested.
Definition gk2.c:245
GK_move_key
int GK_move_key(float oldpos, float precis, float newpos)
Move keyframe.
Definition gk2.c:338
GK_add_key
int GK_add_key(float pos, unsigned long fmask, int force_replace, float precis)
Add keyframe.
Definition gk2.c:431
GK_clear_keys
void GK_clear_keys(void)
Deletes all keyframes, resets field masks.
Definition gk2.c:312
gk_free_key
void gk_free_key(Keylist *ok)
Free keyframe list.
Definition gk.c:271
gk_draw_path
int gk_draw_path(Viewnode *views, int steps, Keylist *keys)
Draw path.
Definition gk.c:749
gk_make_framesfromkeys
Viewnode * gk_make_framesfromkeys(Keylist *keys, int keysteps, int newsteps, int loop, float t)
Generate viewnode from keyframes.
Definition gk.c:301
gk_make_linear_framesfromkeys
Viewnode * gk_make_linear_framesfromkeys(Keylist *keys, int keysteps, int newsteps, int loop)
Generate viewnode from keyframe list (linear interpolation).
Definition gk.c:611
gk_follow_frames
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
GP_alldraw_site
void GP_alldraw_site(void)
Draw all available point sets.
Definition gp2.c:615
GS_get_twist
int GS_get_twist(void)
Get twist value.
Definition gs2.c:2863
GS_draw_all_list
void GS_draw_all_list(void)
Draw all glLists.
Definition gs2.c:874
GS_get_from
void GS_get_from(float *fr)
Get viewpoint 'from' position.
Definition gs2.c:2724
GS_get_viewdir
void GS_get_viewdir(float *dir)
Get viewdir.
Definition gs2.c:2807
GS_alldraw_wire
void GS_alldraw_wire(void)
Draw all wires.
Definition gs2.c:1920
GS_clear
void GS_clear(int col)
Clear view.
Definition gs2.c:3417
GS_get_fov
int GS_get_fov(void)
Get field of view.
Definition gs2.c:2853
GS_ready_draw
void GS_ready_draw(void)
Definition gs2.c:2488
GS_background_color
unsigned int GS_background_color(void)
Get background color.
Definition gs2.c:2452
GS_set_draw
void GS_set_draw(int where)
Sets which buffer to draw to.
Definition gs2.c:2462
GS_done_draw
void GS_done_draw(void)
Draw done, swap buffers.
Definition gs2.c:2501
GV_alldraw_vect
void GV_alldraw_vect(void)
Draw all loaded vector sets.
Definition gv2.c:506
GVL_alldraw_vol
void GVL_alldraw_vol(void)
Draw all volume sets.
Definition gvl2.c:447
name
const char * name
Definition named_colr.c:6
X
#define X(j)
Y
#define Y(j)