#include "loader.h" /* fonctions utilisees par le loader */ static unsigned int getint(FILE *fp) { int c, c1, c2, c3; c = getc(fp); c1 = getc(fp); c2 = getc(fp); c3 = getc(fp); return ((unsigned int) c) + (((unsigned int) c1) << 8) + (((unsigned int) c2) << 16) + (((unsigned int) c3) << 24); } static unsigned int getshort(FILE *fp) { int c, c1; c = getc(fp); c1 = getc(fp); return ((unsigned int) c) + (((unsigned int) c1) << 8); } /* Charger une image bmp */ int ImageLoad(char *filename, Image *image){ FILE *file; unsigned long size; unsigned long i; unsigned short int planes; unsigned short int bpp; GLubyte temp; if ((file = fopen(filename, "rb"))==NULL) { printf("File Not Found : %s\n",filename); return 0; } fseek(file, 18, SEEK_CUR); image->sizeX = getint(file); image->sizeY = getint(file); size = image->sizeX * image->sizeY * 3; planes = getshort(file); if (planes != 1) { printf("Planes from %s is not 1: %u\n", filename, planes); return 0; } bpp = getshort(file); if (bpp != 24) { printf("Bpp from %s is not 24: %u\n", filename, bpp); return 0; } fseek(file, 24, SEEK_CUR); image->data = (GLubyte*) malloc(size); if (image->data == NULL) { printf("Error allocating memory for color-corrected image data"); return 0; } if ((i = fread(image->data, size, 1, file)) != 1) { printf("Error reading image data from %s.\n", filename); return 0; } for (i=0;idata[i]; image->data[i] = image->data[i+2]; image->data[i+2] = temp; } return 1; } /*Enregistrer une image bmp*/ int ImageSave(char *filename, Image *image) { FILE *file; GLubyte *data; struct { unsigned short int type; /* Magic identifier */ unsigned int size; /* File size in bytes */ unsigned short int reserved1, reserved2; unsigned int offset; /* Offset to image a, bytes */ } header; struct { unsigned int size; /* Header size in bytes */ int width,height; /* Width and height of image */ unsigned short int planes; /* Number of colour planes */ unsigned short int bits; /* Bits per pixel */ unsigned int compression; /* Compression type */ unsigned int imagesize; /* Image size in bytes */ int xresolution,yresolution; /* Pixels per meter */ unsigned int ncolours; /* Number of colours */ unsigned int importantcolours; /* Important colours */ } infoheader; GLuint size; GLuint i; if ((file = fopen(filename, "wb"))==NULL) { printf("Problem to open file : %s\n",filename); return -1; } #define UNDEFINED 0 header.type = 0x4d42; #ifdef __OSX2__ header.type = ((header.type>>8)&0x00ff) | ((header.type & 0xff)<<8); #endif header.size = 54+3*image->sizeX+image->sizeY; #ifdef __OSX2__ header.size = (((header.size)>>24)&0xff) | ((((header.size)>>16)&0x00ff)<<8) | ((((header.size)>>8)&0x0000ff)<<16) | ((((header.size)>>0)&0x000000ff)<<24); #endif header.reserved1 = 0; #ifdef __OSX2__ header.reserved2 = 0x3600; #else header.reserved2 = 0x36; #endif #ifdef __OSX2__ header.offset = 0x49d0; #else header.offset = 0; #endif fwrite(&header, 14, 1, file); infoheader.size=40; #ifdef __OSX2__ infoheader.size = (((infoheader.size)>>24)&0xff) | ((((infoheader.size)>>16)&0x00ff)<<8) | ((((infoheader.size)>>8)&0x0000ff)<<16) | ((((infoheader.size)>>0)&0x000000ff)<<24); #endif infoheader.width=image->sizeX; infoheader.height=image->sizeY; #ifdef __OSX2__ infoheader.width = (((infoheader.width)>>24)&0xff) | ((((infoheader.width)>>16)&0x00ff)<<8) | ((((infoheader.width)>>8)&0x0000ff)<<16) | ((((infoheader.width)>>0)&0x000000ff)<<24); infoheader.height = (((infoheader.height)>>24)&0xff) | ((((infoheader.height)>>16)&0x00ff)<<8) | ((((infoheader.height)>>8)&0x0000ff)<<16) | ((((infoheader.height)>>0)&0x000000ff)<<24); #endif #ifdef __OSX2__ infoheader.planes=256; #else infoheader.planes=1; #endif #ifdef __OSX2__ infoheader.bits= 0x1800; #else infoheader.bits= 24; #endif infoheader.compression=0; infoheader.imagesize = 3*image->sizeX*image->sizeY; #ifdef __OSX2__ infoheader.imagesize = (((infoheader.imagesize)>>24)&0xff) | ((((infoheader.imagesize)>>16)&0x00ff)<<8) | ((((infoheader.imagesize)>>8)&0x0000ff)<<16) | ((((infoheader.imagesize)>>0)&0x000000ff)<<24); #endif infoheader.xresolution = infoheader.yresolution = 0; infoheader.ncolours = 0; infoheader.importantcolours = 0; fwrite(&infoheader, 40, 1, file); size = image->sizeX*image->sizeY*3; data = (GLubyte*) malloc(size); for (i=0;idata[i+2]; data[i+1] = image->data[i+1]; data[i+2] = image->data[i]; } fwrite(data, size, 1, file); fclose(file); free(data); return 0; } /*Chargement une texture*/ GLuint load_texture(char *filename, GLuint * texchrg,int n){ Image *image; image = (Image *) malloc(sizeof(Image)); ImageLoad(filename, image); texchrg=(GLuint*)malloc (sizeof(GLuint)); glEnable(GL_TEXTURE_2D); glGenTextures(1, texchrg); glBindTexture(GL_TEXTURE_2D, *texchrg); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST); gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image->sizeX, image->sizeY, GL_RGB, GL_UNSIGNED_BYTE, image->data); free(image->data); free(image); return *texchrg; } /*Chargement des images (textures) de base pour le multitextuting*/ void load_image(){ flocons = (Image *) malloc(sizeof(Image)); pierre = (Image *) malloc(sizeof(Image)); champ = (Image *) malloc(sizeof(Image)); liquide= (Image *) malloc(sizeof(Image)); ImageLoad("textures/neige.bmp", flocons); ImageLoad("textures/roche.bmp", pierre); ImageLoad("textures/gazon.bmp", champ); ImageLoad("textures/eau.bmp", liquide); } /*Calcul des couleurs pour chaque pixel des heightmaps selon la hauteur*/ participation Terrain_RemplitPart(float haut){ participation part; //c:champ, p:pierre, f:flocons, l:liquide, int add; add = haut + (rand()%30)-15; //un petit peu de hasard if(add<0) add = 0; if(add>255) add = 255; haut = add; if(haut<5.0){//les faible altitudes correspondent a la texture d'eau (liquide) part.c=0.0; part.p=0.0; part.f=0.0; part.l=1.0; } else if(haut<20.0){// melange d'eau et de champ (gazon) part.c = (haut-5.0)/10.0; part.p = 0.0f; part.f = 0.0f; part.l = 1.0 - (haut-5.0)/10.0; } else if(haut<60.0){// en moyenne altitude on a du champ (gazon) part.c = 1.0f; part.p = 0.0f; part.f = 0.0f; part.l = 0.0f; } else if(haut<130.0){// melange de champ et de pierre (roche) part.c = 1.0 - (haut-60.0)/70.0; part.p = (haut-60.0)/70.0; part.f = 0.0f; part.l = 0.0f; } else if(haut<180.0){// en haute altitude on a de la pierre (roche) part.c = 0.0f; part.p = 1.0f; part.f = 0.0f; part.l = 0.0f; } else if(haut<220.0){// melange de pierre (roche) et de flocons (neige) part.c = 0.0f; part.p = 1.0 - (haut-180.0)/40.0; part.f = (haut-180.0)/40.0; part.l = 0.0f; } else{// et en tres haute altitude on a du flocons (neige) part.c = 0.0f; part.p = 0.0f; part.f = 1.0f; part.l = 0.0f; } return part; } /*Charger une heightmap, remplit la matrice d'altitude, puis cree la matrice de couleurs et genere la texture correspondante */ multitexture concevoir_carte(multitexture h){ int i,j; int k,l; Image *image = (Image *) malloc(sizeof(Image)); ImageLoad(h.name, image); //remplisage de la matrice d'altitude 'h.heightmap[][]': h.heightmap=(float**)malloc(SIZE*sizeof(float*)); for (i=SIZE-1,k=0;i>0;i--,k++){ h.heightmap[k]=(float*)malloc (SIZE*sizeof(float)); for(j=0,l=0;jdata[i*image->sizeX*3+j]; proportion[k][l]=Terrain_RemplitPart(h.heightmap[k][l]);//calcul de la matrice de couleur } } generer_texture(h);//generation de la nouvelle texture free(image); return h; } /*Genere une texture en fonction de la matrice de couleurs*/ void generer_texture(multitexture h){ int i, j, k, l, tmpj, tmpi; Image *image = (Image *) malloc(sizeof(Image)); ImageLoad(h.name, image); /*Pour chaque pixel, on calcule la composition des 4 textures*/ for (i=SIZE-1,k=0;i>0;i--,k++){ for(j=0,l=0;jsizeY); tmpi=(i%champ->sizeX)*champ->sizeX*3+tmpj-tmpj%3; //calcul des couleurs de chaque pixel de la texture grace a la matrice de couleurs precalculee /* Recuperation des couleurs par image de base */ rouge[k][l] = proportion[k][l].c *champ->data[tmpi] + proportion[k][l].p *pierre->data[tmpi] + proportion[k][l].f *flocons->data[tmpi] + proportion[k][l].l *liquide->data[tmpi] ; tmpj=(j%pierre->sizeY); tmpi=(i%pierre->sizeX)*pierre->sizeX*3+tmpj-tmpj%3; vert[k][l] = proportion[k][l].c *champ->data[tmpi+1] + proportion[k][l].p *pierre->data[tmpi+1] + proportion[k][l].f *flocons->data[tmpi+1] + proportion[k][l].l *liquide->data[tmpi+1] ; bleu[k][l] = proportion[k][l].c *champ->data[tmpi+2] + proportion[k][l].p *pierre->data[tmpi+2] + proportion[k][l].f *flocons->data[tmpi+2] + proportion[k][l].l *liquide->data[tmpi+2] ; //on memorise ces nouvelles couleurs dans l'image image->data[(SIZE-i)*image->sizeX*3+j]=(rouge[k][l]); image->data[(SIZE-i)*image->sizeX*3+j+1]=(vert[k][l]); image->data[(SIZE-i)*image->sizeX*3+j+2]=(bleu[k][l]); } } //enfin on enregistre la texture ImageSave(h.name_texture,image); free(image); }