Sign in to follow this  

[NEWBIE] Generating terrain in PS2

This topic is 3300 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

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 (sps2). 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. Below is an excerpt from terrain.cpp which generates a patch of flat terrain. I wonder if it is possible to modify it to generate terrain from a RAW heightmap instead? Have been playing around with the code but only getting crashes so far. Any help appreciated! Thanks in advance!
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(int iVert = 0; iVert < iVertsThisChunk; iVert++)
		{
			float fX = (float)iX;
			float fY = (float)(iY + bBottomRow);

			// 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 = (iX == 0) ? 1 : 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(iX == iSizeX)
			{
				iX = 0;
				bBottomRow = 0;
				iY += 1;
			}

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

		if(bFirst)
		{
			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(MSCALL(0));
		}
		else
		{
			// For multiple times MSCNT means to continue where the VU code finished last time at the --cont.
			VIFStaticDMA.Add32(MSCNT);
		}

		// 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. (the XGKick in the vector code will flush to make sure that we don't get ahead of ourselves)
	}

	VIFStaticDMA.Add32(FLUSH);
	VIFStaticDMA.DMARet();	
		
}

Share this post


Link to post
Share on other sites

This topic is 3300 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