ogre实现加入物理效果terrain

view plaincopy to clipboardprint?
//------------------------------------------------------------------------------------------------  
void TriangleMeshData::addVertexData(const VertexData *vertex_data,  
                                   const VertexData *blended_data,  
                                   const Mesh::IndexMap *indexMap)  
{  
    if (!vertex_data)   
        return;  
 
    const VertexData *data = (blended_data) ? blended_data: vertex_data;  
 
    const unsigned int prev_size = _vertex_count;  
    _vertex_count += (unsigned int)data->vertexCount;  
 
    Ogre::Vector3* tmp_vert = new Ogre::Vector3[_vertex_count];  
    if (_vertices)  
    {  
        memcpy(tmp_vert,_vertices,sizeof(Vector3) * prev_size);  
        delete[] _vertices;  
    }  
    _vertices = 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 = &_vertices[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 = _transform * (*curVertices);  
 
            curVertices++;  
        }  
        vbuf->unlock();  
    }  
 
    // Get the bone index element  
    if (_entity && _entity->hasSkeleton())  
    {  
 
        Ogre::MeshPtr mesh = _entity->getMesh ();  
 
        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 (!_bone_mapping)  
                _bone_mapping = new BoneMapping();    
            BoneMapping::iterator i;  
 
            Ogre::Vector3 * curVertices = &_vertices[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 = _bone_mapping->find (currBone);  
                Vector3Array* l = 0;  
                if (i == _bone_mapping->end())  
                {  
                    l = new Vector3Array;  
                    _bone_mapping->insert(BoneMappingKey(currBone, l));  
                }                         
                else   
                {  
                    l = i->second;  
                }  
 
                l->push_back(*curVertices);  
 
                curVertices++;  
            }  
            vbuf->unlock();  
        }  
    }  

//------------------------------------------------------------------------------------------------
void TriangleMeshData::addVertexData(const VertexData *vertex_data,
                                   const VertexData *blended_data,
                                   const Mesh::IndexMap *indexMap)
{
    if (!vertex_data)
        return;

    const VertexData *data = (blended_data) ? blended_data: vertex_data;

    const unsigned int prev_size = _vertex_count;
    _vertex_count += (unsigned int)data->vertexCount;

    Ogre::Vector3* tmp_vert = new Ogre::Vector3[_vertex_count];
    if (_vertices)
    {
        memcpy(tmp_vert,_vertices,sizeof(Vector3) * prev_size);
        delete[] _vertices;
    }
    _vertices = 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 = &_vertices[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 = _transform * (*curVertices);

            curVertices++;
        }
        vbuf->unlock();
    }

    // Get the bone index element
    if (_entity && _entity->hasSkeleton())
    {

        Ogre::MeshPtr mesh = _entity->getMesh ();

        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 (!_bone_mapping)
                _bone_mapping = new BoneMapping(); 
            BoneMapping::iterator i;

            Ogre::Vector3 * curVertices = &_vertices[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 = _bone_mapping->find (currBone);
                Vector3Array* l = 0;
                if (i == _bone_mapping->end())
                {
                    l = new Vector3Array;
                    _bone_mapping->insert(BoneMappingKey(currBone, l));
                }      
                else
                {
                    l = i->second;
                }

                l->push_back(*curVertices);

                curVertices++;
            }
            vbuf->unlock();
        }
    }
}
  从ogre中设置terrain的物理效果我认为可以分成两类:

第一类很简单是从高度图直接读出然后建立定点索引序列,自己动手创建地形;

第二类是从实体创建,很简单的说就是从mesh模型来创建,这样的好处就是不用自己渲染了。。。

现在只实现了第二类的方法,其实本质就是从mesh里提取顶点信息和索引信息然后填充到

    NxTriangleMeshDesc* triangleMeshDesc; 剩下的无非是生成对应的模型而已;

 view plaincopy to clipboardprint?
NxActor* PhysxTool::CreateTriangleMesh(TriangleMeshData* data,NxPhysicsSDK *gPhysicsSDK,NxScene*gScene)  
    
