Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Added OgreODE to our source repository because already we really need the newest version. And there is no hope to find any packages under linux.
The files included should compile and link with Ogre 1.4/1.6 and ODE 0.9/0.10. I was only able to test Ogre 1.4 and ODE 0.9/.10 under msvc until now.

  • 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        _vertices (0),
265        _indices (0),
266        _vertex_count (0),
267        _index_count (0),
268        _size (Vector3(-1,-1,-1)),
269        _center (Vector3(-1,-1,-1)),
270        _radius (-1),
271        _bone_mapping (0)
272{
273        addEntity(entity, transform);   
274}
275//------------------------------------------------------------------------------------------------
276EntityInformer::EntityInformer() :
277                _vertices (0),
278                _indices (0),
279                _vertex_count (0),
280                _index_count (0),
281                _size (Vector3(-1,-1,-1)),
282                _center (Vector3(-1,-1,-1)),
283                _radius (-1),
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.