Sign in to follow this  

Problems of terrain generation with DirectX9

This topic is 3726 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey guys, I'm new here. I'm a rookie of DirectX and game programming, and I'm trying to write a virtual interactive environment program. However, I encountered problems about terrain generation. My goal is to produce a terrain with quad tree, but first I think I should build the terrain and leave the things about culling later. But the thing is not as easy as I estimated. Here I have built the CTerrain and CTerrainQuad(two adjacent triangles that compose a cell) classes under the guide of the book "Introduction to 3D Game Engine Design Using DirectX9 and C#"(it's the only book I can find on the topic in China~~). It seems to be right, but the terrain just cannot show up. I can't figure out what's wrong.Perhaps that my usage of the vertex buffer is wrong or I haven't set the instance of these classes and the matrices correctly in the DXUT framework program? I'll be really appreciated that you veterans can help me or introduce some available electronic tutorials of game programming using DirectX9. You know, I can't find materials of game programming and DirectX in China... Here is the project in VC 2005.

Share this post


Link to post
Share on other sites
I don't know how to upload my project or my source, could anyone tell me?
copy some here:
The CTerrainQuad.h:
#pragma once

typedef struct CustomVertex
{
float x,y,z;
D3DXVECTOR3 n;
float u,v;
static const int FVF = D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1;
CustomVertex( float zx, float zy, float zz, D3DXVECTOR3 zn, float zu, float zv)
{
x = zx; y = zy; z = zz;
n = zn;
u = zu; v = zv;
}
CustomVertex()
{
x = y = z = 0;
n = D3DXVECTOR3(0,0,0);
u = v = 0;
}
void SetVertexWithoutNorm( float zx, float zy, float zz, float zu, float zv)
{
x = zx; y = zy; z = zz;
u = zu; v = zv;
};

void SetVertexNorm( D3DXVECTOR3 zn)
{
n = zn;
}
} CustomVertex;

class CTerrainQuad
{
public:
CTerrainQuad(){};
CTerrainQuad( const D3DXVECTOR3 p1, const D3DXVECTOR3 p2, const D3DXVECTOR3 p3, const D3DXVECTOR3 p4 );
~CTerrainQuad(void);
void Setup( const D3DXVECTOR3 p1, const D3DXVECTOR3 p2, const D3DXVECTOR3 p3, const D3DXVECTOR3 p4 );
int RenderQuad( int Offset, CustomVertex* vertices);
inline bool isValid(){return m_bValid;}

inline D3DXVECTOR3 GetFaceNormals()
{
D3DXVECTOR3 sum = m_vFace1Norm + m_vFace2Norm;
D3DXVec3Normalize( &sum, &sum);
return sum;
}

inline void ComputeFaceNormal( const D3DXVECTOR3* p0,const D3DXVECTOR3* p1, const D3DXVECTOR3* p2, D3DXVECTOR3* out)
{
D3DXVECTOR3 u = *p1 - *p0;
D3DXVECTOR3 v = *p2 - *p0;

D3DXVec3Cross( out, &u, &v);
D3DXVec3Normalize( out, out);
}

void SetCornerNormal( int index, D3DXVECTOR3 zn);
D3DXVECTOR3 m_vFace1Norm;
D3DXVECTOR3 m_vFace2Norm;
private:
CustomVertex m_Corners[6];
bool m_bValid;
};

Share this post


Link to post
Share on other sites
The CTerrainQuad.cpp:
#include "dxstdafx.h"
#include "TerrainQuad.h"

CTerrainQuad::CTerrainQuad(const D3DXVECTOR3 p1, const D3DXVECTOR3 p2, const D3DXVECTOR3 p3, const D3DXVECTOR3 p4 )
{
m_Corners[0].SetVertexWithoutNorm( p3.x, p3.y, p3.z, 0.0f, 1.0f); // northwest
m_Corners[1].SetVertexWithoutNorm( p1.x, p1.y, p1.z, 0.0f, 0.0f); // southwest
m_Corners[2].SetVertexWithoutNorm( p4.x, p4.y, p4.z, 1.0f, 1.0f); // northeast
m_Corners[3].SetVertexWithoutNorm( p2.x, p2.y, p2.z, 1.0f, 0.0f); // southeast

ComputeFaceNormal( &p3, &p1, &p4, &m_vFace1Norm);
ComputeFaceNormal( &p1, &p2, &p4, &m_vFace2Norm);

// Default the vertex normals to the face normal value
m_Corners[0].SetVertexNorm( m_vFace1Norm);
m_Corners[1].SetVertexNorm(GetFaceNormals());
m_Corners[2].SetVertexNorm(GetFaceNormals());
m_Corners[3].SetVertexNorm( m_vFace1Norm);
m_Corners[4].SetVertexNorm(GetFaceNormals());
m_Corners[5].SetVertexNorm(GetFaceNormals());

m_Corners[4].x = m_Corners[2].x; m_Corners[4].y = m_Corners[2].y; m_Corners[4].z = m_Corners[2].z;
m_Corners[4].u = m_Corners[2].u; m_Corners[4].v = m_Corners[2].v;

m_Corners[5].x = m_Corners[1].x; m_Corners[5].y = m_Corners[1].y; m_Corners[5].z = m_Corners[1].z;
m_Corners[5].u = m_Corners[1].u; m_Corners[5].v = m_Corners[1].v;

m_bValid = true;

}

