Ogre实现简单地形

利用SimpleRenderable实现DirectX 9 3D 游戏设计入门中 第十三章 地形渲染基础的简单地形,只是简单的实现了地形的基本框架,顶点,索引,纹理等,为简单起见高度都为1,适合新手做入门的学习,高手可以飘过了,效果图:

Terrain.h:

#ifndef _TERRAIN_H_
#define _TERRAIN_H_

#include <Ogre.h>
#include "Common.h"


using namespace Ogre;

#define VERTEX_POS_BINDING 0

class CTerrain :public SimpleRenderable
{
public:
    //numVertsPerCol,numVertsPerRow为奇数时m_width,m_depth必定为偶数
    CTerrain(int numVertsPerRow=513,int numVertsPerCol=513,int cellSize=10,float heightScal=1.0f);
    ~CTerrain();

public:
    bool InitData();
    void LoadHeightmap();
    void CreateVertexData();
    void CreateIndexData();

    // Overridden from MovableObject
    virtual Real getBoundingRadius() const;
    virtual const AxisAlignedBox& getBoundingBox() const;

    // Overridden from Renderable
    virtual Real getSquaredViewDepth(const Ogre::Camera* cam) const;
private:
    String m_heightMapPath;//高度图
    float *m_heightMap;//高度数据
    float m_heightScal;//高度缩放值
    int m_numVertsPerRow;//每行顶点数
    int m_numVertsPerCol;//每列顶点数
    int m_numCellsPerRow;//每行格子数
    int m_numCellsPerCol;//每列格子数
    int m_cellSize;//格子边长
    int m_numVerts;//顶点总数
    int m_numTriangles;//三角形总数
    int m_width;//地形宽度
    int m_depth;//地形深度
    bool m_bSaveData;//是否保存顶点信息

    AxisAlignedBox mAABB;
    Real mBoundingRadius;
    VertexData *pVertexData;
    IndexData *pIndexData;
};



#endif

Terrain.cpp:

#include "Terrain.h"
#include <fstream>

CTerrain::CTerrain(int numVertsPerRow,int numVertsPerCol,int cellSize,float heightScal)
{
    m_numVertsPerRow=numVertsPerRow;
    m_numVertsPerCol=numVertsPerCol;
    m_heightScal=heightScal;
    m_cellSize=cellSize;
    m_heightMapPath="";
    m_bSaveData=true;

    m_numCellsPerRow=m_numVertsPerRow-1;
    m_numCellsPerCol=m_numVertsPerCol-1;
    m_numVerts=m_numVertsPerRow*m_numVertsPerCol;
    m_numTriangles=m_numCellsPerRow*m_numCellsPerCol*2;
    m_width=m_numCellsPerRow*m_cellSize;
    m_depth=m_numCellsPerCol*m_cellSize;

    m_heightMap=new float[m_numVerts];
}

CTerrain::~CTerrain()
{
    safeDelArry(m_heightMap);
    
    OGRE_DELETE(mRenderOp.vertexData);
    OGRE_DELETE(mRenderOp.indexData);
}


bool CTerrain::InitData()
{
    LoadHeightmap();
    CreateVertexData();
    CreateIndexData();

    return true;
}

void CTerrain::LoadHeightmap()
{
    for (int i=0;i<m_numVerts;i++)
    {
        m_heightMap[i]=1.0f;
    }
}

