Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Cleaned up the heavy mess with header file includes in OgreOde. It should now compile a lot faster.

  • 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.