Skip to main content
gamedev.net
🔒 Locked

Stack overflow (heightmaps)

Started by shakazed 13 replies 750+ views
Original Post
shakazed
shakazed
Hi! I´ve been working on a terrain thingy for a couple of weeks and it works quite fine. Problem is that it´s 128*128 and I want it bigger. Figuring 128*128 works fine witha same size heightmap (.raw file) I tried to convert the code to load a 1920*1920 heightmap. I only changed the numbers but now I get a stack overflow wgen trying ot load the hmap. Here´s some code.
//cGraphics header file


#include<windows.h>
#include<d3d9.h>
#include<d3dx9.h>
#include<stdio.h>
#include"CCamera.h"

#define CUSTOMVERTEX_FVF (D3DFVF_XYZ|D3DFVF_NORMAL)
#define DXERROR(function,type) if(FAILED(function)){MessageBox(NULL,type,"Error",MB_OK); return false;}

struct CUSTOMVERTEX 
{
	float x,y,z;
	D3DXVECTOR3 vecNormal;
};

class CGraphics
{
public:

	bool Initialize(HINSTANCE hInstance,HWND hWnd);    //Set it up

	bool Present(void);			   //Presents the scene

	bool LoadHeightMap(void);      //Loads and sets up the heightmap

	void Cleanup(void);			   //Release all resources

	void SetupMatrices(void);      //Handles cameras

	bool SetupLights(void);        //Adds some light

	void CalcTerrainNormals(void); //Calculates the normals of the goraud lighting

	CGraphics(void); //Constructor


private:

	IDirect3D9 *p_iD3D9;
	IDirect3DDevice9 *p_iD3DDevice9;
	IDirect3DIndexBuffer9 *p_iD3DIndexBuffer9;
	IDirect3DVertexBuffer9 *p_iD3DVertexBuffer9;
	CCamera cCamera;
	
};


bool CGraphics::Initialize(HINSTANCE hInstance,HWND hWnd)
{
	
	p_iD3D9 = Direct3DCreate9(D3D_SDK_VERSION);
	
	D3DPRESENT_PARAMETERS d3dpp;
	ZeroMemory(&d3dpp, sizeof(d3dpp));
	d3dpp.Windowed = TRUE;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
	d3dpp.EnableAutoDepthStencil = TRUE;
	d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

	DXERROR(p_iD3D9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING,
	&d3dpp, &p_iD3DDevice9), "Failed to create device");



	p_iD3DDevice9->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
	p_iD3DDevice9->SetRenderState(D3DRS_ZENABLE, TRUE);



	if(LoadHeightMap()==false) //Load the .raw file and setup vertices/indices

	{
		MessageBox(NULL, "Failed to load heightmap", "Error", MB_OK);
		return false;
	}

	//Initialize dinput camera

	if(cCamera.Initialize(hInstance,hWnd)==false)
	{
		MessageBox(NULL,"Error in camera initialization","Error",MB_OK);
		return false;
	}

	return true;
}

bool CGraphics::Present(void)
{
	
	//Get keyboard state

	if(cCamera.GetData()==false)
	{
		return false;
	}

	p_iD3DDevice9->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,255),1.0f,0);

	DXERROR(p_iD3DDevice9->BeginScene(),"Failed to begin scene rendering");
	SetupMatrices(); //Setup camera 

	SetupLights();


	// Set the location source of our vertex input stream

	DXERROR(p_iD3DDevice9->SetStreamSource( 0, p_iD3DVertexBuffer9,0, sizeof(CUSTOMVERTEX)),"Failed to set streamsource");
		
	// Set the location of our index information to our Index Buffer

	DXERROR(p_iD3DDevice9->SetIndices( p_iD3DIndexBuffer9 ),"Failed to set indices")
	
	DXERROR(p_iD3DDevice9->SetFVF(CUSTOMVERTEX_FVF),"Failed to set FVF");

	DXERROR(p_iD3DDevice9->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,
					   0,
					   0,
					   1920*1920,
					   0,
					   1919*1919*2), "Failed to draw indexed primitive");


	p_iD3DDevice9->EndScene();

	RECT rRect;
	rRect.left = 0;
	rRect.top  = 0;
	rRect.right = 480;
	rRect.bottom = 480;

	//Render only from and to the given rect

	DXERROR(p_iD3DDevice9->Present(&rRect,&rRect,NULL,NULL), "Failed to present scene")

	return true;
}

