libanim
changeset 57:2da758956e50
added the option of lightweight pre-pass top-down recursive calculation of
matrices instead of going through the existing lazy thread-specific caching
algorithm.
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Mon, 09 Dec 2013 04:06:30 +0200 |
parents | 73cd80b3db29 |
children | fe017bde08bc |
files | example/Makefile example/test.c src/anim.c src/anim.h |
diffstat | 4 files changed, 76 insertions(+), 6 deletions(-) [+] |
line diff
1.1 --- a/example/Makefile Sat Nov 16 12:31:03 2013 +0200 1.2 +++ b/example/Makefile Mon Dec 09 04:06:30 2013 +0200 1.3 @@ -3,7 +3,7 @@ 1.4 bin = test 1.5 1.6 CFLAGS = -pedantic -Wall -g -I../src 1.7 -LDFLAGS = -L.. -lanim -lvmath $(libgl) -lm 1.8 +LDFLAGS = -L.. -lanim -lvmath $(libgl) -lm -lpthread 1.9 1.10 ifeq ($(shell uname -s), Darwin) 1.11 libgl = -framework OpenGL -framework GLUT
2.1 --- a/example/test.c Sat Nov 16 12:31:03 2013 +0200 2.2 +++ b/example/test.c Mon Dec 09 04:06:30 2013 +0200 2.3 @@ -184,6 +184,10 @@ 2.4 glRotatef(cam_phi, 1, 0, 0); 2.5 glRotatef(cam_theta, 0, 1, 0); 2.6 2.7 + /* first render a character with bottom-up lazy matrix calculation */ 2.8 + glPushMatrix(); 2.9 + glTranslatef(-2.5, 0, 0); 2.10 + 2.11 for(i=0; i<NUM_NODES; i++) { 2.12 float color[4] = {0, 0, 0, 1}; 2.13 mat4_t xform, xform_transp; 2.14 @@ -203,10 +207,39 @@ 2.15 2.16 glScalef(parts[i].sz.x, parts[i].sz.y, parts[i].sz.z); 2.17 glutSolidCube(1.0); 2.18 - /*glutWireSphere(0.6, 16, 8);*/ 2.19 2.20 glPopMatrix(); 2.21 } 2.22 + glPopMatrix(); 2.23 + 2.24 + /* then render another one using simple top-down recursive evaluation */ 2.25 + glPushMatrix(); 2.26 + glTranslatef(2.5, 0, 0); 2.27 + 2.28 + anm_eval(nodes[NODE_TORSO], msec); /* calculate all matrices recursively */ 2.29 + 2.30 + for(i=0; i<NUM_NODES; i++) { 2.31 + float color[4] = {0, 0, 0, 1}; 2.32 + mat4_t xform_transp; 2.33 + 2.34 + color[0] = parts[i].color.x; 2.35 + color[1] = parts[i].color.y; 2.36 + color[2] = parts[i].color.z; 2.37 + 2.38 + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); 2.39 + glColor4fv(color); 2.40 + 2.41 + m4_transpose(xform_transp, nodes[i]->matrix); 2.42 + 2.43 + glPushMatrix(); 2.44 + glMultMatrixf((float*)xform_transp); 2.45 + 2.46 + glScalef(parts[i].sz.x, parts[i].sz.y, parts[i].sz.z); 2.47 + glutSolidCube(1.0); 2.48 + 2.49 + glPopMatrix(); 2.50 + } 2.51 + glPopMatrix(); 2.52 2.53 glutSwapBuffers(); 2.54 assert(glGetError() == GL_NO_ERROR);
3.1 --- a/src/anim.c Sat Nov 16 12:31:03 2013 +0200 3.2 +++ b/src/anim.c Mon Dec 09 04:06:30 2013 +0200 3.3 @@ -381,6 +381,30 @@ 3.4 m4_inverse(mat, tmp); 3.5 } 3.6 3.7 +void anm_eval_node(struct anm_node *node, anm_time_t tm) 3.8 +{ 3.9 + anm_get_node_matrix(node, node->matrix, tm); 3.10 +} 3.11 + 3.12 +void anm_eval(struct anm_node *node, anm_time_t tm) 3.13 +{ 3.14 + struct anm_node *c; 3.15 + 3.16 + anm_eval_node(node, tm); 3.17 + 3.18 + if(node->parent) { 3.19 + /* due to post-order traversal, the parent matrix is already evaluated */ 3.20 + m4_mult(node->matrix, node->parent->matrix, node->matrix); 3.21 + } 3.22 + 3.23 + /* recersively evaluate all children */ 3.24 + c = node->child; 3.25 + while(c) { 3.26 + anm_eval(c, tm); 3.27 + c = c->next; 3.28 + } 3.29 +} 3.30 + 3.31 void anm_get_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm) 3.32 { 3.33 struct mat_cache *cache = pthread_getspecific(node->cache_key);
4.1 --- a/src/anim.h Sat Nov 16 12:31:03 2013 +0200 4.2 +++ b/src/anim.h Mon Dec 09 04:06:30 2013 +0200 4.3 @@ -42,6 +42,9 @@ 4.4 pthread_key_t cache_key; 4.5 pthread_mutex_t cache_list_lock; 4.6 4.7 + /* matrix calculated by anm_eval functions (no locking, meant as a pre-pass) */ 4.8 + mat4_t matrix; 4.9 + 4.10 struct anm_node *parent; 4.11 struct anm_node *child; 4.12 struct anm_node *next; 4.13 @@ -95,10 +98,24 @@ 4.14 void anm_set_pivot(struct anm_node *node, vec3_t pivot); 4.15 vec3_t anm_get_pivot(struct anm_node *node); 4.16 4.17 +/* those return the start and end times of the whole tree */ 4.18 +anm_time_t anm_get_start_time(struct anm_node *node); 4.19 +anm_time_t anm_get_end_time(struct anm_node *node); 4.20 + 4.21 /* these calculate the matrix and inverse matrix of this node alone */ 4.22 void anm_get_node_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm); 4.23 void anm_get_node_inv_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm); 4.24 4.25 +/* ---- top-down matrix calculation interface ---- */ 4.26 + 4.27 +/* calculate and set the matrix of this node */ 4.28 +void anm_eval_node(struct anm_node *node, anm_time_t tm); 4.29 +/* calculate and set the matrix of this node and all its children recursively */ 4.30 +void anm_eval(struct anm_node *node, anm_time_t tm); 4.31 + 4.32 + 4.33 +/* ---- bottom-up lazy matrix calculation interface ---- */ 4.34 + 4.35 /* These calculate the matrix and inverse matrix of this node taking hierarchy 4.36 * into account. The results are cached in thread-specific storage and returned 4.37 * if there's no change in time or tracks from the last query... 4.38 @@ -106,10 +123,6 @@ 4.39 void anm_get_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm); 4.40 void anm_get_inv_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm); 4.41 4.42 -/* those return the start and end times of the whole tree */ 4.43 -anm_time_t anm_get_start_time(struct anm_node *node); 4.44 -anm_time_t anm_get_end_time(struct anm_node *node); 4.45 - 4.46 #ifdef __cplusplus 4.47 } 4.48 #endif