{  
    NxTriangleMeshDesc* triangleMeshDesc;  
    // Create descriptor for triangle mesh  
    triangleMeshDesc= new NxTriangleMeshDesc();  
    triangleMeshDesc->numVertices            = data->getVertexCount();  
    triangleMeshDesc->pointStrideBytes       = sizeof(NxVec3);  
    triangleMeshDesc->points             = (void*)data->getVertices();  
    triangleMeshDesc->numTriangles           = data->getIndexCount()/3;  
    triangleMeshDesc->flags                  = 0;  
    triangleMeshDesc->triangles              = (void*)data->getIndices();  
    triangleMeshDesc->triangleStrideBytes    = 3 * sizeof(NxU32);  
 
    triangleMeshDesc->heightFieldVerticalAxis= NX_Y;     
    triangleMeshDesc->heightFieldVerticalExtent= -1000.0f;  
 
    // The actor has one shape, a triangle mesh  
    NxInitCooking();  
    MemoryWriteBuffer buf;  
 
    bool status = NxCookTriangleMesh(*triangleMeshDesc, buf);  
    NxTriangleMesh* pMesh;  
    if (status)  
    {  
        pMesh = gPhysicsSDK->createTriangleMesh(MemoryReadBuffer(buf.data));  
    }  
    else 
    {  
        assert(false);  
        pMesh = NULL;  
    }  
    NxCloseCooking();  
    // Create TriangleMesh above code segment.  
 
    NxTriangleMeshShapeDesc tmsd;  
    tmsd.meshData       = pMesh;  
    tmsd.userData       = triangleMeshDesc;  
    tmsd.localPose.t    = NxVec3(0, 0, 0);  
    tmsd.meshPagingMode = NX_MESH_PAGING_AUTO;  
    tmsd.shapeFlags     = NX_SF_FEATURE_INDICES;  
    NxActorDesc actorDesc;  
 
    assert(tmsd.isValid());  
    actorDesc.shapes.pushBack(&tmsd);  
    if (pMesh)  
        return gScene->createActor(actorDesc);  
    else 
        return NULL;  

NxActor* PhysxTool::CreateTriangleMesh(TriangleMeshData* data,NxPhysicsSDK *gPhysicsSDK,NxScene*gScene)
 
{
    NxTriangleMeshDesc* triangleMeshDesc;
    // Create descriptor for triangle mesh
    triangleMeshDesc= new NxTriangleMeshDesc();
    triangleMeshDesc->numVertices   = data->getVertexCount();
    triangleMeshDesc->pointStrideBytes  = sizeof(NxVec3);
    triangleMeshDesc->points    = (void*)data->getVertices();
    triangleMeshDesc->numTriangles   = data->getIndexCount()/3;
    triangleMeshDesc->flags     = 0;
    triangleMeshDesc->triangles    = (void*)data->getIndices();
    triangleMeshDesc->triangleStrideBytes = 3 * sizeof(NxU32);

    triangleMeshDesc->heightFieldVerticalAxis= NX_Y;  
    triangleMeshDesc->heightFieldVerticalExtent= -1000.0f;

    // The actor has one shape, a triangle mesh
    NxInitCooking();
    MemoryWriteBuffer buf;

    bool status = NxCookTriangleMesh(*triangleMeshDesc, buf);
    NxTriangleMesh* pMesh;
    if (status)
    {
        pMesh = gPhysicsSDK->createTriangleMesh(MemoryReadBuffer(buf.data));
    }
    else
    {
        assert(false);
        pMesh = NULL;
    }
    NxCloseCooking();
    // Create TriangleMesh above code segment.

    NxTriangleMeshShapeDesc tmsd;
    tmsd.meshData  = pMesh;
    tmsd.userData  = triangleMeshDesc;
    tmsd.localPose.t = NxVec3(0, 0, 0);
    tmsd.meshPagingMode = NX_MESH_PAGING_AUTO;
    tmsd.shapeFlags     = NX_SF_FEATURE_INDICES;
    NxActorDesc actorDesc;

    assert(tmsd.isValid());
    actorDesc.shapes.pushBack(&tmsd);
    if (pMesh)
        return gScene->createActor(actorDesc);
    else
        return NULL;
}
 

返回的actor就可以直接使用了,因为没有设置body,所以默认为static,当有物体落到表面是自动进行碰撞检测;

这个实现的关键还在于对mesh的数据的提取,这是从ogreode中“剽窃”的一段代码,演示如何提取顶点数据和索引数据;

·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
//const bool isHWanimated = isSkeletonAnimated && entity->isHardwareAnimationEnabled();  
if (isSkeletonAnimated)  
{  
    _entity->addSoftwareAnimationRequest(false);  
    _entity->_updateAnimation();  
}  
 
 
if (_entity->getMesh()->sharedVertexData)  
{  
    if (!isSkeletonAnimated)  
        addVertexData (_entity->getMesh()->sharedVertexData);  
    else 
        addVertexData (_entity->getMesh()->sharedVertexData,   
        _entity->_getSkelAnimVertexData(),  
        &_entity->getMesh()->sharedBlendIndexToBoneIndexMap);   
}  
 
for(unsigned int i = 0;i < _entity->getNumSubEntities();++i)  
{  
    SubMesh *sub_mesh = _entity->getSubEntity(i)->getSubMesh();  
 
    if (!sub_mesh->useSharedVertices)  
    {  
        addIndexData(sub_mesh->indexData,_vertex_count);  
 
        if (!isSkeletonAnimated)  
            addVertexData (sub_mesh->vertexData);  
        else 
            addVertexData (sub_mesh->vertexData,   
            _entity->getSubEntity(i)->_getSkelAnimVertexData(),  
            &sub_mesh->blendIndexToBoneIndexMap);   
    }  
    else   
    {  
        addIndexData (sub_mesh->indexData);  
    }  
 

    //const bool isHWanimated = isSkeletonAnimated && entity->isHardwareAnimationEnabled();
    if (isSkeletonAnimated)
    {
        _entity->addSoftwareAnimationRequest(false);
        _entity->_updateAnimation();
    }


    if (_entity->getMesh()->sharedVertexData)
    {
        if (!isSkeletonAnimated)
            addVertexData (_entity->getMesh()->sharedVertexData);
        else
            addVertexData (_entity->getMesh()->sharedVertexData,
            _entity->_getSkelAnimVertexData(),
            &_entity->getMesh()->sharedBlendIndexToBoneIndexMap);
    }

    for(unsigned int i = 0;i < _entity->getNumSubEntities();++i)
    {
        SubMesh *sub_mesh = _entity->getSubEntity(i)->getSubMesh();

        if (!sub_mesh->useSharedVertices)
        {
            addIndexData(sub_mesh->indexData,_vertex_count);

            if (!isSkeletonAnimated)
                addVertexData (sub_mesh->vertexData);
            else
                addVertexData (sub_mesh->vertexData,
                _entity->getSubEntity(i)->_getSkelAnimVertexData(),
                &sub_mesh->blendIndexToBoneIndexMap);
        }
        else
        {
            addIndexData (sub_mesh->indexData);
        }

    }

addindex和addvertex分别向该类中写入数据:

view plaincopy to clipboardprint?
void TriangleMeshData::addIndexData(IndexData *data, const unsigned int offset)  
{  
    const unsigned int prev_size = _index_count;  
    _index_count += (unsigned int)data->indexCount;  
 
    TriangleIndex* tmp_ind = new TriangleIndex[_index_count];  
    if (_indices)  
    {  
        memcpy (tmp_ind, _indices, sizeof(unsigned int) * prev_size);  
        delete[] _indices;  
    }  
    _indices = 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)  
        {  
            _indices[index_offset ++] = offset + *pInt++;  
            _indices[index_offset ++] = offset + *pInt++;  
            _indices[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)  
        {  
            _indices[index_offset ++] = offset + static_cast<unsigned int> (*pShort++);  
            _indices[index_offset ++] = offset + static_cast<unsigned int> (*pShort++);  
            _indices[index_offset ++] = offset + static_cast<unsigned int> (*pShort++);  
        }  
        ibuf->unlock();  
    }  
 

void TriangleMeshData::addIndexData(IndexData *data, const unsigned int offset)
{
    const unsigned int prev_size = _index_count;
    _index_count += (unsigned int)data->indexCount;

    TriangleIndex* tmp_ind = new TriangleIndex[_index_count];
    if (_indices)
    {
        memcpy (tmp_ind, _indices, sizeof(unsigned int) * prev_size);
        delete[] _indices;
    }
    _indices = 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)
        {
            _indices[index_offset ++] = offset + *pInt++;
            _indices[index_offset ++] = offset + *pInt++;
            _indices[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)
        {
            _indices[index_offset ++] = offset + static_cast<unsigned int> (*pShort++);
            _indices[index_offset ++] = offset + static_cast<unsigned int> (*pShort++);
            _indices[index_offset ++] = offset + static_cast<unsigned int> (*pShort++);
        }
        ibuf->unlock();
    }

}

 

本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/liu3xing3long/archive/2009/01/30/3855286.aspx

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值