Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/physics/src/ogrebullet/Collisions/Utils/OgreBulletCollisionsMeshToShapeConverter.cpp @ 1985

Last change on this file since 1985 was 1985, checked in by rgrieder, 16 years ago

Split up OgreBullet into Collisions and Dynamics as it was intended by the developers.

  • Property svn:eol-style set to native
File size: 24.8 KB
Line 
1/***************************************************************************
2
3This source file is part of OGREBULLET
4(Object-oriented Graphics Rendering Engine Bullet Wrapper)
5For the latest info, see http://www.ogre3d.org/phpBB2addons/viewforum.php?f=10
6
7Copyright (c) 2007 tuan.kuranes@gmail.com (Use it Freely, even Statically, but have to contribute any changes)
8
9
10
11This program is free software; you can redistribute it and/or modify it under
12the terms of the GPL General Public License with runtime exception as published by the Free Software
13Foundation; either version 2 of the License, or (at your option) any later
14version.
15
16This program is distributed in the hope that it will be useful, but WITHOUT
17ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18FOR A PARTICULAR PURPOSE. See the GPL General Public License with runtime exception for more details.
19
20You should have received a copy of the GPL General Public License with runtime exception along with
21this program; if not, write to the Free Software Foundation, Inc., 59 Temple
22Place - Suite 330, Boston, MA 02111-1307, USA, or go to
23http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
24-----------------------------------------------------------------------------
25*/
26
27#include "OgreBulletCollisions.h"
28
29#include "Utils/OgreBulletCollisionsMeshToShapeConverter.h"
30
31#include "Shapes/OgreBulletCollisionsTrimeshShape.h"
32#include "Shapes/OgreBulletCollisionsCylinderShape.h"
33#include "Shapes/OgreBulletCollisionsSphereShape.h"
34#include "Shapes/OgreBulletCollisionsBoxShape.h"
35#include "Shapes/OgreBulletCollisionsConvexHullShape.h"
36#include "Shapes/OgreBulletCollisionsCapsuleShape.h"
37
38using namespace OgreBulletCollisions;
39using namespace Ogre;
40
41//------------------------------------------------------------------------------------------------
42void VertexIndexToShape::addStaticVertexData(const VertexData *vertex_data)
43{
44        if (!vertex_data) 
45        return;
46
47        const VertexData *data = vertex_data;
48
49        const unsigned int prev_size = mVertexCount;
50    mVertexCount += (unsigned int)data->vertexCount;
51
52    Ogre::Vector3* tmp_vert = new Ogre::Vector3[mVertexCount];
53        if (mVertexBuffer)
54        {
55                memcpy(tmp_vert, mVertexBuffer, sizeof(Vector3) * prev_size);
56                delete[] mVertexBuffer;
57        }
58        mVertexBuffer = tmp_vert;
59
60        // Get the positional buffer element
61    {   
62        const Ogre::VertexElement* posElem = data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);                       
63        Ogre::HardwareVertexBufferSharedPtr vbuf = data->vertexBufferBinding->getBuffer(posElem->getSource());
64        const unsigned int vSize = (unsigned int)vbuf->getVertexSize();
65
66            unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
67            float* pReal;
68        Ogre::Vector3 * curVertices = &mVertexBuffer[prev_size];
69        const unsigned int vertexCount = (unsigned int)data->vertexCount;
70            for(unsigned int j = 0; j < vertexCount; ++j)
71            {
72                    posElem->baseVertexPointerToElement(vertex, &pReal);
73            vertex += vSize;
74
75                    curVertices->x = (*pReal++);
76                    curVertices->y = (*pReal++);
77                    curVertices->z = (*pReal++);
78
79                    *curVertices = mTransform * (*curVertices);
80           
81            curVertices++;
82        }
83            vbuf->unlock();
84    }
85}
86
87//------------------------------------------------------------------------------------------------
88void VertexIndexToShape::addAnimatedVertexData(const Ogre::VertexData *vertex_data,
89                                                                                           const Ogre::VertexData *blend_data,
90                                                                                           const Ogre::Mesh::IndexMap *indexMap)
91{       
92        // Get the bone index element
93        assert(vertex_data);
94
95        const VertexData *data = blend_data;
96        const unsigned int prev_size = mVertexCount;
97        mVertexCount += (unsigned int)data->vertexCount;
98        Ogre::Vector3* tmp_vert = new Ogre::Vector3[mVertexCount];
99        if (mVertexBuffer)
100        {
101                memcpy(tmp_vert, mVertexBuffer, sizeof(Vector3) * prev_size);
102                delete[] mVertexBuffer;
103        }
104        mVertexBuffer = tmp_vert;
105
106        // Get the positional buffer element
107        {       
108                const Ogre::VertexElement* posElem = data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);       
109                assert (posElem);
110                Ogre::HardwareVertexBufferSharedPtr vbuf = data->vertexBufferBinding->getBuffer(posElem->getSource());
111                const unsigned int vSize = (unsigned int)vbuf->getVertexSize();
112
113                unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
114                float* pReal;
115                Ogre::Vector3 * curVertices = &mVertexBuffer[prev_size];
116                const unsigned int vertexCount = (unsigned int)data->vertexCount;
117                for(unsigned int j = 0; j < vertexCount; ++j)
118                {
119                        posElem->baseVertexPointerToElement(vertex, &pReal);
120                        vertex += vSize;
121
122                        curVertices->x = (*pReal++);
123                        curVertices->y = (*pReal++);
124                        curVertices->z = (*pReal++);
125
126                        *curVertices = mTransform * (*curVertices);
127
128                        curVertices++;
129                }
130                vbuf->unlock();
131        }
132        {
133                const Ogre::VertexElement* bneElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_BLEND_INDICES);
134                assert (bneElem);
135               
136                Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(bneElem->getSource());
137                const unsigned int vSize = (unsigned int)vbuf->getVertexSize();
138                unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
139
140                unsigned char* pBone;
141
142                if (!mBoneIndex)
143                        mBoneIndex = new BoneIndex();   
144                BoneIndex::iterator i;
145
146                Ogre::Vector3 * curVertices = &mVertexBuffer[prev_size];
147
148                const unsigned int vertexCount = (unsigned int)vertex_data->vertexCount;
149                for(unsigned int j = 0; j < vertexCount; ++j)
150                {
151                        bneElem->baseVertexPointerToElement(vertex, &pBone);
152                        vertex += vSize;
153
154                        const unsigned char currBone = (indexMap) ? (*indexMap)[*pBone] : *pBone;
155                        i = mBoneIndex->find (currBone);
156                        Vector3Array* l = 0;
157                        if (i == mBoneIndex->end())
158                        {
159                                l = new Vector3Array;
160                                mBoneIndex->insert(BoneKeyIndex(currBone, l));
161                        }                                               
162                        else 
163                        {
164                                l = i->second;
165                        }
166
167                        l->push_back(*curVertices);
168
169                        curVertices++;
170                }
171                vbuf->unlock(); 
172        }
173}
174
175//------------------------------------------------------------------------------------------------
176void VertexIndexToShape::addIndexData(IndexData *data, const unsigned int offset)
177{
178    const unsigned int prev_size = mIndexCount;
179    mIndexCount += (unsigned int)data->indexCount;
180
181        unsigned int* tmp_ind = new unsigned int[mIndexCount];
182        if (mIndexBuffer)
183        {
184                memcpy (tmp_ind, mIndexBuffer, sizeof(unsigned int) * prev_size);
185                delete[] mIndexBuffer;
186        }
187        mIndexBuffer = tmp_ind;
188
189        const unsigned int numTris = (unsigned int) data->indexCount / 3;
190        HardwareIndexBufferSharedPtr ibuf = data->indexBuffer; 
191        const bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT);
192    unsigned int index_offset = prev_size;
193
194        if (use32bitindexes) 
195    {
196        const unsigned int* pInt = static_cast<unsigned int*>(ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
197        for(unsigned int k = 0; k < numTris; ++k)
198        {
199            mIndexBuffer[index_offset ++] = offset + *pInt++;
200            mIndexBuffer[index_offset ++] = offset + *pInt++;
201            mIndexBuffer[index_offset ++] = offset + *pInt++;
202        }
203        ibuf->unlock();
204    }
205        else 
206    {
207        const unsigned short* pShort = static_cast<unsigned short*>(ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
208                for(unsigned int k = 0; k < numTris; ++k)
209        {
210            mIndexBuffer[index_offset ++] = offset + static_cast<unsigned int> (*pShort++);
211            mIndexBuffer[index_offset ++] = offset + static_cast<unsigned int> (*pShort++);
212            mIndexBuffer[index_offset ++] = offset + static_cast<unsigned int> (*pShort++);
213        }
214        ibuf->unlock();
215    }
216
217}
218//------------------------------------------------------------------------------------------------
219Real VertexIndexToShape::getRadius()
220{
221        if (mBoundRadius == (-1))
222        {
223                getSize();
224                mBoundRadius = (std::max(mBounds.x,std::max(mBounds.y,mBounds.z)) * 0.5);
225        }
226        return mBoundRadius;
227}
228//------------------------------------------------------------------------------------------------
229Vector3 VertexIndexToShape::getSize()
230{
231    const unsigned int vCount = getVertexCount();
232        if (mBounds == Ogre::Vector3(-1,-1,-1) && vCount > 0)
233        {
234
235                const Ogre::Vector3 * const v = getVertices();
236
237        Ogre::Vector3 vmin(v[0]);
238        Ogre::Vector3 vmax(v[0]);
239
240                for(unsigned int j = 1; j < vCount; j++)
241                {
242                        vmin.x = std::min(vmin.x, v[j].x);
243                        vmin.y = std::min(vmin.y, v[j].y);
244                        vmin.z = std::min(vmin.z, v[j].z);
245
246                        vmax.x = std::max(vmax.x, v[j].x);
247                        vmax.y = std::max(vmax.y, v[j].y);
248                        vmax.z = std::max(vmax.z, v[j].z);
249                }
250
251                mBounds.x = vmax.x - vmin.x;
252                mBounds.y = vmax.y - vmin.y;
253                mBounds.z = vmax.z - vmin.z;
254        }
255
256        return mBounds;
257}
258//------------------------------------------------------------------------------------------------
259const Ogre::Vector3* VertexIndexToShape::getVertices()
260{
261        return mVertexBuffer;
262}
263//------------------------------------------------------------------------------------------------
264unsigned int VertexIndexToShape::getVertexCount()
265{
266        return mVertexCount;
267}
268//------------------------------------------------------------------------------------------------
269const unsigned int* VertexIndexToShape::getIndices()
270{
271        return mIndexBuffer;
272}
273//------------------------------------------------------------------------------------------------
274unsigned int VertexIndexToShape::getIndexCount()
275{
276        return mIndexCount;
277}
278
279//------------------------------------------------------------------------------------------------
280SphereCollisionShape* VertexIndexToShape::createSphere()
281{
282        const Ogre::Real rad = getRadius();
283        assert((rad > 0.0) && 
284        ("Sphere radius must be greater than zero"));
285    SphereCollisionShape* shape = new SphereCollisionShape(rad);
286
287    return shape;
288}
289//------------------------------------------------------------------------------------------------
290BoxCollisionShape* VertexIndexToShape::createBox()
291{
292        const Ogre::Vector3 sz = getSize();
293
294        assert((sz.x > 0.0) && (sz.y > 0.0) && (sz.y > 0.0) && 
295        ("Size of box must be greater than zero on all axes"));
296
297        BoxCollisionShape* shape = new BoxCollisionShape(sz);
298        return shape;
299}
300//------------------------------------------------------------------------------------------------
301CylinderCollisionShape* VertexIndexToShape::createCylinder()
302{
303    const Ogre::Vector3 sz = getSize();
304
305    assert((sz.x > 0.0) && (sz.y > 0.0) && (sz.y > 0.0) && 
306        ("Size of Cylinder must be greater than zero on all axes"));
307
308    CylinderCollisionShape* shape = new CylinderCollisionShape(sz, Vector3::UNIT_X);
309    return shape;
310}
311//------------------------------------------------------------------------------------------------
312ConvexHullCollisionShape* VertexIndexToShape::createConvex()
313{
314    assert(mVertexCount && (mIndexCount >= 6) && 
315        ("Mesh must have some vertices and at least 6 indices (2 triangles)"));
316
317    return new ConvexHullCollisionShape(&mVertexBuffer[0].x, mVertexCount, sizeof(Vector3));
318}
319//------------------------------------------------------------------------------------------------
320TriangleMeshCollisionShape* VertexIndexToShape::createTrimesh()
321{
322        assert(mVertexCount && (mIndexCount >= 6) && 
323        ("Mesh must have some vertices and at least 6 indices (2 triangles)"));
324
325        return new TriangleMeshCollisionShape(mVertexBuffer, mVertexCount,mIndexBuffer, mIndexCount);
326}
327//------------------------------------------------------------------------------------------------
328VertexIndexToShape::~VertexIndexToShape()
329{
330        delete[] mVertexBuffer;
331        delete[] mIndexBuffer;
332
333        if (mBoneIndex)
334        {
335                for(BoneIndex::iterator i = mBoneIndex->begin();
336            i != mBoneIndex->end();
337            ++i)
338                {
339                        delete i->second;
340                }
341                delete mBoneIndex;
342        }
343}
344//------------------------------------------------------------------------------------------------
345VertexIndexToShape::VertexIndexToShape(const Matrix4 &transform) :
346        mVertexBuffer (0),
347        mIndexBuffer (0),
348        mVertexCount (0),
349        mIndexCount (0),
350        mBounds (Vector3(-1,-1,-1)),
351        mBoundRadius (-1),
352        mBoneIndex (0),
353        mTransform (transform)
354{       
355}
356//------------------------------------------------------------------------------------------------
357StaticMeshToShapeConverter::StaticMeshToShapeConverter() :
358VertexIndexToShape(),
359        mEntity (0),
360        mNode (0)
361{
362}
363//------------------------------------------------------------------------------------------------
364StaticMeshToShapeConverter::~StaticMeshToShapeConverter()
365{
366}
367//------------------------------------------------------------------------------------------------
368StaticMeshToShapeConverter::StaticMeshToShapeConverter(Entity *entity,  const Matrix4 &transform) :
369        VertexIndexToShape(transform),
370        mEntity (0),
371        mNode (0)
372{
373        addEntity(entity, transform);   
374}
375//------------------------------------------------------------------------------------------------
376StaticMeshToShapeConverter::StaticMeshToShapeConverter(Renderable *rend, const Matrix4 &transform) :
377        VertexIndexToShape(transform),
378        mEntity (0),
379        mNode (0)
380{
381        RenderOperation op;
382        rend->getRenderOperation(op);
383        VertexIndexToShape::addStaticVertexData(op.vertexData);
384        if(op.useIndexes)
385                VertexIndexToShape::addIndexData(op.indexData);
386
387}
388//------------------------------------------------------------------------------------------------
389void StaticMeshToShapeConverter::addEntity(Entity *entity,const Matrix4 &transform)
390{
391        // Each entity added need to reset size and radius
392        // next time getRadius and getSize are asked, they're computed.
393        mBounds  = Ogre::Vector3(-1,-1,-1);
394        mBoundRadius = -1;
395
396        mEntity = entity;
397        mNode = (SceneNode*)(mEntity->getParentNode());
398        mTransform = transform;
399
400        if (mEntity->getMesh()->sharedVertexData)
401        {
402                VertexIndexToShape::addStaticVertexData (mEntity->getMesh()->sharedVertexData);
403        }
404
405        for (unsigned int i = 0;i < mEntity->getNumSubEntities();++i)
406        {
407                SubMesh *sub_mesh = mEntity->getSubEntity(i)->getSubMesh();
408
409                if (!sub_mesh->useSharedVertices)
410                {
411                        VertexIndexToShape::addIndexData(sub_mesh->indexData, mVertexCount);
412                        VertexIndexToShape::addStaticVertexData (sub_mesh->vertexData);
413                }
414                else 
415                {
416                        VertexIndexToShape::addIndexData (sub_mesh->indexData);
417                }
418
419        }
420}
421//------------------------------------------------------------------------------------------------
422void StaticMeshToShapeConverter::addMesh(const MeshPtr &mesh, const Matrix4 &transform)
423{
424        // Each entity added need to reset size and radius
425        // next time getRadius and getSize are asked, they're computed.
426        mBounds  = Ogre::Vector3(-1,-1,-1);
427        mBoundRadius = -1;
428
429        //_entity = entity;
430        //_node = (SceneNode*)(_entity->getParentNode());
431        mTransform = transform;
432
433        if (mesh->hasSkeleton ())
434                Ogre::LogManager::getSingleton().logMessage("MeshToShapeConverter::addMesh : Mesh " + mesh->getName () + " as skeleton but added to trimesh non animated");
435
436        if (mesh->sharedVertexData)
437        {
438                VertexIndexToShape::addStaticVertexData (mesh->sharedVertexData);
439        }
440
441        for(unsigned int i = 0;i < mesh->getNumSubMeshes();++i)
442        {
443                SubMesh *sub_mesh = mesh->getSubMesh(i);
444
445                if (!sub_mesh->useSharedVertices)
446                {
447                        VertexIndexToShape::addIndexData(sub_mesh->indexData, mVertexCount);
448                        VertexIndexToShape::addStaticVertexData (sub_mesh->vertexData);
449                }
450                else 
451                {
452                        VertexIndexToShape::addIndexData (sub_mesh->indexData);
453                }
454
455        }
456}
457//------------------------------------------------------------------------------------------------
458AnimatedMeshToShapeConverter::AnimatedMeshToShapeConverter(Entity *entity,const Matrix4 &transform) :
459VertexIndexToShape(transform),
460mEntity (0),
461mNode (0),
462mTransformedVerticesTemp(0),
463mTransformedVerticesTempSize(0)
464{
465        addEntity(entity, transform);   
466}
467//------------------------------------------------------------------------------------------------
468AnimatedMeshToShapeConverter::AnimatedMeshToShapeConverter() :
469VertexIndexToShape(),
470mEntity (0),
471mNode (0),
472mTransformedVerticesTemp(0),
473mTransformedVerticesTempSize(0)
474{
475}
476//------------------------------------------------------------------------------------------------
477AnimatedMeshToShapeConverter::~AnimatedMeshToShapeConverter()
478{
479        delete[] mTransformedVerticesTemp;
480}
481//------------------------------------------------------------------------------------------------
482void AnimatedMeshToShapeConverter::addEntity(Entity *entity,const Matrix4 &transform)
483{
484        // Each entity added need to reset size and radius
485        // next time getRadius and getSize are asked, they're computed.
486        mBounds  = Ogre::Vector3(-1,-1,-1);
487        mBoundRadius = -1;
488
489        mEntity = entity;
490        mNode = (SceneNode*)(mEntity->getParentNode());
491        mTransform = transform;
492
493        assert (entity->getMesh()->hasSkeleton ());
494
495        mEntity->addSoftwareAnimationRequest(false);
496        mEntity->_updateAnimation();
497
498        if (mEntity->getMesh()->sharedVertexData)
499        {
500                VertexIndexToShape::addAnimatedVertexData (mEntity->getMesh()->sharedVertexData, 
501                        mEntity->_getSkelAnimVertexData(),
502                        &mEntity->getMesh()->sharedBlendIndexToBoneIndexMap); 
503        }
504
505        for (unsigned int i = 0;i < mEntity->getNumSubEntities();++i)
506        {
507                SubMesh *sub_mesh = mEntity->getSubEntity(i)->getSubMesh();
508
509                if (!sub_mesh->useSharedVertices)
510                {
511                        VertexIndexToShape::addIndexData(sub_mesh->indexData, mVertexCount);
512
513                        VertexIndexToShape::addAnimatedVertexData (sub_mesh->vertexData, 
514                                mEntity->getSubEntity(i)->_getSkelAnimVertexData(),
515                                &sub_mesh->blendIndexToBoneIndexMap); 
516                }
517                else 
518                {
519                        VertexIndexToShape::addIndexData (sub_mesh->indexData);
520                }
521
522        }
523
524        mEntity->removeSoftwareAnimationRequest(false);
525}
526//------------------------------------------------------------------------------------------------
527void AnimatedMeshToShapeConverter::addMesh(const MeshPtr &mesh, const Matrix4 &transform)
528{
529        // Each entity added need to reset size and radius
530        // next time getRadius and getSize are asked, they're computed.
531        mBounds  = Ogre::Vector3(-1,-1,-1);
532        mBoundRadius = -1;
533
534        //_entity = entity;
535        //_node = (SceneNode*)(_entity->getParentNode());
536        mTransform = transform;
537
538        assert (mesh->hasSkeleton ());
539
540        if (mesh->sharedVertexData)
541        {
542                VertexIndexToShape::addAnimatedVertexData (mesh->sharedVertexData, 
543                        0,
544                        &mesh->sharedBlendIndexToBoneIndexMap); 
545        }
546
547        for(unsigned int i = 0;i < mesh->getNumSubMeshes();++i)
548        {
549                SubMesh *sub_mesh = mesh->getSubMesh(i);
550
551                if (!sub_mesh->useSharedVertices)
552                {
553                        VertexIndexToShape::addIndexData(sub_mesh->indexData, mVertexCount);
554
555                        VertexIndexToShape::addAnimatedVertexData (sub_mesh->vertexData, 
556                                0,
557                                &sub_mesh->blendIndexToBoneIndexMap); 
558                }
559                else 
560                {
561                        VertexIndexToShape::addIndexData (sub_mesh->indexData);
562                }
563
564        }
565}
566//------------------------------------------------------------------------------------------------
567bool AnimatedMeshToShapeConverter::getBoneVertices(unsigned char bone, 
568                                                                                                         unsigned int &vertex_count, 
569                                                                                                         Ogre::Vector3* &vertices,
570                                                                                                         const Vector3 &bonePosition)
571{
572        BoneIndex::iterator i = mBoneIndex->find(bone);
573
574        if (i == mBoneIndex->end()) 
575                return false;
576
577        if (i->second->empty()) 
578                return false;
579
580        vertex_count = (unsigned int) i->second->size() + 1;
581        if (vertex_count > mTransformedVerticesTempSize)
582        {       
583                if (mTransformedVerticesTemp)
584                        delete[] mTransformedVerticesTemp;
585
586                mTransformedVerticesTemp = new Ogre::Vector3[vertex_count];
587
588        }
589
590        vertices = mTransformedVerticesTemp;
591        vertices[0] = bonePosition;
592        //mEntity->_getParentNodeFullTransform() *
593        //      mEntity->getSkeleton()->getBone(bone)->_getDerivedPosition();
594
595        //mEntity->getSkeleton()->getBone(bone)->_getDerivedOrientation()
596        unsigned int currBoneVertex = 1;
597        Vector3Array::iterator j = i->second->begin();
598        while(j != i->second->end())
599        {
600                vertices[currBoneVertex] = (*j);
601                ++j;
602                ++currBoneVertex; 
603        }       
604        return true;
605}
606//------------------------------------------------------------------------------------------------
607BoxCollisionShape* AnimatedMeshToShapeConverter::createAlignedBox(unsigned char bone, 
608                                                                                                                                  const Vector3 &bonePosition,
609                                                                                                                                  const Quaternion &boneOrientation)
610{
611        unsigned int vertex_count;
612        Vector3* vertices;
613
614        if (!getBoneVertices(bone, vertex_count, vertices, bonePosition)) 
615                return 0;
616
617        Vector3 min_vec(vertices[0]);
618        Vector3 max_vec(vertices[0]);
619
620        for(unsigned int j = 1; j < vertex_count ;j++)
621        {
622                min_vec.x = std::min(min_vec.x,vertices[j].x);
623                min_vec.y = std::min(min_vec.y,vertices[j].y);
624                min_vec.z = std::min(min_vec.z,vertices[j].z);
625
626                max_vec.x = std::max(max_vec.x,vertices[j].x);
627                max_vec.y = std::max(max_vec.y,vertices[j].y);
628                max_vec.z = std::max(max_vec.z,vertices[j].z);
629        }
630        const Ogre::Vector3 maxMinusMin(max_vec - min_vec);
631        BoxCollisionShape* box = new BoxCollisionShape(maxMinusMin);
632
633        const Ogre::Vector3 pos
634                (min_vec.x + (maxMinusMin.x * 0.5),
635                min_vec.y + (maxMinusMin.y * 0.5),
636                min_vec.z + (maxMinusMin.z * 0.5));
637
638        //box->setPosition(pos);
639
640        return box;
641}
642//------------------------------------------------------------------------------------------------
643bool AnimatedMeshToShapeConverter::getOrientedBox(unsigned char bone, 
644                                         const Vector3 &bonePosition,
645                                         const Quaternion &boneOrientation,
646                                         Vector3 &box_afExtent,
647                                         Vector3 *box_akAxis,
648                                         Vector3 &box_kCenter)
649{
650        unsigned int vertex_count;
651        Vector3* vertices;
652
653        if (!getBoneVertices(bone, vertex_count, vertices, bonePosition))
654                return false;
655
656         box_kCenter = Vector3::ZERO;
657
658         {
659                 for(unsigned int c = 0 ;c < vertex_count;c++)
660                 {
661                         box_kCenter += vertices[c];
662                 }
663                 const Ogre::Real invVertexCount = 1.0 / vertex_count;
664                 box_kCenter *= invVertexCount;
665         }
666        Quaternion orient = boneOrientation;
667        orient.ToAxes(box_akAxis);
668
669
670        // Let C be the box center and let U0, U1, and U2 be the box axes.  Each
671        // input point is of the form X = C + y0*U0 + y1*U1 + y2*U2.  The
672        // following code computes min(y0), max(y0), min(y1), max(y1), min(y2),
673        // and max(y2).  The box center is then adjusted to be
674        //   C' = C + 0.5*(min(y0)+max(y0))*U0 + 0.5*(min(y1)+max(y1))*U1 +
675        //        0.5*(min(y2)+max(y2))*U2
676
677        Ogre::Vector3 kDiff (vertices[1] - box_kCenter);
678        Ogre::Real fY0Min = kDiff.dotProduct(box_akAxis[0]), fY0Max = fY0Min;
679        Ogre::Real fY1Min = kDiff.dotProduct(box_akAxis[1]), fY1Max = fY1Min;
680        Ogre::Real fY2Min = kDiff.dotProduct(box_akAxis[2]), fY2Max = fY2Min;
681
682        for (unsigned int i = 2; i < vertex_count; i++)
683        {
684                kDiff = vertices[i] - box_kCenter;
685
686                const Ogre::Real fY0 = kDiff.dotProduct(box_akAxis[0]);
687                if ( fY0 < fY0Min )
688                        fY0Min = fY0;
689                else if ( fY0 > fY0Max )
690                        fY0Max = fY0;
691
692                const Ogre::Real fY1 = kDiff.dotProduct(box_akAxis[1]);
693                if ( fY1 < fY1Min )
694                        fY1Min = fY1;
695                else if ( fY1 > fY1Max )
696                        fY1Max = fY1;
697
698                const Ogre::Real fY2 = kDiff.dotProduct(box_akAxis[2]);
699                if ( fY2 < fY2Min )
700                        fY2Min = fY2;
701                else if ( fY2 > fY2Max )
702                        fY2Max = fY2;
703        }
704
705        box_afExtent.x = ((Real)0.5)*(fY0Max - fY0Min);
706        box_afExtent.y = ((Real)0.5)*(fY1Max - fY1Min);
707        box_afExtent.z = ((Real)0.5)*(fY2Max - fY2Min);
708
709        box_kCenter += (0.5*(fY0Max+fY0Min))*box_akAxis[0] +
710                (0.5*(fY1Max+fY1Min))*box_akAxis[1] +
711                (0.5*(fY2Max+fY2Min))*box_akAxis[2];
712
713        box_afExtent *= 2.0;
714
715        return true;
716}
717//------------------------------------------------------------------------------------------------
718BoxCollisionShape* AnimatedMeshToShapeConverter::createOrientedBox(unsigned char bone, 
719                                                                                                                                   const Vector3 &bonePosition,
720                                                                                                                                   const Quaternion &boneOrientation)
721{
722        Ogre::Vector3 box_akAxis[3];
723        Ogre::Vector3 box_afExtent;
724        Ogre::Vector3 box_afCenter;
725
726        if (!getOrientedBox(bone, bonePosition, boneOrientation,
727                                                box_afExtent,
728                                                box_akAxis,
729                                                box_afCenter))
730                return 0;
731
732        BoxCollisionShape *geom = new BoxCollisionShape(box_afExtent);
733        //geom->setOrientation(Quaternion(box_akAxis[0],box_akAxis[1],box_akAxis[2]));
734        //geom->setPosition(box_afCenter);
735        return geom; 
736}
737//------------------------------------------------------------------------------------------------
738CapsuleCollisionShape* AnimatedMeshToShapeConverter::createOrientedCapsuleCollisionShape(unsigned char bone, 
739                                                                                                                                                                                         const Vector3 &bonePosition,
740                                                                                                                                                                                         const Quaternion &boneOrientation)
741{
742        Ogre::Vector3 box_akAxis[3];
743        Ogre::Vector3 box_afExtent;
744        Ogre::Vector3 box_afCenter;
745
746        if (!getOrientedBox(bone,  bonePosition, boneOrientation,
747                                                box_afExtent,
748                                                box_akAxis,
749                                                box_afCenter))
750                return 0;
751
752        // find axes with longest length
753
754        Vector3 cap_dir;    //std::max(box_afExtent.x,std::max(box_afExtent.y,box_afExtent.z));
755        Real cap_dirLength;  //std::max(box_afExtent.x,std::max(box_afExtent.y,box_afExtent.z));
756        Real cap_radius;         // max axe length
757        if (box_afExtent.x - box_afExtent.y > 0 && box_afExtent.x - box_afExtent.z > 0)
758        {
759                cap_dir = Vector3::UNIT_X;
760                cap_dirLength = box_afExtent.x;
761                cap_radius = std::max (box_afExtent.y, box_afExtent.z);
762        }
763        else if (box_afExtent.y - box_afExtent.x > 0 && box_afExtent.y - box_afExtent.z > 0)
764        {
765                cap_dir = Vector3::UNIT_Y;
766                cap_dirLength = box_afExtent.y;
767                cap_radius = std::max (box_afExtent.x, box_afExtent.z);
768        }
769        else if (box_afExtent.z - box_afExtent.y > 0 && box_afExtent.z - box_afExtent.y > 0)
770        {
771                cap_dir = Vector3::UNIT_Z;
772                cap_dirLength = box_afExtent.z;
773                cap_radius = std::max (box_afExtent.x, box_afExtent.z);
774        }
775
776        CapsuleCollisionShape* geom = new CapsuleCollisionShape(cap_radius, cap_dirLength, cap_dir);
777
778        //geom->setOrientation(orient);
779        //geom->setPosition(cap_orig + (boneOrientation * (cap_dirLength * 0.5)));
780
781        return geom;
782}
Note: See TracBrowser for help on using the repository browser.