15 local_bvol_valid = false;
18 SceneNode::SceneNode(Object *obj)
25 local_bvol_valid = false;
29 SceneNode::~SceneNode()
34 void SceneNode::set_name(const char *s)
37 name = new char[strlen(s) + 1];
41 const char *SceneNode::get_name() const
46 void SceneNode::add_child(SceneNode *node)
51 if(node->parent == this) {
54 node->parent->remove_child(node);
57 children.push_back(node);
62 bool SceneNode::remove_child(SceneNode *node)
64 if(!node) return false;
66 auto it = std::find(children.begin(), children.end(), node);
67 if(it != children.end()) {
68 assert(node->parent == this);
77 int SceneNode::get_num_children() const
79 return (int)children.size();
82 SceneNode *SceneNode::get_child(int idx) const
87 SceneNode *SceneNode::get_parent() const
92 void SceneNode::add_object(Object *obj)
94 if(obj->node == this) return;
97 obj->node->remove_object(obj);
100 this->obj.push_back(obj);
103 local_bvol_valid = false;
106 bool SceneNode::remove_object(Object *o)
108 if(o->node != this) {
113 auto it = std::find(obj.begin(), obj.end(), o);
114 if(it == obj.end()) {
119 local_bvol_valid = false;
123 int SceneNode::get_num_objects() const
125 return (int)obj.size();
128 Object *SceneNode::get_object(int idx) const
133 void SceneNode::set_position(const Vec3 &pos)
138 void SceneNode::set_rotation(const Quat &rot)
143 void SceneNode::set_scaling(const Vec3 &scale)
149 const Vec3 &SceneNode::get_node_position() const
154 const Quat &SceneNode::get_node_rotation() const
159 const Vec3 &SceneNode::get_node_scaling() const
165 Vec3 SceneNode::get_position() const
167 return xform * Vec3(0, 0, 0);
170 Quat SceneNode::get_rotation() const
175 Vec3 SceneNode::get_scaling() const
177 return scale; // TODO
180 const Mat4 &SceneNode::get_matrix() const
185 const Mat4 &SceneNode::get_inv_matrix() const
191 void SceneNode::update_node(float dt)
193 xform = Mat4::identity;
194 xform.pre_translate(pos);
195 xform.pre_rotate(rot);
196 xform.pre_scale(scale);
199 xform = xform * parent->xform;
201 inv_xform = inverse(xform);
204 void SceneNode::update(float dt)
206 bool expanded = false;
209 if(parent_expanded) {
211 ImGui::AlignTextToFramePadding();
213 int flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick;
214 if(children.empty()) flags |= ImGuiTreeNodeFlags_Leaf;
215 if(dbg_sel_node == this) flags |= ImGuiTreeNodeFlags_Selected;
216 expanded = ImGui::TreeNodeEx(name ? name : "<nameless node>", flags);
217 if(ImGui::IsItemClicked()) {
222 ImGui::Checkbox("##vis", &visible);
230 int num = children.size();
231 for(int i=0; i<num; i++) {
232 parent_expanded = expanded;
233 children[i]->update(dt);
236 if(debug_gui && expanded) {
241 void SceneNode::apply_xform()
245 // apply post-order to make sure we don't affect the children xform by our reset
247 int nchild = children.size();
248 for(int i=0; i<nchild; i++) {
249 children[i]->apply_xform();
252 int nobj = obj.size();
253 for(int i=0; i<nobj; i++) {
254 if(obj[i]->get_type() == OBJ_MESH) {
255 ObjMesh *om = (ObjMesh*)obj[i];
257 om->mesh->apply_xform(xform);
263 rot = Quat::identity;
264 scale = Vec3(1, 1, 1);
267 bool SceneNode::intersect(const Ray &ray, HitPoint *hit) const
269 Ray local_ray = inv_xform * ray;
272 nearest.dist = FLT_MAX;
273 for(size_t i=0; i<obj.size(); i++) {
274 if(obj[i]->intersect(local_ray, hit)) {
275 if(!hit) return true;
276 if(hit->dist < nearest.dist) {
278 nearest.data = (void*)this;
279 nearest.local_ray = local_ray;
284 for(size_t i=0; i<children.size(); i++) {
285 if(children[i]->intersect(ray, hit)) {
286 if(!hit) return true;
287 if(hit->dist < nearest.dist) {
293 if(nearest.dist < FLT_MAX) {
301 const AABox &SceneNode::calc_local_bounds()
303 local_bvol = AABox(Vec3(FLT_MAX, FLT_MAX, FLT_MAX), Vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX));
305 // calculate the axis-aligned bounding box of all objects in this node
306 int nobj = obj.size();
307 for(int i=0; i<nobj; i++) {
308 AABox tmp = obj[i]->get_aabox();
309 calc_bounding_aabox(&local_bvol, &local_bvol, &tmp);
312 local_bvol_valid = true;
316 const AABox &SceneNode::get_local_bounds() const
318 if(!local_bvol_valid) {
319 ((SceneNode*)this)->calc_local_bounds();
324 AABox SceneNode::get_node_bounds() const
326 get_local_bounds(); // validate local_bvol
328 // calculate the transformed local_bvol
329 Box node_bbox = Box(local_bvol, xform);
331 // then calculate the axis-aligned bounding box
333 calc_bounding_aabox(&aabox, &node_bbox);
337 AABox SceneNode::get_bounds() const
339 AABox sub_aabb = AABox(Vec3(FLT_MAX, FLT_MAX, FLT_MAX), Vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX));
341 // calculate the bounding box of all children
342 int nchild = children.size();
343 for(int i=0; i<nchild; i++) {
344 AABox tmp = children[i]->get_bounds();
345 calc_bounding_aabox(&sub_aabb, &sub_aabb, &tmp);
348 AABox aabb = get_node_bounds();
349 calc_bounding_aabox(&aabb, &aabb, &sub_aabb);