working on the transformation node system master
authorJohn Tsiombikas <nuclear@member.fsf.org>
Thu, 24 Dec 2020 09:29:39 +0000 (11:29 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Thu, 24 Dec 2020 09:29:39 +0000 (11:29 +0200)
liberebus/src/erebus.c
liberebus/src/erebus.h
liberebus/src/node.c [new file with mode: 0644]
xerebus/src/main.c

index 8ad4a88..de8598f 100644 (file)
@@ -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);
index e6e067b..758e4d3 100644 (file)
@@ -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 (file)
index 0000000..593a0c7
--- /dev/null
@@ -0,0 +1,175 @@
+#include <stdio.h>
+#include <stdlib.h>
+#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;
+}
index 9569df1..0eda94d 100644 (file)
@@ -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);
 }