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

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