Skip to main content
gamedev.net
🔒 Locked

Triangle Strip Question

Started by Programmer101 12 replies 1.8k views
Original Post
Programmer101
Programmer101
Okay so I have a program that is supposed to initialize direct3d and make a terrain from a RAW file. I am using triangle strips to do this. When I run the program nothing shows up and I am getting quite angry. BTW Happy new year to all! So here is my code(I know most of you probably don't want to read it all): also, how do you do the code boxes?
#include "dhGraphics.h"
#include <stdio.h>

IDirect3D9 *g_pD3D = NULL;
IDirect3DDevice9 *g_pD3DDevice = NULL;
IDirect3DVertexBuffer9 *pD3DVB;

//Vertex Data
typedef struct {
	float x,y,z;
	D3DCOLOR diffuse;
} sVertex;

const int VERTS = 257*257*2;

sVertex Verts[VERTS];

#define VertexFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE)

//Game Variables
float heightmap[257*257];

BOOL loadTerr()
{
	FILE *Terrain;
	Terrain = fopen("heightmap.raw","rb");
	if(Terrain == NULL)
		return FALSE;
	fread(heightmap, 257*257, 1, Terrain);
	fclose(Terrain);
	int z=0,x=0,i=0;
	for(z = 0; z < 257 - 1; ++z)
	{
		for (x = 0; x < 257; ++x)
		{
			float Height = heightmap[z * 257 + x];
			float nextHeight = heightmap[(z + 1)* 257 + x];

			Verts.x = (x - 257/2);
			Verts.y = Height;
			Verts.z = (z - 257/2);
			Verts.diffuse = D3DCOLOR_RGBA(0,150,0,255);

			i++;

			Verts.x = (x - 257/2);
			Verts.y = nextHeight;
			Verts.z = (z + 1 - 257/2);
			Verts.diffuse = D3DCOLOR_RGBA(0,150,0,255);
			
			i++;
		}
	}
	return TRUE;
}

BOOL InitVB()
{
	BYTE *Ptr;
	if(FAILED(g_pD3DDevice->CreateVertexBuffer(sizeof(sVertex)*VERTS,0,VertexFVF,D3DPOOL_MANAGED,&pD3DVB, NULL)))
		return FALSE;

	//Lock Vertex Buffer
	if(FAILED(pD3DVB->Lock(0, 0, (void**)&Ptr, 0)))
		return FALSE;
	
	//Copy local verts
	memcpy(Ptr, Verts, sizeof(Verts));

	//Unlock vertex buffer
	pD3DVB->Unlock();

	return TRUE;
}

BOOL InitDX(HWND hWnd)
{
	//Initialize DX
	if((g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL)
		return FALSE;
	
	D3DDISPLAYMODE d3ddm;
	//For Fullscreen
	/*
	d3ddm.Width = 800;
	d3ddm.Height = 600;
	d3ddm.RefreshRate = 0;
	d3ddm.Format = D3DFMT_A8R8G8B8;

	//Check if Display Mode exists
	if(FAILED(g_pD3D->CheckDeviceType(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,&d3ddm.Format,&d3ddm.Format, FALSE)))
		return FALSE;
	*/
	
	//For Windowed
	if(FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm)))
		return FALSE;

	D3DPRESENT_PARAMETERS d3dpp;

	ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));

	//For Windowed
	d3dpp.Windowed = TRUE;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.BackBufferFormat = d3ddm.Format;

	//Mutual
	d3dpp.BackBufferWidth = 800;
	d3dpp.BackBufferHeight = 600;

	if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dpp,&g_pD3DDevice)))
		return FALSE;
	
	if(loadTerr() == FALSE)
		return FALSE;
	
	InitVB();

	return TRUE;
}

BOOL Render()
{
	if(FAILED(g_pD3DDevice->BeginScene()))
		return FALSE;
	if(FAILED(g_pD3DDevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_RGBA(0,0,0,255), 1.0f, 0)))
		return FALSE;

	g_pD3DDevice->SetStreamSource(0, pD3DVB, 0, sizeof(sVertex));
	g_pD3DDevice->SetFVF(VertexFVF);
	g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,2,VERTS);

	if(FAILED(g_pD3DDevice->EndScene()))
		return FALSE;
	if(FAILED(g_pD3DDevice->Present(NULL,NULL,NULL,NULL)))
		return FALSE;
	return TRUE;
}

