+Box::Box()
+{
+ type = GOBJ_BOX;
+}
+
+Box::Box(const AABox &aabox, const Mat4 &xform)
+ : xform(xform)
+{
+ type = GOBJ_BOX;
+ min = aabox.min;
+ max = aabox.max;
+}
+
+void Box::invalidate()
+{
+ AABox::invalidate();
+ xform = Mat4::identity;
+}
+
+Box::Box(const Vec3 &min, const Vec3 &max)
+ : AABox(min, max)
+{
+ type = GOBJ_BOX;
+}
+
+Box::Box(const Vec3 &min, const Vec3 &max, const Mat4 &xform)
+ : AABox(min, max), xform(xform)
+{
+ type = GOBJ_BOX;
+}
+
+// XXX all this shit is completely untested
+Box::Box(const Vec3 &pos, const Vec3 &vi, const Vec3 &vj, const Vec3 &vk)
+{
+ type = GOBJ_BOX;
+ float ilen = length(vi);
+ float jlen = length(vj);
+ float klen = length(vk);
+
+ min = Vec3(-ilen, -jlen, -klen);
+ max = Vec3(ilen, jlen, klen);
+
+ float si = ilen == 0.0 ? 1.0 : 1.0 / ilen;
+ float sj = jlen == 0.0 ? 1.0 : 1.0 / jlen;
+ float sk = klen == 0.0 ? 1.0 : 1.0 / klen;
+
+ xform = Mat4(vi * si, vj * sj, vk * sk);
+ xform.translate(pos);
+}
+
+Box::Box(const Vec3 *varr, int vcount)
+{
+ type = GOBJ_BOX;
+ calc_bounding_aabox(this, varr, vcount);
+}
+
+Vec3 Box::get_corner(int idx) const
+{
+ return xform * AABox::get_corner(idx);
+}
+
+bool Box::intersect(const Ray &ray, HitPoint *hit) const
+{
+ Mat4 inv_xform = inverse(xform);
+ Mat4 dir_inv_xform = inv_xform.upper3x3();
+ Mat4 dir_xform = transpose(dir_inv_xform);
+ Ray local_ray = Ray(inv_xform * ray.origin, dir_inv_xform * ray.dir);
+
+ bool res = AABox::intersect(local_ray, hit);
+ if(!res || !hit) return res;
+
+ hit->pos = xform * hit->pos;
+ hit->normal = dir_xform * hit->normal;
+ hit->local_ray = local_ray;
+ hit->ray = ray;
+ return true;
+}
+
+bool Box::contains(const Vec3 &pt) const
+{
+ // XXX is it faster to extract 6 planes and do dot products? sounds marginal
+ return AABox::contains(inverse(xform) * pt);
+}
+
+float Box::distance_sq(const Vec3 &v) const
+{
+ return 0.0f; // TODO
+}
+
+float Box::signed_distance_sq(const Vec3 &v) const
+{
+ return 0.0f; // TODO