PixelLightAPI
.
|
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__
|