#include "munga.h" #pragma hdrstop #include "bndgbox.h" #include "origin.h" #include "line.h" //############################################################################# //############################## BoundingBox ############################ //############################################################################# //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // BoundingBox::BoundingBox(const ExtentBox &extents): ExtentBox(extents) { Check_Pointer(this); Check(&extents); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // BoundingBox::BoundingBox() { Check_Pointer(this); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void BoundingBox::PlaceBoundingBox(const Origin& origin) { Check(this); Check(&origin); Dump(origin); minX += origin.linearPosition.x; maxX += origin.linearPosition.x; minY += origin.linearPosition.y; maxY += origin.linearPosition.y; minZ += origin.linearPosition.z; maxZ += origin.linearPosition.z; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // BoundingBox::~BoundingBox() { Check_Pointer(this); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical BoundingBox::Intersects(const ExtentBox &extents) { Check(this); Check(&extents); if (ExtentBox::Intersects(extents)) { ExtentBox slice; slice.Intersect(*this, extents); return IntersectsBounded(slice); } else { return False; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical BoundingBox::Intersects( const ExtentBox &extents, ExtentBox *slice ) { Check(this); Check(&extents); Check_Pointer(slice); if (ExtentBox::Intersects(extents)) { slice->Intersect(*this, extents); return IntersectsBounded(*slice); } else { return False; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical BoundingBox::Contains(const Point3D &point) { Check(this); Check(&point); if (ExtentBox::Contains(point)) { return ContainsBounded(point); } else { return False; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Scalar BoundingBox::FindDistanceBelow(const Point3D &point) { Check(this); Check(&point); if ( minX <= point.x && maxX >= point.x && minY <= point.y && minZ <= point.z && maxZ >= point.z ) { return FindDistanceBelowBounded(point); } else { return -1.0f; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical BoundingBox::HitBy(Line *line) { Check(this); Check(line); Scalar enter, leave, perpendicular, drift, distance; // //-------------------- // Set up for the test //-------------------- // Logical entered = False; Logical left = False; for (int i=0; i<6; ++i) { // //-------------------------------------------------------------------- // Figure out what axis we are dealing with, then based upon the // direction of the face, find out the distance from the origin to the // place against the normal, and find out how fast the perpendicular // distance changes with a unit movement along the line //-------------------------------------------------------------------- // int face = i; int axis = face >> 1; if (face&1) { perpendicular = line->origin[axis] - (*this)[face]; drift = line->direction[axis]; } else { perpendicular = (*this)[face] - line->origin[axis]; drift = -line->direction[axis]; } // //------------------------------------------------------------------- // If the line is parallel to the face, figure out whether or not the // line origin lies within the face's half-space //------------------------------------------------------------------- // if (Small_Enough(drift)) { if (perpendicular > 0.0f) { return False; } else { continue; } } // //-------------------------------------------------------------------- // If the drift is towards the plane's halfspace, this plane is one of // the one through which the line could enter the node //-------------------------------------------------------------------- // distance = -perpendicular / drift; if (drift < 0.0f) { if (!entered) { entered = True; enter = distance; } else if (distance > enter) { enter = distance; } if (enter > line->length) { return False; } } // //-------------------------------------------------------------------- // If the drift is towards the plane's halfspace, this plane is one of // the one through which the line could enter the node //-------------------------------------------------------------------- // else { if (!left) { left = True; leave = distance; } else if (distance < leave) { leave = distance; } if (leave < 0.0f) { return False; } } } // //----------------------------------------------------------------------- // If we exit the loop, then make sure that we actually hit the interior, // and let the box figure out if the what happens inside it //----------------------------------------------------------------------- // if (enter <= leave) { return HitByBounded(line, enter, leave); } return False; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical #if DEBUG_LEVEL>0 BoundingBox::IntersectsBounded(const ExtentBox &extents) #else BoundingBox::IntersectsBounded(const ExtentBox &) #endif { Check(this); Check(&extents); Verify(minX <= extents.minX); Verify(maxX >= extents.maxX); Verify(minY <= extents.minY); Verify(maxY >= extents.maxY); Verify(minZ <= extents.minZ); Verify(maxZ >= extents.maxZ); return True; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical #if DEBUG_LEVEL>0 BoundingBox::ContainsBounded(const Point3D &point) #else BoundingBox::ContainsBounded(const Point3D &) #endif { Check(this); Check(&point); Verify(minX <= point.x); Verify(maxX >= point.x); Verify(minY <= point.y); Verify(maxY >= point.y); Verify(minZ <= point.z); Verify(maxZ >= point.z); return True; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Scalar BoundingBox::FindDistanceBelowBounded(const Point3D &point) { Check(this); Check(&point); Verify(minX <= point.x); Verify(maxX >= point.x); Verify(minY <= point.y); Verify(minZ <= point.z); Verify(maxZ >= point.z); Scalar result = point.y - maxY; return Max(result, 0.0f); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical BoundingBox::HitByBounded( Line *line, Scalar enters, #if DEBUG_LEVEL>0 Scalar leaves #else Scalar #endif ) { Check(this); Check(line); Verify(enters <= leaves); Verify(leaves >= 0.0f); line->length = Max(enters, 0.0f); return True; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical BoundingBox::TestInstance() const { return True; } //############################################################################# //######################### BoundingBoxCollision ######################## //############################################################################# //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical BoundingBoxCollision::TestInstance() const { return True; } //############################################################################# //####################### BoundingBoxCollisionList ###################### //############################################################################# //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // BoundingBoxCollisionList::BoundingBoxCollisionList(int max_length) { listStart = new BoundingBoxCollision[max_length]; Register_Pointer(listStart); maxCollisions = max_length; Reset(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void BoundingBoxCollisionList::AddCollisionToList( BoundingBox *tree_volume, const ExtentBox &slice ) { Check(tree_volume); Check(&slice); Check(this); Check_Pointer(nextCollision); Verify(collisionsLeft); nextCollision->treeVolume = tree_volume; nextCollision->collisionSlice = slice; ++nextCollision; --collisionsLeft; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical BoundingBoxCollisionList::TestInstance() const { return True; } //############################################################################# //########################### TaggedBoundingBox ######################### //############################################################################# //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // TaggedBoundingBox::TaggedBoundingBox(void *tag) { tagPointer = tag; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // TaggedBoundingBox::TaggedBoundingBox( const ExtentBox &extents, void *tag ): BoundingBox(extents) { tagPointer = tag; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // TaggedBoundingBox::~TaggedBoundingBox() { } #if defined(TEST_CLASS) #include "bndgbox.tcp" #endif