Sign in to follow this  
m4gnus

Drawing a Grid(Terrainlike)

Recommended Posts

m4gnus    240
Hi Finally the Inputsystem for my engine works so now i just want to render a simple grid with an indexed Trianglelist...I tried to keep everything as clear as possible so i first wrote a basemsh class which just contains an Index-,a Vertexbuffer and a DWORD for the FVF...every class that will be renders should be a child of this class so i thought i'll make a very basic terrain class which just creates a grid of variable size with a variable number of subdivions... but something is worng with it..it definitly has something to do with the creation of the Vertex and Indexbuffer because if i fill 'em manually it works fine... My terrain Class:
#include "stdafx.h"
#include ".\terrain.h"
#include "ngEngine.h"

Terrain::Terrain(void)
{
FVF=D3DFVF_XYZ|D3DFVF_DIFFUSE;
}

Terrain::~Terrain(void)
{
}

void Terrain::Create(ngEngine *engine,D3DXVECTOR3 StartPoint,float xSize,float zSize,int xRes,int zRes)
{
	m_pEngine=engine;
	float RowHeight=zSize/zRes;
	float ColWidth=xSize/xRes;
	CreateVertices(StartPoint,RowHeight,ColWidth,xRes,zRes);
	CreateIndices(xRes,zRes);
	ConstructBuffers();

}
void Terrain::CreateVertices(D3DXVECTOR3 StartPoint,float RowHeight,float ColWidth,int xCount,int zCount) 
{
	for(int j=0;j<=zCount;j++)   //<--for every Row do:
	{
		for(int i=0;i<=xCount;i++) //<--for every Vert do:
		{
			TerrainVert Vertex;
			Vertex.x=StartPoint.x+i*ColWidth;
			Vertex.y=StartPoint.y;            //<---Terrain Height
			Vertex.z=StartPoint.z+j*RowHeight;
			Vertex.color=0xff00ff00;
			Verts.push_back(Vertex);


		}
	}


}

void Terrain::CreateIndices(int xRes, int yRes) 
{
for(int j=0;j<=yRes-1;j++) //<--For Every Row do:
{
	for(int i=0;i<=xRes-1;i++) //<--For Every QUAD(!) do:
	{
		int Row=j*xRes;
		//First Triangle
		Indices.push_back(xRes*j+i+Row);
		Indices.push_back(i+Row);
		Indices.push_back(i+Row+1);

		//Indices.push_back(xRes*j+i+1+Row);
		//Second Triangle
		Indices.push_back(i+Row);
		Indices.push_back(i+1+Row);
		Indices.push_back(xRes*j+i+1+Row);
	}

}

}

void Terrain::ConstructBuffers() 
{

//Create VertexBuffer:

	if( FAILED( m_pEngine->g_pD3DDevice->CreateVertexBuffer(Verts.size()*sizeof(std::vector<TerrainVert>::value_type),
                                                       0,
                                                       FVF,
                                                       D3DPOOL_DEFAULT,
                                                       &pVBuffer,   //<---inherited from BaseMesh
                                                       NULL ) ) )
    {
        MessageBox(0,"Fetter Error1!","Error",0);
        PostQuitMessage(1);
    }
VOID *pVData;
pVBuffer->Lock(0,sizeof(std::vector<TerrainVert>::value_type),(void**)&pVData,0);	//lock buffer 
std::vector<TerrainVert>::pointer Vptr = &Verts[0];
memcpy(pVData,Vptr,Verts.size()*sizeof(std::vector<TerrainVert>::value_type));						//copy data to buffer
pVBuffer->Unlock();	

//Create IndexBuffer:
if(FAILED(m_pEngine->g_pD3DDevice->CreateIndexBuffer(Indices.size()*sizeof(std::vector<short>::value_type),D3DUSAGE_WRITEONLY,D3DFMT_INDEX16,D3DPOOL_MANAGED,&pIBuffer,NULL))) 
{
	MessageBox(0,"Fetter Error2!","Error",0);
	PostQuitMessage(1);
}

VOID *pIData;
pIBuffer->Lock(0,sizeof(std::vector<short>::value_type),(void**)&pIData,0);	//lock buffer 
std::vector<short>::pointer Iptr = &Indices[0];
memcpy(pIData,Iptr,Indices.size()*sizeof(std::vector<short>::value_type));	//copy data to buffer
pIBuffer->Unlock();	
}

void Terrain::render() 
{
	m_pEngine->g_pD3DDevice->SetFVF(FVF); //<---inherited from BaseMesh
	m_pEngine->g_pD3DDevice->SetStreamSource(0,pVBuffer,0,sizeof(std::vector<TerrainVert>::value_type));
	m_pEngine->g_pD3DDevice->SetIndices(pIBuffer);
	m_pEngine->g_pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,Verts.size(),0,(xDivs-1)*(zDivs-1)*2);

}

regards, m4gnus

Share this post


Link to post
Share on other sites
Kippesoep    892
It would help if you posted the actual problem, too. Does it render nothing? Does it crash? Do you get an error message?

