csplugincommon/rendermanager/occluvis.h
00001 /* 00002 Copyright (C) 2010 by Mike Gist and Claudiu Mihail 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Lesser General Public 00006 License as published by the Free Software Foundation; either 00007 version 2 of the License, or (at your option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public 00015 License along with this library; if not, write to the Free 00016 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00017 */ 00018 00019 #ifndef __CS_RENDERMANAGER_OCCLUVIS_H__ 00020 #define __CS_RENDERMANAGER_OCCLUVIS_H__ 00021 00022 #include "csgeom/aabbtree.h" 00023 #include "csutil/hash.h" 00024 #include "csutil/refarr.h" 00025 #include "csutil/scf_implementation.h" 00026 #include "iengine/engine.h" 00027 #include "iengine/movable.h" 00028 #include "iengine/sector.h" 00029 #include "iengine/viscull.h" 00030 #include "imesh/objmodel.h" 00031 00032 struct iGraphics3D; 00033 struct iMeshWrapper; 00034 struct iObjectRegistry; 00035 00036 #include "csutil/deprecated_warn_off.h" 00037 00038 namespace CS 00039 { 00040 namespace RenderManager 00041 { 00042 // Frustum culling visibility results. 00043 enum NodeVisibility 00044 { 00045 NODE_INVISIBLE, 00046 NODE_VISIBLE, 00047 NODE_INSIDE 00048 }; 00049 00050 // Occlusion visibility results. 00051 enum OcclusionVisibility 00052 { 00053 VISIBLE, 00054 UNKNOWN, 00055 INVISIBLE, 00056 INVALID 00057 }; 00058 00059 typedef csArray<iVisibilityObject*, csArrayElementHandler<iVisibilityObject*>, 00060 CS::Container::ArrayAllocDefault, csArrayCapacityFixedGrow<256> > 00061 VistestObjectsArray; 00062 00063 struct IntersectSegmentFront2BackData 00064 { 00065 csSegment3 seg; 00066 csVector3 isect; 00067 float sqdist; // Squared distance between seg.start and isect. 00068 float r; 00069 iMeshWrapper* mesh; 00070 int polygon_idx; 00071 VistestObjectsArray* vector; // If not-null we need all objects. 00072 bool accurate; 00073 bool bf; 00074 }; 00075 00076 struct QueryData : public csRefCount 00077 { 00078 unsigned int uOQuery; 00079 uint32 uQueryFrame; 00080 uint32 uNextCheck; 00081 OcclusionVisibility eResult; 00082 00083 QueryData () 00084 : uOQuery (0), uQueryFrame (0), 00085 uNextCheck (0), eResult (INVALID) 00086 {} 00087 }; 00088 00089 struct AABBTreeNodeVisibilityData 00090 { 00091 AABBTreeNodeVisibilityData () 00092 { 00093 g3d = 0; 00094 } 00095 00096 ~AABBTreeNodeVisibilityData () 00097 { 00098 if (g3d) 00099 { 00100 FreeQueryData (); 00101 } 00102 } 00103 00104 void LeafAddObject (iVisibilityObject*) 00105 { 00106 RViewQueryHash::GlobalIterator itr = RViewQueries.GetIterator (); 00107 while (itr.HasNext ()) 00108 { 00109 itr.Next ()->eResult = INVALID; 00110 } 00111 } 00112 00113 void LeafUpdateObjects (iVisibilityObject**, uint) 00114 { 00115 RViewQueryHash::GlobalIterator itr = RViewQueries.GetIterator (); 00116 while (itr.HasNext ()) 00117 { 00118 itr.Next ()->eResult = INVALID; 00119 } 00120 } 00121 00122 void NodeUpdate (const AABBTreeNodeVisibilityData& child1, 00123 const AABBTreeNodeVisibilityData& child2) 00124 { 00125 RViewQueryHash::GlobalIterator itr = RViewQueries.GetIterator (); 00126 while (itr.HasNext ()) 00127 { 00128 itr.Next ()->eResult = INVALID; 00129 } 00130 } 00131 00132 QueryData* GetQueryData (iGraphics3D* ig3d, iRenderView* rview) 00133 { 00134 csRef<QueryData> queryData = RViewQueries.Get (csPtrKey<iRenderView> (rview), csRef<QueryData> ()); 00135 00136 if (!queryData.IsValid ()) 00137 { 00138 g3d = ig3d; 00139 queryData.AttachNew (new QueryData); 00140 g3d->OQInitQueries (&queryData->uOQuery, 1); 00141 RViewQueries.Put (csPtrKey<iRenderView> (rview), queryData); 00142 } 00143 00144 return queryData; 00145 } 00146 00147 void FreeQueryData () 00148 { 00149 RViewQueryHash::GlobalIterator itr = RViewQueries.GetIterator (); 00150 while (itr.HasNext ()) 00151 { 00152 g3d->OQDelQueries (&itr.Next ()->uOQuery, 1); 00153 } 00154 00155 RViewQueries.DeleteAll (); 00156 } 00157 00158 private: 00159 iGraphics3D* g3d; 00160 00161 typedef csHash<csRef<QueryData>, csPtrKey<iRenderView> > RViewQueryHash; 00162 RViewQueryHash RViewQueries; 00163 }; 00164 00165 typedef CS::Geometry::AABBTree<iVisibilityObject, 1, AABBTreeNodeVisibilityData> AABBVisTree; 00166 typedef AABBVisTree::Node AABBVisTreeNode; 00167 00168 class CS_CRYSTALSPACE_EXPORT csOccluvis : public AABBVisTree, 00169 public scfImplementation1<csOccluvis, iVisibilityCuller> 00170 { 00171 private: 00172 iObjectRegistry *object_reg; 00173 csRef<iGraphics3D> g3d; 00174 csRef<iEngine> engine; 00175 csRef<iShaderManager> shaderMgr; 00176 csRef<iStringSet> stringSet; 00177 csRef<iShaderVarStringSet> svStrings; 00178 00179 // Structure of common f2b data. 00180 struct Front2BackData 00181 { 00182 csVector3 pos; 00183 iRenderView* rview; 00184 csPlane3* frustum; 00185 iVisibilityCullerListener* viscallback; 00186 }; 00187 00188 struct NodeMeshList : public csRefCount 00189 { 00190 NodeMeshList () : numMeshes (0), meshList (nullptr) 00191 { 00192 } 00193 00194 ~NodeMeshList () 00195 { 00196 delete[] meshList; 00197 } 00198 00199 int numMeshes; 00200 uint framePassed; 00201 csBitArray onlyTestZ; 00202 bool alwaysVisible; 00203 AABBVisTreeNode* node; 00204 csSectorVisibleRenderMeshes* meshList; 00205 }; 00206 00207 class csVisibilityObjectWrapper 00208 : public scfImplementation2<csVisibilityObjectWrapper, iMovableListener, iObjectModelListener> 00209 { 00210 public: 00211 csVisibilityObjectWrapper (csOccluvis* culler, iVisibilityObject* vis_obj); 00212 00214 virtual void ObjectModelChanged (iObjectModel* model); 00215 00217 virtual void MovableChanged (iMovable* movable); 00218 00220 virtual void MovableDestroyed (iMovable*); 00221 00222 inline iVisibilityObject* GetVisObject () const 00223 { 00224 return vis_obj; 00225 } 00226 00227 private: 00228 csOccluvis* culler; 00229 iVisibilityObject* vis_obj; 00230 csBox3 oldBBox; 00231 }; 00232 00233 // Array of visibility objects. 00234 csRefArray<csVisibilityObjectWrapper> visObjects; 00235 00236 // Set to true to pass all objects regardless of visibility next VisCull. 00237 bool bAllVisible; 00238 00239 // Frame skip parameter 00240 static const unsigned int visibilityFrameSkip = 10; 00241 00242 // Hash of mesh nodes for a render view. 00243 csHash<csRefArray<NodeMeshList>*, csPtrKey<iRenderView> > nodeMeshHash; 00244 00245 // Hashes of MeshList objects for visibility objects. 00246 typedef csHash<NodeMeshList*, csPtrKey<iVisibilityObject> > VisObjMeshHash; 00247 typedef csHash<VisObjMeshHash, csPtrKey<iRenderView> > VisObjMeshHashes; 00248 VisObjMeshHashes visobjMeshHashes; 00249 00250 // Vector of vistest objects (used in the box/sphere/etc. tests). 00251 VistestObjectsArray vistest_objects; 00252 bool vistest_objects_inuse; 00253 00254 // Depth test shader type ID. 00255 csStringID depthTestID; 00256 00257 // Depth write shader type ID. 00258 csStringID depthWriteID; 00259 00260 // Fallback depth write shader type ID. 00261 csStringID fbDepthWriteID; 00262 00263 // Name of the default depth write/test shader. 00264 csString defaultShader; 00265 00266 // Shader variable stack for depth rendering. 00267 csShaderVariableStack shaderVarStack; 00268 00269 friend class F2BSorter; 00270 00271 protected: 00275 template<bool bQueryVisibility> 00276 void RenderMeshes (AABBVisTreeNode* node, 00277 iRenderView* rview, 00278 size_t& lastTicket, 00279 iShader*& lastShader, 00280 iShaderVariableContext* shadervars, 00281 NodeMeshList*& nodeMeshList); 00282 00286 template<bool bDoFrustumCulling> 00287 void TraverseTreeF2B(AABBVisTreeNode* node, uint32 frustum_mask, 00288 Front2BackData& f2bData, csRefArray<NodeMeshList>& meshList); 00289 00293 inline AABBTreeNodeVisibilityData& GetNodeVisData (AABBVisTreeNode* node) 00294 { 00295 return static_cast<AABBTreeNodeVisibilityData&> (*node); 00296 } 00297 00301 OcclusionVisibility GetNodeVisibility (AABBVisTreeNode* node, iRenderView* rview); 00302 00306 bool CheckNodeVisibility (AABBVisTreeNode* node, iRenderView* rview); 00307 00311 void BeginNodeQuery (AABBVisTreeNode* node, iRenderView* rview); 00312 00316 void GetF2BChildren (AABBVisTreeNode* node, Front2BackData& data, 00317 AABBVisTreeNode*& fChild, AABBVisTreeNode*& bChild); 00318 00322 NodeVisibility TestNodeVisibility (AABBVisTreeNode* node, Front2BackData& data, uint32& frustum_mask); 00323 00327 void MarkAllVisible (AABBVisTreeNode* node, Front2BackData& f2bData); 00328 00332 static int NodeMeshListCompare (NodeMeshList* const& object, AABBVisTreeNode* const& key); 00333 00337 void TraverseTreeBox(AABBVisTreeNode* node, 00338 VistestObjectsArray* voArray, const csBox3& box); 00339 00343 void TraverseTreeSphere(AABBVisTreeNode* node, 00344 VistestObjectsArray* voArray, const csVector3& centre, 00345 const float sqradius); 00346 00350 void TraverseTreeSphere(AABBVisTreeNode* node, 00351 iVisibilityCullerListener* viscallback, 00352 const csVector3& centre, const float sqradius); 00353 00358 void TraverseTreePlanes (AABBVisTreeNode* node, 00359 VistestObjectsArray* voArray, csPlane3* planes, 00360 uint32 frustum_mask); 00361 00366 void TraverseTreePlanes (AABBVisTreeNode* node, 00367 iVisibilityCullerListener* viscallback, 00368 csPlane3* planes, uint32 frustum_mask); 00369 00370 public: 00371 csOccluvis (iObjectRegistry *object_reg); 00372 virtual ~csOccluvis (); 00373 00374 virtual void Setup (const char* defaultShaderName); 00375 00379 virtual void RegisterVisObject (iVisibilityObject* visobj); 00380 00384 virtual void UnregisterVisObject (iVisibilityObject* visobj); 00385 00389 virtual bool VisTest (iRenderView* rview, iVisibilityCullerListener* viscallback, int, int); 00390 00391 virtual csPtr<iVisibilityObjectIterator> VisTest (const csBox3& box); 00392 00393 virtual csPtr<iVisibilityObjectIterator> VisTest (const csSphere& sphere); 00394 00395 virtual void VisTest (const csSphere& sphere, 00396 iVisibilityCullerListener* viscallback); 00397 00398 virtual csPtr<iVisibilityObjectIterator> VisTest (csPlane3* planes, int num_planes); 00399 00400 virtual void VisTest (csPlane3* planes, 00401 int num_planes, iVisibilityCullerListener* viscallback); 00402 00403 virtual csPtr<iVisibilityObjectIterator> IntersectSegmentSloppy ( 00404 const csVector3& start, const csVector3& end); 00405 00406 virtual csPtr<iVisibilityObjectIterator> IntersectSegment ( 00407 const csVector3& start, const csVector3& end, bool accurate = false, 00408 bool bf = false); 00409 00410 virtual bool IntersectSegment (const csVector3& start, 00411 const csVector3& end, csVector3& isect, float* pr = 0, 00412 iMeshWrapper** p_mesh = 0, int* poly_idx = 0, 00413 bool accurate = true, bool bf = false); 00414 00418 virtual void RenderViscull (iRenderView* rview, iShaderVariableContext* shadervars); 00419 00423 virtual void BeginPrecacheCulling () 00424 { 00425 bAllVisible = true; 00426 } 00427 00431 virtual void EndPrecacheCulling () 00432 { 00433 bAllVisible = false; 00434 } 00435 00436 virtual void PrecacheCulling () { CS_ASSERT ("Call (Begin/End)PrecacheCulling!\n"); } 00437 virtual const char* ParseCullerParameters (iDocumentNode* node) { return 0; } 00438 }; 00439 00440 class F2BSorter 00441 { 00442 public: 00443 F2BSorter (iEngine* engine, const csVector3& cameraOrigin) 00444 : cameraOrigin (cameraOrigin) 00445 { 00446 portalPriority = engine->GetRenderPriority ("portal"); 00447 } 00448 00449 bool operator() (csOccluvis::NodeMeshList* const& m1, 00450 csOccluvis::NodeMeshList* const& m2); 00451 00452 private: 00453 const csVector3& cameraOrigin; 00454 CS::Graphics::RenderPriority portalPriority; 00455 }; 00456 00457 class csOccluvisObjIt : 00458 public scfImplementation1<csOccluvisObjIt, iVisibilityObjectIterator> 00459 { 00460 private: 00461 VistestObjectsArray* vector; 00462 size_t position; 00463 bool* vistest_objects_inuse; 00464 00465 public: 00466 csOccluvisObjIt (VistestObjectsArray* vector, 00467 bool* vistest_objects_inuse) : 00468 scfImplementationType(this) 00469 { 00470 csOccluvisObjIt::vector = vector; 00471 csOccluvisObjIt::vistest_objects_inuse = vistest_objects_inuse; 00472 if (vistest_objects_inuse) *vistest_objects_inuse = true; 00473 Reset (); 00474 } 00475 virtual ~csOccluvisObjIt () 00476 { 00477 // If the vistest_objects_inuse pointer is not 0 we set the 00478 // bool to false to indicate we're no longer using the base 00479 // vector. Otherwise we delete the vector. 00480 if (vistest_objects_inuse) 00481 *vistest_objects_inuse = false; 00482 else 00483 delete vector; 00484 } 00485 00486 virtual iVisibilityObject* Next() 00487 { 00488 if (position == (size_t)-1) return 0; 00489 iVisibilityObject* vo = vector->Get (position); 00490 position++; 00491 if (position == vector->GetSize ()) 00492 position = (size_t)-1; 00493 return vo; 00494 } 00495 00496 virtual void Reset() 00497 { 00498 if (vector == 0 || vector->GetSize () < 1) 00499 position = (size_t)-1; 00500 else 00501 position = 0; 00502 } 00503 00504 virtual bool HasNext () const 00505 { 00506 return ((position != (size_t)-1) && position <= vector->GetSize ()); 00507 } 00508 }; 00509 } 00510 } 00511 00512 #include "csutil/deprecated_warn_on.h" 00513 00514 #endif // __CS_RENDERMANAGER_OCCLUVIS_H__
Generated for Crystal Space 2.1 by doxygen 1.6.1
