121 assert(node->update_func != NULL); |
121 assert(node->update_func != NULL); |
122 node->need_graphics_update = false; |
122 node->need_graphics_update = false; |
123 node->update_func(node); |
123 node->update_func(node); |
124 } |
124 } |
125 if (node->need_transform_update) { |
125 if (node->need_transform_update) { |
126 assert(node->transform_update_func != NULL); |
|
127 node->need_transform_update = false; |
126 node->need_transform_update = false; |
128 asc_transform_identity(node->local_transform); |
127 asc_transform_from_parts( |
129 asc_transform_copy(node->world_transform, node->parent->world_transform); |
128 node->transform, |
130 node->transform_update_func(node); |
129 node->position, |
131 asc_mat4f_mulst(node->final_transform, node->local_transform, node->world_transform); |
130 node->scale, |
|
131 node->rotation |
|
132 ); |
|
133 asc_mat4f_mulst( |
|
134 node->world_transform, |
|
135 node->transform, |
|
136 node->parent->world_transform |
|
137 ); |
132 } |
138 } |
133 |
139 |
134 // add to render group |
140 // add to render group |
135 if (node->draw_func != NULL) { |
141 if (node->draw_func != NULL) { |
136 struct asc_render_group_entry entry = { |
142 struct asc_render_group_entry entry = { |
172 glClear(GL_DEPTH_BUFFER_BIT); |
178 glClear(GL_DEPTH_BUFFER_BIT); |
173 |
179 |
174 // Sprites |
180 // Sprites |
175 // ------- |
181 // ------- |
176 // TODO: see if we can really always ignore the view matrix |
182 // TODO: see if we can really always ignore the view matrix |
177 shader = &asc_context.active_window->glctx.shader.sprite; |
183 shader = &asc_context.active_window->glctx.shader.sprite.base; |
178 glUseProgram(shader->id); |
184 glUseProgram(shader->id); |
179 glUniformMatrix4fv(shader->projection, 1, |
185 glUniformMatrix4fv(shader->projection, 1, |
180 GL_FALSE, camera->projection); |
186 GL_FALSE, camera->projection); |
181 |
187 |
182 // render opaque sprites from front to back |
188 // render opaque sprites from front to back |
190 } |
196 } |
191 |
197 |
192 AscSceneNode *asc_scene_node_empty(void) { |
198 AscSceneNode *asc_scene_node_empty(void) { |
193 AscSceneNode *node = calloc(1, sizeof(AscSceneNode)); |
199 AscSceneNode *node = calloc(1, sizeof(AscSceneNode)); |
194 node->free_func = (asc_scene_free_func) free; |
200 node->free_func = (asc_scene_free_func) free; |
195 asc_transform_identity(node->local_transform); |
201 asc_transform_identity(node->transform); |
196 asc_transform_identity(node->world_transform); |
202 asc_transform_identity(node->world_transform); |
197 asc_transform_identity(node->final_transform); |
|
198 return node; |
203 return node; |
199 } |
204 } |
200 |
205 |
201 void asc_scene_node_free(AscSceneNode *node) { |
206 void asc_scene_node_free(AscSceneNode *node) { |
202 if (node == NULL) return; |
207 if (node == NULL) return; |
258 offsetof(AscBehaviorNode, prev), |
263 offsetof(AscBehaviorNode, prev), |
259 offsetof(AscBehaviorNode, next) |
264 offsetof(AscBehaviorNode, next) |
260 ); |
265 ); |
261 } |
266 } |
262 |
267 |
263 void asc_node_update_transform(AscSceneNode *node) { |
268 void asc_update_transform(AscSceneNode *node) { |
|
269 if (node->need_transform_update) return; |
|
270 |
264 CxTreeIterator iter = asc_scene_node_iterator(node, false); |
271 CxTreeIterator iter = asc_scene_node_iterator(node, false); |
265 cx_foreach(AscSceneNode*, n, iter) { |
272 cx_foreach(AscSceneNode*, n, iter) { |
|
273 // TODO: break/continue when subtree is already marked for update |
266 n->need_transform_update = true; |
274 n->need_transform_update = true; |
267 } |
275 } |
268 } |
276 } |