#include "OgreItemBufferQueryManager.h" #include #include #include #include namespace Ogre { //----------------------------------------------------------------------- ItemBufferQueryManager::ItemBufferQueryManager(PlatformHierarchyInterface *hierarchyInterface, Viewport *vp, const bool renderPatches): PlatformQueryManager(hierarchyInterface, vp), mRenderPatchesForItemBuffer(renderPatches) { } //----------------------------------------------------------------------- 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, InfoContainer *visiblePatches, bool relativeVisibility) { // initialise item buffer (if not already initialised) InitItemBuffer(visibleNodes, visibleGeometry, visiblePatches); // 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)); pfHierarchyInterface->GetRenderSystem()->clearFrameBuffer(FBT_COLOUR | FBT_DEPTH); //-- render item buffer sm->_renderScene(pCam, mViewport, false); //mViewport->getTarget()->update(); //for(int j=0; j<10000000; j++) printf("wait"); //---- collect results int dimx = 0; int dimy = 0; // get 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 & 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 // don't need item buffer anymore useItemBuffer = false; sm->setOption("UseItemBuffer", &useItemBuffer); // reset initialised - flag mWasInitialised = false; // reset old overlay status mViewport->setOverlaysEnabled(overlayEnabled); // reset background color mViewport->setBackgroundColour(bg); // delete array storing the frame buffer delete [] buf; } //----------------------------------------------------------------------- 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