CTerrainQuad::~CTerrainQuad(void)
{
}

int CTerrainQuad::RenderQuad(int Offset, CustomVertex* vertices)
{
int newOffset = Offset;

if (1) // modify later to include culling
{
for( int i = 0; i<6; i++)
vertices[ Offset + i] = m_Corners[i];
newOffset += 6;
}
return newOffset;
}

void CTerrainQuad::Setup(const D3DXVECTOR3 p1, const D3DXVECTOR3 p2, const D3DXVECTOR3 p3, const D3DXVECTOR3 p4 )
{
m_Corners[0].SetVertexWithoutNorm( p3.x, p3.y, p3.z, 0.0f, 1.0f); // northwest
m_Corners[1].SetVertexWithoutNorm( p1.x, p1.y, p1.z, 0.0f, 0.0f); // southwest
m_Corners[2].SetVertexWithoutNorm( p4.x, p4.y, p4.z, 1.0f, 1.0f); // northeast
m_Corners[3].SetVertexWithoutNorm( p2.x, p2.y, p2.z, 1.0f, 0.0f); // southeast

ComputeFaceNormal( &p3, &p1, &p4, &m_vFace1Norm);
ComputeFaceNormal( &p1, &p2, &p4, &m_vFace2Norm);

// Default the vertex normals to the face normal value
m_Corners[0].SetVertexNorm( m_vFace1Norm);
m_Corners[1].SetVertexNorm(GetFaceNormals());
m_Corners[2].SetVertexNorm(GetFaceNormals());
m_Corners[3].SetVertexNorm( m_vFace1Norm);
m_Corners[4].SetVertexNorm(GetFaceNormals());
m_Corners[5].SetVertexNorm(GetFaceNormals());

m_Corners[4].x = m_Corners[2].x; m_Corners[4].y = m_Corners[2].y; m_Corners[4].z = m_Corners[2].z;
m_Corners[4].u = m_Corners[2].u; m_Corners[4].v = m_Corners[2].v;

m_Corners[5].x = m_Corners[1].x; m_Corners[5].y = m_Corners[1].y; m_Corners[5].z = m_Corners[1].z;
m_Corners[5].u = m_Corners[1].u; m_Corners[5].v = m_Corners[1].v;

m_bValid = true;

}

void CTerrainQuad::SetCornerNormal(int index, D3DXVECTOR3 zn)
{
D3DXVec3Normalize( &zn, &zn);
m_Corners[index].SetVertexNorm( zn);
}

Share this post


Link to post
Share on other sites
The CTerrain.h:
#pragma once
#include "TerrainQuad.h"


class CTerrain
{
public:
CTerrain();
HRESULT Render(LPDIRECT3DDEVICE9 pd3dDevice);
HRESULT Setup(LPDIRECT3DDEVICE9 pd3dDevice, int xSize, int ySize, LPCWSTR sHeightMap, LPCWSTR sTexName, float fSpacing, float fElevFactor);
public:
void Destroy();
~CTerrain(void);
private:
D3DXVECTOR3* m_pElevations;
CTerrainQuad* m_pTerrainQuads;
LPDIRECT3DVERTEXBUFFER9 m_pVB;
int m_xSize;
int m_ySize;
LPDIRECT3DTEXTURE9 m_pTex;
bool m_bValid;
CustomVertex* m_pVertices;
float m_fSpacing;
LPCWSTR m_sTexName;
};

Share this post


Link to post
Share on other sites
The CTerrain.cpp:
#include "dxstdafx.h"
#include "Terrain.h"
#include <fstream>
CTerrain::CTerrain(void):m_xSize(0),m_ySize(0),m_fSpacing(0),m_sTexName(NULL),m_bValid(true)
{
}

CTerrain::~CTerrain(void)
{
}


