All pastes #777589 Raw Edit

Unnamed

public text v1 · immutable
·published 2007-11-16 22:13 UTC
rendered paste body
#ifndef __Terrain__
#define __Terrain__


#include <math_vec3.h>
#include <GL/gl.h>


class Terrain
{
	
	private :
		
		uint   width;
		uint   height;
	
		vec3 * heightmap;
		vec3 * normals;
		/* texture */
		GLuint texture;
	
		uint glList;
		
		vec3 & getCoords(uint _i, uint _j);
		vec3 & getNormal(uint _i, uint _j);
	
	
	public : 
		
		Terrain(uint _width, uint _height, const char * _filename);
	
		bool loadTerrain(uint _width, uint _height, const char * _filename);
		bool loadTexture (const char * _filename);
		void computeNormals();	
		void scale(double _s);
	
		void createGLList();
		void display();
};


#endif

















----------------------------[ CPP ]-----------------------------------

#include <terrain.h>
#include <iostream>
#include <fstream>
#include <GL/gl.h>
#include <fstream>

using namespace std;


Terrain :: Terrain(uint _width, uint _height, const char * _filename)
{
	glList = 0;
	texture = 0;
	
	loadTerrain(_width, _height, _filename);
}


inline vec3 & Terrain :: getCoords(uint _i, uint _j)
{
	return *(heightmap + _j * width + _i);
}


inline vec3 & Terrain :: getNormal(uint _i, uint _j)
{
	return *(normals + _j * width + _i);
}


bool Terrain :: loadTerrain(uint _width, uint _height, const char * _filename)
{
	ifstream file;
	double center, max, min;
	
	width  = _width;
	height = _height;
	
	file.open(_filename, ios::binary);
	
	if(file.is_open() == false)
	{
		cerr << "[-] Terrain::loadTerrain - Impossible d'ouvrir le fichier " << _filename << endl;
		return false;
	}
	
	heightmap = new vec3[width * height];
	normals   = new vec3[width * height];
	
	short pix[width * height], p;
	file.read((char *)&pix, sizeof(short) * width * height);
	
	max = pix[0];
	min = pix[0];
	
	for(uint j(0); j < height; j++)
		for(uint i(0); i < width; i++)
		{
			p = *(pix + j * width + i);
			
			getCoords(i, j).x = i - width / 2.0;
			getCoords(i, j).y = p;
			getCoords(i, j).z = j - height / 2.0;
			
			if(min > p)
				min = p;
			
			if(max < p)
				max = p;
		}
	
	center = (max + min) / 2.0;
	for(uint i(0); i < width * height; i++)
			(heightmap + i)->y -= center;
	
	file.close();

	return true;
}


bool Terrain :: loadTexture (const char * _filename)
{	
    char buff[16];
	int l, h, maxval;

	/* ouverture du fichier PPM */
    ifstream img (_filename, ios::in | ios::binary);
    if (!img.is_open())
	{
		cout << "[-] Terrain::loadTexture > Impossible d'ouvrir le fichier " << _filename << endl;
		return false;
    }
	
	/* lecture de la magic value */
    img.read(buff, 3);
    if (img.bad())
	{
		cout << "[-] Terrain::loadTexture > Impossible de lire le fichier " << _filename << endl;
		return false;
    }
    if (buff[0]!='P' || buff[1]!='6')
	{
		cout << "[-] Terrain::loadTexture > MagicValue incorrecte (pas P6)" << endl;
		return false;
    }
    
    if (buff[2] != 0x0a)
		img.seekg(-1,ios::cur);

    while (img.read(buff, 1), buff[0]=='#')
	{
		while (img.read(buff, 1), buff[0]!='\n');
    }

    img.seekg(-1,ios::cur);

	/* taille de la texture */
    img >> l;
    img >> h;
	if (l<=0 || h<=0 || l!=(int)width || h!=(int)height)
	{
		cout << "[-] Terrain::loadTexture > Dimensions de l'image incorrectes.\n";
		return false;
	}
	
    img >> maxval;
    while (img.read(buff, 1), buff[0]!='\n');
	
	/* allocation mémoire */
    char *texture_temp = new char[3*width*height];
    if (!texture_temp)
    {
		cout << "[-] Terrain::loadTexture > Impossible d'allouer la variable texture_temp.\n";
		return false;
	}

	/* mise en mémoire de l'image */
    img.read (texture_temp, 3*width*height);
	
	/* fermeture du fichier */
    img.close();
	
	
	/* création d'une texture */
	cout << "texture : "<<texture<<endl;
	cout << glGenTextures(1, &texture) << endl;
	cout << "texture : "<<texture<<endl;
	glBindTexture(GL_TEXTURE_2D, texture);
	cout << "texture : "<<texture<<endl;
	
	/*
	cout << "GLU : avt" << endl;
	
	int test = gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height,
		GL_RGB, GL_UNSIGNED_BYTE, texture_temp);
	
	cout << "GLU : " << test << endl;
	*/
	glTexImage2D(GL_TEXTURE_2D,0,GL_RGB, width, height,0,GL_RGB,GL_UNSIGNED_BYTE, texture_temp);
	
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	
	/* libération de la mémoire allouée */
	delete [] texture_temp;
	
	return true;
}


void Terrain :: computeNormals()
{
	for(uint i(0); i < width * height; i++)
		*(normals + i) = vec3::zero;
	
	vec3 v1, v2, normal;	
	for(uint j(0); j < height - 1; j++)
	{
		for(uint i(0); i < width - 1; i++)
		{
			vec3 & p1 = getCoords(i    , j    );
			vec3 & p2 = getCoords(i + 1, j    );
			vec3 & p3 = getCoords(i + 1, j + 1);
			vec3 & p4 = getCoords(i    , j + 1);
			
			v1 = p2 - p1;
			v2 = p4 - p1;
			
			normal = v1 ^ v2;			
			getNormal(i    , j    ) += normal;
			getNormal(i + 1, j    ) += normal;
			getNormal(i    , j + 1) += normal;
			
			v1 = p4 - p3;
			v2 = p2 - p3;
			
			normal = v1 ^ v2;			
			getNormal(i + 1, j + 1) += normal;
			getNormal(i + 1, j    ) += normal;
			getNormal(i    , j + 1) += normal;
		}
	}
	
	for(uint i(0); i < width * height; i++)
		(normals + i)->normalize();
}


void Terrain :: scale(double _s)
{
	for(uint i(0); i < width * height; i++)
		(heightmap + i)->y /= _s;
}


void Terrain :: createGLList()
{
	cout << "texture : "<<texture<<endl;
	if(glList != 0)
		glDeleteLists(glList, 1);
	
	glList = glGenLists(1);
	glNewList(glList, GL_COMPILE);
	if (texture != 0)
	{
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D, texture);
		cout << "on bind !\n";
	}
	
	for(uint j(0); j < height - 1; j++)
	{
		glBegin(GL_TRIANGLE_STRIP);
		for(uint i(0); i < width; i++)
		{
			glNormal3fv(getNormal(i, j));
			if (texture != 0)
				glTexCoord2f ((float)i/width, (float)(j+1)/height);
			glVertex3fv(getCoords(i, j));
			
			glNormal3fv(getNormal(i, j + 1));
			if (texture != 0)
				glTexCoord2f ((float)i/width, (float)j/height);
			glVertex3fv(getCoords(i, j + 1));
		}			
		glEnd();
	}
	
	glEndList();
}


void Terrain :: display()
{
	if (glList == 0)
		createGLList();
	
	glCallList(glList);
}