# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

quad_grid_clip_cluster.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "std3d.h"
00027 
00028 #include "3d/quad_grid_clip_cluster.h"
00029 
00030 
00031 using namespace NLMISC;
00032 using namespace std;
00033 
00034 
00035 namespace NL3D {
00036 
00037 
00038 // ***************************************************************************
00039 void            CQuadGridClipCluster::registerBasic()
00040 {
00041         CMOT::registerModel( QuadGridClipClusterId, 0, CQuadGridClipCluster::creator);
00042         CMOT::registerObs( ClipTravId, QuadGridClipClusterId, CQuadGridClipClusterClipObs::creator );
00043 }
00044 
00045 
00046 // ***************************************************************************
00047 void            CQuadGridClipCluster::extendCluster(const NLMISC::CAABBox &worldBBox)
00048 {
00049         if(_Empty)
00050         {
00051                 _Empty= false;
00052                 _BBox= worldBBox;
00053         }
00054         else
00055         {
00056                 // extend the bbox with 2 corners of the incoming bbox (sufficient for an AABBox).
00057                 _BBox.extend( worldBBox.getCenter() + worldBBox.getHalfSize() );
00058                 _BBox.extend( worldBBox.getCenter() - worldBBox.getHalfSize() );
00059         }
00060 
00061         // update _Radius
00062         _Radius= _BBox.getRadius();
00063 }
00064 
00065 
00066 // ***************************************************************************
00067 void            CQuadGridClipCluster::update()
00068 {
00069         // never need to update, so unlink me from ValidateList.
00070         unlinkFromValidateList();
00071 }
00072 
00073 
00074 // ***************************************************************************
00075 CQuadGridClipClusterClipObs::CQuadGridClipClusterClipObs()
00076 {
00077         _LastClipWasDistMaxClip= false;
00078         _LastClipWasFrustumClip= false;
00079 }
00080 
00081 // ***************************************************************************
00082 void            CQuadGridClipClusterClipObs::traverse(IObs *caller)
00083 {
00084         CQuadGridClipCluster    *cluster= (CQuadGridClipCluster*)Model;
00085         CClipTrav                       *clipTrav= (CClipTrav*)Trav;
00086 
00087         // if empty, just return (not visible at all).
00088         if(cluster->_Empty)
00089         {
00090                 /* reset cache, to be sure that any instances added to this cluster later will 
00091                         be correctly updated if a clip of this cluster occurs.
00092                 */
00093                 _LastClipWasDistMaxClip= false;
00094                 _LastClipWasFrustumClip= false;
00095                 return;
00096         }
00097 
00098         // First, clip DistMax.
00099         CAABBox         &bbox= cluster->_BBox;
00100         // if clip DistMax enabled
00101         if(cluster->_DistMax!=-1)
00102         {
00103                 CVector         c= bbox.getCenter();
00104                 float           dist= (c - clipTrav->CamPos).norm();
00105                 // it the bbox is entirely out the distMax
00106                 if( dist-cluster->_Radius > cluster->_DistMax )
00107                 {
00108                         // if the cluster was DistMax-visible at last frame
00109                         if( !_LastClipWasDistMaxClip )
00110                         {
00111                                 // Advert sons of the clip. Important for CMeshMultiLodInstace. Do it for me and my sons.
00112                                 forceClip(IBaseClipObs::DistMaxClip);
00113                                 // new state.
00114                                 _LastClipWasDistMaxClip= true;
00115                         }
00116                         // quit
00117                         return;
00118                 }
00119                 else
00120                 {
00121                         // reset.
00122                         _LastClipWasDistMaxClip= false;
00123                 }
00124         }
00125 
00126         // Then clip against pyramid
00127         bool    unspecified= false;
00128         bool    visible= true;
00129         for(sint i=0;i<(sint)clipTrav->WorldPyramid.size();i++)
00130         {
00131                 // We are sure that pyramid has normalized plane normals.
00132                 if(!bbox.clipBack(clipTrav->WorldPyramid[i]))
00133                 {
00134                         visible= false;
00135                         break;
00136                 }
00137                 // else test is the bbox is partially or fully in the plane
00138                 else if(!unspecified)
00139                 {
00140                         // if clipFront AND clipBack, it means partially.
00141                         if(bbox.clipFront(clipTrav->WorldPyramid[i]))
00142                                 unspecified= true;
00143                 }
00144         }
00145 
00146         // if ! visible at all, just skip sons.
00147         if(!visible)
00148         {
00149                 // if the cluster was frustum visible at last frame
00150                 if( !_LastClipWasFrustumClip )
00151                 {
00152                         // Advert sons of the clip. Do it for me and my sons.
00153                         forceClip(IBaseClipObs::FrustumClip);
00154                         // new state.
00155                         _LastClipWasFrustumClip= true;
00156                 }
00157         }
00158         else
00159         {
00160                 // reset frustum clip cache.
00161                 _LastClipWasFrustumClip= false;
00162 
00163                 // clip sons.
00164                 if(unspecified)
00165                 {
00166                         // clip the sons individually 
00167                         traverseSons();
00168                 }
00169                 else
00170                 {
00171                         // udpdate the sons, but don't clip, because we know they are fully visible.
00172                         clipTrav->ForceNoFrustumClip= true;
00173                         traverseSons();
00174                         clipTrav->ForceNoFrustumClip= false;
00175                 }
00176         }
00177 }
00178 
00179 
00180 } // NL3D