ManiaDrive/raydium/texture.c
2025-01-26 18:33:45 +01:00

403 lines
9.0 KiB
C

/*
Raydium - CQFD Corp.
http://raydium.org/
License: GPL - GNU General Public License, see "gpl.txt" file.
*/
#ifndef DONT_INCLUDE_HEADERS
#include "index.h"
#else
#include "headers/texture.h"
#endif
#include "live.h"
// proto
int raydium_init_cli_option(char *option, char *value);
FILE *raydium_file_fopen(char *path, char *mode);
signed char raydium_texture_size_is_correct(GLuint size)
{
int i;
if(raydium_window_mode==RAYDIUM_RENDERING_NONE)
return 1;
// must be a power of 2 and <= to raydium_texture_size_max
if(size==1) return 1;
for(i=2;i<=raydium_texture_size_max;i*=2)
if(i==size) return 1;
return 0;
}
GLuint raydium_texture_load_internal(char *filename, char *as, signed char faked, int faked_tx, int faked_ty, int faked_bpp, int or_live_id_fake)
{
FILE *file;
unsigned char temp[RAYDIUM_MAX_NAME_LEN];
unsigned char *data;
GLuint tx,ty,bpp,id;
GLuint i,j,k,GLbpp=0,GLbppi;
GLuint texsize=0;
char blended=0,filter=0,cutout=0,simulate=0;
char rgb;
GLfloat r,g,b;
signed char reflect=0;
// "as" is duplicated ?
for(i=0;i<raydium_texture_index;i++)
if(!strcmp(raydium_texture_name[i],as))
{
raydium_log("texture: (internal) %s is duplicated",as);
return i;
}
if(raydium_window_mode==RAYDIUM_RENDERING_NONE)
simulate=1;
/* is RGB color ? (or texture) */
strcpy((char *)temp,filename);
temp[4]=0;
if(!strcmp("rgb(",(char *)temp)) rgb=1; else rgb=0;
strcpy((char *)temp,filename);
temp[3]=0;
if(!strcmp("ENV",(char *)temp)) reflect=1;
if(!rgb && !faked)
{
file=raydium_file_fopen(filename,"rb");
if(!file)
{
raydium_log("Cannot open %s texture",filename);
return 0;
}
fread(temp,1,12,file);
if(temp[2]!=2 && temp[2]!=3)
{
fclose(file);
raydium_log("%s is not an uncompressed TGA RGB or grayscale file (type %i)",filename,temp[2]);
return 0; //not a: uncompressed TGA RGB file
}
fread(temp,1,6,file);
tx = temp[1] * 256 + temp[0]; // highbyte*256+lowbyte
ty = temp[3] * 256 + temp[2]; // highbyte*256+lowbyte
if( !raydium_texture_size_is_correct(tx) || !raydium_texture_size_is_correct(ty) )
{
raydium_log("texture: ERROR: cannot load %s: invalid size %ix%i (must be a power of two and inferior to your max hardware size: %i)",filename,tx,ty,raydium_texture_size_max);
raydium_log("texture: I will fake this texture.");
tx=ty=1;
}
bpp= temp[4] / 8;
texsize = tx * ty * bpp;
data=malloc(texsize);
if(!data) {
fclose(file);
raydium_log("texture: ERROR ! malloc for %s failed ! (%i bytes needed)",filename,tx*ty*bpp);
return 0; }
for(j=0; j<ty; j++)
for(i=0; i<tx; i++)
{
if(fread(temp,1,bpp,file)!=bpp)
{ free(data); fclose(file);
raydium_log("Invalid data in %s",filename);
return 0; }
k=(( (ty-j-1) *tx)+i)*bpp;
if(bpp == 1) data[k]=temp[0];
else // no greyscale
{
if(reflect)
{
temp[0]*=RAYDIUM_RENDER_REFLECTION_FACT;
temp[1]*=RAYDIUM_RENDER_REFLECTION_FACT;
temp[2]*=RAYDIUM_RENDER_REFLECTION_FACT;
}
data[k]=temp[2];
data[k+1]=temp[1];
data[k+2]=temp[0];
if(bpp == 4)
{
data[k+3]=temp[3];
if(temp[3]>0 && temp[3]<255)
blended=1;
if(temp[3]==0)
cutout=1;
}
}
}
fclose(file);
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
} //end !rgb && !faked
if(raydium_texture_to_replace)
{ id=raydium_texture_to_replace; raydium_texture_to_replace=0; }
else
id=raydium_texture_index++;
if(raydium_texture_index>RAYDIUM_MAX_TEXTURES)
{
raydium_log("texture: No more texture slots left ! (%i max)",
RAYDIUM_MAX_TEXTURES);
return 0;
}
strcpy(raydium_texture_name[id],as);
if(faked)
{
raydium_live_Texture *tex;
if(or_live_id_fake>=0)
{
tex=&raydium_live_texture[or_live_id_fake];
tx=tex->hardware_tx;
ty=tex->hardware_ty;
bpp=tex->bpp/8;
}
else
{
tx=faked_tx;
ty=faked_ty;
bpp=faked_bpp;
}
texsize = tx * ty * bpp;
data=malloc(texsize);
memset(data,0,texsize);
if(!data)
{
fclose(file);
raydium_log("texture: ERROR ! malloc for %s failed ! (%i bytes needed)",filename,tx*ty*bpp);
return 0;
}
}
if(!rgb)
{
if(bpp==1)
{
GLbpp=GL_ALPHA;
GLbppi=GL_ALPHA8;
blended=1;
}
if(bpp==3)
{
GLbpp=GL_RGB;
GLbppi=GL_RGBA8; // force RGBA (since ATI cards needs it)
texsize += tx * ty;
}
if(bpp==4)
{
GLbpp=GL_RGBA;
GLbppi=GL_RGBA8;
}
raydium_texture_blended[id]=0;
if(blended)
raydium_texture_blended[id]=1;
if(cutout && !blended)
{
raydium_texture_blended[id]=2;
blended=2;
}
raydium_texture_used_memory+=texsize;
if(raydium_texture_filter==RAYDIUM_TEXTURE_FILTER_TRILINEAR && !faked)
raydium_texture_used_memory+=(texsize/3); // mipmaps
if(!simulate)
glBindTexture(GL_TEXTURE_2D,id);
if(strstr(filename,".tri."))
raydium_texture_islightmap[id]=1;
memcpy(temp,filename,3); // TEMP !!
temp[3]=0; // TEMP !!
if(!simulate)
{
if(!strcmp("BOX",(char *)temp) || faked) // TEMP !!
{ // TEMP !!
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // TEMP !!
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // TEMP !!
} // TEMP !!
else
{
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
}
}
filter=raydium_texture_filter;
if(!strcmp("HDR",(char *)temp)) // TEMP !!
{
raydium_texture_hdr[id]=1;
raydium_texture_nolight[id]=1;
}
if(reflect)
raydium_texture_env[id]=1;
if(filter==RAYDIUM_TEXTURE_FILTER_TRILINEAR && blended)
filter=RAYDIUM_TEXTURE_FILTER_BILINEAR;
if(faked)
filter=RAYDIUM_TEXTURE_FILTER_BILINEAR;
if(filter==RAYDIUM_TEXTURE_FILTER_NONE && !simulate)
{
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D,0,GLbppi,tx,ty,0,GLbpp,GL_UNSIGNED_BYTE,data);
}
if(filter==RAYDIUM_TEXTURE_FILTER_BILINEAR && !simulate)
{
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,0,GLbppi,tx,ty,0,GLbpp,GL_UNSIGNED_BYTE,data);
}
if(filter==RAYDIUM_TEXTURE_FILTER_TRILINEAR && !simulate)
{
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); // Trilinear filtering
gluBuild2DMipmaps(GL_TEXTURE_2D, GLbppi, tx, ty, GLbpp, GL_UNSIGNED_BYTE, data);
}
raydium_log("Texture num %i (%s) %s: %ix%i, %i Bpp (b%i lm%i hdr%i)",
id,raydium_texture_name[id],
(faked?"FAKED":"loaded"),
tx,ty,bpp,
blended,raydium_texture_islightmap[id],
raydium_texture_hdr[id]);
free(data);
} else /* is rgb color */
{
sscanf(filename,"rgb(%f,%f,%f)",&r,&g,&b);
raydium_texture_rgb[id][0]=r;
raydium_texture_rgb[id][1]=g;
raydium_texture_rgb[id][2]=b;
raydium_texture_rgb[id][3]=1.f;
if(r<0 && g<0 && b<0)
{
raydium_texture_blended[id]=RAYDIUM_TEXTURE_PHANTOM;
raydium_log("Texture num %i is Phantom (depth buffer only)",id);
}
else
{
raydium_texture_blended[id]=0;
raydium_log("Texture num %i, rgb(%f,%f,%f) is RGB Color",id,r,g,b);
}
}
return id;
}
GLuint raydium_texture_load(char *filename)
{
GLuint res;
res=raydium_texture_load_internal(filename,filename,0,0,0,0,0);
if(res<=0)
{
raydium_log("texture: faking '%s' with pink color",filename);
res=raydium_texture_load_internal("rgb(1,0,1)",filename,0,0,0,0,0);
}
return res;
}
GLuint raydium_texture_load_erase(char *filename, GLuint to_replace)
{
if(to_replace<=0) return 0;
raydium_texture_to_replace=to_replace;
return raydium_texture_load(filename);
}
signed char raydium_texture_current_set(GLuint current)
{
if(current<RAYDIUM_MAX_TEXTURES)
{ raydium_texture_current_main=current; return current; }
return 0;
}
GLuint raydium_texture_find_by_name(char *name)
{
GLuint i;
char flag=0;
GLuint ret=0;
for(i=0;i<raydium_texture_index;i++)
if(!strcmp(raydium_texture_name[i],name)) { flag++; ret=i; }
if(!flag) ret=raydium_texture_load(name);
return ret;
}
GLuint raydium_texture_exists(char *name)
{
int i;
for(i=0;i<raydium_texture_index;i++)
if(!strcmp(raydium_texture_name[i],name))
return i;
return -1;
}
signed char raydium_texture_current_set_name(char *name)
{
/*
GLuint i;
char flag=0;
char ret=0;
for(i=0;i<raydium_texture_index;i++)
if(!strcmp(raydium_texture_name[i],name)) { flag++; raydium_texture_current_set(i); ret=i; }
if(!flag) ret=raydium_texture_current_set(raydium_texture_load(name));
*/
return raydium_texture_current_set(raydium_texture_find_by_name(name));
}
void raydium_texture_filter_change(GLuint filter)
{
//GLuint i;
char force[RAYDIUM_MAX_NAME_LEN];
if(raydium_init_cli_option("filter",force))
{
if(!strcmp(force,"none")) filter=RAYDIUM_TEXTURE_FILTER_NONE;
if(!strcmp(force,"bilinear")) filter=RAYDIUM_TEXTURE_FILTER_BILINEAR;
if(!strcmp(force,"trilinear")) filter=RAYDIUM_TEXTURE_FILTER_TRILINEAR;
}
raydium_texture_filter=filter;
// too ... dangerous
/*for(i=0;i<raydium_texture_index;i++)
raydium_texture_load_erase(raydium_texture_name[i],i);*/
}