00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
00043 enum NodeVisibility
00044 {
00045 NODE_INVISIBLE,
00046 NODE_VISIBLE,
00047 NODE_INSIDE
00048 };
00049
00050
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;
00068 float r;
00069 iMeshWrapper* mesh;
00070 int polygon_idx;
00071 VistestObjectsArray* vector;
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
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
00233 csRefArray<csVisibilityObjectWrapper> visObjects;
00234
00235
00236 bool bAllVisible;
00237
00238
00239 static const unsigned int visibilityFrameSkip = 10;
00240
00241
00242 csHash<csRefArray<NodeMeshList>*, csPtrKey<iRenderView> > nodeMeshHash;
00243
00244
00245 typedef csHash<NodeMeshList*, csPtrKey<iVisibilityObject> > VisObjMeshHash;
00246 typedef csHash<VisObjMeshHash, csPtrKey<iRenderView> > VisObjMeshHashes;
00247 VisObjMeshHashes visobjMeshHashes;
00248
00249
00250 VistestObjectsArray vistest_objects;
00251 bool vistest_objects_inuse;
00252
00253
00254 csStringID depthTestID;
00255
00256
00257 csStringID depthWriteID;
00258
00259
00260 csStringID fbDepthWriteID;
00261
00262
00263 csString defaultShader;
00264
00265
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
00476
00477
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__