CrystalSpace

Public API Reference

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.7.6.1