working on the transformation node system
[erebus2020] / liberebus / src / node.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include "erebus.h"
4
5 static struct erb_key *findkey(struct erb_track *trk, long tm);
6 static int setkey(struct erb_track *trk, long key, float val);
7 static float evalkey(struct erb_track *trk, long key);
8
9 void erb_node_pos(struct erb_node *n, long tm, float x, float y, float z)
10 {
11         setkey(n->track + ERB_TRK_X, tm, x);
12         setkey(n->track + ERB_TRK_Y, tm, y);
13         setkey(n->track + ERB_TRK_Z, tm, z);
14 }
15
16 void erb_node_rot(struct erb_node *n, long tm, float qx, float qy, float qz, float qw)
17 {
18         setkey(n->track + ERB_TRK_QX, tm, qx);
19         setkey(n->track + ERB_TRK_QY, tm, qy);
20         setkey(n->track + ERB_TRK_QZ, tm, qz);
21         setkey(n->track + ERB_TRK_QW, tm, qw);
22 }
23
24 void erb_node_rot_axis(struct erb_node *n, long tm, float angle_deg, float x, float y, float z)
25 {
26         cgm_quat q;
27         cgm_qrotation(&q, cgm_deg_to_rad(angle_deg), x, y, z);
28         erb_node_rot(n, tm, q.x, q.y, q.z, q.w);
29 }
30
31 void erb_node_scale(struct erb_node *n, long tm, float sx, float sy, float sz)
32 {
33         setkey(n->track + ERB_TRK_SX, tm, sx);
34         setkey(n->track + ERB_TRK_SY, tm, sy);
35         setkey(n->track + ERB_TRK_SZ, tm, sz);
36 }
37
38 void erb_node_update(struct erb_node *n, long tm)
39 {
40         erb_node_eval_node_matrix(n, tm, n->node_xform);
41
42         cgm_mcopy(n->inv_node_xform, n->node_xform);
43         cgm_minverse(n->inv_node_xform);
44
45         cgm_mcopy(n->xform, n->node_xform);
46         cgm_mcopy(n->inv_xform, n->inv_node_xform);
47
48         if(n->par) {
49                 cgm_mmul(n->xform, n->par->xform);
50                 cgm_mpremul(n->inv_xform, n->par->inv_xform);
51         }
52 }
53
54 void erb_node_setxform(struct erb_node *n, float *mat)
55 {
56         cgm_mcopy(n->node_xform, mat);
57         cgm_mcopy(n->inv_node_xform, mat);
58         cgm_minverse(n->inv_node_xform);
59
60         cgm_mcopy(n->xform, n->node_xform);
61         cgm_mcopy(n->inv_xform, n->inv_node_xform);
62
63         if(n->par) {
64                 cgm_mmul(n->xform, n->par->xform);
65                 cgm_mpremul(n->inv_xform, n->par->inv_xform);
66         }
67 }
68
69 void erb_node_eval_pos(struct erb_node *n, long tm, cgm_vec3 *pos)
70 {
71         pos->x = evalkey(n->track + ERB_TRK_X, tm);
72         pos->y = evalkey(n->track + ERB_TRK_Y, tm);
73         pos->z = evalkey(n->track + ERB_TRK_Z, tm);
74 }
75
76 void erb_node_eval_rot(struct erb_node *n, long tm, cgm_quat *rot)
77 {
78         rot->x = evalkey(n->track + ERB_TRK_QX, tm);
79         rot->y = evalkey(n->track + ERB_TRK_QY, tm);
80         rot->z = evalkey(n->track + ERB_TRK_QZ, tm);
81         rot->w = evalkey(n->track + ERB_TRK_QW, tm);
82 }
83
84 void erb_node_eval_scale(struct erb_node *n, long tm, cgm_vec3 *scale)
85 {
86         scale->x = evalkey(n->track + ERB_TRK_SX, tm);
87         scale->y = evalkey(n->track + ERB_TRK_SY, tm);
88         scale->z = evalkey(n->track + ERB_TRK_SZ, tm);
89 }
90
91 void erb_node_eval_matrix(struct erb_node *n, long tm, float *mat)
92 {
93         erb_node_eval_node_matrix(n, tm, mat);
94         if(n->par) {
95                 cgm_mmul(mat, n->par->xform);
96         }
97 }
98
99 void erb_node_eval_node_matrix(struct erb_node *n, long tm, float *mat)
100 {
101         cgm_vec3 pos, scale;
102         cgm_quat rot;
103
104         erb_node_eval_pos(n, tm, &pos);
105         erb_node_eval_rot(n, tm, &rot);
106         erb_node_eval_scale(n, tm, &scale);
107
108         cgm_midentity(mat);
109         cgm_mtranslate(mat, pos.x, pos.y, pos.z);
110         cgm_mrotate_quat(mat, &rot);
111         cgm_mscale(mat, scale.x, scale.y, scale.z);
112 }
113
114 static struct erb_key *findkey(struct erb_track *trk, long tm)
115 {
116         struct erb_key *beg, *end, *mid;
117
118         /* TODO: if num_keys < something_small, do linear search */
119         if(trk->num_keys <= 0) return 0;
120
121         beg = trk->keys;
122         end = trk->keys + trk->num_keys;
123
124         while(beg < end) {
125                 mid = beg + ((end - beg) >> 1);
126
127                 if(tm == mid->tm) return mid;
128                 if(tm < mid->tm) {
129                         end = mid;
130                 } else {
131                         beg = mid + 1;
132                 }
133         }
134         return beg;
135 }
136
137
138 static int setkey(struct erb_track *trk, long tm, float val)
139 {
140         int rest;
141         struct erb_key *key;
142
143         if((key = findkey(trk, tm)) && key->tm == tm) {
144                 key->val = val;
145                 return 0;
146         }
147
148         if(trk->num_keys >= trk->max_keys) {
149                 int newsz = trk->max_keys ? trk->max_keys << 1 : 8;
150                 void *ptr;
151
152                 if(!(ptr = realloc(trk->keys, newsz * sizeof *key))) {
153                         fprintf(stderr, "erebus: failed to add keyframe (realloc track failed)\n");
154                         return -1;
155                 }
156                 trk->keys = ptr;
157                 trk->max_keys = newsz;
158         }
159
160         key++;
161         rest = trk->num_keys - (key - trk->keys);
162         if(rest > 0) {
163                 memmove(key + 1, key, rest * sizeof *key);
164         }
165         key->tm = tm;
166         key->val = val;
167         trk->num_keys++;
168         return 0;
169 }
170
171 static float evalkey(struct erb_track *trk, long tm)
172 {
173         /* TODO */
174         return 0;
175 }