Terrain generation using heightmaps

Discuss the development of software, tools, libraries and anything else that helps make ps2dev happen.

Moderators: cheriff, Herben

Post Reply
shamus88
Posts: 2
Joined: Thu Nov 27, 2008 7:13 am

Terrain generation using heightmaps

Post by shamus88 »

Hi all!

I am new here so please forgive me if this is in the wrong forum.

I have recently begun to learn game programming on the ps2 linux devkit. I am working based on a framework written by Henry Fortuna.

However, I am wondering if anyone had any experience of expanding the framework to read heightmap information from RAW files and render it? I can currently generate a flat trianglestrip patch which I can stretch a texture over it. This is handle by a terrain class in terrain.cpp. I am unsure of how to modify this to read in information from RAW files and then to pack the necessary y-axis information into the VU.

I hope that someone have any experience here in generating a heightmap in PS2 and could lend me a helping hand in this project.

I can link/provide the necessary framework files/code if needed.

Thanks in advance!
shamus88
Posts: 2
Joined: Thu Nov 27, 2008 7:13 am

Re: Terrain generation using heightmaps

Post by shamus88 »

Hmmm, noone at all? :(

I can draw a flat terrain consisting of triangle strips zig zagging from left to right , producing a flat patch. But any attempts at modifying the code to accept data from RAW files made the PS2 crash so far. Here is the relevant part of the code I hope someone could help me with :

Code: Select all

void CTerrain::LoadTerrainData(void)
{
	// Get the address that we can call to later.
	m_iStaticAddr = VIFStaticDMA.GetPointer();

	VIFStaticDMA.Add32(FLUSH);			// Make sure VU1 isn't busy
	VIFStaticDMA.Add32(STCYCL(1,1));	// Unpack linearly, i.e. don't skip any spaces
	VIFStaticDMA.Add32(BASE(32));		// The double buffers start at VU1 address 16 (giving us 16 QW to store data that won't change)
	VIFStaticDMA.Add32(OFFSET(496));	// The size of each buffer.

	VIFStaticDMA.AddUnpack(V4_32, 0, 1);	// Unpack 8QW of data that won't change
	VIFStaticDMA.AddVector(Vector4(2048, 2048, (0xFFFFFF / 32.0f), 1));	// 0: The scales

	// Set the PRIM field here. This may look like it's for convenience, but actually it's the only
	// way we can do it. If we set this in the GIFTag it would reset the strip every buffer.
	// As we want one huge strip, we can't use the prim setting capabilites of the GIFTag.
	VIFStaticDMA.StartDirect();
	VIFStaticDMA.StartAD();
	VIFStaticDMA.AddAD(PRIM_SET(GS_TRISTRIP, 1, 1, 0, 0, 0, 0, 0, 0), PRIM);
	VIFStaticDMA.EndAD();
	VIFStaticDMA.EndDirect();
	

	// The verts are 3QW each, and the 504QW is split in half. Therefore we have 252QW for each buffer.
	// Each buffer also has 2QW of info (GIFTag + Numverts), so we can process 83 vertices (249QW)
	// in each buffer.
	int iNumVertsPerChunk = 82;

	// The number of triangles in each dimension.
	int iSizeX = 256;
	int iSizeY = 256;

	int iNumVerts = (iSizeX * 2) * (iSizeY - 1);

	int iX = 0, iY = 0;
	int bBottomRow = 0;
	bool bFirst = true;

	while(iNumVerts > 0)
	{
		int iVertsThisChunk;

		if(iNumVerts > iNumVertsPerChunk)
		{
			iVertsThisChunk = iNumVertsPerChunk;
			iNumVerts -= iVertsThisChunk;
		}
		else
		{
			iVertsThisChunk = iNumVerts;
			iNumVerts -= iVertsThisChunk;
		}

		VIFStaticDMA.AddUnpack(V4_32, 0, iVertsThisChunk * 3 + 2, 1);
		VIFStaticDMA.Add128(iVertsThisChunk * 3);
		VIFStaticDMA.Add128(
			GS_GIFTAG_BATCH(iVertsThisChunk,
					1, 0, 0, GIF_FLG_PACKED,
					GS_BATCH_3(GIF_REG_ST, GIF_REG_RGBAQ, GIF_REG_XYZ2)));

		// Zigzag from left to right across the patch making a huge triangle strip.
		//
		//	0	   	2		4		6
		//  |     / |     / |     / |
  		//  |   /   |   /   |   /   |
		//	1 /		3 /		5 /		7 etc.
		//
		for&#40;int iVert = 0; iVert < iVertsThisChunk; iVert++&#41;
		&#123;
			float fX = &#40;float&#41;iX;
			float fY = &#40;float&#41;&#40;iY + bBottomRow&#41;;

			// Disable the drawing kick when we move to the next row, so that we don't get a huge
			// polygon going across the patch.
			int iDontDraw = &#40;iX == 0&#41; ? 1 &#58; 0;

			// Alternate between the current row and the one below.
			iX += bBottomRow;
			bBottomRow ^= 1;

			// If we have reached the end, start again on the next row.
			if&#40;iX == iSizeX&#41;
			&#123;
				iX = 0;
				bBottomRow = 0;
				iY += 1;
			&#125;

			// Add a huge number of vertices 
			VIFStaticDMA.AddVector&#40;Vector4&#40;fX / iSizeX, fY / iSizeY, 1, *&#40;&#40;float *&#41;&iDontDraw&#41;&#41;&#41;;	// Tex coords + in W, a flag to set ADC or not.
			VIFStaticDMA.AddVector&#40;Vector4&#40;0, 1, 0, 0&#41;&#41;;											// Normal
			VIFStaticDMA.AddVector&#40;Vector4&#40;&#40;fX - &#40;iSizeX / 2&#41;&#41;, 0, &#40;fY - &#40;iSizeY / 2&#41;&#41;, 1&#41;&#41;;		// Position
		&#125;

		if&#40;bFirst&#41;
		&#123;
			bFirst = false;
			// If this is the first buffer then run the VU code from address 0 so that the initialisation
			// VU code is ran.
			VIFStaticDMA.Add32&#40;MSCALL&#40;0&#41;&#41;;
		&#125;
		else
		&#123;
			// For multiple times MSCNT means to continue where the VU code finished last time at the --cont.
			VIFStaticDMA.Add32&#40;MSCNT&#41;;
		&#125;

		// Notice that due to the quad buffer setup we don't need to flush here because we can upload, process, and render
		// all in parallel now. &#40;the XGKick in the vector code will flush to make sure that we don't get ahead of ourselves&#41;
	&#125;

	VIFStaticDMA.Add32&#40;FLUSH&#41;;
	VIFStaticDMA.DMARet&#40;&#41;;
	
	
	
	
&#125;
Thanks.
Post Reply