Jump to content
  • Advertisement
Sign in to follow this  
shalrath

Procedural Texture Generation Prob

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

I'm attempting to generate a procedural texture for my terrain heightmap engine. I've been following Tobias Franke's tutorial over on flipcode (http://www.flipcode.com/tutorials/tut_proctext.shtml) to get most of this code. However, he uses floats for height values and colour values, and I'm using unsigned bytes (to load RAW images), so I've made my attempt to convert his code over for use in my project. It all seemed to be going fine, until I actually saved out the final image. From the coordinates x (height) = 119, y (width) = 60 (in a 256x128 <height x width> image), the generator just stops working and outputs lines of a single colour for 10 or so rows, and then simply outputs black for the rest of the image. If anyone can point me in the right direction I'd be most grateful. Here is the code: (sorry its a bit long)
//Standard Includes
#include <stdio.h>
#include <math.h>
#include <fstream.h>

//Local Includes
#include "textures.h"

CTexGen::CTexGen()
{
}

CTexGen::~CTexGen()
{
}

//Initialise variables
bool CTexGen::bInitialise(int iWidth, int iHeight)
{
	int i;

	uiWidth = iWidth;
	uiHeight = iHeight;

	uiDataSize = uiWidth*uiHeight;

	for (i = 0; i < 4; i++)
	{
		ttTex = new triplet_t[uiDataSize];
		if (!ttTex)
			return 0;
	}

	ttNewTex = new triplet_t[uiDataSize];
	if (!ttNewTex)
		return 0;

	return 1;
}

//Load a greyscale RAW file (heightmap)
bool CTexGen::bLoadHMAP(char *fname)
{
	btHMAP = NULL;
	
	btHMAP = new byte_t[uiDataSize];
	if (!btHMAP)
		return 0;

	FILE *RawHMAP;

	RawHMAP = fopen(fname, "r");

	if (!RawHMAP)	//Failed to open
		return 0;

	fread(btHMAP, 1, uiDataSize, RawHMAP);

	fclose(RawHMAP);

	return 1;
}

//Load an RGB RAW file (texture image)
triplet_t *CTexGen::ttLoadRAW_RGB(char *fname)
{
	ttCurTex = NULL;
	
	ttCurTex = new triplet_t[uiDataSize];
	if (!ttCurTex)
		return 0;

	FILE *RawData;

	RawData = fopen(fname, "r");

	if (!RawData)	//Failed to open
		return 0;

	fread(ttCurTex, 1, uiDataSize*3, RawData);

	fclose(RawData);

	return ttCurTex;
}

//Load the textures
bool CTexGen::bLoadTextures()
{
	//Load the 'highest' texture
	ttTex[0] = ttLoadRAW_RGB("highest.raw");
	if (!ttTex[0])
		return 0;

	//Load the 'high' texture
	ttTex[1] = ttLoadRAW_RGB("high.raw");
	if (!ttTex[1])
		return 0;

	//Load the 'low' texture
	ttTex[2] = ttLoadRAW_RGB("low.raw");
	if (!ttTex[2])
		return 0;

	//Load the 'lowest' texture
	ttTex[3] = ttLoadRAW_RGB("lowest.raw");
	if (!ttTex[3])
		return 0;

	return 1;
}

//Calculate a textures 'presence' at a particular height value
float CTexGen::fTexFactor(float fH1, float fH2)
{
	float percent;

	percent = (64.0f - abs(fH1-fH2)) / 64.0f;

	//Clamp the value
	if (percent < 0.0f)
		percent = 0.0f;

	if (percent > 1.0f)
		percent = 1.0f;

	return percent;
}

//Error check x & y vals
float CTexGen::Height(byte_t *pHeightMap, int X, int Y)
{
	int x = X % uiHeight;					// Error check our x value
	int y = Y % uiWidth;					// Error check our y value

	if(!pHeightMap) return 0;				// Make sure our data is valid

    return (float)pHeightMap[x + (y * uiWidth)];	// Index into our height array and return the height
}

