Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/physics_new/src/ogreode/OgreOdeEntityInformer.cpp @ 2119

Last change on this file since 2119 was 2119, checked in by rgrieder, 15 years ago

Merged physics branch into physics_new branch.

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