void CTerrain::CreateVertexData()
{
    mRenderOp.vertexData=new VertexData();
    pVertexData=mRenderOp.vertexData;
    pVertexData->vertexCount=m_numVerts;
    pVertexData->vertexStart=0;
    mRenderOp.operationType=RenderOperation::OT_TRIANGLE_LIST;
    mRenderOp.useIndexes=true;
    VertexDeclaration *decl=pVertexData->vertexDeclaration;
    VertexBufferBinding *bind=pVertexData->vertexBufferBinding;

    size_t vOffset=0,textCoordSet=0;
    decl->addElement(0,vOffset,VET_FLOAT3,VES_POSITION);
    vOffset=vOffset+VertexElement::getTypeSize(VET_FLOAT3);
    decl->addElement(0,vOffset,VET_COLOUR,VES_DIFFUSE);
    vOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR);
    decl->addElement(0,vOffset,VET_FLOAT2,VES_TEXTURE_COORDINATES,textCoordSet++);
    vOffset=vOffset+VertexElement::getTypeSize(VET_FLOAT2);
    decl->addElement(0,vOffset,VET_FLOAT2,VES_TEXTURE_COORDINATES,textCoordSet++);

    HardwareVertexBufferSharedPtr pVerBuff;
    pVerBuff=HardwareBufferManager::getSingleton().createVertexBuffer(decl->getVertexSize(0),m_numVerts,HardwareBuffer::HBU_STATIC_WRITE_ONLY,false);

    float *pLock=static_cast<float *>(pVerBuff->lock(0,pVerBuff->getSizeInBytes(),HardwareBuffer::HBL_DISCARD));

    RGBA colour,*pColour;
    RenderSystem *rs=Ogre::Root::getSingleton().getRenderSystem();
    rs->convertColourValue(ColourValue(1.0f,1.0f,1.0f),&colour);
    float start_x,end_x,start_z,end_z;
    int index=0;
    start_x=-m_width/2;
    end_x=-start_x;
    start_z=-m_depth/2;
    end_z=-start_z;

    std::ofstream of;
    bool bopen=false;
    if (m_bSaveData)
    {
        of.open(L"vertexInfo.txt",std::ios::out|std::ios::trunc);
        if (of.is_open())
        {
            bopen=true;
            of<<"------------------------------------------\r\n";
            of<<"vertex data info:\r\n";
        }else
        {
            MessageBox( NULL, L"INFO",L"An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
        }
    }
    float y=0.0f,tu=0.0f,tv=0.0f;
    int h=0,c=0;
    char tmepChar[128]={0};
    for (float z=start_z;z<=end_z;z+=m_cellSize)
    {
        tu=h*m_cellSize/(float)m_width;
        h++;
        c=0;
        for (float x=start_x;x<=end_x;x+=m_cellSize)
        {
            tv=c*m_cellSize/(float)m_depth;
            c++;

            y=m_heightMap[index++];
            *pLock=x;
            pLock++;
            *pLock=y;
            pLock++;
            *pLock=z;
            pLock++;

            pColour=static_cast<RGBA *>(static_cast<void *>(pLock));
            *pColour=colour;
            pColour++;
            pLock=static_cast<float *>(static_cast<void *>(pColour));

            *pLock=tu;
            pLock++;
            *pLock=tv;
            pLock++;

            *pLock=tu;
            pLock++;
            *pLock=tv;
            pLock++;

            if (m_bSaveData&&bopen)
            {
                sprintf(tmepChar,"x=%f y=%f z=%f u=%f v=%f\r\n",x,y,z,tu,tv);
                of<<tmepChar;
            }

        }

    }
    pVerBuff->unlock();
    bind->setBinding(0,pVerBuff);

    if (m_bSaveData&&bopen)
        of.close();

    float boxHeght=20.0f;
    float vertices[8][3] = {
        start_x, boxHeght, start_z,        // A
        -start_x, boxHeght, start_z,    // B
        start_x, boxHeght, -start_z,    // C
        -start_x, boxHeght, -start_z,    // D

        start_x, boxHeght, start_z,        // A
        -start_x, boxHeght, start_z,    // B
        start_x, boxHeght, -start_z,    // C
        -start_x, boxHeght, -start_z,    // D
    };

    for (int i=0;i<8;i++)
    {
        mAABB.merge(Ogre::Vector3(vertices[i][0], vertices[i][1], vertices[i][2]));        
    }
    mBoundingRadius = Ogre::Math::boundingRadiusFromAABB(mAABB);

}
/*A---------B
 -            -
 -            -
 -            -
 C-----------D
*/
void CTerrain::CreateIndexData()
{
    mRenderOp.indexData=new IndexData();
    pIndexData=mRenderOp.indexData;
    pIndexData->indexStart=0;
    pIndexData->indexCount=m_numTriangles*3;
    pIndexData->indexBuffer=HardwareBufferManager::getSingleton().createIndexBuffer(HardwareIndexBuffer::IT_16BIT,pIndexData->indexCount,HardwareBuffer::HBU_STATIC_WRITE_ONLY);
    unsigned short *pIndexLock=static_cast<unsigned short *>(pIndexData->indexBuffer->lock(0, pIndexData->indexBuffer->getSizeInBytes(),HardwareBuffer::HBL_DISCARD));
    

    std::ofstream of;
    bool bopen=false;
    if (m_bSaveData)
    {
        of.open(L"indexInfo.txt",std::ios::out|std::ios::trunc);
        if (of.is_open())
        {
            bopen=true;
            of<<"------------------------------------------\r\n";
            of<<"index data info:\r\n";
        }else
        {
            MessageBox( NULL, L"INFO",L"An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
        }
    }

    char tmepChar[128]={0};
    unsigned short uvalue[6];
    int index=0;

    for (unsigned short row=0;row<m_numCellsPerCol;row++)
    {
        for (unsigned short col=0;col<m_numCellsPerRow;col++)
        {
            //ACB
            uvalue[0]=row*m_numVertsPerRow+col;
            *pIndexLock=uvalue[0];
            pIndexLock++;
            uvalue[1]=(row+1)*m_numVertsPerRow+col;
            *pIndexLock=uvalue[1];
            pIndexLock++;
            uvalue[2]=row*m_numVertsPerRow+col+1;//
            *pIndexLock=uvalue[2];
            pIndexLock++;
            //CDB
            uvalue[3]=uvalue[1];
            uvalue[5]=uvalue[2];
            uvalue[4]=(row+1)*m_numVertsPerRow+col+1;
            *pIndexLock=uvalue[3];
            pIndexLock++;
            *pIndexLock=uvalue[4];
            pIndexLock++;
            *pIndexLock=uvalue[5];
            pIndexLock++;

            if (m_bSaveData&&bopen)
            {
                for (int j=0;j<6;j++)
                {
                    sprintf(tmepChar,"index%d=%u ",index++,uvalue[j]);
                    of<<tmepChar;
                    if (j==5)
                    {
                        of<<std::endl;
                    }
                }

            }
        }
    }
    pIndexData->indexBuffer->unlock();
    if (m_bSaveData&&bopen)
    {
        of.close();
    }
}

Real CTerrain::getBoundingRadius() const
{
    return mBoundingRadius;
}

Real CTerrain::getSquaredViewDepth(const Ogre::Camera* cam) const
{
    assert(mParentNode);
    return mParentNode->getSquaredViewDepth(cam);
}

const AxisAlignedBox& CTerrain::getBoundingBox() const
{
    return mAABB;
}

创建地形:

void CApplication::CreateTerrain()
{
    pTerrain=new CTerrain(65,65,10,1.0f);
    pTerrain->InitData();
    pTerrain->setMaterial("Examples/Terrain_Material");
    SceneNode *node =pSceneManager->getRootSceneNode()->createChildSceneNode("TerrainNode",Vector3(0,0,0));
    node->attachObject(pTerrain);
    node->showBoundingBox(true);
}

 材质:

material Examples/Terrain_Material : Examples/OgreDance
{
    technique
    {
        pass
        {
            lighting off
            //scene_blend alpha_blend
            //cull_hardware none
            //cull_software none

            texture_unit
            {
                texture dirt_grayrocky_diffusespecular.dds
                tex_address_mode wrap
            }
            texture_unit
            {
                //colour_op_ex add src_texture src_current
                //colour_op_multipass_fallback one one

                texture grass_green-01_diffusespecular.dds
                tex_address_mode wrap
            }
        }
    }
}

 

posted @ 2013-08-14 14:32  冷夜 - 网游编程技术  阅读(1253)  评论(0编辑  收藏  举报