~ubuntu-branches/debian/sid/ember/sid

« back to all changes in this revision

Viewing changes to src/components/ogre/ogreopcode/src/OgreEntityCollisionShape.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michael Koch
  • Date: 2009-10-22 23:21:17 UTC
  • mfrom: (1.1.1 upstream) (2.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20091022232117-isr8u3402qmu7ilo
Tags: 0.5.7-1
* New upstream release.
  - Compile against current ogre (Closes: #551431)
  - Removed debian/patches/ember-gcc4.4.patch. Merged upstream.
  - Updated Depends on ember-media.
* Add libboost-thread-dev tp Build-Depends.
* Make debian/rules independent from upstream version.
* Updated watch file to allow automatic download of new upstream
  tarballs.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
///////////////////////////////////////////////////////////////////////////////
2
 
///  @file OgreEntityCollisionShape.cpp
3
 
///  @brief <TODO: insert file description here>
4
 
///
5
 
///  @author The OgreOpcode Team @date 28-05-2005
6
 
///
7
 
///////////////////////////////////////////////////////////////////////////////
8
 
///
9
 
///  This file is part of OgreOpcode.
10
 
///
11
 
///  A lot of the code is based on the Nebula Opcode Collision module, see docs/Nebula_license.txt
12
 
///
13
 
///  OgreOpcode is free software; you can redistribute it and/or
14
 
///  modify it under the terms of the GNU Lesser General Public
15
 
///  License as published by the Free Software Foundation; either
16
 
///  version 2.1 of the License, or (at your option) any later version.
17
 
///
18
 
///  OgreOpcode is distributed in the hope that it will be useful,
19
 
///  but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 
///  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21
 
///  Lesser General Public License for more details.
22
 
///
23
 
///  You should have received a copy of the GNU Lesser General Public
24
 
///  License along with OgreOpcode; if not, write to the Free Software
25
 
///  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
 
///
27
 
///////////////////////////////////////////////////////////////////////////////
28
 
#include "OgreOpcodeExports.h"
29
 
#include "OgreEntityCollisionShape.h"
30
 
#include "OgreCollisionReporter.h"
31
 
#include "OgreCollisionManager.h"
32
 
#include "OgreOpcodeMath.h"
33
 
#include "OgreOpcodeUtils.h"
34
 
 
35
 
using namespace Ogre;
36
 
namespace OgreOpcode
37
 
{
38
 
        //------------------------------------------------------------------------
39
 
        EntityCollisionShape::EntityCollisionShape(const Ogre::String& name)
40
 
                : ICollisionShape(name),
41
 
                mDummyNode(0),
42
 
                mDummyCreated(false)
43
 
        {
44
 
        }
45
 
 
46
 
        //------------------------------------------------------------------------
47
 
        EntityCollisionShape::~EntityCollisionShape()
48
 
        {
49
 
                if (mEntity && mEntity->hasSkeleton())
50
 
                {
51
 
#ifdef BUILD_AGAINST_AZATHOTH
52
 
                        mEntity->removeSoftwareSkinningRequest(false);
53
 
#else
54
 
                        mEntity->removeSoftwareAnimationRequest(false);
55
 
#endif                  
56
 
                }
57
 
                delete[] mVertexBuf;
58
 
                delete[] mFaceBuf;
59
 
                // Note that unlike PtrCollisionShape which creates a node, mParentNode is used
60
 
                // as a reference to the Entity's parent SceneNode.  We are not responsible for cleanup
61
 
                mParentNode = NULL;
62
 
        }
63
 
 
64
 
        //------------------------------------------------------------------------
65
 
        ///////////////////////////////////////////////////////////////////////////////
66
 
        /// Counts how many indices (faces) and vertices an entity contains.
67
 
        /// @param[in]  entity Entity to count its data.
68
 
        /// @param[out] index_count  Number of indices.
69
 
        /// @param[out] vertex_count Number of vertices.
70
 
        /// @author Yavin from the Ogre4J team
71
 
        ///////////////////////////////////////////////////////////////////////////////
72
 
        void EntityCollisionShape::countIndicesAndVertices(Entity * entity, size_t & index_count, size_t & vertex_count)
73
 
        {
74
 
//              Mesh * mesh = entity->getMesh().getPointer();
75
 
 
76
 
#ifdef BUILD_AGAINST_AZATHOTH
77
 
                bool hwSkinning = entity->isHardwareSkinningEnabled();
78
 
#else
79
 
                bool hwSkinning = entity->isHardwareAnimationEnabled();
80
 
#endif          
81
 
 
82
 
                bool added_shared = false;
83
 
                index_count  = 0;
84
 
                vertex_count = 0;
85
 
 
86
 
                // Calculate how many vertices and indices we're going to need
87
 
                for ( size_t i = 0; i < entity->getNumSubEntities(); ++i)
88
 
                {
89
 
                        SubEntity* subEntity = entity->getSubEntity(i);
90
 
                        if (subEntity->isVisible()) {
91
 
                                SubMesh* submesh = subEntity->getSubMesh();
92
 
        
93
 
                                // We only need to add the shared vertices once
94
 
                                if(submesh->useSharedVertices)
95
 
                                {
96
 
                                        if( !added_shared )
97
 
                                        {
98
 
                                                vertex_count += submesh->parent->sharedVertexData->vertexCount;
99
 
                                                added_shared = true;
100
 
                                        }
101
 
                                }
102
 
                                else
103
 
                                {
104
 
                                        vertex_count += submesh->vertexData->vertexCount;
105
 
                                }
106
 
        
107
 
                                // Add the indices
108
 
                                index_count += submesh->indexData->indexCount;
109
 
                        }
110
 
                }
111
 
        }
112
 
 
113
 
 
114
 
        //------------------------------------------------------------------------
115
 
        //////////////////////////////////////////////////////////////////////////
116
 
        /// Converts mesh vertex and face data into simple float arrays.
117
 
        /// If the buffer parameters are null then that data is not converted.
118
 
        /// @param[in]  entity              Entity to extract data from.
119
 
        /// @param[out] vertexBuf          Target vertex data array (can be null).
120
 
        /// @param[in]  size_t vertex_count Number of vertices.
121
 
        /// @param[out] faceData            Target face data array (can be null).
122
 
        /// @param[int] index_count         Number of indices.
123
 
        /// @author Yavin from the Ogre4J team
124
 
        //////////////////////////////////////////////////////////////////////////
125
 
        void EntityCollisionShape::convertMeshData(Entity * entity,
126
 
                float * vertexBuf, size_t vertex_count,
127
 
                size_t * faceBuf, size_t index_count)
128
 
        {
129
 
                //---------------------------------------------------------------------
130
 
                // CONVERT MESH DATA
131
 
                //---------------------------------------------------------------------
132
 
//              MeshPtr mesh = entity->getMesh();
133
 
                bool added_shared = false;
134
 
                size_t current_offset = 0;
135
 
                size_t shared_offset = 0;
136
 
                size_t next_offset = 0;
137
 
                size_t index_offset = 0;
138
 
                int numOfSubs = 0;
139
 
 
140
 
                bool useSoftwareBlendingVertices = entity->hasSkeleton();
141
 
 
142
 
                if (useSoftwareBlendingVertices)
143
 
                {
144
 
                        entity->_updateAnimation();
145
 
                }
146
 
 
147
 
                // Run through the submeshes again, adding the data into the arrays
148
 
                for ( size_t i = 0; i < entity->getNumSubEntities(); ++i)
149
 
                {
150
 
                        SubEntity* subEntity = entity->getSubEntity(i);
151
 
                        if (subEntity->isVisible()) {
152
 
                                SubMesh* submesh = subEntity->getSubMesh();
153
 
                                bool useSharedVertices = submesh->useSharedVertices;
154
 
        
155
 
                                if (vertexBuf)
156
 
                                {
157
 
                                        //----------------------------------------------------------------
158
 
                                        // GET VERTEXDATA
159
 
                                        //----------------------------------------------------------------
160
 
                                        const VertexData * vertex_data;
161
 
                                        if(useSoftwareBlendingVertices)
162
 
        #ifdef BUILD_AGAINST_AZATHOTH
163
 
                                                vertex_data = useSharedVertices ? entity->_getSharedBlendedVertexData() : entity->getSubEntity(i)->_getBlendedVertexData();
164
 
        #else
165
 
                                                vertex_data = useSharedVertices ? entity->_getSkelAnimVertexData() : entity->getSubEntity(i)->_getSkelAnimVertexData(); 
166
 
        #endif  
167
 
                                        else
168
 
                                                vertex_data = useSharedVertices ? submesh->parent->sharedVertexData : submesh->vertexData;
169
 
        
170
 
                                        if((!useSharedVertices)||(useSharedVertices && !added_shared))
171
 
                                        {
172
 
                                                if(useSharedVertices)
173
 
                                                {
174
 
                                                        added_shared = true;
175
 
                                                        shared_offset = current_offset;
176
 
                                                }
177
 
        
178
 
                                                const VertexElement* posElem =
179
 
                                                        vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
180
 
        
181
 
                                                HardwareVertexBufferSharedPtr vbuf =
182
 
                                                        vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
183
 
        
184
 
                                                unsigned char* vertex =
185
 
                                                        static_cast<unsigned char*>(vbuf->lock(HardwareBuffer::HBL_READ_ONLY));
186
 
        
187
 
                                                // There is _no_ baseVertexPointerToElement() which takes an Ogre::Real or a double
188
 
                                                //  as second argument. So make it float, to avoid trouble when Ogre::Real is
189
 
                                                //  comiled/typedefed as double:
190
 
                                                float* pReal;
191
 
        
192
 
        #ifdef BUILD_AGAINST_AZATHOTH
193
 
                                                if (useSoftwareBlendingVertices)
194
 
                                                {
195
 
                                                        // Blended bone data is computed in world space.
196
 
                                                        // Opcode expects data in local coordinates.
197
 
                                                        Matrix4 xform = entity->_getParentNodeFullTransform().inverse();
198
 
        
199
 
                                                        for( size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
200
 
                                                        {
201
 
                                                                posElem->baseVertexPointerToElement(vertex, &pReal);
202
 
                                                                Vector3 v = Vector3(pReal[0],pReal[1],pReal[2]);
203
 
                                                                v = xform * v;
204
 
                                                                size_t n = current_offset*3 + j*3;
205
 
                                                                vertexBuf[n + 0] = v[0];
206
 
                                                                vertexBuf[n + 1] = v[1];
207
 
                                                                vertexBuf[n + 2] = v[2];
208
 
                                                        }
209
 
                                                }
210
 
                                                else
211
 
                                                {
212
 
                                                        for( size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
213
 
                                                        {
214
 
                                                                posElem->baseVertexPointerToElement(vertex, &pReal);
215
 
                                                                size_t n = current_offset*3 + j*3;
216
 
                                                                vertexBuf[n + 0] = pReal[0];
217
 
                                                                vertexBuf[n + 1] = pReal[1];
218
 
                                                                vertexBuf[n + 2] = pReal[2];
219
 
                                                        }
220
 
                                                }
221
 
        #else
222
 
        
223
 
                                                for( size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
224
 
                                                {
225
 
                                                        posElem->baseVertexPointerToElement(vertex, &pReal);
226
 
        
227
 
                                                        size_t n = current_offset*3 + j*3;
228
 
        
229
 
                                                        vertexBuf[n + 0] = pReal[0];
230
 
                                                        vertexBuf[n + 1] = pReal[1];
231
 
                                                        vertexBuf[n + 2] = pReal[2];
232
 
                                                }
233
 
        #endif  
234
 
        
235
 
                                                vbuf->unlock();
236
 
                                                next_offset += vertex_data->vertexCount;
237
 
                                        }
238
 
                                }
239
 
        
240
 
                                if (faceBuf)
241
 
                                {
242
 
                                        //----------------------------------------------------------------
243
 
                                        // GET INDEXDATA
244
 
                                        //----------------------------------------------------------------
245
 
                                        IndexData* index_data = submesh->indexData;
246
 
                                        size_t numTris = index_data->indexCount / 3;
247
 
                                        HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
248
 
        
249
 
                                        bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT);
250
 
        
251
 
                                        uint32 *pLong = static_cast<uint32*>(ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
252
 
                                        uint16* pShort = reinterpret_cast<uint16*>(pLong);
253
 
        
254
 
        
255
 
                                        size_t offset = (submesh->useSharedVertices)? shared_offset : current_offset;
256
 
        
257
 
                                        if ( use32bitindexes )
258
 
                                        {
259
 
                                                for ( size_t k = 0; k < numTris*3; ++k)
260
 
                                                {
261
 
                                                        faceBuf[index_offset++] = pLong[k] + static_cast<int>(offset);
262
 
                                                }
263
 
                                        }
264
 
                                        else
265
 
                                        {
266
 
                                                for ( size_t k = 0; k < numTris*3; ++k)
267
 
                                                {
268
 
                                                        faceBuf[index_offset++] = static_cast<int>(pShort[k]) + static_cast<int>(offset);
269
 
                                                }
270
 
                                        }
271
 
        
272
 
                                        ibuf->unlock();
273
 
                                }
274
 
        
275
 
                                current_offset = next_offset;
276
 
                        }
277
 
                }
278
 
        }
279
 
 
280
 
        //------------------------------------------------------------------------
281
 
        /// <TODO: insert function description here>
282
 
        /// @param [in, out]  ent Entity *    <TODO: insert parameter description here>
283
 
        /// @return bool <TODO: insert return value description here>
284
 
        bool EntityCollisionShape::load(Entity* ent)
285
 
        {
286
 
                assert(ent);
287
 
                assert(!mVertexBuf && !mFaceBuf);
288
 
                mEntity = ent;
289
 
 
290
 
                if (mEntity->hasSkeleton())
291
 
                {
292
 
#ifdef BUILD_AGAINST_AZATHOTH
293
 
                        mEntity->addSoftwareSkinningRequest(false);                             
294
 
#else
295
 
                        mEntity->addSoftwareAnimationRequest(false);
296
 
#endif
297
 
                }
298
 
 
299
 
                mParentNode = mEntity->getParentSceneNode();
300
 
                mFullTransform = mEntity->getParentSceneNode()->_getFullTransform();
301
 
                //mParentNode->getWorldTransforms(&mFullTransform);
302
 
                return rebuild();
303
 
        }
304
 
 
305
 
        //------------------------------------------------------------------------
306
 
        /// <TODO: insert function description here>
307
 
        /// @return bool <TODO: insert return value description here>
308
 
        bool EntityCollisionShape::rebuild()
309
 
        {
310
 
                assert(mEntity);
311
 
 
312
 
                // NOTE: Assuming presence or absence of skeleton hasn't changed!
313
 
 
314
 
                size_t vertex_count = 0;
315
 
                size_t index_count  = 0;
316
 
                countIndicesAndVertices(mEntity, index_count, vertex_count);
317
 
 
318
 
                // Re-Allocate space for the vertices and indices
319
 
                if (mVertexBuf && numVertices != vertex_count) {
320
 
                        delete [] mVertexBuf;
321
 
                        mVertexBuf = 0;
322
 
                }
323
 
                if (mFaceBuf && numFaces != index_count/3) {
324
 
                        delete [] mFaceBuf;
325
 
                        mFaceBuf = 0;
326
 
                }
327
 
 
328
 
                if (!mVertexBuf)
329
 
                        mVertexBuf = new float[vertex_count * 3];
330
 
                if (!mFaceBuf)
331
 
                        mFaceBuf = new size_t[index_count];
332
 
 
333
 
                if (index_count > 0 && vertex_count > 0) {
334
 
                        convertMeshData(mEntity, mVertexBuf, vertex_count, mFaceBuf, index_count );
335
 
        
336
 
                        numFaces = index_count / 3;
337
 
                        numVertices = vertex_count;
338
 
        
339
 
                        opcMeshAccess.SetNbTriangles(numFaces);
340
 
                        opcMeshAccess.SetNbVertices(numVertices);
341
 
                        opcMeshAccess.SetPointers((IceMaths::IndexedTriangle*)mFaceBuf, (IceMaths::Point*)mVertexBuf);
342
 
                        //opcMeshAccess.SetStrides(sizeof(int) * 3, sizeof(float) * 3);
343
 
        
344
 
                        return _rebuildFromCachedData();
345
 
                }
346
 
                return true;
347
 
 
348
 
        }
349
 
 
350
 
        //------------------------------------------------------------------------
351
 
        /// <TODO: insert function description here>
352
 
        /// @return bool <TODO: insert return value description here>
353
 
        bool EntityCollisionShape::refit()
354
 
        {
355
 
                // bail if we don't need to refit
356
 
                if ( mShapeIsStatic )
357
 
                        return true;
358
 
 
359
 
                assert(mEntity && mVertexBuf);
360
 
 
361
 
#ifdef _DEBUG
362
 
                size_t vertex_count = 0;
363
 
                size_t index_count  = 0;
364
 
                countIndicesAndVertices(mEntity, index_count, vertex_count);
365
 
                assert(numVertices == vertex_count);
366
 
#endif
367
 
 
368
 
                if (numVertices > 0) {
369
 
                        convertMeshData(mEntity, mVertexBuf, numVertices);
370
 
        
371
 
                        return _refitToCachedData();
372
 
                }
373
 
                return true;
374
 
        }
375
 
 
376
 
        //------------------------------------------------------------------------
377
 
        /// <TODO: insert function description here>
378
 
        /// @return bool <TODO: insert return value description here>
379
 
        bool EntityCollisionShape::_refitToCachedData()
380
 
        {
381
 
                assert(mEntity && mVertexBuf);
382
 
 
383
 
                // rebuild tree
384
 
                if (!opcModel.Refit())
385
 
                {
386
 
                        LogManager::getSingleton().logMessage(
387
 
                                "OgreOpcode::EntityCollisionShape::_refitToCachedData(): OPCODE Quick refit not possible with the given tree type.");
388
 
                        // Backup plan -- rebuild full tree
389
 
                        opcMeshAccess.SetPointers((IceMaths::IndexedTriangle*)mFaceBuf, (IceMaths::Point*)mVertexBuf);
390
 
                        Opcode::OPCODECREATE opcc;
391
 
                        _prepareOpcodeCreateParams(opcc);
392
 
                        opcModel.Build(opcc);
393
 
                }
394
 
 
395
 
                calculateSize();
396
 
 
397
 
                //computeIceABB();
398
 
 
399
 
                return true;
400
 
        }
401
 
 
402
 
        //------------------------------------------------------------------------
403
 
        /// <TODO: insert function description here>
404
 
        /// @return bool <TODO: insert return value description here>
405
 
        bool EntityCollisionShape::_rebuildFromCachedData()
406
 
        {
407
 
                assert(mEntity && mVertexBuf && mFaceBuf);
408
 
 
409
 
                Opcode::OPCODECREATE opcc;
410
 
                _prepareOpcodeCreateParams(opcc);
411
 
                opcModel.Build(opcc);
412
 
 
413
 
                calculateSize();
414
 
 
415
 
                //computeIceABB();
416
 
 
417
 
                return true;
418
 
        }
419
 
        //------------------------------------------------------------------------
420
 
        /// <TODO: insert function description here>
421
 
        void EntityCollisionShape::createDummyNode()
422
 
        {
423
 
                if(!mDummyCreated)
424
 
                {
425
 
                        mDummyNode = CollisionManager::getSingletonPtr()->getSceneManager()->getRootSceneNode()->createChildSceneNode(getName());
426
 
                        mDummyNode->attachObject(mEntity);
427
 
                        mDummyCreated = true;
428
 
                }
429
 
 
430
 
        }
431
 
}
432
 
 
433
 
//------------------------------------------------------------------------