1 //------------------------------------------------------------------------------
2 // File : SkySceneManager.cpp
3 //------------------------------------------------------------------------------
4 // SkyWorks : Copyright 2002 Mark J. Harris and
5 // The University of North Carolina at Chapel Hill
6 //------------------------------------------------------------------------------
7 // Permission to use, copy, modify, distribute and sell this software and its
8 // documentation for any purpose is hereby granted without fee, provided that
9 // the above copyright notice appear in all copies and that both that copyright
10 // notice and this permission notice appear in supporting documentation.
11 // Binaries may be compiled with this software without any royalties or
14 // The author(s) and The University of North Carolina at Chapel Hill make no
15 // representations about the suitability of this software for any purpose.
16 // It is provided "as is" without express or
20 * @file SkySceneManager.cpp
22 * Implementation of the singleton class SkySceneManager, which manages objects,
23 * instances, scene update, visibility, culling, and rendering.
26 // warning for truncation of template name for browse info
27 #pragma warning( disable : 4786)
29 #include "SkySceneManager.hpp"
30 #include "SkyMaterial.hpp"
31 #include "SkyLight.hpp"
32 #include "SkyCloud.hpp"
33 #include "SkyRenderable.hpp"
34 #include "SkyRenderableInstance.hpp"
35 #include "SkyRenderableInstanceCloud.hpp"
37 #include "camutils.hpp"
40 //------------------------------------------------------------------------------
41 // Function : SkySceneManager::SkySceneManager
43 //------------------------------------------------------------------------------
45 * @fn SkySceneManager::SkySceneManager()
48 SkySceneManager::SkySceneManager()
55 _wireframeMaterial.SetColorMaterialMode(GL_DIFFUSE);
56 _wireframeMaterial.EnableColorMaterial(true);
57 _wireframeMaterial.EnableLighting(false);
59 // add the default material with ID -1
60 // this should avoid errors caused by models without materials exported from MAX
61 // (because flexporter gives them the ID -1).
62 SkyMaterial *pDefaultMaterial = new SkyMaterial;
63 pDefaultMaterial->SetMaterialID(-1);
64 AddMaterial(pDefaultMaterial);
67 //------------------------------------------------------------------------------
68 // Function : SkySceneManager::~SkySceneManager
70 //------------------------------------------------------------------------------
72 * @fn SkySceneManager::~SkySceneManager()
75 * This destructor deletes all renderables, instances (renderable instances, cloud instances,
76 * and otherwise), materials, and lights that were added to the scene using the Add*() functions.
77 * In other words, the scene manager owns all entities added to the scene. This eases cleanup
80 SkySceneManager::~SkySceneManager()
83 for (oi = _objects.begin(); oi != _objects.end(); ++oi)
88 for (ci = _clouds.begin(); ci != _clouds.end(); ++ci)
93 for (ii = _instances.begin(); ii != _instances.end(); ++ii)
97 CloudInstanceIterator cii;
98 for (cii = _cloudInstances.begin(); cii != _cloudInstances.end(); ++cii)
100 _cloudInstances.clear();
102 ContainerSetIterator cni;
103 for (cni = _containerClouds.begin(); cni != _containerClouds.end(); ++cni)
104 SAFE_DELETE(cni->second);
105 _containerClouds.clear();
108 for (mi = _materials.begin(); mi != _materials.end(); ++mi)
109 SAFE_DELETE(mi->second);
113 for (li = _lights.begin(); li!= _lights.end(); ++li)
114 SAFE_DELETE(li->second);
117 //SAFE_DELETE(_pSkyBox);
118 //SAFE_DELETE(_pTerrain);
121 //------------------------------------------------------------------------------
122 // Function : SkySceneManager::AddObject
124 //------------------------------------------------------------------------------
126 * @fn SkySceneManager::AddObject(SkyRenderable *pObject)
127 * @brief Add a new SkyRenderable object to the manager.
129 SKYRESULT SkySceneManager::AddObject(SkyRenderable *pObject)
131 // Check for null object
134 FAIL_RETURN_MSG(SKYRESULT_FAIL,
135 "SkySceneManager::AddObject(): Attempting to add NULL Renderable Object.");
138 _objects.push_back(pObject);
144 //------------------------------------------------------------------------------
145 // Function : SkySceneManager::AddInstance
147 //------------------------------------------------------------------------------
149 * @fn SkySceneManager::AddInstance(SkyRenderableInstance *pInstance, bool bTransparent)
150 * @brief Add a new SkyRenderableInstance to the manager.
152 SKYRESULT SkySceneManager::AddInstance(SkyRenderableInstance *pInstance, bool bTransparent /* = false */)
154 // Check for null instance
155 if (NULL == pInstance)
157 FAIL_RETURN_MSG(SKYRESULT_FAIL,
158 "SkySceneManager::AddObject(): Attempting to add NULL Renderable Instance.");
162 _instances.push_back(pInstance);
164 _transparentInstances.push_back(pInstance);
170 //------------------------------------------------------------------------------
171 // Function : SkySceneManager::AddCloud
173 //------------------------------------------------------------------------------
175 * @fn SkySceneManager::AddCloud(SkyCloud *pCloud)
176 * @brief Add a new cloud object to the manager.
178 * @todo <WRITE EXTENDED SkySceneManager::AddCloud FUNCTION DOCUMENTATION>
180 SKYRESULT SkySceneManager::AddCloud(SkyCloud *pCloud)
184 FAIL_RETURN_MSG(SKYRESULT_FAIL,
185 "SkySceneManager::AddObject(): Attempting to add NULL SkyCloud Object.");
188 _clouds.push_back(pCloud);
195 //------------------------------------------------------------------------------
196 // Function : SkySceneManager::AddCloudInstance
198 //------------------------------------------------------------------------------
200 * @fn SkySceneManager::AddCloudInstance(SkyRenderableInstanceCloud *pInstance)
201 * @brief Add a new instance of a cloud to the manager.
203 * @todo Note that since cloud instances share shading information, if two instances
204 * of a cloud have different orientations, one of the instances will have incorrect
205 * lighting for the scene. For this reason, I recommend that the number of clouds and
206 * cloud instances is equal.
208 SKYRESULT SkySceneManager::AddCloudInstance(SkyRenderableInstanceCloud *pInstance)
210 // Check for null instance
211 if (NULL == pInstance)
213 FAIL_RETURN_MSG(SKYRESULT_FAIL,
214 "SkySceneManager::AddObject(): Attempting to add NULL SkyCloud Instance.");
217 pInstance->SetID(_cloudInstances.size());
219 _cloudInstances.push_back(pInstance);
221 SkyContainerCloud *pContainer = new SkyContainerCloud(pInstance);
222 _containerClouds.insert(std::make_pair(pInstance->GetID(), pContainer));
224 RebuildCloudBVTree();
230 //------------------------------------------------------------------------------
231 // Function : SkySceneManager::AddMaterial
233 //------------------------------------------------------------------------------
235 * @fn SkySceneManager::AddMaterial(SkyMaterial *pMaterial)
236 * @brief Adds a material to the scene.
238 * Materials are kept in a map with their ID as key. A material can be retrieved
239 * from the scene manager by passing its ID to GetMaterial.
241 * @see GetMaterial, SkyMaterial
243 SKYRESULT SkySceneManager::AddMaterial(SkyMaterial *pMaterial)
245 // Check for null instance
246 if (NULL == pMaterial)
248 FAIL_RETURN_MSG(SKYRESULT_FAIL,
249 "SkySceneMananger::AddMaterial(): Attempting to add NULL Material to Scene Manager");
252 _materials.insert(std::make_pair(pMaterial->GetMaterialID(), pMaterial));
258 //------------------------------------------------------------------------------
259 // Function : SkySceneManager::GetMaterial
261 //------------------------------------------------------------------------------
263 * @fn SkySceneManager::GetMaterial(int iMaterialID)
264 * @brief Returns the material with ID @a iMaterialID.
266 * If the material is not found, returns NULL.
268 * @see AddMaterial, SkyMaterial
270 SkyMaterial* SkySceneManager::GetMaterial(int iMaterialID)
272 MaterialIterator mi = _materials.find(iMaterialID);
273 if (_materials.end() == mi)
275 SkyTrace("SkySceneManager::GetMaterial: Error: invalid material ID");
283 //------------------------------------------------------------------------------
284 // Function : SkySceneManager::ActivateMaterial
286 //------------------------------------------------------------------------------
288 * @fn SkySceneManager::ActivateMaterial(int iMaterialID)
289 * @brief Makes the specified material active, setting the appropriate rendering state.
291 * @todo <WRITE EXTENDED SkySceneManager::ActivateMaterial FUNCTION DOCUMENTATION>
293 SKYRESULT SkySceneManager::ActivateMaterial(int iMaterialID)
295 // cout << "Activating material\n"; char mm; cin >> mm;
296 MaterialIterator mi = _materials.find(iMaterialID);
297 if (_materials.end() == mi)
299 FAIL_RETURN_MSG(SKYRESULT_FAIL,
300 "SkySceneManager::ActivateMaterial: Error: invalid material ID.");
304 FAIL_RETURN_MSG(mi->second->Activate(),
305 "SkySceneManager::ActivateMaterial: Error: failed to activate.");
312 //------------------------------------------------------------------------------
313 // Function : SkySceneManager::AddLight
315 //------------------------------------------------------------------------------
317 * @fn SkySceneManager::AddLight(SkyLight *pLight)
318 * @brief @todo <WRITE BRIEF SkySceneManager::AddLight DOCUMENTATION>
320 * @todo <WRITE EXTENDED SkySceneManager::AddLight FUNCTION DOCUMENTATION>
322 SKYRESULT SkySceneManager::AddLight(SkyLight *pLight)
324 // Check for null instance
327 FAIL_RETURN_MSG(SKYRESULT_FAIL,
328 "SkySceneMananger::AddLight(): Attempting to add NULL Light to Scene Manager");
331 _lights.insert(std::make_pair(_lights.size(), pLight));
336 //------------------------------------------------------------------------------
337 // Function : SkySceneManager::GetLight
339 //------------------------------------------------------------------------------
341 * @fn SkySceneManager::GetLight(int iLightID)
342 * @brief @todo <WRITE BRIEF SkySceneManager::GetLight DOCUMENTATION>
344 * @todo <WRITE EXTENDED SkySceneManager::GetLight FUNCTION DOCUMENTATION>
346 SkyLight* SkySceneManager::GetLight(int iLightID)
348 LightIterator li = _lights.find(iLightID);
349 if (_lights.end() == li)
351 SkyTrace("SkySceneManager::GetLight: Error: Invalid light ID");
359 //------------------------------------------------------------------------------
362 //------------------------------------------------------------------------------
364 * @fn Alive(SkyRenderableInstance* pInstance)
365 * @brief A predicate to determine if an object is dead or not.
367 bool Alive(SkyRenderableInstance* pInstance)
369 return (pInstance->IsAlive());
373 //------------------------------------------------------------------------------
374 // Function : SkySceneManager::Update
376 //------------------------------------------------------------------------------
378 * @fn SkySceneManager::Update(const Camera &cam)
379 * @brief Iterate through all SkyRenderableInstances and update them.
381 SKYRESULT SkySceneManager::Update(const Camera &cam)
383 _ResolveVisibility(cam);
389 //------------------------------------------------------------------------------
390 // Function : SkySceneManager::Display
392 //------------------------------------------------------------------------------
394 * @fn SkySceneManager::Display(const Camera &cam)
395 * @brief Iterate through all SkyRenderableInstances and display them.
397 SKYRESULT SkySceneManager::Display( const Camera &cam )
400 // _clearMaterial.Force();
401 _clearMaterial.Activate();
402 //glClear(GL_DEPTH_BUFFER_BIT);
404 // set lights (only lights that have changed will be passed to GL).
405 for (LightIterator li = _lights.begin(); li != _lights.end(); ++li)
407 li->second->Activate(li->first);
409 //li->second->Display();
412 //if (_bDrawTree)// force the issue and draw
413 //_VisualizeCloudBVTree(cam, _cloudBVTree.GetRoot());
417 // red is Cartesian y-axis
418 glColor3ub( 255, 0, 0 );
419 glVertex3f( 0.0,0.0,0.0 );
420 glVertex3f( 0.0, -104000.0, 0.0);
421 // yellow is Cartesian z-axis
422 glColor3ub( 255, 255, 0 );
423 glVertex3f( 0.0, 0.0, 0.0);
424 glVertex3f( 0.0, 0.0, 104000.0);
425 // blue is Cartesian x-axis
426 glColor3ub( 0, 0, 255 );
427 glVertex3f( 0.0, 0.0, 0.0);
428 glVertex3f( -104000.0, 0.0, 0.0);
431 // draw all container clouds and "free" objects not in clouds.
433 for (InstanceIterator iter = _visibleInstances.begin(); iter != _visibleInstances.end(); ++iter)
435 FAIL_RETURN_MSG((*iter)->Display(),
436 "SkySceneManager::Display(): instance display failed.");
439 //cout << "There are " << i << " visible clouds\n";
445 //------------------------------------------------------------------------------
446 // Function : SkySceneManager::RebuildCloudBVTree
448 //------------------------------------------------------------------------------
450 * @fn SkySceneManager::RebuildCloudBVTree()
451 * @brief Builds an AABB tree of the cloud bounding volumes.
453 SKYRESULT SkySceneManager::RebuildCloudBVTree()
455 CloudInstanceIterator cii;
458 _cloudBVTree.BeginTree();
459 for (cii = _cloudInstances.begin(); cii != _cloudInstances.end(); ++cii)
461 bbox = (*cii)->GetWorldSpaceBounds();
462 _cloudBVTree.AddObject(*cii, bbox);
464 _cloudBVTree.EndTree();
470 //------------------------------------------------------------------------------
471 // Function : SkySceneManager::ShadeClouds
473 //------------------------------------------------------------------------------
475 * @fn SkySceneManager::ShadeClouds()
476 * @brief @todo <WRITE BRIEF SkySceneManager::ShadeClouds DOCUMENTATION>
478 * @todo <WRITE EXTENDED SkySceneManager::ShadeClouds FUNCTION DOCUMENTATION>
480 SKYRESULT SkySceneManager::ShadeClouds()
482 // cout << "SkySceneManager::ShadeClouds()\n";
485 for (CloudInstanceIterator cii = _cloudInstances.begin(); cii != _cloudInstances.end(); ++cii)
487 for (LightIterator li = _lights.begin(); li != _lights.end(); ++li)
490 if (SkyLight::SKY_LIGHT_DIRECTIONAL == li->second->GetType())
492 (*cii)->GetCloud()->Illuminate(li->second, *cii, li == _lights.begin());
493 // printf("Shading Cloud %d of %d with light %d \n", i++, _cloudInstances.size(), *li );
497 _bReshadeClouds = false;
502 //------------------------------------------------------------------------------
503 // Function : SkySceneManager::LoadClouds
505 //------------------------------------------------------------------------------
507 * @fn SkySceneManager::LoadClouds(SkyArchive& cloudArchive, float rScale)
508 * @brief @todo <WRITE BRIEF SkySceneManager::LoadClouds DOCUMENTATION>
510 * @todo <WRITE EXTENDED SkySceneManager::LoadClouds FUNCTION DOCUMENTATION>
512 SKYRESULT SkySceneManager::LoadClouds(unsigned char *data, unsigned int size, float rScale, double latitude, double longitude)
514 SkyCloud *pCloud = new SkyCloud();
515 pCloud->Load(data, size, rScale, latitude, longitude);
516 SkyRenderableInstanceCloud *pInstance = new SkyRenderableInstanceCloud(pCloud, false);
518 AddCloudInstance(pInstance);
520 RebuildCloudBVTree();
525 //------------------------------------------------------------------------------
526 // Function : SkySceneManager::LoadClouds
528 //------------------------------------------------------------------------------
530 * @fn SkySceneManager::LoadClouds(SkyArchive& cloudArchive, float rScale)
531 * @brief @todo <WRITE BRIEF SkySceneManager::LoadClouds DOCUMENTATION>
533 * @todo <WRITE EXTENDED SkySceneManager::LoadClouds FUNCTION DOCUMENTATION>
535 SKYRESULT SkySceneManager::LoadClouds(SkyArchive& cloudArchive, float rScale, double latitude, double longitude)
537 unsigned int iNumClouds = 0;
538 cloudArchive.FindUInt32("CldNumClouds", &iNumClouds);
539 _ulEndianSwap(&iNumClouds);
541 SkyArchive subArchive;
542 //iNumClouds = 5; //set this value to reduce cloud field for debugging
543 for (int i = 0; i < iNumClouds; ++i)
544 {printf("Loading # %d of %d clouds\n", i+1, iNumClouds);
545 cloudArchive.FindArchive("Cloud", &subArchive, i);
546 SkyCloud *pCloud = new SkyCloud();
547 pCloud->Load(subArchive, rScale, latitude, longitude);
548 SkyRenderableInstanceCloud *pInstance = new SkyRenderableInstanceCloud(pCloud, false);
550 AddCloudInstance(pInstance);
552 RebuildCloudBVTree();
556 //------------------------------------------------------------------------------
557 // Function : SkySceneManager::_SortClouds
559 //------------------------------------------------------------------------------
561 * @fn SkySceneManager::_SortClouds(CloudInstanceArray& clouds, const Vec3f& vecSortPoint)
562 * @brief @todo <WRITE BRIEF SkySceneManager::_SortClouds DOCUMENTATION>
564 * @todo <WRITE EXTENDED SkySceneManager::_SortClouds FUNCTION DOCUMENTATION>
566 void SkySceneManager::_SortClouds(CloudInstanceArray& clouds, const Vec3f& vecSortPoint)
568 static InstanceComparator comparator;
570 for (CloudInstanceIterator cii = clouds.begin(); cii != clouds.end(); ++cii)
572 Vec3f vecPos = (*cii)->GetPosition();
573 vecPos -= vecSortPoint;
574 (*cii)->SetSquareSortDistance(vecPos.LengthSqr());
577 std::sort(clouds.begin(), clouds.end(), comparator);
581 //------------------------------------------------------------------------------
582 // Function : SkySceneManager::_SortInstances
584 //------------------------------------------------------------------------------
586 * @fn SkySceneManager::SortInstances(InstanceArray& instances, const Vec3f& vecSortPoint)
587 * @brief @todo <WRITE BRIEF SkySceneManager::_SortInstances DOCUMENTATION>
589 * @todo <WRITE EXTENDED SkySceneManager::_SortInstances FUNCTION DOCUMENTATION>
591 void SkySceneManager::SortInstances(InstanceArray& instances, const Vec3f& vecSortPoint)
593 static InstanceComparator comparator;
595 for (InstanceIterator ii = instances.begin(); ii != instances.end(); ++ii)
597 Vec3f vecPos = (*ii)->GetPosition();
598 vecPos -= vecSortPoint;
599 (*ii)->SetSquareSortDistance(vecPos.LengthSqr());
602 std::sort(instances.begin(), instances.end(), comparator);
606 //------------------------------------------------------------------------------
607 // Function : SkySceneManager::_ViewFrustumCullClouds
609 //------------------------------------------------------------------------------
611 * @fn SkySceneManager::_ViewFrustumCullClouds(const Camera& cam, const CloudBVTree::Node *pNode)
612 * @brief @todo <WRITE BRIEF SkySceneManager::_ViewFrustumCullClouds DOCUMENTATION>
614 * @todo <WRITE EXTENDED SkySceneManager::_ViewFrustumCullClouds FUNCTION DOCUMENTATION>
616 void SkySceneManager::_ViewFrustumCullClouds(const Camera& cam, const CloudBVTree::Node *pNode)
622 int iResult = CamMinMaxBoxOverlap(&cam, pNode->GetNodeBV().GetMin(), pNode->GetNodeBV().GetMax());
624 //iResult = COMPLETEIN; // just a hack to force the issue
625 if (COMPLETEIN == iResult)
627 // trivially add all instances
628 for (i = 0; i < pNode->GetNumObjs(); ++i)
630 SkyRenderableInstanceCloud* pInstance =
631 const_cast<SkyRenderableInstanceCloud*>(pNode->GetObj(i));
632 _visibleCloudInstances.push_back(pInstance);
635 else if ((PARTIAL == iResult) && pNode->IsLeaf())
639 // check each instance in this node against camera
640 for (i = 0; i < pNode->GetNumObjs(); ++i)
642 SkyRenderableInstanceCloud* pInstance =
643 const_cast<SkyRenderableInstanceCloud*>(pNode->GetObj(i));
644 bbox = pInstance->GetWorldSpaceBounds();
645 iResult = CamMinMaxBoxOverlap(&cam, bbox.GetMin(), bbox.GetMax());
646 if (COMPLETEOUT != iResult)
647 _visibleCloudInstances.push_back(pInstance);
649 pInstance->ReleaseImpostorTextures();
652 else if (PARTIAL == iResult)
654 _ViewFrustumCullClouds(cam, pNode->GetLeftChild());
655 _ViewFrustumCullClouds(cam, pNode->GetRightChild());
657 else // the node is completely out. All of its child clouds should release their textures.
659 for (i = 0; i < pNode->GetNumObjs(); ++i)
661 SkyRenderableInstanceCloud* pInstance =
662 const_cast<SkyRenderableInstanceCloud*>(pNode->GetObj(i));
663 pInstance->ReleaseImpostorTextures();
669 //------------------------------------------------------------------------------
670 // Function : SkySceneManager::_VisualizeCloudBVTree
672 //------------------------------------------------------------------------------
674 * @fn SkySceneManager::_VisualizeCloudBVTree(const Camera& cam, const CloudBVTree::Node *pNode)
675 * @brief @todo <WRITE BRIEF SkySceneManager::_VisualizeCloudBVTree DOCUMENTATION>
677 * @todo <WRITE EXTENDED SkySceneManager::_VisualizeCloudBVTree FUNCTION DOCUMENTATION>
679 void SkySceneManager::_VisualizeCloudBVTree(const Camera& cam, const CloudBVTree::Node *pNode)
681 // set display state.
682 _wireframeMaterial.Activate();
684 int iResult = CamMinMaxBoxOverlap(&cam, pNode->GetNodeBV().GetMin(), pNode->GetNodeBV().GetMax());
686 if (COMPLETEIN == iResult)
688 // draw this node's bounding box in green.
690 pNode->GetNodeBV().Display();
692 else if (PARTIAL == iResult)
698 // draw this node's bounding box and the boxes of all of its objects that are visible.
699 // draw this node's bbox in orange.
700 glColor3f(1, 0.5, 0);
701 pNode->GetNodeBV().Display();
704 for (i = 0; i < pNode->GetNumObjs(); ++i)
706 SkyRenderableInstanceCloud* pInstance =
707 const_cast<SkyRenderableInstanceCloud*>(pNode->GetObj(i));
708 bbox = pInstance->GetWorldSpaceBounds();
709 iResult = CamMinMaxBoxOverlap(&cam, bbox.GetMin(), bbox.GetMax());
711 if (COMPLETEIN == iResult)
713 // draw the box in green
717 else if (PARTIAL == iResult)
719 // draw the box in yellow
727 _VisualizeCloudBVTree(cam, pNode->GetLeftChild());
728 _VisualizeCloudBVTree(cam, pNode->GetRightChild());
733 // draw the node's bbox in red.
734 // This should NEVER be visible from the camera from which it was culled!
736 pNode->GetNodeBV().Display();
741 //------------------------------------------------------------------------------
742 // Function : SkySceneManager::_ResolveVisibility
744 //------------------------------------------------------------------------------
746 * @fn SkySceneManager::_ResolveVisibility(const Camera &cam)
747 * @brief @todo <WRITE BRIEF SkySceneManager::_ResolveRenderingOrder DOCUMENTATION>
749 * @todo <WRITE EXTENDED SkySceneManager::_ResolveRenderingOrder FUNCTION DOCUMENTATION>
751 SKYRESULT SkySceneManager::_ResolveVisibility(const Camera &cam)
755 // clear the free instance array
756 _visibleInstances.clear();
758 // clear the contained instance arrays
759 ContainerSetIterator csi;
760 for (csi = _containerClouds.begin(); csi != _containerClouds.end(); ++csi)
762 csi->second->containedOpaqueInstances.clear();
763 csi->second->containedTransparentInstances.clear();
766 // clear the visible cloud array.
767 _visibleCloudInstances.clear();
769 // Test each instance for containment inside a cloud's bounding volume.
770 // If the instance is inside a cloud, it is considered a "contained" instance, and will be
771 // rendered with the cloud in which it is contained for correct visibility. If the instance is
772 // not inside any cloud, then it is a "free" instance, and will be rendered after all contained
773 // instances. Transparent instances of each type are rendered after opaque instances of each
777 for (ii = _instances.begin(); ii != _instances.end(); ++ii)
779 // cout << "Opague instance\n"; char zz; cin >> zz;
780 (*ii)->ViewFrustumCull(cam); // First VFC then check if culled, some instances may
781 // manually set the culled flag, instead of using VFC
782 if (!(*ii)->IsCulled())
784 // first update this instance.
785 FAIL_RETURN_MSG((*ii)->Update(cam), "SkySceneManager::_ResolveVisibility(): instance update failed.");
787 if (!_TestInsertInstanceIntoClouds(cam, _cloudBVTree.GetRoot(), *ii, false))
788 _visibleInstances.push_back(*ii);
792 // transparent instances
793 for (ii = _transparentInstances.begin(); ii != _transparentInstances.end(); ++ii)
795 // cout << "Transparent instance\n"; char tt; cin >> tt;
796 (*ii)->ViewFrustumCull(cam); // First VFC then check if culled, some instances may
797 // manually set the culled flag, instead of using VFC
798 if (!(*ii)->IsCulled())
800 // first update this instance.
801 FAIL_RETURN_MSG((*ii)->Update(cam), "SkySceneManager::Update(): instance update failed.");
803 if (!_TestInsertInstanceIntoClouds(cam, _cloudBVTree.GetRoot(), *ii, true))
804 _visibleInstances.push_back(*ii);
808 // view frustum cull the clouds
809 _ViewFrustumCullClouds(cam, _cloudBVTree.GetRoot());
811 // Clouds must be rendered in sorted order.
812 //_SortClouds(_visibleCloudInstances, cam.Orig);
814 // reshade the clouds if necessary.
817 printf("ReShading clouds\n");
818 FAIL_RETURN(ShadeClouds());
821 // Now process the visible clouds. First, go through the container clouds corresponding to the
822 // clouds, calculate their split points, and update their impostors.
823 for (CloudInstanceIterator cii = _visibleCloudInstances.begin();
824 cii != _visibleCloudInstances.end();
827 // get the container corresponding to this cloud
828 ContainerSetIterator csi = _containerClouds.find((*cii)->GetID());
830 if (csi == _containerClouds.end())
832 SkyTrace("Error: SkySceneManager::_ResolveVisibility(): Invalid cloud instance %d.",
834 return SKYRESULT_FAIL;
837 if (csi->second->containedOpaqueInstances.size() > 0 ||
838 csi->second->containedTransparentInstances.size() > 0)
840 SortInstances(csi->second->containedOpaqueInstances, cam.Orig);
841 SortInstances(csi->second->containedTransparentInstances, cam.Orig);
844 SkyRenderableInstance *pOpaque = (csi->second->containedOpaqueInstances.size() > 0) ?
845 csi->second->containedOpaqueInstances.back() : NULL;
846 SkyRenderableInstance *pTransparent = (csi->second->containedTransparentInstances.size() > 0) ?
847 csi->second->containedTransparentInstances.back() : NULL;
849 // find the closest contained instance to the camera
850 if (pOpaque && pTransparent)
852 if (*pOpaque < *pTransparent)
853 (*cii)->SetSplitPoint(pOpaque->GetPosition());
855 (*cii)->SetSplitPoint(pTransparent->GetPosition());
858 (*cii)->SetSplitPoint(pOpaque->GetPosition());
859 else if (pTransparent)
860 (*cii)->SetSplitPoint(pTransparent->GetPosition());
862 (*cii)->SetSplit(false);
865 (*cii)->SetSplit(false);
867 // add the container to the list of visiblie clouds to be rendered this frame.
868 _visibleInstances.push_back(csi->second);
870 // now update the impostors
871 FAIL_RETURN_MSG((*cii)->Update(cam),
872 "SkySceneManager::_ResolveVisibility(): cloud instance update failed.");
875 SortInstances(_visibleInstances, cam.Orig);
881 //------------------------------------------------------------------------------
882 // Function : SkySceneManager::_TestInsertInstanceIntoClouds
884 //------------------------------------------------------------------------------
886 * @fn SkySceneManager::_TestInsertInstanceIntoClouds(const Camera &cam, const CloudBVTree::Node *pNode, SkyRenderableInstance *pInstanceToInsert, bool bTransparent)
887 * @brief @todo <WRITE BRIEF SkySceneManager::_TestInsertInstanceIntoClouds DOCUMENTATION>
889 * @todo <WRITE EXTENDED SkySceneManager::_TestInsertInstanceIntoClouds FUNCTION DOCUMENTATION>
891 bool SkySceneManager::_TestInsertInstanceIntoClouds(const Camera &cam,
892 const CloudBVTree::Node *pNode,
893 SkyRenderableInstance *pInstanceToInsert,
896 if (_clouds.size() <= 0)
899 if (pNode->GetNodeBV().PointInBBox(pInstanceToInsert->GetPosition()))
906 // check the instance against each cloud in this leaf node.
907 for (i = 0; i < pNode->GetNumObjs(); ++i)
909 SkyRenderableInstanceCloud* pCloud =
910 const_cast<SkyRenderableInstanceCloud*>(pNode->GetObj(i));
911 bbox = pCloud->GetWorldSpaceBounds();
912 if (bbox.PointInBBox(pInstanceToInsert->GetPosition()))
914 // get the container cloud struct for this cloud instance, and add this instance.
915 ContainerSetIterator csi = _containerClouds.find(pCloud->GetID());
916 if (csi == _containerClouds.end())
919 "Error: SkySceneManager::_TestInsertInstanceIntoClouds(): Invalid cloud instance %d.",
923 else // this instance is inside a cloud. Set up for split cloud rendering.
926 csi->second->containedOpaqueInstances.push_back(pInstanceToInsert);
928 csi->second->containedTransparentInstances.push_back(pInstanceToInsert);
929 csi->second->pCloud->SetSplit(true);
938 if (!_TestInsertInstanceIntoClouds(cam, pNode->GetLeftChild(), pInstanceToInsert, bTransparent))
939 return _TestInsertInstanceIntoClouds(cam, pNode->GetRightChild(), pInstanceToInsert, bTransparent);