#include "OgreBoundingBoxConverter.h" #include "OgreTypeConverter.h" #include "OgreMeshInstance.h" #include "OgreOctreeSceneManager.h" #include namespace Ogre { //------------------------------------------------------------------------- OgreBoundingBoxConverter::OgreBoundingBoxConverter(OctreeSceneManager *sm): mSceneMgr(sm) { } //------------------------------------------------------------------------- bool OgreBoundingBoxConverter::IdentifyObjects(const GtpVisibilityPreprocessor::IndexedBoundingBoxContainer &iboxes, GtpVisibilityPreprocessor::ObjectContainer &objects) const { GtpVisibilityPreprocessor::IndexedBoundingBoxContainer:: const_iterator iit, iit_end = iboxes.end(); for (iit = iboxes.begin(); iit != iit_end; ++ iit) { const GtpVisibilityPreprocessor::AxisAlignedBox3 box = (*iit).second; const AxisAlignedBox currentBox = OgreTypeConverter::ConvertToOgre(box); Entity *ent = FindCorrespondingObject(currentBox); // create new mesh instance OgreMeshInstance *omi = new OgreMeshInstance(ent); omi->SetId((*iit).first); objects.push_back(omi); } return true; } //------------------------------------------------------------------------- inline static AxisAlignedBox EnlargeBox(const AxisAlignedBox &box) { const float eps = 1e-3f; const Vector3 veps(eps, eps, eps); Vector3 max = box.getMaximum(); Vector3 min = box.getMinimum(); return AxisAlignedBox(min - veps, max + veps); } //----------------------------------------------------------------------- Entity *OgreBoundingBoxConverter::FindCorrespondingObject(const AxisAlignedBox &box) const { list sceneNodeList; AxisAlignedBox mybox = EnlargeBox(box); //AxisAlignedBox dummy(Vector3(-50000, -50000, -50000), Vector3(50000, 50000, 50000)); //-- get intersecting scene nodes mSceneMgr->findNodesIn(mybox, sceneNodeList, NULL); list::const_iterator sit, sit_end = sceneNodeList.end(); // minimal overlap float overlap = 0;//1e-6; Entity *bestFittingObj = NULL; float bestFit = overlap; // perfect fit threshold const float thresh = 1.0 - GtpVisibilityPreprocessor::Limits::Small; // find the bbox which is closest to the current bbox for (sit = sceneNodeList.begin(); sit != sceneNodeList.end(); ++ sit) { SceneNode *sn = *sit; SceneNode::ObjectIterator oit = sn->getAttachedObjectIterator(); while (oit.hasMoreElements()) { MovableObject *mo = oit.getNext(); // we are only interested in scene entities if (mo->getMovableType() != "Entity") { continue; } const AxisAlignedBox bbox = EnlargeBox(mo->getWorldBoundingBox()); // compute measure how much aabbs overlap overlap = RatioOfOverlap(OgreTypeConverter::ConvertFromOgre(mybox), OgreTypeConverter::ConvertFromOgre(bbox)); if (overlap > bestFit) { bestFit = overlap; bestFittingObj = static_cast(mo); // perfect fit => object found, eraly exit if (overlap >= thresh) return bestFittingObj; } } } if (0) { std::stringstream d; if (bestFittingObj) d << "best fit: " << bestFit; else d << "warning, objects do not fit\n" << box; Ogre::LogManager::getSingleton().logMessage(d.str()); } return bestFittingObj; } }