14 local_bvol_valid = false;
17 SceneNode::SceneNode(Object *obj)
23 local_bvol_valid = false;
27 SceneNode::~SceneNode()
32 void SceneNode::set_name(const char *s)
35 name = new char[strlen(s) + 1];
39 const char *SceneNode::get_name() const
44 void SceneNode::add_child(SceneNode *node)
49 if(node->parent == this) {
52 node->parent->remove_child(node);
55 children.push_back(node);
60 bool SceneNode::remove_child(SceneNode *node)
62 if(!node) return false;
64 auto it = std::find(children.begin(), children.end(), node);
65 if(it != children.end()) {
66 assert(node->parent == this);
75 int SceneNode::get_num_children() const
77 return (int)children.size();
80 SceneNode *SceneNode::get_child(int idx) const
85 SceneNode *SceneNode::get_parent() const
90 void SceneNode::add_object(Object *obj)
92 if(obj->node == this) return;
95 obj->node->remove_object(obj);
98 this->obj.push_back(obj);
101 local_bvol_valid = false;
104 bool SceneNode::remove_object(Object *o)
106 if(o->node != this) {
111 auto it = std::find(obj.begin(), obj.end(), o);
112 if(it == obj.end()) {
117 local_bvol_valid = false;
121 int SceneNode::get_num_objects() const
123 return (int)obj.size();
126 Object *SceneNode::get_object(int idx) const
131 void SceneNode::set_position(const Vec3 &pos)
136 void SceneNode::set_rotation(const Quat &rot)
141 void SceneNode::set_scaling(const Vec3 &scale)
147 const Vec3 &SceneNode::get_node_position() const
152 const Quat &SceneNode::get_node_rotation() const
157 const Vec3 &SceneNode::get_node_scaling() const
163 Vec3 SceneNode::get_position() const
165 return xform * Vec3(0, 0, 0);
168 Quat SceneNode::get_rotation() const
173 Vec3 SceneNode::get_scaling() const
175 return scale; // TODO
178 const Mat4 &SceneNode::get_matrix() const
183 const Mat4 &SceneNode::get_inv_matrix() const
189 void SceneNode::update_node(float dt)
191 xform = Mat4::identity;
192 xform.pre_translate(pos);
193 xform.pre_rotate(rot);
194 xform.pre_scale(scale);
197 xform = xform * parent->xform;
199 inv_xform = inverse(xform);
202 void SceneNode::update(float dt)
204 bool expanded = false;
207 if(parent_expanded) {
208 int flags = children.empty() ? ImGuiTreeNodeFlags_Leaf : 0;
209 expanded = ImGui::TreeNodeEx(name ? name : "<nameless node>", flags);
215 int num = children.size();
216 for(int i=0; i<num; i++) {
217 parent_expanded = expanded;
218 children[i]->update(dt);
221 if(debug_gui && expanded) {
226 void SceneNode::apply_xform()
230 // apply post-order to make sure we don't affect the children xform by our reset
232 int nchild = children.size();
233 for(int i=0; i<nchild; i++) {
234 children[i]->apply_xform();
237 int nobj = obj.size();
238 for(int i=0; i<nobj; i++) {
239 if(obj[i]->get_type() == OBJ_MESH) {
240 ObjMesh *om = (ObjMesh*)obj[i];
242 om->mesh->apply_xform(xform);
248 rot = Quat::identity;
249 scale = Vec3(1, 1, 1);
252 bool SceneNode::intersect(const Ray &ray, HitPoint *hit) const
254 Ray local_ray = inv_xform * ray;
257 nearest.dist = FLT_MAX;
258 for(size_t i=0; i<obj.size(); i++) {
259 if(obj[i]->intersect(local_ray, hit)) {
260 if(!hit) return true;
261 if(hit->dist < nearest.dist) {
263 nearest.data = (void*)this;
264 nearest.local_ray = local_ray;
269 for(size_t i=0; i<children.size(); i++) {
270 if(children[i]->intersect(ray, hit)) {
271 if(!hit) return true;
272 if(hit->dist < nearest.dist) {
278 if(nearest.dist < FLT_MAX) {
286 const AABox &SceneNode::calc_local_bounds()
288 local_bvol = AABox(Vec3(FLT_MAX, FLT_MAX, FLT_MAX), Vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX));
290 // calculate the axis-aligned bounding box of all objects in this node
291 int nobj = obj.size();
292 for(int i=0; i<nobj; i++) {
293 AABox tmp = obj[i]->get_aabox();
294 calc_bounding_aabox(&local_bvol, &local_bvol, &tmp);
297 local_bvol_valid = true;
301 const AABox &SceneNode::get_local_bounds() const
303 if(!local_bvol_valid) {
304 ((SceneNode*)this)->calc_local_bounds();
309 AABox SceneNode::get_node_bounds() const
311 get_local_bounds(); // validate local_bvol
313 // calculate the transformed local_bvol
314 Box node_bbox = Box(local_bvol, xform);
316 // then calculate the axis-aligned bounding box
318 calc_bounding_aabox(&aabox, &node_bbox);
322 AABox SceneNode::get_bounds() const
324 AABox sub_aabb = AABox(Vec3(FLT_MAX, FLT_MAX, FLT_MAX), Vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX));
326 // calculate the bounding box of all children
327 int nchild = children.size();
328 for(int i=0; i<nchild; i++) {
329 AABox tmp = children[i]->get_bounds();
330 calc_bounding_aabox(&sub_aabb, &sub_aabb, &tmp);
333 AABox aabb = get_node_bounds();
334 calc_bounding_aabox(&aabb, &aabb, &sub_aabb);