src/scene.c

changeset 38
6e5629ea4c5c
parent 37
8a8cc6725b48
child 39
7cf310cc47cb
equal deleted inserted replaced
37:8a8cc6725b48 38:6e5629ea4c5c
36 #include "ascension/shader.h" 36 #include "ascension/shader.h"
37 #include <GL/glew.h> 37 #include <GL/glew.h>
38 38
39 #include <assert.h> 39 #include <assert.h>
40 40
41 static CxTreeIterator asc_scene_node_iterator(
42 AscSceneNode *node,
43 bool visit_on_exit
44 ) {
45 return cx_tree_iterator(
46 node, visit_on_exit,
47 offsetof(AscSceneNode, children),
48 offsetof(AscSceneNode, next)
49 );
50 }
51
41 void asc_scene_init(AscScene *scene) { 52 void asc_scene_init(AscScene *scene) {
42 if (scene->root != NULL) { 53 if (scene->root != NULL) {
43 asc_error("Scene is already initialized."); 54 asc_error("Scene is already initialized.");
44 return; 55 return;
45 } 56 }
76 // reset render groups 87 // reset render groups
77 scene->rg_none_size = 0; 88 scene->rg_none_size = 0;
78 scene->rg_fonts_size = 0; 89 scene->rg_fonts_size = 0;
79 90
80 // skip the root node deliberately, we know it's just the container 91 // skip the root node deliberately, we know it's just the container
81 CxTreeIterator iter = cx_tree_iterator( 92 CxTreeIterator iter = asc_scene_node_iterator(scene->root, false);
82 scene->root, false,
83 offsetof(AscSceneNode, children),
84 offsetof(AscSceneNode, next)
85 );
86 cxIteratorNext(iter); 93 cxIteratorNext(iter);
87 94
88 // update the children and add them to the render groups 95 // update the children and add them to the render groups
89 cx_foreach(AscSceneNode*, node, iter) { 96 cx_foreach(AscSceneNode*, node, iter) {
90 // execute behaviors, first 97 // execute behaviors, first
101 node->update_func(node); 108 node->update_func(node);
102 } 109 }
103 if (node->need_transform_update) { 110 if (node->need_transform_update) {
104 assert(node->transform_update_func != NULL); 111 assert(node->transform_update_func != NULL);
105 node->need_transform_update = false; 112 node->need_transform_update = false;
106 asc_transform_identity(node->transform); 113 asc_transform_identity(node->local_transform);
114 asc_transform_copy(node->world_transform, node->parent->world_transform);
107 node->transform_update_func(node); 115 node->transform_update_func(node);
116 asc_mat4f_mulst(node->final_transform, node->local_transform, node->world_transform);
108 } 117 }
109 118
110 // add to render group 119 // add to render group
111 if (node->draw_func != NULL) { 120 if (node->draw_func != NULL) {
112 struct asc_render_group_entry entry = { 121 struct asc_render_group_entry entry = {
153 } 162 }
154 163
155 AscSceneNode *asc_scene_node_empty(void) { 164 AscSceneNode *asc_scene_node_empty(void) {
156 AscSceneNode *node = calloc(1, sizeof(AscSceneNode)); 165 AscSceneNode *node = calloc(1, sizeof(AscSceneNode));
157 node->free_func = (asc_scene_free_func) free; 166 node->free_func = (asc_scene_free_func) free;
158 asc_transform_identity(node->transform); 167 asc_transform_identity(node->local_transform);
168 asc_transform_identity(node->world_transform);
169 asc_transform_identity(node->final_transform);
159 return node; 170 return node;
160 } 171 }
161 172
162 void asc_scene_node_free(AscSceneNode *node) { 173 void asc_scene_node_free(AscSceneNode *node) {
163 if (node == NULL) return; 174 if (node == NULL) return;
164 175
165 // remove this node from its parent 176 // remove this node from its parent
166 asc_scene_node_unlink(node); 177 asc_scene_node_unlink(node);
167 178
168 // free the entire subtree 179 // free the entire subtree
169 CxTreeIterator iter = cx_tree_iterator( 180 CxTreeIterator iter = asc_scene_node_iterator(node, true);
170 node, true,
171 offsetof(AscSceneNode, children),
172 offsetof(AscSceneNode, next)
173 );
174 cx_foreach(AscSceneNode*, child, iter) { 181 cx_foreach(AscSceneNode*, child, iter) {
175 if (!iter.exiting) continue; 182 if (!iter.exiting) continue;
176 if (child->free_func != NULL) { 183 if (child->free_func != NULL) {
177 child->free_func(child); 184 child->free_func(child);
178 } else { 185 } else {
222 offsetof(AscSceneNode, behaviors), 229 offsetof(AscSceneNode, behaviors),
223 offsetof(AscBehaviorNode, prev), 230 offsetof(AscBehaviorNode, prev),
224 offsetof(AscBehaviorNode, next) 231 offsetof(AscBehaviorNode, next)
225 ); 232 );
226 } 233 }
234
235 void asc_node_update_transform(AscSceneNode *node) {
236 CxTreeIterator iter = asc_scene_node_iterator(node, false);
237 cx_foreach(AscSceneNode*, n, iter) {
238 n->need_transform_update = true;
239 }
240 }

mercurial