Also, whatever the problem:
- use the DirectX Debug runtime
- turn the Debug Ouput Level up to full
- look at the debug spew

Share this post


Link to post
Share on other sites
Kippesoep    892
Assuming the matrices are correct (considering your said it works if you fill the buffers manually): I don't see any set up of xDivs and zDivs in your code. Perhaps these are 0?

Share this post


Link to post
Share on other sites
Kippesoep    892
Never mind that, you're creating degenerate triangles in your index buffer. Take a look at the contents of your index buffer.

You want something like:

for (int j = 0; j < yRes; ++j)
{
for (int i = 0; i < xRes; ++i)
{
int Row = j * xRes;
//First Triangle
Indices.push_back(Row + i);
Indices.push_back(Row + i + 1);
Indices.push_back(Row + i + xRes);

//Second Triangle
Indices.push_back(Row + i + 1);
Indices.push_back(Row + i + 1 + xRes);
Indices.push_back(Row + i + xRes);
}
}


Share this post


Link to post
Share on other sites
m4gnus    240
ok thx i was also thinking it is a mistake like this but i calculated the indices of some traingle on paper and it seemed alright... i too tired to fix it now so i'll post tomorrow if it has helped..

regards,
m4gnus

Share this post


Link to post
Share on other sites
m4gnus    240
Ok it finally draws something but just 1 single trinagle... the rest of the terrain is missing...

regards,
m4gnus

Share this post


Link to post
Share on other sites
Kippesoep    892
That brings me back to the former question: how are xDivs and zDivs set up?
Set through your program with the debugger and check the debug spew.

Share this post


Link to post
Share on other sites
m4gnus    240
what do you mean by set up? they are both set to 4 in my main cpp..
do you really think a debugger can help me here? i would use a debugger if i had a runtime error

regards,
m4gnus

Share this post


Link to post
Share on other sites
m4gnus    240
ok the error has to be in the vertex creation because if i create them by hand for a grid with xRes=2 and zRes=2 (a simple quad) and let the CreateIndices function create the indices everything works fine!

regards,
m4gnus

Share this post


Link to post
Share on other sites
Kippesoep    892
By "set up" I mean "given a value".

That's the thing about the debugger: you can inspect the value of anything in memory. You'd be able to see what the coordinates are of the vectors being generated. What you have is a runtime error. Non-fatal, but a runtime error nonetheless.

Another thing you may want to check out: you're only locking one vertex in ConstructBuffers:

pVBuffer->Lock(0,sizeof(std::vector<TerrainVert>::value_type),&pVData,0);


You probably want to lock the entire buffer:

pVBuffer->Lock(0,0,&pVData,0);

Share this post


Link to post
Share on other sites
m4gnus    240
oops..thx i fixed that but my prob is still there and i don't really know why this:

for(int j=0;j<=zCount;j++) //<--for every Row do:
{
for(int i=0;i<=xCount;i++) //<--for every Vert do:
{
TerrainVert Vertex;
Vertex.x=StartPoint.x+i*ColWidth;
Vertex.y=StartPoint.y; //<---Terrain Height
Vertex.z=StartPoint.z+j*RowHeight;
Vertex.color=0xff00ff00;
Verts.push_back(Vertex);


}
}



does something different than:

TerrainVert vertex;
vertex.x=0.0f;
vertex.y=-10.0f;
vertex.z=100.0f;
vertex.color=0xff00ff00;
TerrainVert vertex2;
vertex2.x=400.0f;
vertex2.y=-10.0f;
vertex2.z=100.0f;
vertex2.color=0xff00ff00;
TerrainVert vertex3;
vertex3.x=0.0f;
vertex3.y=-10.0f;
vertex3.z=-300.0f;
vertex3.color=0xff0000ff;
TerrainVert vertex4;
vertex4.x=400.0f;
vertex4.y=-10.0f;
vertex4.z=-300.0f;
vertex4.color=0xffff0000;

Verts.push_back(vertex);
Verts.push_back(vertex2);
Verts.push_back(vertex3);
Verts.push_back(vertex4);



if StartPoint is set to 0,-10,100, xSize and zSize to 400 and xRes+zRes to 2...if i do it by hand it create a large wuad like i want but the double loop just create 1 strange triangle. Can somebody tell me what's the difference betweem these too?


regards,
m4gnus

Share this post


Link to post
Share on other sites
Kippesoep    892
It does something different because that's what you're telling it to do. To get those 4 vertices, you'd have to set xSize to 400, zSize to -400 (negative!!), xRes and zRes to 1.

It's probably the negative zSize that is causing the problem. If you want z to go along the negative axis, but specify a positive zSive, all your triangles are reversed and will be backface-culled.

Share this post


Link to post
Share on other sites
m4gnus    240
no backface culling is turned off...and are you sure that i have to set xRes+zRes to 1? these 2 values are not the number of quad-columns(/rows) but the number of vertex-columns(/rows)

btw it would it help if i post a screenshot like it should be(with manual filled vertexbuffer) and a screenshot with that strange triangle when generating the vertices.

if i change zRes to -zRes it draws nothing...

regards,
m4gnus

Share this post