BOOL ShutDown()
{
	if( pD3DVB != NULL )        
        pD3DVB->Release();

    if( g_pD3DDevice != NULL ) 
        g_pD3DDevice->Release();

    if( g_pD3D != NULL )       
        g_pD3D->Release();
	return TRUE;
}

[Edited by - Programmer101 on January 1, 2007 3:29:18 PM]
ET3D
ET3D
Try the usual:

Run with debug runtime to see if there are errors.

Disable culling in case your triangles are in the wrong direction.

Try rendering something simpler to make sure you don't have a problem with your geometry.
DrunkenHyena
DrunkenHyena
Also, clear your background to something other than black. That way you can see the difference between rendering nothing and rendering blackness. If something does show up, then it is quite likely an issue with lighting.
Stay Casual,KenDrunken Hyena</FON
Xrystal
Xrystal
And to do the code blocks...

code and /code for small code blocks
source and /source for scrollable highlightable source code blocks

Of course inside [ and ] to get them to work.
Programmer101
Programmer101
How can I turn off backface culling?

Also, I made it do just a few triangles so now it works, but as z values change the depth fading does not occur, so if i put a triangle at z=1 it is the same size as one at z=0 yet it seems to cull any triangles past z=1. Is there a state or something that I have to set? Thanks.
Xrystal
Xrystal
Somewhere before you render the offending item place

g_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);


in your code.

If you do a help look up for CULLMODE it will show you the rest of the options.


For enabling the Depth Buffer try altering this line:
if(FAILED(g_pD3DDevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_RGBA(0,0,0,255), 1.0f, 0)))return FALSE;

to something like this:
if(FAILED(g_pD3DDevice->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,D3DCOLOR_RGBA(0,0,0,255), 1.0f, 0)))return FALSE;



The D3DCLEAR_ZBUFFER tells it to clear the depth buffer.

You could also add these renderstates too:

SetRenderState(D3DRS_ZWRITEENABLE, D3DZB_TRUE);SetRenderState(D3DRS_ZENABLE, TRUE);


Also, it looks like you are rendering technically in 2D mode as the perspective hasn't been set up.

D3DXMatrixPerspectiveFovLH(&m_mD3DProjection, PI/3, width/height,1.0f,1000.0f);m_pD3DDevice->SetTransform(D3DTS_PROJECTION,&m_mD3DProjection);


Something like that after you have created your device should help simulate the 3D effect.

oh also noticed the lack of some PresentParameters that enable depth drawing:

It might not be the ideal set of PresentParams but here's my set. Feel free to use to get you started.
	ZeroMemory(&m_pD3DParams, sizeof(m_pD3DParams));	m_pD3DParams.hDeviceWindow = m_hWnd;	m_pD3DParams.Windowed = m_bWindowed;	m_pD3DParams.SwapEffect = D3DSWAPEFFECT_DISCARD;	m_pD3DParams.BackBufferFormat = m_pD3DDisplayMode.Format;	m_pD3DParams.BackBufferCount = 1;	m_pD3DParams.BackBufferHeight = m_pD3DDisplayMode.Height;	m_pD3DParams.BackBufferWidth = m_pD3DDisplayMode.Width;	m_pD3DParams.EnableAutoDepthStencil = true;	m_pD3DParams.AutoDepthStencilFormat = D3DFMT_D24S8;	m_pD3DParams.MultiSampleType = D3DMULTISAMPLE_NONE;	m_pD3DParams.MultiSampleQuality = 0;	m_pD3DParams.Flags = 0;	if (!m_pD3DParams.Windowed)	{		m_pD3DParams.FullScreen_RefreshRateInHz = m_pD3DDisplayMode.RefreshRate;		m_pD3DParams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;	}



[Edited by - Xrystal on January 1, 2007 5:25:25 PM]
Programmer101
Programmer101
Thanks alot, that works for me except for the stencil present parameter. When I use EnableAutoDepthStencil and AutoDepthStencilFormat a whole bunch of weird lines appear on my polygons shown here and it does not draw the whole thing:

Xrystal
Xrystal
Hmm, not come across that one before. What does it look like when you set it to wireframe mode ?

The code to do that if you weren't aware is as follows: .. Just change the last value to the one you want to display.
SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);SetRenderState(D3DRS_FILLMODE,D3DFILL_SOLID);


