#include "OgreItemBufferQueryManager.h" #include #include #include #include namespace Ogre { //----------------------------------------------------------------------- ItemBufferQueryManager::ItemBufferQueryManager(PlatformHierarchyInterface *hierarchyInterface, Viewport *vp, const bool renderPatches): PlatformQueryManager(hierarchyInterface, vp), mRenderPatchesForItemBuffer(renderPatches) { } //----------------------------------------------------------------------- void ItemBufferQueryManager::ComputeCameraVisibility(const Camera &camera, InfoContainer *visibleNodes, InfoContainer *visibleGeometry, InfoContainer *visiblePatches, bool relativeVisibility) { // we need access to the scene manager and the rendersystem PlatformHierarchyInterface *pfHierarchyInterface = dynamic_cast(mHierarchyInterface); SceneManager *sm = pfHierarchyInterface->GetSceneManager(); // 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); // clear background with black (i.e., not a valid item id) ColourValue bg = mViewport->getBackgroundColour(); mViewport->setBackgroundColour(ColourValue(0, 0, 0, 0)); //pfHierarchyInterface->GetRenderSystem()->clearFrameBuffer(FBT_COLOUR | FBT_DEPTH); //-- render scene with item buffer (i.e., objects with their id as color codes) // enable item buffer (must be provided by scene manager) bool useItemBuffer = true; sm->setOption("UseItemBuffer", &useItemBuffer); sm->_renderScene(pCam, mViewport, false); // render item buffer //-- collect results // initialise item buffer (if not already initialised) InitItemBuffer(visibleNodes, visibleGeometry, visiblePatches); int dimx = 0; int dimy = 0; // copy frame buffer uchar *buf = mViewport->getTarget()->getBufferContents(dimx, dimy); int n = mRenderPatchesForItemBuffer ? (int)visiblePatches->size() : (int)visibleGeometry->size(); //std::stringstream d; d << "dimx: " << dimx << ", dimy: " << dimy; LogManager::getSingleton().logMessage(d.str()); // loop through frame buffer and 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]; //std::stringstream d; d << "myid: " << (int)buf[idx] << " " << (int)buf[idx + 1] << " " << (int)buf[idx + 2]; LogManager::getSingleton().logMessage(d.str()); // if valid id <= add visibility (id values start at 1) if ((id > 0) && (id < n)) { if (mRenderPatchesForItemBuffer) { ((*visiblePatches)[id]).AddVisibility(1, 1); } else { ((*visibleGeometry)[id]).AddVisibility(1, 1); } } } //-- reset options useItemBuffer = false; // don't need item buffer anymore sm->setOption("UseItemBuffer", &useItemBuffer); mWasInitialised = false; // reset initialised - flag mViewport->setOverlaysEnabled(overlayEnabled); // reset old overlay status mViewport->setBackgroundColour(bg); // reset background color delete [] buf; // delete copy of the frame buffer } //----------------------------------------------------------------------- void ItemBufferQueryManager::InitItemBuffer( InfoContainer *visibleNodes, InfoContainer *visibleGeometry, InfoContainer *visiblePatches) { 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(); visiblePatches->clear(); int id = 0; /* We can either use patches or meshes. If patches are used, an unique id must be given each patch. Otherwise the same id must be given to all patches belonging to the same mesh. */ while (it.hasMoreElements()) { Entity *ent = it.getNext(); for (int i = 0; i < (int)ent->getNumSubEntities(); ++i) { SubEntity *subEnt = ent->getSubEntity(i); if (mRenderPatchesForItemBuffer) { ++ id; visiblePatches->push_back(GtpVisibility::PatchInfo(subEnt, 0, 0)); } subEnt->setId(id); //subEnt->setId((41 << 16) + (4 << 8) + 60); //subEnt->setId((2 << 16) + (4 << 8) + 60); } if (!mRenderPatchesForItemBuffer) { visibleGeometry->push_back(GtpVisibility::MeshInfo(ent, 0, 0)); ++ id; } } } /* //----------------------------------------------------------------------- Entity* VisibilityOctreeSceneManager::createEntity(const String& entityName, const String& meshName) { Entity *ent = SceneManager::createEntity(entityName, meshName); for (int i = 0; i < (int)ent->getNumSubEntities(); ++i) { ent->getSubEntity(i)->setId(mCurrentEntityId); } // increase counter of entity id values ++ mCurrentEntityId; return ent; } */ } // namespace Ogre