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 }; 00074 00075 struct QueryData : public csRefCount 00076 { 00077 unsigned int uOQuery; 00078 uint32 uQueryFrame; 00079 uint32 uNextCheck; 00080 OcclusionVisibility eResult; 00081 00082 QueryData () 00083 : uOQuery (0), uQueryFrame (0), 00084 uNextCheck (0), eResult (INVALID) 00085 {} 00086 }; 00087 00088 struct AABBTreeNodeVisibilityData 00089 { 00090 AABBTreeNodeVisibilityData () 00091 { 00092 g3d = 0; 00093 } 00094 00095 ~AABBTreeNodeVisibilityData () 00096 { 00097 if (g3d) 00098 { 00099 FreeQueryData (); 00100 } 00101 } 00102 00103 void LeafAddObject (iVisibilityObject*) 00104 { 00105 RViewQueryHash::GlobalIterator itr = RViewQueries.GetIterator (); 00106 while (itr.HasNext ()) 00107 { 00108 itr.Next ()->eResult = INVALID; 00109 } 00110 } 00111 00112 void LeafUpdateObjects (iVisibilityObject**, uint) 00113 { 00114 RViewQueryHash::GlobalIterator itr = RViewQueries.GetIterator (); 00115 while (itr.HasNext ()) 00116 { 00117 itr.Next ()->eResult = INVALID; 00118 } 00119 } 00120 00121 void NodeUpdate (const AABBTreeNodeVisibilityData& child1, 00122 const AABBTreeNodeVisibilityData& child2) 00123 { 00124 RViewQueryHash::GlobalIterator itr = RViewQueries.GetIterator (); 00125 while (itr.HasNext ()) 00126 { 00127 itr.Next ()->eResult = INVALID; 00128 } 00129 } 00130 00131 QueryData* GetQueryData (iGraphics3D* ig3d, iRenderView* rview) 00132 { 00133 csRef<QueryData> queryData = RViewQueries.Get (csPtrKey<iRenderView> (rview), csRef<QueryData> ()); 00134 00135 if (!queryData.IsValid ()) 00136 { 00137 g3d = ig3d; 00138 queryData.AttachNew (new QueryData); 00139 g3d->OQInitQueries (&queryData->uOQuery, 1); 00140 RViewQueries.Put (csPtrKey<iRenderView> (rview), queryData); 00141 } 00142 00143 return queryData; 00144 } 00145 00146 void FreeQueryData () 00147 { 00148 RViewQueryHash::GlobalIterator itr = RViewQueries.GetIterator (); 00149 while (itr.HasNext ()) 00150 { 00151 g3d->OQDelQueries (&itr.Next ()->uOQuery, 1); 00152 } 00153 00154 RViewQueries.DeleteAll (); 00155 } 00156 00157 private: 00158 iGraphics3D* g3d; 00159 00160 typedef csHash<csRef<QueryData>, csPtrKey<iRenderView> > RViewQueryHash; 00161 RViewQueryHash RViewQueries; 00162 }; 00163 00164 typedef CS::Geometry::AABBTree<iVisibilityObject, 1, AABBTreeNodeVisibilityData> AABBVisTree; 00165 typedef AABBVisTree::Node AABBVisTreeNode; 00166 00167 class CS_CRYSTALSPACE_EXPORT csOccluvis : public AABBVisTree, 00168 public scfImplementation1<csOccluvis, iVisibilityCuller> 00169 { 00170 private: 00171 iObjectRegistry *object_reg; 00172 csRef<iGraphics3D> g3d; 00173 csRef<iEngine> engine; 00174 csRef<iShaderManager> shaderMgr; 00175 csRef<iStringSet> stringSet; 00176 csRef<iShaderVarStringSet> svStrings; 00177 00178 // Structure of common f2b data. 00179 struct Front2BackData 00180 { 00181 csVector3 pos; 00182 iRenderView* rview; 00183 csPlane3* frustum; 00184 iVisibilityCullerListener* viscallback; 00185 }; 00186 00187 struct NodeMeshList : public csRefCount 00188 { 00189 NodeMeshList () : numMeshes (0), meshList (nullptr) 00190 { 00191 } 00192 00193 ~NodeMeshList () 00194 { 00195 delete[] meshList; 00196 } 00197 00198 int numMeshes; 00199 uint framePassed; 00200 csBitArray onlyTestZ; 00201 bool alwaysVisible; 00202 AABBVisTreeNode* node; 00203 csSectorVisibleRenderMeshes* meshList; 00204 }; 00205 00206 class csVisibilityObjectWrapper 00207 : public scfImplementation2<csVisibilityObjectWrapper, iMovableListener, iObjectModelListener> 00208 { 00209 public: 00210 csVisibilityObjectWrapper (csOccluvis* culler, iVisibilityObject* vis_obj); 00211 00213 virtual void ObjectModelChanged (iObjectModel* model); 00214 00216 virtual void MovableChanged (iMovable* movable); 00217 00219 virtual void MovableDestroyed (iMovable*); 00220 00221 inline iVisibilityObject* GetVisObject () const 00222 { 00223 return vis_obj; 00224 } 00225 00226 private: 00227 csOccluvis* culler; 00228 iVisibilityObject* vis_obj; 00229 csBox3 oldBBox; 00230 }; 00231 00232 // Array of visibility objects. 00233 csRefArray<csVisibilityObjectWrapper> visObjects; 00234 00235 // Set to true to pass all objects regardless of visibility next VisCull. 00236 bool bAllVisible; 00237 00238 // Frame skip parameter 00239 static const unsigned int visibilityFrameSkip = 10; 00240 00241 // Hash of mesh nodes for a render view. 00242 csHash<csRefArray<NodeMeshList>*, csPtrKey<iRenderView> > nodeMeshHash; 00243 00244 // Hashes of MeshList objects for visibility objects. 00245 typedef csHash<NodeMeshList*, csPtrKey<iVisibilityObject> > VisObjMeshHash; 00246 typedef csHash<VisObjMeshHash, csPtrKey<iRenderView> > VisObjMeshHashes; 00247 VisObjMeshHashes visobjMeshHashes; 00248 00249 // Vector of vistest objects (used in the box/sphere/etc. tests). 00250 VistestObjectsArray vistest_objects; 00251 bool vistest_objects_inuse; 00252 00253 // Depth test shader type ID. 00254 csStringID depthTestID; 00255 00256 // Depth write shader type ID. 00257 csStringID depthWriteID; 00258 00259 // Fallback depth write shader type ID. 00260 csStringID fbDepthWriteID; 00261 00262 // Name of the default depth write/test shader. 00263 csString defaultShader; 00264 00265 // Shader variable stack for depth rendering. 00266 csShaderVariableStack shaderVarStack; 00267 00268 friend class F2BSorter; 00269 00270 protected: 00274 template<bool bQueryVisibility> 00275 void RenderMeshes (AABBVisTreeNode* node, 00276 iRenderView* rview, 00277 size_t& lastTicket, 00278 iShader*& lastShader, 00279 iShaderVariableContext* shadervars, 00280 NodeMeshList*& nodeMeshList); 00281 00285 template<bool bDoFrustumCulling> 00286 void TraverseTreeF2B(AABBVisTreeNode* node, uint32 frustum_mask, 00287 Front2BackData& f2bData, csRefArray<NodeMeshList>& meshList); 00288 00292 inline AABBTreeNodeVisibilityData& GetNodeVisData (AABBVisTreeNode* node) 00293 { 00294 return static_cast<AABBTreeNodeVisibilityData&> (*node); 00295 } 00296 00300 OcclusionVisibility GetNodeVisibility (AABBVisTreeNode* node, iRenderView* rview); 00301 00305 bool CheckNodeVisibility (AABBVisTreeNode* node, iRenderView* rview); 00306 00310 void BeginNodeQuery (AABBVisTreeNode* node, iRenderView* rview); 00311 00315 void GetF2BChildren (AABBVisTreeNode* node, Front2BackData& data, 00316 AABBVisTreeNode*& fChild, AABBVisTreeNode*& bChild); 00317 00321 NodeVisibility TestNodeVisibility (AABBVisTreeNode* node, Front2BackData& data, uint32& frustum_mask); 00322 00326 void MarkAllVisible (AABBVisTreeNode* node, Front2BackData& f2bData); 00327 00331 static int NodeMeshListCompare (NodeMeshList* const& object, AABBVisTreeNode* const& key); 00332 00336 void TraverseTreeBox(AABBVisTreeNode* node, 00337 VistestObjectsArray* voArray, const csBox3& box); 00338 00342 void TraverseTreeSphere(AABBVisTreeNode* node, 00343 VistestObjectsArray* voArray, const csVector3& centre, 00344 const float sqradius); 00345 00349 void TraverseTreeSphere(AABBVisTreeNode* node, 00350 iVisibilityCullerListener* viscallback, 00351 const csVector3& centre, const float sqradius); 00352 00357 void TraverseTreePlanes (AABBVisTreeNode* node, 00358 VistestObjectsArray* voArray, csPlane3* planes, 00359 uint32 frustum_mask); 00360 00365 void TraverseTreePlanes (AABBVisTreeNode* node, 00366 iVisibilityCullerListener* viscallback, 00367 csPlane3* planes, uint32 frustum_mask); 00368 00369 public: 00370 csOccluvis (iObjectRegistry *object_reg); 00371 virtual ~csOccluvis (); 00372 00373 virtual void Setup (const char* defaultShaderName); 00374 00378 virtual void RegisterVisObject (iVisibilityObject* visobj); 00379 00383 virtual void UnregisterVisObject (iVisibilityObject* visobj); 00384 00388 virtual bool VisTest (iRenderView* rview, iVisibilityCullerListener* viscallback, int, int); 00389 00390 virtual csPtr<iVisibilityObjectIterator> VisTest (const csBox3& box); 00391 00392 virtual csPtr<iVisibilityObjectIterator> VisTest (const csSphere& sphere); 00393 00394 virtual void VisTest (const csSphere& sphere, 00395 iVisibilityCullerListener* viscallback); 00396 00397 virtual csPtr<iVisibilityObjectIterator> VisTest (csPlane3* planes, int num_planes); 00398 00399 virtual void VisTest (csPlane3* planes, 00400 int num_planes, iVisibilityCullerListener* viscallback); 00401 00402 virtual csPtr<iVisibilityObjectIterator> IntersectSegmentSloppy ( 00403 const csVector3& start, const csVector3& end); 00404 00405 virtual csPtr<iVisibilityObjectIterator> IntersectSegment ( 00406 const csVector3& start, const csVector3& end, bool accurate = false); 00407 00408 virtual bool IntersectSegment (const csVector3& start, 00409 const csVector3& end, csVector3& isect, float* pr = 0, 00410 iMeshWrapper** p_mesh = 0, int* poly_idx = 0, 00411 bool accurate = true); 00412 00416 virtual void RenderViscull (iRenderView* rview, iShaderVariableContext* shadervars); 00417 00421 virtual void BeginPrecacheCulling () 00422 { 00423 bAllVisible = true; 00424 } 00425 00429 virtual void EndPrecacheCulling () 00430 { 00431 bAllVisible = false; 00432 } 00433 00434 virtual void PrecacheCulling () { CS_ASSERT ("Call (Begin/End)PrecacheCulling!\n"); } 00435 virtual const char* ParseCullerParameters (iDocumentNode* node) { return 0; } 00436 }; 00437 00438 class F2BSorter 00439 { 00440 public: 00441 F2BSorter (iEngine* engine, const csVector3& cameraOrigin) 00442 : cameraOrigin (cameraOrigin) 00443 { 00444 portalPriority = engine->GetRenderPriority ("portal"); 00445 } 00446 00447 bool operator() (csOccluvis::NodeMeshList* const& m1, 00448 csOccluvis::NodeMeshList* const& m2); 00449 00450 private: 00451 const csVector3& cameraOrigin; 00452 CS::Graphics::RenderPriority portalPriority; 00453 }; 00454 00455 class csOccluvisObjIt : 00456 public scfImplementation1<csOccluvisObjIt, iVisibilityObjectIterator> 00457 { 00458 private: 00459 VistestObjectsArray* vector; 00460 size_t position; 00461 bool* vistest_objects_inuse; 00462 00463 public: 00464 csOccluvisObjIt (VistestObjectsArray* vector, 00465 bool* vistest_objects_inuse) : 00466 scfImplementationType(this) 00467 { 00468 csOccluvisObjIt::vector = vector; 00469 csOccluvisObjIt::vistest_objects_inuse = vistest_objects_inuse; 00470 if (vistest_objects_inuse) *vistest_objects_inuse = true; 00471 Reset (); 00472 } 00473 virtual ~csOccluvisObjIt () 00474 { 00475 // If the vistest_objects_inuse pointer is not 0 we set the 00476 // bool to false to indicate we're no longer using the base 00477 // vector. Otherwise we delete the vector. 00478 if (vistest_objects_inuse) 00479 *vistest_objects_inuse = false; 00480 else 00481 delete vector; 00482 } 00483 00484 virtual iVisibilityObject* Next() 00485 { 00486 if (position == (size_t)-1) return 0; 00487 iVisibilityObject* vo = vector->Get (position); 00488 position++; 00489 if (position == vector->GetSize ()) 00490 position = (size_t)-1; 00491 return vo; 00492 } 00493 00494 virtual void Reset() 00495 { 00496 if (vector == 0 || vector->GetSize () < 1) 00497 position = (size_t)-1; 00498 else 00499 position = 0; 00500 } 00501 00502 virtual bool HasNext () const 00503 { 00504 return ((position != (size_t)-1) && position <= vector->GetSize ()); 00505 } 00506 }; 00507 } 00508 } 00509 00510 #include "csutil/deprecated_warn_on.h" 00511 00512 #endif // __CS_RENDERMANAGER_OCCLUVIS_H__
Generated for Crystal Space 2.0 by doxygen 1.6.1