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 } |