diff --git a/shapes/Extrude.cc b/shapes/Extrude.cc index 7924d2b..9fb697b 100644 --- a/shapes/Extrude.cc +++ b/shapes/Extrude.cc @@ -35,12 +35,43 @@ Shape::IntersectionList Extrude::intersect(refptr _this, const Ray & ray) { Ray ray_inv = m_inverse.transform_ray(ray); IntersectionList res; + + /*** optimization ***/ + if (ray_inv.getOrigin()[0] > m_aabb.max[0]) + { + if (ray_inv.getDirection() % Vector::X > 0) + return res; + } + else if (ray_inv.getOrigin()[0] < m_aabb.min[0]) + { + if (ray_inv.getDirection() % Vector::X < 0) + return res; + } + if (ray_inv.getOrigin()[1] > m_aabb.max[1]) + { + if (ray_inv.getDirection() % Vector::Y > 0) + return res; + } + else if (ray_inv.getOrigin()[1] < m_aabb.min[1]) + { + if (ray_inv.getDirection() % Vector::Y < 0) + return res; + } + if (ray_inv.getOrigin()[2] > m_aabb.max[2]) + { + if (ray_inv.getDirection() % Vector::Z > 0) + return res; + } + else if (ray_inv.getOrigin()[2] < m_aabb.min[2]) + { + if (ray_inv.getDirection() % Vector::Z < 0) + return res; + } + /*** end optimization ***/ + int n_polygons = m_polygons.size(); int n_offsets = m_offsets.size(); - if (n_polygons < 1 || n_offsets < 1) - return res; - double distance = 0.0; Vector scale(1.0, 1.0, 1.0); Vector shift(0.0, 0.0, 0.0); @@ -159,12 +190,75 @@ Shape::IntersectionList Extrude::intersect(refptr _this, const Ray & ray) void Extrude::addPolygon(refptr polygon) { m_polygons.push_back(polygon); + updateAABB(); } void Extrude::addOffset(double distance, const Vector & scale, const Vector & shift) { m_offsets.push_back(Offset(distance, scale, shift)); + updateAABB(); +} + +void Extrude::updateAABB() +{ + int n_polygons = m_polygons.size(); + int n_offsets = m_offsets.size(); + bool first = true; + double distance = 0.0; + Vector scale(1.0, 1.0, 1.0); + Vector shift(0.0, 0.0, 0.0); + for (int p = 0; p < n_polygons; p++) + { + refptr polygon = m_polygons[p]; + for (int o = 0; o < n_offsets; o++) + { + Offset & offset = m_offsets[o]; + for (int pt = 0, n_pts = polygon->size(); pt < n_pts; pt++) + { + Vector p1 = scale.mult(*(*polygon)[pt]) + shift; + Vector p2 = scale.mult(*(*polygon)[(pt+1) % n_pts]) + shift; + Vector p3 = scale.mult(offset.scale) + .mult(*(*polygon)[(pt+1) % n_pts]) + + shift + offset.shift; + Vector p4 = scale.mult(offset.scale).mult(*(*polygon)[pt]) + + shift + offset.shift; + p1[2] += distance; + p2[2] += distance; + p3[2] += distance + offset.distance; + p4[2] += distance + offset.distance; + if (first) + { + m_aabb.min = p1; + m_aabb.max = p1; + first = false; + } + expandAABB(p1); + expandAABB(p2); + expandAABB(p3); + expandAABB(p4); + } + distance += offset.distance; + scale = scale.mult(offset.scale); + shift += offset.shift; + } + } +} + +void Extrude::expandAABB(const Vector & v) +{ + if (v[0] < m_aabb.min[0]) + m_aabb.min[0] = v[0]; + if (v[0] > m_aabb.max[0]) + m_aabb.max[0] = v[0]; + if (v[1] < m_aabb.min[1]) + m_aabb.min[1] = v[1]; + if (v[1] > m_aabb.max[1]) + m_aabb.max[1] = v[1]; + if (v[2] < m_aabb.min[2]) + m_aabb.min[2] = v[2]; + if (v[2] > m_aabb.max[2]) + m_aabb.max[2] = v[2]; } refptr Extrude::clone() diff --git a/shapes/Extrude.h b/shapes/Extrude.h index ac9c9a5..93e63bf 100644 --- a/shapes/Extrude.h +++ b/shapes/Extrude.h @@ -5,6 +5,8 @@ #include #include "util/Polygon.h" +#include "util/AABB.h" + #include "Shape.h" class Extrude : public Shape @@ -31,6 +33,10 @@ class Extrude : public Shape protected: std::vector< refptr > m_polygons; std::vector m_offsets; + AABB m_aabb; + + void updateAABB(); + void expandAABB(const Vector & v); }; #endif diff --git a/util/AABB.h b/util/AABB.h new file mode 100644 index 0000000..b953dda --- /dev/null +++ b/util/AABB.h @@ -0,0 +1,21 @@ + +#ifndef AABB_H +#define AABB_H + +class AABB +{ + public: + Vector min; + Vector max; + + AABB() + { + } + + AABB(const Vector & min, const Vector & max) + : min(min), max(max) + { + } +}; + +#endif /* AABB_H */