00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef LILITH_QUADTREE_INCLUDED
00024 #define LILITH_QUADTREE_INCLUDED
00025
00026 #include "../grinliz/gldebug.h"
00027 #include "mesh.h"
00028 #include "terrainmesh.h"
00029
00030 namespace lilith3d
00031 {
00032
00033 class Mesh;
00034
00035
00045 class QuadTree : public TerrainListener
00046 {
00047 public:
00048 QuadTree();
00049 ~QuadTree();
00050
00051 void AddMesh( Mesh* item );
00052
00053
00054 void DoCulling( bool stencilObjects = false );
00055
00056
00057
00058
00059
00061 BuildingMesh* FindBuilding( int mapX, int mapY );
00062
00063
00064
00065 virtual void TerrainChange( const grinliz::Rectangle2I& vertexBounds );
00066
00067
00068
00069 Mesh* GetMeshRoot() { return meshRoot; }
00070
00071
00072
00073 Mesh* GetMeshShadowRoot() { return meshShadowRoot; }
00074
00075 Mesh* GetFoliageRoot() { return foliageRoot; }
00076
00077 Mesh* GetTreeRoot() { return treeRoot; }
00078
00079 Mesh* GetDecalStencilRoot() { return decalStencilRoot; }
00080
00081
00082 float NodesInUse() { return (float)nodesInUse / (float)NUM_QUADNODES; };
00083
00087 void IntersectRay( int flags, const grinliz::Ray& ray, LilithObjectList* vec );
00088
00089 enum {
00090
00091
00092
00093
00094
00095
00096
00097 MAX_LOD = MAP_POWER-2,
00098 QUADLEN = ( 1<<MAX_LOD ),
00099 QUADLEN_SQUARED = QUADLEN * QUADLEN,
00100 NUM_QUADNODES = QUADLEN_SQUARED + QUADLEN_SQUARED/4 + QUADLEN_SQUARED/16 + QUADLEN_SQUARED/64 + QUADLEN_SQUARED/256 + 2*QUADLEN_SQUARED/1024
00101 };
00102
00103 private:
00104
00105 struct QuadTreeNode
00106 {
00107 QuadTreeNode* Children( QuadTreeNode* offsets[] )
00108 {
00109
00110
00111
00112
00113 GLASSERT( lod < QuadTree::MAX_LOD );
00114 UPTR offset = ( this - offsets[ lod ] );
00115 QuadTreeNode* result = offsets[ lod+1 ] + (offset<<2);
00116 return result;
00117 }
00118
00119 QuadTreeNode* Child( U32 i, QuadTreeNode* offsets[] )
00120 {
00121 GLASSERT( lod < QuadTree::MAX_LOD );
00122 GLASSERT( i<4 );
00123
00124 QuadTreeNode* result = 0;
00125 U32 offset = (U32)( this - offsets[ lod ] );
00126 result = offsets[ lod+1 ] + (offset<<2) + i;
00127 return result;
00128 }
00129
00130 QuadTreeNode* Parent( QuadTreeNode* offsets[] )
00131 {
00132 if ( lod == 0 )
00133 return 0;
00134 unsigned offset = (unsigned)(this - offsets[ lod ]);
00135 QuadTreeNode* result = offsets[ lod-1 ] + (offset>>2);
00136 return result;
00137 }
00138
00139 static unsigned LODToSize( U32 lod ) { return ( MAPSIZE >> lod ); }
00140
00141 unsigned Size() { return LODToSize( lod ); }
00142 unsigned LOD() { return lod; }
00143
00144 void Init( U32 _x, U32 _y, U32 _lod ) {
00145 sentinel.next = &sentinel;
00146 sentinel.prev = &sentinel;
00147 this->x = _x;
00148 this->y = _y;
00149 this->lod = _lod;
00150 }
00151
00152
00153 MeshNode sentinel;
00154 U16 x;
00155 U16 y;
00156 U16 lod;
00157 };
00158
00159 void InitNodeRec( QuadTree::QuadTreeNode* node, unsigned x, unsigned y, unsigned lod );
00160 void DoCullingRec( QuadTreeNode* node, int frustum );
00161 void TerrainChangeRec( const grinliz::Rectangle2I& vertexBounds, QuadTreeNode* node );
00162 void IntersectRayRec( int flags, QuadTreeNode* node, const grinliz::Ray& ray, const grinliz::Rectangle2I& clip, LilithObjectList* vec );
00163
00164
00165
00166 void AddToList( Mesh* mesh, bool onlyShadow )
00167 {
00168 GLASSERT( mesh != meshRoot );
00169 GLASSERT( mesh != foliageRoot );
00170 GLASSERT( mesh != treeRoot );
00171
00172 if ( mesh->Type() == TREEMESH ) {
00173 mesh->nextRender = treeRoot;
00174 treeRoot = mesh;
00175 }
00176 else if ( mesh->Type() == FOLIAGEMESH ) {
00177 mesh->nextRender = foliageRoot;
00178 foliageRoot = mesh;
00179 }
00180 else if ( mesh->Type() == DECALMESH && mesh->Stencil() )
00181 {
00182 mesh->nextRender = decalStencilRoot;
00183 decalStencilRoot = mesh;
00184 }
00185 else {
00186 if ( onlyShadow ) {
00187 mesh->nextRender = meshShadowRoot;
00188 meshShadowRoot = mesh;
00189 }
00190 else {
00191 mesh->nextRender = meshRoot;
00192 meshRoot = mesh;
00193 }
00194 }
00195 }
00196
00197
00198 QuadTree::QuadTreeNode root[ NUM_QUADNODES ];
00199 QuadTree::QuadTreeNode* offsets[ MAX_LOD+1 ];
00200
00201 Lilith3D* lilith;
00202 Mesh* meshRoot;
00203 Mesh* meshShadowRoot;
00204 Mesh* foliageRoot;
00205 Mesh* treeRoot;
00206 Mesh* decalStencilRoot;
00207
00208 unsigned nodesInUse;
00209 grinliz::Rectangle3F quadTreeAABB;
00210
00211
00212 };
00213
00214 };
00215 #endif
00216