#include "OgreItemBufferQueryManager.h" #include #include #include namespace Ogre { //----------------------------------------------------------------------- ItemBufferQueryManager::ItemBufferQueryManager(PlatformHierarchyInterface *hierarchyInterface, Viewport *vp): PlatformQueryManager(hierarchyInterface, vp) { } //----------------------------------------------------------------------- bool ItemBufferQueryManager::ShootRay(const Ray &ray, std::vector *visibleMeshes, bool isGlobalLine) { // run OGRE ray shooting query return false; } //----------------------------------------------------------------------- void ItemBufferQueryManager::ComputeCameraVisibility(const Camera &camera, InfoContainer *visibleNodes, InfoContainer *visibleGeometry, bool relativeVisibility) { // initialise item buffer (if not already initialised) InitItemBuffer(visibleNodes, visibleGeometry); // we need access to the scene manager and the rendersystem PlatformHierarchyInterface *pfHierarchyInterface = dynamic_cast(mHierarchyInterface); SceneManager *sm = pfHierarchyInterface->GetSceneManager(); // ---- Render scene with item buffer (i.e., objects with their id as color codes) // const_cast allowed because camera is not changed in renderScene Camera *pCam = const_cast(&camera); // disable overlays, reset them later bool overlayEnabled = mViewport->getOverlaysEnabled(); mViewport->setOverlaysEnabled(false); // set item buffer (must be provided by scene manager) bool useItemBuffer = true; sm->setOption("UseItemBuffer", &useItemBuffer); // clear background with black (i.e., not a valid item id) ColourValue bg = mViewport->getBackgroundColour(); mViewport->setBackgroundColour(ColourValue(0, 0, 0, 0)); // --- render item buffer pfHierarchyInterface->GetSceneManager()->_renderScene(pCam, mViewport, false); //---- collect results int dimx = 0; int dimy = 0; // get frame buffer uchar *buf = mViewport->getTarget()->getBufferContents(dimx, dimy); // loop through frame buffer & collect visible pixels for (int idx = 0; idx < dimy * dimx * 3; idx += 3) { // -- decode color code to receive id int id = buf[idx] << 16; id += buf[idx + 1] << 8; id += buf[idx + 2]; // if valid id <= add visibility (id values start at 1 if ((id > 0) && (id < (int)visibleGeometry->size())) { ((*visibleGeometry)[id]).AddVisibility(1, 1); } } delete [] buf; // ---- render visible nodes and collect node visibility bool renderBoxes = true; sm->setOption("RenderHierarchyNodes", &renderBoxes); // --- render item buffer for visible nodes only pfHierarchyInterface->GetSceneManager()->_renderScene(pCam, mViewport, false); // get frame buffer for node visibility buf = mViewport->getTarget()->getBufferContents(dimx, dimy); // loop through frame buffer & collect visible pixels for (int idx = 0; idx < dimy * dimx * 3; idx += 3) { // -- decode color code to receive id int id = buf[idx] << 16; id += buf[idx + 1] << 8; id += buf[idx + 2]; // if valid id <= add visibility (id values start at 1 if ((id > 0) && (id < (int)visibleNodes->size())) { ((*visibleNodes)[id]).AddVisibility(1, 1); } } // don't need item buffer anymore useItemBuffer = false; //sm->setOption("UseItemBuffer", &useItemBuffer); renderBoxes = false; //sm->setOption("RenderHierarchyNodes", &renderBoxes); // reset initialised - flag mWasInitialised = false; // reset old overlay status mViewport->setOverlaysEnabled(overlayEnabled); mViewport->setBackgroundColour(bg); delete [] buf; } //----------------------------------------------------------------------- void ItemBufferQueryManager::InitItemBuffer(InfoContainer *visibleNodes, InfoContainer *visibleGeometry) { if (mWasInitialised) return; mWasInitialised = true; SceneManager *sm = dynamic_cast(mHierarchyInterface)->GetSceneManager(); SceneManager::EntityIterator it = sm->getEntityIterator(); // TODO: make this more efficient visibleGeometry->clear(); visibleNodes->clear(); while (it.hasMoreElements()) { visibleGeometry->push_back(GtpVisibility::MeshInfo(it.getNext(), 0, 0)); } // -- initialise hierarchy interface for simple node traversal mHierarchyInterface->InitTraversal(false); GtpVisibility::HierarchyNode *node = NULL; int i = 1; while (node = mHierarchyInterface->GetNextNode()) { mHierarchyInterface->SetNodeId(node, i++); visibleNodes->push_back(GtpVisibility::NodeInfo(node, 0, 0)); } } } // namespace Ogre