TGC Codebase Backup



AGK T2 heightmap loader by The Zoq2

16th Mar 2013 11:39
Summary

This code will take a 2d heightmap and generate a .obj file from it. Then it will load the file and apply textures as well as a detail shader to it. The code was originaly created



Description

The function takes 7 arguments, one heightmap which will be what the map is generated from. One texture which will be added as a normal texture. The hdTexture is used by the shader to add more detail to the texture. The detailX and detailY are parameters for the shader which I believe are used to specify how small the details will be. The max height specifys how high the mesh will become. And finaly stepSize determines the detail of the map. A step size of one will create a mesh with just as many vertices as the heightmap, 2 will use every second pixel, 4 every fourth and so on. Use what you feel gives the most detail without compromising the quality to much.

Thanks to MikeMax for creating the original code for AGK tier1 and letting me post this T2 version of the code.



Code
                                    ` This code was downloaded from The Game Creators
                                    ` It is reproduced here with full permission
                                    ` http://www.thegamecreators.com
                                    
                                    //////////////////////////////////////////////////////////////
//			Original code created by mike max               //
//				Ported to T2 by TheZoq2						//
//////////////////////////////////////////////////////////////

int Terrain::loadTerrain(char heightMap[128], char sdTexture[128], char hdTexture[128], float detailX, float detailY, float MaxHeight,int stepSize){
	int heightMapImg = agk::LoadImage(heightMap);
	std::vector<Vertex> v;

	//Getting the size of the heightmap
	int x = agk::GetImageWidth(heightMapImg) - 2; int y = agk::GetImageHeight(heightMapImg) - 2;
	
	std::vector< std::vector<Vertex> > vertices;

	for (int i = 0; i <= x; i++)
	{
		//v = std::vector<Vertex*> (y, new Vertex());
		vertices.push_back(v);
		for(int j = 0; j <= y; j++){
			Vertex tempVertex;
			vertices[i].push_back(tempVertex);
		}
	}

	int memblockID = agk::CreateMemblockFromImage(heightMapImg);

	//Checking if the object file exists and deleting it if it does
	if(agk::GetFileExists("Map.obj")){agk::DeleteFile("Map.obj");}

	int ObjFile = agk::OpenToWrite("Map.obj");
	int VertNumber = 1; 
	//Generation loop
	for(int ly = 0; ly <= y; ly = ly + stepSize){
		agk::PrintC("Generating: "); agk::Print(ly);
		agk::Render2DFront(); agk::Swap();

		for(int lx = 0; lx <= x; lx = lx + stepSize){
			int offsetPix=12+(((lx)+(ly*(x+2))))*4;
			int r = agk::GetMemblockByte(memblockID, offsetPix + 0);
			int g = agk::GetMemblockByte(memblockID, offsetPix + 1);
			int b = agk::GetMemblockByte(memblockID, offsetPix + 2);
			int a = agk::GetMemblockByte(memblockID, offsetPix + 3);

			float h = ((r+g+b)/3.0f)/255.0f;
			vertices[lx][ly].x = lx;
			vertices[lx][ly].y = h*MaxHeight;
			vertices[lx][ly].z = y - ly;

			//UV cordinates
			vertices[lx][ly].u = float(lx)/ float(x);
			vertices[lx][ly].v = (float(y - ly)/float(y));

			//Vertex number
			vertices[lx][ly].vertexNumber = VertNumber;

			//Getting the line to write to the file
			char line[128];
			sprintf(line, "v %f %f %f",vertices[lx][ly].x, vertices[lx][ly].y, vertices[lx][ly].z);

			//Writing the lines to the file
			agk::WriteLine(ObjFile, line);

			//Getting the uv file
			char line2[128];
			sprintf(line2, "vt %f %f", vertices[lx][ly].u, vertices[lx][ly].v);
			agk::WriteLine(ObjFile, line2);

			VertNumber = VertNumber + 1;
		}
	}

	//Creating the faces
	for(int ly = 0; ly <= y; ly = ly + stepSize){
		//Printing the progress
		agk::PrintC("Generating faces: "); agk::Print(ly);
		agk::Render2DFront(); agk::Swap();
		for(int lx = 0; lx <= y; lx = lx + stepSize){
			//
			if (lx>stepSize-1 && ly>stepSize-1){
				//Converting indexes to form faces
				int v1 = vertices[lx][ly].vertexNumber;
				int v2 = vertices[lx - stepSize][ly].vertexNumber;
				int v3 = vertices[lx][ly - stepSize].vertexNumber;

				int v4 = vertices[lx][ly-stepSize].vertexNumber;
				int v5 = vertices[lx-stepSize][ly].vertexNumber;
				int v6 = vertices[lx-stepSize][ly-stepSize].vertexNumber;

				// VT indexes are the same as vertices ones.
				int vt1 = v1; int vt2=v2; int vt3=v3; int vt4=v4; int vt5=v5; int vt6=v6;

				char line[128];
				sprintf(line, "f %i/%i %i/%i %i/%i", v1, vt1, v2, vt2, v3, vt3);
				char line2[128];
				sprintf(line2, "f %i/%i %i/%i %i/%i", v4, vt4, v5, vt5, v6, vt6);

				agk::WriteLine(ObjFile, line);
				agk::WriteLine(ObjFile, line2);
			}
		}
	}
	agk::CloseFile(ObjFile);

	int terrainID = agk::LoadObject("Map.obj");

	if(agk::GetFileExists(sdTexture)){
		int colorMap = agk::LoadImage(sdTexture);
		agk::SetObjectImage(terrainID, colorMap, 0);
		agk::SetImageWrapU(colorMap, 1);
		agk::SetImageWrapV(colorMap, 1);
	}

	if(agk::GetFileExists(hdTexture)){
		int detailMap = agk::LoadImage(hdTexture);
		agk::SetImageWrapU(detailMap, 1);
		agk::SetImageWrapV(detailMap, 1);
		agk::SetObjectImage(terrainID, detailMap, 1);

		//Loading the shader
		int detailShader = agk::LoadShader("media/vertexDetail.vs", "media/pixelDetail.ps");
		agk::SetShaderConstantByName(detailShader, "ScaleDetailMap", detailX, detailY, 0, 0);
		agk::SetObjectShader(terrainID, detailShader);
	}

	return terrainID;
}