#include "OgrePlatformQueryManager.h" #include "OcclusionQuery.h" #include #include #include namespace Ogre { //----------------------------------------------------------------------- PlatformQueryManager::PlatformQueryManager(PlatformHierarchyInterface *hierarchyInterface, Viewport *vp): QueryManager(hierarchyInterface), mViewport(vp) { } //----------------------------------------------------------------------- bool PlatformQueryManager::ShootRay(const Ray &ray, std::vector *visibleMeshes, bool isGlobalLine) { // run OGRE ray shooting query return false; } //----------------------------------------------------------------------- void PlatformQueryManager::ComputeCameraVisibility(const Camera &camera, InfoContainer *visibleNodes, InfoContainer *visibleGeometry, bool relativeVisibility) { // we need access to the scene manager and the rendersystem PlatformHierarchyInterface *pfHierarchyInterface = dynamic_cast(mHierarchyInterface); //-- Render scene to get conservative visibility and fill depth buffer // can do const_cast because Camera no changed in renderScene Camera *pCam = const_cast(&camera); bool overlayEnabled = mViewport->getOverlaysEnabled(); mViewport->setOverlaysEnabled(false); pfHierarchyInterface->GetSceneManager()->_renderScene(pCam, mViewport, false); /* Two query lists: We test two to get exact visibility with regard to the current camera and issue all queries at once to avoid starvation & stalls. */ GtpVisibility::QueryList queryList[2]; // get rendered hierarchy nodes GtpVisibility::HierarchyNodeList *nodeList = mHierarchyInterface->GetRenderedNodes(); // vector for storing entities of meshes GtpVisibility::GeometryList geometryList; GtpVisibility::HierarchyNodeList::iterator nodeIt, nodeIt_end = nodeList->end(); // geometry list has still do be built GtpVisibility::GeometryList::iterator geometryIt, geometryIt_end; // to obtain the correct number of projected pixels, depth write must be disabled bool enableDepthWrite = false; // this option must be provided by the scene manager pfHierarchyInterface->GetSceneManager()->setOption("DepthWrite", &enableDepthWrite); /* relative visiblity: 1) get visible pixels count of objects 2) clear frame buffer 3) get projected visible pixels count: test all objects again without depth write (set as option in scene manager) 4) calculate ratio between visible vs. projected pixels */ // for relative visibility we need 2 rendering passes int n = relativeVisibility ? 2 : 1; for (int i=0; ibegin(); nodeIt != nodeIt_end; ++nodeIt) { // TODO: DELETE QUERIES FROM PREVIOUS RENDER queryList[i].push_back(mHierarchyInterface->IssueOcclusionQuery(*nodeIt, false)); // store geometry of the hierarchy node in a geometry list (only once!) if (i == 0) { mHierarchyInterface->GetGeometry(*nodeIt, &geometryList, false); } } geometryIt_end = geometryList.end(); //-- add queries for geometry for (geometryIt = geometryList.begin(); geometryIt != geometryIt_end; ++geometryIt) { queryList[i].push_back(mHierarchyInterface->IssueOcclusionQuery(*geometryIt)); } pfHierarchyInterface->GetRenderSystem()->clearFrameBuffer(FBT_DEPTH); } enableDepthWrite = true; // this option must be provided by the scene manager pfHierarchyInterface->GetSceneManager()->setOption("DepthWrite", &enableDepthWrite); mViewport->setOverlaysEnabled(overlayEnabled); //---- collect results unsigned int visiblePixels = 0; GtpVisibility::QueryList::iterator visQueryIt, projQueryIt; visQueryIt = queryList[0].begin(); projQueryIt = queryList[1].begin(); for (nodeIt = nodeList->begin(); nodeIt != nodeIt_end; ++nodeIt) { (*visQueryIt)->GetQueryResult(visiblePixels, true); float vis = (float)visiblePixels; if (relativeVisibility) { (*projQueryIt)->GetQueryResult(visiblePixels, true); if (visiblePixels > 0) { vis /= (float) visiblePixels; } ++projQueryIt; } ++visQueryIt; // leave nodes with visibilty 0 in queue: // happens if node is intersected by near plane visibleNodes->push_back(GtpVisibility::NodeInfo(*nodeIt, vis)); } //---- queries for geometry geometryIt_end = geometryList.end(); for (geometryIt = geometryList.begin(); geometryIt != geometryIt_end; ++geometryIt) { (*visQueryIt)->GetQueryResult(visiblePixels, true); float vis = (float)visiblePixels; bool isVisible = visiblePixels > 0; if (relativeVisibility) { (*projQueryIt)->GetQueryResult(visiblePixels, true); if (visiblePixels) { vis /= (float) visiblePixels; } ++projQueryIt; } ++visQueryIt; // approximate depth ordering during rendering => // geometry maybe occluded if (isVisible) { visibleGeometry->push_back(GtpVisibility::MeshInfo(*geometryIt, vis)); } } } //----------------------------------------------------------------------- void PlatformQueryManager::ComputeFromPointVisibility(const Vector3 &point, InfoContainer *visibleNodes, InfoContainer *visibleGeometry, bool relativeVisibility) { } //----------------------------------------------------------------------- void PlatformQueryManager::SetViewport(Viewport *vp) { mViewport = vp; } } // namespace Ogre