Sometimes looking at the wireframe version will show you whats happening as it will draw lines from the different vertex points instead of creating a colored/textured plane.
sirob
sirob
You'll need to clear the Z-buffer every frame, along with the Render Target. Just add the D3DCLEAR_ZBUFFER flag to your Clear call.
Sirob Yes.» - status: Work-O-Rama.
Programmer101
Programmer101
Oh, I see. Thank you. When I tried using the code that Xrystal had posted earlier I tried clearing the z buffer before putting in the stencil params, so I deleted th D3DCLEAR_ZBUFFER and put in the stencil params which caused those funny lines, but together they work.

Does anyone know a good way to generate normals for a heightmap. Currently I am having them stick straight up, but I would like to have them be correct. This is the code I have for loading a heightmap:

BOOL loadTerr(){	FILE *Terrain;	Terrain = fopen("heightmap.raw","rb");	if(Terrain == NULL)		return FALSE;	fread(heightmap, 257*257, 1, Terrain);	fclose(Terrain);	int z=0,x=0,i=0;	for(z = 0; z < rows; z++)	{		for (x = 0; x < columns+1; x++)		{			float Height = heightmap[z * (rows + 1) + x];			float nextHeight = heightmap[(z + 1)* (columns+1) + x];			Verts.x = ((x - columns/2));			Verts.y = Height-0.2f;			Verts.z = ((z - rows/2));			Verts.nx = ((x - columns/2));			Verts.ny = Height;			Verts.nz = ((z - rows/2));			Verts.diffuse = D3DCOLOR_RGBA(0,150,0,255);			i++;			Verts.x = ((x - columns/2));			Verts.y = nextHeight-0.2f;			Verts.z = ((z - rows/2 + 1));			Verts.nx = ((x - columns/2));			Verts.ny = nextHeight;			Verts.nz = ((z - rows/2 + 1));			Verts.diffuse = D3DCOLOR_RGBA(0,150,0,255);						i++;		}	}	return TRUE;}


[Edited by - Programmer101 on January 2, 2007 8:16:11 AM]
Gagyi
Gagyi
If you have heightmap[x,z] height values, the normal should be like this:

normal[x,z].y=1;normal[x,z].x=heightmap[x-1,z]-heightmap[x+1,z];normal[x,z].z=heightmap[x,z-1]-heightmap[x,z+1];Normalize(normal[x,z]);


It has a proper deviation, but it is not neded here.
-----------------------------------"After you finish the first 90% of a project, you have to finish the other 90%." - Michael Abrashstickman.hu <=my game (please tell me your opinion about it)
Programmer101
Programmer101
Thanks, I'm currently using float nx,ny,nz as my normal coordinates, is there like a directx class that you were using for "normal[x,z]".
uncle albert
uncle albert
Hi guys,

I'm basically doing the same thing at the moment (rendering a heightfield from a RAW file using DX9), and I'm almost there with the basics of it, except that I seem to be getting a few artifacts, as can be seen in the screenshot below.