bool CGraphics::LoadHeightMap(void)
{


	FILE *pFile = NULL;

	unsigned char iHeightMapArray[1920*1920];; //All the y values


	pFile = fopen("Heightmaps\\hmap000.raw", "rb" );

	fread(&iHeightMapArray, 1, 1920*1920, pFile );
	fclose(pFile);
	/////////////////////////////////////////////////////////////////



	/////////////////////////////////////////////////////////////////

	CUSTOMVERTEX vertices[1920*1920];
	int dPosition = 0;
	for(int i = 0; i<1920; ++i)
	{
		dPosition = 0;
		for(int j = 0; j<1920; ++j)
		{
	
			vertices[1920*i+dPosition].x = (float)j;
			vertices[1920*i+dPosition].y = (float)iHeightMapArray[i*1919+j]/5;
			vertices[1920*i+dPosition].z = (float)i;
			
			//Calculate the normals for vertices

			if(i != 0 || i != 1919)//Check so not the first or last row are affected

			{
				if(dPosition != 0 || dPosition != 1919) //Check so the first and last vertex are not affected

				{
					//Get the vertex data for the left,right,up and down side vertices

					D3DXVECTOR3 vecRight;
					vecRight.x = vertices[128*i+dPosition+1].x;
					vecRight.y = vertices[128*i+dPosition+1].y;
					vecRight.z = vertices[128*i+dPosition+1].z;	
					
					D3DXVECTOR3 vecLeft;
					vecLeft.x = vertices[128*i+dPosition-1].x;
					vecLeft.y = vertices[128*i+dPosition-1].y;
					vecLeft.z = vertices[128*i+dPosition-1].z;
					
					D3DXVECTOR3 vecUp;
					vecUp.x = vertices[128*i+dPosition+128].x;
					vecUp.y = vertices[128*i+dPosition+128].y;
					vecUp.z = vertices[128*i+dPosition+128].z;

					D3DXVECTOR3 vecDown;
					vecDown.x = vertices[128*i+dPosition-128].x;
					vecDown.y = vertices[128*i+dPosition-128].y;
					vecDown.z = vertices[128*i+dPosition-128].z;

					D3DXVECTOR3 vecUpRightCross;
					D3DXVECTOR3 vecUpLeftCross;
					D3DXVECTOR3 vecDownRightCross;
					D3DXVECTOR3 vecDownLeftCross;

					D3DXVECTOR3 vecTempUpRightCross;
					D3DXVECTOR3 vecTempUpLeftCross;
					D3DXVECTOR3 vecTempDownRightCross;
					D3DXVECTOR3 vecTempDownLeftCross;

					//Add the vector data to get a cross product

					vecTempUpRightCross.x = vecUp.x*vecRight.x;
					vecTempUpRightCross.y = vecUp.y*vecRight.y;
					vecTempUpRightCross.z = vecUp.z*vecRight.z;

					vecTempDownRightCross.x = vecDown.x*vecRight.x;
					vecTempDownRightCross.y = vecDown.y*vecRight.y;
					vecTempDownRightCross.z = vecDown.z*vecRight.z;

					vecTempUpLeftCross.x = vecUp.x*vecLeft.x;
					vecTempUpLeftCross.y = vecUp.y*vecLeft.y;
					vecTempUpLeftCross.z = vecUp.z*vecLeft.z;

					vecTempDownLeftCross.x = vecDown.x*vecLeft.x;
					vecTempDownLeftCross.y = vecDown.y*vecLeft.y;
					vecTempDownLeftCross.z = vecDown.z*vecLeft.z;

					//Normalize the cross product

					D3DXVec3Normalize(&vecUpRightCross, &vecTempUpRightCross);
					D3DXVec3Normalize(&vecUpLeftCross, &vecTempUpLeftCross);
					D3DXVec3Normalize(&vecDownLeftCross, &vecTempDownLeftCross);
					D3DXVec3Normalize(&vecDownRightCross, &vecTempDownRightCross);

					//Fill the temp vector with the normal

					D3DXVECTOR3 vecTemp;
					D3DXVECTOR3 vecFinal;
					vecTemp.x = vecUpRightCross.x+vecUpLeftCross.x+vecDownRightCross.x+vecDownLeftCross.x;
					vecTemp.y = vecUpRightCross.y+vecUpLeftCross.y+vecDownRightCross.y+vecDownLeftCross.y;
					vecTemp.z = vecUpRightCross.z+vecUpLeftCross.z+vecDownRightCross.z+vecDownLeftCross.z;

					//And normalize to the final vector

					D3DXVec3Normalize(&vecFinal, &vecTemp);
					
					//Add normal data to the vertex

					vertices[1920*i+dPosition].vecNormal.x = vecFinal.x;
					vertices[1920*i+dPosition].vecNormal.y = vecFinal.y;
					vertices[1920*i+dPosition].vecNormal.z = vecFinal.z;
				}
			}

			dPosition++;
		}
	}


	DXERROR(p_iD3DDevice9->CreateVertexBuffer((1920*1920)*sizeof(CUSTOMVERTEX),
		0, CUSTOMVERTEX_FVF, D3DPOOL_DEFAULT,&p_iD3DVertexBuffer9,NULL), "Failed to create vertex buffer");
	
	
	
	VOID* pVertices;
	DXERROR(p_iD3DVertexBuffer9->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ),
		"Failed to lock vertexbuffer");
		

	memcpy( pVertices, vertices, sizeof(vertices) );
	DXERROR(p_iD3DVertexBuffer9->Unlock(), "Failed to unlock vertex buffer");


	
	
	//Now set up the index buffer


	WORD dIndices[1919*1919*6];
	ZeroMemory(&dIndices, sizeof(dIndices));

	long dPos = 0;

	for(int y = 0;y < 1919;++y)
	{
		dPos = 0;

		for(int x = 0;x < 1919;++x)
		{
			dIndices[1919*y*6+dPos] = x + y * (1919 + 1);	
			dPos++; //Go next

			dIndices[1919*y*6+dPos]= x + 1 + y * (1919 + 1);					//v2

			dPos++; //Go next

			dIndices[1919*y*6+dPos] = x + 1 + (y + 1) * (1919 + 1);				//v4

			dPos++; //Go next

			dIndices[1919*y*6+dPos] = x + y * (1919 + 1);					//v1

			dPos++; //Go next

			dIndices[1919*y*6+dPos] = x + 1 + (y + 1) * (1919 + 1);				//v4

			dPos++; //Go next

			dIndices[1919*y*6+dPos] = x + (y + 1) * (1919 + 1);					//v3

			dPos++;
		}
	}

	DXERROR(p_iD3DDevice9->CreateIndexBuffer((1919*1919*2*3)*sizeof(WORD),0,D3DFMT_INDEX32,D3DPOOL_MANAGED,
		&p_iD3DIndexBuffer9,NULL), "Failed to create index buffer");


	VOID *p_vData;
	DXERROR(p_iD3DIndexBuffer9->Lock(0,sizeof(dIndices),(VOID**)&p_vData,0),
		"Failed to lock index buffer");

	memcpy(p_vData,dIndices,sizeof(dIndices));					//copy data

	DXERROR(p_iD3DIndexBuffer9->Unlock(), "Failed to unlock indexbuffer");

	//Set all the pointer to NULL

	p_vData = NULL;
	pFile= NULL;
	pVertices = NULL;
	return true;
}

