Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/ogreode/src/OgreOdeEntityInformer.cpp @ 21

Last change on this file since 21 was 21, checked in by nicolasc, 16 years ago

added ogreode and Colladaplugin

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