zoukankan      html  css  js  c++  java
  • 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<<"------------------------------------------
    ";
                of<<"vertex data info:
    ";
            }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
    ",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<<"------------------------------------------
    ";
                of<<"index data info:
    ";
            }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
                }
            }
        }
    }
  • 相关阅读:
    禁用Clusterware在系统启动后自己主动启动
    码农的产品思维培养第4节----听用户饿但不要照着做《人人都是产品经理》
    android RecycleView复杂多条目的布局
    【shell脚本练习】网卡信息和简单日志分析
    Java太阳系小游戏分析和源代码
    《你是我的眼》,歌曲非常好听
    hdu 1856 More is better(并查集)
    Python 中的isinstance函数
    Python中的 isdigit()方法
    Python中的split()函数的使用方法
  • 原文地址:https://www.cnblogs.com/gamesky/p/3257119.html
Copyright © 2011-2022 走看看