X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=laserbrain_demo;a=blobdiff_plain;f=src%2Fsnode.cc;h=eee5fcec02b26e266306b5eeaf36f23e1aa89f74;hp=fac6c650b9c7e69b29d410bff6e7e29a9a5b38e1;hb=ad052fc67fe4e76d2f4a01b2381a738da1708cdb;hpb=b7c92831285013b2a0783bccaf3d900545ebb5ba diff --git a/src/snode.cc b/src/snode.cc index fac6c65..eee5fce 100644 --- a/src/snode.cc +++ b/src/snode.cc @@ -2,19 +2,25 @@ #include #include #include "snode.h" +#include "objmesh.h" +#include "dbg_gui.h" SceneNode::SceneNode() : scale(1, 1, 1) { + scene = 0; parent = 0; name = 0; + local_bvol_valid = false; } SceneNode::SceneNode(Object *obj) : scale(1, 1, 1) { + scene = 0; parent = 0; name = 0; + local_bvol_valid = false; add_object(obj); } @@ -37,6 +43,8 @@ const char *SceneNode::get_name() const void SceneNode::add_child(SceneNode *node) { + if(!node) return; + if(node->parent) { if(node->parent == this) { return; @@ -46,14 +54,19 @@ void SceneNode::add_child(SceneNode *node) children.push_back(node); node->parent = this; + node->scene = scene; } bool SceneNode::remove_child(SceneNode *node) { + if(!node) return false; + auto it = std::find(children.begin(), children.end(), node); if(it != children.end()) { assert(node->parent == this); node->parent = 0; + node->scene = 0; + children.erase(it); return true; } return false; @@ -84,6 +97,8 @@ void SceneNode::add_object(Object *obj) this->obj.push_back(obj); obj->node = this; + + local_bvol_valid = false; } bool SceneNode::remove_object(Object *o) @@ -98,6 +113,8 @@ bool SceneNode::remove_object(Object *o) return false; } obj.erase(it); + + local_bvol_valid = false; return true; } @@ -177,20 +194,60 @@ void SceneNode::update_node(float dt) xform.pre_scale(scale); if(parent) { - xform = parent->xform * xform; + xform = xform * parent->xform; } inv_xform = inverse(xform); } void SceneNode::update(float dt) { + bool expanded = false; + + if(debug_gui) { + if(parent_expanded) { + int flags = children.empty() ? ImGuiTreeNodeFlags_Leaf : 0; + expanded = ImGui::TreeNodeEx(name ? name : "", flags); + } + } + update_node(dt); - for(size_t i=0; iupdate(dt); } + + if(debug_gui && expanded) { + ImGui::TreePop(); + } } +void SceneNode::apply_xform() +{ + update_node(); + + // apply post-order to make sure we don't affect the children xform by our reset + + int nchild = children.size(); + for(int i=0; iapply_xform(); + } + + int nobj = obj.size(); + for(int i=0; iget_type() == OBJ_MESH) { + ObjMesh *om = (ObjMesh*)obj[i]; + if(om->mesh) { + om->mesh->apply_xform(xform); + } + } + } + + pos = Vec3(0, 0, 0); + rot = Quat::identity; + scale = Vec3(1, 1, 1); +} bool SceneNode::intersect(const Ray &ray, HitPoint *hit) const { @@ -225,3 +282,55 @@ bool SceneNode::intersect(const Ray &ray, HitPoint *hit) const } return false; } + +const AABox &SceneNode::calc_local_bounds() +{ + local_bvol = AABox(Vec3(FLT_MAX, FLT_MAX, FLT_MAX), Vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX)); + + // calculate the axis-aligned bounding box of all objects in this node + int nobj = obj.size(); + for(int i=0; iget_aabox(); + calc_bounding_aabox(&local_bvol, &local_bvol, &tmp); + } + + local_bvol_valid = true; + return local_bvol; +} + +const AABox &SceneNode::get_local_bounds() const +{ + if(!local_bvol_valid) { + ((SceneNode*)this)->calc_local_bounds(); + } + return local_bvol; +} + +AABox SceneNode::get_node_bounds() const +{ + get_local_bounds(); // validate local_bvol + + // calculate the transformed local_bvol + Box node_bbox = Box(local_bvol, xform); + + // then calculate the axis-aligned bounding box + AABox aabox; + calc_bounding_aabox(&aabox, &node_bbox); + return aabox; +} + +AABox SceneNode::get_bounds() const +{ + AABox sub_aabb = AABox(Vec3(FLT_MAX, FLT_MAX, FLT_MAX), Vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX)); + + // calculate the bounding box of all children + int nchild = children.size(); + for(int i=0; iget_bounds(); + calc_bounding_aabox(&sub_aabb, &sub_aabb, &tmp); + } + + AABox aabb; + calc_bounding_aabox(&aabb, &local_bvol, &sub_aabb); + return aabb; +}