具有顶点的Directx 9基本地形创建

时间:2012-01-12 05:40:48

标签: c++ winapi directx

我正在尝试使用索引基元创建地形...我已经编写了一个类来处理图形,但是,我无法让纹理地形出现在屏幕上......以下是源代码和此进程关联的头文件...请忽略天空盒功能......

graphics.h中:

#pragma once

#include <d3d9.h>
#include <d3dx9.h>
#include <d3dx9tex.h>
#include <string>
#include "Camera.h"


class CGraphics
{
public:
    CGraphics(IDirect3DDevice9 *device);
    ~CGraphics(void);

    IDirect3DDevice9 *m_d3ddev;
    LPDIRECT3DVERTEXBUFFER9 m_vertexBuffer;
    LPDIRECT3DVERTEXBUFFER9 m_terrainVertexBuffer;
    LPDIRECT3DINDEXBUFFER9 m_terrainIndexBuffer;
    LPDIRECT3DTEXTURE9 m_textures[6];
    LPDIRECT3DTEXTURE9 m_terrainTexture;
    int m_numVertices;
    int m_numFaces;

    bool SkyBox(void);  
    void UpdateSkyBox(void);
    bool Terrain(D3DXVECTOR3 minB, D3DXVECTOR3 maxB, int numCellsW, int numCellsL);
    void RenderTerrain(void);
private:
    void RenderSkyBox(void);

};

graphics.cpp:

#include "Graphics.h"
#include "3D Shapes.h"
#include "assert.h"