CGraphics::CGraphics(void)
{
	p_iD3D9 = NULL;
	p_iD3DDevice9= NULL;
	p_iD3DIndexBuffer9= NULL;
	p_iD3DVertexBuffer9= NULL;


}

void CGraphics::Cleanup(void)
{
	cCamera.Release();

	if(p_iD3DIndexBuffer9 != NULL)
	{
		p_iD3DIndexBuffer9->Release();
		p_iD3DIndexBuffer9 = NULL;
	}

	if(p_iD3DVertexBuffer9 != NULL)
	{
		p_iD3DVertexBuffer9->Release();
		p_iD3DVertexBuffer9 = NULL;
	}

	if(p_iD3DDevice9 != NULL)
	{
		p_iD3DDevice9->Release();
		p_iD3DDevice9 = NULL;
	}

	if(p_iD3D9 != NULL)
	{
		p_iD3D9->Release();
		p_iD3D9 = NULL;
	}
		

}





void CGraphics::SetupMatrices(void)
{
    D3DXMATRIX matWorld;
    D3DXMatrixIdentity( &matWorld );	
	p_iD3DDevice9->SetTransform( D3DTS_WORLD, &matWorld );

	//Set up the view. First struct is eye point, next is lookat point

	//third is the direction of up, which here is set to the y axis.

	D3DXVECTOR3 vecPos;
	D3DXVECTOR3 vecLookAt;

	cCamera.FillVectors(&vecPos,&vecLookAt);

	D3DXMATRIX matView;
   	D3DXMatrixLookAtLH( &matView,
			    &vecPos,
			    &vecLookAt,
			    &D3DXVECTOR3(0.0f,  1.0f, 0.0f ) );

	p_iD3DDevice9->SetTransform( D3DTS_VIEW, &matView );


	//Set up the projection so that I get a far clip at 100 and near

	//at 1. 

	D3DXMATRIX matProj;
   	D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 1000.0f );
   	p_iD3DDevice9->SetTransform( D3DTS_PROJECTION, &matProj );
	
}