HRESULT CTerrain::Setup( LPDIRECT3DDEVICE9 pd3dDevice, int xSize, int ySize, LPCWSTR sHeightMap, LPCWSTR sTexName, float fSpacing, float fElevFactor)
{
m_pElevations = new D3DXVECTOR3 [xSize * ySize];
m_xSize = xSize - 1;
m_ySize = ySize - 1;
m_pTerrainQuads = new CTerrainQuad[ m_xSize * m_ySize ];
m_fSpacing = fSpacing;
m_pVertices = new CustomVertex[3000];
m_sTexName = sTexName;

std::ifstream inFile( sHeightMap, std::ios_base::binary);
if( inFile == 0)
return E_FAIL;

// Read the .raw File
for ( int i = 0; i < xSize; i++)
{
for ( int j = 0; j < ySize; j++)
{
char temp;
inFile.read( &temp, sizeof(BYTE));
m_pElevations[i * xSize + j].x = i * fSpacing;
m_pElevations[i * xSize + j].z = j * fSpacing;
m_pElevations[i * xSize + j].y = temp * fElevFactor;
}
}

// Create Terrain Quads
for ( int i = 0; i < m_xSize; i++)
{
for ( int j = 0; j < m_ySize; j++)
{
CTerrainQuad tempQuad = m_pTerrainQuads[ i * m_xSize + j];
tempQuad.Setup( m_pElevations[i * xSize + j],m_pElevations[(i+1) * xSize + j],
m_pElevations[i * xSize + j+1],m_pElevations[(i+1) * xSize + j+1]);
}
}

// Set up the vertices' normals
for (int i = 1; i < m_xSize-1; i++)
{
for ( int j = 1; j < m_ySize-1; j++)
{
D3DXVECTOR3 Normalsw = m_pTerrainQuads[i * m_xSize + j ].GetFaceNormals() +
m_pTerrainQuads[(i-1) * m_xSize + j - 1].GetFaceNormals()+
m_pTerrainQuads[(i-1) * m_xSize + j ].GetFaceNormals()+
m_pTerrainQuads[i * m_xSize + j - 1 ].GetFaceNormals();
m_pTerrainQuads[i * m_xSize + j ].SetCornerNormal( 0, Normalsw);

D3DXVECTOR3 Normalse = m_pTerrainQuads[i * m_xSize + j ].GetFaceNormals() +
m_pTerrainQuads[i * m_xSize + j - 1].GetFaceNormals()+
m_pTerrainQuads[(i+1) * m_xSize + j ].GetFaceNormals()+
m_pTerrainQuads[(i+1) * m_xSize + j - 1 ].GetFaceNormals();
m_pTerrainQuads[i * m_xSize + j ].SetCornerNormal( 1, Normalse);

D3DXVECTOR3 Normalnw = m_pTerrainQuads[i * m_xSize + j].GetFaceNormals() +
m_pTerrainQuads[(i-1) * m_xSize + j].GetFaceNormals()+
m_pTerrainQuads[(i-1) * m_xSize + j+1].GetFaceNormals()+
m_pTerrainQuads[ i * m_xSize + j+1].GetFaceNormals();
m_pTerrainQuads[i * m_xSize + j].SetCornerNormal( 2, Normalnw);

D3DXVECTOR3 Normalne = m_pTerrainQuads[i * m_xSize + j].GetFaceNormals() +
m_pTerrainQuads[i * m_xSize + j +1].GetFaceNormals()+
m_pTerrainQuads[(i+1) * m_xSize + j+1].GetFaceNormals()+
m_pTerrainQuads[(i+1) * m_xSize + j].GetFaceNormals();
m_pTerrainQuads[i * m_xSize + j].SetCornerNormal( 3, Normalnw);

}
}


HRESULT hr;
// V_RETURN(D3DXCreateTextureFromFile( pd3dDevice,sTexName, &m_pTex));
V_RETURN(pd3dDevice->CreateVertexBuffer( sizeof(CustomVertex) * 3000, D3DUSAGE_WRITEONLY,
CustomVertex::FVF, D3DPOOL_MANAGED,&m_pVB, NULL)
);

return S_OK;

}

HRESULT CTerrain::Render( LPDIRECT3DDEVICE9 pd3dDevice)
{
// Render Terrain Quads
if( m_bValid)
{
pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW);
pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILLMODE::D3DFILL_WIREFRAME);
pd3dDevice->SetFVF( CustomVertex::FVF);

D3DMATERIAL9 mtrl;
mtrl.Ambient = D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f);
mtrl.Diffuse = D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f);
pd3dDevice->SetMaterial( &mtrl);

// pd3dDevice->SetTexture( 0, m_pTex);

int Offset = 0;
for ( int i = 0; i < m_xSize; i++)
{
for ( int j = 0; j < m_ySize; j++)
{
// Render 3000 vertices a time

// copy the vertices into space where m_pVertices points
if(FAILED(m_pVB->Lock( 0,sizeof(CustomVertex), (void**)&m_pVertices, 0)))
return E_FAIL;
Offset = m_pTerrainQuads[i * m_xSize + j].RenderQuad( Offset, m_pVertices);
m_pVB->Unlock();

if ( Offset >= 2990)
{
pd3dDevice->SetFVF( CustomVertex::FVF);
pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(CustomVertex));
pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, Offset/3);
Offset = 0;
}
}
}
if ( Offset > 0 )
{
pd3dDevice->SetFVF( CustomVertex::FVF);
pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(CustomVertex));
pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, Offset/3);
Offset = 0;
}
}
return S_OK;
}

void CTerrain::Destroy()
{
SAFE_DELETE_ARRAY( m_pTerrainQuads);
SAFE_DELETE_ARRAY( m_pElevations);
SAFE_DELETE_ARRAY( m_pVertices);
SAFE_RELEASE(m_pVB);
SAFE_RELEASE(m_pTex);
}

Share this post


Link to post
Share on other sites

This topic is 3726 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this