Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/physics/src/ogreode/OgreOdeEntityInformer.cpp @ 1922

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

Minor adjustments to OgreODE when compiling under gcc.

  • Property svn:eol-style set to native
File size: 24.0 KB
Line 
1#include "OgreOdePrecompiledHeaders.h"
2
3#include "OgreOdeEntityInformer.h"
4#include "OgreOdeMaintainedList.h"
5#include "OgreOdeBody.h"
6#include "OgreOdeGeometry.h"
7#include "OgreOdeMass.h"
8#include "OgreOdeEigenSolver.h"
9
10#include "OgreOdeTriangleMeshDataManager.h"
11
12using namespace OgreOde;
13using namespace Ogre;
14
15
16#include "OgreOdePrecompiledHeaders.h"
17
18#include "OgreOdeEntityInformer.h"
19#include "OgreOdeMaintainedList.h"
20#include "OgreOdeBody.h"
21#include "OgreOdeGeometry.h"
22#include "OgreOdeMass.h"
23#include "OgreOdeEigenSolver.h"
24
25using namespace OgreOde;
26using namespace Ogre;
27
28//------------------------------------------------------------------------------------------------
29void EntityInformer::addVertexData(const VertexData *vertex_data,
30                                   const VertexData *blended_data,
31                                   const Mesh::IndexMap *indexMap)
32{
33        if (!vertex_data) 
34        return;
35
36        const VertexData *data = (blended_data) ? blended_data: vertex_data;
37
38        const unsigned int prev_size = _vertex_count;
39    _vertex_count += (unsigned int)data->vertexCount;
40
41    Ogre::Vector3* tmp_vert = new Ogre::Vector3[_vertex_count];
42        if (_vertices)
43        {
44                memcpy(tmp_vert,_vertices,sizeof(Vector3) * prev_size);
45                delete[] _vertices;
46        }
47        _vertices = tmp_vert;
48
49        // Get the positional buffer element
50    {   
51        const Ogre::VertexElement* posElem = data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);                       
52        Ogre::HardwareVertexBufferSharedPtr vbuf = data->vertexBufferBinding->getBuffer(posElem->getSource());
53        const unsigned int vSize = (unsigned int)vbuf->getVertexSize();
54
55            unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
56            float* pReal;
57        Ogre::Vector3 * curVertices = &_vertices[prev_size];
58        const unsigned int vertexCount = (unsigned int)data->vertexCount;
59            for(unsigned int j = 0; j < vertexCount; ++j)
60            {
61                    posElem->baseVertexPointerToElement(vertex, &pReal);
62            vertex += vSize;
63
64                    curVertices->x = (*pReal++);
65                    curVertices->y = (*pReal++);
66                    curVertices->z = (*pReal++);
67
68                    *curVertices = _transform * (*curVertices);
69           
70            curVertices++;
71        }
72            vbuf->unlock();
73    }
74
75        // Get the bone index element
76        if (_entity && _entity->hasSkeleton())
77        {
78
79        Ogre::MeshPtr mesh = _entity->getMesh ();
80
81                const Ogre::VertexElement* bneElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_BLEND_INDICES);
82                assert (bneElem);
83                {
84            Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(bneElem->getSource());
85            const unsigned int vSize = (unsigned int)vbuf->getVertexSize();
86                        unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
87
88                        unsigned char* pBone;
89
90            if (!_bone_mapping)
91                _bone_mapping = new BoneMapping();     
92            BoneMapping::iterator i;
93
94            Ogre::Vector3 * curVertices = &_vertices[prev_size];
95           
96            const unsigned int vertexCount = (unsigned int)vertex_data->vertexCount;
97                        for(unsigned int j = 0; j < vertexCount; ++j)
98                        {
99                                bneElem->baseVertexPointerToElement(vertex, &pBone);
100                vertex += vSize;
101               
102                const unsigned char currBone = (indexMap) ? (*indexMap)[*pBone] : *pBone;
103                                i = _bone_mapping->find (currBone);
104                                Vector3Array* l = 0;
105                                if (i == _bone_mapping->end())
106                                {
107                                        l = new Vector3Array;
108                                        _bone_mapping->insert(BoneMappingKey(currBone, l));
109                                }                                               
110                                else 
111                {
112                    l = i->second;
113                }
114
115                                l->push_back(*curVertices);
116
117                curVertices++;
118                        }
119                        vbuf->unlock();
120                }
121        }
122}
123
124
125//------------------------------------------------------------------------------------------------
126void EntityInformer::addIndexData(IndexData *data, const unsigned int offset)
127{
128    const unsigned int prev_size = _index_count;
129    _index_count += (unsigned int)data->indexCount;
130
131        TriangleIndex* tmp_ind = new TriangleIndex[_index_count];
132        if (_indices)
133        {
134                memcpy (tmp_ind, _indices, sizeof(unsigned int) * prev_size);
135                delete[] _indices;
136        }
137        _indices = tmp_ind;
138
139        const unsigned int numTris = (unsigned int) data->indexCount / 3;
140        HardwareIndexBufferSharedPtr ibuf = data->indexBuffer; 
141        const bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT);
142    unsigned int index_offset = prev_size;
143
144        if (use32bitindexes) 
145    {
146        const unsigned int* pInt = static_cast<unsigned int*>(ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
147        for(unsigned int k = 0; k < numTris; ++k)
148        {
149            _indices[index_offset ++] = offset + *pInt++;
150            _indices[index_offset ++] = offset + *pInt++;
151            _indices[index_offset ++] = offset + *pInt++;
152        }
153        ibuf->unlock();
154    }
155        else 
156    {
157        const unsigned short* pShort = static_cast<unsigned short*>(ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
158                for(unsigned int k = 0; k < numTris; ++k)
159        {
160            _indices[index_offset ++] = offset + static_cast<unsigned int> (*pShort++);
161            _indices[index_offset ++] = offset + static_cast<unsigned int> (*pShort++);
162            _indices[index_offset ++] = offset + static_cast<unsigned int> (*pShort++);
163        }
164        ibuf->unlock();
165    }
166
167}
168//------------------------------------------------------------------------------------------------
169void EntityInformer::addEntity(Entity *entity,const Matrix4 &transform)
170{
171        // Each entity added need to reset size and radius
172        // next time getRadius and getSize are asked, they're computed.
173        _size  = Ogre::Vector3(-1,-1,-1);
174        _radius = -1;
175
176        _entity = entity;
177        _node = (SceneNode*)(_entity->getParentNode());
178        _transform = transform;
179
180        const bool isSkeletonAnimated = _entity->hasSkeleton();
181        //const bool isHWanimated = isSkeletonAnimated && entity->isHardwareAnimationEnabled();
182        if (isSkeletonAnimated)
183        {
184                _entity->addSoftwareAnimationRequest(false);
185                _entity->_updateAnimation();
186        }
187
188
189        if (_entity->getMesh()->sharedVertexData)
190        {
191                if (!isSkeletonAnimated)
192                        addVertexData (_entity->getMesh()->sharedVertexData);
193                else
194                        addVertexData (_entity->getMesh()->sharedVertexData, 
195                        _entity->_getSkelAnimVertexData(),
196                        &_entity->getMesh()->sharedBlendIndexToBoneIndexMap); 
197        }
198
199        for(unsigned int i = 0;i < _entity->getNumSubEntities();++i)
200        {
201                SubMesh *sub_mesh = _entity->getSubEntity(i)->getSubMesh();
202
203                if (!sub_mesh->useSharedVertices)
204                {
205                        addIndexData(sub_mesh->indexData,_vertex_count);
206
207                        if (!isSkeletonAnimated)
208                                addVertexData (sub_mesh->vertexData);
209                        else
210                                addVertexData (sub_mesh->vertexData, 
211                                _entity->getSubEntity(i)->_getSkelAnimVertexData(),
212                                &sub_mesh->blendIndexToBoneIndexMap); 
213                }
214                else 
215                {
216                        addIndexData (sub_mesh->indexData);
217                }
218
219        }
220
221        if (isSkeletonAnimated) 
222                _entity->removeSoftwareAnimationRequest(false);
223}
224//------------------------------------------------------------------------------------------------
225void EntityInformer::addMesh(const MeshPtr &mesh, const Matrix4 &transform)
226{
227        // Each entity added need to reset size and radius
228        // next time getRadius and getSize are asked, they're computed.
229        _size  = Ogre::Vector3(-1,-1,-1);
230        _radius = -1;
231
232        //_entity = entity;
233        //_node = (SceneNode*)(_entity->getParentNode());
234        _transform = transform;
235
236        if (mesh->hasSkeleton ())
237                Ogre::LogManager::getSingleton().logMessage("EntityInformer::addMesh : Mesh " + mesh->getName () + " as skeleton but added to trimesh non animated");
238//              OGRE_EXCEPT(1, "Mesh " + mesh->getName () + " as skeleton but added to trimesh non animated",
239//                                      "EntityInformer::addMesh");
240
241        if (mesh->sharedVertexData)
242        {
243                addVertexData (mesh->sharedVertexData);
244        }
245
246        for(unsigned int i = 0;i < mesh->getNumSubMeshes();++i)
247        {
248                SubMesh *sub_mesh = mesh->getSubMesh(i);
249
250                if (!sub_mesh->useSharedVertices)
251                {
252                        addIndexData(sub_mesh->indexData, _vertex_count);
253                        addVertexData (sub_mesh->vertexData);
254                }
255                else 
256                {
257                        addIndexData (sub_mesh->indexData);
258                }
259
260        }
261}
262//------------------------------------------------------------------------------------------------
263EntityInformer::EntityInformer(Entity *entity,const Matrix4 &transform) :
264        _radius (-1),
265        _size (Vector3(-1,-1,-1)),
266        _center (Vector3(-1,-1,-1)),
267        _vertices (0),
268        _indices (0),
269        _vertex_count (0),
270        _index_count (0),
271        _bone_mapping (0)
272{
273        addEntity(entity, transform);   
274}
275//------------------------------------------------------------------------------------------------
276EntityInformer::EntityInformer() :
277                _radius (-1),
278                _size (Vector3(-1,-1,-1)),
279                _center (Vector3(-1,-1,-1)),
280                _vertices (0),
281                _indices (0),
282                _vertex_count (0),
283                _index_count (0),
284        _bone_mapping (0)
285{
286         
287}
288//------------------------------------------------------------------------------------------------
289Real EntityInformer::getRadius()
290{
291        if (_radius == (-1))
292        {
293                getSize();
294                _radius = (std::max(_size.x,std::max(_size.y,_size.z)) * 0.5);
295        }
296        return _radius;
297}
298//------------------------------------------------------------------------------------------------
299Vector3 EntityInformer::getSize()
300{
301    const unsigned int vCount = getVertexCount();
302        if (_size == Ogre::Vector3(-1,-1,-1) && vCount > 0)
303        {
304
305                const Ogre::Vector3 * const v = getVertices();
306
307        Ogre::Vector3 vmin(v[0]);
308        Ogre::Vector3 vmax(v[0]);
309
310                for(unsigned int j = 1; j < vCount; j++)
311                {
312                        vmin.x = std::min(vmin.x, v[j].x);
313                        vmin.y = std::min(vmin.y, v[j].y);
314                        vmin.z = std::min(vmin.z, v[j].z);
315
316                        vmax.x = std::max(vmax.x, v[j].x);
317                        vmax.y = std::max(vmax.y, v[j].y);
318                        vmax.z = std::max(vmax.z, v[j].z);
319                }
320
321                _size.x = vmax.x - vmin.x;
322                _size.y = vmax.y - vmin.y;
323                _size.z = vmax.z - vmin.z;
324
325                _center.x = vmin.x + _size.x * 0.5;
326                _center.y = vmin.y + _size.y * 0.5;
327                _center.z = vmin.z + _size.z * 0.5;
328
329        }
330
331        return _size;
332}
333//------------------------------------------------------------------------------------------------
334Vector3 EntityInformer::getCenter()
335{
336        const unsigned int vCount = getVertexCount();
337        if (_center == Ogre::Vector3(-1,-1,-1) && vCount > 0)
338        {
339                getSize();
340        }
341
342        return _center;
343}
344//------------------------------------------------------------------------------------------------
345const Ogre::Vector3* EntityInformer::getVertices()
346{
347        return _vertices;
348}
349//------------------------------------------------------------------------------------------------
350unsigned int EntityInformer::getVertexCount()
351{
352        return _vertex_count;
353}
354//------------------------------------------------------------------------------------------------
355const TriangleIndex* EntityInformer::getIndices()
356{
357        return _indices;
358}
359//------------------------------------------------------------------------------------------------
360unsigned int EntityInformer::getIndexCount()
361{
362        return _index_count;
363}
364//------------------------------------------------------------------------------------------------
365Body* EntityInformer::createSingleDynamicSphere(Real mass, World *world, Space* space)
366{
367        const Ogre::Real rad = getRadius();
368
369        assert((rad > 0.0) && 
370        ("Sphere radius must be greater than zero"));
371
372        Body* body = new Body(world, "OgreOde::Body_" + _entity->getName());
373        body->setMass(SphereMass(mass, rad));
374
375        SphereGeometry* geom = new SphereGeometry(rad, world, space);
376        geom->setBody(body);
377
378        body->setPosition(_node->_getDerivedPosition());
379        body->setOrientation(_node->_getDerivedOrientation());
380
381        _node->attachObject(body);
382
383        return body;
384}
385//------------------------------------------------------------------------------------------------
386Body* EntityInformer::createSingleDynamicBox(Real mass, World *world, Space* space)
387{
388        const Ogre::Vector3 sz = getSize();
389
390        assert((sz.x > 0.0) && (sz.y > 0.0) && (sz.y > 0.0) && 
391        ("Size of box must be greater than zero on all axes"));
392
393        Body* body = new Body(world, "OgreOde::Body_" + _node->getName());
394        body->setMass(BoxMass(mass,sz));
395
396        BoxGeometry* geom = new BoxGeometry(sz, world, space);
397        geom->setBody(body);
398
399        body->setPosition(_node->_getDerivedPosition());
400        body->setOrientation(_node->_getDerivedOrientation());
401
402        _node->attachObject(body);
403
404        return body;
405}
406//------------------------------------------------------------------------------------------------
407TriangleMeshGeometry* EntityInformer::createStaticTriangleMesh(World *world, Space* space)
408{
409        assert(_vertex_count && (_index_count >= 6) && 
410        ("Mesh must have some vertices and at least 6 indices (2 triangles)"));
411
412        return new TriangleMeshGeometry(_vertices, _vertex_count,_indices, _index_count, world, space);
413}
414//------------------------------------------------------------------------------------------------
415BoxGeometry* EntityInformer::createSingleStaticBox(World *world, Space* space)
416{
417        BoxGeometry* geom = new BoxGeometry(getSize(), world, space);
418
419        geom->setPosition(_node->_getDerivedPosition());
420        geom->setOrientation(_node->_getDerivedOrientation());
421
422        return geom;
423}
424//------------------------------------------------------------------------------------------------
425bool EntityInformer::getBoneVertices(unsigned char bone, unsigned int &vertex_count, Ogre::Vector3* &vertices)
426{
427        BoneMapping::iterator i = _bone_mapping->find(bone);
428       
429    if (i == _bone_mapping->end()) 
430        return false;
431
432        if (i->second->empty()) 
433        return false;
434
435    vertex_count = (unsigned int) i->second->size() + 1;
436
437        vertices = new Ogre::Vector3[vertex_count];
438        vertices[0] = _entity->_getParentNodeFullTransform() * 
439            _entity->getSkeleton()->getBone(bone)->_getDerivedPosition();
440
441        unsigned int o = 1;
442        for(Vector3Array::iterator j = i->second->begin();
443        j != i->second->end(); ++j,++o) 
444    {
445        vertices[o] = (*j);
446    }       
447        return true;
448}
449//------------------------------------------------------------------------------------------------
450BoxGeometry* EntityInformer::createAlignedBox(unsigned char bone, World *world, Space* space)
451{
452        unsigned int vertex_count;
453        Vector3* vertices;
454        if (!getBoneVertices(bone, vertex_count, vertices)) 
455        return 0;
456
457        Vector3 min_vec(vertices[0]);
458        Vector3 max_vec(vertices[0]);
459
460        for(unsigned int j = 1; j < vertex_count ;j++)
461        {
462                min_vec.x = std::min(min_vec.x,vertices[j].x);
463                min_vec.y = std::min(min_vec.y,vertices[j].y);
464                min_vec.z = std::min(min_vec.z,vertices[j].z);
465
466                max_vec.x = std::max(max_vec.x,vertices[j].x);
467                max_vec.y = std::max(max_vec.y,vertices[j].y);
468                max_vec.z = std::max(max_vec.z,vertices[j].z);
469        }
470    const Ogre::Vector3 maxMinusMin(max_vec - min_vec);
471    BoxGeometry* box = new BoxGeometry(maxMinusMin, world, space);
472
473    const Ogre::Vector3 pos(min_vec.x + (maxMinusMin.x * 0.5),
474                      min_vec.y + (maxMinusMin.y * 0.5),
475                      min_vec.z + (maxMinusMin.z * 0.5));
476
477        box->setPosition(pos);
478
479        delete[] vertices;
480
481        return box;
482}
483//------------------------------------------------------------------------------------------------
484BoxGeometry* EntityInformer::createOrientedBox(unsigned char bone, World *world, Space* space)
485{
486
487#define TESTOOB
488#ifdef TESTOOB
489        unsigned int vertex_count;
490        Vector3* vertices;
491        if (!getBoneVertices(bone, vertex_count, vertices))
492                return 0;
493
494        Vector3 box_kCenter(Vector3::ZERO);
495        Ogre::Vector3 box_akAxis[3];
496        Ogre::Real box_afExtent[3];
497
498        //   EigenSolver::GaussPointsFit (vertex_count-1, &vertices[1], box_kCenter, box_akAxis, box_afExtent);
499
500        Ogre::Real invVertexCount=1.0/(Ogre::Real)vertex_count;
501        for(size_t c=0;c<vertex_count;c++)
502        {
503                box_kCenter+=vertices[c];
504        }
505        box_kCenter*=invVertexCount;
506
507        Quaternion orient=_entity->getSkeleton()->getBone(bone)->_getDerivedOrientation();
508        orient.ToAxes(box_akAxis);
509
510
511        // Let C be the box center and let U0, U1, and U2 be the box axes.  Each
512        // input point is of the form X = C + y0*U0 + y1*U1 + y2*U2.  The
513        // following code computes min(y0), max(y0), min(y1), max(y1), min(y2),
514        // and max(y2).  The box center is then adjusted to be
515        //   C' = C + 0.5*(min(y0)+max(y0))*U0 + 0.5*(min(y1)+max(y1))*U1 +
516        //        0.5*(min(y2)+max(y2))*U2
517
518
519        Ogre::Vector3 kDiff (vertices[1] - box_kCenter);
520        Ogre::Real fY0Min = kDiff.dotProduct(box_akAxis[0]), fY0Max = fY0Min;
521        Ogre::Real fY1Min = kDiff.dotProduct(box_akAxis[1]), fY1Max = fY1Min;
522        Ogre::Real fY2Min = kDiff.dotProduct(box_akAxis[2]), fY2Max = fY2Min;
523
524        for (unsigned int i = 2; i < vertex_count; i++)
525        {
526                kDiff = vertices[i] - box_kCenter;
527
528                const Ogre::Real fY0 = kDiff.dotProduct(box_akAxis[0]);
529                if ( fY0 < fY0Min )
530                        fY0Min = fY0;
531                else if ( fY0 > fY0Max )
532                        fY0Max = fY0;
533
534                const Ogre::Real fY1 = kDiff.dotProduct(box_akAxis[1]);
535                if ( fY1 < fY1Min )
536                        fY1Min = fY1;
537                else if ( fY1 > fY1Max )
538                        fY1Max = fY1;
539
540                const Ogre::Real fY2 = kDiff.dotProduct(box_akAxis[2]);
541                if ( fY2 < fY2Min )
542                        fY2Min = fY2;
543                else if ( fY2 > fY2Max )
544                        fY2Max = fY2;
545        }
546
547        box_afExtent[0] = ((Real)0.5)*(fY0Max - fY0Min);
548        box_afExtent[1] = ((Real)0.5)*(fY1Max - fY1Min);
549        box_afExtent[2] = ((Real)0.5)*(fY2Max - fY2Min);
550
551        box_kCenter += (0.5*(fY0Max+fY0Min))*box_akAxis[0] +
552                (0.5*(fY1Max+fY1Min))*box_akAxis[1] +
553                (0.5*(fY2Max+fY2Min))*box_akAxis[2];
554
555        BoxGeometry *geom = new BoxGeometry(Vector3(box_afExtent[0] * 2.0,
556                box_afExtent[1] * 2.0,
557                box_afExtent[2] * 2.0),
558                world, space);
559        geom->setOrientation(Quaternion(box_akAxis[0],box_akAxis[1],box_akAxis[2]));
560        geom->setPosition(box_kCenter);
561        return geom; 
562#else
563        unsigned int vertex_count;
564        Vector3* vertices;
565        if (!getBoneVertices(bone, vertex_count, vertices)) 
566                return 0;
567
568        Vector3 box_kCenter;
569        Ogre::Vector3 box_akAxis[3];
570        Ogre::Real box_afExtent[3];
571
572        EigenSolver::GaussPointsFit (vertex_count, vertices, box_kCenter, box_akAxis, box_afExtent);
573
574        // Let C be the box center and let U0, U1, and U2 be the box axes.  Each
575        // input point is of the form X = C + y0*U0 + y1*U1 + y2*U2.  The
576        // following code computes min(y0), max(y0), min(y1), max(y1), min(y2),
577        // and max(y2).  The box center is then adjusted to be
578        //   C' = C + 0.5*(min(y0)+max(y0))*U0 + 0.5*(min(y1)+max(y1))*U1 +
579        //        0.5*(min(y2)+max(y2))*U2
580
581        Ogre::Vector3 kDiff (vertices[0] - box_kCenter);
582        Ogre::Real fY0Min = kDiff.dotProduct(box_akAxis[0]), fY0Max = fY0Min;
583        Ogre::Real fY1Min = kDiff.dotProduct(box_akAxis[1]), fY1Max = fY1Min;
584        Ogre::Real fY2Min = kDiff.dotProduct(box_akAxis[2]), fY2Max = fY2Min;
585
586        for (unsigned int i = 1; i < vertex_count; i++)
587        {
588                kDiff = vertices[i] - box_kCenter;
589
590                const Ogre::Real fY0 = kDiff.dotProduct(box_akAxis[0]);
591                if ( fY0 < fY0Min )
592                        fY0Min = fY0;
593                else if ( fY0 > fY0Max )
594                        fY0Max = fY0;
595
596                const Ogre::Real fY1 = kDiff.dotProduct(box_akAxis[1]);
597                if ( fY1 < fY1Min )
598                        fY1Min = fY1;
599                else if ( fY1 > fY1Max )
600                        fY1Max = fY1;
601
602                const Ogre::Real fY2 = kDiff.dotProduct(box_akAxis[2]);
603                if ( fY2 < fY2Min )
604                        fY2Min = fY2;
605                else if ( fY2 > fY2Max )
606                        fY2Max = fY2;
607        }
608
609        box_afExtent[0] = ((Real)0.5)*(fY0Max - fY0Min);
610        box_afExtent[1] = ((Real)0.5)*(fY1Max - fY1Min);
611        box_afExtent[2] = ((Real)0.5)*(fY2Max - fY2Min);
612
613        box_kCenter += (box_afExtent[0])*box_akAxis[0] +
614                (box_afExtent[1])*box_akAxis[1] +
615                (box_afExtent[2])*box_akAxis[2];
616
617        BoxGeometry *geom = new BoxGeometry(Vector3(box_afExtent[0] * 2.0,
618                box_afExtent[1] * 2.0,
619                box_afExtent[2] * 2.0),
620                world, space);
621        geom->setOrientation(Quaternion(box_akAxis[0],box_akAxis[1],box_akAxis[2]));
622        geom->setPosition(box_kCenter);
623        return geom;
624#endif
625}
626//------------------------------------------------------------------------------------------------
627CapsuleGeometry* EntityInformer::createOrientedCapsule(unsigned char bone, World *world, Space* space)
628{
629        unsigned int vertex_count;
630        Vector3* vertices;
631
632        if (!getBoneVertices(bone,vertex_count,vertices)) 
633        return 0;
634
635        Vector3 cap_orig;
636        Vector3 cap_dir;
637        Real cap_rad;
638
639        Vector3 line_orig;
640        Vector3 line_dir;
641
642        EigenSolver::orthogonalLineFit (vertex_count, vertices, line_orig, line_dir);
643
644   Ogre::Real fMaxRadiusSqr = (Real) 0.0;
645    unsigned int c;
646    for (c = 0; c < vertex_count; c++)
647    {
648                const Ogre::Real fRadiusSqr = EigenSolver::SqrDistance(vertices[c], line_orig, line_dir);
649        if ( fRadiusSqr > fMaxRadiusSqr ) 
650            fMaxRadiusSqr = fRadiusSqr;
651    }
652
653    Ogre::Vector3 kU, kV, kW = line_dir;
654        EigenSolver::GenerateOrthonormalBasis (kU, kV, kW, true);
655
656   Ogre::Real fMin = FLT_MAX, fMax = -fMin;
657    for (c = 0; c < vertex_count; c++)
658    {
659        const  Ogre::Vector3 kDiff (vertices[c] - line_orig);
660        const Ogre::Real fU = kU.dotProduct (kDiff);
661        const Ogre::Real fV = kV.dotProduct (kDiff);
662        const Ogre::Real fW = kW.dotProduct (kDiff);
663        const Ogre::Real fDiscr = fMaxRadiusSqr - (fU*fU + fV*fV);
664        const Ogre::Real fRadical = sqrtf(fabs(fDiscr));
665
666        fMin = std::min(fW + fRadical, fMin);
667        fMax = std::max(fW - fRadical, fMax);
668    }
669
670    if ( fMin < fMax )
671    {
672        cap_orig = line_orig + fMin*line_dir;
673        cap_dir = (fMax-fMin)*line_dir;
674    }
675    else
676    {
677        // enclosing capsule is really a sphere
678        cap_orig = line_orig + (((Real)0.5)*(fMin+fMax))*line_dir;
679        //----------------------------
680        cap_dir = Ogre::Vector3::ZERO;
681        //cap_dir = (fMax-fMin)*line_dir;
682    }
683
684    cap_rad = sqrtf(fMaxRadiusSqr);
685
686
687    CapsuleGeometry* geom = 0;
688    const Ogre::Real cap_dirLength = cap_dir.length();
689    if (cap_rad > 0 && cap_dirLength > 0)
690    {
691        const Ogre::Vector3 orig_axis (Vector3::UNIT_Z);
692        const Ogre::Vector3 reqd_axis (cap_dir.normalisedCopy());
693        const Ogre::Vector3 rot_axis (orig_axis.crossProduct(reqd_axis));
694        const Ogre::Real cos_ang = orig_axis.dotProduct(reqd_axis);
695       Ogre::Real ang = acos(cos_ang);
696        if (cos_ang < 0.0) 
697            ang -= M_PI;
698
699        const Ogre::Quaternion orient = Ogre::Quaternion(Radian(ang),rot_axis);
700
701        geom = new CapsuleGeometry(cap_rad, cap_dirLength, world, space);
702        geom->setOrientation(orient);
703        geom->setPosition(cap_orig + (reqd_axis * (cap_dirLength * 0.5)));
704    }
705        return geom;
706}
707//------------------------------------------------------------------------------------------------
708EntityInformer::~EntityInformer()
709{
710        delete[] _vertices;
711        delete[] _indices;
712
713        if (_bone_mapping)
714        {
715                for(BoneMapping::iterator i = _bone_mapping->begin();
716            i != _bone_mapping->end();
717            ++i)
718                {
719                        delete i->second;
720                }
721                delete _bone_mapping;
722        }
723}
724
725//------------------------------------------------------------------------------------------------
726EntityInformerReuse::EntityInformerReuse(Entity *entity, const Vector3 &scale, bool forceRecreate) : EntityInformer()
727{
728        _transform.makeTransform(Vector3::ZERO, scale, Quaternion::IDENTITY);
729       
730        if(!forceRecreate)
731                _dataPtr = TriangleMeshDataManager::getSingleton().getTriangleMeshData(entity->getMesh()->getName(), scale);
732
733        if(_dataPtr.isNull()) 
734        {
735                EntityInformer::addEntity(entity, _transform);
736               
737                _dataPtr = new TriangleMeshData(entity->getMesh()->getName(), scale, _vertices, _vertex_count, _indices, _index_count);
738                TriangleMeshDataManager::getSingleton().addTriangleMeshData(entity->getMesh()->getName(), _dataPtr, scale);
739        }
740}
741//------------------------------------------------------------------------------------------------
742EntityInformerReuse::EntityInformerReuse(const MeshPtr &mesh, const Vector3 &scale, bool forceRecreate) : EntityInformer()
743{
744        _entity = NULL;
745       
746        _transform.makeTransform(Vector3::ZERO, scale, Quaternion::IDENTITY);
747       
748        if(!forceRecreate)
749                _dataPtr = TriangleMeshDataManager::getSingleton().getTriangleMeshData(mesh->getName(), scale);
750       
751        if(_dataPtr.isNull()) 
752        {
753                EntityInformer::addMesh(mesh, _transform);
754               
755                _dataPtr = new TriangleMeshData(mesh->getName(), scale, _vertices, _vertex_count, _indices, _index_count);
756                TriangleMeshDataManager::getSingleton().addTriangleMeshData(mesh->getName(), _dataPtr, scale);
757        }
758}
759//------------------------------------------------------------------------------------------------
760EntityInformerReuse::~EntityInformerReuse()
761{
762}
763//------------------------------------------------------------------------------------------------
764TriangleMeshGeometry* EntityInformerReuse::createStaticTriangleMesh(World *world, Space* space)
765{
766        return new TriangleMeshGeometry(_dataPtr, world, space);
767}
768//------------------------------------------------------------------------------------------------
769TriangleMeshGeometry* EntityInformerReuse::recreateStaticTriangleMesh(TriangleMeshGeometry* geom)
770{
771        geom->changeTriangleMeshData(_dataPtr);
772        return geom;
773}
Note: See TracBrowser for help on using the repository browser.