mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-11-03 23:56:43 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			1094 lines
		
	
	
	
		
			38 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1094 lines
		
	
	
	
		
			38 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
 * =============================================================================================
 | 
						|
 *
 | 
						|
 *       Filename:  BtOgre.cpp
 | 
						|
 *
 | 
						|
 *    Description:  BtOgre implementation.
 | 
						|
 *
 | 
						|
 *        Version:  1.0
 | 
						|
 *        Created:  27/12/2008 01:47:56 PM
 | 
						|
 *
 | 
						|
 *         Author:  Nikhilesh (nikki)
 | 
						|
 *
 | 
						|
 * =============================================================================================
 | 
						|
 */
 | 
						|
 | 
						|
#include "BtOgrePG.h"
 | 
						|
#include "BtOgreGP.h"
 | 
						|
#include "BtOgreExtras.h"
 | 
						|
 | 
						|
#include <OgreEntity.h>
 | 
						|
#include <OgreSubMesh.h>
 | 
						|
#include <OgreSubEntity.h>
 | 
						|
 | 
						|
using namespace Ogre;
 | 
						|
 | 
						|
namespace BtOgre {
 | 
						|
 | 
						|
/*
 | 
						|
 * =============================================================================================
 | 
						|
 * BtOgre::VertexIndexToShape
 | 
						|
 * =============================================================================================
 | 
						|
 */
 | 
						|
 | 
						|
    void VertexIndexToShape::addStaticVertexData(const VertexData *vertex_data)
 | 
						|
    {
 | 
						|
        if (!vertex_data)
 | 
						|
            return;
 | 
						|
 | 
						|
        const VertexData *data = vertex_data;
 | 
						|
 | 
						|
        const unsigned int prev_size = mVertexCount;
 | 
						|
        mVertexCount += (unsigned int)data->vertexCount;
 | 
						|
 | 
						|
        Ogre::Vector3* tmp_vert = new Ogre::Vector3[mVertexCount];
 | 
						|
        if (mVertexBuffer)
 | 
						|
        {
 | 
						|
            memcpy(tmp_vert, mVertexBuffer, sizeof(Vector3) * prev_size);
 | 
						|
            delete[] mVertexBuffer;
 | 
						|
        }
 | 
						|
        mVertexBuffer = tmp_vert;
 | 
						|
 | 
						|
        // Get the positional buffer element
 | 
						|
        {
 | 
						|
            const Ogre::VertexElement* posElem = data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
 | 
						|
            Ogre::HardwareVertexBufferSharedPtr vbuf = data->vertexBufferBinding->getBuffer(posElem->getSource());
 | 
						|
            const unsigned int vSize = (unsigned int)vbuf->getVertexSize();
 | 
						|
 | 
						|
            unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
 | 
						|
            float* pReal;
 | 
						|
            Ogre::Vector3 * curVertices = &mVertexBuffer[prev_size];
 | 
						|
            const unsigned int vertexCount = (unsigned int)data->vertexCount;
 | 
						|
            for(unsigned int j = 0; j < vertexCount; ++j)
 | 
						|
            {
 | 
						|
                posElem->baseVertexPointerToElement(vertex, &pReal);
 | 
						|
                vertex += vSize;
 | 
						|
 | 
						|
                curVertices->x = (*pReal++);
 | 
						|
                curVertices->y = (*pReal++);
 | 
						|
                curVertices->z = (*pReal++);
 | 
						|
 | 
						|
                *curVertices = mTransform * (*curVertices);
 | 
						|
 | 
						|
                curVertices++;
 | 
						|
            }
 | 
						|
            vbuf->unlock();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    void VertexIndexToShape::addAnimatedVertexData(const Ogre::VertexData *vertex_data,
 | 
						|
                                                   const Ogre::VertexData *blend_data,
 | 
						|
                                                   const Ogre::Mesh::IndexMap *indexMap)
 | 
						|
    {
 | 
						|
        // Get the bone index element
 | 
						|
        assert(vertex_data);
 | 
						|
 | 
						|
        const VertexData *data = blend_data;
 | 
						|
        const unsigned int prev_size = mVertexCount;
 | 
						|
        mVertexCount += (unsigned int)data->vertexCount;
 | 
						|
        Ogre::Vector3* tmp_vert = new Ogre::Vector3[mVertexCount];
 | 
						|
        if (mVertexBuffer)
 | 
						|
        {
 | 
						|
            memcpy(tmp_vert, mVertexBuffer, sizeof(Vector3) * prev_size);
 | 
						|
            delete[] mVertexBuffer;
 | 
						|
        }
 | 
						|
        mVertexBuffer = tmp_vert;
 | 
						|
 | 
						|
        // Get the positional buffer element
 | 
						|
        {
 | 
						|
            const Ogre::VertexElement* posElem = data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
 | 
						|
            assert (posElem);
 | 
						|
            Ogre::HardwareVertexBufferSharedPtr vbuf = data->vertexBufferBinding->getBuffer(posElem->getSource());
 | 
						|
            const unsigned int vSize = (unsigned int)vbuf->getVertexSize();
 | 
						|
 | 
						|
            unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
 | 
						|
            float* pReal;
 | 
						|
            Ogre::Vector3 * curVertices = &mVertexBuffer[prev_size];
 | 
						|
            const unsigned int vertexCount = (unsigned int)data->vertexCount;
 | 
						|
            for(unsigned int j = 0; j < vertexCount; ++j)
 | 
						|
            {
 | 
						|
                posElem->baseVertexPointerToElement(vertex, &pReal);
 | 
						|
                vertex += vSize;
 | 
						|
 | 
						|
                curVertices->x = (*pReal++);
 | 
						|
                curVertices->y = (*pReal++);
 | 
						|
                curVertices->z = (*pReal++);
 | 
						|
 | 
						|
                *curVertices = mTransform * (*curVertices);
 | 
						|
 | 
						|
                curVertices++;
 | 
						|
            }
 | 
						|
            vbuf->unlock();
 | 
						|
        }
 | 
						|
 | 
						|
        {
 | 
						|
            const Ogre::VertexElement* bneElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_BLEND_INDICES);
 | 
						|
            assert (bneElem);
 | 
						|
 | 
						|
            Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(bneElem->getSource());
 | 
						|
            const unsigned int vSize = (unsigned int)vbuf->getVertexSize();
 | 
						|
            unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
 | 
						|
 | 
						|
            unsigned char* pBone;
 | 
						|
 | 
						|
            if (!mBoneIndex)
 | 
						|
                mBoneIndex = new BoneIndex();
 | 
						|
            BoneIndex::iterator i;
 | 
						|
 | 
						|
            Ogre::Vector3 * curVertices = &mVertexBuffer[prev_size];
 | 
						|
 | 
						|
            const unsigned int vertexCount = (unsigned int)vertex_data->vertexCount;
 | 
						|
            for(unsigned int j = 0; j < vertexCount; ++j)
 | 
						|
            {
 | 
						|
                bneElem->baseVertexPointerToElement(vertex, &pBone);
 | 
						|
                vertex += vSize;
 | 
						|
 | 
						|
                const unsigned char currBone = (indexMap) ? (*indexMap)[*pBone] : *pBone;
 | 
						|
                i = mBoneIndex->find (currBone);
 | 
						|
                Vector3Array* l = 0;
 | 
						|
                if (i == mBoneIndex->end())
 | 
						|
                {
 | 
						|
                    l = new Vector3Array;
 | 
						|
                    mBoneIndex->insert(BoneKeyIndex(currBone, l));
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    l = i->second;
 | 
						|
                }
 | 
						|
 | 
						|
                l->push_back(*curVertices);
 | 
						|
 | 
						|
                curVertices++;
 | 
						|
            }
 | 
						|
            vbuf->unlock();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    void VertexIndexToShape::addIndexData(IndexData *data, const unsigned int offset)
 | 
						|
    {
 | 
						|
        const unsigned int prev_size = mIndexCount;
 | 
						|
        mIndexCount += (unsigned int)data->indexCount;
 | 
						|
 | 
						|
        unsigned int* tmp_ind = new unsigned int[mIndexCount];
 | 
						|
        if (mIndexBuffer)
 | 
						|
        {
 | 
						|
            memcpy (tmp_ind, mIndexBuffer, sizeof(unsigned int) * prev_size);
 | 
						|
            delete[] mIndexBuffer;
 | 
						|
        }
 | 
						|
        mIndexBuffer = tmp_ind;
 | 
						|
 | 
						|
        const unsigned int numTris = (unsigned int) data->indexCount / 3;
 | 
						|
        HardwareIndexBufferSharedPtr ibuf = data->indexBuffer;
 | 
						|
        const bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT);
 | 
						|
        unsigned int index_offset = prev_size;
 | 
						|
 | 
						|
        if (use32bitindexes)
 | 
						|
        {
 | 
						|
            const unsigned int* pInt = static_cast<unsigned int*>(ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
 | 
						|
            for(unsigned int k = 0; k < numTris; ++k)
 | 
						|
            {
 | 
						|
                mIndexBuffer[index_offset ++] = offset + *pInt++;
 | 
						|
                mIndexBuffer[index_offset ++] = offset + *pInt++;
 | 
						|
                mIndexBuffer[index_offset ++] = offset + *pInt++;
 | 
						|
            }
 | 
						|
            ibuf->unlock();
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            const unsigned short* pShort = static_cast<unsigned short*>(ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
 | 
						|
            for(unsigned int k = 0; k < numTris; ++k)
 | 
						|
            {
 | 
						|
                mIndexBuffer[index_offset ++] = offset + static_cast<unsigned int> (*pShort++);
 | 
						|
                mIndexBuffer[index_offset ++] = offset + static_cast<unsigned int> (*pShort++);
 | 
						|
                mIndexBuffer[index_offset ++] = offset + static_cast<unsigned int> (*pShort++);
 | 
						|
            }
 | 
						|
            ibuf->unlock();
 | 
						|
        }
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    Real VertexIndexToShape::getRadius()
 | 
						|
    {
 | 
						|
        if (mBoundRadius == (-1))
 | 
						|
        {
 | 
						|
            getSize();
 | 
						|
            mBoundRadius = (std::max(mBounds.x,std::max(mBounds.y,mBounds.z)) * 0.5);
 | 
						|
        }
 | 
						|
        return mBoundRadius;
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    Vector3 VertexIndexToShape::getSize()
 | 
						|
    {
 | 
						|
        const unsigned int vCount = getVertexCount();
 | 
						|
        if (mBounds == Ogre::Vector3(-1,-1,-1) && vCount > 0)
 | 
						|
        {
 | 
						|
 | 
						|
            const Ogre::Vector3 * const v = getVertices();
 | 
						|
 | 
						|
            Ogre::Vector3 vmin(v[0]);
 | 
						|
            Ogre::Vector3 vmax(v[0]);
 | 
						|
 | 
						|
            for(unsigned int j = 1; j < vCount; j++)
 | 
						|
            {
 | 
						|
                vmin.x = std::min(vmin.x, v[j].x);
 | 
						|
                vmin.y = std::min(vmin.y, v[j].y);
 | 
						|
                vmin.z = std::min(vmin.z, v[j].z);
 | 
						|
 | 
						|
                vmax.x = std::max(vmax.x, v[j].x);
 | 
						|
                vmax.y = std::max(vmax.y, v[j].y);
 | 
						|
                vmax.z = std::max(vmax.z, v[j].z);
 | 
						|
            }
 | 
						|
 | 
						|
            mBounds.x = vmax.x - vmin.x;
 | 
						|
            mBounds.y = vmax.y - vmin.y;
 | 
						|
            mBounds.z = vmax.z - vmin.z;
 | 
						|
        }
 | 
						|
 | 
						|
        return mBounds;
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    const Ogre::Vector3* VertexIndexToShape::getVertices()
 | 
						|
    {
 | 
						|
        return mVertexBuffer;
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    unsigned int VertexIndexToShape::getVertexCount()
 | 
						|
    {
 | 
						|
        return mVertexCount;
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    const unsigned int* VertexIndexToShape::getIndices()
 | 
						|
    {
 | 
						|
        return mIndexBuffer;
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    unsigned int VertexIndexToShape::getIndexCount()
 | 
						|
    {
 | 
						|
        return mIndexCount;
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    btSphereShape* VertexIndexToShape::createSphere()
 | 
						|
    {
 | 
						|
        const Ogre::Real rad = getRadius();
 | 
						|
        assert((rad > 0.0) &&
 | 
						|
                ("Sphere radius must be greater than zero"));
 | 
						|
        btSphereShape* shape = new btSphereShape(rad);
 | 
						|
 | 
						|
        shape->setLocalScaling(Convert::toBullet(mScale));
 | 
						|
 | 
						|
        return shape;
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    btBoxShape* VertexIndexToShape::createBox()
 | 
						|
    {
 | 
						|
        const Ogre::Vector3 sz = getSize();
 | 
						|
 | 
						|
        assert((sz.x > 0.0) && (sz.y > 0.0) && (sz.y > 0.0) &&
 | 
						|
                ("Size of box must be greater than zero on all axes"));
 | 
						|
 | 
						|
        btBoxShape* shape = new btBoxShape(Convert::toBullet(sz * 0.5));
 | 
						|
 | 
						|
        shape->setLocalScaling(Convert::toBullet(mScale));
 | 
						|
 | 
						|
        return shape;
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    btCylinderShape* VertexIndexToShape::createCylinder()
 | 
						|
    {
 | 
						|
        const Ogre::Vector3 sz = getSize();
 | 
						|
 | 
						|
        assert((sz.x > 0.0) && (sz.y > 0.0) && (sz.y > 0.0) &&
 | 
						|
                ("Size of Cylinder must be greater than zero on all axes"));
 | 
						|
 | 
						|
        btCylinderShape* shape = new btCylinderShapeX(Convert::toBullet(sz * 0.5));
 | 
						|
 | 
						|
        shape->setLocalScaling(Convert::toBullet(mScale));
 | 
						|
 | 
						|
        return shape;
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    btConvexHullShape* VertexIndexToShape::createConvex()
 | 
						|
    {
 | 
						|
        assert(mVertexCount && (mIndexCount >= 6) &&
 | 
						|
                ("Mesh must have some vertices and at least 6 indices (2 triangles)"));
 | 
						|
 | 
						|
        return new btConvexHullShape((btScalar*) &mVertexBuffer[0].x, mVertexCount, sizeof(Vector3));
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    btBvhTriangleMeshShape* VertexIndexToShape::createTrimesh()
 | 
						|
    {
 | 
						|
        assert(mVertexCount && (mIndexCount >= 6) &&
 | 
						|
                ("Mesh must have some vertices and at least 6 indices (2 triangles)"));
 | 
						|
 | 
						|
        unsigned int numFaces = mIndexCount / 3;
 | 
						|
 | 
						|
        btTriangleMesh *trimesh = new btTriangleMesh();
 | 
						|
        unsigned int *indices = mIndexBuffer;
 | 
						|
        Vector3 *vertices = mVertexBuffer;
 | 
						|
 | 
						|
        btVector3    vertexPos[3];
 | 
						|
        for (unsigned int n = 0; n < numFaces; ++n)
 | 
						|
        {
 | 
						|
            {
 | 
						|
                const Vector3 &vec = vertices[*indices];
 | 
						|
                vertexPos[0][0] = vec.x;
 | 
						|
                vertexPos[0][1] = vec.y;
 | 
						|
                vertexPos[0][2] = vec.z;
 | 
						|
            }
 | 
						|
            {
 | 
						|
                const Vector3 &vec = vertices[*(indices + 1)];
 | 
						|
                vertexPos[1][0] = vec.x;
 | 
						|
                vertexPos[1][1] = vec.y;
 | 
						|
                vertexPos[1][2] = vec.z;
 | 
						|
            }
 | 
						|
            {
 | 
						|
                const Vector3 &vec = vertices[*(indices + 2)];
 | 
						|
                vertexPos[2][0] = vec.x;
 | 
						|
                vertexPos[2][1] = vec.y;
 | 
						|
                vertexPos[2][2] = vec.z;
 | 
						|
            }
 | 
						|
 | 
						|
            indices += 3;
 | 
						|
 | 
						|
            trimesh->addTriangle(vertexPos[0], vertexPos[1], vertexPos[2]);
 | 
						|
        }
 | 
						|
 | 
						|
        const bool useQuantizedAABB = true;
 | 
						|
        btBvhTriangleMeshShape *shape = new btBvhTriangleMeshShape(trimesh, useQuantizedAABB);
 | 
						|
 | 
						|
        shape->setLocalScaling(Convert::toBullet(mScale));
 | 
						|
 | 
						|
        return shape;
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    VertexIndexToShape::~VertexIndexToShape()
 | 
						|
    {
 | 
						|
        delete[] mVertexBuffer;
 | 
						|
        delete[] mIndexBuffer;
 | 
						|
 | 
						|
        if (mBoneIndex)
 | 
						|
        {
 | 
						|
            for(BoneIndex::iterator i = mBoneIndex->begin();
 | 
						|
                    i != mBoneIndex->end();
 | 
						|
                    ++i)
 | 
						|
            {
 | 
						|
                delete i->second;
 | 
						|
            }
 | 
						|
            delete mBoneIndex;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    VertexIndexToShape::VertexIndexToShape(const Matrix4 &transform) :
 | 
						|
        mVertexBuffer (0),
 | 
						|
        mIndexBuffer (0),
 | 
						|
        mVertexCount (0),
 | 
						|
        mIndexCount (0),
 | 
						|
        mTransform (transform),
 | 
						|
        mBoundRadius (-1),
 | 
						|
        mBounds (Vector3(-1,-1,-1)),
 | 
						|
        mBoneIndex (0),
 | 
						|
        mScale(1)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
/*
 | 
						|
 * =============================================================================================
 | 
						|
 * BtOgre::StaticMeshToShapeConverter
 | 
						|
 * =============================================================================================
 | 
						|
 */
 | 
						|
 | 
						|
    StaticMeshToShapeConverter::StaticMeshToShapeConverter() :
 | 
						|
        VertexIndexToShape(),
 | 
						|
        mEntity (0),
 | 
						|
        mNode (0)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    StaticMeshToShapeConverter::~StaticMeshToShapeConverter()
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    StaticMeshToShapeConverter::StaticMeshToShapeConverter(Entity *entity,  const Matrix4 &transform) :
 | 
						|
        VertexIndexToShape(transform),
 | 
						|
        mEntity (0),
 | 
						|
        mNode (0)
 | 
						|
    {
 | 
						|
        addEntity(entity, transform);
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    StaticMeshToShapeConverter::StaticMeshToShapeConverter(Renderable *rend, const Matrix4 &transform) :
 | 
						|
        VertexIndexToShape(transform),
 | 
						|
        mEntity (0),
 | 
						|
        mNode (0)
 | 
						|
    {
 | 
						|
        RenderOperation op;
 | 
						|
        rend->getRenderOperation(op);
 | 
						|
        VertexIndexToShape::addStaticVertexData(op.vertexData);
 | 
						|
        if(op.useIndexes)
 | 
						|
            VertexIndexToShape::addIndexData(op.indexData);
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    void StaticMeshToShapeConverter::addEntity(Entity *entity,const Matrix4 &transform)
 | 
						|
    {
 | 
						|
        // Each entity added need to reset size and radius
 | 
						|
        // next time getRadius and getSize are asked, they're computed.
 | 
						|
        mBounds  = Ogre::Vector3(-1,-1,-1);
 | 
						|
        mBoundRadius = -1;
 | 
						|
 | 
						|
        mEntity = entity;
 | 
						|
        mNode = (SceneNode*)(mEntity->getParentNode());
 | 
						|
        mTransform = transform;
 | 
						|
        mScale = mNode->getScale();
 | 
						|
 | 
						|
        if (mEntity->getMesh()->sharedVertexData)
 | 
						|
        {
 | 
						|
            VertexIndexToShape::addStaticVertexData (mEntity->getMesh()->sharedVertexData);
 | 
						|
        }
 | 
						|
 | 
						|
        for (unsigned int i = 0;i < mEntity->getNumSubEntities();++i)
 | 
						|
        {
 | 
						|
            SubMesh *sub_mesh = mEntity->getSubEntity(i)->getSubMesh();
 | 
						|
 | 
						|
            if (!sub_mesh->useSharedVertices)
 | 
						|
            {
 | 
						|
                VertexIndexToShape::addIndexData(sub_mesh->indexData, mVertexCount);
 | 
						|
                VertexIndexToShape::addStaticVertexData (sub_mesh->vertexData);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                VertexIndexToShape::addIndexData (sub_mesh->indexData);
 | 
						|
            }
 | 
						|
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    void StaticMeshToShapeConverter::addMesh(const MeshPtr &mesh, const Matrix4 &transform)
 | 
						|
    {
 | 
						|
        // Each entity added need to reset size and radius
 | 
						|
        // next time getRadius and getSize are asked, they're computed.
 | 
						|
        mBounds  = Ogre::Vector3(-1,-1,-1);
 | 
						|
        mBoundRadius = -1;
 | 
						|
 | 
						|
        //_entity = entity;
 | 
						|
        //_node = (SceneNode*)(_entity->getParentNode());
 | 
						|
        mTransform = transform;
 | 
						|
 | 
						|
        if (mesh->hasSkeleton ())
 | 
						|
            Ogre::LogManager::getSingleton().logMessage("MeshToShapeConverter::addMesh : Mesh " + mesh->getName () + " as skeleton but added to trimesh non animated");
 | 
						|
 | 
						|
        if (mesh->sharedVertexData)
 | 
						|
        {
 | 
						|
            VertexIndexToShape::addStaticVertexData (mesh->sharedVertexData);
 | 
						|
        }
 | 
						|
 | 
						|
        for(unsigned int i = 0;i < mesh->getNumSubMeshes();++i)
 | 
						|
        {
 | 
						|
            SubMesh *sub_mesh = mesh->getSubMesh(i);
 | 
						|
 | 
						|
            if (!sub_mesh->useSharedVertices)
 | 
						|
            {
 | 
						|
                VertexIndexToShape::addIndexData(sub_mesh->indexData, mVertexCount);
 | 
						|
                VertexIndexToShape::addStaticVertexData (sub_mesh->vertexData);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                VertexIndexToShape::addIndexData (sub_mesh->indexData);
 | 
						|
            }
 | 
						|
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
/*
 | 
						|
 * =============================================================================================
 | 
						|
 * BtOgre::AnimatedMeshToShapeConverter
 | 
						|
 * =============================================================================================
 | 
						|
 */
 | 
						|
 | 
						|
    AnimatedMeshToShapeConverter::AnimatedMeshToShapeConverter(Entity *entity,const Matrix4 &transform) :
 | 
						|
        VertexIndexToShape(transform),
 | 
						|
        mEntity (0),
 | 
						|
        mNode (0),
 | 
						|
        mTransformedVerticesTemp(0),
 | 
						|
        mTransformedVerticesTempSize(0)
 | 
						|
    {
 | 
						|
        addEntity(entity, transform);
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    AnimatedMeshToShapeConverter::AnimatedMeshToShapeConverter() :
 | 
						|
        VertexIndexToShape(),
 | 
						|
        mEntity (0),
 | 
						|
        mNode (0),
 | 
						|
        mTransformedVerticesTemp(0),
 | 
						|
        mTransformedVerticesTempSize(0)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    AnimatedMeshToShapeConverter::~AnimatedMeshToShapeConverter()
 | 
						|
    {
 | 
						|
        delete[] mTransformedVerticesTemp;
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    void AnimatedMeshToShapeConverter::addEntity(Entity *entity,const Matrix4 &transform)
 | 
						|
    {
 | 
						|
        // Each entity added need to reset size and radius
 | 
						|
        // next time getRadius and getSize are asked, they're computed.
 | 
						|
        mBounds  = Ogre::Vector3(-1,-1,-1);
 | 
						|
        mBoundRadius = -1;
 | 
						|
 | 
						|
        mEntity = entity;
 | 
						|
        mNode = (SceneNode*)(mEntity->getParentNode());
 | 
						|
        mTransform = transform;
 | 
						|
 | 
						|
        assert (entity->getMesh()->hasSkeleton ());
 | 
						|
 | 
						|
        mEntity->addSoftwareAnimationRequest(false);
 | 
						|
        mEntity->_updateAnimation();
 | 
						|
 | 
						|
        if (mEntity->getMesh()->sharedVertexData)
 | 
						|
        {
 | 
						|
            VertexIndexToShape::addAnimatedVertexData (mEntity->getMesh()->sharedVertexData,
 | 
						|
                    mEntity->_getSkelAnimVertexData(),
 | 
						|
                    &mEntity->getMesh()->sharedBlendIndexToBoneIndexMap);
 | 
						|
        }
 | 
						|
 | 
						|
        for (unsigned int i = 0;i < mEntity->getNumSubEntities();++i)
 | 
						|
        {
 | 
						|
            SubMesh *sub_mesh = mEntity->getSubEntity(i)->getSubMesh();
 | 
						|
 | 
						|
            if (!sub_mesh->useSharedVertices)
 | 
						|
            {
 | 
						|
                VertexIndexToShape::addIndexData(sub_mesh->indexData, mVertexCount);
 | 
						|
 | 
						|
                VertexIndexToShape::addAnimatedVertexData (sub_mesh->vertexData,
 | 
						|
                        mEntity->getSubEntity(i)->_getSkelAnimVertexData(),
 | 
						|
                        &sub_mesh->blendIndexToBoneIndexMap);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                VertexIndexToShape::addIndexData (sub_mesh->indexData);
 | 
						|
            }
 | 
						|
 | 
						|
        }
 | 
						|
 | 
						|
        mEntity->removeSoftwareAnimationRequest(false);
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    void AnimatedMeshToShapeConverter::addMesh(const MeshPtr &mesh, const Matrix4 &transform)
 | 
						|
    {
 | 
						|
        // Each entity added need to reset size and radius
 | 
						|
        // next time getRadius and getSize are asked, they're computed.
 | 
						|
        mBounds  = Ogre::Vector3(-1,-1,-1);
 | 
						|
        mBoundRadius = -1;
 | 
						|
 | 
						|
        //_entity = entity;
 | 
						|
        //_node = (SceneNode*)(_entity->getParentNode());
 | 
						|
        mTransform = transform;
 | 
						|
 | 
						|
        assert (mesh->hasSkeleton ());
 | 
						|
 | 
						|
        if (mesh->sharedVertexData)
 | 
						|
        {
 | 
						|
            VertexIndexToShape::addAnimatedVertexData (mesh->sharedVertexData,
 | 
						|
                    0,
 | 
						|
                    &mesh->sharedBlendIndexToBoneIndexMap);
 | 
						|
        }
 | 
						|
 | 
						|
        for(unsigned int i = 0;i < mesh->getNumSubMeshes();++i)
 | 
						|
        {
 | 
						|
            SubMesh *sub_mesh = mesh->getSubMesh(i);
 | 
						|
 | 
						|
            if (!sub_mesh->useSharedVertices)
 | 
						|
            {
 | 
						|
                VertexIndexToShape::addIndexData(sub_mesh->indexData, mVertexCount);
 | 
						|
 | 
						|
                VertexIndexToShape::addAnimatedVertexData (sub_mesh->vertexData,
 | 
						|
                        0,
 | 
						|
                        &sub_mesh->blendIndexToBoneIndexMap);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                VertexIndexToShape::addIndexData (sub_mesh->indexData);
 | 
						|
            }
 | 
						|
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    bool AnimatedMeshToShapeConverter::getBoneVertices(unsigned char bone,
 | 
						|
                                                       unsigned int &vertex_count,
 | 
						|
                                                       Ogre::Vector3* &vertices,
 | 
						|
                                                       const Vector3 &bonePosition)
 | 
						|
    {
 | 
						|
        BoneIndex::iterator i = mBoneIndex->find(bone);
 | 
						|
 | 
						|
        if (i == mBoneIndex->end())
 | 
						|
            return false;
 | 
						|
 | 
						|
        if (i->second->empty())
 | 
						|
            return false;
 | 
						|
 | 
						|
        vertex_count = (unsigned int) i->second->size() + 1;
 | 
						|
        if (vertex_count > mTransformedVerticesTempSize)
 | 
						|
        {
 | 
						|
            if (mTransformedVerticesTemp)
 | 
						|
                delete[] mTransformedVerticesTemp;
 | 
						|
 | 
						|
            mTransformedVerticesTemp = new Ogre::Vector3[vertex_count];
 | 
						|
 | 
						|
        }
 | 
						|
 | 
						|
        vertices = mTransformedVerticesTemp;
 | 
						|
        vertices[0] = bonePosition;
 | 
						|
        //mEntity->_getParentNodeFullTransform() *
 | 
						|
        //mEntity->getSkeleton()->getBone(bone)->_getDerivedPosition();
 | 
						|
 | 
						|
        //mEntity->getSkeleton()->getBone(bone)->_getDerivedOrientation()
 | 
						|
        unsigned int currBoneVertex = 1;
 | 
						|
        Vector3Array::iterator j = i->second->begin();
 | 
						|
        while(j != i->second->end())
 | 
						|
        {
 | 
						|
            vertices[currBoneVertex] = (*j);
 | 
						|
            ++j;
 | 
						|
            ++currBoneVertex;
 | 
						|
        }
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    btBoxShape* AnimatedMeshToShapeConverter::createAlignedBox(unsigned char bone,
 | 
						|
                                                               const Vector3 &bonePosition,
 | 
						|
                                                               const Quaternion &boneOrientation)
 | 
						|
    {
 | 
						|
        unsigned int vertex_count;
 | 
						|
        Vector3* vertices;
 | 
						|
 | 
						|
        if (!getBoneVertices(bone, vertex_count, vertices, bonePosition))
 | 
						|
            return 0;
 | 
						|
 | 
						|
        Vector3 min_vec(vertices[0]);
 | 
						|
        Vector3 max_vec(vertices[0]);
 | 
						|
 | 
						|
        for(unsigned int j = 1; j < vertex_count ;j++)
 | 
						|
        {
 | 
						|
            min_vec.x = std::min(min_vec.x,vertices[j].x);
 | 
						|
            min_vec.y = std::min(min_vec.y,vertices[j].y);
 | 
						|
            min_vec.z = std::min(min_vec.z,vertices[j].z);
 | 
						|
 | 
						|
            max_vec.x = std::max(max_vec.x,vertices[j].x);
 | 
						|
            max_vec.y = std::max(max_vec.y,vertices[j].y);
 | 
						|
            max_vec.z = std::max(max_vec.z,vertices[j].z);
 | 
						|
        }
 | 
						|
        const Ogre::Vector3 maxMinusMin(max_vec - min_vec);
 | 
						|
        btBoxShape* box = new btBoxShape(Convert::toBullet(maxMinusMin));
 | 
						|
 | 
						|
        /*const Ogre::Vector3 pos
 | 
						|
          (min_vec.x + (maxMinusMin.x * 0.5),
 | 
						|
          min_vec.y + (maxMinusMin.y * 0.5),
 | 
						|
          min_vec.z + (maxMinusMin.z * 0.5));*/
 | 
						|
 | 
						|
        //box->setPosition(pos);
 | 
						|
 | 
						|
        return box;
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    bool AnimatedMeshToShapeConverter::getOrientedBox(unsigned char bone,
 | 
						|
                                                      const Vector3 &bonePosition,
 | 
						|
                                                      const Quaternion &boneOrientation,
 | 
						|
                                                      Vector3 &box_afExtent,
 | 
						|
                                                      Vector3 *box_akAxis,
 | 
						|
                                                      Vector3 &box_kCenter)
 | 
						|
    {
 | 
						|
        unsigned int vertex_count;
 | 
						|
        Vector3* vertices;
 | 
						|
 | 
						|
        if (!getBoneVertices(bone, vertex_count, vertices, bonePosition))
 | 
						|
            return false;
 | 
						|
 | 
						|
        box_kCenter = Vector3::ZERO;
 | 
						|
 | 
						|
        {
 | 
						|
            for(unsigned int c = 0 ;c < vertex_count;c++)
 | 
						|
            {
 | 
						|
                box_kCenter += vertices[c];
 | 
						|
            }
 | 
						|
            const Ogre::Real invVertexCount = 1.0 / vertex_count;
 | 
						|
            box_kCenter *= invVertexCount;
 | 
						|
        }
 | 
						|
        Quaternion orient = boneOrientation;
 | 
						|
        orient.ToAxes(box_akAxis);
 | 
						|
 | 
						|
        // Let C be the box center and let U0, U1, and U2 be the box axes.  Each
 | 
						|
        // input point is of the form X = C + y0*U0 + y1*U1 + y2*U2.  The
 | 
						|
        // following code computes min(y0), max(y0), min(y1), max(y1), min(y2),
 | 
						|
        // and max(y2).  The box center is then adjusted to be
 | 
						|
        //   C' = C + 0.5*(min(y0)+max(y0))*U0 + 0.5*(min(y1)+max(y1))*U1 +
 | 
						|
        //        0.5*(min(y2)+max(y2))*U2
 | 
						|
 | 
						|
        Ogre::Vector3 kDiff (vertices[1] - box_kCenter);
 | 
						|
        Ogre::Real fY0Min = kDiff.dotProduct(box_akAxis[0]), fY0Max = fY0Min;
 | 
						|
        Ogre::Real fY1Min = kDiff.dotProduct(box_akAxis[1]), fY1Max = fY1Min;
 | 
						|
        Ogre::Real fY2Min = kDiff.dotProduct(box_akAxis[2]), fY2Max = fY2Min;
 | 
						|
 | 
						|
        for (unsigned int i = 2; i < vertex_count; i++)
 | 
						|
        {
 | 
						|
            kDiff = vertices[i] - box_kCenter;
 | 
						|
 | 
						|
            const Ogre::Real fY0 = kDiff.dotProduct(box_akAxis[0]);
 | 
						|
            if ( fY0 < fY0Min )
 | 
						|
                fY0Min = fY0;
 | 
						|
            else if ( fY0 > fY0Max )
 | 
						|
                fY0Max = fY0;
 | 
						|
 | 
						|
            const Ogre::Real fY1 = kDiff.dotProduct(box_akAxis[1]);
 | 
						|
            if ( fY1 < fY1Min )
 | 
						|
                fY1Min = fY1;
 | 
						|
            else if ( fY1 > fY1Max )
 | 
						|
                fY1Max = fY1;
 | 
						|
 | 
						|
            const Ogre::Real fY2 = kDiff.dotProduct(box_akAxis[2]);
 | 
						|
            if ( fY2 < fY2Min )
 | 
						|
                fY2Min = fY2;
 | 
						|
            else if ( fY2 > fY2Max )
 | 
						|
                fY2Max = fY2;
 | 
						|
        }
 | 
						|
 | 
						|
        box_afExtent.x = ((Real)0.5)*(fY0Max - fY0Min);
 | 
						|
        box_afExtent.y = ((Real)0.5)*(fY1Max - fY1Min);
 | 
						|
        box_afExtent.z = ((Real)0.5)*(fY2Max - fY2Min);
 | 
						|
 | 
						|
        box_kCenter += (0.5*(fY0Max+fY0Min))*box_akAxis[0] +
 | 
						|
            (0.5*(fY1Max+fY1Min))*box_akAxis[1] +
 | 
						|
            (0.5*(fY2Max+fY2Min))*box_akAxis[2];
 | 
						|
 | 
						|
        box_afExtent *= 2.0;
 | 
						|
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    btBoxShape *AnimatedMeshToShapeConverter::createOrientedBox(unsigned char bone,
 | 
						|
                                                                const Vector3 &bonePosition,
 | 
						|
                                                                const Quaternion &boneOrientation)
 | 
						|
    {
 | 
						|
        Ogre::Vector3 box_akAxis[3];
 | 
						|
        Ogre::Vector3 box_afExtent;
 | 
						|
        Ogre::Vector3 box_afCenter;
 | 
						|
 | 
						|
        if (!getOrientedBox(bone, bonePosition, boneOrientation,
 | 
						|
                    box_afExtent,
 | 
						|
                    box_akAxis,
 | 
						|
                    box_afCenter))
 | 
						|
            return 0;
 | 
						|
 | 
						|
        btBoxShape *geom = new btBoxShape(Convert::toBullet(box_afExtent));
 | 
						|
        //geom->setOrientation(Quaternion(box_akAxis[0],box_akAxis[1],box_akAxis[2]));
 | 
						|
        //geom->setPosition(box_afCenter);
 | 
						|
        return geom;
 | 
						|
    }
 | 
						|
 | 
						|
/*
 | 
						|
 * =============================================================================================
 | 
						|
 * BtOgre::DynamicRenderable
 | 
						|
 * =============================================================================================
 | 
						|
 */
 | 
						|
 | 
						|
    DynamicRenderable::DynamicRenderable()
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    DynamicRenderable::~DynamicRenderable()
 | 
						|
    {
 | 
						|
        delete mRenderOp.vertexData;
 | 
						|
        delete mRenderOp.indexData;
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    void DynamicRenderable::initialize(RenderOperation::OperationType operationType,
 | 
						|
                                       bool useIndices)
 | 
						|
    {
 | 
						|
        // Initialize render operation
 | 
						|
        mRenderOp.operationType = operationType;
 | 
						|
        mRenderOp.useIndexes = useIndices;
 | 
						|
        mRenderOp.vertexData = new VertexData;
 | 
						|
        if (mRenderOp.useIndexes)
 | 
						|
            mRenderOp.indexData = new IndexData;
 | 
						|
 | 
						|
        // Reset buffer capacities
 | 
						|
        mVertexBufferCapacity = 0;
 | 
						|
        mIndexBufferCapacity = 0;
 | 
						|
 | 
						|
        // Create vertex declaration
 | 
						|
        createVertexDeclaration();
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    void DynamicRenderable::prepareHardwareBuffers(size_t vertexCount,
 | 
						|
                                                   size_t indexCount)
 | 
						|
    {
 | 
						|
        // Prepare vertex buffer
 | 
						|
        size_t newVertCapacity = mVertexBufferCapacity;
 | 
						|
        if ((vertexCount > mVertexBufferCapacity) ||
 | 
						|
                (!mVertexBufferCapacity))
 | 
						|
        {
 | 
						|
            // vertexCount exceeds current capacity!
 | 
						|
            // It is necessary to reallocate the buffer.
 | 
						|
 | 
						|
            // Check if this is the first call
 | 
						|
            if (!newVertCapacity)
 | 
						|
                newVertCapacity = 1;
 | 
						|
 | 
						|
            // Make capacity the next power of two
 | 
						|
            while (newVertCapacity < vertexCount)
 | 
						|
                newVertCapacity <<= 1;
 | 
						|
        }
 | 
						|
        else if (vertexCount < mVertexBufferCapacity>>1) {
 | 
						|
            // Make capacity the previous power of two
 | 
						|
            while (vertexCount < newVertCapacity>>1)
 | 
						|
                newVertCapacity >>= 1;
 | 
						|
        }
 | 
						|
        if (newVertCapacity != mVertexBufferCapacity)
 | 
						|
        {
 | 
						|
            mVertexBufferCapacity = newVertCapacity;
 | 
						|
            // Create new vertex buffer
 | 
						|
            HardwareVertexBufferSharedPtr vbuf =
 | 
						|
                HardwareBufferManager::getSingleton().createVertexBuffer(
 | 
						|
                        mRenderOp.vertexData->vertexDeclaration->getVertexSize(0),
 | 
						|
                        mVertexBufferCapacity,
 | 
						|
                        HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); // TODO: Custom HBU_?
 | 
						|
 | 
						|
            // Bind buffer
 | 
						|
            mRenderOp.vertexData->vertexBufferBinding->setBinding(0, vbuf);
 | 
						|
        }
 | 
						|
        // Update vertex count in the render operation
 | 
						|
        mRenderOp.vertexData->vertexCount = vertexCount;
 | 
						|
 | 
						|
        if (mRenderOp.useIndexes)
 | 
						|
        {
 | 
						|
            OgreAssert(indexCount <= std::numeric_limits<unsigned short>::max(), "indexCount exceeds 16 bit");
 | 
						|
 | 
						|
            size_t newIndexCapacity = mIndexBufferCapacity;
 | 
						|
            // Prepare index buffer
 | 
						|
            if ((indexCount > newIndexCapacity) ||
 | 
						|
                    (!newIndexCapacity))
 | 
						|
            {
 | 
						|
                // indexCount exceeds current capacity!
 | 
						|
                // It is necessary to reallocate the buffer.
 | 
						|
 | 
						|
                // Check if this is the first call
 | 
						|
                if (!newIndexCapacity)
 | 
						|
                    newIndexCapacity = 1;
 | 
						|
 | 
						|
                // Make capacity the next power of two
 | 
						|
                while (newIndexCapacity < indexCount)
 | 
						|
                    newIndexCapacity <<= 1;
 | 
						|
 | 
						|
            }
 | 
						|
            else if (indexCount < newIndexCapacity>>1)
 | 
						|
            {
 | 
						|
                // Make capacity the previous power of two
 | 
						|
                while (indexCount < newIndexCapacity>>1)
 | 
						|
                    newIndexCapacity >>= 1;
 | 
						|
            }
 | 
						|
 | 
						|
            if (newIndexCapacity != mIndexBufferCapacity)
 | 
						|
            {
 | 
						|
                mIndexBufferCapacity = newIndexCapacity;
 | 
						|
                // Create new index buffer
 | 
						|
                mRenderOp.indexData->indexBuffer =
 | 
						|
                    HardwareBufferManager::getSingleton().createIndexBuffer(
 | 
						|
                            HardwareIndexBuffer::IT_16BIT,
 | 
						|
                            mIndexBufferCapacity,
 | 
						|
                            HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); // TODO: Custom HBU_?
 | 
						|
            }
 | 
						|
 | 
						|
            // Update index count in the render operation
 | 
						|
            mRenderOp.indexData->indexCount = indexCount;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    Real DynamicRenderable::getBoundingRadius(void) const
 | 
						|
    {
 | 
						|
        return Math::Sqrt(std::max(mBox.getMaximum().squaredLength(), mBox.getMinimum().squaredLength()));
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    Real DynamicRenderable::getSquaredViewDepth(const Camera* cam) const
 | 
						|
    {
 | 
						|
        Vector3 vMin, vMax, vMid, vDist;
 | 
						|
        vMin = mBox.getMinimum();
 | 
						|
        vMax = mBox.getMaximum();
 | 
						|
        vMid = ((vMax - vMin) * 0.5) + vMin;
 | 
						|
        vDist = cam->getDerivedPosition() - vMid;
 | 
						|
 | 
						|
        return vDist.squaredLength();
 | 
						|
    }
 | 
						|
 | 
						|
/*
 | 
						|
 * =============================================================================================
 | 
						|
 * BtOgre::DynamicLines
 | 
						|
 * =============================================================================================
 | 
						|
 */
 | 
						|
 | 
						|
    enum {
 | 
						|
        POSITION_BINDING,
 | 
						|
        TEXCOORD_BINDING
 | 
						|
    };
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    DynamicLines::DynamicLines(OperationType opType)
 | 
						|
    {
 | 
						|
        initialize(opType,false);
 | 
						|
        setMaterial("BaseWhiteNoLighting");
 | 
						|
        mDirty = true;
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    DynamicLines::~DynamicLines()
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    void DynamicLines::setOperationType(OperationType opType)
 | 
						|
    {
 | 
						|
        mRenderOp.operationType = opType;
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    RenderOperation::OperationType DynamicLines::getOperationType() const
 | 
						|
    {
 | 
						|
        return mRenderOp.operationType;
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    void DynamicLines::addPoint(const Vector3 &p)
 | 
						|
    {
 | 
						|
        mPoints.push_back(p);
 | 
						|
        mDirty = true;
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    void DynamicLines::addPoint(Real x, Real y, Real z)
 | 
						|
    {
 | 
						|
        mPoints.push_back(Vector3(x,y,z));
 | 
						|
        mDirty = true;
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    const Vector3& DynamicLines::getPoint(unsigned short index) const
 | 
						|
    {
 | 
						|
        assert(index < mPoints.size() && "Point index is out of bounds!!");
 | 
						|
        return mPoints[index];
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    unsigned short DynamicLines::getNumPoints(void) const
 | 
						|
    {
 | 
						|
        return (unsigned short)mPoints.size();
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    void DynamicLines::setPoint(unsigned short index, const Vector3 &value)
 | 
						|
    {
 | 
						|
        assert(index < mPoints.size() && "Point index is out of bounds!!");
 | 
						|
 | 
						|
        mPoints[index] = value;
 | 
						|
        mDirty = true;
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    void DynamicLines::clear()
 | 
						|
    {
 | 
						|
        mPoints.clear();
 | 
						|
        mDirty = true;
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    void DynamicLines::update()
 | 
						|
    {
 | 
						|
        if (mDirty) fillHardwareBuffers();
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    void DynamicLines::createVertexDeclaration()
 | 
						|
    {
 | 
						|
        VertexDeclaration *decl = mRenderOp.vertexData->vertexDeclaration;
 | 
						|
        decl->addElement(POSITION_BINDING, 0, VET_FLOAT3, VES_POSITION);
 | 
						|
    }
 | 
						|
 | 
						|
    //------------------------------------------------------------------------------------------------
 | 
						|
    void DynamicLines::fillHardwareBuffers()
 | 
						|
    {
 | 
						|
        int size = mPoints.size();
 | 
						|
 | 
						|
        prepareHardwareBuffers(size,0);
 | 
						|
 | 
						|
        if (!size) {
 | 
						|
            mBox.setExtents(Vector3::ZERO,Vector3::ZERO);
 | 
						|
            mDirty=false;
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        Vector3 vaabMin = mPoints[0];
 | 
						|
        Vector3 vaabMax = mPoints[0];
 | 
						|
 | 
						|
        HardwareVertexBufferSharedPtr vbuf =
 | 
						|
            mRenderOp.vertexData->vertexBufferBinding->getBuffer(0);
 | 
						|
 | 
						|
        Real *prPos = static_cast<Real*>(vbuf->lock(HardwareBuffer::HBL_DISCARD));
 | 
						|
        {
 | 
						|
            for(int i = 0; i < size; i++)
 | 
						|
            {
 | 
						|
                *prPos++ = mPoints[i].x;
 | 
						|
                *prPos++ = mPoints[i].y;
 | 
						|
                *prPos++ = mPoints[i].z;
 | 
						|
 | 
						|
                if(mPoints[i].x < vaabMin.x)
 | 
						|
                    vaabMin.x = mPoints[i].x;
 | 
						|
                if(mPoints[i].y < vaabMin.y)
 | 
						|
                    vaabMin.y = mPoints[i].y;
 | 
						|
                if(mPoints[i].z < vaabMin.z)
 | 
						|
                    vaabMin.z = mPoints[i].z;
 | 
						|
 | 
						|
                if(mPoints[i].x > vaabMax.x)
 | 
						|
                    vaabMax.x = mPoints[i].x;
 | 
						|
                if(mPoints[i].y > vaabMax.y)
 | 
						|
                    vaabMax.y = mPoints[i].y;
 | 
						|
                if(mPoints[i].z > vaabMax.z)
 | 
						|
                    vaabMax.z = mPoints[i].z;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        vbuf->unlock();
 | 
						|
 | 
						|
        mBox.setExtents(vaabMin, vaabMax);
 | 
						|
 | 
						|
        mDirty = false;
 | 
						|
    }
 | 
						|
}
 |