CGraphics::CGraphics(IDirect3DDevice9 *device) : m_d3ddev(device), m_vertexBuffer(0)
{
    for(unsigned int i = 0; i < sizeof(LPDIRECT3DTEXTURE9)/sizeof(m_textures); i++)
    {
        m_textures[i] = 0;
        m_terrainVertexBuffer = NULL;
        m_terrainIndexBuffer = NULL;
    }
}
CGraphics::~CGraphics(void)
{
    if(m_vertexBuffer)
    {
        delete m_vertexBuffer;
        m_vertexBuffer=0;
    }
    if(m_d3ddev)
    {
        m_d3ddev->Release();
        m_d3ddev=0;
    }
    if(m_terrainVertexBuffer){
        m_terrainVertexBuffer->Release();
        m_terrainVertexBuffer=0;
    }
    if(m_terrainIndexBuffer){
        m_terrainIndexBuffer->Release();
        m_terrainIndexBuffer=0;
    }
}
bool CGraphics::SkyBox(void)
{
    HRESULT hr;
    hr = m_d3ddev->CreateVertexBuffer(sizeof(TEXTUREVERTEX) * 24, 0, CUSTOMFVF, D3DPOOL_MANAGED,
        &m_vertexBuffer, NULL);
    if(FAILED(hr))
    {
        MessageBox(NULL, L"Failed to 'Create Vertex Buffer for SkyBox'", L"ERROR", MB_OK);
        return false;
    }

    void* pVertices = NULL;

    m_vertexBuffer->Lock(0, sizeof(TEXTUREVERTEX)*24, (void**)&pVertices, 0);
    memcpy(pVertices, skyBox, sizeof(TEXTUREVERTEX)*24);
    m_vertexBuffer->Unlock();

    hr  = D3DXCreateTextureFromFileA(m_d3ddev, fileF.c_str(), &m_textures[0]);
    hr |= D3DXCreateTextureFromFileA(m_d3ddev, fileB.c_str(), &m_textures[1]);
    hr |= D3DXCreateTextureFromFileA(m_d3ddev, fileL.c_str(), &m_textures[2]);
    hr |= D3DXCreateTextureFromFileA(m_d3ddev, fileR.c_str(), &m_textures[3]);
    hr |= D3DXCreateTextureFromFileA(m_d3ddev, fileTop.c_str(), &m_textures[4]);
    hr |= D3DXCreateTextureFromFileA(m_d3ddev, fileBottom.c_str(), &m_textures[5]);
    if ( FAILED(hr) )
    {
        MessageBox(NULL, L"Failed to open 1 or more images files!", L"Error Opening Texture Files", MB_OK);
        return false;
    }   
    return true;
}
void CGraphics::UpdateSkyBox(void)
{
    D3DXMATRIX matView, matSave, matWorld;
    m_d3ddev->GetTransform(D3DTS_VIEW, &matSave);
    matView = matSave;
    matView._41 = 0.0f; matView._42 = -0.4f; matView._43 = 0.0f;
    m_d3ddev->SetTransform(D3DTS_VIEW, &matView);
    D3DXMatrixIdentity(&matWorld);
    m_d3ddev->SetTransform(D3DTS_WORLD, &matWorld);
    RenderSkyBox();
    m_d3ddev->SetTransform(D3DTS_VIEW, &matSave);
}
void CGraphics::RenderSkyBox(void)
{
    m_d3ddev->SetRenderState(D3DRS_ZENABLE, false);
    m_d3ddev->SetRenderState(D3DRS_ZWRITEENABLE, false);
    m_d3ddev->SetRenderState(D3DRS_LIGHTING, false);
    m_d3ddev->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP );
    m_d3ddev->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP );

    m_d3ddev->SetFVF(CUSTOMFVF);
    m_d3ddev->SetStreamSource(0, m_vertexBuffer, 0, sizeof(TEXTUREVERTEX));

    for(unsigned int i = 0; i < 6; i ++)
    {
        m_d3ddev->SetTexture(0, m_textures[i]);
        m_d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, i*4, 2);
    }
    m_d3ddev->SetRenderState(D3DRS_ZENABLE, true);
    m_d3ddev->SetRenderState(D3DRS_ZWRITEENABLE, true);
    m_d3ddev->SetRenderState(D3DRS_LIGHTING, true);
}
bool CGraphics::Terrain(D3DXVECTOR3 minB, D3DXVECTOR3 maxB, int numCellsW, int numCellsL)
{
    HRESULT hr = D3DXCreateTextureFromFileA(m_d3ddev, (LPCSTR)texFileTerrain.c_str(), &m_terrainTexture);
    if(FAILED(hr))
    {
        MessageBox(NULL, L"Could not 'Load Texture(Terrain)'", L"ERROR", MB_OK);
        return false;
    }

    TERRAIN terra = {minB,maxB,numCellsW,numCellsL,numCellsW+1,numCellsL+1,(maxB.x - minB.x)/numCellsW,
        (maxB.z - minB.z)/numCellsL,
        terra.vertices = new VERTEXARRAY[terra.numVertsX*terra.numVertsZ],
    };
    m_numVertices = terra.numVertsX*terra.numVertsZ;
    m_numFaces = terra.numCellsX*terra.numCellsZ*2;
    DWORD *indices = new DWORD[terra.numCellsX*terra.numCellsZ*6];
    for(int i = 0; i < sizeof(indices); i++)
    {
        indices[i] = 0;
    }
    D3DXVECTOR3 pos(minB.x, 0, minB.z);

    int vIter = 0;
    for(int z = 0; z < terra.numVertsZ; z++)
    {
        for(int x = 0; x < terra.numVertsX; x++)
        {
            terra.vertices[vIter].x = 0;
            terra.vertices[vIter].y = 0;
            terra.vertices[vIter].z = 0;
            terra.vertices[vIter].tu = 0;
            terra.vertices[vIter].tv = 0;
            vIter++;
        }
    }
    double curTexPosZ = 1.0;
    vIter=0;
    for(double z = 0; z < (double)terra.numVertsZ; z++)
    {
        pos.x = minB.x;
        curTexPosZ = (double)((double)terra.numCellsZ - z) / (double)(terra.numCellsZ);     
        for(double x = 0; x < terra.numVertsX; x++)
        {
            terra.vertices[vIter].x = pos.x;
            terra.vertices[vIter].y = pos.y;
            terra.vertices[vIter].z = pos.z;
            //terra.vertices[vIter].color = D3DCOLOR_ARGB(0,255,255,255);
            terra.vertices[vIter].tu = (float)(x / (double)terra.numCellsX);
            terra.vertices[vIter].tv = (float)curTexPosZ;
            pos.x += terra.stepX;
            vIter++;
        }
        pos.z += terra.stepZ;
    }
    assert(vIter <= terra.numVertsX*terra.numVertsZ);

    vIter = 0;
    int iPos =0;
    for(int z =0; z< terra.numCellsZ; z++)
    {
        for(int x = 0; x< terra.numCellsX; x++)
        {
            indices[iPos] = vIter; iPos++;
            indices[iPos] = vIter+terra.numVertsX; iPos++;
            indices[iPos] = vIter+terra.numVertsX+1; iPos++;
            indices[iPos] = vIter; iPos++;
            indices[iPos] = vIter+terra.numVertsX+1; iPos++;
            indices[iPos] = vIter+1; iPos++;
            vIter++;
        }
        vIter++;
    }
    assert(vIter <= terra.numCellsX*terra.numCellsZ*6);
    void* pVoid;

    hr = m_d3ddev->CreateVertexBuffer(sizeof(VERTEXARRAY)*terra.numVertsX*terra.numVertsZ,0,
        CUSTOMFVF,D3DPOOL_MANAGED,&m_terrainVertexBuffer,NULL);
    if(FAILED(hr)){
        MessageBox(NULL, L"Could not Create Vertex Buffer", L"ERROR", MB_OK);
        return false;
    }   
    hr = m_terrainVertexBuffer->Lock(0, 0, (void**)&pVoid, NULL);
    if(FAILED(hr)){
        MessageBox(NULL, L"Could not Lock Vertex Buffer", L"ERROR", MB_OK);
        return false;
    }   
    memcpy(pVoid, terra.vertices, sizeof(terra.vertices));
    m_terrainVertexBuffer->Unlock();

    hr = m_d3ddev->CreateIndexBuffer(sizeof(DWORD)*sizeof(indices),0,
        D3DFMT_INDEX16, D3DPOOL_MANAGED, &m_terrainIndexBuffer, NULL);
    if(FAILED(hr)){
        MessageBox(NULL, L"Could not Create Index Buffer", L"ERROR", MB_OK);
        return false;
    }   
    hr = m_terrainIndexBuffer->Lock(0, 0, (void**)&pVoid, 0);
    if(FAILED(hr)){
        MessageBox(NULL, L"Could not Create Vertex Buffer", L"ERROR", MB_OK);
        return false;
    }   
    memcpy(pVoid, indices, sizeof(indices));
    if(FAILED(hr)){
        MessageBox(NULL, L"Could not Create Vertex Buffer", L"ERROR", MB_OK);
        return false;
    }   
    m_terrainIndexBuffer->Unlock();

    return true;
}
void CGraphics::RenderTerrain(void)
{
    m_d3ddev->SetFVF(CUSTOMFVF);
    m_d3ddev->SetTexture(0, m_terrainTexture);
    m_d3ddev->SetStreamSource(0, m_terrainVertexBuffer, 0, sizeof(VERTEXARRAY));
    m_d3ddev->SetIndices(m_terrainIndexBuffer);
    m_d3ddev->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0, 0, m_numVertices, 0, m_numFaces);
}

