{
}
+Box::Box(const AABox &aabox, const Mat4 &xform)
+ : xform(xform)
+{
+ min = aabox.min;
+ max = aabox.max;
+}
+
Box::Box(const Vec3 &min, const Vec3 &max)
: AABox(min, max)
{
}
+Box::Box(const Vec3 &min, const Vec3 &max, const Mat4 &xform)
+ : AABox(min, max), xform(xform)
+{
+}
+
// XXX all this shit is completely untested
Box::Box(const Vec3 &pos, const Vec3 &vi, const Vec3 &vj, const Vec3 &vk)
{
return true;
}
+bool calc_bounding_box(Box *box, const GeomObject *obj)
+{
+ switch(obj->type) {
+ case GOBJ_BOX:
+ *box = *(Box*)obj;
+ break;
+
+ case GOBJ_AABOX:
+ box->min = BOX(obj)->min;
+ box->max = BOX(obj)->max;
+ box->xform = Mat4::identity;
+ break;
+
+ case GOBJ_SPHERE:
+ {
+ float r = SPHERE(obj)->radius;
+ box->min = SPHERE(obj)->center - Vec3(r, r, r);
+ box->max = SPHERE(obj)->center + Vec3(r, r, r);
+ box->xform = Mat4::identity;
+ }
+ break;
+
+ case GOBJ_PLANE:
+ default:
+ return false;
+ }
+ return true;
+}
+
bool intersect_sphere_sphere(Disc *result, const Sphere &a, const Sphere &b)
{
Vec3 dir = b.center - a.center;
Mat4 xform;
Box();
+ Box(const AABox &aabox, const Mat4 &xform);
Box(const Vec3 &min, const Vec3 &max);
+ Box(const Vec3 &min, const Vec3 &max, const Mat4 &xform);
Box(const Vec3 &pos, const Vec3 &vi, const Vec3 &vj, const Vec3 &vk);
Box(const Vec3 *varr, int vcount);
//! calculate the bounding axis-aligned box of multiple points, optionally transformed by `xform`
bool calc_bounding_aabox(AABox *box, const Vec3 *v, int num, const Mat4 &xform = Mat4::identity);
+//! calculate the bounding box of any object
+bool calc_bounding_box(Box *box, const GeomObject *obj);
+
//! calculate the intersection plane of two spheres. false if there is no plane or infinite planes.
bool intersect_sphere_sphere(Plane *result, const Sphere &a, const Sphere &b);
//! calculate the intersection line of two planes. returns false if planes are exactly parallel.
scene = 0;
parent = 0;
name = 0;
- bvol_valid = false;
+ local_bvol_valid = false;
}
SceneNode::SceneNode(Object *obj)
scene = 0;
parent = 0;
name = 0;
- bvol_valid = false;
+ local_bvol_valid = false;
add_object(obj);
}
children.push_back(node);
node->parent = this;
node->scene = scene;
-
- bvol_valid = false;
}
bool SceneNode::remove_child(SceneNode *node)
node->parent = 0;
node->scene = 0;
children.erase(it);
-
- bvol_valid = false;
return true;
}
return false;
this->obj.push_back(obj);
obj->node = this;
- bvol_valid = false;
+ local_bvol_valid = false;
}
bool SceneNode::remove_object(Object *o)
}
obj.erase(it);
- bvol_valid = false;
+ local_bvol_valid = false;
return true;
}
return false;
}
-const Box &SceneNode::calc_bounds()
+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; i<nobj; i++) {
+ AABox tmp = obj[i]->get_aabox();
+ calc_bounding_aabox(&local_bvol, &local_bvol, &tmp);
+ }
+
+ local_bvol_valid = true;
+ return local_bvol;
+}
+
+const AABox &SceneNode::get_local_bounds() const
{
- // TODO
+ 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;
}
-const Box &SceneNode::get_bounds() const
+AABox SceneNode::get_bounds() const
{
- if(!bvol_valid) {
- return ((SceneNode*)this)->calc_bounds();
+ 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; i<nchild; i++) {
+ AABox tmp = children[i]->get_bounds();
+ calc_bounding_aabox(&sub_aabb, &sub_aabb, &tmp);
}
- return bvol;
+
+ AABox aabb;
+ calc_bounding_aabox(&aabb, &local_bvol, &sub_aabb);
+ return aabb;
}
Mat4 xform;
Mat4 inv_xform;
- mutable bool bvol_valid;
- mutable Box bvol;
+ mutable bool local_bvol_valid;
+ mutable AABox local_bvol;
public:
Scene *scene; // scene to which this node belongs
bool intersect(const Ray &ray, HitPoint *hit) const;
- const Box &calc_bounds();
- const Box &get_bounds() const;
+ // cached local bounding box (all objects in this node in model space)
+ const AABox &calc_local_bounds();
+ const AABox &get_local_bounds() const;
+
+ // world bounding box of the node
+ AABox get_node_bounds() const;
+ // world bounding box of the node and it's subtree
+ AABox get_bounds() const;
};
#endif // SNODE_H_