From: John Tsiombikas Date: Thu, 24 Dec 2020 09:29:39 +0000 (+0200) Subject: working on the transformation node system X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=commitdiff_plain;ds=sidebyside;h=refs%2Fheads%2Fmaster;p=erebus2020 working on the transformation node system --- diff --git a/liberebus/src/erebus.c b/liberebus/src/erebus.c index 8ad4a88..de8598f 100644 --- a/liberebus/src/erebus.c +++ b/liberebus/src/erebus.c @@ -16,6 +16,8 @@ struct erb_rend { erb_done_func donecb; void *donecls; + + float vfov; }; static void proc_render_job(void *cls); @@ -40,6 +42,9 @@ struct erb_rend *erb_create(void) if(!(erb = calloc(1, sizeof *erb))) { return 0; } + + erb->vfov = cgm_deg_to_rad(50.0f); + return erb; } @@ -79,6 +84,11 @@ float *erb_getframe(struct erb_rend *erb) return erb->fb_pixels; } +void erb_setfov(struct erb_rend *erb, float vfov_deg) +{ + erb->vfov = cgm_deg_to_rad(vfov_deg); +} + void erb_begin(struct erb_rend *erb) { memset(erb->fb_pixels, 0, erb->fb_size); diff --git a/liberebus/src/erebus.h b/liberebus/src/erebus.h index e6e067b..758e4d3 100644 --- a/liberebus/src/erebus.h +++ b/liberebus/src/erebus.h @@ -26,10 +26,32 @@ struct erb_aabb { cgm_vec3 pos, sz; }; +struct erb_key { + long tm; + float val; +}; + +enum { + ERB_TRK_X, ERB_TRK_Y, ERB_TRK_Z, /* position (x,y,z) */ + ERB_TRK_QX, ERB_TRK_QY, ERB_TRK_QZ, ERB_TRK_QW, /* rotation quat (xi+yj+zk+w) */ + ERB_TRK_SX, ERB_TRK_SY, ERB_TRK_SZ, /* scaling (x,y,z) */ + ERB_NUM_TRACKS +}; +enum erb_interp { ERB_LINEAR, ERB_STEP, ERB_CUBIC }; +enum erb_extrap { ERB_CLAMP, ERB_EXTEND, ERB_REPEAT }; + +struct erb_track { + enum erb_interp interp; /* interpolation mode */ + enum erb_extrap extrap; /* extrapolation mode */ + struct erb_key *keys; /* dynamic array of keyframes */ + int num_keys, max_keys; /* max_keys: allocated size, num_keys: used */ +}; + struct erb_node { struct erb_node *par; /* parent node */ struct erb_node *clist; /* child nodes */ struct erb_surf *surflist; /* surfaces in this node */ + struct erb_track track[ERB_NUM_TRACKS]; /* PRS keyframe tracks */ float xform[16], inv_xform[16]; /* global transformation */ float node_xform[16], inv_node_xform[16]; /* local transformation */ }; @@ -72,6 +94,8 @@ void erb_destroy(struct erb_rend *erb); int erb_allocframe(struct erb_rend *erb, int width, int height); float *erb_getframe(struct erb_rend *erb); +void erb_setfov(struct erb_rend *erb, float vfov_deg); + /* clears the framebuffer and sample counters to begin rendering a new frame */ void erb_begin(struct erb_rend *erb); /* finalizes the frame, averaging samples (optional) */ @@ -96,8 +120,22 @@ int erb_node_addsurf(struct erb_node *n, struct erb_surf *s); int erb_node_rmsurf(struct erb_node *n, struct erb_surf *s); /* sets the transformation matrix and also calculates the inverse */ +void erb_node_pos(struct erb_node *n, long tm, float x, float y, float z); +void erb_node_rot(struct erb_node *n, long tm, float qx, float qy, float qz, float qw); +void erb_node_rot_axis(struct erb_node *n, long tm, float angle_deg, float x, float y, float z); +void erb_node_scale(struct erb_node *n, long tm, float sx, float sy, float sz); +/* calculates transformation matrices for time tm by keyframe interpolation */ +void erb_node_update(struct erb_node *n, long tm); +/* sets transformation, ignoring animation keyframes */ void erb_node_setxform(struct erb_node *n, float *mat); +void erb_node_eval_pos(struct erb_node *n, long tm, cgm_vec3 *pos); +void erb_node_eval_rot(struct erb_node *n, long tm, cgm_quat *rot); +void erb_node_eval_scale(struct erb_node *n, long tm, cgm_vec3 *scale); + +void erb_node_eval_matrix(struct erb_node *n, long tm, float *mat); /* mat[16] */ +void erb_node_eval_node_matrix(struct erb_node *n, long tm, float *mat); /* mat[16] */ + /* surfaces */ struct erb_surf *erb_surface(int datasz); void erb_free_surface(struct erb_surf *surf); diff --git a/liberebus/src/node.c b/liberebus/src/node.c new file mode 100644 index 0000000..593a0c7 --- /dev/null +++ b/liberebus/src/node.c @@ -0,0 +1,175 @@ +#include +#include +#include "erebus.h" + +static struct erb_key *findkey(struct erb_track *trk, long tm); +static int setkey(struct erb_track *trk, long key, float val); +static float evalkey(struct erb_track *trk, long key); + +void erb_node_pos(struct erb_node *n, long tm, float x, float y, float z) +{ + setkey(n->track + ERB_TRK_X, tm, x); + setkey(n->track + ERB_TRK_Y, tm, y); + setkey(n->track + ERB_TRK_Z, tm, z); +} + +void erb_node_rot(struct erb_node *n, long tm, float qx, float qy, float qz, float qw) +{ + setkey(n->track + ERB_TRK_QX, tm, qx); + setkey(n->track + ERB_TRK_QY, tm, qy); + setkey(n->track + ERB_TRK_QZ, tm, qz); + setkey(n->track + ERB_TRK_QW, tm, qw); +} + +void erb_node_rot_axis(struct erb_node *n, long tm, float angle_deg, float x, float y, float z) +{ + cgm_quat q; + cgm_qrotation(&q, cgm_deg_to_rad(angle_deg), x, y, z); + erb_node_rot(n, tm, q.x, q.y, q.z, q.w); +} + +void erb_node_scale(struct erb_node *n, long tm, float sx, float sy, float sz) +{ + setkey(n->track + ERB_TRK_SX, tm, sx); + setkey(n->track + ERB_TRK_SY, tm, sy); + setkey(n->track + ERB_TRK_SZ, tm, sz); +} + +void erb_node_update(struct erb_node *n, long tm) +{ + erb_node_eval_node_matrix(n, tm, n->node_xform); + + cgm_mcopy(n->inv_node_xform, n->node_xform); + cgm_minverse(n->inv_node_xform); + + cgm_mcopy(n->xform, n->node_xform); + cgm_mcopy(n->inv_xform, n->inv_node_xform); + + if(n->par) { + cgm_mmul(n->xform, n->par->xform); + cgm_mpremul(n->inv_xform, n->par->inv_xform); + } +} + +void erb_node_setxform(struct erb_node *n, float *mat) +{ + cgm_mcopy(n->node_xform, mat); + cgm_mcopy(n->inv_node_xform, mat); + cgm_minverse(n->inv_node_xform); + + cgm_mcopy(n->xform, n->node_xform); + cgm_mcopy(n->inv_xform, n->inv_node_xform); + + if(n->par) { + cgm_mmul(n->xform, n->par->xform); + cgm_mpremul(n->inv_xform, n->par->inv_xform); + } +} + +void erb_node_eval_pos(struct erb_node *n, long tm, cgm_vec3 *pos) +{ + pos->x = evalkey(n->track + ERB_TRK_X, tm); + pos->y = evalkey(n->track + ERB_TRK_Y, tm); + pos->z = evalkey(n->track + ERB_TRK_Z, tm); +} + +void erb_node_eval_rot(struct erb_node *n, long tm, cgm_quat *rot) +{ + rot->x = evalkey(n->track + ERB_TRK_QX, tm); + rot->y = evalkey(n->track + ERB_TRK_QY, tm); + rot->z = evalkey(n->track + ERB_TRK_QZ, tm); + rot->w = evalkey(n->track + ERB_TRK_QW, tm); +} + +void erb_node_eval_scale(struct erb_node *n, long tm, cgm_vec3 *scale) +{ + scale->x = evalkey(n->track + ERB_TRK_SX, tm); + scale->y = evalkey(n->track + ERB_TRK_SY, tm); + scale->z = evalkey(n->track + ERB_TRK_SZ, tm); +} + +void erb_node_eval_matrix(struct erb_node *n, long tm, float *mat) +{ + erb_node_eval_node_matrix(n, tm, mat); + if(n->par) { + cgm_mmul(mat, n->par->xform); + } +} + +void erb_node_eval_node_matrix(struct erb_node *n, long tm, float *mat) +{ + cgm_vec3 pos, scale; + cgm_quat rot; + + erb_node_eval_pos(n, tm, &pos); + erb_node_eval_rot(n, tm, &rot); + erb_node_eval_scale(n, tm, &scale); + + cgm_midentity(mat); + cgm_mtranslate(mat, pos.x, pos.y, pos.z); + cgm_mrotate_quat(mat, &rot); + cgm_mscale(mat, scale.x, scale.y, scale.z); +} + +static struct erb_key *findkey(struct erb_track *trk, long tm) +{ + struct erb_key *beg, *end, *mid; + + /* TODO: if num_keys < something_small, do linear search */ + if(trk->num_keys <= 0) return 0; + + beg = trk->keys; + end = trk->keys + trk->num_keys; + + while(beg < end) { + mid = beg + ((end - beg) >> 1); + + if(tm == mid->tm) return mid; + if(tm < mid->tm) { + end = mid; + } else { + beg = mid + 1; + } + } + return beg; +} + + +static int setkey(struct erb_track *trk, long tm, float val) +{ + int rest; + struct erb_key *key; + + if((key = findkey(trk, tm)) && key->tm == tm) { + key->val = val; + return 0; + } + + if(trk->num_keys >= trk->max_keys) { + int newsz = trk->max_keys ? trk->max_keys << 1 : 8; + void *ptr; + + if(!(ptr = realloc(trk->keys, newsz * sizeof *key))) { + fprintf(stderr, "erebus: failed to add keyframe (realloc track failed)\n"); + return -1; + } + trk->keys = ptr; + trk->max_keys = newsz; + } + + key++; + rest = trk->num_keys - (key - trk->keys); + if(rest > 0) { + memmove(key + 1, key, rest * sizeof *key); + } + key->tm = tm; + key->val = val; + trk->num_keys++; + return 0; +} + +static float evalkey(struct erb_track *trk, long tm) +{ + /* TODO */ + return 0; +} diff --git a/xerebus/src/main.c b/xerebus/src/main.c index 9569df1..0eda94d 100644 --- a/xerebus/src/main.c +++ b/xerebus/src/main.c @@ -99,6 +99,7 @@ int main(int argc, char **argv) return 1; } erb_set_done_callback(erb, jobdone, 0); + reshape_pending = redisp_pending = 1; glGenTextures(1, &fbtex); @@ -125,16 +126,17 @@ int main(int argc, char **argv) break; } - redisp_pending = 0; - glutMainLoopEvent(); - if(FD_ISSET(pfd[0], &rdset)) { struct erb_rect rect; read(pfd[0], &rect, sizeof rect); glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x, rect.y, rect.w, rect.h, GL_RGBA, GL_FLOAT, erb_getframe(erb) + (rect.y * win_width + rect.x) * 4); post_redisplay(); - printf("update (%d %d %dx%d)!\n", rect.x, rect.y, rect.w, rect.h); + } + + if(FD_ISSET(xfd, &rdset) || redisp_pending) { + redisp_pending = 0; + glutMainLoopEvent(); } } #endif /* __unix__ */ @@ -145,7 +147,6 @@ int main(int argc, char **argv) static void jobdone(unsigned int job, struct erb_rect *rect, void *cls) { - printf("jobdone!\n"); write(pfd[1], rect, sizeof *rect); }