# 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  

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/cluster.h"
00029 #include "3d/portal.h"
00030 #include "nel/misc/stream.h"
00031 #include "3d/scene.h"
00032 #include "3d/transform_shape.h"
00033 #include "3d/mesh_instance.h"
00034 #include "3d/scene_group.h"
00035 
00036 using namespace NLMISC;
00037 using namespace std;
00038 
00039 namespace NL3D 
00040 {
00041 
00042 // 0.5 cm of precision
00043 #define CLUSTERPRECISION 0.005
00044 
00045 
00046 // ***************************************************************************
00047 CCluster::CCluster ()
00048 {
00049         _Obs = NULL;
00050         FatherVisible = VisibleFromFather = false;
00051         Father = NULL;
00052 }
00053 
00054 
00055 // ***************************************************************************
00056 CCluster::~CCluster()
00057 {
00058         unlinkFromClusterTree();
00059 }
00060 
00061 
00062 // ***************************************************************************
00063 void CCluster::unlinkFromParent()
00064 {
00065         // unlink from father sons list
00066         if (Father)
00067         {
00068                  Father->Children.erase(std::remove(Father->Children.begin(), Father->Children.end(), this), Father->Children.end());
00069                  Father = NULL;
00070         }
00071 }
00072 
00073 // ***************************************************************************
00074 void CCluster::unlinkSons()
00075 {
00076         // tells all sons that they have no more father
00077         for(uint k = 0; k < Children.size(); ++k)
00078         {
00079                 if (Children[k]->Father == this)
00080                 {
00081                         Children[k]->Father = NULL;
00082                 }
00083         }
00084         NLMISC::contReset(Children);
00085 }
00086 
00087 
00088 
00089 // ***************************************************************************
00090 void CCluster::unlinkFromClusterTree()
00091 {
00092         unlinkFromParent();
00093         unlinkSons();   
00094 }
00095 
00096 
00097 
00098 // ***************************************************************************
00099 void CCluster::registerBasic ()
00100 {
00101         CMOT::registerModel (ClusterId, 0, CCluster::creator);
00102         CMOT::registerObs (ClipTravId, ClusterId, CClusterClipObs::creator);
00103         CMOT::registerObs (HrcTravId, ClusterId, CClusterHrcObs::creator);
00104 }
00105 
00106 // ***************************************************************************
00107 bool CCluster::makeVolume (CVector& p1, CVector& p2, CVector& p3)
00108 {
00109         uint i;
00110         // Check if the plane is not close to a plane that already define the cluster
00111         for (i = 0; i < _LocalVolume.size(); ++i)
00112         {
00113                 float f1 = fabsf (_LocalVolume[i]*p1);
00114                 float f2 = fabsf (_LocalVolume[i]*p2);
00115                 float f3 = fabsf (_LocalVolume[i]*p3);
00116                 if ((f1 < CLUSTERPRECISION) && (f2 < CLUSTERPRECISION) && (f3 < CLUSTERPRECISION))
00117                         return true;
00118         }
00119         // Check if we want to add a triangle not completely in the predefined volume
00120         for (i = 0; i < _LocalVolume.size(); ++i)
00121         {
00122                 float f1 = _LocalVolume[i]*p1;
00123                 float f2 = _LocalVolume[i]*p2;
00124                 float f3 = _LocalVolume[i]*p3;
00125                 if ((f1 > CLUSTERPRECISION) && (f2 > CLUSTERPRECISION) && (f3 > CLUSTERPRECISION))
00126                         return false;
00127         }
00128         // Build volume
00129         CPlane p;
00130         p.make (p1, p2, p3);
00131         p.normalize();
00132         _LocalVolume.push_back (p);
00133         // Build BBox   
00134         if (_LocalVolume.size() == 1)
00135                 _LocalBBox.setCenter(p1);
00136         else
00137                 _LocalBBox.extend(p1);
00138         _LocalBBox.extend(p2);
00139         _LocalBBox.extend(p3);
00140         _Volume = _LocalVolume;
00141         _BBox = _LocalBBox;
00142         return true;
00143 }
00144 
00145 // ***************************************************************************
00146 bool CCluster::isIn (CVector& p)
00147 {
00148         for (uint i = 0; i < _Volume.size(); ++i)
00149                 if (_Volume[i]*p > CLUSTERPRECISION)
00150                         return false;
00151         return true;
00152 }
00153 
00154 
00155 // ***************************************************************************
00156 bool CCluster::isIn (CAABBox& b)
00157 {
00158         for (uint i = 0; i < _Volume.size(); ++i)
00159         {
00160                 if (!b.clipBack (_Volume[i]))
00161                         return false;
00162         }
00163         return true;
00164 }
00165 
00166 // ***************************************************************************
00167 bool CCluster::isIn (NLMISC::CVector& center, float size)
00168 {
00169         for (uint i = 0; i < _Volume.size(); ++i)
00170                 if (_Volume[i]*center > size)
00171                         return false;
00172         return true;
00173 }
00174 
00175 // ***************************************************************************
00176 void CCluster::resetPortalLinks ()
00177 {
00178         _Portals.clear();
00179 }
00180 
00181 // ***************************************************************************
00182 void CCluster::link (CPortal* portal)
00183 {
00184         _Portals.push_back (portal);
00185 }
00186 
00187 // ***************************************************************************
00188 void CCluster::unlink (CPortal* portal)
00189 {
00190         uint32 pos;
00191         for (pos = 0; pos < _Portals.size(); ++pos)
00192         {
00193                 if (_Portals[pos] == portal)
00194                         break;
00195         }
00196         if (pos < _Portals.size())
00197                 _Portals.erase (_Portals.begin()+pos);
00198 }
00199 
00200 // ***************************************************************************
00201 void CCluster::serial (IStream&f)
00202 {
00203         sint version = f.serialVersion (1);
00204 
00205         if (version >= 1)
00206                 f.serial (Name);
00207         
00208         f.serialCont (_LocalVolume);
00209         f.serial (_LocalBBox);
00210         f.serial (FatherVisible);
00211         f.serial (VisibleFromFather);
00212         if (f.isReading())
00213         {
00214                 _Volume = _LocalVolume;
00215                 _BBox = _LocalBBox;
00216         }
00217 }
00218 
00219 // ***************************************************************************
00220 void CCluster::setWorldMatrix (const CMatrix &WM)
00221 {
00222         uint32 i;
00223         CMatrix invWM = WM;
00224         invWM.invert();
00225 
00226         // Transform the volume
00227         for (i = 0; i < _LocalVolume.size(); ++i)
00228                 _Volume[i] = _LocalVolume[i] * invWM;
00229 
00230         _BBox = NLMISC::CAABBox::transformAABBox(WM, _LocalBBox);
00231 
00232         // Transform the bounding box
00233         /*CVector p[8];
00234         p[0].x = _LocalBBox.getMin().x;
00235         p[0].y = _LocalBBox.getMin().y;
00236         p[0].z = _LocalBBox.getMin().z;
00237 
00238         p[1].x = _LocalBBox.getMax().x;
00239         p[1].y = _LocalBBox.getMin().y;
00240         p[1].z = _LocalBBox.getMin().z;
00241 
00242         p[2].x = _LocalBBox.getMin().x;
00243         p[2].y = _LocalBBox.getMax().y;
00244         p[2].z = _LocalBBox.getMin().z;
00245 
00246         p[3].x = _LocalBBox.getMax().x;
00247         p[3].y = _LocalBBox.getMax().y;
00248         p[3].z = _LocalBBox.getMin().z;
00249 
00250         p[4].x = _LocalBBox.getMin().x;
00251         p[4].y = _LocalBBox.getMin().y;
00252         p[4].z = _LocalBBox.getMax().z;
00253 
00254         p[5].x = _LocalBBox.getMax().x;
00255         p[5].y = _LocalBBox.getMin().y;
00256         p[5].z = _LocalBBox.getMax().z;
00257 
00258         p[6].x = _LocalBBox.getMin().x;
00259         p[6].y = _LocalBBox.getMax().y;
00260         p[6].z = _LocalBBox.getMax().z;
00261 
00262         p[7].x = _LocalBBox.getMax().x;
00263         p[7].y = _LocalBBox.getMax().y;
00264         p[7].z = _LocalBBox.getMax().z;
00265 
00266         for (i = 0; i < 8; ++i)
00267                 p[i] = WM.mulPoint(p[i]);
00268 
00269         CAABBox boxTemp;
00270 
00271         boxTemp.setCenter(p[0]);
00272         for (i = 1; i < 8; ++i)
00273                 boxTemp.extend(p[i]);
00274         _BBox = boxTemp;*/
00275 }
00276 
00277 // ***************************************************************************
00278 CClusterClipObs *CCluster::getClipObs()
00279 {
00280         if (_Obs == NULL)
00281                 _Obs = (CClusterClipObs*)getObs (ClipTravId);
00282         return _Obs;
00283 }
00284 
00285 // ---------------------------------------------------------------------------
00286 // Observer HRC
00287 // ---------------------------------------------------------------------------
00288 
00289 // ***************************************************************************
00290 void CClusterHrcObs::traverse (IObs *caller)
00291 {
00292         CTransformHrcObs::traverse (caller);
00293 
00294         CCluster *pCluster = static_cast<CCluster*>(this->Model);
00295 
00296         pCluster->setWorldMatrix (WorldMatrix);
00297 
00298         for (uint32 i = 0; i < pCluster->getNbPortals(); ++i)
00299         {
00300                 CPortal *pPortal = pCluster->getPortal(i);
00301                 pPortal->setWorldMatrix (WorldMatrix);
00302         }
00303 
00304         // Re affect the cluster to the accelerator if not the root
00305         if (!pCluster->isRoot())
00306         {
00307                 pCluster->Group->_ClipTrav->Accel.erase (pCluster->AccelIt);
00308                 pCluster->Group->_ClipTrav->registerCluster (pCluster);
00309         }
00310 }
00311 
00312 // ---------------------------------------------------------------------------
00313 // Observer CLIP
00314 // ---------------------------------------------------------------------------
00315 
00316 // ***************************************************************************
00317 CClusterClipObs::CClusterClipObs ()
00318 {
00319         Visited = false;
00320 }
00321 
00322 // ***************************************************************************
00323 bool CClusterClipObs::clip (IBaseClipObs *caller)
00324 {
00325         return true;
00326 }
00327 
00328 // ***************************************************************************
00329 void CClusterClipObs::traverse (IObs *caller)
00330 {
00331         nlassert(!caller || dynamic_cast<IBaseClipObs*>(caller));
00332 
00333         if (Visited)
00334                 return;
00335         Visited = true;
00336         // The cluster is visible because we are in it
00337         // So clip the models attached (with MOT links) to the cluster
00338         traverseSons();
00339 
00340         // And look through portals
00341         CCluster *pCluster = static_cast<CCluster*>(this->Model);
00342         uint32 i;
00343         for (i = 0; i < pCluster->getNbPortals(); ++i)
00344         {
00345                 CPortal*pPortal = pCluster->getPortal (i);
00346                 vector<CPlane> WorldPyrTemp = (static_cast<CClipTrav*>(Trav))->WorldPyramid;
00347                 bool backfaceclipped = false;
00348                 CCluster *pOtherSideCluster;
00349                 if (pPortal->getCluster(0) == pCluster)
00350                         pOtherSideCluster = pPortal->getCluster (1);
00351                 else
00352                         pOtherSideCluster = pPortal->getCluster (0);
00353 
00354                 if (pCluster->Father != NULL)
00355                 if (caller == pCluster->Father->getClipObs()) // If the caller is the father
00356                 if (pCluster->VisibleFromFather)
00357                         // Backface clipping
00358                         if( !pPortal->isInFront( (static_cast<CClipTrav*>(Trav))->CamPos ))
00359                                 backfaceclipped = true;
00360 
00361                 if (!backfaceclipped)
00362                 if (pPortal->clipPyramid ((static_cast<CClipTrav*>(Trav))->CamPos,
00363                                                                 (static_cast<CClipTrav*>(Trav))->WorldPyramid))
00364                 {
00365                         CClusterClipObs *pObserver = pOtherSideCluster->getClipObs();
00366                         pObserver->traverse (this);
00367                 }
00368 
00369                 (static_cast<CClipTrav*>(Trav))->WorldPyramid = WorldPyrTemp;
00370         }
00371 
00372         // Link up in hierarchy
00373         if ((pCluster->FatherVisible)&&(pCluster->Father != NULL))
00374         {
00375                 CClusterClipObs *pObserver = pCluster->Father->getClipObs();
00376                 pObserver->traverse (this);
00377         }
00378 
00379         // Link down in hierarchy
00380         for (i = 0; i < pCluster->Children.size(); ++i)
00381         if (pCluster->Children[i]->VisibleFromFather)
00382         {
00383                 CClusterClipObs *pObserver = pCluster->Children[i]->getClipObs();
00384                 pObserver->traverse (this);
00385         }
00386 
00387         Visited = false;
00388 }
00389 
00390 
00391 // ***************************************************************************
00392 void CCluster::applyMatrix(const NLMISC::CMatrix &m)
00393 {
00394         uint32 i;
00395         CMatrix invM = m;
00396         invM.invert();
00397         nlassert(_Volume.size() == _LocalVolume.size());
00398 
00399         // Transform the volume
00400         for (i = 0; i < _LocalVolume.size(); ++i)
00401         {       
00402                 _Volume[i] = _Volume[i] * invM;
00403                 _LocalVolume[i] = _LocalVolume[i] * invM;
00404         }
00405 
00406         // Transform the bounding boxes 
00407         _BBox = NLMISC::CAABBox::transformAABBox(m, _BBox);
00408         _LocalBBox = NLMISC::CAABBox::transformAABBox(m, _LocalBBox);   
00409 }
00410 
00411 
00412 } // NL3D