quadtree.h

00001 /*--License:
00002         Lilith 3D Engine
00003         Copyright Lee Thomason (Grinning Lizard Software) 2002-2007
00004         www.grinninglizard.com/lilith
00005 
00006         This program is free software; you can redistribute it and/or
00007         modify it under the terms of the GNU General Public License
00008         as published by the Free Software Foundation; either version 2
00009         of the License, or (at your option) any later version.
00010 
00011         This program is distributed in the hope that it will be useful,
00012         but WITHOUT ANY WARRANTY; without even the implied warranty of
00013         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014         GNU General Public License for more details.
00015 
00016         You should have received a copy of the GNU General Public License
00017         along with this program; if not, write to the Free Software
00018         Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019 
00020         The full text of the license can be found in license.txt
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         // Basic visible culling
00054         void DoCulling( bool stencilObjects = false );
00055 
00056         // Culling, accounting for shadow cast
00057         //void DoCullingShadow( const grinliz::Rectangle2F& shadowBounds, U32 meshMask );
00058 
00059 
00061         BuildingMesh* FindBuilding( int mapX, int mapY );
00062 
00063         // The TerrainMesh will notify the quadtree of a terrain change
00064         // so that the quadtree can update the z values
00065         virtual void TerrainChange( const grinliz::Rectangle2I& vertexBounds );
00066         
00067         // After culling, the root of the mesh list to be rendered
00068         // Linked list of all visible meshes
00069         Mesh* GetMeshRoot()                     { return meshRoot; }
00070         // If you can see the mesh, you can see the shadow. (Or that's the approximation
00071         // lilith uses.) However, you can often seen the shadows but not the mesh. This
00072         // is a link list of shadow-only renders.
00073         Mesh* GetMeshShadowRoot()       { return meshShadowRoot; }
00074         // All the foliage
00075         Mesh* GetFoliageRoot()  { return foliageRoot; }
00076         // All the trees
00077         Mesh* GetTreeRoot()             { return treeRoot; }
00078         // All the stencil decals
00079         Mesh* GetDecalStencilRoot() { return decalStencilRoot; }
00080         
00081         // Debugging - how many nodes of the tree are in use?
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                 // LOD 0: 1 node
00091                 // LOD 1: 4 nodes
00092                 // LOD 2: 16
00093                 // LOD 3: 64
00094                 // #nodes at level = ( 1 << (lod*2) )
00095                 // LOD 8: 64k
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                         // The memory is laid out so
00110                         // that the children of this node are the same
00111                         // offset in the NEXT lod as THIS lod. Of course the
00112                         // next LOD has 4 times as many nodes.
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                 // FIXME Sum to 16 bytes 
00153                 MeshNode                sentinel;               // 12 bytes - damn vtable!
00154                 U16                             x;                              // in map & vertex coordinates, requires 13 bits
00155                 U16                             y;                              // in map & vertex coordinates, requires 13 bits
00156                 U16                             lod;                    // requires 4 bits
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         //void Clear( QuadTreeNode* node );
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 ];   // FIXME: align to 16 bit boundaries?
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         //U32 cullingMask;
00211         //bool stencilObjects;
00212 };
00213 
00214 };      //namespace lilith3d
00215 #endif
00216 

Generated on Fri Mar 23 19:36:22 2007 for Lilith3D by  doxygen 1.5.1-p1