3D形状:

#pragma once
#define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_TEX1)

struct TEXTUREVERTEX {
    float x, y, z, tu, tv;
};
TEXTUREVERTEX skyBox[] = {
    // Front quad, NOTE: All quads face inward
    {-10.0f, -10.0f,  10.0f,  0.0f, 1.0f }, {-10.0f,  10.0f,  10.0f,  0.0f, 0.0f }, { 10.0f, -10.0f,  10.0f,  1.0f, 1.0f }, { 10.0f,  10.0f,  10.0f,  1.0f, 0.0f },
    // Back quad
    { 10.0f, -10.0f, -10.0f,  0.0f, 1.0f }, { 10.0f,  10.0f, -10.0f,  0.0f, 0.0f }, {-10.0f, -10.0f, -10.0f,  1.0f, 1.0f },{-10.0f,  10.0f, -10.0f,  1.0f, 0.0f },
    // Left quad
    {-10.0f, -10.0f, -10.0f,  0.0f, 1.0f }, {-10.0f,  10.0f, -10.0f,  0.0f, 0.0f }, {-10.0f, -10.0f,  10.0f,  1.0f, 1.0f }, {-10.0f,  10.0f,  10.0f,  1.0f, 0.0f },
    // Right quad
    { 10.0f, -10.0f,  10.0f,  0.0f, 1.0f }, { 10.0f,  10.0f,  10.0f,  0.0f, 0.0f }, { 10.0f, -10.0f, -10.0f,  1.0f, 1.0f }, { 10.0f,  10.0f, -10.0f,  1.0f, 0.0f },
    // Top quad
    {-10.0f,  10.0f,  10.0f,  0.0f, 1.0f }, {-10.0f,  10.0f, -10.0f,  0.0f, 0.0f }, { 10.0f,  10.0f,  10.0f,  1.0f, 1.0f }, { 10.0f,  10.0f, -10.0f,  1.0f, 0.0f },
    // Bottom quad
    {-10.0f, -10.0f, -10.0f,  0.0f, 1.0f }, {-10.0f, -10.0f,  10.0f,  0.0f, 0.0f }, { 10.0f, -10.0f, -10.0f,  1.0f, 1.0f },{ 10.0f, -10.0f,  10.0f,  1.0f, 0.0f }

};

std::string fileF("skybox_front.jpg");
std::string fileB("skybox_back.jpg");
std::string fileL("skybox_left.jpg");
std::string fileR("skybox_right.jpg");
std::string fileTop("skybox_top.jpg");
std::string fileBottom("skybox_bottom.jpg");

struct VERTEXARRAY {
    float x, y, z, tu, tv;
};
struct TERRAIN {
    D3DXVECTOR3     minBounds;      // minimum bounds (x, y, z)
    D3DXVECTOR3     maxBounds;      // maximum bounds (x, y, z)
    int             numCellsX;      // # of cells in the x direction
    int             numCellsZ;      // # of cells in the z direction
    int             numVertsX;      // # of vertices in the x direction
    int             numVertsZ;      // # of vertices in the z direction
    float           stepX;          // space between vertices in the x direction
    float           stepZ;          // space between vertices in the z direction
    VERTEXARRAY     *vertices;          // vertex array pointer (stores the position for each vertex
};

std::string texFileTerrain("sunset.jpg");

我在线查看了无数的教程和样本,但没有找到解决方案。我想我遇到的问题与设置有关,我必须忽略一些事情......任何想法都会受到赞赏......提前谢谢!

0 个答案:

没有答案