Link to post
Share on other sites
Kippesoep    892
The numbers I gave you are the way to generate the four vertices you created manually. Step through it with the debugger and you'll see.

BTW, instead of xDivs and zDivs, I meant to use those values for xRes and zRes (why do you have two different variables refering to the same concept with slightly different semantics without any good link in the class that uses them?).

Share this post


Link to post
Share on other sites
m4gnus    240
i mean that for a quad you have to use xRes,zRes=2 because these values are the vertices per row/column not the quads per row/column and because a simple quad consists of 4 vertices(2 in 1 row, 2 rows) i need to set xRes,zRes to 2. if i would set 'em to 1 i would have a point...i know that you would ussually expect it to be the number of quads per row, so i'll change it as soon as everything works so far...

btw i changed xDivs,zDivs to xRes,zRes now...

Share this post


Link to post
Share on other sites
Kippesoep    892
In the code you gave, to get one quad, you need to set xDivs and zDivs to 2, and xRes and yRes to 1. (Always: xDivs = xRes + 1; zDivs = zRes + 1;). Again, in the code shown, there is nothing that shows where xDivs and zDivs come from. It is not set anywhere, so it's likely to be a global variable. Bad idea to use global variables like that inside your class. Basically: get rid of that. What I'd expect to see (and recommend you do) is something like:


void Terrain::Create (ngEngine *engine, D3DXVECTOR3 StartPoint, float xSize, float zSize, int xRes, int zRes)
{
//Store values
m_pEngine = engine;
m_xRes = xRes;
m_zRes = zRes;

//Create vertices
CreateVertices (StartPoint, xSize/m_xRes, zSize/m_zRes);

//Create indices
CreateIndices ();
}

void Terrain::CreateVertices (D3DXVECTOR3 StartPoint, float RowHeight, float ColWidth)
{
for (int j = 0; j <= m_zRes; ++j)
{
for (int i = 0; i <= m_xRes; ++i)
{
TerrainVert Vertex;
Vertex.x = StartPoint.x + i * ColWidth;
Vertex.y = StartPoint.y;
Vertex.z = StartPoint.z + j * RowHeight;
Vertex.color = 0xDD00DD00;
Verts.push_back (Vertex);
}
}
}

void Terrain::CreateIndices ()
{
for (int j = 0; j < m_zRes; ++j)
{
for (int i = 0; i < m_xRes; ++i)
{
/* ... */
}
}
}

void Terrain::render()
{
m_pEngine->g_pD3DDevice->DrawIndexedPrimitive (D3DPT_TRIANGLELIST, 0, 0, Verts.size (), 0, m_zRes * m_xRes * 2);
}



This places the terrain resolution in the class, where it belongs, and doesn't cause the confusion.

If the numbers I gave you don't work, then something is wrong elsewhere. They will generate the exact same vertices you listed manually. Let me spell out the program flow for you:


terrain->Create (g_Engine, D3DXVECTOR3 (0, -10, 100), 400, -400, 1, 1);

//In terrain::Create
float RowHeight=-400/*zSize/zRes*/;
float ColWidth=400/*xSize/xRes*/;
CreateVertices(D3DXVECTOR3 (0, -10, 100), -400, 400, 1, 1);

//In CreateVertices
/* j = 0, zCount == 1 */
/* i = 0; xCount == 1 */
Vertex.x = 0; //(StartPoint.x+i*ColWidth) = 0 + 0 * 400 = 0
Vertex.y = -10;
Vertex.z = 100; //(StartPoint.z+j*RowHeight) = 100 + 0 * -400 = 100

/* j = 0, zCount == 1 */
/* i = 1; xCount == 1 */
Vertex.x = 400; //(StartPoint.x+i*ColWidth) = 0 + 1 * 400 = 400
Vertex.y = -10;
Vertex.z = 100; //(StartPoint.z+j*RowHeight) = 100 + 0 * -400 = 100

/* j = 1, zCount == 1 */
/* i = 0; xCount == 1 */
Vertex.x = 0; //(StartPoint.x+i*ColWidth) = 0 + 0 * 400 = 0
Vertex.y = -10;
Vertex.z = -300; //(StartPoint.z+j*RowHeight) = 100 + 1 * -400 = -300

/* j = 1, zCount == 1 */
/* i = 1; xCount == 1 */
Vertex.x = 400; //(StartPoint.x+i*ColWidth) = 0 + 1 * 400 = 400
Vertex.y = -10;
Vertex.z = -300; //(StartPoint.z+j*RowHeight) = 100 + 1 * -400 = -300



So, you get (0,-10,100) (400,-10,100) (0,-10,300) (400,-10,-300), which is exactly what you wanted.

Share this post


Link to post
Share on other sites
m4gnus    240
everything works fine now...the xRes and zRes variables now really are the fertex rows+columns...just had to use for(int i=0;i<xCount;i++) instead of for(int i=0;i<=xCount;i++)

thank you

Edit: oops it only works for xRes,zRes=2 but if i set it to higher values one quad is missing..

regards,
m4gnus

Share this post


Link to post
Share on other sites

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