source: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/include/OgreBoundingBoxConverter.h @ 2543

Revision 2543, 9.3 KB checked in by mattausch, 17 years ago (diff)
Line 
1#ifndef _PlatformBoundingBoxConverter_H__
2#define _PlatformBoundingBoxConverter_H__
3 
4#include "OgreAxisAlignedBox.h"
5#include "AxisAlignedBox3.h"
6#include "Vector3.h"
7#include "BoundingBoxConverter.h"
8#include "Containers.h"
9#include "IntersectableWrapper.h"
10
11
12namespace Ogre {
13
14#define USE_KD_PVS 1
15
16class Entity;
17class OctreeSceneManager;
18class KdTreeSceneManager;
19class BiHierarchySceneManager;
20
21typedef vector<Entity *> EntityContainer;
22
23class EngineIntersectable: public GtpVisibilityPreprocessor::IntersectableWrapper<EntityContainer *>
24{
25public:
26        EngineIntersectable(EntityContainer *item):
27        GtpVisibilityPreprocessor::IntersectableWrapper<EntityContainer *>(item) {}
28
29        // hack
30        EngineIntersectable::~EngineIntersectable()
31        {
32                delete mItem;
33        }
34
35        int Type() const
36        {
37                return Intersectable::ENGINE_INTERSECTABLE;
38        }
39};
40
41
42/**     Class which converts preprocessor types to OGRE types
43*/
44template<typename T>
45class __declspec(dllexport) PlatFormBoundingBoxConverter: public GtpVisibilityPreprocessor::BoundingBoxConverter
46{
47public:
48        PlatFormBoundingBoxConverter(T *sm);
49       
50        bool IdentifyObjects(const GtpVisibilityPreprocessor::IndexedBoundingBoxContainer &iboxes,
51                                                 GtpVisibilityPreprocessor::ObjectContainer &objects) const;
52
53
54protected:
55
56        //-------------------------------------------------------------------------
57        inline static AxisAlignedBox EnlargeBox(const AxisAlignedBox &box)
58        {
59                const float eps = 1e-3f;
60                const Vector3 veps(eps, eps, eps);
61               
62                Vector3 max = box.getMaximum();
63        Vector3 min = box.getMinimum();
64
65                return AxisAlignedBox(min - veps, max + veps);
66        }
67       
68        //-------------------------------------------------------------------------
69        inline static AxisAlignedBox ScaleBox(const AxisAlignedBox &box)
70        {
71                const float scale = 1.5f;
72        Vector3 max = box.getMaximum();
73        Vector3 min = box.getMinimum();
74                Vector3 size = max - min;
75                Vector3 newSize = size*(scale*0.5f);
76                Vector3 center = 0.5f * (min + max);
77
78                Vector3 min = center - newSize;
79                Vector3 max = center + newSize;
80
81                return AxisAlignedBox(min, max);
82        }
83        /** find object which fits best to this bounding box
84        */
85        Entity *FindBestFittingObject(const AxisAlignedBox &box) const;
86       
87        /** find objects which are intersected by this box
88        */
89        void FindIntersectingObjects(const AxisAlignedBox &box,
90                                                                 vector<Entity *> &objects) const;
91
92        /// this can be any scene manager
93        T *mSceneMgr;
94};
95
96//-------------------------------------------------------------------------
97template<typename T>
98PlatFormBoundingBoxConverter<T>::PlatFormBoundingBoxConverter(T *sm):
99mSceneMgr(sm)
100{
101}
102//-----------------------------------------------------------------------
103template<typename T>
104Entity *PlatFormBoundingBoxConverter<T>::FindBestFittingObject(const AxisAlignedBox &box) const
105{
106        list<SceneNode *> sceneNodeList;
107        AxisAlignedBox3 enlargedBox =
108        AxisAlignedBox mybox = EnlargeBox(box);
109               
110        // get intersecting scene nodes
111        // note: this function must be provided by scene manager
112        mSceneMgr->findNodesIn(mybox, sceneNodeList, NULL);
113               
114        // minimal overlap
115        float overlap = 0;//1e-6;
116
117        Entity *bestFittingObj = NULL;
118        float bestFit = overlap;
119
120        // perfect fit threshold
121        const float thresh = 1.0 - GtpVisibilityPreprocessor::Limits::Small;
122
123        list<SceneNode *>::const_iterator sit, sit_end = sceneNodeList.end();
124
125        // find the bbox which is closest to the current bbox
126        for (sit = sceneNodeList.begin(); sit != sit_end; ++ sit)
127        {
128                SceneNode *sn = *sit;
129                SceneNode::ObjectIterator oit = sn->getAttachedObjectIterator();
130
131        while (oit.hasMoreElements())
132                {
133                        MovableObject *mo = oit.getNext();
134
135                        // we are only interested in scene entities
136                        if (mo->getMovableType() != "Entity")
137                        {
138                                continue;
139                        }
140                         
141                        const AxisAlignedBox bbox = EnlargeBox(mo->getWorldBoundingBox());
142                                       
143                        // compute measure how much aabbs overlap
144                        overlap = RatioOfOverlap(OgreTypeConverter::ConvertFromOgre(mybox),
145                                                                         OgreTypeConverter::ConvertFromOgre(bbox));
146       
147                         if (overlap > bestFit)
148                         {
149                                 bestFit = overlap;
150                                 bestFittingObj = static_cast<Entity *>(mo);
151
152                                 // perfect fit => object found, early exit
153                                 if (overlap >= thresh)
154                                 {
155                                         return bestFittingObj;
156                                 }
157                         }
158                }
159        }
160
161        if (0)
162        {
163                std::stringstream d;
164                if (bestFittingObj)
165                        d << "best fit: " << bestFit;     
166                else
167                        d << "warning, no best fitting object\n" << box;
168       
169                Ogre::LogManager::getSingleton().logMessage(d.str());
170        }
171
172        return bestFittingObj;
173}
174
175
176#define ENLARGE_OBJECT_BBOX 0
177#define ENLRAGE_NODE_BBOX 0
178
179template<typename T>
180void PlatFormBoundingBoxConverter<T>::FindIntersectingObjects(const AxisAlignedBox &box,
181                                                                                                                          EntityContainer &objects) const
182{
183        list<SceneNode *> sceneNodeList;
184
185        // find intersecting scene nodes to get candidates for intersection
186    // note: this function has to be provided by scene manager
187
188#if ENLARGE_NODE_BBOX
189        // make search radius larger
190        AxisAlignedBox largebox = EnlargeBox(box);
191        mSceneMgr->findNodesIn(largebox, sceneNodeList, NULL);
192
193        list<SceneNode *>::const_iterator sit, sit_end = sceneNodeList.end();
194
195        GtpVisibilityPreprocessor::AxisAlignedBox3 nodeBox =
196                OgreTypeConverter::ConvertFromOgre(largebox);
197#else
198
199        mSceneMgr->findNodesIn(box, sceneNodeList, NULL);
200
201        list<SceneNode *>::const_iterator sit, sit_end = sceneNodeList.end();
202
203        GtpVisibilityPreprocessor::AxisAlignedBox3 nodeBox =
204                OgreTypeConverter::ConvertFromOgre(box);
205#endif
206
207        // loop through the intersected scene nodes
208        for (sit = sceneNodeList.begin(); sit != sceneNodeList.end(); ++ sit)
209        {
210                SceneNode *sn = *sit;
211                SceneNode::ObjectIterator oit = sn->getAttachedObjectIterator();
212
213                // find the objects that intersect the box
214        while (oit.hasMoreElements())
215                {
216                        MovableObject *mo = oit.getNext();
217
218                        // we are only interested in scene entities
219                        if ((mo->getMovableType() != "Entity") &&
220                                (mo->getMovableType() != "ManualObject"))
221                                continue;
222                       
223                        // get the bounding box of the objects
224#if ENLARGE_OBJECT_BBOX
225                        // compare with enlarged entitiy box
226                        const AxisAlignedBox bbox = EnlargeBox(mo->getWorldBoundingBox());
227#else
228                        const AxisAlignedBox bbox = mo->getWorldBoundingBox();
229#endif
230
231                        // test for intersection (note: function provided of preprocessor)
232                        if (Overlap(nodeBox, OgreTypeConverter::ConvertFromOgre(bbox)))
233                        {
234                                objects.push_back(static_cast<Entity *>(mo));
235                        }
236                }
237        }
238}
239
240static void AddToObjects(EntityContainer *entites,
241                                                 GtpVisibilityPreprocessor::ObjectContainer &objects,
242                                                 const int id)
243{
244        // TODO: can actually just put single objects into pvs with same id,
245        // this can be sorted out later!!
246#if 0
247        EntityContainer::const_iterator eit, eit_end = entryObjects.end();
248
249        for (eit = entryObjects.begin(); eit != eit_end; ++ eit)
250        {
251                Entity *ent = *eit;
252
253        // warning: multiple ids possible
254                OgreMeshInstance *omi = new OgreMeshInstance(ent);
255                omi->SetId(id);
256                objects.push_back(omi);
257        }
258
259        delete entryObjects;
260
261#else
262
263        EngineIntersectable *entry = new EngineIntersectable(entites);
264
265        entry->SetId(id);
266        objects.push_back(entry);
267#endif
268}
269
270#if USE_KD_PVS
271//-------------------------------------------------------------------------
272template<typename T>
273bool PlatFormBoundingBoxConverter<T>::IdentifyObjects(
274        const GtpVisibilityPreprocessor::IndexedBoundingBoxContainer &iboxes,
275        GtpVisibilityPreprocessor::ObjectContainer &objects) const
276{
277        GtpVisibilityPreprocessor::IndexedBoundingBoxContainer::
278                const_iterator iit, iit_end = iboxes.end();
279 
280        for (iit = iboxes.begin(); iit != iit_end; ++ iit)
281        {
282                const GtpVisibilityPreprocessor::AxisAlignedBox3 pbox = (*iit).second;
283                const int id = (*iit).first;
284
285                const AxisAlignedBox box =
286                        OgreTypeConverter::ConvertToOgre(pbox);
287               
288                EntityContainer *entryObjects = new EntityContainer();
289
290                // find all objects that intersect the bounding box
291                FindIntersectingObjects(box, *entryObjects);
292
293                /*stringstream d;
294                d << "identified: " << entryObjects->size() << " objects \n";
295                LogManager::getSingleton().logMessage(d.str());
296*/
297                AddToObjects(entryObjects, objects, id);
298        }
299
300        return true;
301}
302
303#else
304
305//-------------------------------------------------------------------------
306template<typename T>
307bool PlatFormBoundingBoxConverter<T>::IdentifyObjects(
308        const GtpVisibilityPreprocessor::IndexedBoundingBoxContainer &iboxes,
309        GtpVisibilityPreprocessor::ObjectContainer &objects) const
310{
311        GtpVisibilityPreprocessor::IndexedBoundingBoxContainer::
312                const_iterator iit, iit_end = iboxes.end();
313 
314        for (iit = iboxes.begin(); iit != iit_end; ++ iit)
315        {
316                const GtpVisibilityPreprocessor::AxisAlignedBox3 box = (*iit).second;
317                const AxisAlignedBox currentBox = OgreTypeConverter::ConvertToOgre(box);
318   
319                Entity *ent = FindBestFittingObject(currentBox);
320                if (!ent) continue;
321               
322                // create new mesh instance
323                OgreMeshInstance *omi = new OgreMeshInstance(ent);
324                omi->SetId((*iit).first);
325                objects.push_back(omi);
326        }
327
328        return true;
329}
330#endif
331
332typedef PlatFormBoundingBoxConverter<OctreeSceneManager> OctreeBoundingBoxConverter;
333typedef PlatFormBoundingBoxConverter<BiHierarchySceneManager> BihBoundingBoxConverter;
334typedef PlatFormBoundingBoxConverter<KdTreeSceneManager> KdTreeBoundingBoxConverter;
335
336} // namespace Ogre
337
338#endif // PlatFormBoundingBoxConverter
Note: See TracBrowser for help on using the repository browser.