Source

ogre-npr / ogre-npr / MeshData.cpp

Full commit
#include "precompiled.h"
#include "MeshData.hpp"


//-----------------------------------------------------------------------------
MeshData::MeshData(Ogre::MeshPtr _mesh
                   , const Ogre::Vector3 &_pos
                   , const Ogre::Quaternion &_orient
                   , const Ogre::Vector3 &_scale)
    :mMesh(_mesh)
    ,mPosition(_pos)
    ,mScale(_scale)
    ,mRotation(_orient)
{
    _getMeshInformation();
}
//-----------------------------------------------------------------------------
MeshData::~MeshData(){}
//-----------------------------------------------------------------------------
void MeshData::_getMeshInformation()
{
    added_shared = false;
    current_offset = 0;
    shared_offset = 0;
    next_offset = 0;
    index_offset = 0;

    _initBuffers();


    // Run through the submeshes again, adding the data into the arrays
    for ( unsigned short i = 0; i < mMesh->getNumSubMeshes(); ++i)
    {

        _extractVertexData(mMesh->getSubMesh(i));
        _extractIndexBuffer(mMesh->getSubMesh(i));
    }
} 
//-----------------------------------------------------------------------------
void MeshData::_extractBufferSizes()
{
    // Calculate how many vertices and indices we're going to need
    for (unsigned short i = 0; i < mMesh->getNumSubMeshes(); ++i)
    {
        Ogre::SubMesh* submesh = mMesh->getSubMesh( i );

        // We only need to add the shared vertices once
        if(submesh->useSharedVertices)
        {
            if( !added_shared )
            {
                mVertexCount += mMesh->sharedVertexData->vertexCount;
                added_shared = true;
            }
        }
        else
        {
            mVertexCount += submesh->vertexData->vertexCount;
        }

        mIndexCount += submesh->indexData->indexCount;
    }
}
//-----------------------------------------------------------------------------
void MeshData::_initBuffers()
{
    mVertexCount = 0;
    mIndexCount = 0;

    _extractBufferSizes();

    mVertices.resize(mVertexCount);
    mNormals.resize(mVertexCount);
    mIndices.resize(mIndexCount);
}
//-----------------------------------------------------------------------------
void MeshData::_extractVertexData(Ogre::SubMesh* submesh)
{
    Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mMesh->sharedVertexData : submesh->vertexData;

    if((!submesh->useSharedVertices)||(submesh->useSharedVertices && !added_shared))
    {
        if(submesh->useSharedVertices)
        {
            added_shared = true;
            shared_offset = current_offset;
        }
        _extractPositions(vertex_data);
        _extractNormals(vertex_data);
        next_offset += vertex_data->vertexCount;

    }
}
//-----------------------------------------------------------------------------
void MeshData::_extractPositions(Ogre::VertexData *_vertexdata)
{
    const Ogre::VertexElement* posElem =
        _vertexdata->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);

    Ogre::HardwareVertexBufferSharedPtr vbuf =
        _vertexdata->vertexBufferBinding->getBuffer(posElem->getSource());

    unsigned char* vertex =
        static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));

    // There is _no_ baseVertexPointerToElement() which takes an Ogre::Real or a double
    //  as second argument. So make it float, to avoid trouble when Ogre::Real will
    //  be comiled/typedefed as double:
    //      Ogre::Real* pReal;
    float* pReal;

    for( size_t j = 0; j < _vertexdata->vertexCount; ++j, vertex += vbuf->getVertexSize())
    {
        posElem->baseVertexPointerToElement(vertex, &pReal);

        Ogre::Vector3 pt(pReal[0], pReal[1], pReal[2]);

        mVertices[current_offset + j] = (mRotation * (pt * mScale)) + mPosition;
    }
    vbuf->unlock();
}
//-----------------------------------------------------------------------------
void MeshData::_extractNormals(Ogre::VertexData *_vertexdata)
{
    const Ogre::VertexElement* normalElem =
        _vertexdata->vertexDeclaration->findElementBySemantic(Ogre::VES_NORMAL);

    Ogre::HardwareVertexBufferSharedPtr vbuf =
        _vertexdata->vertexBufferBinding->getBuffer(normalElem->getSource());

    unsigned char* normal =
        static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));

    float* pReal;
    for( size_t j = 0; j < _vertexdata->vertexCount; ++j, normal += vbuf->getVertexSize())
    {
        normalElem->baseVertexPointerToElement(normal, &pReal);
        Ogre::Vector3 normal(pReal[0], pReal[1], pReal[2]);
        mNormals[current_offset + j] = (mRotation * (normal));
    }
    vbuf->unlock();

}
//-----------------------------------------------------------------------------
void MeshData::_extractIndexBuffer(Ogre::SubMesh *_submesh)
{
    Ogre::IndexData* index_data = _submesh->indexData;
    size_t numTris = index_data->indexCount / 3;
    Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;

    bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);

    unsigned long*  pLong = static_cast<unsigned long*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
    unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong);


    size_t offset = (_submesh->useSharedVertices)? shared_offset : current_offset;

    // Ogre 1.6 patch (commenting the static_cast...) - index offsets start from 0 for each submesh
    if ( use32bitindexes )
    {
        for ( size_t k = 0; k < numTris*3; ++k)
        {
            mIndices[index_offset++] = pLong[k] /*+ static_cast<unsigned long>(offset)*/;
        }
    }
    else
    {
        for ( size_t k = 0; k < numTris*3; ++k)
        {
            mIndices[index_offset++] = static_cast<unsigned long>(pShort[k]) /*+
                                                                             static_cast<unsigned long>(offset)*/;
        }
    }

    ibuf->unlock();
    current_offset = next_offset;

}