bool CGraphics::SetupLights(void)
{
	D3DMATERIAL9 mtrlTerrain;

	ZeroMemory(&mtrlTerrain, sizeof(mtrlTerrain));
	
	mtrlTerrain.Diffuse.r = mtrlTerrain.Ambient.r = 0.0f;
	mtrlTerrain.Diffuse.g = mtrlTerrain.Ambient.g = 1.0f;
	mtrlTerrain.Diffuse.b = mtrlTerrain.Ambient.b = 0.0f;
	mtrlTerrain.Diffuse.a = mtrlTerrain.Ambient.a = 1.0f;
	
	DXERROR(p_iD3DDevice9->SetMaterial(&mtrlTerrain),"Failed to set material"); //Set the light


	D3DXVECTOR3 vecLightDir; //Direction of the light 

	vecLightDir.x = -450.0f;
	vecLightDir.y = -1.0f;
	vecLightDir.z = -200.0f;

	D3DLIGHT9 lghLight;
	ZeroMemory(&lghLight, sizeof(lghLight));
	lghLight.Type = D3DLIGHT_DIRECTIONAL;

	//Diffuse light color

	lghLight.Diffuse.r = 1.0f;
	lghLight.Diffuse.g = 1.0f;
	lghLight.Diffuse.b = 1.0f;
	
	//Normalize the direction vector

	D3DXVec3Normalize((D3DXVECTOR3*)&lghLight.Direction, &vecLightDir);
	
	lghLight.Range = 1000.0f; //Wont affect directional lights

	
	DXERROR(p_iD3DDevice9->SetLight(0,&lghLight),"Failed tp set lights"); //Use this light

	DXERROR(p_iD3DDevice9->LightEnable(0,TRUE),"Failed to enable light");
	
	p_iD3DDevice9->SetRenderState(D3DRS_LIGHTING,TRUE);
	p_iD3DDevice9->SetRenderState(D3DRS_AMBIENT,0x00202020);
	p_iD3DDevice9->SetRenderState(D3DRS_LIGHTING,TRUE);
	p_iD3DDevice9->SetRenderState(D3DRS_AMBIENT,0x00202020);
	return true;
}
This is the class that handles graphics. Gotta go to work so I can´t check it out at the moment. If anyone would notice something strange with the code, please reply. Oh and ignore those 128:s at the normals calc. I changed them but it didn´t help
Bad Monkey Productions
Prosper/LOADED
Prosper/LOADED
You should use dynamic memory allocation instead of creating your array on the stack. Use a std::vector or the new operator.

