00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
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
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
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
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
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
00129 CPlane p;
00130 p.make (p1, p2, p3);
00131 p.normalize();
00132 _LocalVolume.push_back (p);
00133
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
00227 for (i = 0; i < _LocalVolume.size(); ++i)
00228 _Volume[i] = _LocalVolume[i] * invWM;
00229
00230 _BBox = NLMISC::CAABBox::transformAABBox(WM, _LocalBBox);
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 }
00276
00277
00278 CClusterClipObs *CCluster::getClipObs()
00279 {
00280 if (_Obs == NULL)
00281 _Obs = (CClusterClipObs*)getObs (ClipTravId);
00282 return _Obs;
00283 }
00284
00285
00286
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
00305 if (!pCluster->isRoot())
00306 {
00307 pCluster->Group->_ClipTrav->Accel.erase (pCluster->AccelIt);
00308 pCluster->Group->_ClipTrav->registerCluster (pCluster);
00309 }
00310 }
00311
00312
00313
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
00337
00338 traverseSons();
00339
00340
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())
00356 if (pCluster->VisibleFromFather)
00357
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
00373 if ((pCluster->FatherVisible)&&(pCluster->Father != NULL))
00374 {
00375 CClusterClipObs *pObserver = pCluster->Father->getClipObs();
00376 pObserver->traverse (this);
00377 }
00378
00379
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
00400 for (i = 0; i < _LocalVolume.size(); ++i)
00401 {
00402 _Volume[i] = _Volume[i] * invM;
00403 _LocalVolume[i] = _LocalVolume[i] * invM;
00404 }
00405
00406
00407 _BBox = NLMISC::CAABBox::transformAABBox(m, _BBox);
00408 _LocalBBox = NLMISC::CAABBox::transformAABBox(m, _LocalBBox);
00409 }
00410
00411
00412 }