//Generate the new texture from 4 existing textures
bool CTexGen::Generate()
{
	//================================================
	//Initialise Locals
	float fTexFact[4];	//Percentage of visibility for each texture
	float fHeight;	//The height at the current working point (on the hmap)
	int x, y;	//our current position on the map
	int count;
	int i; //counter
	triplet_t ttNewColour;	//An RGB triplet for the new colour we'll generate
	triplet_t ttOldColour[4];	//Original RGB values for each texture we're processing
	//================================================

	//================================================
	//Loading Fuctions
    if (!bLoadHMAP("map.raw"))
	{
		printf("Load Failed\n");
		return 0;
	}
	if (!bLoadTextures())
	{
		printf("Load Textures Failed\n");
		return 0;
	}

	count = 0;
	//================================================

	//================================================
	//Cycle the map and generate new colour values
	for (x = 0; x < uiHeight; x++)
	{
		for (y = 0; y < uiWidth; y++)
		{
			fHeight = Height(btHMAP,x,y);

			//================================================
			//Get the percentage of visibility for each texture at current height
			fTexFact[0] = fTexFactor(256.0f, fHeight);
			fTexFact[1] = fTexFactor(192.0f, fHeight);
			fTexFact[2] = fTexFactor(128.0f, fHeight);
			fTexFact[3] = fTexFactor(64.0f, fHeight);
			//================================================

			//================================================
			//Read RGB vals
			for (i = 0; i < 4; i++)
			{
				ttOldColour.r = ttTex[x + (y*uiWidth)].r;
				ttOldColour.g = ttTex[x + (y*uiWidth)].g;
				ttOldColour.b = ttTex[x + (y*uiWidth)].b;
			}
			//================================================

			//================================================
			//Generate new RGB values
			//New red value
			ttNewColour.r = (byte_t)((fTexFact[0]*(float)ttOldColour[0].r) +
							 (fTexFact[1]*(float)ttOldColour[1].r) +
							 (fTexFact[2]*(float)ttOldColour[2].r) +
							 (fTexFact[3]*(float)ttOldColour[3].r));
			
			//New green value
			ttNewColour.g = (byte_t)((fTexFact[0]*(float)ttOldColour[0].g) +
							 (fTexFact[1]*(float)ttOldColour[1].g) +
							 (fTexFact[2]*(float)ttOldColour[2].g) +
							 (fTexFact[3]*(float)ttOldColour[3].g));

			//New blue value
			ttNewColour.b = (byte_t)((fTexFact[0]*(float)ttOldColour[0].b) +
							 (fTexFact[1]*(float)ttOldColour[1].b) +
							 (fTexFact[2]*(float)ttOldColour[2].b) +
							 (fTexFact[3]*(float)ttOldColour[3].b));
			//================================================
			
			//================================================
			//Put this colour onto the new texture
			ttNewTex[x + (y*uiWidth)].r = ttNewColour.r;
			ttNewTex[x + (y*uiWidth)].g = ttNewColour.g;
			ttNewTex[x + (y*uiWidth)].b = ttNewColour.b;
			//================================================
			count++;
		}
	}
	//================================================

	//================================================
	//Save function
	if (!bSaveNew("newtex.raw"))
		return 0;
	//================================================

	//Wow, we succeeded
	return 1;
}

bool CTexGen::bSaveNew(char *fname)
{
	ofstream TexFile;

	TexFile.open(fname, ios::out, filebuf::sh_none);

	TexFile.write((const char *)ttNewTex, uiDataSize*3);

	TexFile.close();
	/*
	FILE *NewHMAP;

	NewHMAP = fopen(fname, "w");

	if (!NewHMAP)	//Failed to open
		return 0;

	fwrite(ttNewTex, 1, uiDataSize*3, NewHMAP);

	fclose(NewHMAP);
*/
	return 1;
}

Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!