The old version had problems with coplanar surfaces and sometimes failed
to produce intersections when it should have.
ShapeArray shapes;
unsigned max_isect;
ShapeArray shapes;
unsigned max_isect;
CompositeShape() { }
CompositeShape(const Shape<T, D> &, const Shape<T, D> &);
CompositeShape() { }
CompositeShape(const Shape<T, D> &, const Shape<T, D> &);
inline void CompositeShape<T, D, O>::init()
{
max_isect = 0;
inline void CompositeShape<T, D, O>::init()
{
max_isect = 0;
for(typename ShapeArray::const_iterator i=shapes.begin(); i!=shapes.end(); ++i)
for(typename ShapeArray::const_iterator i=shapes.begin(); i!=shapes.end(); ++i)
- {
- unsigned mi = (*i)->get_max_ray_intersections();
- max_isect += mi;
- min_scratch = std::max(min_scratch, mi);
- }
+ max_isect += (*i)->get_max_ray_intersections();
}
template<typename T, unsigned D, typename O>
inline CompositeShape<T, D, O>::CompositeShape(const CompositeShape<T, D, O> &other):
shapes(other.shapes),
}
template<typename T, unsigned D, typename O>
inline CompositeShape<T, D, O>::CompositeShape(const CompositeShape<T, D, O> &other):
shapes(other.shapes),
- max_isect(other.max_isect),
- min_scratch(other.min_scratch)
+ max_isect(other.max_isect)
{
for(typename ShapeArray::iterator i=shapes.begin(); i!=shapes.end(); ++i)
*i = (*i)->clone();
{
for(typename ShapeArray::iterator i=shapes.begin(); i!=shapes.end(); ++i)
*i = (*i)->clone();
*i = (*i)->clone();
max_isect = other.max_isect;
*i = (*i)->clone();
max_isect = other.max_isect;
- min_scratch = other.min_scratch;
}
template<typename T, unsigned D, typename O>
}
template<typename T, unsigned D, typename O>
template<typename T, unsigned D, typename O>
inline bool CompositeShape<T, D, O>::contains(const LinAl::Vector<T, D> &point) const
{
template<typename T, unsigned D, typename O>
inline bool CompositeShape<T, D, O>::contains(const LinAl::Vector<T, D> &point) const
{
- bool inside = Ops::init_inside();
for(typename ShapeArray::const_iterator i=shapes.begin(); i!=shapes.end(); ++i)
{
for(typename ShapeArray::const_iterator i=shapes.begin(); i!=shapes.end(); ++i)
{
- inside = Ops::combine_inside(inside, (*i)->contains(point));
- if(Ops::is_inside_decided(inside))
- break;
+ inside = (*i)->contains(point);
+ if(Ops::shortcircuit(inside))
+ return inside;
{
SurfacePoint<T, D> *buffer = points;
unsigned buf_size = size;
{
SurfacePoint<T, D> *buffer = points;
unsigned buf_size = size;
+ if(!points && !Ops::shortcircuit(true))
- buffer = new SurfacePoint<T, D>[min_scratch];
- buf_size = min_scratch;
+ buffer = new SurfacePoint<T, D>[max_isect];
+ buf_size = max_isect;
- for(typename ShapeArray::const_iterator i=shapes.begin(); (n<size && i!=shapes.end()); ++i)
+ for(typename ShapeArray::const_iterator i=shapes.begin(); (n<buf_size && i!=shapes.end()); ++i)
- unsigned base = (points ? n : 0);
unsigned count = (*i)->get_intersections(ray, buffer+base, buf_size-base);
unsigned count = (*i)->get_intersections(ray, buffer+base, buf_size-base);
- for(unsigned j=0; (n<size && j<count); ++j)
+ bool start_inside = (*i)->contains(ray.get_start());
+
+ if(!count && !start_inside)
- SurfacePoint<T, D> &pt = buffer[base+j];
+ if(Ops::shortcircuit(false))
+ return 0;
+ continue;
+ }
- bool surface = Ops::init_surface();
- for(typename ShapeArray::const_iterator k=shapes.begin(); k!=shapes.end(); ++k)
- if(k!=i)
- surface = Ops::combine_surface(surface, (*k)->contains(pt.position));
+ start_nesting += start_inside;
- if(surface)
- {
- if(points && base+j!=n)
- points[n] = pt;
+ if(!base)
+ {
+ n = count;
+ continue;
+ }
+ sort_points(buffer, base+count);
+
+ int nesting = start_nesting;
+ unsigned k = 0;
+ for(unsigned j=0; j<base+count; ++j)
+ {
+ if(Ops::shortcircuit(nesting+buffer[j].entry<2))
+ {
+ if(j!=k)
+ buffer[k] = buffer[j];
+ ++k;
+
+ nesting += buffer[j].entry*2-1;
+
+ if(!k && Ops::shortcircuit(false))
+ return 0;
+
+ n = k;
- if(points)
- sort_points(points, n);
- else
delete[] buffer;
return n;
delete[] buffer;
return n;
struct IntersectionOps
{
static BoundingBox<T, D> combine_aabb(const BoundingBox<T, D> &a, const BoundingBox<T, D> &b) { return a&b; }
struct IntersectionOps
{
static BoundingBox<T, D> combine_aabb(const BoundingBox<T, D> &a, const BoundingBox<T, D> &b) { return a&b; }
- static bool init_inside() { return true; }
- static bool combine_inside(bool a, bool b) { return a && b; }
- static bool is_inside_decided(bool a) { return !a; }
- static bool init_surface() { return true; }
- static bool combine_surface(bool a, bool b) { return a && b; }
+ static bool shortcircuit(bool c) { return !c; }
struct UnionOps
{
static BoundingBox<T, D> combine_aabb(const BoundingBox<T, D> &a, const BoundingBox<T, D> &b) { return a|b; }
struct UnionOps
{
static BoundingBox<T, D> combine_aabb(const BoundingBox<T, D> &a, const BoundingBox<T, D> &b) { return a|b; }
- static bool init_inside() { return false; }
- static bool combine_inside(bool a, bool b) { return a || b; }
- static bool is_inside_decided(bool a) { return a; }
- static bool init_surface() { return true; }
- static bool combine_surface(bool a, bool b) { return a && !b; }
+ static bool shortcircuit(bool c) { return c; }