# 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  

scene_group.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/scene_group.h"
00029 #include "nel/misc/stream.h"
00030 #include "nel/misc/matrix.h"
00031 #include "3d/scene.h"
00032 #include "3d/transform_shape.h"
00033 #include "3d/mesh_instance.h"
00034 #include "3d/shape_bank.h"
00035 #include "nel/3d/u_instance_group.h"
00036 
00037 using namespace NLMISC;
00038 using namespace std;
00039 
00040 namespace NL3D 
00041 {
00042 
00043 // ---------------------------------------------------------------------------
00044 // CInstance
00045 // ---------------------------------------------------------------------------
00046 
00047 // ***************************************************************************
00048 CInstanceGroup::CInstance::CInstance ()
00049 {
00050         DontAddToScene = false;
00051         AvoidStaticLightPreCompute= false;
00052         StaticLightEnabled= false;
00053         DontCastShadow= false;
00054         LocalAmbientId= 0xFF;
00055 }
00056 
00057 // ***************************************************************************
00058 void CInstanceGroup::CInstance::serial (NLMISC::IStream& f)
00059 {
00060         /*
00061         Version 4:
00062                 - LocalAmbientId.
00063         Version 3:
00064                 - StaticLight.
00065         Version 2:
00066                 - gameDev data.
00067         Version 1:
00068                 - Clusters
00069         */
00070         // Serial a version number
00071         sint version=f.serialVersion (4);
00072 
00073 
00074         // Serial the LocalAmbientId.
00075         if (version >= 4)
00076         {
00077                 f.serial(LocalAmbientId);
00078         }
00079         else if(f.isReading())
00080         {
00081                 LocalAmbientId= 0xFF;
00082         }
00083 
00084         // Serial the StaticLight
00085         if (version >= 3)
00086         {
00087                 f.serial (AvoidStaticLightPreCompute);
00088                 f.serial (DontCastShadow);
00089                 f.serial (StaticLightEnabled);
00090                 f.serial (SunContribution);
00091                 nlassert(CInstanceGroup::NumStaticLightPerInstance==2);
00092                 f.serial (Light[0]);
00093                 f.serial (Light[1]);
00094         }
00095         else if(f.isReading())
00096         {
00097                 AvoidStaticLightPreCompute= false;
00098                 StaticLightEnabled= false;
00099                 DontCastShadow= false;
00100         }
00101 
00102         // Serial the gamedev data
00103         if (version >= 2)
00104         {
00105                 f.serial (InstanceName);
00106                 f.serial (DontAddToScene);
00107         }
00108 
00109         // Serial the clusters
00110         if (version >= 1)
00111                 f.serialCont (Clusters);
00112 
00113         // Serial the name
00114         f.serial (Name);
00115 
00116         // Serial the position vector
00117         f.serial (Pos);
00118 
00119         // Serial the rotation vector
00120         f.serial (Rot);
00121 
00122         // Serial the scale vector
00123         f.serial (Scale);
00124 
00125         // Serial the parent location in the vector (-1 if no parent)
00126         f.serial (nParent);
00127 }
00128 
00129 // ---------------------------------------------------------------------------
00130 // CInstanceGroup
00131 // ---------------------------------------------------------------------------
00132 
00133 // ***************************************************************************
00134 
00135 uint CInstanceGroup::getNumInstance () const
00136 {
00137         return _InstancesInfos.size();
00138 }
00139 
00140 // ***************************************************************************
00141 
00142 const string& CInstanceGroup::getShapeName (uint instanceNb) const
00143 {
00144         // Return the name of the n-th instance
00145         return _InstancesInfos[instanceNb].Name;
00146 }
00147 
00148 // ***************************************************************************
00149 
00150 const string& CInstanceGroup::getInstanceName (uint instanceNb) const
00151 {
00152         // Return the name of the n-th instance
00153         return _InstancesInfos[instanceNb].InstanceName;
00154 }
00155 
00156 // ***************************************************************************
00157 
00158 const CVector& CInstanceGroup::getInstancePos (uint instanceNb) const
00159 {
00160         // Return the position vector of the n-th instance
00161         return _InstancesInfos[instanceNb].Pos;
00162 }
00163 
00164 // ***************************************************************************
00165 
00166 const CQuat& CInstanceGroup::getInstanceRot (uint instanceNb) const
00167 {
00168         // Return the rotation vector of the n-th instance
00169         return _InstancesInfos[instanceNb].Rot;
00170 }
00171 
00172 // ***************************************************************************
00173 
00174 const CVector& CInstanceGroup::getInstanceScale (uint instanceNb) const
00175 {
00176         // Return the scale vector of the n-th instance
00177         return _InstancesInfos[instanceNb].Scale;
00178 }
00179 
00180 // ***************************************************************************
00181 
00182 void CInstanceGroup::getInstanceMatrix(uint instanceNb,NLMISC::CMatrix &dest) const
00183 {
00184         dest.identity();        
00185         dest.translate(getInstancePos(instanceNb));
00186         dest.rotate(getInstanceRot(instanceNb));
00187         dest.scale(getInstanceScale(instanceNb));       
00188 }
00189 
00190         
00191 
00192 // ***************************************************************************
00193 
00194 const sint32 CInstanceGroup::getInstanceParent (uint instanceNb) const
00195 {
00196         // Return the scale vector of the n-th instance
00197         return _InstancesInfos[instanceNb].nParent;
00198 }
00199 
00200 
00201 // ***************************************************************************
00202 const CInstanceGroup::CInstance         &CInstanceGroup::getInstance(uint instanceNb) const
00203 {
00204         return _InstancesInfos[instanceNb];
00205 }
00206 
00207 // ***************************************************************************
00208 CInstanceGroup::CInstance               &CInstanceGroup::getInstance(uint instanceNb)
00209 {
00210         return _InstancesInfos[instanceNb];
00211 }
00212 
00213 // ***************************************************************************
00214 CTransformShape                         *CInstanceGroup::getTransformShape(uint instanceNb) const
00215 {
00216         if(instanceNb>_Instances.size())
00217                 return NULL;
00218         return _Instances[instanceNb];
00219 }
00220 
00221 // ***************************************************************************
00222 CInstanceGroup::CInstanceGroup()
00223 {
00224         _IGSurfaceLight.setOwner(this);
00225         _GlobalPos = CVector(0,0,0);
00226         _Root = NULL;
00227         _ClusterSystem = NULL;
00228         _RealTimeSunContribution= true;
00229         _AddToSceneState = StateNotAdded;
00230         _TransformName = NULL;
00231         _AddRemoveInstance = NULL;
00232         _IGAddBeginCallback = NULL;
00233 }
00234 
00235 // ***************************************************************************
00236 CInstanceGroup::~CInstanceGroup()
00237 {
00238 }
00239 
00240 // ***************************************************************************
00241 void CInstanceGroup::build (const CVector &vGlobalPos, const TInstanceArray& array, 
00242                                                         const std::vector<CCluster>& Clusters, 
00243                                                         const std::vector<CPortal>& Portals,
00244                                                         const std::vector<CPointLightNamed> &pointLightList,
00245                                                         const CIGSurfaceLight::TRetrieverGridMap *retrieverGridMap, 
00246                                                         float igSurfaceLightCellSize)
00247 {
00248         _GlobalPos = vGlobalPos;
00249         // Copy the array
00250         _InstancesInfos = array;
00251 
00252         _Portals = Portals;
00253         _ClusterInfos = Clusters;
00254 
00255         // Link portals and clusters
00256         uint32 i, j, k;
00257         for (i = 0; i < _Portals.size(); ++i)
00258         {
00259                 for (j = 0; j < _ClusterInfos.size(); ++j)
00260                 {
00261                         bool bPortalInCluster = true;
00262                         for (k = 0; k < _Portals[i]._Poly.size(); ++k)
00263                                 if (!_ClusterInfos[j].isIn (_Portals[i]._Poly[k]) )
00264                                 {
00265                                         bPortalInCluster = false;
00266                                         break;
00267                                 }
00268                         if (bPortalInCluster)
00269                         {                               
00270                                 _Portals[i].setCluster(&_ClusterInfos[j]);
00271                                 _ClusterInfos[j].link (&_Portals[i]);
00272                         }
00273                 }
00274         }
00275 
00276         // Create Meta Cluster if needed
00277         /*
00278         CCluster clusterTemp;
00279         bool mustAdd = false;
00280         for (i = 0; i < _Portals.size(); ++i)
00281         if (_Portals[i].getNbCluster() == 1)
00282         {
00283                 mustAdd = true;
00284                 break;
00285         }
00286         if (mustAdd)
00287         {
00288                 CCluster clusterTemp;
00289                 _ClusterInfos.push_back(clusterTemp);
00290                 CCluster *pMetaCluster = &_ClusterInfos[_ClusterInfos.size()-1];
00291                 pMetaCluster->setMetaCluster();
00292                 for (i = 0; i < _Portals.size(); ++i)
00293                 if (_Portals[i].getNbCluster() == 1)
00294                 {
00295                         _Portals[i].setCluster(pMetaCluster);
00296                         pMetaCluster->link(&_Portals[i]);
00297                 }
00298         }*/
00299 
00300 
00301         // Build the list of light. NB: sort by LightGroupName the array.
00302         std::vector<uint>       plRemap;
00303         buildPointLightList(pointLightList, plRemap);
00304 
00305         // Build IgSurfaceLight
00306         // clear
00307         _IGSurfaceLight.clear();
00308         if(retrieverGridMap)
00309         {
00310                 //build
00311                 _IGSurfaceLight.build(*retrieverGridMap, igSurfaceLightCellSize, plRemap);
00312         }
00313 }
00314 
00315 
00316 // ***************************************************************************
00317 void CInstanceGroup::build (const CVector &vGlobalPos, const TInstanceArray& array, 
00318                                                         const std::vector<CCluster>& Clusters, 
00319                                                         const std::vector<CPortal>& Portals)
00320 {
00321         // empty pointLightList
00322         std::vector<CPointLightNamed> pointLightList;
00323 
00324         build(vGlobalPos, array, Clusters, Portals, pointLightList);
00325 }
00326 
00327 
00328 // ***************************************************************************
00329 void CInstanceGroup::retrieve (CVector &vGlobalPos, TInstanceArray& array, 
00330                                 std::vector<CCluster>& Clusters, 
00331                                 std::vector<CPortal>& Portals,
00332                                 std::vector<CPointLightNamed> &pointLightList) const
00333 {
00334         // Just copy infos. NB: light information order have change but is still valid
00335         vGlobalPos= _GlobalPos;
00336         array= _InstancesInfos;
00337 
00338         Portals= _Portals;
00339         Clusters= _ClusterInfos;
00340         // Must reset links to all portals and clusters.
00341         uint    i;
00342         for(i=0; i<Portals.size(); i++)
00343                 Portals[i].resetClusterLinks();
00344         for(i=0; i<Clusters.size(); i++)
00345                 Clusters[i].resetPortalLinks();
00346 
00347 
00348         pointLightList= getPointLightList();
00349 }
00350 
00351 
00352 // ***************************************************************************
00353 
00354 void CInstanceGroup::serial (NLMISC::IStream& f)
00355 {
00356         // Serial a header
00357         f.serialCheck ((uint32)'TPRG');
00358 
00359         /*
00360         Version 5:
00361                 _ _RealTimeSunContribution
00362         Version 4:
00363                 _ IGSurfaceLight
00364         Version 3:
00365                 - PointLights
00366         */
00367         // Serial a version number
00368         sint version=f.serialVersion (5);
00369 
00370 
00371         // _RealTimeSunContribution
00372         if (version >= 5)
00373         {
00374                 f.serial(_RealTimeSunContribution);
00375         }
00376         else if(f.isReading())
00377         {
00378                 _RealTimeSunContribution= true;
00379         }
00380 
00381 
00382         // Serial the IGSurfaceLight
00383         if (version >= 4)
00384         {
00385                 f.serial(_IGSurfaceLight);
00386         }
00387         else if(f.isReading())
00388         {
00389                 _IGSurfaceLight.clear();
00390         }
00391 
00392 
00393         // Serial the PointLights info
00394         if (version >= 3)
00395         {
00396                 f.serial(_PointLightArray);
00397         }
00398         else if(f.isReading())
00399         {
00400                 _PointLightArray.clear();
00401         }
00402 
00403 
00404         if (version >= 2)
00405                 f.serial(_GlobalPos);
00406 
00407         if (version >= 1)
00408         {
00409                 f.serialCont (_ClusterInfos);
00410                 f.serialCont (_Portals);
00411                 // Links
00412                 if (f.isReading())
00413                 {
00414                         uint32 i, j;
00415                         for (i = 0; i < _ClusterInfos.size(); ++i)
00416                         {
00417                                 uint32 nNbPortals;
00418                                 f.serial (nNbPortals);
00419                                 _ClusterInfos[i]._Portals.resize (nNbPortals);
00420                                 // Recreate clusters to portals links
00421                                 for (j = 0; j < nNbPortals; ++j)
00422                                 {
00423                                         sint32 nPortalNb;
00424                                         f.serial (nPortalNb);
00425                                         _ClusterInfos[i]._Portals[j] = &_Portals[nPortalNb];
00426                                         _Portals[nPortalNb].setCluster (&_ClusterInfos[i]);
00427                                 }
00428                         }
00429                 }
00430                 else // We are writing to the stream
00431                 {
00432                         uint32 i, j;
00433                         for (i = 0; i < _ClusterInfos.size(); ++i)
00434                         {
00435                                 uint32 nNbPortals = _ClusterInfos[i]._Portals.size();
00436                                 f.serial (nNbPortals);
00437                                 for (j = 0; j < nNbPortals; ++j)
00438                                 {
00439                                         sint32 nPortalNb = (_ClusterInfos[i]._Portals[j] - &_Portals[0]);
00440                                         f.serial (nPortalNb);
00441                                 }
00442                         }
00443                 }
00444         }
00445 
00446         // Serial the array
00447         f.serialCont (_InstancesInfos);
00448 }
00449 
00450 // ***************************************************************************
00451 void CInstanceGroup::createRoot (CScene& scene)
00452 {
00453         _Root = (CTransform*)scene.createModel (TransformId);
00454         _Root->setDontUnfreezeChildren (true);
00455         setPos (CVector(0,0,0));
00456 }
00457 
00458 // ***************************************************************************
00459 void CInstanceGroup::setTransformNameCallback (ITransformName *pTN)
00460 {
00461         _TransformName = pTN;
00462 }
00463 
00464 
00465 // ***************************************************************************
00466 void CInstanceGroup::setAddRemoveInstanceCallback(IAddRemoveInstance *callback)
00467 {
00468         _AddRemoveInstance = callback;
00469 }
00470 
00471 // ***************************************************************************
00472 void CInstanceGroup::setIGAddBeginCallback(IIGAddBegin *callback)
00473 {
00474         _IGAddBeginCallback = callback;
00475 }
00476 
00477 // ***************************************************************************
00478 bool CInstanceGroup::addToScene (CScene& scene, IDriver *driver)
00479 {
00480         uint32 i;
00481 
00482         _Instances.resize (_InstancesInfos.size(), NULL);
00483 
00484         if (_IGAddBeginCallback)
00485                 _IGAddBeginCallback->startAddingIG(_InstancesInfos.size());
00486 
00487         // Creation and positionning of the new instance
00488 
00489         vector<CInstance>::iterator it = _InstancesInfos.begin();
00490 
00491         for (i = 0; i < _InstancesInfos.size(); ++i, ++it)
00492         {
00493                 CInstance &rInstanceInfo = *it;
00494                 if (!rInstanceInfo.DontAddToScene)
00495                 {
00496                         string shapeName;
00497                         
00498                         bool getShapeName = true;
00499                         
00500                         // If there is a callback added to this instance group then transform
00501                         // the name of the shape to load.
00502                         if (_TransformName != NULL && !rInstanceInfo.InstanceName.empty())
00503                         {                                                                                               
00504                                 shapeName = _TransformName->transformName (i, rInstanceInfo.InstanceName);                                                              
00505                                 if (!shapeName.empty())
00506                                         getShapeName = false;
00507                         }
00508                         
00509                         if (getShapeName)
00510                         {                       
00511                                 if (rInstanceInfo.Name.find('.') == std::string::npos)
00512                                 {
00513                                         shapeName = rInstanceInfo.Name + ".shape";
00514                                 }
00515                                 else    // extension has already been added
00516                                 {
00517                                         shapeName = rInstanceInfo.Name;
00518                                 }
00519                         }
00520                         strlwr (shapeName);
00521 
00522                                         
00523                         _Instances[i] = scene.createInstance (shapeName);
00524                         if( _Instances[i] == NULL )
00525                         {
00526                                 
00527                                 nlwarning("Not found '%s' file\n", shapeName.c_str());
00528                                 //#if defined(NL_DEBUG) && defined(__STL_DEBUG)
00529                                 //      nlstop;
00530                                 //#endif
00531 
00532                                 /*
00533                                         for (uint32 j = 0; j < i; ++j)
00534                                         {
00535                                                 scene.deleteInstance(_Instances[j]);
00536                                                 _Instances[j] = NULL;
00537                                         }
00538                                         throw NLMISC::Exception("CInstanceGroup::addToScene : unable to create %s shape file", rInstanceInfo.Name.c_str());
00539                                 */
00540                         }
00541                 }
00542         }
00543 
00544         return addToSceneWhenAllShapesLoaded (scene, driver);
00545 }
00546 
00547 // ***************************************************************************
00548 // Private method
00549 bool CInstanceGroup::addToSceneWhenAllShapesLoaded (CScene& scene, IDriver *driver)
00550 {
00551         uint32 i, j;
00552         vector<CInstance>::iterator it = _InstancesInfos.begin();
00553         for (i = 0; i < _InstancesInfos.size(); ++i, ++it)
00554         {
00555                 CInstance &rInstanceInfo = *it;
00556 
00557                 if (!rInstanceInfo.DontAddToScene)
00558                 {
00559                         if (_Instances[i])
00560                         {
00561                                 _Instances[i]->setPos (rInstanceInfo.Pos);
00562                                 _Instances[i]->setRotQuat (rInstanceInfo.Rot);
00563                                 _Instances[i]->setScale (rInstanceInfo.Scale);
00564                                 _Instances[i]->setPivot (CVector::Null);
00565 
00566                                 // Static Light Setup
00567                                 if( rInstanceInfo.StaticLightEnabled )
00568                                 {
00569                                         // Count lights.
00570                                         uint numPointLights;
00571                                         for(numPointLights= 0; numPointLights<CInstanceGroup::NumStaticLightPerInstance; numPointLights++)
00572                                         {
00573                                                 if(rInstanceInfo.Light[numPointLights]==0xFF)
00574                                                         break;
00575                                         }
00576                                         // Max allowed.
00577                                         numPointLights= min(numPointLights, (uint)NL3D_MAX_LIGHT_CONTRIBUTION);
00578 
00579                                         // Get pl ptrs.
00580                                         CPointLight             *pls[CInstanceGroup::NumStaticLightPerInstance];
00581                                         for(uint j=0; j<numPointLights;j++)
00582                                         {
00583                                                 uint    plId= rInstanceInfo.Light[j];
00584                                                 pls[j]= (CPointLight*)(&_PointLightArray.getPointLights()[plId]);
00585                                         }
00586 
00587                                         // get frozenAmbientlight.
00588                                         CPointLight *frozenAmbientlight;
00589                                         if(rInstanceInfo.LocalAmbientId == 0xFF)
00590                                                 // must take the sun one.
00591                                                 frozenAmbientlight= NULL;
00592                                         else
00593                                                 // ok, take the local ambient one.
00594                                                 frozenAmbientlight= (CPointLight*)(&_PointLightArray.getPointLights()[rInstanceInfo.LocalAmbientId]);
00595 
00596                                         // Setup the instance.
00597                                         _Instances[i]->freezeStaticLightSetup(pls, numPointLights, rInstanceInfo.SunContribution, frozenAmbientlight);
00598                                 }
00599 
00600                                 // Driver not NULL ?
00601                                 if (driver)
00602                                 {
00603                                         // Flush shape's texture with this driver
00604                                         _Instances[i]->Shape->flushTextures (*driver);
00605                                 }
00606                         }
00607                 }
00608                 else
00609                 {
00610                         _Instances[i] = NULL;
00611                 }
00612         }
00613 
00614         // Setup the hierarchy
00615         // We just have to set the traversal HRC (Hierarchy)
00616         ITrav *pHrcTrav = scene.getTrav (HrcTravId);
00617 
00618         if (_Root == NULL)
00619         {
00620                 createRoot (scene);
00621         }
00622         it = _InstancesInfos.begin();
00623         for (i = 0; i < _InstancesInfos.size(); ++i, ++it)
00624         if (!_InstancesInfos[i].DontAddToScene && _Instances[i] != NULL)
00625         {
00626                 CInstance &rInstanceInfo = *it;
00627                 if( rInstanceInfo.nParent != -1 ) // Is the instance get a parent
00628                         pHrcTrav->link (_Instances[rInstanceInfo.nParent], _Instances[i]);
00629                 else
00630                         pHrcTrav->link (_Root, _Instances[i]);
00631         }
00632         // Attach the root of the instance group to the root of the hierarchy traversal
00633         pHrcTrav->link (NULL, _Root);
00634 
00635         // Cluster / Portals
00636         // -----------------
00637 
00638         CClipTrav *pClipTrav = (CClipTrav*)(scene.getTrav (ClipTravId));
00639         _ClipTrav = pClipTrav;
00640 
00641         // Create the MOT links (create the physical clusters)
00642         _ClusterInstances.resize (_ClusterInfos.size());
00643         for (i = 0; i < _ClusterInstances.size(); ++i)
00644         {
00645                 _ClusterInstances[i] = (CCluster*)scene.createModel (ClusterId);
00646                 _ClusterInstances[i]->Group = this;
00647                 _ClusterInstances[i]->_Portals = _ClusterInfos[i]._Portals;
00648                 _ClusterInstances[i]->_LocalVolume = _ClusterInfos[i]._LocalVolume;
00649                 _ClusterInstances[i]->_LocalBBox = _ClusterInfos[i]._LocalBBox;
00650                 _ClusterInstances[i]->_Volume = _ClusterInfos[i]._Volume;
00651                 _ClusterInstances[i]->_BBox = _ClusterInfos[i]._BBox;
00652                 _ClusterInstances[i]->FatherVisible = _ClusterInfos[i].FatherVisible;
00653                 _ClusterInstances[i]->VisibleFromFather = _ClusterInfos[i].VisibleFromFather;
00654                 _ClusterInstances[i]->Name = _ClusterInfos[i].Name;
00655                 pClipTrav->registerCluster (_ClusterInstances[i]);
00656                 pClipTrav->unlink (NULL, _ClusterInstances[i]);
00657         }
00658 
00659         // Relink portals with newly created clusters
00660         for (i = 0; i < _Portals.size(); ++i)
00661         for (j = 0; j < 2; ++j)
00662         {
00663                 sint32 nClusterNb;
00664                 nClusterNb = (_Portals[i]._Clusters[j] - &_ClusterInfos[0]);
00665                 _Portals[i]._Clusters[j] = _ClusterInstances[nClusterNb];
00666         }
00667 
00668         // Link shapes to clusters
00669         for (i = 0; i < _Instances.size(); ++i)
00670         if (_Instances[i] != NULL && !_InstancesInfos[i].DontAddToScene)
00671         {
00672                 if (_InstancesInfos[i].Clusters.size() > 0)
00673                 {
00674                         pClipTrav->unlink (NULL, _Instances[i]);
00675                         for (j = 0; j < _InstancesInfos[i].Clusters.size(); ++j)
00676                                 pClipTrav->link (_ClusterInstances[_InstancesInfos[i].Clusters[j]], _Instances[i]);
00677                         // For the first time we have to set all the instances to NOT move (and not be rebinded)
00678                         _Instances[i]->freeze();
00679                         _Instances[i]->setClusterSystem (this);
00680                 }
00681                 else
00682                 {
00683                         // These instances are not attached to a cluster at this level so we cannot freeze them
00684                         // Moreover we must set their clustersystem they will be tested against
00685                         _Instances[i]->setClusterSystem (_ClusterSystem);
00686                 }
00687         }
00688         _Root->freeze();
00689 
00690         // HRC OBS like
00691         for (i = 0; i < _ClusterInstances.size(); ++i)
00692         {
00693                 _ClusterInstances[i]->setWorldMatrix (_Root->getMatrix());
00694 
00695                 for (j = 0; j < _ClusterInstances[i]->getNbPortals(); ++j)
00696                 {
00697                         CPortal *pPortal = _ClusterInstances[i]->getPortal(j);
00698                         pPortal->setWorldMatrix (_Root->getMatrix());
00699                 }
00700 
00701                 // Re affect the cluster to the accelerator if not the root
00702                 if (!_ClusterInstances[i]->isRoot())
00703                 {
00704                         _ClipTrav->Accel.erase (_ClusterInstances[i]->AccelIt);
00705                         _ClipTrav->registerCluster (_ClusterInstances[i]);
00706                 }
00707         }
00708 
00709 
00710         // Link the instance group to the parent
00711         linkToParent (scene.getGlobalInstanceGroup());
00712 
00713         // Attach the clusters to the root of the instance group
00714         for (i = 0; i < _ClusterInstances.size(); ++i)
00715                 pHrcTrav->link (_Root, _ClusterInstances[i]);
00716 
00717 
00718         // Default: freezeHRC all instances.
00719         freezeHRC();
00720 
00721 
00722         // Register the instanceGroup for light animation
00723         // -----------------
00724         // If some PointLight to animate
00725         if(_PointLightArray.getPointLights().size() > 0)
00726                 scene.addInstanceGroupForLightAnimation(this);
00727 
00728         _AddToSceneState = StateAdded;
00729 
00730         if (_AddRemoveInstance)
00731                 _AddRemoveInstance->instanceGroupAdded();
00732         return true;
00733 }
00734 
00735 // ***************************************************************************
00736 bool CInstanceGroup::addToSceneAsync (CScene& scene, IDriver *driver)
00737 {
00738         uint32 i;
00739 
00740         _AddToSceneState = StateAdding;
00741         _AddToSceneTempScene = &scene;
00742         _AddToSceneTempDriver = driver;
00743 
00744         _Instances.resize (_InstancesInfos.size(), NULL);
00745 
00746         if (_IGAddBeginCallback)
00747                 _IGAddBeginCallback->startAddingIG(_InstancesInfos.size());
00748 
00749         // Creation and positionning of the new instance
00750 
00751         vector<CInstance>::iterator it = _InstancesInfos.begin();
00752         set<string> allShapesToLoad;
00753         _AddToSceneSignal = false;
00754         bool loadAsyncStarted = false;
00755         for (i = 0; i < _InstancesInfos.size(); ++i, ++it)
00756         {
00757                 CInstance &rInstanceInfo = *it;
00758                 if (!rInstanceInfo.DontAddToScene)
00759                 {
00760                         string shapeName;
00761                         bool   getShapeName = true;
00762 
00763                         if (_TransformName != NULL && !rInstanceInfo.InstanceName.empty())
00764                         {                                                                                               
00765                                 shapeName = _TransformName->transformName (i, rInstanceInfo.InstanceName);                                                              
00766                                 if (!shapeName.empty())
00767                                         getShapeName = false;
00768                         }
00769                         
00770 
00771                         if (getShapeName)
00772                         {                                               
00773                                 if (rInstanceInfo.Name.find('.') == std::string::npos)
00774                                 {
00775                                         shapeName = rInstanceInfo.Name + ".shape";
00776                                 }
00777                                 else    // extension has already been added
00778                                 {
00779                                         shapeName  = rInstanceInfo.Name;
00780                                 }
00781                         }
00782                         shapeName = strlwr (shapeName);
00783 
00784                         shapeName = strlwr (shapeName);
00785                         if (allShapesToLoad.find(shapeName) == allShapesToLoad.end())
00786                         {
00787                                 allShapesToLoad.insert (shapeName);
00788                                 if (scene.getShapeBank()->isPresent(shapeName) != CShapeBank::Present)
00789                                 {
00790                                         // Load it from file asynchronously
00791                                         scene.getShapeBank()->loadAsync (shapeName, scene.getDriver(), &_AddToSceneSignal);
00792                                         loadAsyncStarted = true;
00793                                 }
00794                         }
00795                 }
00796         }
00797         if (!loadAsyncStarted)
00798                 _AddToSceneSignal = true;
00799         else
00800                 _AddToSceneSignal = false;
00801         //CAsyncFileManager::getInstance().signal (&_AddToSceneSignal);
00802         return true;
00803 }
00804 
00805 // ***************************************************************************
00806 void CInstanceGroup::stopAddToSceneAsync ()
00807 {
00808         if (_AddToSceneState != StateAdding)
00809                 return;
00810         vector<CInstance>::iterator it = _InstancesInfos.begin();
00811         CAsyncFileManager::getInstance().cancelSignal (&_AddToSceneSignal);
00812         for (uint32 i = 0; i < _InstancesInfos.size(); ++i, ++it)
00813         {
00814                 CInstance &rInstanceInfo = *it;
00815                 if (!rInstanceInfo.DontAddToScene)
00816                 {
00817                         string shapeName;
00818 
00819 
00820                         bool getShapeName = true;
00821 
00822                         if (_TransformName != NULL && !rInstanceInfo.InstanceName.empty())
00823                         {                                                                                               
00824                                 shapeName = _TransformName->transformName (i, rInstanceInfo.InstanceName);                                                              
00825                                 if (!shapeName.empty())
00826                                         getShapeName = false;
00827                         }
00828 
00829                         
00830                         if (getShapeName)
00831                         {                       
00832                                 if (rInstanceInfo.Name.find('.') == std::string::npos)
00833                                         shapeName = rInstanceInfo.Name + ".shape";
00834                                 else    // extension has already been added
00835                                         shapeName  = rInstanceInfo.Name;
00836                         }
00837 
00838                         shapeName = strlwr (shapeName);
00839                         _AddToSceneTempScene->getShapeBank()->cancelLoadAsync (shapeName);
00840                 }
00841         }
00842         _AddToSceneState = StateNotAdded;
00843 }
00844 
00845 // ***************************************************************************
00846 CInstanceGroup::TState CInstanceGroup::getAddToSceneState ()
00847 {
00848         // If we are adding but we have finished loading shapes (all shapes are here)
00849         if (_AddToSceneState == StateAdding)
00850         {
00851                 if (_AddToSceneSignal)
00852                 {
00853                         addToScene (*_AddToSceneTempScene, _AddToSceneTempDriver);
00854                 }
00855         }
00856         return _AddToSceneState;
00857 }
00858 
00859 // ***************************************************************************
00860 // Search in the hierarchy of ig the most low level (child) ig that contains the clusters that
00861 // are flagged to be visible from father or which father is visible
00862 bool CInstanceGroup::linkToParent (CInstanceGroup *pFather)
00863 {               
00864         uint32 i, j;
00865         bool ret;
00866 
00867         
00868 
00869         for (i = 0; i < pFather->_ClusterInstances.size(); ++i)
00870         {
00871                 for(j = 0; j < pFather->_ClusterInstances[i]->Children.size(); ++j)
00872                 {
00873                         if (linkToParent(pFather->_ClusterInstances[i]->Children[j]->Group))
00874                                 return true;
00875                 }
00876         }       
00877         ret = false;
00878         if (this != pFather)
00879         {               
00880                 for (j = 0; j < this->_ClusterInstances.size(); ++j)
00881                 {
00882                         if ((this->_ClusterInstances[j]->FatherVisible) ||
00883                                 (this->_ClusterInstances[j]->VisibleFromFather))
00884                         {
00885                                 for (i = 0; i < pFather->_ClusterInstances .size(); ++i)
00886                                 {                       
00887                                         
00888                                         if (pFather->_ClusterInstances[i]->isIn(this->_ClusterInstances[j]->getBBox()))
00889                                         {
00890                                                 if (this->_ClusterInstances[j]->Father != pFather->_ClusterInstances[i]) // not already sons of the right cluster ?
00891                                                 {                                               
00892                                                         // unlink from parent
00893                                                         this->_ClusterInstances[j]->unlinkFromParent();
00894 
00895                                                         // relink in hierarchy
00896                                                         pFather->_ClusterInstances[i]->Children.push_back(this->_ClusterInstances[j]);
00897                                                         this->_ClusterInstances[j]->Father = pFather->_ClusterInstances[i];
00898                                                 }
00899                                                 ret = true;
00900                                         }
00901                                 }
00902                         }
00903                 }
00904         }
00905         return ret;
00906 }
00907 
00908 // ***************************************************************************
00909 bool CInstanceGroup::removeFromScene (CScene& scene)
00910 {
00911         uint32 i, j, k;
00912         // Remove shapes
00913         vector<CTransformShape*>::iterator it = _Instances.begin();
00914         for (i = 0; i < _InstancesInfos.size(); ++i, ++it)
00915         {
00916                 CTransformShape *pTShape = *it;
00917                 if(pTShape)
00918                 {
00919                         // For security, unfreeze any StaticLightSetup setuped.
00920                         pTShape->unfreezeStaticLightSetup();
00921                         // delete the instance
00922                         scene.deleteInstance (pTShape);
00923                         *it = NULL;
00924                 }
00925         }
00926 
00927         // Relink portals with old clusters
00928         for (i = 0; i < _Portals.size(); ++i)
00929         for (k = 0; k < 2; ++k)
00930         {
00931                 for (j = 0; j < _ClusterInstances.size(); ++j)
00932                         if( _Portals[i]._Clusters[k] == _ClusterInstances[j] )
00933                                 break;
00934 
00935                 nlassert (j!=_ClusterInstances.size());
00936                 _Portals[i]._Clusters[k] = &_ClusterInfos[j];
00937         }
00938 
00939         // Remove clusters
00940         CClipTrav *pClipTrav = (CClipTrav*)(scene.getTrav (ClipTravId));
00941         for (i = 0; i < _ClusterInstances.size(); ++i)
00942         {
00943                 pClipTrav->unregisterCluster (_ClusterInstances[i]);
00944                 scene.deleteModel (_ClusterInstances[i]);
00945         }
00946 
00947         scene.deleteModel (_Root);
00948         _Root = NULL;
00949 
00950 
00951         // UnRegister the instanceGroup for light animation
00952         // -----------------
00953         // If some PointLight to animate
00954         if(_PointLightArray.getPointLights().size() > 0)
00955                 scene.removeInstanceGroupForLightAnimation(this);
00956 
00957         if (_AddRemoveInstance)
00958                 _AddRemoveInstance->instanceGroupRemoved();
00959         return true;
00960 }
00961 
00962 
00963 // ***************************************************************************
00964 void CInstanceGroup::getLights( set<string> &LightNames )
00965 {
00966         LightNames.clear();
00967         for( uint32 i = 0; i < _Instances.size(); ++i )
00968         {
00969                 CMeshInstance *pMI = dynamic_cast<CMeshInstance*>(_Instances[i]);
00970                 if( pMI != NULL )
00971                 {
00972                         uint32 nNbLM = pMI->getNbLightMap();
00973                         for( uint32 j = 0; j < nNbLM; ++j )
00974                         {
00975                                 string sTmp;
00976                                 pMI->getLightMapName( j, sTmp );
00977                                 set<string>::iterator itSet =  LightNames.find(sTmp);
00978                                 if( itSet == LightNames.end() )
00979                                         LightNames.insert( sTmp );
00980                         }
00981                 }
00982         }
00983 }
00984 
00985 // ***************************************************************************
00986 void CInstanceGroup::setLightFactor( const string &LightName, CRGBA Factor )
00987 {
00988         for( uint32 i = 0; i < _Instances.size(); ++i )
00989         {
00990                 CMeshBaseInstance *pMI = dynamic_cast<CMeshBaseInstance*>(_Instances[i]);
00991                 if( pMI != NULL )
00992                 {
00993                         pMI->setLightMapFactor( LightName, Factor );
00994                 }
00995         }
00996 }
00997 
00998 // ***************************************************************************
00999 void CInstanceGroup::getBlendShapes( set<string> &BlendShapeNames )
01000 {
01001         BlendShapeNames.clear();
01002         for( uint32 i = 0; i < _Instances.size(); ++i )
01003         {
01004                 CMeshBaseInstance *pMBI = dynamic_cast<CMeshBaseInstance*>(_Instances[i]);
01005                 if (pMBI != NULL)
01006                 {
01007                         uint32 nNbBS = pMBI->getNbBlendShape();
01008                         for( uint32 j = 0; j < nNbBS; ++j )
01009                         {
01010                                 string sTmp;
01011                                 pMBI->getBlendShapeName( j, sTmp );
01012                                 set<string>::iterator itSet =  BlendShapeNames.find(sTmp);
01013                                 if( itSet == BlendShapeNames.end() )
01014                                         BlendShapeNames.insert( sTmp );
01015                         }
01016                 }
01017         }
01018 }
01019 
01020 // ***************************************************************************
01021 void CInstanceGroup::setBlendShapeFactor( const string &BlendShapeName, float rFactor )
01022 {
01023         for( uint32 i = 0; i < _Instances.size(); ++i )
01024         {
01025                 CMeshBaseInstance *pMI = dynamic_cast<CMeshBaseInstance*>(_Instances[i]);
01026                 if( pMI != NULL )
01027                 {
01028                         pMI->setBlendShapeFactor( BlendShapeName, rFactor );
01029                 }
01030         }
01031 }
01032 
01033 // ***************************************************************************
01034 void CInstanceGroup::addCluster(CCluster *pCluster)
01035 {
01036         _ClusterInstances.push_back(pCluster);
01037 }
01038 
01039 // ***************************************************************************
01040 void CInstanceGroup::setClusterSystem(CInstanceGroup *pIG)
01041 {
01042         _ClusterSystem = pIG;
01043         for (uint32 i = 0; i < _Instances.size(); ++i)
01044                 if (_Instances[i] && _InstancesInfos[i].Clusters.size() == 0)
01045                         _Instances[i]->setClusterSystem (_ClusterSystem);
01046 }
01047 
01048 // ***************************************************************************
01049 void CInstanceGroup::getDynamicPortals (std::vector<std::string> &names)
01050 {
01051         for (uint32 i = 0; i < _Portals.size(); ++i)
01052                 if (_Portals[i].getName() != "")
01053                         names.push_back (_Portals[i].getName());
01054 }
01055 
01056 // ***************************************************************************
01057 void CInstanceGroup::setDynamicPortal (std::string& name, bool opened)
01058 {
01059         for (uint32 i = 0; i < _Portals.size(); ++i)
01060                 if (_Portals[i].getName() == name)
01061                         _Portals[i].open (opened);
01062 }
01063 
01064 // ***************************************************************************
01065 bool CInstanceGroup::getDynamicPortal (std::string& name)
01066 {
01067         for (uint32 i = 0; i < _Portals.size(); ++i)
01068                 if (_Portals[i].getName() == name)
01069                         return _Portals[i].isOpened ();
01070         return false;
01071 }
01072 
01073 // ***************************************************************************
01074 void CInstanceGroup::setPos (const CVector &pos)
01075 {
01076         if (_Root != NULL)
01078                 _Root->setPos (pos);
01079 }
01080 
01081 // ***************************************************************************
01082 void CInstanceGroup::setRotQuat (const CQuat &quat)
01083 {
01084         if (_Root != NULL)
01085                 _Root->setRotQuat (quat);
01086 }
01087 
01088 // ***************************************************************************
01089 CVector CInstanceGroup::getPos ()
01090 {
01091         if (_Root != NULL)
01092                 return _Root->getPos ();
01093         else
01094                 return CVector(0.0f, 0.0f, 0.0f);
01095 }
01096 
01097 // ***************************************************************************
01098 CQuat CInstanceGroup::getRotQuat ()
01099 {
01100         if (_Root != NULL)
01101                 return _Root->getRotQuat ();
01102         else
01103                 return CQuat();
01104 }
01105 
01106 // ***************************************************************************
01107 void            CInstanceGroup::linkRoot (CScene &scene, CTransform *father)
01108 {
01109         if(_Root)
01110         {
01111                 ITrav *pHrcTrav = scene.getTrav (HrcTravId);
01112                 pHrcTrav->link(father, _Root);
01113         }
01114 }
01115 
01116 // ***************************************************************************
01117 void            CInstanceGroup::freezeHRC()
01118 {
01119         // For all instances.
01120         for (uint i=0; i < _Instances.size(); i++)
01121         {
01122                 if(_Instances[i])
01123                         _Instances[i]->freezeHRC();
01124         }
01125         // and for root.
01126         _Root->freezeHRC();
01127 }
01128 
01129 
01130 // ***************************************************************************
01131 void            CInstanceGroup::unfreezeHRC()
01132 {
01133         // For all instances.
01134         for (uint i=0; i < _Instances.size(); i++)
01135         {
01136                 if(_Instances[i])
01137                         _Instances[i]->unfreezeHRC();
01138         }
01139         // and for root.
01140         _Root->unfreezeHRC();
01141 }
01142 
01143 // ***************************************************************************
01144 // ***************************************************************************
01145 // ***************************************************************************
01146 // ***************************************************************************
01147 
01148 
01149 // ***************************************************************************
01150 void                    CInstanceGroup::buildPointLightList(const std::vector<CPointLightNamed> &pointLightList,
01151         std::vector<uint>       &plRemap)
01152 {
01153         // build.
01154         _PointLightArray.build(pointLightList, plRemap);
01155 
01156         // remap Instance precalc lighted.
01157         for(uint i=0; i<_InstancesInfos.size(); i++)
01158         {
01159                 CInstance       &inst= _InstancesInfos[i];
01160                 // If the instance has no precomputed lighting, skip
01161                 if(!inst.StaticLightEnabled)
01162                         continue;
01163 
01164                 // remap pointlights
01165                 for(uint l=0; l<CInstanceGroup::NumStaticLightPerInstance; l++)
01166                 {
01167                         // If NULL light, break and continue to next instance
01168                         if(inst.Light[l]== 0xFF)
01169                                 break;
01170                         else
01171                         {
01172                                 // Check good index.
01173                                 nlassert(inst.Light[l] < _PointLightArray.getPointLights().size());
01174                                 // Remap index, because of light sorting.
01175                                 inst.Light[l]= plRemap[inst.Light[l]];
01176                         }
01177                 }
01178 
01179                 // remap ambient light
01180                 if(inst.LocalAmbientId!=0xFF)
01181                 {
01182                         nlassert(inst.LocalAmbientId < _PointLightArray.getPointLights().size());
01183                         inst.LocalAmbientId= plRemap[inst.LocalAmbientId];
01184                 }
01185         }
01186 
01187 }
01188 
01189 // ***************************************************************************
01190 void                    CInstanceGroup::setPointLightFactor(const std::string &lightGroupName, NLMISC::CRGBA nFactor)
01191 {
01192         _PointLightArray.setPointLightFactor(lightGroupName, nFactor);
01193 }
01194 
01195 
01196 // ***************************************************************************
01197 void                    CInstanceGroup::enableRealTimeSunContribution(bool enable)
01198 {
01199         _RealTimeSunContribution= enable;
01200 }
01201 
01202 
01203 } // NL3D