12#ifndef TT_INCLUDE_GRIDCULL_H
13#define TT_INCLUDE_GRIDCULL_H
14#include "cullsystemclass.h"
15#include "frustumclass.h"
16#include "aaboxclass.h"
17#include "obboxclass.h"
20class GridCullSystemClass :
public CullSystemClass
23 GridCullSystemClass(
void);
24 ~GridCullSystemClass(
void);
25 virtual void Collect_Objects(
const Vector3 & point);
26 virtual void Collect_Objects(
const AABoxClass & box);
27 virtual void Collect_Objects(
const OBBoxClass & box);
28 virtual void Collect_Objects(
const FrustumClass & frustum);
29 virtual void Re_Partition(
const Vector3 & min,
const Vector3 & max,
float objdim);
30 virtual void Update_Culling(CullableClass * obj);
31 virtual void Load(ChunkLoadClass & cload);
32 virtual void Save(ChunkSaveClass & csave);
33 virtual int Get_Object_Count (
void)
const {
return ObjCount; }
38 int NodesTriviallyAccepted;
41 void Reset_Statistics(
void);
42 const StatsStruct & Get_Statistics(
void);
43 void Get_Min_Cell_Size (Vector3 &size)
const { size = MinCellSize; }
44 void Set_Min_Cell_Size (
const Vector3 &size) { MinCellSize = size; }
45 int Get_Termination_Count (
void)
const {
return TerminationCellCount; }
46 void Set_Termination_Count (
int count) { TerminationCellCount = count; }
48 void Collect_And_Unlink_All(
void);
49 void Add_Object_Internal(CullableClass * obj);
50 void Remove_Object_Internal(CullableClass * obj);
53 TERMINATION_CELL_COUNT = 16384,
54 UNGRIDDED_ADDRESS = 0xFFFFFFFF
58 int TerminationCellCount;
63 CullableClass ** Cells;
64 CullableClass * NoGridList;
72 VolumeStruct(
int i0,
int j0,
int k0,
int i1,
int j1,
int k1)
81 bool Is_Leaf(
void)
const
83 return ((Max[0]-Min[0] == 1) && (Max[1]-Min[1] == 1) && (Max[2]-Min[2] == 1));
85 bool Is_Empty(
void)
const
87 return ((Max[0]-Min[0] <= 0) || (Max[1]-Min[1] <= 0) || (Max[2]-Min[2] <= 0));
89 void Split(VolumeStruct & v0,VolumeStruct & v1)
const
93 delta[0] = Max[0] - Min[0];
94 delta[1] = Max[1] - Min[1];
95 delta[2] = Max[2] - Min[2];
96 if (delta[1] > delta[split_axis]) split_axis = 1;
97 if (delta[2] > delta[split_axis]) split_axis = 2;
98 memcpy(&v0,
this,
sizeof(VolumeStruct));
99 memcpy(&v1,
this,
sizeof(VolumeStruct));
100 v0.Max[split_axis] = v1.Min[split_axis] = Min[split_axis] + (delta[split_axis] >> 1);
105 void link_object(CullableClass * obj);
106 void link_object(CullableClass * obj,
int address);
107 void unlink_object(CullableClass * obj);
108 void link_object_to_list(CullableClass ** head,CullableClass * obj);
109 void unlink_object_from_list(CullableClass ** head,CullableClass * obj);
110 bool map_point_to_cell(
const Vector3 & pt,
int & set_i,
int & set_j,
int & set_k)
112 Vector3 dp = pt - Origin;
113 set_i = (int)floor(dp.X * OOCellDim.X);
114 set_j = (int)floor(dp.Y * OOCellDim.Y);
115 set_k = (int)floor(dp.Z * OOCellDim.Z);
116 if ( (set_i >= 0) && (set_j >= 0) && (set_k >= 0) && (set_i < CellCount[0]) && (set_j < CellCount[1]) && (set_k < CellCount[2]) )
122 bool map_point_to_address(
const Vector3 & pt,
int & set_address)
125 bool res = map_point_to_cell(pt,i,j,k);
128 set_address = map_indices_to_address(i,j,k);
133 set_address = UNGRIDDED_ADDRESS;
137 int map_indices_to_address(
int i,
int j,
int k)
139 return i + j*CellCount[0] + k*CellCount[0]*CellCount[1];
141 void clamp_indices_to_grid(
int * i,
int * j,
int * k)
144 if (*i >= CellCount[0]) *i = CellCount[0] - 1;
146 if (*j >= CellCount[1]) *j = CellCount[1] - 1;
148 if (*k >= CellCount[2]) *k = CellCount[2] - 1;
150 int total_cell_count(
void)
152 return CellCount[0] * CellCount[1] * CellCount[2];
154 void compute_box(
int i,
int j,
int k,AABoxClass * set_box)
157 min.X = Origin.X + i * CellDim.X - MaxObjExtent;
158 min.Y = Origin.Y + j * CellDim.Y - MaxObjExtent;
159 min.Z = Origin.Z + k * CellDim.Z - MaxObjExtent;
160 max.X = min.X + CellDim.X + 2.0f*MaxObjExtent;
161 max.Y = min.Y + CellDim.Y + 2.0f*MaxObjExtent;
162 max.Z = min.Z + CellDim.Z + 2.0f*MaxObjExtent;
163 set_box->Init((min+max)*0.5f, (min-max)*0.5f);
165 void compute_box(
const VolumeStruct & vol, AABoxClass * set_box)
168 min.X = Origin.X + vol.Min[0] * CellDim.X - MaxObjExtent;
169 min.Y = Origin.Y + vol.Min[1] * CellDim.Y - MaxObjExtent;
170 min.Z = Origin.Z + vol.Min[2] * CellDim.Z - MaxObjExtent;
171 max.X = Origin.X + vol.Max[0] * CellDim.X + MaxObjExtent;
172 max.Y = Origin.Y + vol.Max[1] * CellDim.Y + MaxObjExtent;
173 max.Z = Origin.Z + vol.Max[2] * CellDim.Z + MaxObjExtent;
174 Vector3 center((max.X+min.X)*0.5f,(max.Y+min.Y)*0.5f,(max.Z+min.Z)*0.5f);
175 Vector3 extent((max.X-min.X)*0.5f,(max.Y-min.Y)*0.5f,(max.Z-min.Z)*0.5f);
176 set_box->Init(center,extent);
178 void init_volume(
const Vector3 & bound_min,
const Vector3 & bound_max,VolumeStruct * set_vol)
180 Vector3 grid_min = bound_min;
181 grid_min.X -= MaxObjExtent;
182 grid_min.Y -= MaxObjExtent;
183 grid_min.Z -= MaxObjExtent;
184 Vector3 grid_max = bound_max;
185 grid_max.X += MaxObjExtent;
186 grid_max.Y += MaxObjExtent;
187 grid_max.Z += MaxObjExtent;
188 GridCullSystemClass::map_point_to_cell(grid_min,set_vol->Min[0],set_vol->Min[1],set_vol->Min[2]);
189 GridCullSystemClass::map_point_to_cell(grid_max,set_vol->Max[0],set_vol->Max[1],set_vol->Max[2]);
190 clamp_indices_to_grid(&(set_vol->Min[0]),&(set_vol->Min[1]),&(set_vol->Min[2]));
191 clamp_indices_to_grid(&(set_vol->Max[0]),&(set_vol->Max[1]),&(set_vol->Max[2]));
196 void init_volume(
const Vector3 & point,VolumeStruct * set_volume);
197 void init_volume(
const LineSegClass & line,VolumeStruct * set_volume)
199 Vector3 min_pt,max_pt;
200 min_pt.X = WWMath::Min(line.Get_P0().X,line.Get_P1().X);
201 max_pt.X = WWMath::Max(line.Get_P0().X,line.Get_P1().X);
202 min_pt.Y = WWMath::Min(line.Get_P0().Y,line.Get_P1().Y);
203 max_pt.Y = WWMath::Max(line.Get_P0().Y,line.Get_P1().Y);
204 min_pt.Z = WWMath::Min(line.Get_P0().Z,line.Get_P1().Z);
205 max_pt.Z = WWMath::Max(line.Get_P0().Z,line.Get_P1().Z);
206 init_volume(min_pt,max_pt,set_volume);
208 void init_volume(
const AABoxClass & box,VolumeStruct * set_volume)
210 init_volume(box.Center - box.Extent,box.Center + box.Extent,set_volume);
212 void init_volume(
const OBBoxClass & box,VolumeStruct * set_volume)
215 box.Compute_Axis_Aligned_Extent(&aaextent);
216 init_volume(box.Center - aaextent,box.Center + aaextent,set_volume);
218 void init_volume(
const FrustumClass & frustum,VolumeStruct * set_volume)
220 init_volume(frustum.Get_Bound_Min(),frustum.Get_Bound_Max(),set_volume);
222 void collect_objects_in_leaf(
const Vector3 & point,CullableClass * head);
223 void collect_objects_in_leaf(
const AABoxClass & aabox,CullableClass * head);
224 void collect_objects_in_leaf(
const OBBoxClass & obbox,CullableClass * head);
225 void collect_objects_in_leaf(
const FrustumClass & frustum,CullableClass * head);
227#define GRIDCULL_NODE_ACCEPTED
228#define GRIDCULL_NODE_TRIVIALLY_ACCEPTED
229#define GRIDCULL_NODE_REJECTED
230template <
class T>
class TypedGridCullSystemClass :
public GridCullSystemClass
233 virtual void Add_Object(T * obj) { Add_Object_Internal(obj); }
234 virtual void Remove_Object(T * obj) { Remove_Object_Internal(obj); }
235 T * Get_First_Collected_Object(
void) {
return (T*)Get_First_Collected_Object_Internal(); }
236 T * Get_Next_Collected_Object(T * obj) {
return (T*)Get_Next_Collected_Object_Internal(obj); }
238class GridLinkClass :
public CullLinkClass,
public AutoPoolClass<GridLinkClass,256>
241 GridLinkClass(GridCullSystemClass * system);
242 virtual ~GridLinkClass(
void);
244 CullableClass * Prev;
245 CullableClass * Next;
247class GridListIterator
250 GridListIterator(CullableClass * head) { First(head); }
251 void First(CullableClass * head) { Head = head; CurObj = head; }
252 void First(
void) { CurObj = Head; }
253 void Next(
void) {
if (CurObj) { CurObj = ((GridLinkClass *)CurObj->Get_Cull_Link())->Next; } }
254 void Prev(
void) {
if (CurObj) { CurObj = ((GridLinkClass *)CurObj->Get_Cull_Link())->Prev; } }
255 bool Is_Done(
void) {
return (CurObj == NULL); }
256 CullableClass * Get_Obj(
void) {
if (CurObj) { CurObj->Add_Ref(); }
return CurObj; }
257 CullableClass * Peek_Obj(
void) {
return CurObj; }
259 CullableClass * Head;
260 CullableClass * CurObj;