PixelLightAPI  .
SQCull.h
Go to the documentation of this file.
00001 /*********************************************************\
00002  *  File: SQCull.h                                       *
00003  *
00004  *  Copyright (C) 2002-2012 The PixelLight Team (http://www.pixellight.org/)
00005  *
00006  *  This file is part of PixelLight.
00007  *
00008  *  PixelLight is free software: you can redistribute it and/or modify
00009  *  it under the terms of the GNU Lesser General Public License as published by
00010  *  the Free Software Foundation, either version 3 of the License, or
00011  *  (at your option) any later version.
00012  *
00013  *  PixelLight is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016  *  GNU Lesser General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU Lesser General Public License
00019  *  along with PixelLight. If not, see <http://www.gnu.org/licenses/>.
00020 \*********************************************************/
00021 
00022 
00023 #ifndef __PLSCENE_SCENEQUERY_CULL_H__
00024 #define __PLSCENE_SCENEQUERY_CULL_H__
00025 #pragma once
00026 
00027 
00028 //[-------------------------------------------------------]
00029 //[ Includes                                              ]
00030 //[-------------------------------------------------------]
00031 #include <PLCore/Container/Pool.h>
00032 #include <PLCore/Container/Array.h>
00033 #include <PLCore/Container/Bitset.h>
00034 #include <PLCore/Container/HashMap.h>
00035 #include <PLCore/Container/BinaryHeap.h>
00036 #include <PLMath/PlaneSet.h>
00037 #include <PLMath/Matrix4x4.h>
00038 #include "PLScene/Scene/SceneQuery.h"
00039 
00040 
00041 //[-------------------------------------------------------]
00042 //[ Forward declarations                                  ]
00043 //[-------------------------------------------------------]
00044 namespace PLRenderer {
00045     class OcclusionQuery;
00046 }
00047 namespace PLScene {
00048     class VisContainer;
00049     class SceneHierarchy;
00050     class SceneNodeHandler;
00051     class SceneQueryHandler;
00052     class SceneHierarchyNode;
00053 }
00054 
00055 
00056 //[-------------------------------------------------------]
00057 //[ Namespace                                             ]
00058 //[-------------------------------------------------------]
00059 namespace PLScene {
00060 
00061 
00062 //[-------------------------------------------------------]
00063 //[ Classes                                               ]
00064 //[-------------------------------------------------------]
00065 /**
00066 *  @brief
00067 *    Visibility determination scene query class
00068 *
00069 *  @remarks
00070 *    This scene query is used to request the current visible scene nodes. (Hidden Surface Removal (HSR))
00071 *    You can choose between different culling algorithms whereby the advanced techniques not only ignore
00072 *    scene nodes outside the view frustum but also scene nodes which are hidden through other scene nodes.
00073 *    Additionally, some statistics are calculated. In optimal situations, cells&portals, frustum culling and
00074 *    occlusion culling are used all together to get the desired results.
00075 *    The result of the whole process is called PVS. (Potential Visibility Set)
00076 *
00077 *  @note
00078 *    - The 'PerformQuery()'-call must be done within the correct render target and with a valid set
00079 *      viewport and scissor rectangle
00080 */
00081 class SQCull : public SceneQuery {
00082 
00083 
00084     //[-------------------------------------------------------]
00085     //[ Friends                                               ]
00086     //[-------------------------------------------------------]
00087     friend class VisContainer;
00088 
00089 
00090     //[-------------------------------------------------------]
00091     //[ Public definitions                                    ]
00092     //[-------------------------------------------------------]
00093     public:
00094         /**
00095         *  @brief
00096         *    Cull mode
00097         */
00098         enum EMode {
00099             Frustum     = 0,    /**< Culls the scene with view frustum culling only */
00100             StopAndWait = 1,    /**< Culls the scene with the hierarchical stop and wait algorithm */
00101             Coherent    = 2,    /**< Culls the scene with the coherent hierarchical algorithm (CHC) */
00102             Previous    = 3     /**< Culls the scene using the visibility information of the previous frame */
00103         };
00104 
00105 
00106     //[-------------------------------------------------------]
00107     //[ RTTI interface                                        ]
00108     //[-------------------------------------------------------]
00109     pl_class(PLS_RTTI_EXPORT, SQCull, "PLScene", PLScene::SceneQuery, "Visibility determination scene query class")
00110         // Constructors
00111         pl_constructor_0(DefaultConstructor,    "Default constructor",  "")
00112     pl_class_end
00113 
00114 
00115     //[-------------------------------------------------------]
00116     //[ Public structures                                     ]
00117     //[-------------------------------------------------------]
00118     public:
00119         /**
00120         *  @brief
00121         *    Several statistics of the culling process
00122         */
00123         struct Statistics {
00124             PLCore::uint64 nCullTime;                           /**< Culling time of the specified algorithm (in ms) */
00125             PLCore::uint32 nNumOfTraversedNodes;                /**< Number of traversed nodes */
00126             PLCore::uint32 nNumOfOccluders;                     /**< Number of used occludes */
00127             PLCore::uint32 nNumOfQueryCulledNodes;              /**< Number of hierarchy nodes culled by the occlusion query */
00128             PLCore::uint32 nNumOfSkippedFrustumTests;           /**< Number of skipped frustum tests because for instance the parent node was
00129                                                                      already complete within the frustum. (hierarchy node & scene node tests) */
00130             PLCore::uint32 nNumOfFrustumCulledNodes;            /**< Number of hierarchy nodes culled by the frustum culling only */
00131             PLCore::uint32 nNumOfNearPlaneIntersectingNodes;    /**< Number of hierarchy nodes with near plane intersection */
00132             PLCore::uint32 nNumOfVisibleSceneNodes;             /**< Number of visible scene nodes */
00133             PLCore::uint32 nNumOfQueries;                       /**< Total number of occlusion queries */
00134             PLCore::uint32 nMaxNumOfQueries;                    /**< Maximum number of occlusion queries active at the same time */
00135             bool           bWaitForQueryResult;                 /**< Was waiting for a query result required? */
00136         };
00137 
00138 
00139     //[-------------------------------------------------------]
00140     //[ Public functions                                      ]
00141     //[-------------------------------------------------------]
00142     public:
00143         /**
00144         *  @brief
00145         *    Default constructor
00146         */
00147         PLS_API SQCull();
00148 
00149         /**
00150         *  @brief
00151         *    Destructor
00152         */
00153         PLS_API virtual ~SQCull();
00154 
00155         /**
00156         *  @brief
00157         *    Returns the used cull mode
00158         *
00159         *  @return
00160         *    Used cull mode
00161         */
00162         PLS_API EMode GetMode() const;
00163 
00164         /**
00165         *  @brief
00166         *    Sets the used cull mode
00167         *
00168         *  @param[in] nMode
00169         *    Used cull mode
00170         */
00171         PLS_API void SetMode(EMode nMode = Coherent);
00172 
00173         /**
00174         *  @brief
00175         *    Returns visibility threshold
00176         *
00177         *  @return
00178         *    Visibility threshold
00179         *
00180         *  @remarks
00181         *    The visibility threshold is dependent of the render target dimension. If
00182         *    you set the visibility threshold to 100 and your render target dimension
00183         *    is 100x100 scene nodes may ugly disappear and at a render target dimension
00184         *    of 1000x1000 you can't see such disappearances.
00185         *
00186         *  @note
00187         *    - Used by the render modes StopAndWait and Coherent
00188         */
00189         PLS_API PLCore::uint32 GetVisibilityThreshold() const;
00190 
00191         /**
00192         *  @brief
00193         *    Sets visible pixels threshold for visibility classification
00194         *
00195         *  @param[in] nThreshold
00196         *    Threshold
00197         *
00198         *  @see
00199         *    - GetVisibilityThreshold()
00200         */
00201         PLS_API void SetVisibilityThreshold(PLCore::uint32 nThreshold = 1);
00202 
00203         /**
00204         *  @brief
00205         *    Returns the statistics
00206         *
00207         *  @return
00208         *    Statistics
00209         */
00210         PLS_API const Statistics &GetStatistics() const;
00211 
00212         /**
00213         *  @brief
00214         *    Returns the container the camera is in
00215         *
00216         *  @return
00217         *    Container the camera is in, a null pointer on error
00218         */
00219         PLS_API SceneContainer *GetCameraContainer() const;
00220 
00221         /**
00222         *  @brief
00223         *    Sets the container the camera is in
00224         *
00225         *  @param[in] pCameraContainer
00226         *    Container the camera is in, can be a null pointer
00227         *
00228         *  @return
00229         *    'true' if all went fine, else 'false'
00230         */
00231         PLS_API bool SetCameraContainer(SceneContainer *pCameraContainer);
00232 
00233         /**
00234         *  @brief
00235         *    Returns the used camera position
00236         *
00237         *  @return
00238         *    The used camera position (container space)
00239         */
00240         PLS_API const PLMath::Vector3 &GetCameraPosition() const;
00241 
00242         /**
00243         *  @brief
00244         *    Sets the used camera position
00245         *
00246         *  @param[in] vPos
00247         *    The used camera position (container space)
00248         */
00249         PLS_API void SetCameraPosition(const PLMath::Vector3 &vPos);
00250 
00251         /**
00252         *  @brief
00253         *    Returns the used view frustum
00254         *
00255         *  @return
00256         *    The used view frustum (container space)
00257         */
00258         PLS_API const PLMath::PlaneSet &GetViewFrustum() const;
00259 
00260         /**
00261         *  @brief
00262         *    Sets the used view frustum
00263         *
00264         *  @param[in] cFrustum
00265         *    The used view frustum (container space)
00266         */
00267         PLS_API void SetViewFrustum(const PLMath::PlaneSet &cFrustum);
00268 
00269         // [TODO] Cleanup
00270         PLS_API const PLMath::Matrix4x4 &GetProjectionMatrix() const;
00271         PLS_API void SetProjectionMatrix(const PLMath::Matrix4x4 &mProjection);
00272         PLS_API const PLMath::Matrix4x4 &GetViewMatrix() const;
00273         PLS_API void SetViewMatrix(const PLMath::Matrix4x4 &mView);
00274         PLS_API const PLMath::Matrix4x4 &GetViewProjectionMatrix() const;
00275         PLS_API void SetViewProjectionMatrix(const PLMath::Matrix4x4 &mViewProjection);
00276 
00277         /**
00278         *  @brief
00279         *    Returns the visibility root container
00280         *
00281         *  @return
00282         *    The visibility root container, a null pointer on error
00283         *
00284         *  @see
00285         *    - GetVisContainer()
00286         */
00287         PLS_API const VisContainer *GetVisRootContainer() const;
00288 
00289         /**
00290         *  @brief
00291         *    Returns the visibility container this scene query belongs to
00292         *
00293         *  @return
00294         *    The visibility container this scene query belongs to, same as
00295         *    GetRootContainer() if this is the visibility root container
00296         *
00297         *  @remarks
00298         *    After you performed the cull query (= visibility determination) you can use
00299         *    this function to get the resulting visibility scene tree. Using this tree,
00300         *    you can render the visible parts of the scene without any effort.
00301         */
00302         PLS_API const VisContainer &GetVisContainer() const;
00303 
00304 
00305     //[-------------------------------------------------------]
00306     //[ Private functions                                     ]
00307     //[-------------------------------------------------------]
00308     private:
00309         /**
00310         *  @brief
00311         *    Initialize the statistics
00312         */
00313         void InitStatistics();
00314 
00315         /**
00316         *  @brief
00317         *    Resizes the arrays with the additional scene hierarchy node information if required
00318         */
00319         void ResizeArrays();
00320 
00321         /**
00322         *  @brief
00323         *    This is the standard culling traversal algorithm doing only frustum culling
00324         *
00325         *  @return
00326         *    'false' if the query was cancelled by the user, else 'true'
00327         */
00328         bool CullFrustum();
00329 
00330         /**
00331         *  @brief
00332         *    This is the naive algorithm always waiting for the query to finish
00333         *
00334         *  @return
00335         *    'false' if the query was cancelled by the user, else 'true'
00336         */
00337         bool CullStopAndWait();
00338 
00339         /**
00340         *  @brief
00341         *    Culls the scene using coherent occlusion culling
00342         *
00343         *  @remarks
00344         *    It uses a query queue and frame-to-frame coherence in order to prevent
00345         *    stalls and avoid unnecessary queries. This culling algorithm is basing on
00346         *    "Coherent Hierarchical Culling: Hardware Occlusion Queries Made Useful"
00347         *    (http://www.cg.tuwien.ac.at/research/vr/chcull/)
00348         *
00349         *  @return
00350         *    'false' if the query was cancelled by the user, else 'true'
00351         */
00352         bool CullCoherentWithQueue();
00353 
00354         /**
00355         *  @brief
00356         *    Traverses a node
00357         *
00358         *  @param[in] cHierarchyNode
00359         *    Hierarchy node to traverse
00360         *
00361         *  @return
00362         *    'false' if the query was cancelled by the user, else 'true'
00363         */
00364         bool TraverseNode(const SceneHierarchyNode &cHierarchyNode);
00365 
00366         /**
00367         *  @brief
00368         *    Visibility is pulled up from visibility of children
00369         *
00370         *  @param[in] pHierarchyNode
00371         *    Hierarchy node we currently work on, can be a null pointer
00372         */
00373         void PullUpVisibility(const SceneHierarchyNode *pHierarchyNode);
00374 
00375         /**
00376         *  @brief
00377         *    Issues occlusion query for specified node
00378         *
00379         *  @param[in] cHierarchyNode
00380         *    Hierarchy node to work on
00381         *  @param[in] bWasVisible
00382         *    Was this hierarchy node visible at the last frame?
00383         */
00384         void IssueOcclusionQuery(const SceneHierarchyNode &cHierarchyNode, bool bWasVisible);
00385 
00386         /**
00387         *  @brief
00388         *    Is result available from query queue?
00389         *
00390         *  @param[in] cHierarchyNode
00391         *    Hierarchy node we currently work on
00392         *
00393         *  @return
00394         *    'true' if the result is available, else 'false'
00395         */
00396         bool ResultAvailable(const SceneHierarchyNode &cHierarchyNode);
00397 
00398         /**
00399         *  @brief
00400         *    Returns occlusion query result for specified node
00401         *
00402         *  @param[in] cHierarchyNode
00403         *    Hierarchy node we currently work on
00404         */
00405         PLCore::uint32 GetOcclusionQueryResult(const SceneHierarchyNode &cHierarchyNode);
00406 
00407         /**
00408         *  @brief
00409         *    Checks whether a hierarchy node is within the view frustum
00410         *
00411         *  @param[in]  cHierarchyNode
00412         *    Hierarchy node we currently work on
00413         *  @param[out] bIntersects
00414         *    Will receive the information whether or not the hierarchy node is intersecting
00415         *    the near clip plane
00416         *  @param[in]  bCheckNear
00417         *    Perform near clip plane intersection test?
00418         *
00419         *  @remarks
00420         *    bIntersects returns true if bounding box intersects the near plane.
00421         *    additionally stores the distance from the near plane to the center of the
00422         *    current node with the node. this will for front-to-back ordering
00423         *
00424         *  @return
00425         *    'true' if bounding box is culled by view frustum culling, else 'false'
00426         */
00427         bool InsideViewFrustum(const SceneHierarchyNode &cHierarchyNode, bool &bIntersects, bool bCheckNear = true);
00428 
00429 
00430     //[-------------------------------------------------------]
00431     //[ Private data                                          ]
00432     //[-------------------------------------------------------]
00433     private:
00434         // General data
00435         EMode              m_nMode;                     /**< Used cull mode */
00436         PLCore::uint32     m_nVisibilityThreshold;      /**< Visibility threshold */
00437         Statistics         m_sStatistics;               /**< Some statistics */
00438         SceneNodeHandler  *m_pCameraContainer;          /**< Container the camera is in */
00439         bool               m_bCameraInCell;             /**< Is the camera within a cell? */
00440         PLMath::Vector3    m_vCameraPosition;           /**< Camera position (container space) */
00441         PLMath::PlaneSet   m_cViewFrustum;              /**< View frustum used for the query (container space) */
00442         bool               m_bSetIdentityWorldMatrix;   /**< Do we need to set the world matrix to identity? */
00443         SceneHierarchy    *m_pHierarchy;                /**< The hierarchy we are working on */
00444         PLMath::Matrix4x4  m_mProjection;               /**< Projection matrix */
00445         PLMath::Matrix4x4  m_mView;                     /**< View matrix */
00446         PLMath::Matrix4x4  m_mViewProjection;           /**< View projection matrix */
00447 
00448         // Frame to frame data
00449         PLCore::uint32                  m_nFrame;               /**< Current frame */
00450         PLCore::Bitset                  m_lstVisibility;        /**< Visibility state of all hierarchy nodes */
00451         PLCore::Bitset                  m_lstTotalVisibility;   /**< Total visibility state of all hierarchy nodes */
00452         PLCore::Array<PLCore::uint32>   m_lstLastVisited;       /**< Frame the node was visited last time */
00453 
00454         // Current frame data
00455         PLCore::uint32                                   m_nCurrentQueries;         /**< Current number of queries */
00456         PLCore::uint32                                   m_nOcclusionQueries;       /**< Number of occlusion queries */
00457         PLRenderer::OcclusionQuery                     **m_ppOcclusionQueries;      /**< Occlusion queries */
00458         PLCore::BinaryHeap<float, SceneHierarchyNode*>   m_lstDistanceQueue;        /**< Distance queue */
00459         PLCore::BinaryHeap<float, SceneNode*>            m_lstNodeDistanceQueue;    /**< Distance queue for the scene nodes*/
00460 
00461         VisContainer *m_pVisRootContainer;  /**< Visibility root container */
00462         VisContainer *m_pVisContainer;      /**< Visibility container (do NOT use this variable directly, use GetVisContainer()!) */
00463 
00464 
00465     //[-------------------------------------------------------]
00466     //[ Public virtual SceneQuery functions                   ]
00467     //[-------------------------------------------------------]
00468     public:
00469         PLS_API virtual bool PerformQuery() override;
00470 
00471 
00472 };
00473 
00474 
00475 //[-------------------------------------------------------]
00476 //[ Namespace                                             ]
00477 //[-------------------------------------------------------]
00478 } // PLScene
00479 
00480 
00481 #endif // __PLSCENE_SCENEQUERY_CULL_H__


PixelLight PixelLight 0.9.11-R1
Copyright (C) 2002-2012 by The PixelLight Team
Last modified Thu Feb 23 2012 14:09:00
The content of this PixelLight document is published under the
Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported