| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706 |
- /*
- ** Command & Conquer Generals Zero Hour(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
- ***********************************************************************************************
- * *
- * Project Name : WWMath *
- * *
- * $Archive:: /Commando/Code/wwmath/gridcull.h $*
- * *
- * Author:: Greg Hjelstrom *
- * *
- * $Modtime:: 5/10/01 10:42a $*
- * *
- * $Revision:: 14 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * GridCullSystemClass::clamp_indices_to_grid -- constrains indices to be a valid location *
- * GridCullSystemClass::map_point_to_cell -- determines which cell the point is in *
- * GridCullSystemClass::map_point_to_address -- determines the address of a point in the gri *
- * GridCullSystemClass::map_indices_to_address -- computes the address for given index tripl *
- * GridCullSystemClass::total_cell_count -- returns the total number of cells in the grid *
- * GridCullSystemClass::compute_box -- computes the bounding box for a grid cell *
- * GridCullSystemClass::compute_box -- computes bounding box for a range of grid cells *
- * GridCullSystemClass::init_volume -- inits volume to contain the given range *
- * GridCullSystemClass::init_volume -- inits volume to contain the given line segment *
- * GridCullSystemClass::init_volume -- inits volume to contain the given box *
- * GridCullSystemClass::init_volume -- inits volume to contain the given oriented box *
- * GridCullSystemClass::init_volume -- inits volume to contain the given frustum *
- * GridCullSystemClass::VolumeStruct::VolumeStruct -- constructor *
- * GridCullSystemClass::VolumeStruct::VolumeStruct -- constructor *
- * GridCullSystemClass::VolumeStruct::Is_Leaf -- check if volume is a leaf *
- * GridCullSystemClass::VolumeStruct::Is_Empty -- check if volume is empty (or invalid) *
- * GridCullSystemClass::VolumeStruct::Split -- split this volume *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #if defined(_MSC_VER)
- #pragma once
- #endif
- #include "cullsys.h"
- #include "mempool.h"
- #include "frustum.h"
- #include "aabox.h"
- #include "lineseg.h"
- #include "obbox.h"
- #include <string.h>
- class ChunkLoadClass;
- class ChunkSaveClass;
- /*
- ** GridCullSystemClass
- ** This is a culling system designed for dynamic objects (objects which are moving or
- ** changing bounding box size). It features O(1) insertion as opposed to
- ** the AABTree, QuadTree, or Octree insertion times which are O(logn). It's disadvantages
- ** compared to the above mentioned systems are that it must uniformly divide space. The
- ** AABTree conforms to the geometry placed in it and can therefore cull things more
- ** efficiently. In actual use, this system is like an AAB-tree which is uniformly subdivided,
- ** its just that we can jump straight to the leaves of the tree for insertion...
- **
- ** The bounding volume for each grid cell is considered to be the volume of the cell, expanded
- ** by the maximum object size. Inserting an object into the grid is a matter of determining
- ** which cell its center point is in. Objects which are larger than the maximum size are
- ** allowed but they are simply put into a linked list which is iterated with each call to
- ** the culling system (linearly culled rather than logarithmic...)
- */
- class GridCullSystemClass : public CullSystemClass
- {
- public:
- GridCullSystemClass(void);
- ~GridCullSystemClass(void);
-
- virtual void Collect_Objects(const Vector3 & point);
- virtual void Collect_Objects(const AABoxClass & box);
- virtual void Collect_Objects(const OBBoxClass & box);
- virtual void Collect_Objects(const FrustumClass & frustum);
-
- virtual void Re_Partition(const Vector3 & min,const Vector3 & max,float objdim);
- virtual void Update_Culling(CullableClass * obj);
- virtual void Load(ChunkLoadClass & cload);
- virtual void Save(ChunkSaveClass & csave);
- virtual int Get_Object_Count (void) const { return ObjCount; }
- /*
- ** Statistics
- */
- struct StatsStruct
- {
- int NodeCount;
- int NodesAccepted;
- int NodesTriviallyAccepted;
- int NodesRejected;
- };
- void Reset_Statistics(void);
- const StatsStruct & Get_Statistics(void);
- void Get_Min_Cell_Size (Vector3 &size) const { size = MinCellSize; }
- void Set_Min_Cell_Size (const Vector3 &size) { MinCellSize = size; }
- int Get_Termination_Count (void) const { return TerminationCellCount; }
- void Set_Termination_Count (int count) { TerminationCellCount = count; }
- protected:
- void Collect_And_Unlink_All(void);
- void Add_Object_Internal(CullableClass * obj);
- void Remove_Object_Internal(CullableClass * obj);
- enum
- {
- TERMINATION_CELL_COUNT = 16384, // algorithm terminates if we ever have more than this many cells.
- UNGRIDDED_ADDRESS = 0xFFFFFFFF // address given to objs that didn't fit in grid
- };
- // Constants which control the division of space:
- Vector3 MinCellSize; // min dimensions for a cell (don't go below this...)
- float MaxObjExtent; // max extent/radius (objects bigger than this are just put in a list)
- int TerminationCellCount;
- // Constants that define the division of space
- Vector3 Origin;
- Vector3 CellDim;
- Vector3 OOCellDim;
- int CellCount[3];
- // 3D array of pointers to objects in each cell
- CullableClass ** Cells;
- // list of objs that were outside or too big for the grid.
- CullableClass * NoGridList;
- // number of objects in the system
- int ObjCount;
- // statistics
- StatsStruct Stats;
- // Structure used to define a volume in the grid. The volume spans from the cell indexed
- // by Min[0],Min[1],Min[2] to the cell indexed by Max[0]-1,Max[1]-1,Max[2]-1.
- struct VolumeStruct
- {
- VolumeStruct(void);
- VolumeStruct(int i0,int j0,int k0,int i1,int j1,int k1);
- bool Is_Leaf(void) const;
- bool Is_Empty(void) const;
- void Split(VolumeStruct & v0,VolumeStruct & v1) const;
- int Min[3];
- int Max[3];
- };
- void link_object(CullableClass * obj);
- void link_object(CullableClass * obj,int address);
- void unlink_object(CullableClass * obj);
- void link_object_to_list(CullableClass ** head,CullableClass * obj);
- void unlink_object_from_list(CullableClass ** head,CullableClass * obj);
- bool map_point_to_cell(const Vector3 & pt,int & set_i,int & set_j,int & set_k);
- bool map_point_to_address(const Vector3 & pt,int & set_address);
- WWINLINE int map_indices_to_address(int i,int j,int k);
- void clamp_indices_to_grid(int * i,int * j,int * k);
- int total_cell_count(void);
- void compute_box(int i,int j,int k,AABoxClass * set_box);
- void compute_box(const VolumeStruct & area, AABoxClass * set_box);
- void init_volume(const Vector3 & bound_min,const Vector3 & bound_max,VolumeStruct * set_volume);
- void init_volume(const Vector3 & point,VolumeStruct * set_volume);
- void init_volume(const LineSegClass & line,VolumeStruct * set_volume);
- void init_volume(const AABoxClass & box,VolumeStruct * set_volume);
- void init_volume(const OBBoxClass & box,VolumeStruct * set_volume);
- void init_volume(const FrustumClass & frustum,VolumeStruct * set_volume);
-
- void collect_objects_in_leaf(const Vector3 & point,CullableClass * head);
- void collect_objects_in_leaf(const AABoxClass & aabox,CullableClass * head);
- void collect_objects_in_leaf(const OBBoxClass & obbox,CullableClass * head);
- void collect_objects_in_leaf(const FrustumClass & frustum,CullableClass * head);
- };
- /*
- ** Macros for gathering statistics. Placed here in the header file so that
- ** derived classes can use them as well.
- */
- #ifdef WWDEBUG
- #define GRIDCULL_NODE_ACCEPTED Stats.NodesAccepted ++;
- #define GRIDCULL_NODE_TRIVIALLY_ACCEPTED Stats.NodesTriviallyAccepted ++;
- #define GRIDCULL_NODE_REJECTED Stats.NodesRejected ++;
- #else
- #define GRIDCULL_NODE_ACCEPTED
- #define GRIDCULL_NODE_TRIVIALLY_ACCEPTED
- #define GRIDCULL_NODE_REJECTED
- #endif
- /*
- ** TypedGridCullSystemClass
- ** This class simply enforces that a certain type of object is inserted into the grid cull system.
- ** It exposes the add, remove, and collection iterating functions and is intended to be the class
- ** actually used by the end user.
- */
- template <class T> class TypedGridCullSystemClass : public GridCullSystemClass
- {
- public:
- virtual void Add_Object(T * obj) { Add_Object_Internal(obj); }
- virtual void Remove_Object(T * obj) { Remove_Object_Internal(obj); }
- T * Get_First_Collected_Object(void) { return (T*)Get_First_Collected_Object_Internal(); }
- T * Get_Next_Collected_Object(T * obj) { return (T*)Get_Next_Collected_Object_Internal(obj); }
- };
- /*
- ** GridLinkClass
- ** This structure is used to link cullable objects into a Grid culling system
- ** This class is should only be used by classes which derive from GridCullSystemClass
- ** not normal users.
- */
- class GridLinkClass : public CullLinkClass, public AutoPoolClass<GridLinkClass,256>
- {
- public:
- GridLinkClass(GridCullSystemClass * system);
- virtual ~GridLinkClass(void);
-
- int GridAddress; // address in the grid.
- CullableClass * Prev; // prev object in this cell
- CullableClass * Next; // next object in this cell
- };
- /*
- ** GridListIterator
- ** This is just a simple iterator that contains the code for traversing the
- ** list of objects either in a cell in the grid or in the NoGridList...
- ** This class should only be used by classes which derive from GridCullSystemClass
- ** not normal users.
- */
- class GridListIterator
- {
- public:
- GridListIterator(CullableClass * head) { First(head); }
- void First(CullableClass * head) { Head = head; CurObj = head; }
- void First(void) { CurObj = Head; }
- void Next(void) { if (CurObj) { CurObj = ((GridLinkClass *)CurObj->Get_Cull_Link())->Next; } }
- void Prev(void) { if (CurObj) { CurObj = ((GridLinkClass *)CurObj->Get_Cull_Link())->Prev; } }
- bool Is_Done(void) { return (CurObj == NULL); }
- CullableClass * Get_Obj(void) { if (CurObj) { CurObj->Add_Ref(); } return CurObj; }
- CullableClass * Peek_Obj(void) { return CurObj; }
- private:
- CullableClass * Head; // head of the list we're working in
- CullableClass * CurObj; // node we're currently at.
- };
- /***********************************************************************************************
- * GridCullSystemClass::clamp_indices_to_grid -- constrains indices to be a valid location *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/30/2000 gth : Created. *
- *=============================================================================================*/
- WWINLINE void GridCullSystemClass::clamp_indices_to_grid(int * i,int * j,int * k)
- {
- if (*i < 0) *i = 0;
- if (*i >= CellCount[0]) *i = CellCount[0] - 1;
- if (*j < 0) *j = 0;
- if (*j >= CellCount[1]) *j = CellCount[1] - 1;
- if (*k < 0) *k = 0;
- if (*k >= CellCount[2]) *k = CellCount[2] - 1;
- }
- /***********************************************************************************************
- * GridCullSystemClass::map_point_to_cell -- determines which cell the point is in *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/30/2000 gth : Created. *
- *=============================================================================================*/
- WWINLINE bool GridCullSystemClass::map_point_to_cell(const Vector3 & pt,int & set_i,int & set_j,int & set_k)
- {
- Vector3 dp = pt - Origin;
- set_i = floor(dp.X * OOCellDim.X);
- set_j = floor(dp.Y * OOCellDim.Y);
- set_k = floor(dp.Z * OOCellDim.Z);
- if ( (set_i >= 0) && (set_j >= 0) && (set_k >= 0) &&
- (set_i < CellCount[0]) && (set_j < CellCount[1]) && (set_k < CellCount[2]) )
- {
- return true;
- }
- return false;
- }
- /***********************************************************************************************
- * GridCullSystemClass::map_point_to_address -- determines the address of a point in the grid *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/30/2000 gth : Created. *
- *=============================================================================================*/
- WWINLINE bool GridCullSystemClass::map_point_to_address(const Vector3 & pt,int &set_address)
- {
- int i,j,k;
- bool res = map_point_to_cell(pt,i,j,k);
-
- if (res) {
- set_address = map_indices_to_address(i,j,k);
- return true;
- } else {
- set_address = UNGRIDDED_ADDRESS;
- return false;
- }
- }
- /***********************************************************************************************
- * GridCullSystemClass::map_indices_to_address -- computes the address for given index triplet *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/30/2000 gth : Created. *
- *=============================================================================================*/
- WWINLINE int GridCullSystemClass::map_indices_to_address(int i,int j,int k)
- {
- return i + j*CellCount[0] + k*CellCount[0]*CellCount[1];
- }
- /***********************************************************************************************
- * GridCullSystemClass::total_cell_count -- returns the total number of cells in the grid *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/30/2000 gth : Created. *
- *=============================================================================================*/
- WWINLINE int GridCullSystemClass::total_cell_count(void)
- {
- return CellCount[0] * CellCount[1] * CellCount[2];
- }
- /***********************************************************************************************
- * GridCullSystemClass::compute_box -- computes the bounding box for a grid cell *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/30/2000 gth : Created. *
- *=============================================================================================*/
- WWINLINE void GridCullSystemClass::compute_box(int i,int j,int k,AABoxClass * set_box)
- {
- WWASSERT(set_box != NULL);
- WWASSERT((i >= 0) && (j >= 0) && (k >= 0));
- WWASSERT((i < CellCount[0]) && (j < CellCount[1]) && (k < CellCount[2]));
- Vector3 min,max;
- min.X = Origin.X + i * CellDim.X - MaxObjExtent;
- min.Y = Origin.Y + j * CellDim.Y - MaxObjExtent;
- min.Z = Origin.Z + k * CellDim.Z - MaxObjExtent;
- max.X = min.X + CellDim.X + 2.0f*MaxObjExtent;
- max.Y = min.Y + CellDim.Y + 2.0f*MaxObjExtent;
- max.Z = min.Z + CellDim.Z + 2.0f*MaxObjExtent;
- set_box->Init((min+max)*0.5f, (min-max)*0.5f);
- }
- /***********************************************************************************************
- * GridCullSystemClass::compute_box -- computes bounding box for a range of grid cells *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/30/2000 gth : Created. *
- *=============================================================================================*/
- WWINLINE void GridCullSystemClass::compute_box(const GridCullSystemClass::VolumeStruct & vol, AABoxClass * set_box)
- {
- WWASSERT(set_box != NULL);
- WWASSERT((vol.Min[0] >= 0) && (vol.Min[1] >= 0) && (vol.Min[2] >= 0));
- WWASSERT((vol.Max[0] <= CellCount[0]) && (vol.Max[1] <= CellCount[1]) && (vol.Max[2] <= CellCount[2]));
- Vector3 min,max;
- min.X = Origin.X + vol.Min[0] * CellDim.X - MaxObjExtent;
- min.Y = Origin.Y + vol.Min[1] * CellDim.Y - MaxObjExtent;
- min.Z = Origin.Z + vol.Min[2] * CellDim.Z - MaxObjExtent;
- max.X = Origin.X + vol.Max[0] * CellDim.X + MaxObjExtent;
- max.Y = Origin.Y + vol.Max[1] * CellDim.Y + MaxObjExtent;
- max.Z = Origin.Z + vol.Max[2] * CellDim.Z + MaxObjExtent;
- Vector3 center((max.X+min.X)*0.5f,(max.Y+min.Y)*0.5f,(max.Z+min.Z)*0.5f);
- Vector3 extent((max.X-min.X)*0.5f,(max.Y-min.Y)*0.5f,(max.Z-min.Z)*0.5f);
- set_box->Init(center,extent);
- }
- /***********************************************************************************************
- * GridCullSystemClass::init_volume -- inits volume to contain the given range *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/30/2000 gth : Created. *
- *=============================================================================================*/
- WWINLINE void GridCullSystemClass::init_volume
- (
- const Vector3 & bound_min,
- const Vector3 & bound_max,
- VolumeStruct * set_vol
- )
- {
- // expand the box by the maximum size of any object
- Vector3 grid_min = bound_min;
- grid_min.X -= MaxObjExtent;
- grid_min.Y -= MaxObjExtent;
- grid_min.Z -= MaxObjExtent;
- Vector3 grid_max = bound_max;
- grid_max.X += MaxObjExtent;
- grid_max.Y += MaxObjExtent;
- grid_max.Z += MaxObjExtent;
- // now compute the grid coordinates of the corners of the box
- GridCullSystemClass::map_point_to_cell(grid_min,set_vol->Min[0],set_vol->Min[1],set_vol->Min[2]);
- GridCullSystemClass::map_point_to_cell(grid_max,set_vol->Max[0],set_vol->Max[1],set_vol->Max[2]);
- // now clamp the volume to the actual grid
- clamp_indices_to_grid(&(set_vol->Min[0]),&(set_vol->Min[1]),&(set_vol->Min[2]));
- clamp_indices_to_grid(&(set_vol->Max[0]),&(set_vol->Max[1]),&(set_vol->Max[2]));
- // increment the outer edge of the box due to the way we traverse the grid...
- set_vol->Max[0] ++;
- set_vol->Max[1] ++;
- set_vol->Max[2] ++;
- }
- /***********************************************************************************************
- * GridCullSystemClass::init_volume -- inits volume to contain the given line segment *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/30/2000 gth : Created. *
- *=============================================================================================*/
- WWINLINE void GridCullSystemClass::init_volume(const LineSegClass & line,VolumeStruct * set_volume)
- {
- Vector3 min_pt,max_pt;
- min_pt.X = WWMath::Min(line.Get_P0().X,line.Get_P1().X);
- max_pt.X = WWMath::Max(line.Get_P0().X,line.Get_P1().X);
- min_pt.Y = WWMath::Min(line.Get_P0().Y,line.Get_P1().Y);
- max_pt.Y = WWMath::Max(line.Get_P0().Y,line.Get_P1().Y);
- min_pt.Z = WWMath::Min(line.Get_P0().Z,line.Get_P1().Z);
- max_pt.Z = WWMath::Max(line.Get_P0().Z,line.Get_P1().Z);
- init_volume(min_pt,max_pt,set_volume);
- }
- /***********************************************************************************************
- * GridCullSystemClass::init_volume -- inits volume to contain the given box *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/30/2000 gth : Created. *
- *=============================================================================================*/
- WWINLINE void GridCullSystemClass::init_volume(const AABoxClass & box,VolumeStruct * set_volume)
- {
- init_volume(box.Center - box.Extent,box.Center + box.Extent,set_volume);
- }
- /***********************************************************************************************
- * GridCullSystemClass::init_volume -- inits volume to contain the given oriented box *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/30/2000 gth : Created. *
- *=============================================================================================*/
- WWINLINE void GridCullSystemClass::init_volume(const OBBoxClass & box,VolumeStruct * set_volume)
- {
- Vector3 aaextent;
- box.Compute_Axis_Aligned_Extent(&aaextent);
- init_volume(box.Center - aaextent,box.Center + aaextent,set_volume);
- }
- /***********************************************************************************************
- * GridCullSystemClass::init_volume -- inits volume to contain the given frustum *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/30/2000 gth : Created. *
- *=============================================================================================*/
- WWINLINE void GridCullSystemClass::init_volume(const FrustumClass & frustum,VolumeStruct * set_volume)
- {
- init_volume(frustum.Get_Bound_Min(),frustum.Get_Bound_Max(),set_volume);
- }
- /***********************************************************************************************
- * GridCullSystemClass::VolumeStruct::VolumeStruct -- constructor *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- *=============================================================================================*/
- WWINLINE GridCullSystemClass::VolumeStruct::VolumeStruct(void)
- {
- }
- /***********************************************************************************************
- * GridCullSystemClass::VolumeStruct::VolumeStruct -- constructor *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/30/2000 gth : Created. *
- *=============================================================================================*/
- WWINLINE GridCullSystemClass::VolumeStruct::VolumeStruct(int i0,int j0,int k0,int i1,int j1,int k1)
- {
- Min[0] = i0;
- Min[1] = j0;
- Min[2] = k0;
- Max[0] = i1;
- Max[1] = j1;
- Max[2] = k1;
- WWASSERT(Max[0] > Min[0]);
- WWASSERT(Max[1] > Min[1]);
- WWASSERT(Max[2] > Min[2]);
- }
- /***********************************************************************************************
- * GridCullSystemClass::VolumeStruct::Is_Leaf -- check if volume is a leaf *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/30/2000 gth : Created. *
- *=============================================================================================*/
- WWINLINE bool GridCullSystemClass::VolumeStruct::Is_Leaf(void) const
- {
- return ((Max[0]-Min[0] == 1) && (Max[1]-Min[1] == 1) && (Max[2]-Min[2] == 1));
- }
- /***********************************************************************************************
- * GridCullSystemClass::VolumeStruct::Is_Empty -- check if volume is empty (or invalid) *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/30/2000 gth : Created. *
- *=============================================================================================*/
- WWINLINE bool GridCullSystemClass::VolumeStruct::Is_Empty(void) const
- {
- return ((Max[0]-Min[0] <= 0) || (Max[1]-Min[1] <= 0) || (Max[2]-Min[2] <= 0));
- }
- /***********************************************************************************************
- * GridCullSystemClass::VolumeStruct::Split -- split this volume *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 3/30/2000 gth : Created. *
- *=============================================================================================*/
- WWINLINE void GridCullSystemClass::VolumeStruct::Split(VolumeStruct & v0,VolumeStruct & v1) const
- {
- // find the longest dimension
- int split_axis = 0;
- int delta[3];
- delta[0] = Max[0] - Min[0];
- delta[1] = Max[1] - Min[1];
- delta[2] = Max[2] - Min[2];
- if (delta[1] > delta[split_axis]) split_axis = 1;
- if (delta[2] > delta[split_axis]) split_axis = 2;
- WWASSERT(delta[split_axis] > 0);
- // split the volume perpendicularly to that dimension
- memcpy(&v0,this,sizeof(VolumeStruct));
- memcpy(&v1,this,sizeof(VolumeStruct));
- v0.Max[split_axis] = v1.Min[split_axis] = Min[split_axis] + (delta[split_axis] >> 1);
- }
|