node.c (5015B)
1 2 3 #include "node.h" 4 #include "mat_util.h" 5 #include "debug.h" 6 #include <string.h> 7 #include <stdio.h> 8 #include <assert.h> 9 #include <stdint.h> 10 11 struct resource_manager node_manager = {0}; 12 13 void destroy_node(struct node_id *id) 14 { 15 #ifdef DEBUG 16 struct node *node = get_node(id); 17 debug("destroying node %" PRIu64 " %s\n", id->id.uuid, node->label); 18 #endif 19 20 destroy_resource(&node_manager, &id->id); 21 } 22 23 void init_node_manager() 24 { 25 init_resource_manager(&node_manager, sizeof(struct node), 4096, 26 0xFFFF, "node"); 27 } 28 29 struct node *node_init(struct node *node) { 30 mat4_id(node->mat); 31 vec3_all(node->pos, 0); 32 vec3_all(node->rot, 0); 33 vec3_all(node->scale, 1.0); 34 quat_id(node->orientation); 35 node->n_children = 0; 36 for (int i = 0; i < MAX_NODE_CHILDREN; ++i) 37 init_id(&node->children_ids[i]); 38 node->flags = 0; 39 null_id(&node->parent_id); 40 node_set_label(node, "unknown"); 41 node->needs_recalc = 0; 42 node->custom_update = 0; 43 node_mark_for_recalc(node); 44 45 return node; 46 } 47 48 int node_set_label(struct node *node, const char *label) 49 { 50 strncpy(node->label, label, sizeof(node->label)-1); 51 // return 0 if the string is too big and that we've truncated it 52 int ok = node->label[sizeof(node->label)-1] == '\0'; 53 // strncpy won't write this for large strings =/ 54 node->label[sizeof(node->label)-1] = '\0'; 55 return ok; 56 } 57 58 void node_scale(struct node *node, float val) { 59 vec3_scale(node->scale, val, node->scale); 60 } 61 62 void node_translate(struct node *node, vec3 *p) { 63 if (vec3_isall(p, 0)) 64 return; 65 66 /* printf("translating %f %f %f\n", p[0], p[1], p[2]); */ 67 vec3_add(node->pos, p, node->pos); 68 node_mark_for_recalc(node); 69 } 70 71 void node_rotate(struct node *node, vec3 *axis_angles) { 72 if (vec3_isall(axis_angles, 0)) 73 return; 74 75 for (int i = 0; i < 3; ++i) { 76 float axis[3] = {0}; 77 float quat[4]; 78 axis[i] = 1; 79 quat_axis_angle(axis, axis_angles[i], quat); 80 quat_multiply(node->orientation, quat, node->orientation); 81 } 82 83 /* printf("translating %f %f %f\n", p[0], p[1], p[2]); */ 84 node_mark_for_recalc(node); 85 } 86 87 void node_mark_for_recalc(struct node *node) { 88 static int j = 0; 89 90 if (node->needs_recalc) 91 return; 92 93 node->needs_recalc = 1; 94 95 for (int i = 0; i < node->n_children; ++i) { 96 struct node *child = get_node(&node->children_ids[i]); 97 if (child) 98 node_mark_for_recalc(child); 99 } 100 } 101 102 static void node_recalc_children(struct node *node) { 103 for (int i = 0; i < node->n_children; ++i) { 104 struct node *child = get_node(&node->children_ids[i]); 105 if (child) 106 node_recalc(child); 107 } 108 } 109 110 int node_recalc(struct node *node) { 111 assert(node); 112 float rot[9] = {1.0}; 113 114 struct node *parent = get_node(&node->parent_id); 115 if (parent && node_needs_recalc(parent)) { 116 node_recalc(parent); 117 } 118 119 if (!node_needs_recalc(node)) { 120 node_recalc_children(node); 121 return 0; 122 } 123 124 node->needs_recalc = 0; 125 126 if (!node->custom_update) { 127 quat_to_mat3(node->orientation, rot); 128 mat4_create_transform(node->pos, node->scale, rot, node->mat); 129 130 if (parent) { 131 assert(!parent->needs_recalc); 132 mat4_multiply(parent->mat, node->mat, node->mat); 133 } 134 135 } 136 else { 137 debug("custom updating %s\n", node->label); 138 node->custom_update(node); 139 } 140 141 node_recalc_children(node); 142 143 return 1; 144 } 145 146 int node_detach(struct node *node, struct node *from) { 147 for (int i = 0; i < from->n_children; i++) { 148 struct node_id *child_id = &from->children_ids[i]; 149 struct node *child = get_node(&from->children_ids[i]); 150 if (child && child == node) { 151 destroy_node(child_id); 152 memmove(&from->children_ids[i], &from->children_ids[i+1], 153 sizeof(*from->children_ids) * (from->n_children - i - 1)); 154 // TODO: test node_detach 155 from->n_children--; 156 return 1; 157 } 158 } 159 return 0; 160 } 161 162 void node_detach_from_parent(struct node *node) 163 { 164 struct node *parent = get_node(&node->parent_id); 165 166 if (parent) 167 node_detach(node, parent); 168 } 169 170 // count the total number of nodes 171 int node_count(struct node *node) 172 { 173 int c = 1; 174 for (int i = 0; i < node->n_children; i++) { 175 struct node *child = get_node(&node->children_ids[i]); 176 assert(child); 177 if (child) 178 c += node_count(child); 179 } 180 return c; 181 } 182 183 184 void node_attach(struct node_id *node_id, struct node_id *to_id) 185 { 186 struct node *node = get_node(node_id); 187 struct node *to = get_node(to_id); 188 189 assert(node); 190 if (to->n_children > MAX_NODE_CHILDREN) { 191 debug("to->n_children %d\n", to->n_children); 192 } 193 assert(to && to->n_children <= MAX_NODE_CHILDREN); 194 195 node->parent_id = *to_id; 196 assert(node->parent_id.id.uuid == to_id->id.uuid); 197 to->children_ids[to->n_children++] = *node_id; 198 } 199 200 void node_forward(struct node *node, float *dir) { 201 vec3_forward(node->pos, node->orientation, dir, node->pos); 202 node_mark_for_recalc(node); 203 }