Moteur 3d dimetrique

Description

c'est une application qui affiche un terrain en projection orthogonale dimetrique. une projection dimétrique est une projection gardant les projections de 2 axes (une projection isometrique garde les proportions des 3 axes) . cette projection est faite à l'aide d'une matrice de transformation Opengl

la projection permet de changer l'inclinaison du terrain et de le faire tourner mais je n'ai pas implementer de depth sorting et en regardant le terrain de l'arriere on voit les faces avant .

->click gauche sur l'eau : crée des vagues
-> drag click droit : scroll (translate) le terrain
-> drag click milieu : change l'echelle (scale) le terrain
-> drag click gauche+droite : change l'inclinaison et la rotation du terrain

le programme tourne à 75fps sur mon ordinateur (Geforce 2 MX T_T): je pense qu'il n'est limité que par le nombre de polygones à affiché (128*128)

l'executable est trop gros pour le zip
mais vous pouvez le trouver sur http://matt2000.free.fr/release.rar ainsi que des textures non compressés

Source / Exemple :


void CTerrainNode::Draw() {

GLdouble model[16], proj[4][4];
GLint view[4];
glGetDoublev(GL_PROJECTION_MATRIX, &proj[0][0]);
glGetIntegerv(GL_VIEWPORT, &view[0]);
double x,y,z;
char tmp[32];
unsigned char white[] = { 255,255,255 },height;
short mx = WindowMaker->mouse.x;
short my = WindowMaker->mouse.y;

/**
Projection setting

    • /
glPushMatrix(); float matrix[16]= { sqrt(2)*0.5 , -sqrt(2)*0.5*sin((float)(256-View->camera.ry)/256) , 0 , 0, -sqrt(2)*0.5 , -sqrt(2)*0.5*sin((float)(256-View->camera.ry)/256) , 0 , 0, 0 , cos((256-View->camera.ry)/256) , 1 , 0, View->camera.x , View->camera.y , 0 , 1 }; glLoadMatrixf(matrix); glRotatef((-View->camera.rx+128)/2.8,0,0,1); glScalef((float)View->camera.zoom/8,(float)View->camera.zoom/8,(float)View->camera.zoom/16); /** Terrain rendering
    • /
glEnable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glBindTexture( GL_TEXTURE_2D, tilemap->id ); for(int i=0;i<heightmap->height-1;i++) { for(int j=0;j<heightmap->width-1;j++) { glBegin(GL_QUADS); glTexCoord2f((float)i/heightmap->width,(float)j/heightmap->height); glVertex3f(i ,j ,heightmap->get(i,j,0)); glTexCoord2f((float)(i+1)/heightmap->width,(float)(j)/heightmap->height); glVertex3f(i+1 ,j ,heightmap->get(i+1,j,0)); glTexCoord2f((float)(i+1)/heightmap->width,(float)(j+1)/heightmap->height); glVertex3f(i+1 ,j+1 ,heightmap->get(i+1,j+1,0)); glTexCoord2f((float)(i)/heightmap->width,(float)(j+1)/heightmap->height); glVertex3f(i ,j+1 ,heightmap->get(i,j+1,0)); glEnd(); } } glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glDisable(GL_TEXTURE_2D); /** retrieve the mouse position on the terrain
    • /
glGetDoublev(GL_MODELVIEW_MATRIX, &model[0]); double right[3]; right[0] = model[0]; right[1] = model[4]; right[2] = model[8]; float w; glReadPixels(mx,768-my,1,1,GL_DEPTH_COMPONENT,GL_FLOAT,&w); //read pixel (GL_FLOAT) return a float not a double z = w; gluUnProject( mx,768-my,z,&model[0], &proj[0][0], &view[0], &x, &y,&z); ix = x+0; iy = y+0; if(ix>127) ix = 127; else if(ix<0) ix = 0; if(iy>127) iy = 127; else if(iy<0) iy = 0; glColor4ub(255,0,0,128); glBegin(GL_QUADS); glVertex3f(ix ,iy ,heightmap->get(ix,iy,0)); glVertex3f(ix+1 ,iy ,heightmap->get(ix+1,iy,0)); glVertex3f(ix+1 ,iy+1 ,heightmap->get(ix+1,iy+1,0)); glVertex3f(ix ,iy+1 ,heightmap->get(ix,iy+1,0)); glEnd(); /** Object (tree,building) rendering using point sprite extension
    • /
glPointSize((float)View->camera.zoom/4); glTexEnvf (GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE); glEnable (GL_POINT_SPRITE); glEnable(GL_TEXTURE_2D); glColor3ub(255,255,255); for(int i=0;i<heightmap->height-1;i++) { for(int j=0;j<heightmap->width-1;j++) { if( objectmap->get(i,j,0) && objectmap->get(i,j,0) <= nofObject ) { glBindTexture( GL_TEXTURE_2D, object [ objectmap->get(i,j,0) ].id ); glBegin(GL_POINTS); glVertex3f(i+0.5,j+0.5,heightmap->get(i,j,0)); glEnd(); } } } glPointSize(16); glDisable (GL_POINT_SPRITE); glDisable(GL_TEXTURE_2D); glEnable(GL_DEPTH_TEST); glColor4ub(96,192,255,64); for(int i=0;i<heightmap->height-1;i++) { for(int j=0;j<heightmap->width-1;j++) { if(heightmap->get(i,j,0) < 64) { glBegin(GL_QUADS); //glTexCoord2f((float)i/heightmap->width,(float)j/heightmap->height); glVertex3f(i ,j ,64+((float)wavemap[(i+j*128)*2+swap]/32)); //glTexCoord2f((float)(i+1)/heightmap->width,(float)(j)/heightmap->height); glVertex3f(i-1 ,j ,64+((float)wavemap[(i-1+j*128)*2+swap]/32)); //glTexCoord2f((float)(i+1)/heightmap->width,(float)(j+1)/heightmap->height); glVertex3f(i-1 ,j-1 ,64+((float)wavemap[(i-1+(j-1)*128)*2+swap]/32)); //glTexCoord2f((float)(i)/heightmap->width,(float)(j+1)/heightmap->height); glVertex3f(i ,j-1 ,64+((float)wavemap[(i+(j-1)*128)*2+swap]/32)); glEnd(); } } } glDisable(GL_DEPTH_TEST); sprintf(tmp," x %i y %i z %0.0f",ix,iy,z); gl.DrawText2D(128,128,white,2.0f,0,tmp); glPopMatrix();

Conclusion :


Features :
-projection dimétrique d'un terrain heightmappé et texturé
-Loader de texture tga,bmp & jpg
-selection de la case sous la souris
-affichage d'objet(arbres,batiments) (utilise l'extension point_sprite )
-simulation de l'eau ( vague )

Todo :
-lorsque j'aurai un carte graphique correcte, j'utiliserai l'extension frame buffer object pour faire le reflet de l'eau et ne rerendre qu'une partie de l'écran lors des translations
-possibilité de creation de route
-possibilité de creer un batiment -> selection du batiment -> debut d'interface pour créer des bonhommes
-pathfinding
-un vrai jeu ?

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.