#include "OgrePlatformQueryManager.h" #include "OcclusionQuery.h" #include #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 projectedPixels) { // 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 = projectedPixels ? 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; std::pair::iterator, bool> insertNode; std::pair::iterator, bool> insertGeom; 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); int visiblePixels = visiblePixels; int projectedPixels = 0; if (projectedPixels) { (*projQueryIt)->GetQueryResult(visiblePixels, true); mProjectedPixels = visiblePixels; ++projQueryIt; } ++visQueryIt; // nodes with visibilty 0 in queue: // happens if node is intersected by near plane if (visiblePixels > 0) { visibleNodes->push_back(GtpVisibility::NodeInfo(*nodeIt, visiblePixels, projectedPixels)); } } //---- queries for geometry geometryIt_end = geometryList.end(); for (geometryIt = geometryList.begin(); geometryIt != geometryIt_end; ++geometryIt) { (*visQueryIt)->GetQueryResult(visiblePixels, true); int visiblePixels = visiblePixels; int projectedPixels = 0; if (projectedPixels) { (*projQueryIt)->GetQueryResult(visiblePixels, true); mProjectedPixels = visiblePixels; ++projQueryIt; } ++visQueryIt; // approximate depth ordering during rendering => // geometry maybe occluded if (isVisible) { visibleGeometry->push_back(GtpVisibility::MeshInfo(*geometryIt,visiblePixels, projectedPixels)); } } } //----------------------------------------------------------------------- inline bool nodeinfo_eq(const GtpVisibility::NodeInfo &info1, const GtpVisibility::NodeInfo &info2) { return info1.GetNode() == info2.GetNode(); } //----------------------------------------------------------------------- inline bool meshinfo_eq(const GtpVisibility::MeshInfo &info1, const GtpVisibility::MeshInfo &info2) { return info1.GetMesh() == info2.GetMesh(); } //----------------------------------------------------------------------- void PlatformQueryManager::ComputeFromPointVisibility(const Vector3 &point, InfoContainer *visibleNodes, InfoContainer *visibleGeometry, bool projectedPixels) { SceneManager *sm = dynamic_cast(mHierarchyInterface)->GetSceneManager(); Camera *cam = sm->createCamera("PointQueryCam"); //save old camera Camera *savedCam = mViewport->getCamera(); // --- initialise new camera mViewport->setCamera(cam); cam->setPosition(point); cam->setNearClipDistance(savedCam->getNearClipDistance()); cam->setFarClipDistance(savedCam->getFarClipDistance()); // set frustum to 45 degrees so all the scene can be captured with 6 shots cam->setAspectRatio(1.0); cam->setFOVy(Radian(Math::HALF_PI)); std::stringstream d; d << "old camera: " + StringConverter::toString(savedCam->getDerivedPosition()) + " " + "O: " + StringConverter::toString(savedCam->getDerivedOrientation()); LogManager::getSingleton().logMessage(d.str()); int sign = -1; // ---- capture visibility from all 6 directions for (int i=0; i < 6; i++) { sign *= -1; // Print camera details std::stringstream d; d << "Point query camera: " + StringConverter::toString(cam->getDerivedPosition()) + " " + "O: " + StringConverter::toString(cam->getDerivedOrientation()); LogManager::getSingleton().logMessage(d.str()); ComputeCameraVisibility(*cam, visibleNodes, visibleGeometry, projectedPixels); //mViewport->getTarget()->update(); for(int j=0; j<10000000; j++) printf("HAAHHAHAHAHAH"); // permute directions Vector3 dir(0,0,0); dir[i/2] = sign; cam->setDirection(dir); } // reset camera mViewport->setCamera(savedCam); // --- single out duplicates // before duplicates can be deleted we have to add up visibility // --- visible nodes sort(visibleNodes->begin(), visibleNodes->end()); InfoContainer::iterator visibleNodesIt, visibleNodesIt_end = visibleNodes->end(); GtpVisibility::NodeInfo *nodeInfo = NULL; for (visibleNodesIt = visibleNodes->begin(); visibleNodesIt != visibleNodesIt_end; ++visibleNodesIt); { if (!nodeInfo || (nodeInfo->GetNode() != (*visibleNodesIt).GetNode())) { nodeInfo = &(*visibleNodesIt); } else { // add visibility nodeInfo->SetVisibility(nodeInfo->GetVisiblePixels() + (*visibleNodesIt).GetVisiblePixels()); } } // now delete duplicates visibleNodes->erase( std::unique(visibleNodes->begin(), visibleNodes->end(), nodeinfo_eq), visibleNodes->end()); // --- visible geometry sort(visibleGeometry->begin(), visibleGeometry->end()); InfoContainer::iterator visibleGeomIt, visibleGeomIt_end = visibleGeometry->end(); GtpVisibility::MeshInfo *geomInfo = NULL; for (visibleGeomIt = visibleGeometry->begin(); visibleGeomIt != visibleGeomIt_end; ++visibleGeomIt); { if (!geomInfo || (geomInfo->GetMesh() != (*visibleGeomIt).GetMesh())) { geomInfo = &(*visibleGeomIt); } else // info points to equal mesh { // add visibility geomInfo->SetVisibility(geomInfo->GetVisiblePixels() + (*visibleGeomIt).GetVisiblePixels()); } } // now delete duplicates visibleGeometry->erase(std::unique(visibleGeometry->begin(), visibleGeometry->end(), meshinfo_eq), visibleGeometry->end()); } //----------------------------------------------------------------------- void PlatformQueryManager::SetViewport(Viewport *vp) { mViewport = vp; } } // namespace Ogre