//===========================================================================// // File: extntbox.cc // // Project: MUNGA Brick: Math Library // // Contents: Implementation details of bounding box class // //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 01/07/95 JMA Initial coding. // //---------------------------------------------------------------------------// // Copyright (C) 1994,1995 Virtual World Entertainment, Inc. // // All Rights reserved worldwide // // This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // //===========================================================================// #include "StuffHeaders.hpp" //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ExtentBox::ExtentBox( const Vector3D &min, const Vector3D &max ) { Check_Pointer(this); Check_Object(&min); Check_Object(&max); if (min.x <= max.x) { minX = min.x; maxX = max.x; } else { minX = max.x; maxX = min.x; } if (min.y <= max.y) { minY = min.y; maxY = max.y; } else { minY = max.y; maxY = min.y; } if (min.z <= max.z) { minZ = min.z; maxZ = max.z; } else { minZ = max.z; maxZ = min.z; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ExtentBox::ExtentBox(const ExtentBox &box) { Check_Pointer(this); Check_Object(&box); minX = box.minX; maxX = box.maxX; minY = box.minY; maxY = box.maxY; minZ = box.minZ; maxZ = box.maxZ; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ExtentBox::ExtentBox(const OBB &obb) { Check_Pointer(this); Check_Object(&obb); Verify(obb.axisExtents.x >= 0.0f); Verify(obb.axisExtents.y >= 0.0f); Verify(obb.axisExtents.z >= 0.0f); Stuff::Scalar len = Fabs(obb.localToParent(0,0))*obb.axisExtents.x + Fabs(obb.localToParent(1,0))*obb.axisExtents.y + Fabs(obb.localToParent(2,0))*obb.axisExtents.z; minX = obb.localToParent(3,0) - len; maxX = obb.localToParent(3,0) + len; len = Fabs(obb.localToParent(0,1))*obb.axisExtents.x + Fabs(obb.localToParent(1,1))*obb.axisExtents.y + Fabs(obb.localToParent(2,1))*obb.axisExtents.z; minY = obb.localToParent(3,1) - len; maxY = obb.localToParent(3,1) + len; len = Fabs(obb.localToParent(0,2))*obb.axisExtents.x + Fabs(obb.localToParent(1,2))*obb.axisExtents.y + Fabs(obb.localToParent(2,2))*obb.axisExtents.z; minZ = obb.localToParent(3,2) - len; maxZ = obb.localToParent(3,2) + len; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ExtentBox::ComputeBounds(ReadOnlyArrayOf &points) { Check_Object(&points); minX = maxX = points[0].x; minY = maxY = points[0].y; minZ = maxZ = points[0].z; for (int i=1; i maxX) maxX = points[i].x; if (points[i].y < minY) minY = points[i].y; else if (points[i].y > maxY) maxY = points[i].y; if (points[i].z < minZ) minZ = points[i].z; else if (points[i].z > maxZ) maxZ = points[i].z; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ExtentBox& ExtentBox::Intersect( const ExtentBox &box_1, const ExtentBox &box_2 ) { Check_Pointer(this); Check_Object(&box_1); Check_Object(&box_2); Verify(box_1.minX <= box_2.maxX); Verify(box_1.maxX >= box_2.minX); Verify(box_1.minY <= box_2.maxY); Verify(box_1.maxY >= box_2.minY); Verify(box_1.minZ <= box_2.maxZ); Verify(box_1.maxZ >= box_2.minZ); minX = Max(box_1.minX, box_2.minX); maxX = Min(box_1.maxX, box_2.maxX); minY = Max(box_1.minY, box_2.minY); maxY = Min(box_1.maxY, box_2.maxY); minZ = Max(box_1.minZ, box_2.minZ); maxZ = Min(box_1.maxZ, box_2.maxZ); return *this; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ExtentBox& ExtentBox::Union( const ExtentBox &box_1, const ExtentBox &box_2 ) { Check_Pointer(this); Check_Object(&box_1); Check_Object(&box_2); minX = Min(box_1.minX, box_2.minX); maxX = Max(box_1.maxX, box_2.maxX); minY = Min(box_1.minY, box_2.minY); maxY = Max(box_1.maxY, box_2.maxY); minZ = Min(box_1.minZ, box_2.minZ); maxZ = Max(box_1.maxZ, box_2.maxZ); Check_Object(this); return *this; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ExtentBox& ExtentBox::Union( const ExtentBox &box, const Vector3D &point ) { Check_Pointer(this); Check_Object(&box); Check_Object(&point); minX = Min(box.minX, point.x); maxX = Max(box.maxX, point.x); minY = Min(box.minY, point.y); maxY = Max(box.maxY, point.y); minZ = Min(box.minZ, point.z); maxZ = Max(box.maxZ, point.z); return *this; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Vector3D* ExtentBox::Constrain(Vector3D *point) const { Check_Object(this); Check_Object(point); Clamp(point->x,minX,maxX); Clamp(point->y,minY,maxY); Clamp(point->z,minZ,maxZ); return point; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool ExtentBox::Contains(const Vector3D &point) const { Check_Object(this); Check_Object(&point); return minX <= point.x && maxX >= point.x && minY <= point.y && maxY >= point.y && minZ <= point.z && maxZ >= point.z; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool ExtentBox::Contains(const ExtentBox &box) const { Check_Object(this); Check_Object(&box); return minX <= box.minX && maxX >= box.maxX && minY <= box.minY && maxY >= box.maxY && minZ <= box.minZ && maxZ >= box.maxZ; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool ExtentBox::Intersects(const ExtentBox &box) const { Check_Object(this); Check_Object(&box); return minX <= box.maxX && maxX >= box.minX && minY <= box.maxY && maxY >= box.minY && minZ <= box.maxZ && maxZ >= box.minZ; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ExtentBox::GetCenterpoint(Point3D *point) const { Check_Object(this); Check_Pointer(point); point->x = 0.5f * (minX + maxX); point->y = 0.5f * (minY + maxY); point->z = 0.5f * (minZ + maxZ); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ExtentBox::TestInstance() const { Verify(minX<=maxX && minY<=maxY && minZ<=maxZ); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #if !defined(Spew) void Spew( const char* group, const ExtentBox &box ) { Check_Object(&box); SPEW(( group, "[%f..%f,%f..%f,%f..%f]+", box.minX, box.maxX, box.minY, box.maxY, box.minZ, box.maxZ )); } #endif //~~~~~~~~~~~~~~~~~~~~~~~~~~ ExtentBox functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Stuff::Use_Scalar_In_Sorted_Array( DynamicArrayOf *values, Scalar value, unsigned *max_index, unsigned block_size, Scalar threshold ) { Check_Object(values); Check_Pointer(max_index); // //------------------------------------------------------------- // First, look to see if the table contains the specified value //------------------------------------------------------------- // unsigned bottom = 0; unsigned top = *max_index; while (top > bottom) { unsigned middle = (top + bottom - 1) >> 1; if (Close_Enough((*values)[middle], value, threshold)) { return; } else if ((*values)[middle] > value) { top = middle; } else { bottom = middle + 1; } } Verify(top == bottom); // //----------------------------------------------------------------------- // Since we got here, a new value must be added to the table. First make // room in the table //----------------------------------------------------------------------- // if (*max_index == values->GetLength()) { values->SetLength(*max_index + block_size); } unsigned to_move = *max_index - bottom; Verify(to_move <= *max_index); if (to_move > 0) { memmove( &(*values)[bottom+1], &(*values)[bottom], to_move * sizeof(value) ); } ++(*max_index); (*values)[bottom] = value; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Stuff::Find_Planes_Of_Boxes( DynamicArrayOf *planes, const DynamicArrayOf &boxes ) { Check_Object(planes); Check_Object(&boxes); // //------------------------------------------------------------ // Figure out all the unique axis components used by the boxes //------------------------------------------------------------ // DynamicArrayOf xs, ys, zs; unsigned max_x = 0, max_y = 0, max_z = 0, count = boxes.GetLength(), i; Verify(count > 0); for (i=0; iSetLength(count); // //------------------------ // Generate the Y-Z planes //------------------------ // Plane *plane = &(*planes)[0]; for (i=0; i(plane - &(*planes)[0]) < count); plane->normal.x = 1.0f; plane->normal.y = 0.0f; plane->normal.z = 0.0f; plane->offset = xs[i]; ++plane; } // //------------------------ // Generate the X-Z planes //------------------------ // for (i=0; i(plane - &(*planes)[0]) < count); plane->normal.x = 0.0f; plane->normal.y = 1.0f; plane->normal.z = 0.0f; plane->offset = ys[i]; ++plane; } // //------------------------ // Generate the X-Y planes //------------------------ // for (i=0; i(plane - &(*planes)[0]) < count); plane->normal.x = 0.0f; plane->normal.y = 0.0f; plane->normal.z = 1.0f; plane->offset = zs[i]; ++plane; } }