Sign in to follow this  

Procedural Texture Generation Prob

This topic is 4854 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[i] = new triplet_t[uiDataSize];
		if (!ttTex[i])
			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[i].r = ttTex[i][x + (y*uiWidth)].r;
				ttOldColour[i].g = ttTex[i][x + (y*uiWidth)].g;
				ttOldColour[i].b = ttTex[i][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

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