|
Texture Generation Utility
Submitted by |
I was just reading Terrain Texture Generation by Tobias Franke on flipcode
today. I had written a similar utility some time back which had support for
config-files and multiple texture images. The textures wrap around if the
heightmap is larger than the base textures. I thought that ppl who're
writing terrain engines could use it.
I write and use most of my utilities in Linux. This one was hastily
converted to win32 just for this post.
|
Currently browsing [texgen.zip] (9,084 bytes) - [main.cpp] - (4,225 bytes)
/*
This is the unique texture generator for the terrain
Limitations: The base textures should be in 24bpp format.
and the heightmap should be in 8bpp format
Added config file support
*/
#include <stdio.h>
#include "tga.h"
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define CFG_FILE "texgen.cfg"
typedef struct
{
int hi, lo;
} limits;
int num_textures;
tga **pics, *hmap;
limits *ltable;
//For every texture image create a reference map and......
void parse_file();
void get_string(char *, int, FILE *);
void gen_tex_table(int num)
{
pics=(tga **)malloc(num*sizeof(tga *));
ltable=(limits *)malloc(num*sizeof(limits));
}
void add_to_tex_table(char *filename, int index, int hi, int lo)
{
pics[index]=new tga(filename);
ltable[index].lo=lo;
ltable[index].hi=hi;
}
void destroy_tex_table()
{
int i;
for(i=0; i<num_textures; i++)
{
free(pics[i]);
}
free(pics);
free(ltable);
}
void main(int argc, char **argv)
{
tga *hmap;
unsigned char *data;
if (argc != 2)
{
printf("Usage: %s <8bppheightmap.tga>\n",argv[0]);
exit(0);
}
parse_file();
hmap=new tga(argv[1]);
data=(unsigned char *)malloc(3*hmap->width*hmap->height);
memset(data, 0, 3*hmap->width*hmap->height);
//Main processing phase
int offset=0;
for(int y=0; y<hmap->height; y++)
for(int x=0; x< hmap->width; x++)
{
unsigned char height=hmap->data[offset++];
int clean=1;
float alpha;
for(int i=0; i<num_textures; i++)
{
//If within limits, add to data suitably
if ( (height >= ltable[i].lo) && (height <= ltable[i].hi))
{
//Calculate alpha for the current texture
alpha=(float)(height-ltable[i].lo) \
/(float)(ltable[i].hi-ltable[i].lo);
// This is a real funky way of doing the alpha calculation but
// who cares
//Get a value betn 30 & 150
float degrees=(alpha*120.0f)+30.0f;
alpha=sin(degrees*3.14159f/180.0f);
//Just check the bounds
if (alpha < 0.0f) alpha=0.0f;
if (alpha > 1.0f) alpha=1.0f;
colour24 col=pics[i]->getCol(x,y);
int offset2=(offset<<1)+offset;
if (clean) //write directly
{
data[offset2+1]=col.r;
data[offset2+2]=col.g;
data[offset2+3]=col.b;
}
else
{
#define A1 alpha
#define A2 (1.0f-A1)
//Mix the two colours
data[offset2+1]=(A1*col.r+A2*data[offset2+1]);
data[offset2+2]=(A1*col.g+A2*data[offset2+2]);
data[offset2+3]=(A1*col.b+A2*data[offset2+3]);
}
clean=0;
}
}
}
hmap->write_24bpp(hmap->width,hmap->height,data,"texture.tga");
delete hmap;
//This crashes in windows. I dunno why ?
//free(data);
destroy_tex_table();
}
/*
# SAMPLE CFG FILE
num_textures 2
# filename1 range.....
tex1.tga 0 127
tex2.tga 127 255
*/
void parse_file()
{
FILE *fp;
char buffer[256];
int num_read=0;
char str[256];
int hi,lo;
if((fp=fopen(CFG_FILE,"r"))==NULL)
{
printf("Cannot open file %s\n", CFG_FILE);
exit(0);
}
//read the first string
get_string(buffer,256,fp);
while(buffer[0] == '#' || buffer[0] == ' ' || buffer[0] == '\t')
{
get_string(buffer,256,fp);
}
//If not a comment
//Get the number of textures
sscanf(buffer,"num_textures %d",&num_textures);
printf("TEXGEN: num_textures: %d\n", num_textures);
gen_tex_table(num_textures);
//Now that we got num_textures, we can proceed further
while(num_read != num_textures)
{
get_string(buffer,256,fp);
if(buffer[0] != '#')
{
sscanf(buffer,"%s %d %d",str,&lo,&hi);
printf("TEXGEN: %s %5d %5d\n",str,lo,hi);
add_to_tex_table(str,num_read,hi,lo);
num_read++;
}
}
fclose(fp);
}
/*
Slow way to do it but I dont care
Cut-pasted and modified from my CNC expt
*/
void get_string(char *buff, int size, FILE *stream)
{
char ch;
int i=0;
while( (ch=(char)fgetc(stream)) != '\n')
{
if (i<size-1)
{
buff[i++]=ch;
}
}
buff[i]='\0';
}
|
|
Currently browsing [texgen.zip] (9,084 bytes) - [tga.cpp] - (4,497 bytes)
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "tga.h"
#define DEBUG_ON
tga::~tga()
{
if (data)
free(data);
#ifdef DEBUG_ON
printf("\nUnloaded\n");
#endif
}
tga::tga()
{
}
tga::tga(char *filename)
{
load(filename);
}
void tga::load(char *filename)
{
tga_header hdr;
FILE *fp;
int size;
unsigned char temp;
if ( (fp=fopen(filename,"rb")) == NULL)
{
perror("TGA_LOADER");
exit(1);
}
fread(&hdr,sizeof(tga_header),1,fp);
if (hdr.cmap_type)
{
printf("TGA_LOADER: Can't load colour-mapped Images\n");
exit(1);
}
pixfmt=hdr.bpp >> 3;
width=hdr.width;
height=hdr.height;
size=width*height*pixfmt;
data=(byte *)malloc(size);
//Position the pointer at the raw image data !
fseek(fp,hdr.id_length,SEEK_CUR);
if(hdr.image_type > 3)
{
switch(pixfmt)
{
case 3: //24 bpp
decode24bit(fp);
break;
case 1: //8 bpp
decode8bit(fp);
break;
}
}
else ///Uncompressed data
{
fread(data,1,size,fp);
if (pixfmt == 3)
{
//Convert BGR to RGB
for(int i=0; i<size; i+=3)
{
temp=data[i];
data[i]=data[i+2];
data[i+2]=temp;
}
}
}
#ifdef DEBUG_ON
printf("Loaded %s: %dx%d @ %dbpp\n", filename, width,height,hdr.bpp);
#endif
fclose(fp);
}
void tga::decode8bit(FILE *fp)
{
byte packet, colour;
byte *ptr;
int count, offset=0, size;
size=height*width;
ptr=data;
while(offset < size)
{
fread(&packet,1,1,fp);
count=(packet&0x7f)+1;
offset+=count;
//Runlength packet
if (packet&0x80)
{
//Read BGR and convert to RGB
fread(&colour,1,1,fp);
while(count)
{
*ptr=colour;
ptr++;
--count;
}
}
else
{
//Raw packet
while(count)
{
fread(&colour,1,1,fp);
*ptr=colour;
ptr++;
--count;
}
}
}
#ifdef DEBUG_ON
printf("Offset=%d , Size=%d\n",offset,size);
#endif
}
void tga::decode24bit(FILE *fp)
{
byte packet, colour[3];
byte *ptr;
int count, offset=0, size;
size=height*width;
ptr=data;
//Sometimes offset exceeds size !
while(offset < size)
{
fread(&packet,1,1,fp);
count=(packet&0x7f)+1;
offset+=count;
//Runlength packet
if (packet&0x80)
{
//Read BGR and convert to RGB
fread(colour,3,1,fp);
while(count)
{
ptr[0]=colour[2];
ptr[1]=colour[1];
ptr[2]=colour[0];
ptr+=3;
--count;
}
}
else
{
//Raw packet
while(count)
{
fread(colour,3,1,fp);
ptr[0]=colour[2];
ptr[1]=colour[1];
ptr[2]=colour[0];
ptr+=3;
--count;
}
}
}
#ifdef DEBUG_ON
printf("Offset=%d , Size=%d\n",offset,size);
#endif
}
//Will be defined for future use!
void tga::decode32bit(FILE *fp)
{
}
void tga::write_24bpp(int w, int h, unsigned char *data, char *filename)
{
FILE *fp;
char *header=
"\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00";
//Open o/p file
unsigned char info[6];
unsigned char temp;
unsigned char *copy;
int size;
size=w*h*3;
info[0]=w; //lo
info[1]=(w>>8); //hi
info[2]=h; //lo
info[3]=(h>>8); //hi
info[4]=24;
info[5]=0;
fp=fopen(filename,"wb");
fwrite(header,1,12,fp);
fwrite(info,1,6,fp);
//Just write the data in RGB fmt
copy=(unsigned char *)malloc(size);
memcpy(copy,data,size);
//Convert this buffer to BGR fmt
for(int i=0; i<size; i+=3)
{
temp=copy[i];
copy[i]=copy[i+2];
copy[i+2]=temp;
}
fwrite(copy,1,size,fp);
fclose(fp);
free(copy);
}
void tga::write_8bpp(int w, int h, unsigned char *data, char *filename)
{
FILE *fp;
char *header=
"\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00";
//Open o/p file
unsigned char info[6];
int size;
size=w*h;
info[0]=w; //lo
info[1]=(w>>8); //hi
info[2]=h; //lo
info[3]=(h>>8); //hi
info[4]=8;
info[5]=0;
fp=fopen(filename,"wb");
fwrite(header,1,12,fp);
fwrite(info,1,6,fp);
fwrite(data,1,size,fp);
fclose(fp);
}
// Slightly expensive but who cares..
// this is used in the preprocess stage
colour24 tga::getCol(int x, int y)
{
colour24 a;
int offset;
while( y >= height)
y=y-height;
while( x >= width)
x=x - width;
offset=y*width+x;
offset*=3;
a.r=data[offset+1];
a.g=data[offset+2];
a.b=data[offset+3];
return a;
}
|
|
Currently browsing [texgen.zip] (9,084 bytes) - [tga.h] - (1,136 bytes)
/*
TGA CLASS:
Author: Darshan A Patil
Date: 2000-2001
e-mail: dapatil@hotmail.com
Notes:
This TGA class,
Can load 8bit and 24bit TGA files.
Writes 8 and 24 bit TGA files w/o RLE compression
*/
#ifndef TGA_H
#define TGA_H
#include <stdio.h>
typedef unsigned char byte;
typedef struct
{
byte id_length;
byte cmap_type;
byte image_type;
byte cmap_specs[5];
unsigned short int xorg, yorg,width, height;
byte bpp; //bits per pixel
byte img_descriptor;
}tga_header;
typedef struct
{
unsigned char r,g,b;
} colour24;
class tga
{
private:
void decode8bit(FILE *fp);
void decode32bit(FILE *fp);
void decode24bit(FILE *fp);
public:
int width, height;
byte pixfmt; //Bytes per pixel.
byte *data; //Raw Image Data
tga();
tga(char *filename);
~tga();
void load(char *filename);
void write_24bpp(int width, int height, unsigned char *data, char *filename);
void write_8bpp(int width, int height, unsigned char *data, char *filename);
// To be used only for the synthesizer....
// Uses wrap around mode
colour24 getCol(int x,int y);
};
#endif
|
|
The zip file viewer built into the Developer Toolbox made use
of the zlib library, as well as the zlibdll source additions.
|