(I'm referring to the lines spanning from one side of the heightfield to the other.)

I would post code, but I was hoping it might be something obvious, like trying to draw too many tri strips or similar.

Thanks,

James

EDIT: In that screenshot, D3DRS_CULLMODE is set to whatever is default. When I set it to D3DCULL_NONE, you can see a line for every point in the Z axis of the heightfield.

RESOLVED: Was just calling DrawPrimitive once, which was "wrapping around" in order to draw one long tri strip. Now calling DrawPrimitive for each row (i.e. seperate tri strip for each row).

[Edited by - uncle albert on January 3, 2007 4:58:59 AM]
Xrystal
Xrystal
I remember getting something like that in my terrain block. I would get random lines starting at 0,0,0 and jump at all angles.

With the help of Programming an RTS Game with Direct3D and other terrain books currently not at hand to name I manged to set up a generic Heightmap and Patch class that holds the info for multiple terrain patches. But, if I recall correctly I was having problems keeping the height information in vectors. But that was when I was first learning how to use the vector container so when i next jump back on the terrain project I am sure it will fall together nicely.

As for height generation I've got a sequence of noise processes that randomizes the heights with the plan to make a heightmap generator tool that allows you to customize the heights at each point if they are 'not quite right'. Still in the early stages and really need the GUI project working to use with it first though :D

This is what I do anyway to generate a terrain:
	m_pHeightMap->SetMaxBounds(1800.0f,1800.0f); 	m_pHeightMap->SetMinBounds(-1800.0f,-1800.0f);	m_pHeightMap->SetPatchCount(18.0f,18.0f); 	m_pHeightMap->AddPatches(10.0f,10.0f); 


void CDXTHeightMap::AddPatches(float xCount, float zCount){	m_nVertCount = 0;	CDXTPoint minBounds;	CDXTPoint maxBounds;	m_pPatches.reserve(m_ptPatchCount.Z * m_ptPatchCount.X);	for (int z = 0;z<m_ptPatchCount.Z;z++)	{		for (int x = 0;x<m_ptPatchCount.X;x++)		{			CDXTPatch* p = new CDXTPatch(m_pD3DDevice);			int id = x + (z * m_ptPatchCount.X);			minBounds = m_ptMinBounds + (m_ptStepCount * CDXTPoint(x,z));			maxBounds = minBounds + m_ptStepCount;			p->SetPatchID(id);			p->SetMinBounds(minBounds.X,minBounds.Z);			p->SetMaxBounds(maxBounds.X,maxBounds.Z);			p->SetCellCount(xCount,zCount);			p->SetEffect("Ambient.fx","TerrainPatchC");//techniques[0]);			p->CreatePatch();			p->PlaceInWorld(0.0f,0.0f,0.0f);			m_nVertCount += p->GetVertexCount();			m_pPatches.push_back(p);			int PatchCount = m_pPatches.size();		}	}}bool CDXTPatch::CreatePatch(void){	int ic = GetIndexCount();	int vc = GetVertexCount();	m_pPrimitives->Initialise(ic,vc,false);	m_pPrimitives->HasPosition();	m_pPrimitives->CreateVertexDeclaration();	if (!m_pPrimitives->Finalise(true))	{		MessageBox(NULL,"Failed to Finalise Object","Error",MB_OK);		return false;	}	if (!GenerateVertices())	{		MessageBox(NULL,"Failed to Create Vertices", "Error",MB_OK);		return false;	}	if (!GenerateIndices())	{		MessageBox(NULL,"Failed to Create Indices", "Error",MB_OK);		return false;	}	return true;}bool CDXTPatch::GenerateVertices(void){	// Vertex Buffer	CUSTOMVERTEX* pVertices;	if (!m_pPrimitives->SimpleVBLock((void**)&pVertices))	{		pVertices = NULL;		return false;	}	// Set the start position	CDXTPoint ptPosition(m_ptMinBounds.X,m_ptMaxBounds.Z);	int count=0;	// Loop across and down	for (int z=0;z<m_ptVertCount.Z;z++)	{		ptPosition.X = m_ptMinBounds.X;		for (int x=0;x<m_ptVertCount.X;x++)		{			float height = 0.0f;//heights[x + z * (int)multi];			// Create the verts			pVertices[count].x = ptPosition.X;			pVertices[count].y = height;//0.0f;			pVertices[count].z = ptPosition.Z;			// Increment x across			ptPosition.X += m_ptStepCount.X;			count++;		}		// Increment Z down		ptPosition.Z -= m_ptStepCount.Z;	}	m_pPrimitives->SimpleVBUnlock();	pVertices = NULL;	m_nVertices = count;	return true;}bool CDXTPatch::GenerateIndices(void){	// Indices for Triangle	WORD* pIndices;	if (!m_pPrimitives->SimpleIBLock((void**)&pIndices))	{		pIndices = NULL;		return false;	}	int count=0;	int vIndex=0;	for (int z=0;z<m_ptCellCount.Z;z++)	{		for (int x=0;x<m_ptCellCount.X;x++)		{			// first triangle			pIndices[count++]=vIndex;			pIndices[count++]=vIndex+1;			pIndices[count++]=vIndex+m_ptVertCount.X;				// second triangle			pIndices[count++]=vIndex+m_ptVertCount.X;			pIndices[count++]=vIndex+1;			pIndices[count++]=vIndex+m_ptVertCount.X+1;			vIndex++;		}		vIndex++;	}	m_pPrimitives->SimpleIBUnlock();	pIndices = NULL;	m_nIndices = vIndex;	return true;}



Looking at it again though I can see that the code data is actually for tranglelists so would not work in your case anyway. Guess the book couldn't figure out a simple way for a triangle strip. Should really figure it out myself when I get round to it again.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.