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

Revision 2113, 8.4 KB checked in by mattausch, 17 years ago (diff)

warning: debug version

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 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 != sit_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
186#if ENLARGE_NODE_BBOX
187        // make search radius larger
188        AxisAlignedBox largebox = EnlargeBox(box);
189        mSceneMgr->findNodesIn(largebox, sceneNodeList, NULL);
190
191        list<SceneNode *>::const_iterator sit, sit_end = sceneNodeList.end();
192
193        GtpVisibilityPreprocessor::AxisAlignedBox3 nodeBox =
194                OgreTypeConverter::ConvertFromOgre(largebox);
195#else
196
197        mSceneMgr->findNodesIn(box, sceneNodeList, NULL);
198
199        list<SceneNode *>::const_iterator sit, sit_end = sceneNodeList.end();
200
201        GtpVisibilityPreprocessor::AxisAlignedBox3 nodeBox =
202                OgreTypeConverter::ConvertFromOgre(box);
203#endif
204
205        // loop through the intersected scene nodes
206        for (sit = sceneNodeList.begin(); sit != sceneNodeList.end(); ++ sit)
207        {
208                SceneNode *sn = *sit;
209                SceneNode::ObjectIterator oit = sn->getAttachedObjectIterator();
210
211                // find the objects that intersect the box
212        while (oit.hasMoreElements())
213                {
214                        MovableObject *mo = oit.getNext();
215
216                        // we are only interested in scene entities
217                        if (mo->getMovableType() != "Entity")
218                                continue;
219                       
220                        // get the bounding box of the objects
221#if ENLARGE_OBJECT_BBOX
222                        // compare with enlarged entitiy box
223                        const AxisAlignedBox bbox = EnlargeBox(mo->getWorldBoundingBox());
224#else
225                        const AxisAlignedBox bbox = mo->getWorldBoundingBox();
226#endif
227
228                        // test for intersection (note: function provided of preprocessor)
229                        if (Overlap(nodeBox, OgreTypeConverter::ConvertFromOgre(bbox)))
230                        {
231                                objects.push_back(static_cast<Entity *>(mo));
232                        }
233                }
234        }
235}
236
237#if USE_KD_PVS
238//-------------------------------------------------------------------------
239template<typename T>
240bool PlatFormBoundingBoxConverter<T>::IdentifyObjects(
241        const GtpVisibilityPreprocessor::IndexedBoundingBoxContainer &iboxes,
242        GtpVisibilityPreprocessor::ObjectContainer &objects) const
243{
244        GtpVisibilityPreprocessor::IndexedBoundingBoxContainer::
245                const_iterator iit, iit_end = iboxes.end();
246 
247        for (iit = iboxes.begin(); iit != iit_end; ++ iit)
248        {
249                const AxisAlignedBox box =
250                        OgreTypeConverter::ConvertToOgre((*iit).second);
251               
252                EntityContainer *entryObjects = new EntityContainer();
253
254                // find all objects that intersect the bounding box
255                FindIntersectingObjects(box, *entryObjects);
256
257                EngineIntersectable *entry =
258                        new EngineIntersectable(entryObjects);
259
260                entry->SetId((*iit).first);
261
262                objects.push_back(entry);
263        }
264
265        return true;
266}
267#else
268//-------------------------------------------------------------------------
269template<typename T>
270bool PlatFormBoundingBoxConverter<T>::IdentifyObjects(
271        const GtpVisibilityPreprocessor::IndexedBoundingBoxContainer &iboxes,
272        GtpVisibilityPreprocessor::ObjectContainer &objects) const
273{
274        GtpVisibilityPreprocessor::IndexedBoundingBoxContainer::
275                const_iterator iit, iit_end = iboxes.end();
276 
277        for (iit = iboxes.begin(); iit != iit_end; ++ iit)
278        {
279                const GtpVisibilityPreprocessor::AxisAlignedBox3 box = (*iit).second;
280                const AxisAlignedBox currentBox = OgreTypeConverter::ConvertToOgre(box);
281   
282                Entity *ent = FindBestFittingObject(currentBox);
283                if (!ent) continue;
284               
285                // create new mesh instance
286                OgreMeshInstance *omi = new OgreMeshInstance(ent);
287                omi->SetId((*iit).first);
288                objects.push_back(omi);
289        }
290
291        return true;
292}
293#endif
294
295typedef PlatFormBoundingBoxConverter<OctreeSceneManager> OctreeBoundingBoxConverter;
296typedef PlatFormBoundingBoxConverter<BvHierarchySceneManager> BvhBoundingBoxConverter;
297typedef PlatFormBoundingBoxConverter<KdTreeSceneManager> KdTreeBoundingBoxConverter;
298
299} // namespace Ogre
300
301#endif // PlatFormBoundingBoxConverter
Note: See TracBrowser for help on using the repository browser.