PS : When you post some code, please only put the relevant part, not the whole file, it''s easier to spot the problem this way.
joanusdmentia
joanusdmentia
unsigned char iHeightMapArray[1920*1920];

That''s about 3.6MB on the stack. Instead allocate it on the heap with

unsigned char *iHeightMapArray = new unsigned char[1920*1920];

don''t forget to delete it when you''re finished though
"Voilà! In view, a humble vaudevillian veteran, cast vicariously as both victim and villain by the vicissitudes of Fate. This visage, no mere veneer of vanity, is a vestige of the vox populi, now vacant, vanished. However, this valorous visitation of a bygone vexation stands vivified, and has vowed to vanquish these venal and virulent vermin vanguarding vice and vouchsafing the violently vicious and voracious violation of volition. The nly verdict is vengeance; a vendett o
billybob
billybob
the vertices too, not just the heightmap.
shakazed
shakazed
Atleast got it down to a access violation at "vecDown.x = p_sVertexPtr[1920*i+dPosition-1920].x;"
Question: Why is it recommended to use the heap instead of the stack?

[edited by - shakazed on July 12, 2003 1:07:11 PM]
LessBread
LessBread
The default stack size is 1 Mb, the heap is good for upto 16 Mb. Beyond that you''ll need to use the "Virtual" family of allocation functions and handle carving up the memory yourself.

The stack is where a program "runs" so to speak. The stack is where function arguments are placed along with local function variables. And each thread has it''s own stack - in contrast with the heap which belongs to the entire process.
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
shakazed
shakazed
Hmm, get access violation at "memcpy(p_Indices,p_wIndexPtr,sizeof(p_wIndexPtr)*(1919*1919*3*2))" Now instead. Is this the right way to memcpy using p_wIndexPtr as a pointer to new? Should be since it works on my vertexbuffer.
LessBread
LessBread
Access violation indicates that one of those parameters is bad. Have you allocated enough memory for the receiving parameter - ie p_Indices?
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
billybob
billybob
quote:
Original post by shakazed
Hmm, get access violation at "memcpy(p_Indices,p_wIndexPtr,sizeof(p_wIndexPtr )*(1919*1919*3*2))" Now instead. Is this the right way to memcpy using p_wIndexPtr as a pointer to new? Should be since it works on my vertexbuffer.

the size of a pointer is 4. your indices are 2, you should either use sizeof(p_wIndexPtr[0]) or sizeof(WORD). or if you are lazy, delete the 2 off the end of that.

billybob
billybob
also, you create the index buffer with D3DFMT_INDEX32, but have an array of WORDs as your indices. either use DWORDs, or D3DFMT_INDEX16. with 1920x1920 (you are insane, use some LOD for god sakes!), you''ll need INDEX32.
shakazed
shakazed
Fixed the problem, turned out that I tried to copy to much to the index buffer.

[edited by - shakazed on July 14, 2003 8:16:36 AM]

Topic Locked

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

Sign in to reply to this topic.