begin process at 2012 05 27 14:10:59
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

OpenGL

 > CAMÉRA OPENGL UTILISANT LES QUATERNIONS

CAMÉRA OPENGL UTILISANT LES QUATERNIONS


 Information sur la source

Note :
1 / 10 - par 1 personne
1,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :OpenGL Classé sous :caméra, opengl, quaternion, quaternions Niveau :Initié Date de création :06/04/2006 Date de mise à jour :24/05/2006 16:55:49 Vu / téléchargé :12 332 / 531

Auteur : gouessej

Ecrire un message privé
Site perso
Ce membre participe au partage de revenus publicitaires
Commentaire sur cette source (4)
Ajouter un commentaire et/ou une note


 Description

     Tout d'abord, j'utilise openGL, la GLU et la GLUT. Ca marche sous windows et linux. J'ai un doute pour unix.

     Mon code est composé de 3 classes :
- UnitQuaternion : permet d'utiliser des quaternions unitaires pour représenter des rotations
- MovingObject   : permet de faire bouger un objet (translation et rotation) en déplaçant soit le repère local autour du repère global, soit l'inverse.
- Camera         : hérite de MovingObject, permet d'enrichir le comportement d'un objet mobile en lui permettant de modifier la matrice modèle-vue
- FlatSurface    : permet de définir une surface planaire
- Collidable     : permet de gérer les collsions ellipsoïdes/ellipsoïdes (pas encore au point) et ellipsoïdes/surfaces planaires
Sachez que je fais de l'openGL depuis à peine 4 mois et du C++ depuis 3 mois et demi. Je sais que ce n'est pas très propre, toutes vos critiques seront les bienvenues. Les commentaires sont en anglais car j'ai demandé de l'aide à des gens ne pratiquant pas la langue de Molière, merci de votre compréhension. J'utilise des tableaux de float au même format qu'openGL.

     Ma classe UnitQuaternion sert à utiliser des quaternions unitaires; les quaternions unitaires forment un sous-espace vectoriel des quaternions, appartenant eux-mêmes aux nombres dits "hypercomplexes".

     Ma classe MovingObject comprend une matrice appelée "Transform" dont les lignes contiennent les vecteurs suivants: Up, Right, Forward et LA COLONNE Position (Haut, Droite, Devant et Position). Je pars du principe que j'avance dans les Z négatifs.
Les quaternions unitaires me servent à stocker et combiner des informations sur les rotations. 3 variables de type flottant me permettent de stocker les angles à la façon de Cardan. J'arrive à modifier la matrice modèle-vue mais sans gimbal lock, en chargeant la matrice identité (ici, c'est peut-être facultatif) et en recalculant la matrice de rotation à partir de mes angles de Cardan en passant par les quaternions puis en replaçant l'objet ou la caméra à sa position initiale. J'essaie d'éviter à tout prix la multiplication de matrice et de garder des informations sur mes vecteurs.

    

Source

  • #include <GL/glut.h>
  • #include <GL/glext.h>
  • #include <string.h>
  • #include <stdlib.h>
  • #include <iostream.h>
  • #include <math.h>
  • #include <vector>
  • #ifdef WIN32_API
  • #define glutWarpPointer SetCursorPos
  • #include <windows.h>
  • #endif
  • #ifndef M_PI
  • #define M_PI 3.14159265359
  • #endif
  • /*#if !defined(GLUT_WHEEL_UP)
  • # define GLUT_WHEEL_UP 4
  • # define GLUT_WHEEL_DOWN 5
  • #endif
  • */
  • using namespace std;
  • //GLUT_MIDDLE_BUTTON
  • //http://users.ox.ac.uk/~orie1330/bmploader.html
  • #define BMPError char
  • #define BMPNOTABITMAP 'b' //Possible error flags
  • #define BMPNOOPEN 'o'
  • #define BMPFILEERROR 'f'
  • #define BMPBADINT 'i'
  • #define BMPNOERROR '\0'
  • #define BMPUNKNOWNFORMAT 'u'
  • #include <string.h>
  • typedef unsigned char BYTE;
  • class BMPClass{
  • //private: int width;
  • public: int width;
  • //private: int height;
  • public: int height;
  • //private: BYTE* bytes;//OpenGL formatted pixels
  • public: BYTE* bytes;
  • public: BMPClass(){
  • bytes=NULL;
  • }
  • public: ~BMPClass(){
  • if(bytes!=NULL)
  • delete[](bytes);
  • }
  • public: BYTE& pixel(int x,int y,int c){
  • return(bytes[(y*width+x)*3+c]);
  • }
  • public: void allocateMem(){
  • if(bytes!=NULL)
  • delete[](bytes);
  • bytes=new BYTE[width*height*3];
  • }
  • //Loads the bmp in fname, and puts the data in the current object
  • public: BMPError LoadBMPFromFile(char* fname){
  • if(sizeof(int)!=4)
  • return(BMPBADINT);
  • FILE* f=fopen(fname,"rb"); //open for reading in binary mode
  • if(!f)
  • return(BMPNOOPEN);
  • char header[54];
  • fread(header,54,1,f); //read the 54bit main header
  • if(header[0]!='B' || header[1]!='M')
  • {fclose(f);
  • return(BMPNOTABITMAP); //all bitmaps should start "BM"
  • }
  • //it seems gimp sometimes makes its headers small, so we have to do hence all the fseeks
  • int offset=*(unsigned int*)(header+10);
  • width=*(int*)(header+18);
  • height=*(int*)(header+22);
  • //now the bitmap knows how big it is it can allocate its memory
  • allocateMem();
  • int bits=int(header[28]); //colourdepth
  • int x,y,c;
  • BYTE cols[256*4]; //colourtable
  • switch(bits){
  • case(24):
  • {fseek(f,offset,SEEK_SET);
  • fread(bytes,width*height*3,1,f); //24bit is easy
  • for(x=0;x<width*height*3;x+=3) //except the format is BGR, grr
  • {BYTE temp=bytes[x];
  • bytes[x]=bytes[x+2];
  • bytes[x+2]=temp;
  • }
  • break;
  • }
  • case(8):
  • {fread(cols,256*4,1,f); //read colortable
  • fseek(f,offset,SEEK_SET);
  • for(y=0;y<height;++y) //(Notice 4bytes/col for some reason)
  • for(x=0;x<width;++x)
  • {BYTE byte;
  • fread(&byte,1,1,f); //just read byte
  • for(int c=0;c<3;++c)
  • pixel(x,y,c)=cols[byte*4+2-c]; //and look up in the table
  • }
  • break;
  • }
  • case(4):
  • {fread(cols,16*4,1,f);
  • fseek(f,offset,SEEK_SET);
  • for(y=0;y<256;++y)
  • for(x=0;x<256;x+=2)
  • {BYTE byte;
  • fread(&byte,1,1,f); //as above, but need to exract two
  • for(c=0;c<3;++c) //pixels from each byte
  • pixel(x,y,c)=cols[byte/16*4+2-c];
  • for(c=0;c<3;++c)
  • pixel(x+1,y,c)=cols[byte%16*4+2-c];
  • }
  • break;
  • }
  • case(1):
  • {fread(cols,8,1,f);
  • fseek(f,offset,SEEK_SET);
  • for(y=0;y<height;++y)
  • for(x=0;x<width;x+=8)
  • {BYTE byte;
  • fread(&byte,1,1,f);
  • //Every byte is eight pixels
  • //so I'm shifting the byte to the relevant position, then masking out
  • //all but the lowest bit in order to get the index into the colourtable.
  • for(int x2=0;x2<8;++x2)
  • for(int c=0;c<3;++c)
  • pixel(x+x2,y,c)=cols[((byte>>(7-x2))&1)*4+2-c];
  • }
  • break;
  • }
  • default:
  • {fclose(f);
  • return(BMPUNKNOWNFORMAT);
  • }
  • }
  • if(ferror(f))
  • {fclose(f);
  • return(BMPFILEERROR);
  • }
  • fclose(f);
  • return(BMPNOERROR);
  • }
  • //Translates my error codes into English
  • public: static char* TranslateBMPError(BMPError err){
  • switch(err)
  • {case(BMPNOTABITMAP):
  • return "This file is not a bitmap, specifically it doesn't start 'BM'";
  • case(BMPNOOPEN):
  • return "Failed to open the file, suspect it doesn't exist";
  • case(BMPFILEERROR):
  • return "ferror said we had an error. This error seems to not always mean anything, try ignoring it";
  • case(BMPBADINT):
  • return "sizeof(int)!=4 quite a lot of rewriting probably needs to be done on the code";
  • case(BMPNOERROR):
  • return "No errors detected";
  • case(BMPUNKNOWNFORMAT):
  • return "Unknown bmp format, ie not 24bit, 256,16 or 2 colour";
  • default:
  • return "Not a valid error code";
  • }
  • }
  • public: GLuint loadBMPTexture(char *filename){
  • GLuint TID=0;
  • if(LoadBMPFromFile(filename)!=BMPNOERROR)
  • return(TID);
  • //generate texture
  • glPushAttrib(GL_ENABLE_BIT);
  • glEnable(GL_TEXTURE_2D);
  • glGenTextures(1,&TID);
  • glBindTexture(GL_TEXTURE_2D,TID);
  • //setup some parameters for texture filters
  • glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  • glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  • glTexImage2D(GL_TEXTURE_2D,0,3,width,height,0,GL_RGB,GL_UNSIGNED_BYTE,bytes);
  • glDisable(GL_TEXTURE_2D);
  • glPopAttrib();
  • return(TID);
  • }
  • };
  • //#define JPEG_LIB_VERSION 62
  • #ifdef __cplusplus
  • extern "C" {
  • #endif
  • #include <jpeglib.h>
  • #include <jconfig.h>
  • #include <jerror.h>
  • #include <jmorecfg.h>
  • //OpenGL texture info
  • typedef struct{
  • GLsizei width;
  • GLsizei height;
  • GLenum format;
  • GLint internalFormat;
  • GLuint id;
  • GLubyte *texels;
  • } gl_texture_t;
  • gl_texture_t* ReadJPEGFromFile(const char *filename){
  • gl_texture_t *texinfo = NULL;
  • FILE *fp = NULL;
  • struct jpeg_decompress_struct cinfo;
  • struct jpeg_error_mgr jerr;
  • JSAMPROW j;
  • int i;
  • //open image file
  • fp = fopen (filename, "rb");
  • if (!fp)
  • {
  • fprintf (stderr, "error: couldn't open \"%s\"!\n", filename);
  • return NULL;
  • }
  • //create and configure decompressor
  • jpeg_create_decompress (&cinfo);
  • cinfo.err = jpeg_std_error (&jerr);
  • jpeg_stdio_src (&cinfo, fp);
  • //read header and prepare for decompression
  • jpeg_read_header (&cinfo, TRUE);
  • jpeg_start_decompress (&cinfo);
  • //initialize image's member variables
  • texinfo = (gl_texture_t *)malloc (sizeof (gl_texture_t));
  • texinfo->width = cinfo.image_width;
  • texinfo->height = cinfo.image_height;
  • texinfo->internalFormat = cinfo.num_components;
  • if (cinfo.num_components == 1)
  • texinfo->format = GL_LUMINANCE;
  • else
  • texinfo->format = GL_RGB;
  • texinfo->texels = (GLubyte *)malloc (sizeof (GLubyte) * texinfo->width
  • * texinfo->height * texinfo->internalFormat);
  • //extract each scanline of the image
  • for (i = 0; i < texinfo->height; ++i)
  • {
  • j = (texinfo->texels +
  • ((texinfo->height - (i + 1)) * texinfo->width * texinfo->internalFormat));
  • jpeg_read_scanlines (&cinfo, &j, 1);
  • }
  • //finish decompression and release memory
  • jpeg_finish_decompress (&cinfo);
  • jpeg_destroy_decompress (&cinfo);
  • fclose (fp);
  • return texinfo;
  • }
  • GLuint loadJPEGTexture (const char *filename){
  • gl_texture_t *jpeg_tex = NULL;
  • GLuint tex_id = 0;
  • jpeg_tex = ReadJPEGFromFile (filename);
  • if (jpeg_tex && jpeg_tex->texels)
  • {
  • //generate texture
  • glGenTextures (1, &jpeg_tex->id);
  • glBindTexture (GL_TEXTURE_2D, jpeg_tex->id);
  • //setup some parameters for texture filters and mipmapping
  • glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  • glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  • gluBuild2DMipmaps (GL_TEXTURE_2D, jpeg_tex->internalFormat,
  • jpeg_tex->width, jpeg_tex->height,
  • jpeg_tex->format, GL_UNSIGNED_BYTE, jpeg_tex->texels);
  • tex_id = jpeg_tex->id;
  • //OpenGL has its own copy of texture data
  • free (jpeg_tex->texels);
  • free (jpeg_tex);
  • }
  • return tex_id;
  • }
  • #ifdef __cplusplus
  • }
  • #endif
  • void crossProduct(float *x,float *y,float *z,float x1,float y1,float z1,float x2,float y2,float z2){
  • (*x)=y1*z2-z1*y2;
  • (*y)=z1*x2-x1*z2;
  • (*z)=x1*y2-y1*x2;
  • }
  • void crossProduct(float* vector,float* vector1,float* vector2){
  • vector[0]=vector1[1]*vector2[2]-vector1[2]*vector2[1];
  • vector[1]=vector1[2]*vector2[0]-vector1[0]*vector2[2];
  • vector[2]=vector1[0]*vector2[1]-vector1[1]*vector2[0];
  • }
  • float dot(float x1,float y1,float z1,float x2,float y2,float z2){
  • return((x1*x2)+(y1*y2)+(z1*z2));
  • }
  • float dot(float* vector1,float* vector2){
  • return((vector1[0]*vector2[0])+
  • (vector1[1]*vector2[1])+
  • (vector1[2]*vector2[2]));
  • }
  • float norm(float x,float y,float z){
  • return(sqrt(x*x+y*y+z*z));
  • }
  • float norm(float* vector){
  • return(sqrt(vector[0]*vector[0]+vector[1]*vector[1]+vector[2]*vector[2]));
  • }
  • bool equals(float* vector1,float* vector2){
  • return(vector1[0]==vector2[0]&&vector1[1]==vector2[1]&&vector1[2]==vector2[2]);
  • }
  • void vectorFromBipoint(float* vector,float* point1,float* point2){
  • vector[0]=point2[0]-point1[0];
  • vector[1]=point2[1]-point1[1];
  • vector[2]=point2[2]-point1[2];
  • }
  • void normalize(float *vector){
  • float n;
  • if((n=norm(vector))==0)
  • return;//avoids a division by zero
  • vector[0]/=n;
  • vector[1]/=n;
  • vector[2]/=n;
  • }
  • void normalize(float *x,float *y,float *z){
  • float n;
  • if((n=norm((*x),(*y),(*z)))==0)
  • return;//avoids a division by zero
  • (*x)/=n;
  • (*y)/=n;
  • (*z)/=n;
  • }
  • class UnitQuaternion{
  • private: float m_w;
  • private: float m_x;
  • private: float m_y;
  • private: float m_z;
  • public: inline void setW(float w){
  • m_w=w;
  • }
  • public: inline void setX(float x){
  • m_x=x;
  • }
  • public: inline void setY(float y){
  • m_y=y;
  • }
  • public: inline void setZ(float z){
  • m_z=z;
  • }
  • public: inline void createNeutralUnitQuaternion(){
  • m_w=1;
  • m_x=0;
  • m_y=0;
  • m_z=0;
  • }
  • //warning!! angle in radians!
  • public: void createFromAxisAngle(float angle,float x,float y,float z){
  • float r=(float)sin(angle/2.0f);
  • m_w=(float)cos(angle/2.0f);
  • m_x=x*r;
  • m_y=y*r;
  • m_z=z*r;
  • }
  • public: float norm(){
  • return(sqrt(m_w*m_w+m_x*m_x+m_y*m_y+m_z*m_z));
  • }
  • public: void normalize(){
  • float n;
  • if((n=norm())==0.0f)
  • return;
  • m_w/=n;
  • m_x/=n;
  • m_y/=n;
  • m_z/=n;
  • }
  • public: void createMatrix(float* matrix){
  • /*float mxXmx=m_x*m_x,myXmy=m_y*m_y,mzXmz=m_z*m_z;
  • float mxXmy=m_x*m_y,mzXmw=m_z*m_w,mxXmz=m_x*m_z,myXmw=m_y*m_w,mxXmw=m_x*m_w,myXmz=m_y*m_z;
  • matrix[0]=1.0f-2.0f*(myXmy+mzXmz);
  • matrix[1]=2.0f*(mxXmy+mzXmw);
  • matrix[2]=2.0f*(mxXmz-myXmw);
  • matrix[3]=0.0f;
  • matrix[4]=2.0f*(mxXmy-mzXmw);
  • matrix[5]=1.0f-2.0f*(mxXmx+mzXmz);
  • matrix[6]=2.0f*(myXmz+mxXmw);
  • matrix[7]=0.0f;
  • matrix[8]=2.0f*(mxXmz+myXmw);
  • matrix[9]=2.0f*(myXmz-mxXmw);
  • matrix[10]=1.0f-2.0f*(mxXmx+myXmy);
  • matrix[11]=0.0f;
  • matrix[12]=0.0f;
  • matrix[13]=0.0f;
  • matrix[14]=0.0f;
  • matrix[15]=1.0f;*/
  • float myXmyX2=m_y*m_y*2.0f,mzXmzX2=m_z*m_z*2.0f,mzXmw=m_z*m_w,
  • myXmw=m_y*m_w,mxXmw=m_x*m_w;
  • matrix[0]=1.0f-(myXmyX2+mzXmzX2);
  • matrix[1]=2.0f*(m_x*m_y+mzXmw);
  • matrix[2]=2.0f*(m_x*m_z-myXmw);
  • matrix[3]=0.0f;
  • matrix[4]=matrix[1]-4.0f*mzXmw;
  • matrix[5]=matrix[0]-2.0f*m_x*m_x+myXmyX2;
  • matrix[6]=2.0f*(m_y*m_z+mxXmw);
  • matrix[7]=0.0f;
  • matrix[8]=matrix[2]+4.0f*myXmw;
  • matrix[9]=matrix[6]-4.0f*mxXmw;
  • matrix[10]=matrix[5]+mzXmzX2-myXmyX2;
  • matrix[11]=0.0f;
  • matrix[12]=0.0f;
  • matrix[13]=0.0f;
  • matrix[14]=0.0f;
  • matrix[15]=1.0f;
  • }
  • public: void createInvertedMatrix(float* matrix){
  • float myXmyX2=m_y*m_y*2.0f,mzXmzX2=m_z*m_z*2.0f,mzXmw=m_z*m_w,
  • myXmw=m_y*m_w,mxXmw=m_x*m_w;
  • matrix[0]=1.0f-(myXmyX2+mzXmzX2);
  • matrix[4]=2.0f*(m_x*m_y+mzXmw);
  • matrix[8]=2.0f*(m_x*m_z-myXmw);
  • matrix[3]=0.0f;
  • matrix[1]=matrix[4]-4.0f*mzXmw;
  • matrix[5]=matrix[0]-2.0f*m_x*m_x+myXmyX2;
  • matrix[9]=2.0f*(m_y*m_z+mxXmw);
  • matrix[7]=0.0f;
  • matrix[2]=matrix[8]+4.0f*myXmw;
  • matrix[6]=matrix[9]-4.0f*mxXmw;
  • matrix[10]=matrix[5]+mzXmzX2-myXmyX2;
  • matrix[11]=0.0f;
  • matrix[12]=0.0f;
  • matrix[13]=0.0f;
  • matrix[14]=0.0f;
  • matrix[15]=1.0f;
  • }
  • public: UnitQuaternion operator *(UnitQuaternion q){
  • UnitQuaternion r;
  • r.m_w=m_w*q.m_w-m_x*q.m_x-m_y*q.m_y-m_z*q.m_z;
  • r.m_x=m_w*q.m_x+m_x*q.m_w+m_y*q.m_z-m_z*q.m_y;
  • r.m_y=m_w*q.m_y+m_y*q.m_w+m_z*q.m_x-m_x*q.m_z;
  • r.m_z=m_w*q.m_z+m_z*q.m_w+m_x*q.m_y-m_y*q.m_x;
  • return(r);
  • }
  • };
  • class MovingObject{
  • protected: float Transform[16];
  • protected: float old_position[16];
  • protected: UnitQuaternion m_qPitch;
  • protected: UnitQuaternion m_qYaw;
  • protected: UnitQuaternion m_qRoll;
  • //angles of the movement from the initial position
  • protected: float m_PitchRadians;
  • protected: float m_YawRadians;
  • protected: float m_RollRadians;
  • //angles of the bounding ellipsoide with the axes at the beginning
  • protected: float initial_m_PitchRadians;
  • protected: float initial_m_YawRadians;
  • protected: float initial_m_RollRadians;
  • protected: float* vertexArray;
  • protected: float* textureCoordinateArray;
  • protected: float* normalArray;
  • protected: unsigned int* vertexPerTextureArray;
  • protected: unsigned int* textureArray;
  • protected: unsigned int vertexCount;
  • protected: unsigned int textureCount;
  • public: MovingObject(float x=0.0f,float y=0.0f,float z=0.0f,
  • float initial_m_PitchRadians=0.0f,float initial_m_YawRadians=0.0f,
  • float initial_m_RollRadians=0.0f,
  • float* vertexArray=NULL,unsigned int vertexCount=0,
  • float* textureCoordinateArray=NULL,float* normalArray=NULL,
  • unsigned int* vertexPerTextureArray=NULL,
  • unsigned int* textureArray=NULL,unsigned int textureCount=0){
  • this->vertexArray=vertexArray;
  • this->textureCoordinateArray=textureCoordinateArray;
  • this->normalArray=normalArray;
  • this->textureArray=textureArray;
  • this->vertexPerTextureArray=vertexPerTextureArray;
  • //declare them here
  • //use sizeof to get their sizes like this:
  • //vertexCount=sizeof(vertexArray)/sizeof(float);
  • //textureCount=sizeof(textureArray)/sizeof(float);
  • //warning!! vertexPerTextureArray's size must be equals to
  • //textureCount!!
  • //use glGenTextures to initialize textureArray
  • // glBindTexture to select the texture
  • // glTexImage2D or GluBuild2DMipmaps to load the image data in the texture
  • this->textureCount=textureCount;
  • this->vertexCount=vertexCount;
  • //4x4 matrix filled with 0
  • Transform[0]=1.0f;
  • Transform[1]=0.0f;
  • Transform[2]=0.0f;
  • Transform[3]=0.0f;
  • Transform[4]=0.0f;
  • Transform[5]=1.0f;
  • Transform[6]=0.0f;
  • Transform[7]=0.0f;
  • Transform[8]=0.0f;
  • Transform[9]=0.0f;
  • Transform[10]=-1.0f;
  • Transform[11]=0.0f;
  • Transform[12]=x;//translation matrix
  • Transform[13]=y;
  • Transform[14]=z;
  • Transform[15]=1.0f;
  • old_position[0]=x;
  • old_position[1]=y;
  • old_position[2]=z;
  • m_PitchRadians=0.0f;
  • m_YawRadians=0.0f;
  • m_RollRadians=0.0f;
  • this->initial_m_PitchRadians=initial_m_PitchRadians;
  • this->initial_m_YawRadians=initial_m_YawRadians;
  • this->initial_m_RollRadians=initial_m_RollRadians;
  • m_qPitch.createNeutralUnitQuaternion();
  • m_qYaw.createNeutralUnitQuaternion();
  • m_qRoll.createNeutralUnitQuaternion();
  • }
  • public: virtual ~MovingObject(){
  • if(vertexArray!=NULL)
  • delete[](vertexArray);
  • if(textureCoordinateArray!=NULL)
  • delete[](textureCoordinateArray);
  • if(normalArray!=NULL)
  • delete[](normalArray);
  • if(textureArray!=NULL)
  • delete[](textureArray);
  • }
  • public: virtual void undoPositionChanges(){
  • float tmp[3];
  • int i;
  • for(i=0;i<16;i++)
  • tmp[i]=old_position[i];
  • for(i=0;i<16;i++)
  • old_position[i]=Transform[i];
  • for(i=0;i<16;i++)
  • Transform[i]=tmp[i];
  • }
  • public: virtual void updateOldPosition(){
  • for(int i=0;i<16;i++)
  • old_position[i]=Transform[i];
  • }
  • public: virtual void moveLocal(float x,float y,float z,float distance=1){
  • float dx=x*Transform[0]+y*Transform[4]+z*Transform[8];
  • float dy=x*Transform[1]+y*Transform[5]+z*Transform[9];
  • float dz=x*Transform[2]+y*Transform[6]+z*Transform[10];
  • updateOldPosition();
  • Transform[12]+=dx*distance;
  • Transform[13]+=dy*distance;
  • Transform[14]+=dz*distance;
  • }
  • public: virtual void moveGlobal(float x,float y,float z,float distance=1){
  • updateOldPosition();
  • Transform[12]+=x*distance;
  • Transform[13]+=y*distance;
  • Transform[14]+=z*distance;
  • }
  • public: virtual void rotateLocal(float angle,float x,float y,float z){
  • //rotation at the point (0,0,0)
  • //around the vector (x,y,z) by deg degrees
  • //glPushMatrix();
  • //glLoadMatrixf(Transform);
  • //glRotatef(deg,x,y,z);
  • //glGetFloatv(GL_MODELVIEW_MATRIX,Transform);
  • //glPopMatrix();
  • if(x!=0)
  • m_PitchRadians=0;
  • if(y!=0)
  • m_YawRadians=0;
  • if(z!=0)
  • m_RollRadians=0;
  • rotateGlobal(angle,x,y,z);
  • }
  • public: virtual void rotateGlobal(float angle,float x,float y,float z){
  • //we have to invert the rotations to get global axes
  • //in local coordinates. That's just the transposed matrix
  • //here
  • /*
  • float dx=x*Transform[0]+y*Transform[1]+z*Transform[2];
  • float dy=x*Transform[4]+y*Transform[5]+z*Transform[6];
  • float dz=x*Transform[8]+y*Transform[9]+z*Transform[10];
  • */
  • // Right Up Forward
  • // FIRST TRY WITH UVN
  • /*
  • glMatrixMode(GL_MODELVIEW);
  • glPushMatrix();
  • glLoadMatrixf(Transform);
  • glRotatef(angle,dx,dy,dz);
  • glGetFloatv(GL_MODELVIEW_MATRIX,Transform);
  • glPopMatrix();*/
  • //SECOND TRY WITH QUATERNIONS BUT NOT WORKING
  • //STILL GIMBAL LOCK
  • /*
  • if(dx==0)
  • m_qPitch.createNeutralUnitQuaternion();
  • else
  • m_qPitch.createFromAxisAngle(angle,dx,0.0f,0.0f);
  • if(dy==0)
  • m_qYaw.createNeutralUnitQuaternion();
  • else
  • m_qYaw.createFromAxisAngle(angle,0.0f,dy,0.0f);
  • if(dz==0)
  • m_qRoll.createNeutralUnitQuaternion();
  • else
  • m_qRoll.createFromAxisAngle(angle,0.0f,0.0f,dz);
  • UnitQuaternion q=m_qPitch*m_qYaw*m_qRoll;
  • float matrix[16];
  • q.createInvertedMatrix(matrix);
  • glPushMatrix();
  • glLoadMatrixf(matrix);
  • glMultMatrixf(Transform);
  • float tmp[3]={Transform[12],Transform[13],Transform[14]};
  • glGetFloatv(GL_MODELVIEW_MATRIX,Transform);
  • Transform[12]=tmp[0];
  • Transform[13]=tmp[1];
  • Transform[14]=tmp[2];
  • glPopMatrix();
  • */
  • // NEW NEW NEW
  • if(x!=0.0f)
  • {m_PitchRadians+=angle;
  • if(m_PitchRadians<-M_PI)
  • m_PitchRadians+=2*M_PI;
  • else
  • if(m_PitchRadians>M_PI)
  • m_PitchRadians-=2*M_PI;
  • m_qPitch.createFromAxisAngle(m_PitchRadians,1.0f,0.0f,0.0f);
  • m_qPitch.normalize();
  • }
  • if(y!=0.0f)
  • {m_YawRadians+=angle;
  • if(m_YawRadians<-M_PI)
  • m_YawRadians+=2*M_PI;
  • else
  • if(m_YawRadians>M_PI)
  • m_YawRadians-=2*M_PI;
  • m_qYaw.createFromAxisAngle(m_YawRadians,0.0f,1.0f,0.0f);
  • m_qYaw.normalize();
  • }
  • if(z!=0.0f)
  • {m_RollRadians+=angle;
  • if(m_RollRadians<-M_PI)
  • m_RollRadians+=2*M_PI;
  • else
  • if(m_RollRadians>M_PI)
  • m_RollRadians-=2*M_PI;
  • m_qRoll.createFromAxisAngle(m_RollRadians,0.0f,0.0f,1.0f);
  • m_qRoll.normalize();
  • }
  • UnitQuaternion q=m_qPitch*m_qYaw*m_qRoll;
  • q.normalize();
  • updateOldPosition();
  • float position[3]={Transform[12],Transform[13],Transform[14]};
  • q.createMatrix(Transform);
  • Transform[12]=position[0];
  • Transform[13]=position[1];
  • Transform[14]=position[2];
  • /*
  • cout <<"\n[[";
  • for(int i=0,j=0;i<16;i++)
  • {if(matrix[(i*4)%16+j]==-0)
  • matrix[(i*4)%16+j]=0;
  • cout <<matrix[(i*4)%16+j]<<" ";
  • if(i%4==3)
  • {j++;
  • if(i!=15)
  • cout <<"]\n [";
  • else cout <<"]]";
  • }
  • }
  • cout <<"\n"; */
  • /*
  • cout <<"\n[[";
  • for(int i=0,j=0;i<16;i++)
  • {if(Transform[(i*4)%16+j]==-0)
  • Transform[(i*4)%16+j]=0;
  • cout <<Transform[(i*4)%16+j]<<" ";
  • if(i%4==3)
  • {j++;
  • if(i!=15)
  • cout <<"]\n [";
  • else cout <<"]]";
  • }
  • }
  • cout <<"\n";*/
  • }
  • public: void toString(){
  • cout <<"\n[[";
  • for(int i=0,j=0;i<16;i++)
  • {if(Transform[(i*4)%16+j]==-0)
  • Transform[(i*4)%16+j]=0;
  • cout <<Transform[(i*4)%16+j]<<" ";
  • if(i%4==3)
  • {j++;
  • if(i!=15)
  • cout <<"]\n [";
  • else cout <<"]]";
  • }
  • }
  • cout <<"\n";
  • }
  • public: virtual void draw(){
  • //we need to know:
  • // the number of vertices (= the number of normals)
  • // ? (= the number of texture coordinates)
  • // the number of textures
  • // the numbers of vertices to use before changing
  • // the current texture that has to be used
  • // OR
  • // the number of texture=the number of vertices/4
  • glPushMatrix();
  • glEnableClientState(GL_VERTEX_ARRAY);
  • glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  • glEnableClientState(GL_NORMAL_ARRAY);
  • glEnableClientState(GL_TEXTURE_2D);
  • //glLockArrays();
  • glVertexPointer(3,GL_FLOAT,0,vertexArray);
  • glTexCoordPointer(3,GL_FLOAT,0,textureCoordinateArray);
  • glNormalPointer(GL_FLOAT,0,normalArray);
  • glLoadMatrixf(Transform);
  • for(unsigned int i=0,j=0;i<textureCount&&j<vertexCount;i++)
  • {glBindTexture(GL_TEXTURE_2D,textureArray[i]);
  • glDrawArrays(GL_POLYGON,j,vertexPerTextureArray[i]);
  • j+=vertexPerTextureArray[i];
  • }
  • //glUnlockArrays();
  • glDisableClientState(GL_VERTEX_ARRAY);
  • glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  • glDisableClientState(GL_NORMAL_ARRAY);
  • glDisableClientState(GL_TEXTURE_2D);
  • glPopMatrix();
  • }
  • };
  • class Camera :public MovingObject{
  • private: float min_m_PitchRadians;
  • private: float min_m_YawRadians;
  • private: float min_m_RollRadians;
  • private: float max_m_PitchRadians;
  • private: float max_m_YawRadians;
  • private: float max_m_RollRadians;
  • public: Camera(float x=0.0f,float y=0.0f,float z=0.0f,
  • float min_m_PitchRadians=-2*M_PI,
  • float min_m_YawRadians=-2*M_PI,
  • float min_m_RollRadians=-2*M_PI,
  • float max_m_PitchRadians=2*M_PI,
  • float max_m_YawRadians=2*M_PI,
  • float max_m_RollRadians=2*M_PI){
  • MovingObject::MovingObject(x,y,z);
  • //default behaviour :
  • //doesn't clamp any angle while rotating
  • this->min_m_PitchRadians=min_m_PitchRadians;
  • this->min_m_YawRadians=min_m_YawRadians;
  • this->min_m_RollRadians=min_m_RollRadians;
  • this->max_m_PitchRadians=max_m_PitchRadians;
  • this->max_m_YawRadians=max_m_YawRadians;
  • this->max_m_RollRadians=max_m_RollRadians;
  • }
  • //protected: virtual void collide(){}
  • public: virtual void moveLocal(float x,float y,float z,float distance=1){
  • MovingObject::moveLocal(x,y,z,distance);
  • setView();
  • }
  • public: virtual void moveGlobal(float x,float y,float z,float distance=1){
  • MovingObject::moveGlobal(x,y,z,distance);
  • setView();
  • }
  • public: virtual void rotateLocal(float angle,float x,float y,float z){
  • if(x!=0)
  • m_PitchRadians=0;
  • if(y!=0)
  • m_YawRadians=0;
  • if(z!=0)
  • m_RollRadians=0;
  • rotateGlobal(angle,x,y,z);
  • setView();
  • }
  • public: virtual void rotateGlobal(float angle,float x,float y,float z){
  • if(x!=0.0f)
  • {m_PitchRadians+=angle;
  • if(m_PitchRadians<-M_PI)
  • m_PitchRadians+=2*M_PI;
  • else
  • if(m_PitchRadians>M_PI)
  • m_PitchRadians-=2*M_PI;
  • if(m_PitchRadians<min_m_PitchRadians)
  • m_PitchRadians=min_m_PitchRadians;
  • else
  • if(m_PitchRadians>max_m_PitchRadians)
  • m_PitchRadians=max_m_PitchRadians;
  • m_qPitch.createFromAxisAngle(m_PitchRadians,1.0f,0.0f,0.0f);
  • m_qPitch.normalize();
  • }
  • if(y!=0.0f)
  • {m_YawRadians+=angle;
  • if(m_YawRadians<-M_PI)
  • m_YawRadians+=2*M_PI;
  • else
  • if(m_YawRadians>M_PI)
  • m_YawRadians-=2*M_PI;
  • if(m_YawRadians<min_m_YawRadians)
  • m_YawRadians=min_m_YawRadians;
  • else
  • if(m_YawRadians>max_m_YawRadians)
  • m_YawRadians=max_m_YawRadians;
  • m_qYaw.createFromAxisAngle(m_YawRadians,0.0f,1.0f,0.0f);
  • m_qYaw.normalize();
  • }
  • if(z!=0.0f)
  • {m_RollRadians+=angle;
  • if(m_RollRadians<-M_PI)
  • m_RollRadians+=2*M_PI;
  • else
  • if(m_RollRadians>M_PI)
  • m_RollRadians-=2*M_PI;
  • if(m_RollRadians<min_m_RollRadians)
  • m_RollRadians=min_m_RollRadians;
  • else
  • if(m_RollRadians>max_m_RollRadians)
  • m_RollRadians=max_m_RollRadians;
  • m_qRoll.createFromAxisAngle(m_RollRadians,0.0f,0.0f,1.0f);
  • m_qRoll.normalize();
  • }
  • UnitQuaternion q=m_qPitch*m_qYaw*m_qRoll;
  • q.normalize();
  • updateOldPosition();
  • float position[3]={Transform[12],Transform[13],Transform[14]};
  • q.createMatrix(Transform);
  • Transform[12]=position[0];
  • Transform[13]=position[1];
  • Transform[14]=position[2];
  • setView();
  • }
  • protected: virtual void setView(){
  • float viewmatrix[16]={Transform[0],Transform[4],-Transform[8],0
  • ,Transform[1],Transform[5],-Transform[9],0
  • ,Transform[2],Transform[6],-Transform[10],0
  • ,-(Transform[0]*Transform[12]
  • +Transform[1]*Transform[13]
  • +Transform[2]*Transform[14])
  • ,-(Transform[4]*Transform[12]
  • +Transform[5]*Transform[13]
  • +Transform[6]*Transform[14])
  • ,(Transform[8]*Transform[12]
  • +Transform[9]*Transform[13]
  • +Transform[10]*Transform[14])
  • ,1};
  • glLoadMatrixf(viewmatrix);/*
  • cout <<"\n[[";
  • for(int i=0,j=0;i<16;i++)
  • {if(viewmatrix[(i*4)%16+j]==-0)
  • viewmatrix[(i*4)%16+j]=0;
  • cout <<viewmatrix[(i*4)%16+j]<<" ";
  • if(i%4==3)
  • {j++;
  • if(i!=15)
  • cout <<"]\n [";
  • else cout <<"]]";
  • }
  • }
  • cout <<"\n";
  • gluLookAt(Position[0],Position[1],Position[2]
  • ,Forward[0]+Position[0],Forward[1]+Position[1],Forward[2]+Position[2]
  • ,Up[0],Up[1],Up[2]);*/
  • }
  • };
  • class FlatSurface{
  • private: float center[3];
  • private: float bound[12];
  • private: float normal[3];
  • public: FlatSurface(float bound1x,float bound1y,float bound1z,
  • float bound2x,float bound2y,float bound2z,
  • float bound3x,float bound3y,float bound3z,
  • float bound4x,float bound4y,float bound4z){
  • this->bound[0]=bound1x;
  • this->bound[1]=bound1y;
  • this->bound[2]=bound1z;
  • this->bound[3]=bound2x;
  • this->bound[4]=bound2y;
  • this->bound[5]=bound2z;
  • this->bound[6]=bound3x;
  • this->bound[7]=bound3y;
  • this->bound[8]=bound3z;
  • this->bound[9]=bound4x;
  • this->bound[10]=bound4y;
  • this->bound[11]=bound4z;
  • this->center[0]=(bound1x+bound3x)/2;
  • this->center[1]=(bound1y+bound3y)/2;
  • this->center[2]=(bound1z+bound3z)/2;
  • crossProduct(&normal[0],&normal[1],&normal[2],
  • (bound2x-bound1x),(bound2y-bound1y),(bound2z-bound1z),
  • (bound4x-bound1x),(bound4y-bound1y),(bound4z-bound1z));
  • normalize(normal);
  • }
  • private: void updateNormal(){
  • crossProduct(&normal[0],&normal[1],&normal[2],
  • (bound[3]-bound[0]),(bound[4]-bound[1]),(bound[5]-bound[2]),
  • (bound[9]-bound[0]),(bound[10]-bound[1]),(bound[11]-bound[2]));
  • normalize(normal);
  • }
  • public: float* getCenter(){
  • return(center);
  • }
  • public: float* getBounds(){
  • return(bound);
  • }
  • public: float* getNormal(){
  • return(normal);
  • }
  • public: bool contains(float* point){
  • //b1, b2, b3 and b4 are the rectangle's bounds
  • //a is the point supposed to be a collision point
  • float b1b3[3];
  • vectorFromBipoint(b1b3,&bound[0],&bound[6]);
  • float b1a[3];
  • vectorFromBipoint(b1a,&bound[0],point);
  • float n;
  • if((n=norm(b1a))>norm(b1b3))
  • return(false);
  • if(n==0)
  • return(true);
  • float cosb1b2b1a,n2,b1b2[3];
  • vectorFromBipoint(b1b2,&bound[0],&bound[3]);
  • n2=norm(b1b2);
  • if((cosb1b2b1a=dot(b1b2,b1a)/(n2*n))<0)
  • return(false);
  • float k1;
  • if(cosb1b2b1a==1)
  • {if(b1b2[0]!=0)
  • k1=b1a[0]/b1b2[0];
  • else
  • if(b1b2[1]!=0)
  • k1=b1a[1]/b1b2[1];
  • else
  • k1=b1a[2]/b1b2[2];
  • return(k1>0&&k1<=1);
  • }
  • float b1b4[3],k2;
  • vectorFromBipoint(b1b4,&bound[0],&bound[9]);
  • if(cosb1b2b1a==0)
  • {if(b1b4[0]!=0)
  • k2=b1a[0]/b1b4[0];
  • else
  • if(b1b4[1]!=0)
  • k2=b1a[1]/b1b4[1];
  • else
  • k2=b1a[2]/b1b4[2];
  • return(k2>0&&k2<=1);
  • }
  • if((k1=(cosb1b2b1a*n)/n2)<=0||k1>1)
  • return(false);
  • float cosb1b4b1a,n4=norm(b1b4);
  • if((cosb1b4b1a=dot(b1b4,b1a)/(n4*n))<0)
  • return(false);
  • return((k2=(cosb1b4b1a*n)/n4)>0&&k2<=1);
  • }
  • public: void draw(){}
  • };
  • class WallSet{
  • private: vector<FlatSurface> wallsVector;
  • //I need to modify FlatSurface to allow it to
  • //be able to contain information about the way
  • //to draw it
  • public: WallSet(FlatSurface walls[]=NULL,unsigned int count=0){
  • for(unsigned int i=0;i<count;i++)
  • wallsVector.push_back(walls[i]);
  • }
  • public: void addWall(FlatSurface wall){
  • wallsVector.push_back(wall);
  • }
  • public: FlatSurface getWall(int index){
  • return(wallsVector[index]);
  • }
  • public: unsigned int size(){
  • return(wallsVector.size());
  • }
  • public: void draw(){
  • for(unsigned int i=0;i<size();i++)
  • wallsVector[i].draw();
  • }
  • /*public: void collideAndCorrect(){
  • }*/
  • };
  • class Collidable :public MovingObject{
  • //collidable objects considered as spheres
  • //protected: unsigned int radius;
  • protected: float xradius;
  • protected: float yradius;
  • protected: float zradius;
  • public: Collidable(float x=0.0f,float y=0.0f,float z=0.0f,
  • float xradius=0.0f,float yradius=0.0f,float zradius=0.0f,
  • float initial_m_PitchRadians=0.0f,float initial_m_YawRadians=0.0f,
  • float initial_m_RollRadians=0.0f){
  • MovingObject::MovingObject(x,y,z,initial_m_PitchRadians,
  • initial_m_YawRadians,initial_m_RollRadians);
  • //this->radius=radius;
  • this->xradius=xradius;
  • this->yradius=yradius;
  • this->zradius=zradius;
  • }
  • /*
  • public: virtual void moveLocal(float x,float y,float z,float distance=1){
  • MovingObject::moveLocal(x,y,z,distance);
  • }
  • public: virtual void moveGlobal(float x,float y,float z,float distance=1){
  • MovingObject::moveGlobal(x,y,z,distance);
  • }
  • public: virtual void rotateLocal(float angle,float x,float y,float z){
  • MovingObject::rotateLocal(angle,x,y,z);
  • }
  • public: virtual void rotateGlobal(float angle,float x,float y,float z){
  • MovingObject::rotateGlobal(angle,x,y,z);
  • }
  • */
  • //I can use this collision point and the farthest collision point
  • //to compute a distance between them
  • //to know how to correct the position of the object
  • public: virtual void draw(){
  • MovingObject::draw();
  • }
  • public: virtual bool collide(FlatSurface surface,float* collision_point,
  • float* farthest_collision_point){
  • //warning!! the distance between old and new positions must be
  • //equal or shorter than the shortest DIAMETER!!
  • //Otherwise, the whole movement must be treated as
  • //a sum of smaller movements equal or shorter than
  • //the shortest DIAMETER
  • //handles intersections and check if there is a true collision
  • //does NOT handle case of piercing objects provoking multiple
  • //collisions per movement
  • float d,raydirection[3];
  • vectorFromBipoint(raydirection,&old_position[12],&Transform[12]);
  • //cout<<"\n"<<Transform[2]<<" "<<Transform[6]<<" "<<Transform[10]<<"\n";
  • if(norm(raydirection)!=1)
  • normalize(raydirection);
  • if((d=dot(surface.getNormal(),raydirection))==0)
  • return(false);
  • //checks if the surface is parallel to the ray direction
  • //why do I take the center of the surface???
  • float tmp[3];
  • vectorFromBipoint(tmp,&Transform[12],surface.getCenter());
  • d=dot(surface.getNormal(),tmp)/d;
  • collision_point[0]=Transform[12]+raydirection[0]*d;
  • collision_point[1]=Transform[13]+raydirection[1]*d;
  • collision_point[2]=Transform[14]+raydirection[2]*d;
  • if(isIn(collision_point,farthest_collision_point,raydirection))
  • return(surface.contains(collision_point));
  • //If d is negative, the collision takes place behind the
  • //starting point of the ray along the opposite direction
  • //and again there is no intersection.
  • //warning!! I'm going to assume that I'm doing a rectilinear
  • //movement!!
  • //I check if the new position is behind the plane
  • if(d<0)
  • {float dprime;
  • vectorFromBipoint(tmp,&old_position[12],surface.getCenter());
  • dprime=dot(surface.getNormal(),tmp)/dot(surface.getNormal(),raydirection);
  • //I check if the old position is not behind the plane
  • if(dprime<=0)
  • return(false);/*
  • collision_point[0]=old_position[12]+raydirection[0]*dprime;
  • collision_point[1]=old_position[13]+raydirection[1]*dprime;
  • collision_point[2]=old_position[14]+raydirection[2]*dprime;*/
  • //I check if the direction line goes through the surface
  • return(surface.contains(collision_point));
  • }
  • //else
  • // if(d<0)
  • // then (the object has gone through the wall)
  • // length_of_movement=2*shortest_radius+1
  • // length_of_movements=norm(unnormalized_raydirection);
  • // remaining_distance=length_of_movements
  • // (subdivisions_count=ceil(length_of_movement/length_of_movements);)
  • // test a sum of smaller movements equal or shorter than
  • // the shortest DIAMETER
  • // old_position constant, Transform[12..14] variable
  • // while(true)
  • // {if(remaining_distance>=length_of_movement)
  • // {warning!! this is a rectilinear approximation!!
  • // Transform[12]=old_position[12]+length_of_movement*raydirection[0];
  • // Transform[13]=old_position[13]+length_of_movement*raydirection[1];
  • // Transform[14]=old_position[14]+length_of_movement*raydirection[2];
  • // if(collide(surface,collision_point))
  • // return(true);
  • // remaining_distance-=length_of_movement;
  • // }
  • // else
  • // {warning!! this is a rectilinear approximation!!
  • // Transform[12]=old_position[12]+remaining_distance*raydirection[0];
  • // Transform[13]=old_position[13]+remaining_distance*raydirection[1];
  • // Transform[14]=old_position[14]+remaining_distance*raydirection[2];
  • // if(collide(surface,collision_point))
  • // return(true);
  • // remaining_distance=0; useless
  • // break;
  • // }
  • // }
  • return(false);
  • }
  • public: virtual bool isIn(float* collision_point,float* farthest_collision_point,
  • float* raydirection){
  • bool result=true;
  • float collision_vector[3];
  • vectorFromBipoint(collision_vector,&Transform[12],collision_point);
  • float norm_col=norm(collision_vector);
  • /*
  • if(xradius==0)
  • if(yradius==0)
  • if(zradius==0)
  • {farthest_collision_point[0]=Transform[12];
  • farthest_collision_point[1]=Transform[13];
  • farthest_collision_point[2]=Transform[14];
  • return(norm_col<=0);
  • }
  • else
  • //line
  • else
  • if(zradius==0)
  • //line
  • else
  • //ellipse
  • else
  • if(yradius==0)
  • if(zradius==0)
  • //line
  • else
  • //ellipse
  • else
  • if(zradius==0)
  • //ellipse
  • else
  • //ellipsoide
  • */
  • //angles of the movement from the axes
  • //=angles of the movement from the initial position
  • //+angles of the initial position
  • float real_m_RollRadians=m_RollRadians+initial_m_RollRadians;
  • float real_m_YawRadians=m_YawRadians+initial_m_YawRadians;
  • float cosroll=cos(real_m_RollRadians);
  • float sinroll=sin(real_m_RollRadians);
  • float cosyaw=cos(real_m_YawRadians);
  • float sinyaw=sin(real_m_YawRadians);
  • if(norm_col==0)
  • {//phi==0&&theta==0
  • farthest_collision_point[0]=Transform[12]+xradius*cosyaw*cosroll;
  • farthest_collision_point[1]=Transform[13]+yradius*cosyaw*sinroll;
  • farthest_collision_point[2]=Transform[14]+zradius*sinyaw;
  • return(true);
  • }
  • if(xradius==yradius&&xradius==zradius)
  • result=(norm_col<=xradius);
  • else
  • if(norm_col>xradius&&norm_col>yradius&&norm_col>zradius)
  • result=false;
  • else
  • if(norm_col<=xradius&&norm_col<=yradius&&norm_col<=zradius)
  • result=true;
  • float a[3];
  • a[0]=xradius*cosroll+Transform[12];
  • a[1]=xradius*sinroll+Transform[13];
  • if(collision_point[0]!=Transform[12])
  • a[2]=((xradius*cosroll/(collision_point[0]-Transform[12]))*
  • (collision_point[2]-Transform[14]))+Transform[14];
  • else
  • if(collision_point[1]!=Transform[13])
  • a[2]=((xradius*sinroll/(collision_point[1]-Transform[13]))*
  • (collision_point[2]-Transform[14]))+Transform[14];
  • else
  • a[2]=Transform[14];
  • float oprimea[3];
  • vectorFromBipoint(oprimea,&Transform[12],a);
  • float norm_oprimea_norm_col=norm(oprimea)*norm_col;
  • //warning!! risk of division by zero
  • float cosphi=dot(oprimea,collision_vector)/norm_oprimea_norm_col;
  • float oprimen[3];
  • crossProduct(oprimen,oprimea,collision_vector);
  • float sinphi=norm(oprimen)/norm_oprimea_norm_col;
  • float c[3];
  • c[0]=zradius*cos(real_m_YawRadians)+Transform[12];
  • c[2]=zradius*sin(real_m_YawRadians)+Transform[14];
  • if(collision_point[0]!=Transform[12])
  • c[1]=((zradius*cosyaw/(collision_point[0]-Transform[12]))*
  • (collision_point[1]-Transform[13]))+Transform[13];
  • else
  • if(collision_point[2]!=Transform[14])
  • c[1]=((zradius*sinyaw/(collision_point[2]-Transform[14]))*
  • (collision_point[1]-Transform[13]))+Transform[13];
  • else
  • c[1]=Transform[13];
  • float oprimec[3];
  • vectorFromBipoint(oprimec,&Transform[12],c);
  • float norm_oprimec_norm_col=norm(oprimec)*norm_col;
  • //warning!! risk of division by zero
  • float costheta=dot(oprimec,collision_vector)/norm_oprimec_norm_col;
  • float oprimenprime[3];
  • crossProduct(oprimenprime,oprimec,collision_vector);
  • float sintheta=norm(oprimenprime)/norm_oprimec_norm_col;
  • //farthest collision point from the center of the ellipsoid
  • float costheta_cosyaw=costheta*cosyaw;
  • float cosphi_cosroll=cosphi*cosroll;
  • float sintheta_sinyaw=sintheta*sinyaw;
  • float sinphi_sinroll=sinphi*sinroll;
  • float costheta_cosyaw___sintheta_sinyaw=
  • costheta_cosyaw-sintheta_sinyaw;
  • farthest_collision_point[0]=Transform[12]+xradius*
  • costheta_cosyaw___sintheta_sinyaw*(cosphi_cosroll-sinphi_sinroll);
  • farthest_collision_point[1]=Transform[13]+yradius*
  • costheta_cosyaw___sintheta_sinyaw*(sinphi_sinroll+cosphi_cosroll);
  • farthest_collision_point[2]=Transform[14]+zradius*
  • (sintheta_sinyaw+costheta*cosyaw);
  • float farthest_collision_vector[3];
  • vectorFromBipoint(farthest_collision_vector,&Transform[12],farthest_collision_point);
  • if(norm(collision_vector)>norm(farthest_collision_vector))
  • return(false);
  • return(result);
  • }
  • //I can use this distance between farthest collision points
  • //to know how to correct the position of the object
  • public: virtual bool collide(Collidable object,
  • float* vector_between_farthest_collision_points,float* first_farthest_collision_point){
  • //warning!! the distance between old and new positions must be
  • //equal or shorter than the sum of the shortest DIAMETERS!!
  • //Otherwise, the whole movement must be treated as
  • //a sum of smaller movements equal or shorter than
  • //the shortest DIAMETER
  • float second_farthest_collision_point[3];
  • bool result=false;
  • float raydirection[3];
  • vectorFromBipoint(raydirection,&old_position[12],&Transform[12]);
  • if(norm(raydirection)!=1)
  • normalize(raydirection);
  • if(isIn(&(object.Transform[12]),first_farthest_collision_point,raydirection))
  • result=true;
  • //this excludes the case O==F'
  • //this excludes the case O' in this
  • vectorFromBipoint(raydirection,&Transform[12],&old_position[12]);
  • if(norm(raydirection)!=1)
  • normalize(raydirection);
  • if(object.isIn(&Transform[12],second_farthest_collision_point,raydirection))
  • result=true;
  • //this excludes the case O in object
  • float ffprime[3];
  • vectorFromBipoint(ffprime,first_farthest_collision_point,second_farthest_collision_point);
  • vectorFromBipoint(vector_between_farthest_collision_points
  • ,first_farthest_collision_point,second_farthest_collision_point);
  • if(result==true||equals(first_farthest_collision_point,second_farthest_collision_point))
  • return(true);
  • //this excludes the case F==F'
  • if(equals(&Transform[12],first_farthest_collision_point))
  • {float oprimefprime[3];
  • vectorFromBipoint(oprimefprime,&(object.Transform[12]),second_farthest_collision_point);
  • float oprimef[3];
  • vectorFromBipoint(oprimef,&(object.Transform[12]),first_farthest_collision_point);
  • if(norm(oprimefprime)>=norm(oprimef))
  • return(true);
  • //this excludes the case O==F
  • }
  • else
  • {float of[3];
  • vectorFromBipoint(of,&Transform[12],first_farthest_collision_point);
  • float ofprime[3];
  • vectorFromBipoint(ofprime,&Transform[12],second_farthest_collision_point);
  • float k;
  • if(ofprime[0]!=0)
  • k=of[0]/ofprime[0];
  • else
  • if(ofprime[1]!=0)
  • k=of[1]/ofprime[1];
  • else
  • k=of[2]/ofprime[2];
  • if(k>=1)
  • return(true);
  • //no need to check when k<0 because it is treated
  • //above, when O is in object
  • }
  • return(false);
  • //comment the line above and uncomment the lines below if
  • //you have objects doing movements greater than their own
  • //shortest diameter
  • //at last, we must check if this has not gone through the object
  • //we build the plane which is orthogonal to (OO') in 3 steps
  • // we use the dot product to get a vector which is
  • // orthogonal to (OO')
  • // we use the cross product to get a vector which is
  • // orthogonal to the both vectors
  • // we sum O'F'' and O'F'' to get the last point
  • //we use the class 'FlatSurface' to build a surface
  • //we throw a ray and check if this was behind the plane
  • //we build an other plane which is orthogonal to
  • //the greatest radius and contains O
  • //we check if rays from the
  • //following points go through this new plane
  • //we check if they go through the ellipse which
  • //comes from the object's ellipsoide :
  • // the former origin
  • // its projection at the top of this ellipsoide
  • // its projection at the bottom of this ellipsoide
  • }
  • public: virtual void collideAndCorrect(WallSet walls){
  • for(unsigned int i=0;i<walls.size();i++)
  • collideAndCorrect(walls.getWall(i));
  • }
  • public: virtual bool collideAndCorrect(FlatSurface surface){
  • float collision_point[3];
  • float farthest_collision_point[3];
  • if(collide(surface,collision_point,farthest_collision_point))
  • {reactDuringCollisionWith(surface,collision_point,farthest_collision_point);
  • float tmp[3];
  • vectorFromBipoint(tmp,&Transform[12],&old_position[12]);
  • float farthest_collision_vector[3];
  • vectorFromBipoint(farthest_collision_vector,collision_point
  • ,farthest_collision_point);
  • float n=norm(farthest_collision_vector);
  • tmp[0]*=n+0.0001f;
  • tmp[1]*=n+0.0001f;
  • tmp[2]*=n+0.0001f;
  • correct(tmp);
  • return(true);
  • }
  • return(false);
  • }
  • public: virtual bool collideAndCorrect(Collidable object){
  • float vector_between_farthest_collision_points[3];
  • float first_farthest_collision_point[3];
  • if(collide(object,vector_between_farthest_collision_points,
  • first_farthest_collision_point))
  • {reactDuringCollisionWith(object,vector_between_farthest_collision_points
  • ,first_farthest_collision_point);
  • float tmp[3];
  • vectorFromBipoint(tmp,&Transform[12],&old_position[12]);
  • float n=dot(vector_between_farthest_collision_points,tmp);
  • tmp[0]*=n+0.0001f;
  • tmp[1]*=n+0.0001f;
  • tmp[2]*=n+0.0001f;
  • correct(tmp);
  • return(true);
  • }
  • return(false);
  • }
  • protected: virtual void correct(float* correction_vector){
  • Transform[12]+=correction_vector[0];
  • Transform[13]+=correction_vector[1];
  • Transform[14]+=correction_vector[2];
  • }
  • public: virtual float getCollisionDamage(){
  • return(0.0f);
  • }
  • protected: virtual void reactDuringCollisionWith(FlatSurface surface
  • ,float* collision_point,float* farthest_collision_point){
  • //will be mainly used for damages and explosions
  • }
  • protected: virtual void reactDuringCollisionWith(Collidable object
  • ,float* vector_between_farthest_collision_points
  • ,float* first_farthest_collision_point){
  • //will be mainly used for damages and explosions
  • }
  • /*
  • public: virtual bool collide(FlatSurface surface){
  • float collision_point[3];
  • return(collide(surface,collision_point));
  • }
  • */
  • };
  • class Fallable:public Collidable{
  • public: void fall(){}
  • };
  • class Player:public Fallable,Camera{
  • //handle ammo
  • //handle life
  • };
  • class Bot:public Fallable,Camera{
  • //redefine getCollisionDamage
  • //handle other kinds of damage
  • };
  • class Projectile:public Collidable{
  • //redefine getCollisionDamage
  • };
  • //I may need an Explosion class
  • #define STARTING_MODE 0 //display a few images
  • #define INTRO_MODE 1 //display a few images
  • #define PLAYING_MODE 5 //display the game, movements allowed
  • #define PAUSING_MODE 2 //display a few images
  • #define DYING_MODE 4 //display the game, movements not allowed, no gun
  • #define GAME_OVER_MODE 3 //display a few images
  • //I can simulate the death by reducing the yradius of the player
  • static short alpha=0,beta=0,Gamma=0,delta=0;
  • static int pointerx,pointery;
  • static Camera cam(0,0,0,-M_PI/2.0f,-2*M_PI,-2*M_PI,M_PI/2.0f,2*M_PI,2*M_PI);
  • static Collidable object(0,0,0,10,5,10);
  • static FlatSurface wall(20,20,2000,20,-20,2000,20,-20,-2000,20,20,-2000);
  • static unsigned short WINDOW_WIDTH,WINDOW_HEIGHT;
  • static unsigned char GAME_CURRENT_DISPLAY_MODE;
  • static unsigned int menu_textures_ID[16];
  • static int current_menu_texture_index;
  • void warpPointerAtCenter(){
  • pointerx=WINDOW_WIDTH/2;
  • pointery=WINDOW_HEIGHT/2;
  • glutWarpPointer((int)pointerx,(int)pointery);
  • }
  • bool pointerAtEdge(){
  • return(pointerx<=0||pointerx>=WINDOW_WIDTH-1||
  • pointery<=0||pointerx>=WINDOW_HEIGHT-1);
  • }
  • void drawWalls(){
  • glBegin(GL_QUADS);
  • glNormal3f(-1,0,0);
  • glVertex3f(-20,20,-2000);
  • glVertex3f(-20,-20,-2000);
  • glVertex3f(-20,-20,2000);
  • glVertex3f(-20,20,2000);
  • glNormal3f(1,0,0);
  • glVertex3f(20,20,2000);
  • glVertex3f(20,-20,2000);
  • glVertex3f(20,-20,-2000);
  • glVertex3f(20,20,-2000);
  • glEnd();
  • }
  • void drawParallelipipede(float x,float y,float z){
  • glBegin(GL_QUADS);
  • glNormal3f(0,0,1);
  • glVertex3f(-x/2,y/2,z/2);
  • glVertex3f(-x/2,-y/2,z/2);
  • glVertex3f(x/2,-y/2,z/2);
  • glVertex3f(x/2,y/2,z/2);
  • glNormal3f(1,0,0);
  • glVertex3f(x/2,y/2,z/2);
  • glVertex3f(x/2,-y/2,z/2);
  • glVertex3f(x/2,-y/2,-z/2);
  • glVertex3f(x/2,y/2,-z/2);
  • glNormal3f(0,0,-1);
  • glVertex3f(x/2,y/2,-z/2);
  • glVertex3f(x/2,-y/2,-z/2);
  • glVertex3f(-x/2,-y/2,-z/2);
  • glVertex3f(-x/2,y/2,-z/2);
  • glNormal3f(-1,0,0);
  • glVertex3f(-x/2,y/2,-z/2);
  • glVertex3f(-x/2,-y/2,-z/2);
  • glVertex3f(-x/2,-y/2,z/2);
  • glVertex3f(-x/2,y/2,z/2);
  • glNormal3f(0,1,0);
  • glVertex3f(-x/2,y/2,z/2);
  • glVertex3f(x/2,y/2,z/2);
  • glVertex3f(x/2,y/2,-z/2);
  • glVertex3f(-x/2,y/2,-z/2);
  • glNormal3f(0,-1,0);
  • glVertex3f(-x/2,-y/2,-z/2);
  • glVertex3f(x/2,y/2,-z/2);
  • glVertex3f(x/2,-y/2,z/2);
  • glVertex3f(-x/2,-y/2,z/2);
  • glEnd();
  • }
  • void drawArm(int a,int b,int c,int d){
  • glRotatef(a,0,0,1);
  • glPushMatrix();
  • glTranslatef(5.,0.,0.);
  • //glScalef(10.,1.,1.);
  • glColor3f(1.,0.,0.0);
  • drawParallelipipede(10,1,1);
  • glPopMatrix();
  • glTranslatef(10.,0.,0.);
  • glRotatef(b,0,0,1);
  • glPushMatrix();
  • glTranslatef(4.5,0.,0.);
  • //glScalef(9.,1.,1.);
  • glColor3f(0.,1.,0.0);
  • drawParallelipipede(9,1,1);
  • glPopMatrix();
  • glTranslatef(9.,0,0);
  • glPushMatrix();
  • glRotatef(c,0,0,1);
  • glTranslatef(2.,0.,0.);
  • //glScalef(4.,1.,1.);
  • glColor3f(0.,0.,1.0);
  • drawParallelipipede(4,1,1);
  • glPopMatrix();
  • glRotatef(d,0,0,1);
  • glTranslatef(2.,0.,0.);
  • //glScalef(4.,1.,1.);
  • glColor3f(1.,1.,0.0);
  • drawParallelipipede(4,1,1);
  • }
  • void init(){
  • GAME_CURRENT_DISPLAY_MODE=STARTING_MODE;
  • current_menu_texture_index=GAME_CURRENT_DISPLAY_MODE*4;
  • char filename[30],tmp[3];
  • glEnable(GL_TEXTURE_2D);
  • for(int i=0;i<16;i++)
  • {strcpy(filename,"menu_texture");
  • sprintf(tmp,"%d",i);
  • strcat(filename,tmp);
  • strcat(filename,".jpg");
  • menu_textures_ID[i]=loadJPEGTexture(filename);
  • }
  • glDisable(GL_TEXTURE_2D);
  • WINDOW_WIDTH=glutGet(GLUT_WINDOW_WIDTH);
  • WINDOW_HEIGHT=glutGet(GLUT_WINDOW_HEIGHT);
  • glClearColor(1.0,1.0,1.0,0.0);
  • glClearDepth(1.0);
  • glEnable(GL_DEPTH_TEST);
  • glDepthFunc(GL_LESS);/*
  • glEnable(GL_CULL_FACE);
  • glCullFace(GL_BACK);*/
  • /*glViewport(-50,-50,100,100);*/
  • glMatrixMode(GL_PROJECTION);
  • glLoadIdentity();
  • /*glFrustum(-50,50,-50,50,20,100);*//*ca marche quand meme*/
  • gluPerspective(65.0,((float)WINDOW_WIDTH)/
  • ((float)WINDOW_HEIGHT),1,1000);
  • glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
  • glMatrixMode(GL_MODELVIEW);
  • glutSetCursor(GLUT_CURSOR_NONE);
  • warpPointerAtCenter();
  • //object.rotateLocal(M_PI/2,0,1,0);
  • }
  • void display(){
  • glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  • if(GAME_CURRENT_DISPLAY_MODE==PLAYING_MODE||
  • GAME_CURRENT_DISPLAY_MODE==DYING_MODE)
  • {glPushAttrib(GL_COLOR_BUFFER_BIT);
  • glPushMatrix();
  • drawArm(alpha,beta,Gamma,delta);
  • glPopMatrix();
  • glPopAttrib();
  • glPushAttrib(GL_COLOR_BUFFER_BIT);
  • glPushMatrix();
  • glColor3f(0.3,0.3,0.3);
  • drawWalls();
  • glPopMatrix();
  • glPopAttrib();
  • }
  • else
  • {glPushMatrix();
  • glLoadIdentity();
  • glEnable(GL_TEXTURE_2D);
  • glColor3f(1,1,1);
  • glBindTexture(GL_TEXTURE_2D,menu_textures_ID[current_menu_texture_index]);
  • glBegin(GL_QUADS);
  • glVertex3f(-WINDOW_WIDTH/2,-WINDOW_HEIGHT/2,-250);
  • glTexCoord3f(0,1,-250);
  • glVertex3f(-WINDOW_WIDTH/2,WINDOW_HEIGHT/2,-250);
  • glTexCoord3f(1,1,-250);
  • glVertex3f(WINDOW_WIDTH/2,WINDOW_HEIGHT/2,-250);
  • glTexCoord3f(1,0,-250);
  • glVertex3f(WINDOW_WIDTH/2,-WINDOW_HEIGHT/2,-250);
  • glTexCoord3f(0,0,-250);
  • glEnd();
  • glPopMatrix();/*
  • unsigned char bitmap[512*512*3];
  • glGetTexImage(GL_TEXTURE_2D,0,GL_RGB,GL_UNSIGNED_BYTE,bitmap);
  • glBitmap(512,512,0,0,0,0,bitmap); */
  • glDisable(GL_TEXTURE_2D);
  • }
  • glFlush();
  • glutSwapBuffers();/*
  • if(object.collide(wall))
  • {cout<<"collision\n";
  • object.toString();
  • } */
  • if(pointerAtEdge())
  • warpPointerAtCenter();
  • }
  • void special(int key,int x,int y){
  • if(GAME_CURRENT_DISPLAY_MODE==PLAYING_MODE)
  • {switch(key)
  • {case GLUT_KEY_UP :{alpha=(alpha+10)%360;
  • glutPostRedisplay();
  • break;
  • }
  • case GLUT_KEY_DOWN :{alpha=(alpha-10)%360;
  • glutPostRedisplay();
  • break;
  • }
  • case GLUT_KEY_LEFT :{beta=(beta+10)%360;
  • glutPostRedisplay();
  • break;
  • }
  • case GLUT_KEY_RIGHT :{beta=(beta-10)%360;
  • glutPostRedisplay();
  • break;
  • }
  • case GLUT_KEY_PAGE_UP :{Gamma=(Gamma+10)%360;
  • glutPostRedisplay();
  • break;
  • }
  • case GLUT_KEY_PAGE_DOWN :{Gamma=(Gamma-10)%360;
  • glutPostRedisplay();
  • break;
  • }
  • case GLUT_KEY_F1 :{delta=(delta+10)%360;
  • glutPostRedisplay();
  • break;
  • }
  • case GLUT_KEY_F2 :{delta=(delta-10)%360;
  • glutPostRedisplay();
  • break;
  • }
  • case GLUT_KEY_F3 :{GAME_CURRENT_DISPLAY_MODE=PAUSING_MODE;
  • current_menu_texture_index=GAME_CURRENT_DISPLAY_MODE*4;
  • glutPostRedisplay();
  • break;
  • }
  • default :{exit(EXIT_SUCCESS);
  • break;
  • }
  • }
  • }
  • else
  • {switch(key)
  • {case GLUT_KEY_F4 :{exit(EXIT_SUCCESS);
  • break;
  • }
  • case GLUT_KEY_F3 :{switch(GAME_CURRENT_DISPLAY_MODE)
  • {case STARTING_MODE :{GAME_CURRENT_DISPLAY_MODE=INTRO_MODE;
  • current_menu_texture_index=GAME_CURRENT_DISPLAY_MODE*4;
  • break;
  • }
  • case INTRO_MODE :{GAME_CURRENT_DISPLAY_MODE=PLAYING_MODE;
  • current_menu_texture_index=GAME_CURRENT_DISPLAY_MODE*4;
  • break;
  • }
  • case PAUSING_MODE :{GAME_CURRENT_DISPLAY_MODE=PLAYING_MODE;
  • //glPopMatrix();
  • current_menu_texture_index=GAME_CURRENT_DISPLAY_MODE*4;
  • break;
  • }
  • case DYING_MODE :{GAME_CURRENT_DISPLAY_MODE=GAME_OVER_MODE;
  • current_menu_texture_index=GAME_CURRENT_DISPLAY_MODE*4;
  • break;
  • }
  • case GAME_OVER_MODE :{GAME_CURRENT_DISPLAY_MODE=PLAYING_MODE;
  • current_menu_texture_index=GAME_CURRENT_DISPLAY_MODE*4;
  • break;
  • }
  • }
  • glutPostRedisplay();
  • break;
  • }
  • }
  • }
  • }
  • void keyboard(unsigned char key,int x,int y){
  • if(GAME_CURRENT_DISPLAY_MODE==PLAYING_MODE)
  • {switch(key)
  • {case 'z':{cam.moveLocal(0,0,1,5);
  • /*
  • cam.move(5);
  • cam.move(0);*/
  • break;
  • }
  • case 'q':{cam.moveLocal(1,0,0,-5);/*
  • cam.move(-5);
  • cam.move(0); */
  • break;
  • }
  • case 's':{cam.moveLocal(1,0,0,5);/*
  • cam.move(5);
  • cam.move(0); */
  • break;
  • }
  • case 'w':{cam.moveLocal(0,0,1,-5);
  • /*cam.move(-5);
  • cam.move(0);*/
  • break;
  • }
  • case 't':{object.moveLocal(0,0,1,5);
  • break;
  • }
  • case 'v':{object.moveLocal(0,0,1,-5);
  • break;
  • }
  • case 'f':{object.moveLocal(1,0,0,-5);
  • break;
  • }
  • case 'g':{object.moveLocal(1,0,0,5);
  • break;
  • }
  • }
  • //cam.setView();
  • glutPostRedisplay();
  • }
  • }
  • void passiveMotion(int x,int y){
  • /*if(GAME_CURRENT_DISPLAY_MODE==PLAYING_MODE)
  • {*/
  • float shiftx=0,shifty=0;
  • if(pointerx-x<0)
  • shiftx=-5.0f/60.0f;
  • else if(pointerx-x>0)
  • shiftx=5.0f/60.0f;
  • pointerx=x;
  • cam.rotateGlobal(shiftx,0,1,0);
  • if(y-pointery<0)
  • shifty=-5.0f/60.0f;
  • else if(y-pointery>0)
  • shifty=5.0f/60.0f;
  • pointery=y;
  • cam.rotateGlobal(shifty,1,0,0);
  • glutPostRedisplay();
  • /* }
  • else
  • {pointerx=x;
  • pointery=y;
  • }*/
  • }
  • void idle(){
  • if(GAME_CURRENT_DISPLAY_MODE==PLAYING_MODE||
  • GAME_CURRENT_DISPLAY_MODE==DYING_MODE)
  • {
  • /*glutPostRedisplay();*/
  • }
  • else
  • {if(current_menu_texture_index!=(GAME_CURRENT_DISPLAY_MODE*4)+3)
  • current_menu_texture_index++;
  • else
  • current_menu_texture_index=GAME_CURRENT_DISPLAY_MODE*4;
  • //cout<<current_menu_texture_index<<" "<<menu_textures_ID[current_menu_texture_index]<<" \n";
  • //I should use a timer here
  • glutPostRedisplay();
  • }
  • }
  • int main(int argc,char* argv[]){
  • GAME_CURRENT_DISPLAY_MODE=0;
  • glutInit(&argc,argv);
  • glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH);
  • glutCreateWindow("");
  • glutFullScreen();
  • init();
  • glutIdleFunc(idle);
  • glutPassiveMotionFunc(passiveMotion);
  • glutDisplayFunc(display);
  • glutSpecialFunc(special);
  • glutKeyboardFunc(keyboard);
  • glutMainLoop();
  • exit(EXIT_SUCCESS);
  • }
#include <GL/glut.h>
#include <GL/glext.h>
#include <string.h>
#include <stdlib.h>
#include <iostream.h>
#include <math.h>
#include <vector>
#ifdef WIN32_API
#define glutWarpPointer SetCursorPos
#include <windows.h>
#endif
#ifndef M_PI
#define M_PI 3.14159265359 
#endif
/*#if !defined(GLUT_WHEEL_UP)
#  define GLUT_WHEEL_UP  4
#  define GLUT_WHEEL_DOWN  5
#endif
*/
using namespace std;

//GLUT_MIDDLE_BUTTON

//http://users.ox.ac.uk/~orie1330/bmploader.html

#define BMPError char
#define BMPNOTABITMAP 'b'	//Possible error flags
#define BMPNOOPEN 'o'
#define BMPFILEERROR 'f'
#define BMPBADINT 'i'
#define BMPNOERROR '\0'
#define BMPUNKNOWNFORMAT 'u'
#include <string.h>

typedef unsigned char BYTE;

class BMPClass{

  //private: int width;
  public: int width;
  //private: int height;
  public: int height;
  //private: BYTE* bytes;//OpenGL formatted pixels
  public: BYTE* bytes;

  public: BMPClass(){
    bytes=NULL;
  }
  
  public: ~BMPClass(){
    if(bytes!=NULL) 
      delete[](bytes);
  }
  
  public: BYTE& pixel(int x,int y,int c){
    return(bytes[(y*width+x)*3+c]);
  }
  public: void allocateMem(){
    if(bytes!=NULL) 
      delete[](bytes);
    bytes=new BYTE[width*height*3];
  }	

  //Loads the bmp in fname, and puts the data in the current object
  public: BMPError LoadBMPFromFile(char* fname){
    if(sizeof(int)!=4) 
      return(BMPBADINT);
    FILE* f=fopen(fname,"rb");		//open for reading in binary mode
    if(!f) 
      return(BMPNOOPEN);
    char header[54];
    fread(header,54,1,f);			//read the 54bit main header
    if(header[0]!='B' || header[1]!='M') 
      {fclose(f);
       return(BMPNOTABITMAP);		//all bitmaps should start "BM"
      }
    //it seems gimp sometimes makes its headers small, so we have to do  hence all the fseeks
    int offset=*(unsigned int*)(header+10);
    width=*(int*)(header+18);
    height=*(int*)(header+22);
    //now the bitmap knows how big it is it can allocate its memory
    allocateMem();
    int bits=int(header[28]);		//colourdepth
    int x,y,c;
    BYTE cols[256*4];				//colourtable
    switch(bits){
      case(24):
   	{fseek(f,offset,SEEK_SET);
	 fread(bytes,width*height*3,1,f);	//24bit is easy
	 for(x=0;x<width*height*3;x+=3)		//except the format is BGR, grr
	   {BYTE temp=bytes[x];
	    bytes[x]=bytes[x+2];
	    bytes[x+2]=temp;
	   }
	 break;
        }
      case(8):
	{fread(cols,256*4,1,f);		//read colortable
	 fseek(f,offset,SEEK_SET);
	 for(y=0;y<height;++y)		//(Notice 4bytes/col for some reason)
	   for(x=0;x<width;++x)
	     {BYTE byte;			
	      fread(&byte,1,1,f);	//just read byte					
	      for(int c=0;c<3;++c)
		      pixel(x,y,c)=cols[byte*4+2-c];  //and look up in the table
	     }
	 break;
        }
      case(4):
	{fread(cols,16*4,1,f);
	 fseek(f,offset,SEEK_SET);
	 for(y=0;y<256;++y)
	   for(x=0;x<256;x+=2)
	     {BYTE byte;
	      fread(&byte,1,1,f);	//as above, but need to exract two
	      for(c=0;c<3;++c)		//pixels from each byte
		      pixel(x,y,c)=cols[byte/16*4+2-c];
	      for(c=0;c<3;++c)
		      pixel(x+1,y,c)=cols[byte%16*4+2-c];
	     }
	 break;
        }
      case(1):
	{fread(cols,8,1,f);
	 fseek(f,offset,SEEK_SET);
	 for(y=0;y<height;++y)
	   for(x=0;x<width;x+=8)
	     {BYTE byte;
	      fread(&byte,1,1,f);
	      //Every byte is eight pixels
	      //so I'm shifting the byte to the relevant position, then masking out
	      //all but the lowest bit in order to get the index into the colourtable.
	      for(int x2=0;x2<8;++x2)
		      for(int c=0;c<3;++c)
			      pixel(x+x2,y,c)=cols[((byte>>(7-x2))&1)*4+2-c];
	     }
	 break;
        }
      default:
	{fclose(f);
	 return(BMPUNKNOWNFORMAT);
	}
    }
    if(ferror(f))
      {fclose(f);
       return(BMPFILEERROR);
      }
    fclose(f);
    return(BMPNOERROR);
  }

  //Translates my error codes into English	
  public: static char* TranslateBMPError(BMPError err){
    switch(err)
      {case(BMPNOTABITMAP):
	       return "This file is not a bitmap, specifically it doesn't start 'BM'";
       case(BMPNOOPEN):
	       return "Failed to open the file, suspect it doesn't exist";
       case(BMPFILEERROR):
	       return "ferror said we had an error. This error seems to not always mean anything, try ignoring it";
       case(BMPBADINT):
	       return "sizeof(int)!=4 quite a lot of rewriting probably needs to be done on the code";
       case(BMPNOERROR):
	       return "No errors detected";
       case(BMPUNKNOWNFORMAT):
	       return "Unknown bmp format, ie not 24bit, 256,16 or 2 colour";
       default:
	       return "Not a valid error code";
    }
  }

  public: GLuint loadBMPTexture(char *filename){  
    GLuint TID=0;
    if(LoadBMPFromFile(filename)!=BMPNOERROR)
      return(TID);   
    //generate texture
    glPushAttrib(GL_ENABLE_BIT);
    glEnable(GL_TEXTURE_2D);
    glGenTextures(1,&TID);
    glBindTexture(GL_TEXTURE_2D,TID);
    //setup some parameters for texture filters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);                  
    glTexImage2D(GL_TEXTURE_2D,0,3,width,height,0,GL_RGB,GL_UNSIGNED_BYTE,bytes);
    glDisable(GL_TEXTURE_2D);
    glPopAttrib();
    return(TID);
  }			
};


//#define JPEG_LIB_VERSION  62
#ifdef __cplusplus
extern "C" {
#endif
#include <jpeglib.h>
#include <jconfig.h>
#include <jerror.h>
#include <jmorecfg.h>
//OpenGL texture info
typedef struct{
	       GLsizei width;
	       GLsizei height;

	       GLenum format;
	       GLint internalFormat;
	       GLuint id;

	       GLubyte *texels;
	      } gl_texture_t;

gl_texture_t* ReadJPEGFromFile(const char *filename){
  gl_texture_t *texinfo = NULL;
  FILE *fp = NULL;
  struct jpeg_decompress_struct cinfo;
  struct jpeg_error_mgr jerr;
  JSAMPROW j;
  int i;

  //open image file
  fp = fopen (filename, "rb");
  if (!fp)
    {
      fprintf (stderr, "error: couldn't open \"%s\"!\n", filename);
      return NULL;
    }

  //create and configure decompressor 
  jpeg_create_decompress (&cinfo);
  cinfo.err = jpeg_std_error (&jerr);
  jpeg_stdio_src (&cinfo, fp);

  //read header and prepare for decompression
  jpeg_read_header (&cinfo, TRUE);
  jpeg_start_decompress (&cinfo);

  //initialize image's member variables
  texinfo = (gl_texture_t *)malloc (sizeof (gl_texture_t));
  texinfo->width = cinfo.image_width;
  texinfo->height = cinfo.image_height;
  texinfo->internalFormat = cinfo.num_components;

  if (cinfo.num_components == 1)
    texinfo->format = GL_LUMINANCE;
  else
    texinfo->format = GL_RGB;

  texinfo->texels = (GLubyte *)malloc (sizeof (GLubyte) * texinfo->width
			       * texinfo->height * texinfo->internalFormat);

  //extract each scanline of the image
  for (i = 0; i < texinfo->height; ++i)
    {
      j = (texinfo->texels +
	((texinfo->height - (i + 1)) * texinfo->width * texinfo->internalFormat));
      jpeg_read_scanlines (&cinfo, &j, 1);
    }

  //finish decompression and release memory
  jpeg_finish_decompress (&cinfo);
  jpeg_destroy_decompress (&cinfo);

  fclose (fp);
  return texinfo;
}

GLuint loadJPEGTexture (const char *filename){
  gl_texture_t *jpeg_tex = NULL;
  GLuint tex_id = 0;

  jpeg_tex = ReadJPEGFromFile (filename);

  if (jpeg_tex && jpeg_tex->texels)
    {
      //generate texture
      glGenTextures (1, &jpeg_tex->id);
      glBindTexture (GL_TEXTURE_2D, jpeg_tex->id);

      //setup some parameters for texture filters and mipmapping
      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);      

      gluBuild2DMipmaps (GL_TEXTURE_2D, jpeg_tex->internalFormat,
			 jpeg_tex->width, jpeg_tex->height,
			 jpeg_tex->format, GL_UNSIGNED_BYTE, jpeg_tex->texels);

      tex_id = jpeg_tex->id;

      //OpenGL has its own copy of texture data
      free (jpeg_tex->texels);
      free (jpeg_tex);
    }

  return tex_id;
}

#ifdef __cplusplus
}
#endif

void crossProduct(float *x,float *y,float *z,float x1,float y1,float z1,float x2,float y2,float z2){
  (*x)=y1*z2-z1*y2;
  (*y)=z1*x2-x1*z2;
  (*z)=x1*y2-y1*x2;
}

void crossProduct(float* vector,float* vector1,float* vector2){
  vector[0]=vector1[1]*vector2[2]-vector1[2]*vector2[1];
  vector[1]=vector1[2]*vector2[0]-vector1[0]*vector2[2];
  vector[2]=vector1[0]*vector2[1]-vector1[1]*vector2[0];
}

float dot(float x1,float y1,float z1,float x2,float y2,float z2){
  return((x1*x2)+(y1*y2)+(z1*z2));
}

float dot(float* vector1,float* vector2){
  return((vector1[0]*vector2[0])+
         (vector1[1]*vector2[1])+
	 (vector1[2]*vector2[2]));
}

float norm(float x,float y,float z){
  return(sqrt(x*x+y*y+z*z));
}

float norm(float* vector){
  return(sqrt(vector[0]*vector[0]+vector[1]*vector[1]+vector[2]*vector[2]));
}

bool equals(float* vector1,float* vector2){
  return(vector1[0]==vector2[0]&&vector1[1]==vector2[1]&&vector1[2]==vector2[2]);
}

void vectorFromBipoint(float* vector,float* point1,float* point2){
  vector[0]=point2[0]-point1[0];
  vector[1]=point2[1]-point1[1];
  vector[2]=point2[2]-point1[2];
}


void normalize(float *vector){
  float n;
  if((n=norm(vector))==0) 
    return;//avoids a division by zero
  vector[0]/=n;
  vector[1]/=n;
  vector[2]/=n; 
}

void normalize(float *x,float *y,float *z){
  float n;
  if((n=norm((*x),(*y),(*z)))==0) 
    return;//avoids a division by zero
  (*x)/=n;
  (*y)/=n;
  (*z)/=n;  
}

class UnitQuaternion{

  private: float m_w;
  private: float m_x;
  private: float m_y;
  private: float m_z;
  
  public: inline void setW(float w){
    m_w=w;
  }
  
  public: inline void setX(float x){
    m_x=x;
  }
  
  public: inline void setY(float y){
    m_y=y;
  }
  
  public: inline void setZ(float z){
    m_z=z;
  }
  
  public: inline void createNeutralUnitQuaternion(){
    m_w=1;
    m_x=0;
    m_y=0;
    m_z=0;
  }
  
  //warning!! angle in radians!
  public: void createFromAxisAngle(float angle,float x,float y,float z){
    float r=(float)sin(angle/2.0f);
    m_w=(float)cos(angle/2.0f);
    m_x=x*r;
    m_y=y*r;
    m_z=z*r;
  }
  
  public: float norm(){
    return(sqrt(m_w*m_w+m_x*m_x+m_y*m_y+m_z*m_z));
  }
  
  public: void normalize(){
    float n;
    if((n=norm())==0.0f)
      return;
    m_w/=n;
    m_x/=n;
    m_y/=n;
    m_z/=n;
  }  
  
  public: void createMatrix(float* matrix){    
    /*float mxXmx=m_x*m_x,myXmy=m_y*m_y,mzXmz=m_z*m_z;
    float mxXmy=m_x*m_y,mzXmw=m_z*m_w,mxXmz=m_x*m_z,myXmw=m_y*m_w,mxXmw=m_x*m_w,myXmz=m_y*m_z;    
    matrix[0]=1.0f-2.0f*(myXmy+mzXmz);
    matrix[1]=2.0f*(mxXmy+mzXmw);
    matrix[2]=2.0f*(mxXmz-myXmw);
    matrix[3]=0.0f;
    matrix[4]=2.0f*(mxXmy-mzXmw);
    matrix[5]=1.0f-2.0f*(mxXmx+mzXmz);
    matrix[6]=2.0f*(myXmz+mxXmw);
    matrix[7]=0.0f;
    matrix[8]=2.0f*(mxXmz+myXmw);
    matrix[9]=2.0f*(myXmz-mxXmw);
    matrix[10]=1.0f-2.0f*(mxXmx+myXmy);
    matrix[11]=0.0f;
    matrix[12]=0.0f;
    matrix[13]=0.0f;
    matrix[14]=0.0f;
    matrix[15]=1.0f;*/
    float myXmyX2=m_y*m_y*2.0f,mzXmzX2=m_z*m_z*2.0f,mzXmw=m_z*m_w,
          myXmw=m_y*m_w,mxXmw=m_x*m_w;
    matrix[0]=1.0f-(myXmyX2+mzXmzX2);
    matrix[1]=2.0f*(m_x*m_y+mzXmw);
    matrix[2]=2.0f*(m_x*m_z-myXmw);
    matrix[3]=0.0f;
    matrix[4]=matrix[1]-4.0f*mzXmw;
    matrix[5]=matrix[0]-2.0f*m_x*m_x+myXmyX2;
    matrix[6]=2.0f*(m_y*m_z+mxXmw);
    matrix[7]=0.0f;
    matrix[8]=matrix[2]+4.0f*myXmw;
    matrix[9]=matrix[6]-4.0f*mxXmw;
    matrix[10]=matrix[5]+mzXmzX2-myXmyX2;
    matrix[11]=0.0f;
    matrix[12]=0.0f;
    matrix[13]=0.0f;
    matrix[14]=0.0f;
    matrix[15]=1.0f;
  }

  public: void createInvertedMatrix(float* matrix){        
    float myXmyX2=m_y*m_y*2.0f,mzXmzX2=m_z*m_z*2.0f,mzXmw=m_z*m_w,
          myXmw=m_y*m_w,mxXmw=m_x*m_w;
    matrix[0]=1.0f-(myXmyX2+mzXmzX2);
    matrix[4]=2.0f*(m_x*m_y+mzXmw);
    matrix[8]=2.0f*(m_x*m_z-myXmw);
    matrix[3]=0.0f;
    matrix[1]=matrix[4]-4.0f*mzXmw;
    matrix[5]=matrix[0]-2.0f*m_x*m_x+myXmyX2;
    matrix[9]=2.0f*(m_y*m_z+mxXmw);
    matrix[7]=0.0f;
    matrix[2]=matrix[8]+4.0f*myXmw;
    matrix[6]=matrix[9]-4.0f*mxXmw;
    matrix[10]=matrix[5]+mzXmzX2-myXmyX2;
    matrix[11]=0.0f;
    matrix[12]=0.0f;
    matrix[13]=0.0f;
    matrix[14]=0.0f;
    matrix[15]=1.0f;
  }
  
  public: UnitQuaternion operator *(UnitQuaternion q){
    UnitQuaternion r;
    r.m_w=m_w*q.m_w-m_x*q.m_x-m_y*q.m_y-m_z*q.m_z;
    r.m_x=m_w*q.m_x+m_x*q.m_w+m_y*q.m_z-m_z*q.m_y;
    r.m_y=m_w*q.m_y+m_y*q.m_w+m_z*q.m_x-m_x*q.m_z;
    r.m_z=m_w*q.m_z+m_z*q.m_w+m_x*q.m_y-m_y*q.m_x;
    return(r);
  }
      
};


class MovingObject{  
  protected: float Transform[16];
  protected: float old_position[16];
  protected: UnitQuaternion m_qPitch;
  protected: UnitQuaternion m_qYaw;
  protected: UnitQuaternion m_qRoll;
  //angles of the movement from the initial position
  protected: float m_PitchRadians;
  protected: float m_YawRadians;
  protected: float m_RollRadians;
  //angles of the bounding ellipsoide with the axes at the beginning
  protected: float initial_m_PitchRadians;
  protected: float initial_m_YawRadians;
  protected: float initial_m_RollRadians;
  
  protected: float* vertexArray;
  protected: float* textureCoordinateArray;
  protected: float* normalArray;
  protected: unsigned int* vertexPerTextureArray;
  protected: unsigned int* textureArray;
  protected: unsigned int vertexCount;
  protected: unsigned int textureCount;
  
  public: MovingObject(float x=0.0f,float y=0.0f,float z=0.0f,
  float initial_m_PitchRadians=0.0f,float initial_m_YawRadians=0.0f,
  float initial_m_RollRadians=0.0f,
  float* vertexArray=NULL,unsigned int vertexCount=0,
  float* textureCoordinateArray=NULL,float* normalArray=NULL,
  unsigned int* vertexPerTextureArray=NULL,
  unsigned int* textureArray=NULL,unsigned int textureCount=0){
    this->vertexArray=vertexArray;
    this->textureCoordinateArray=textureCoordinateArray;
    this->normalArray=normalArray;
    this->textureArray=textureArray;
    this->vertexPerTextureArray=vertexPerTextureArray;
    //declare them here
    //use sizeof to get their sizes like this:
    //vertexCount=sizeof(vertexArray)/sizeof(float);
    //textureCount=sizeof(textureArray)/sizeof(float);
    //warning!! vertexPerTextureArray's size must be equals to
    //textureCount!!
    //use glGenTextures to initialize textureArray 
    //    glBindTexture to select the texture
    //    glTexImage2D or GluBuild2DMipmaps to load the image data in the texture 
    this->textureCount=textureCount;
    this->vertexCount=vertexCount;
    //4x4 matrix filled with 0    
    Transform[0]=1.0f;
    Transform[1]=0.0f;
    Transform[2]=0.0f;
    Transform[3]=0.0f;
    Transform[4]=0.0f;    
    Transform[5]=1.0f;
    Transform[6]=0.0f;
    Transform[7]=0.0f;
    Transform[8]=0.0f;
    Transform[9]=0.0f;
    Transform[10]=-1.0f;
    Transform[11]=0.0f;    
    Transform[12]=x;//translation matrix
    Transform[13]=y;
    Transform[14]=z;
    Transform[15]=1.0f;
    old_position[0]=x;
    old_position[1]=y;
    old_position[2]=z;
    m_PitchRadians=0.0f;
    m_YawRadians=0.0f;
    m_RollRadians=0.0f;
    this->initial_m_PitchRadians=initial_m_PitchRadians;
    this->initial_m_YawRadians=initial_m_YawRadians;
    this->initial_m_RollRadians=initial_m_RollRadians;   
    m_qPitch.createNeutralUnitQuaternion();
    m_qYaw.createNeutralUnitQuaternion();
    m_qRoll.createNeutralUnitQuaternion();      
  }
	  
  public: virtual ~MovingObject(){
    if(vertexArray!=NULL)
      delete[](vertexArray);
    if(textureCoordinateArray!=NULL)
      delete[](textureCoordinateArray);
    if(normalArray!=NULL)
      delete[](normalArray);
    if(textureArray!=NULL)
      delete[](textureArray);
  }

  public: virtual void undoPositionChanges(){
    float tmp[3];
    int i;
    for(i=0;i<16;i++)
      tmp[i]=old_position[i];
    for(i=0;i<16;i++)
      old_position[i]=Transform[i];
    for(i=0;i<16;i++)
      Transform[i]=tmp[i];     
  }

  public: virtual void updateOldPosition(){
    for(int i=0;i<16;i++)
      old_position[i]=Transform[i];  
  }
		  
  public: virtual void moveLocal(float x,float y,float z,float distance=1){
    float dx=x*Transform[0]+y*Transform[4]+z*Transform[8];
    float dy=x*Transform[1]+y*Transform[5]+z*Transform[9];
    float dz=x*Transform[2]+y*Transform[6]+z*Transform[10];
    updateOldPosition();
    Transform[12]+=dx*distance;
    Transform[13]+=dy*distance;
    Transform[14]+=dz*distance;    
  }
	  
  public: virtual void moveGlobal(float x,float y,float z,float distance=1){
    updateOldPosition();
    Transform[12]+=x*distance;
    Transform[13]+=y*distance;
    Transform[14]+=z*distance;
  }

  public: virtual void rotateLocal(float angle,float x,float y,float z){
    //rotation at the point (0,0,0) 
    //around the vector (x,y,z) by deg degrees
    //glPushMatrix();
    //glLoadMatrixf(Transform);
    //glRotatef(deg,x,y,z);
    //glGetFloatv(GL_MODELVIEW_MATRIX,Transform);
    //glPopMatrix(); 
    if(x!=0)
      m_PitchRadians=0;
    if(y!=0)
      m_YawRadians=0;
    if(z!=0)
      m_RollRadians=0;
    rotateGlobal(angle,x,y,z);    
  }
	  
  public: virtual void rotateGlobal(float angle,float x,float y,float z){
    //we have to invert the rotations to get global axes 
    //in local coordinates. That's just the transposed matrix 
    //here   
    /*
    float dx=x*Transform[0]+y*Transform[1]+z*Transform[2];
    float dy=x*Transform[4]+y*Transform[5]+z*Transform[6];
    float dz=x*Transform[8]+y*Transform[9]+z*Transform[10];
    */
    //           Right           Up             Forward
    // FIRST TRY WITH UVN
    /*
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();    
    glLoadMatrixf(Transform);   
    glRotatef(angle,dx,dy,dz);    
    glGetFloatv(GL_MODELVIEW_MATRIX,Transform); 
    glPopMatrix();*/
    //SECOND TRY WITH QUATERNIONS BUT NOT WORKING
    //STILL GIMBAL LOCK
    /*
    if(dx==0)    
      m_qPitch.createNeutralUnitQuaternion();
    else      
      m_qPitch.createFromAxisAngle(angle,dx,0.0f,0.0f); 
    if(dy==0)    
      m_qYaw.createNeutralUnitQuaternion();
    else      
      m_qYaw.createFromAxisAngle(angle,0.0f,dy,0.0f); 
    if(dz==0)    
      m_qRoll.createNeutralUnitQuaternion();
    else      
      m_qRoll.createFromAxisAngle(angle,0.0f,0.0f,dz); 
    UnitQuaternion q=m_qPitch*m_qYaw*m_qRoll;    
    float matrix[16];
    q.createInvertedMatrix(matrix);
    glPushMatrix();
    glLoadMatrixf(matrix);       
    glMultMatrixf(Transform);
    float tmp[3]={Transform[12],Transform[13],Transform[14]};  
    glGetFloatv(GL_MODELVIEW_MATRIX,Transform);
    Transform[12]=tmp[0];
    Transform[13]=tmp[1];
    Transform[14]=tmp[2];
    glPopMatrix();   
    */
    // NEW                        NEW                    NEW
    if(x!=0.0f)    
      {m_PitchRadians+=angle;
       if(m_PitchRadians<-M_PI)
         m_PitchRadians+=2*M_PI;
       else 
         if(m_PitchRadians>M_PI)
	   m_PitchRadians-=2*M_PI;
       m_qPitch.createFromAxisAngle(m_PitchRadians,1.0f,0.0f,0.0f);
       m_qPitch.normalize(); 
      }
    if(y!=0.0f)    
      {m_YawRadians+=angle;
       if(m_YawRadians<-M_PI)
         m_YawRadians+=2*M_PI;
       else 
         if(m_YawRadians>M_PI)
	   m_YawRadians-=2*M_PI;
       m_qYaw.createFromAxisAngle(m_YawRadians,0.0f,1.0f,0.0f);
       m_qYaw.normalize();
      }              
    if(z!=0.0f)    
      {m_RollRadians+=angle;
       if(m_RollRadians<-M_PI)
         m_RollRadians+=2*M_PI;
       else 
         if(m_RollRadians>M_PI)
	   m_RollRadians-=2*M_PI;
       m_qRoll.createFromAxisAngle(m_RollRadians,0.0f,0.0f,1.0f);
       m_qRoll.normalize(); 
      }         
    UnitQuaternion q=m_qPitch*m_qYaw*m_qRoll;
    q.normalize();
    updateOldPosition();   
    float position[3]={Transform[12],Transform[13],Transform[14]}; 
    q.createMatrix(Transform); 
    Transform[12]=position[0];
    Transform[13]=position[1];
    Transform[14]=position[2];      
    /*
    cout <<"\n[[";
    for(int i=0,j=0;i<16;i++)
      {if(matrix[(i*4)%16+j]==-0)
         matrix[(i*4)%16+j]=0;
       cout <<matrix[(i*4)%16+j]<<" ";
       if(i%4==3) 
         {j++;
	  if(i!=15)
	    cout <<"]\n [";
	  else cout <<"]]";
	 }       
      }
    cout <<"\n"; */        
    /*
    cout <<"\n[[";
    for(int i=0,j=0;i<16;i++)
      {if(Transform[(i*4)%16+j]==-0)
         Transform[(i*4)%16+j]=0;
       cout <<Transform[(i*4)%16+j]<<" ";
       if(i%4==3) 
         {j++;
	  if(i!=15)
	    cout <<"]\n [";
	  else cout <<"]]";
	 }       
      }
    cout <<"\n";*/
  }
  
  public: void toString(){
    cout <<"\n[[";
    for(int i=0,j=0;i<16;i++)
      {if(Transform[(i*4)%16+j]==-0)
         Transform[(i*4)%16+j]=0;
       cout <<Transform[(i*4)%16+j]<<" ";
       if(i%4==3) 
         {j++;
	  if(i!=15)
	    cout <<"]\n [";
	  else cout <<"]]";
	 }       
      }
    cout <<"\n";
  }
  
  public: virtual void draw(){
    //we need to know: 
    //  the number of vertices (= the number of normals)
    //             ? (= the number of texture coordinates)
    //  the number of textures
    //  the numbers of vertices to use before changing
    //  the current texture that has to be used
    //          OR
    //  the number of texture=the number of vertices/4 
    glPushMatrix();
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_TEXTURE_2D);
    //glLockArrays();
    glVertexPointer(3,GL_FLOAT,0,vertexArray);
    glTexCoordPointer(3,GL_FLOAT,0,textureCoordinateArray);
    glNormalPointer(GL_FLOAT,0,normalArray);
    glLoadMatrixf(Transform);
    for(unsigned int i=0,j=0;i<textureCount&&j<vertexCount;i++)
      {glBindTexture(GL_TEXTURE_2D,textureArray[i]);      
       glDrawArrays(GL_POLYGON,j,vertexPerTextureArray[i]);
       j+=vertexPerTextureArray[i];
      }
    //glUnlockArrays(); 
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_TEXTURE_2D);
    glPopMatrix();
  }  
};

class Camera :public MovingObject{
  private: float min_m_PitchRadians;
  private: float min_m_YawRadians;
  private: float min_m_RollRadians;
  private: float max_m_PitchRadians;
  private: float max_m_YawRadians;
  private: float max_m_RollRadians;

  public: Camera(float x=0.0f,float y=0.0f,float z=0.0f,
    float min_m_PitchRadians=-2*M_PI,
    float min_m_YawRadians=-2*M_PI,
    float min_m_RollRadians=-2*M_PI,
    float max_m_PitchRadians=2*M_PI,
    float max_m_YawRadians=2*M_PI,
    float max_m_RollRadians=2*M_PI){
    MovingObject::MovingObject(x,y,z);
    //default behaviour :
    //doesn't clamp any angle while rotating
    this->min_m_PitchRadians=min_m_PitchRadians;
    this->min_m_YawRadians=min_m_YawRadians;
    this->min_m_RollRadians=min_m_RollRadians;
    this->max_m_PitchRadians=max_m_PitchRadians;
    this->max_m_YawRadians=max_m_YawRadians;
    this->max_m_RollRadians=max_m_RollRadians;    
  }

  //protected: virtual void collide(){}

  public: virtual void moveLocal(float x,float y,float z,float distance=1){
    MovingObject::moveLocal(x,y,z,distance);
    setView();    
  }
  
  public: virtual void moveGlobal(float x,float y,float z,float distance=1){
    MovingObject::moveGlobal(x,y,z,distance);
    setView();
  }
  
  public: virtual void rotateLocal(float angle,float x,float y,float z){
    if(x!=0)
      m_PitchRadians=0;
    if(y!=0)
      m_YawRadians=0;
    if(z!=0)
      m_RollRadians=0;
    rotateGlobal(angle,x,y,z);
    setView();    
  }
  
  public: virtual void rotateGlobal(float angle,float x,float y,float z){    
    if(x!=0.0f)    
      {m_PitchRadians+=angle;
       if(m_PitchRadians<-M_PI)
         m_PitchRadians+=2*M_PI;
       else 
         if(m_PitchRadians>M_PI)
	   m_PitchRadians-=2*M_PI;
       if(m_PitchRadians<min_m_PitchRadians)
         m_PitchRadians=min_m_PitchRadians;
       else
         if(m_PitchRadians>max_m_PitchRadians)
           m_PitchRadians=max_m_PitchRadians;
       m_qPitch.createFromAxisAngle(m_PitchRadians,1.0f,0.0f,0.0f);
       m_qPitch.normalize(); 
      }
    if(y!=0.0f)    
      {m_YawRadians+=angle;
       if(m_YawRadians<-M_PI)
         m_YawRadians+=2*M_PI;
       else 
         if(m_YawRadians>M_PI)
	   m_YawRadians-=2*M_PI;
       if(m_YawRadians<min_m_YawRadians)
         m_YawRadians=min_m_YawRadians;
       else
         if(m_YawRadians>max_m_YawRadians)
           m_YawRadians=max_m_YawRadians; 
       m_qYaw.createFromAxisAngle(m_YawRadians,0.0f,1.0f,0.0f);
       m_qYaw.normalize();
      }              
    if(z!=0.0f)    
      {m_RollRadians+=angle;
       if(m_RollRadians<-M_PI)
         m_RollRadians+=2*M_PI;
       else 
         if(m_RollRadians>M_PI)
	   m_RollRadians-=2*M_PI;
       if(m_RollRadians<min_m_RollRadians)
         m_RollRadians=min_m_RollRadians;
       else
         if(m_RollRadians>max_m_RollRadians)
           m_RollRadians=max_m_RollRadians; 
       m_qRoll.createFromAxisAngle(m_RollRadians,0.0f,0.0f,1.0f);
       m_qRoll.normalize(); 
      }         
    UnitQuaternion q=m_qPitch*m_qYaw*m_qRoll;
    q.normalize();
    updateOldPosition();   
    float position[3]={Transform[12],Transform[13],Transform[14]}; 
    q.createMatrix(Transform); 
    Transform[12]=position[0];
    Transform[13]=position[1];
    Transform[14]=position[2];      
    setView();
  }

  protected: virtual void setView(){    
    float viewmatrix[16]={Transform[0],Transform[4],-Transform[8],0 
                	 ,Transform[1],Transform[5],-Transform[9],0  
			 ,Transform[2],Transform[6],-Transform[10],0 
			 ,-(Transform[0]*Transform[12]
		          +Transform[1]*Transform[13]
			  +Transform[2]*Transform[14])
			 ,-(Transform[4]*Transform[12]
		          +Transform[5]*Transform[13]
			  +Transform[6]*Transform[14])
			 ,(Transform[8]*Transform[12]
		          +Transform[9]*Transform[13]
			  +Transform[10]*Transform[14])
			 ,1};
    glLoadMatrixf(viewmatrix);/*
    cout <<"\n[[";
    for(int i=0,j=0;i<16;i++)
      {if(viewmatrix[(i*4)%16+j]==-0)
         viewmatrix[(i*4)%16+j]=0;
       cout <<viewmatrix[(i*4)%16+j]<<" ";
       if(i%4==3) 
         {j++;
	  if(i!=15)
	    cout <<"]\n [";
	  else cout <<"]]";
	 }       
      }
    cout <<"\n";
    gluLookAt(Position[0],Position[1],Position[2]
             ,Forward[0]+Position[0],Forward[1]+Position[1],Forward[2]+Position[2]
	     ,Up[0],Up[1],Up[2]);*/
  }
  
};

class FlatSurface{
  private: float center[3];
  private: float bound[12];
  private: float normal[3];

  public: FlatSurface(float bound1x,float bound1y,float bound1z,
		      float bound2x,float bound2y,float bound2z,
		      float bound3x,float bound3y,float bound3z,
		      float bound4x,float bound4y,float bound4z){    
    this->bound[0]=bound1x;
    this->bound[1]=bound1y;
    this->bound[2]=bound1z;
    this->bound[3]=bound2x;
    this->bound[4]=bound2y;
    this->bound[5]=bound2z;
    this->bound[6]=bound3x;
    this->bound[7]=bound3y;
    this->bound[8]=bound3z;
    this->bound[9]=bound4x;
    this->bound[10]=bound4y;
    this->bound[11]=bound4z;
    this->center[0]=(bound1x+bound3x)/2;
    this->center[1]=(bound1y+bound3y)/2;
    this->center[2]=(bound1z+bound3z)/2;
    crossProduct(&normal[0],&normal[1],&normal[2],
                 (bound2x-bound1x),(bound2y-bound1y),(bound2z-bound1z),
		 (bound4x-bound1x),(bound4y-bound1y),(bound4z-bound1z));
    normalize(normal);		      
  }
  
  private: void updateNormal(){
    crossProduct(&normal[0],&normal[1],&normal[2],
                 (bound[3]-bound[0]),(bound[4]-bound[1]),(bound[5]-bound[2]),
		 (bound[9]-bound[0]),(bound[10]-bound[1]),(bound[11]-bound[2]));
    normalize(normal);
  }
  
  public: float* getCenter(){
    return(center);
  }
  
  public: float* getBounds(){
    return(bound);
  }
  
  public: float* getNormal(){
    return(normal);
  }
  
  public: bool contains(float* point){
    //b1, b2, b3 and b4 are the rectangle's bounds
    //a is the point supposed to be a collision point
    float b1b3[3];
    vectorFromBipoint(b1b3,&bound[0],&bound[6]);
    float b1a[3];
    vectorFromBipoint(b1a,&bound[0],point);
    float n;
    if((n=norm(b1a))>norm(b1b3))
      return(false);
    if(n==0)
      return(true);
    float cosb1b2b1a,n2,b1b2[3];
    vectorFromBipoint(b1b2,&bound[0],&bound[3]);
    n2=norm(b1b2);
    if((cosb1b2b1a=dot(b1b2,b1a)/(n2*n))<0)
      return(false);
    float k1;
    if(cosb1b2b1a==1)    
      {if(b1b2[0]!=0)      
         k1=b1a[0]/b1b2[0];
       else
         if(b1b2[1]!=0)      
           k1=b1a[1]/b1b2[1];
	 else
	   k1=b1a[2]/b1b2[2];
       return(k1>0&&k1<=1);
      }
    float b1b4[3],k2;
    vectorFromBipoint(b1b4,&bound[0],&bound[9]);
    if(cosb1b2b1a==0)
      {if(b1b4[0]!=0)
         k2=b1a[0]/b1b4[0];
       else
         if(b1b4[1]!=0)
           k2=b1a[1]/b1b4[1];
	 else
	   k2=b1a[2]/b1b4[2];
       return(k2>0&&k2<=1);
      }
    if((k1=(cosb1b2b1a*n)/n2)<=0||k1>1)
      return(false);
    float cosb1b4b1a,n4=norm(b1b4);
    if((cosb1b4b1a=dot(b1b4,b1a)/(n4*n))<0)
      return(false);
    return((k2=(cosb1b4b1a*n)/n4)>0&&k2<=1);
  }
  
  public: void draw(){}
  
};

class WallSet{
  private: vector<FlatSurface> wallsVector;
  //I need to modify FlatSurface to allow it to 
  //be able to contain information about the way
  //to draw it
  public: WallSet(FlatSurface walls[]=NULL,unsigned int count=0){
    for(unsigned int i=0;i<count;i++)
      wallsVector.push_back(walls[i]);
  }
  
  public: void addWall(FlatSurface wall){
    wallsVector.push_back(wall);
  }
  
  public: FlatSurface getWall(int index){
    return(wallsVector[index]);
  }
  
  public: unsigned int size(){
    return(wallsVector.size());
  }
  
  public: void draw(){
    for(unsigned int i=0;i<size();i++)
      wallsVector[i].draw();
  }
  
  /*public: void collideAndCorrect(){
  
  }*/
  
};

class Collidable :public MovingObject{
//collidable objects considered as spheres
  //protected: unsigned int radius;
  protected: float xradius;
  protected: float yradius;
  protected: float zradius;

  public: Collidable(float x=0.0f,float y=0.0f,float z=0.0f,
    float xradius=0.0f,float yradius=0.0f,float zradius=0.0f,
    float initial_m_PitchRadians=0.0f,float initial_m_YawRadians=0.0f,
    float initial_m_RollRadians=0.0f){
    MovingObject::MovingObject(x,y,z,initial_m_PitchRadians,
    initial_m_YawRadians,initial_m_RollRadians);
    //this->radius=radius;
    this->xradius=xradius;
    this->yradius=yradius;
    this->zradius=zradius;
  }
  /*
  public: virtual void moveLocal(float x,float y,float z,float distance=1){
    MovingObject::moveLocal(x,y,z,distance);
       
  }
  
  public: virtual void moveGlobal(float x,float y,float z,float distance=1){
    MovingObject::moveGlobal(x,y,z,distance);
    
  }
  
  public: virtual void rotateLocal(float angle,float x,float y,float z){
    MovingObject::rotateLocal(angle,x,y,z);
        
  }
  
  public: virtual void rotateGlobal(float angle,float x,float y,float z){
    MovingObject::rotateGlobal(angle,x,y,z);
    
  }
  */
  //I can use this collision point and the farthest collision point
  //to compute a distance between them
  //to know how to correct the position of the object
 
  public: virtual void draw(){
    MovingObject::draw();
  }
  
  public: virtual bool collide(FlatSurface surface,float* collision_point,
  float* farthest_collision_point){
    //warning!! the distance between old and new positions must be
    //equal or shorter than the shortest DIAMETER!!
    //Otherwise, the whole movement must be treated as
    //a sum of smaller movements equal or shorter than 
    //the shortest DIAMETER
    //handles intersections and check if there is a true collision
    //does NOT handle case of piercing objects provoking multiple
    //collisions per movement        
    float d,raydirection[3];
    vectorFromBipoint(raydirection,&old_position[12],&Transform[12]);
    //cout<<"\n"<<Transform[2]<<" "<<Transform[6]<<" "<<Transform[10]<<"\n";
    if(norm(raydirection)!=1)
      normalize(raydirection);    
    if((d=dot(surface.getNormal(),raydirection))==0)
      return(false);
    //checks if the surface is parallel to the ray direction
    //why do I take the center of the surface???
    float tmp[3];
    vectorFromBipoint(tmp,&Transform[12],surface.getCenter());		  
    d=dot(surface.getNormal(),tmp)/d;
    collision_point[0]=Transform[12]+raydirection[0]*d;
    collision_point[1]=Transform[13]+raydirection[1]*d;
    collision_point[2]=Transform[14]+raydirection[2]*d;    
    if(isIn(collision_point,farthest_collision_point,raydirection))        
      return(surface.contains(collision_point));
    //If d is negative, the collision takes place behind the 
    //starting point of the ray along the opposite direction 
    //and again there is no intersection.           
    //warning!! I'm going to assume that I'm doing a rectilinear
    //movement!!
    //I check if the new position is behind the plane
    if(d<0)
      {float dprime;
       vectorFromBipoint(tmp,&old_position[12],surface.getCenter());
       dprime=dot(surface.getNormal(),tmp)/dot(surface.getNormal(),raydirection);         
       //I check if the old position is not behind the plane
       if(dprime<=0)
         return(false);/*
       collision_point[0]=old_position[12]+raydirection[0]*dprime;
       collision_point[1]=old_position[13]+raydirection[1]*dprime;
       collision_point[2]=old_position[14]+raydirection[2]*dprime;*/
       //I check if the direction line goes through the surface
       return(surface.contains(collision_point));              
      }
    //else
    //  if(d<0)
    //    then (the object has gone through the wall)
    //         length_of_movement=2*shortest_radius+1
    //         length_of_movements=norm(unnormalized_raydirection);
    //         remaining_distance=length_of_movements
    //         (subdivisions_count=ceil(length_of_movement/length_of_movements);)
    //         test a sum of smaller movements equal or shorter than 
    //         the shortest DIAMETER
    //         old_position constant, Transform[12..14] variable
    //         while(true)
    //           {if(remaining_distance>=length_of_movement)
    //              {warning!! this is a rectilinear approximation!!
    //               Transform[12]=old_position[12]+length_of_movement*raydirection[0];
    //               Transform[13]=old_position[13]+length_of_movement*raydirection[1];
    //               Transform[14]=old_position[14]+length_of_movement*raydirection[2];
    //               if(collide(surface,collision_point))
    //                 return(true);
    //               remaining_distance-=length_of_movement;
    //              }
    //            else
    //              {warning!! this is a rectilinear approximation!!
    //               Transform[12]=old_position[12]+remaining_distance*raydirection[0];
    //               Transform[13]=old_position[13]+remaining_distance*raydirection[1];
    //               Transform[14]=old_position[14]+remaining_distance*raydirection[2];
    //               if(collide(surface,collision_point))
    //                 return(true);
    //               remaining_distance=0; useless
    //               break;
    //              }
    //           }
    return(false);
  }
  
  public: virtual bool isIn(float* collision_point,float* farthest_collision_point,
  float* raydirection){
    bool result=true;      
    float collision_vector[3];
    vectorFromBipoint(collision_vector,&Transform[12],collision_point);
    float norm_col=norm(collision_vector);
    /*
    if(xradius==0)
      if(yradius==0)
        if(zradius==0)
	  {farthest_collision_point[0]=Transform[12];
           farthest_collision_point[1]=Transform[13];
           farthest_collision_point[2]=Transform[14];
	   return(norm_col<=0);
          }
	else
	  //line
      else
        if(zradius==0)
	  //line
	else
	  //ellipse
    else
      if(yradius==0)
        if(zradius==0)
	  //line
	else
	  //ellipse
      else
        if(zradius==0)
	  //ellipse
	else
	  //ellipsoide
    */
    //angles of the movement from the axes
    //=angles of the movement from the initial position
    //+angles of the initial position            
    float real_m_RollRadians=m_RollRadians+initial_m_RollRadians;
    float real_m_YawRadians=m_YawRadians+initial_m_YawRadians;
    float cosroll=cos(real_m_RollRadians);
    float sinroll=sin(real_m_RollRadians);
    float cosyaw=cos(real_m_YawRadians);
    float sinyaw=sin(real_m_YawRadians);     
    if(norm_col==0)
      {//phi==0&&theta==0       
       farthest_collision_point[0]=Transform[12]+xradius*cosyaw*cosroll;
       farthest_collision_point[1]=Transform[13]+yradius*cosyaw*sinroll;
       farthest_collision_point[2]=Transform[14]+zradius*sinyaw;
       return(true);	   
      }     
    if(xradius==yradius&&xradius==zradius)      
      result=(norm_col<=xradius);    
    else         
      if(norm_col>xradius&&norm_col>yradius&&norm_col>zradius)
	result=false;
      else
	if(norm_col<=xradius&&norm_col<=yradius&&norm_col<=zradius)      
          result=true;	               
    float a[3];    
    a[0]=xradius*cosroll+Transform[12];
    a[1]=xradius*sinroll+Transform[13];
    if(collision_point[0]!=Transform[12])
      a[2]=((xradius*cosroll/(collision_point[0]-Transform[12]))*
      (collision_point[2]-Transform[14]))+Transform[14];       
    else
      if(collision_point[1]!=Transform[13])
        a[2]=((xradius*sinroll/(collision_point[1]-Transform[13]))*
        (collision_point[2]-Transform[14]))+Transform[14];
      else
        a[2]=Transform[14]; 
    float oprimea[3];
    vectorFromBipoint(oprimea,&Transform[12],a);    
    float norm_oprimea_norm_col=norm(oprimea)*norm_col;
    //warning!! risk of division by zero
    float cosphi=dot(oprimea,collision_vector)/norm_oprimea_norm_col;    
    float oprimen[3];
    crossProduct(oprimen,oprimea,collision_vector);
    float sinphi=norm(oprimen)/norm_oprimea_norm_col;
    float c[3];
    c[0]=zradius*cos(real_m_YawRadians)+Transform[12];
    c[2]=zradius*sin(real_m_YawRadians)+Transform[14];
    if(collision_point[0]!=Transform[12])
      c[1]=((zradius*cosyaw/(collision_point[0]-Transform[12]))*
	        (collision_point[1]-Transform[13]))+Transform[13];
    else
      if(collision_point[2]!=Transform[14])
        c[1]=((zradius*sinyaw/(collision_point[2]-Transform[14]))*
	        (collision_point[1]-Transform[13]))+Transform[13];
      else
        c[1]=Transform[13];
    float oprimec[3];
    vectorFromBipoint(oprimec,&Transform[12],c);
    float norm_oprimec_norm_col=norm(oprimec)*norm_col;
    //warning!! risk of division by zero
    float costheta=dot(oprimec,collision_vector)/norm_oprimec_norm_col;
    float oprimenprime[3];
    crossProduct(oprimenprime,oprimec,collision_vector);
    float sintheta=norm(oprimenprime)/norm_oprimec_norm_col;
    //farthest collision point from the center of the ellipsoid
    float costheta_cosyaw=costheta*cosyaw;
    float cosphi_cosroll=cosphi*cosroll;
    float sintheta_sinyaw=sintheta*sinyaw;
    float sinphi_sinroll=sinphi*sinroll;
    float costheta_cosyaw___sintheta_sinyaw=
    costheta_cosyaw-sintheta_sinyaw;
    farthest_collision_point[0]=Transform[12]+xradius*
    costheta_cosyaw___sintheta_sinyaw*(cosphi_cosroll-sinphi_sinroll);
    farthest_collision_point[1]=Transform[13]+yradius*
    costheta_cosyaw___sintheta_sinyaw*(sinphi_sinroll+cosphi_cosroll);
    farthest_collision_point[2]=Transform[14]+zradius*
    (sintheta_sinyaw+costheta*cosyaw);    
    float farthest_collision_vector[3];
    vectorFromBipoint(farthest_collision_vector,&Transform[12],farthest_collision_point);
    if(norm(collision_vector)>norm(farthest_collision_vector))
      return(false);      
    return(result);
  }
  
  //I can use this distance between farthest collision points
  //to know how to correct the position of the object  
  public: virtual bool collide(Collidable object,
  float* vector_between_farthest_collision_points,float* first_farthest_collision_point){
    //warning!! the distance between old and new positions must be
    //equal or shorter than the sum of the shortest DIAMETERS!!
    //Otherwise, the whole movement must be treated as
    //a sum of smaller movements equal or shorter than 
    //the shortest DIAMETER    
    float second_farthest_collision_point[3];
    bool result=false;
    float raydirection[3];
    vectorFromBipoint(raydirection,&old_position[12],&Transform[12]);
    if(norm(raydirection)!=1)
      normalize(raydirection); 
    if(isIn(&(object.Transform[12]),first_farthest_collision_point,raydirection))      
      result=true;
      //this excludes the case O==F'
      //this excludes the case O' in this
    vectorFromBipoint(raydirection,&Transform[12],&old_position[12]); 
    if(norm(raydirection)!=1)
      normalize(raydirection);  
    if(object.isIn(&Transform[12],second_farthest_collision_point,raydirection))      
      result=true;
      //this excludes the case O in object    
    float ffprime[3];
    vectorFromBipoint(ffprime,first_farthest_collision_point,second_farthest_collision_point);
    vectorFromBipoint(vector_between_farthest_collision_points
    ,first_farthest_collision_point,second_farthest_collision_point);   
    if(result==true||equals(first_farthest_collision_point,second_farthest_collision_point))
      return(true); 
      //this excludes the case F==F'
    if(equals(&Transform[12],first_farthest_collision_point))
      {float oprimefprime[3];
       vectorFromBipoint(oprimefprime,&(object.Transform[12]),second_farthest_collision_point);
       float oprimef[3];
       vectorFromBipoint(oprimef,&(object.Transform[12]),first_farthest_collision_point);
       if(norm(oprimefprime)>=norm(oprimef))
         return(true);       
       //this excludes the case O==F
      }
    else
      {float of[3];
       vectorFromBipoint(of,&Transform[12],first_farthest_collision_point);
       float ofprime[3];
       vectorFromBipoint(ofprime,&Transform[12],second_farthest_collision_point);
       float k;
       if(ofprime[0]!=0)
	 k=of[0]/ofprime[0];
       else
	 if(ofprime[1]!=0)
           k=of[1]/ofprime[1];
	 else
           k=of[2]/ofprime[2];
       if(k>=1)
         return(true); 
       //no need to check when k<0 because it is treated
       //above, when O is in object 
      }
    return(false);
    //comment the line above and uncomment the lines below if
    //you have objects doing movements greater than their own
    //shortest diameter
    //at last, we must check if this has not gone through the object
    //we build the plane which is orthogonal to (OO') in 3 steps
    //    we use the dot product to get a vector which is 
    //  orthogonal to (OO')
    //    we use the cross product to get a vector which is
    //  orthogonal to the both vectors
    //    we sum O'F'' and O'F'' to get the last point
    //we use the class 'FlatSurface' to build a surface
    //we throw a ray and check if this was behind the plane
    //we build an other plane which is orthogonal to
    //the greatest radius and contains O
    //we check if rays from the  
    //following points go through this new plane 
    //we check if they go through the ellipse which
    //comes from the object's ellipsoide :
    //  the former origin 
    //  its projection at the top of this ellipsoide
    //  its projection at the bottom of this ellipsoide 
  } 
  
  public: virtual void collideAndCorrect(WallSet walls){
    for(unsigned int i=0;i<walls.size();i++)
      collideAndCorrect(walls.getWall(i));
  }
  
  public: virtual bool collideAndCorrect(FlatSurface surface){
    float collision_point[3];
    float farthest_collision_point[3];      
    if(collide(surface,collision_point,farthest_collision_point))
      {reactDuringCollisionWith(surface,collision_point,farthest_collision_point);
       float tmp[3];
       vectorFromBipoint(tmp,&Transform[12],&old_position[12]);
       float farthest_collision_vector[3];
       vectorFromBipoint(farthest_collision_vector,collision_point
       ,farthest_collision_point);
       float n=norm(farthest_collision_vector);
       tmp[0]*=n+0.0001f;
       tmp[1]*=n+0.0001f;
       tmp[2]*=n+0.0001f;       
       correct(tmp);
       return(true);
      }
    return(false);
  }
 
  public: virtual bool collideAndCorrect(Collidable object){
    float vector_between_farthest_collision_points[3];
    float first_farthest_collision_point[3];
    if(collide(object,vector_between_farthest_collision_points,
    first_farthest_collision_point))
      {reactDuringCollisionWith(object,vector_between_farthest_collision_points
       ,first_farthest_collision_point);
       float tmp[3];
       vectorFromBipoint(tmp,&Transform[12],&old_position[12]);
       float n=dot(vector_between_farthest_collision_points,tmp);
       tmp[0]*=n+0.0001f;
       tmp[1]*=n+0.0001f;
       tmp[2]*=n+0.0001f;  
       correct(tmp);
       return(true);
      }
    return(false);
  }
 
  protected: virtual void correct(float* correction_vector){
    Transform[12]+=correction_vector[0];
    Transform[13]+=correction_vector[1];
    Transform[14]+=correction_vector[2];
  }
  
  public: virtual float getCollisionDamage(){
    return(0.0f);
  }
  
  protected: virtual void reactDuringCollisionWith(FlatSurface surface
  ,float* collision_point,float* farthest_collision_point){
    //will be mainly used for damages and explosions 
  }
  
  protected: virtual void reactDuringCollisionWith(Collidable object
  ,float* vector_between_farthest_collision_points
  ,float* first_farthest_collision_point){
    //will be mainly used for damages and explosions 
  }
  
  /* 
  public: virtual bool collide(FlatSurface surface){
    float collision_point[3];
    return(collide(surface,collision_point));
  }
  */
};



class Fallable:public Collidable{

  public: void fall(){}

};

class Player:public Fallable,Camera{
  //handle ammo
  //handle life
};

class Bot:public Fallable,Camera{
  //redefine getCollisionDamage
  //handle other kinds of damage
};

class Projectile:public Collidable{
  //redefine getCollisionDamage
};

//I may need an Explosion class

#define STARTING_MODE 0   //display a few images
#define INTRO_MODE 1      //display a few images
#define PLAYING_MODE 5    //display the game, movements allowed
#define PAUSING_MODE 2    //display a few images
#define DYING_MODE 4      //display the game, movements not allowed, no gun
#define GAME_OVER_MODE 3  //display a few images

//I can simulate the death by reducing the yradius of the player

static short alpha=0,beta=0,Gamma=0,delta=0;
static int pointerx,pointery;
static Camera cam(0,0,0,-M_PI/2.0f,-2*M_PI,-2*M_PI,M_PI/2.0f,2*M_PI,2*M_PI);
static Collidable object(0,0,0,10,5,10);
static FlatSurface wall(20,20,2000,20,-20,2000,20,-20,-2000,20,20,-2000);
static unsigned short WINDOW_WIDTH,WINDOW_HEIGHT;
static unsigned char GAME_CURRENT_DISPLAY_MODE;
static unsigned int menu_textures_ID[16];
static int current_menu_texture_index;

void warpPointerAtCenter(){
  pointerx=WINDOW_WIDTH/2;
  pointery=WINDOW_HEIGHT/2;
  glutWarpPointer((int)pointerx,(int)pointery);
}

bool pointerAtEdge(){  
  return(pointerx<=0||pointerx>=WINDOW_WIDTH-1||
         pointery<=0||pointerx>=WINDOW_HEIGHT-1);
}

void drawWalls(){
  glBegin(GL_QUADS);
  glNormal3f(-1,0,0);
  glVertex3f(-20,20,-2000); 
  glVertex3f(-20,-20,-2000); 
  glVertex3f(-20,-20,2000);
  glVertex3f(-20,20,2000);
  
  glNormal3f(1,0,0);
  glVertex3f(20,20,2000);
  glVertex3f(20,-20,2000);  
  glVertex3f(20,-20,-2000);
  glVertex3f(20,20,-2000);
  
  glEnd();
}

void drawParallelipipede(float x,float y,float z){
  glBegin(GL_QUADS);
    
  glNormal3f(0,0,1);
  glVertex3f(-x/2,y/2,z/2);
  glVertex3f(-x/2,-y/2,z/2);
  glVertex3f(x/2,-y/2,z/2);
  glVertex3f(x/2,y/2,z/2);
  
  glNormal3f(1,0,0); 
  glVertex3f(x/2,y/2,z/2);
  glVertex3f(x/2,-y/2,z/2);  
  glVertex3f(x/2,-y/2,-z/2);
  glVertex3f(x/2,y/2,-z/2);
  
  glNormal3f(0,0,-1);  
  glVertex3f(x/2,y/2,-z/2);  
  glVertex3f(x/2,-y/2,-z/2);  
  glVertex3f(-x/2,-y/2,-z/2);
  glVertex3f(-x/2,y/2,-z/2);
    
  glNormal3f(-1,0,0);
  glVertex3f(-x/2,y/2,-z/2); 
  glVertex3f(-x/2,-y/2,-z/2); 
  glVertex3f(-x/2,-y/2,z/2);
  glVertex3f(-x/2,y/2,z/2);
  
  glNormal3f(0,1,0);
  glVertex3f(-x/2,y/2,z/2);
  glVertex3f(x/2,y/2,z/2);
  glVertex3f(x/2,y/2,-z/2);
  glVertex3f(-x/2,y/2,-z/2);
  
  glNormal3f(0,-1,0);
  glVertex3f(-x/2,-y/2,-z/2);
  glVertex3f(x/2,y/2,-z/2);
  glVertex3f(x/2,-y/2,z/2);
  glVertex3f(-x/2,-y/2,z/2);
  glEnd();
}

void drawArm(int a,int b,int c,int d){  
  glRotatef(a,0,0,1);  
  glPushMatrix();
  glTranslatef(5.,0.,0.);
  //glScalef(10.,1.,1.);
  glColor3f(1.,0.,0.0);
  drawParallelipipede(10,1,1);
  glPopMatrix();

  glTranslatef(10.,0.,0.);
  glRotatef(b,0,0,1);
  glPushMatrix();
  glTranslatef(4.5,0.,0.);  
  //glScalef(9.,1.,1.);
  glColor3f(0.,1.,0.0);
  drawParallelipipede(9,1,1);
  glPopMatrix();

  glTranslatef(9.,0,0);
  glPushMatrix();
  glRotatef(c,0,0,1);
  glTranslatef(2.,0.,0.);
  //glScalef(4.,1.,1.);
  glColor3f(0.,0.,1.0);
  drawParallelipipede(4,1,1);
  glPopMatrix();

  glRotatef(d,0,0,1);
  glTranslatef(2.,0.,0.);
  //glScalef(4.,1.,1.);
  glColor3f(1.,1.,0.0);
  drawParallelipipede(4,1,1);
}

void init(){
  GAME_CURRENT_DISPLAY_MODE=STARTING_MODE;  
  current_menu_texture_index=GAME_CURRENT_DISPLAY_MODE*4;  
  char filename[30],tmp[3];
  glEnable(GL_TEXTURE_2D);
  for(int i=0;i<16;i++)
    {strcpy(filename,"menu_texture");
     sprintf(tmp,"%d",i);
     strcat(filename,tmp);
     strcat(filename,".jpg");     
     menu_textures_ID[i]=loadJPEGTexture(filename);     
    }
  glDisable(GL_TEXTURE_2D);
  WINDOW_WIDTH=glutGet(GLUT_WINDOW_WIDTH);
  WINDOW_HEIGHT=glutGet(GLUT_WINDOW_HEIGHT);
  glClearColor(1.0,1.0,1.0,0.0);
  glClearDepth(1.0);
  glEnable(GL_DEPTH_TEST);
  glDepthFunc(GL_LESS);/*
  glEnable(GL_CULL_FACE);
  glCullFace(GL_BACK);*/
  /*glViewport(-50,-50,100,100);*/
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();  
  /*glFrustum(-50,50,-50,50,20,100);*//*ca marche quand meme*/
  gluPerspective(65.0,((float)WINDOW_WIDTH)/
                      ((float)WINDOW_HEIGHT),1,1000);
  glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
  glMatrixMode(GL_MODELVIEW);  
  glutSetCursor(GLUT_CURSOR_NONE);
  warpPointerAtCenter(); 
  //object.rotateLocal(M_PI/2,0,1,0);
}

void display(){  
  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  if(GAME_CURRENT_DISPLAY_MODE==PLAYING_MODE||
     GAME_CURRENT_DISPLAY_MODE==DYING_MODE)
    {glPushAttrib(GL_COLOR_BUFFER_BIT);
     glPushMatrix();
     drawArm(alpha,beta,Gamma,delta);
     glPopMatrix();
     glPopAttrib();
     glPushAttrib(GL_COLOR_BUFFER_BIT);
     glPushMatrix();
     glColor3f(0.3,0.3,0.3);
     drawWalls();
     glPopMatrix();
     glPopAttrib();
    }
  else
    {glPushMatrix();
     glLoadIdentity();
     glEnable(GL_TEXTURE_2D);     
     glColor3f(1,1,1);
     glBindTexture(GL_TEXTURE_2D,menu_textures_ID[current_menu_texture_index]);     
     glBegin(GL_QUADS);     
     glVertex3f(-WINDOW_WIDTH/2,-WINDOW_HEIGHT/2,-250);
     glTexCoord3f(0,1,-250);
     glVertex3f(-WINDOW_WIDTH/2,WINDOW_HEIGHT/2,-250);
     glTexCoord3f(1,1,-250);
     glVertex3f(WINDOW_WIDTH/2,WINDOW_HEIGHT/2,-250);
     glTexCoord3f(1,0,-250);
     glVertex3f(WINDOW_WIDTH/2,-WINDOW_HEIGHT/2,-250);
     glTexCoord3f(0,0,-250);
     glEnd(); 
     glPopMatrix();/*
     unsigned char bitmap[512*512*3];  
     glGetTexImage(GL_TEXTURE_2D,0,GL_RGB,GL_UNSIGNED_BYTE,bitmap);
     glBitmap(512,512,0,0,0,0,bitmap);  */   
     glDisable(GL_TEXTURE_2D);         
    }
  glFlush();
  glutSwapBuffers();/*
  if(object.collide(wall))
    {cout<<"collision\n";
     object.toString();
    } */
  if(pointerAtEdge())  
    warpPointerAtCenter();
}

void special(int key,int x,int y){
  if(GAME_CURRENT_DISPLAY_MODE==PLAYING_MODE)    
    {switch(key)
       {case  GLUT_KEY_UP   :{alpha=(alpha+10)%360;                           
                              glutPostRedisplay();
                              break;
                             }
	case  GLUT_KEY_DOWN :{alpha=(alpha-10)%360;                           
                              glutPostRedisplay();
                              break;
                             }
	case  GLUT_KEY_LEFT   :{beta=(beta+10)%360;                             
                        	glutPostRedisplay();
                        	break;
                               }
	case  GLUT_KEY_RIGHT :{beta=(beta-10)%360;                            
                               glutPostRedisplay();
                               break;
                              }
	case  GLUT_KEY_PAGE_UP   :{Gamma=(Gamma+10)%360;
                        	   glutPostRedisplay();
                        	   break;
                        	  }
	case  GLUT_KEY_PAGE_DOWN :{Gamma=(Gamma-10)%360;
                        	   glutPostRedisplay();
                        	   break;
                        	  }
	case  GLUT_KEY_F1   :{delta=(delta+10)%360;
                              glutPostRedisplay();
                              break;
                             }
	case  GLUT_KEY_F2 :{delta=(delta-10)%360;
                            glutPostRedisplay();
                            break;
                           }
	case  GLUT_KEY_F3 :{GAME_CURRENT_DISPLAY_MODE=PAUSING_MODE;	                    			    
	                    current_menu_texture_index=GAME_CURRENT_DISPLAY_MODE*4;
	                    glutPostRedisplay();
	                    break;
	                   }
	default :{exit(EXIT_SUCCESS);
        	  break;
        	 }
       }
     }
   else
     {switch(key)
       {case  GLUT_KEY_F4 :{exit(EXIT_SUCCESS);
        	            break;
        	           }
	case  GLUT_KEY_F3 :{switch(GAME_CURRENT_DISPLAY_MODE)
	                      {case STARTING_MODE :{GAME_CURRENT_DISPLAY_MODE=INTRO_MODE;
			                            current_menu_texture_index=GAME_CURRENT_DISPLAY_MODE*4;
			                            break;
			                           }
			       case INTRO_MODE :{GAME_CURRENT_DISPLAY_MODE=PLAYING_MODE;			                         
			                         current_menu_texture_index=GAME_CURRENT_DISPLAY_MODE*4;
						 break;
			                        }
			       case PAUSING_MODE :{GAME_CURRENT_DISPLAY_MODE=PLAYING_MODE;
			                           //glPopMatrix();			                           
			                           current_menu_texture_index=GAME_CURRENT_DISPLAY_MODE*4;
						   break;
			                          }
			       case DYING_MODE :{GAME_CURRENT_DISPLAY_MODE=GAME_OVER_MODE;
			                         current_menu_texture_index=GAME_CURRENT_DISPLAY_MODE*4;
						 break;
			                        }
			       case GAME_OVER_MODE :{GAME_CURRENT_DISPLAY_MODE=PLAYING_MODE;
			                             current_menu_texture_index=GAME_CURRENT_DISPLAY_MODE*4;
						     break;
			                            }		  			      
			      }	                    
	                    glutPostRedisplay();
	                    break;
	                   }
       }
    }
}

void keyboard(unsigned char key,int x,int y){
  if(GAME_CURRENT_DISPLAY_MODE==PLAYING_MODE)    
    {switch(key)
       {case 'z':{cam.moveLocal(0,0,1,5);
        	  /*
        	  cam.move(5);
		  cam.move(0);*/
        	  break;
		 }
	case 'q':{cam.moveLocal(1,0,0,-5);/*
        	  cam.move(-5);
		  cam.move(0);              */
        	  break;
        	 }
	case 's':{cam.moveLocal(1,0,0,5);/*
        	  cam.move(5);
		  cam.move(0);             */  
        	  break;
		 }
	case 'w':{cam.moveLocal(0,0,1,-5);
        	  /*cam.move(-5);
		  cam.move(0);*/
        	  break;
		 }
	case 't':{object.moveLocal(0,0,1,5);
        	  break;
        	 }
	case 'v':{object.moveLocal(0,0,1,-5);
        	  break;             
		 }      
	case 'f':{object.moveLocal(1,0,0,-5);
        	  break;
        	 }
	case 'g':{object.moveLocal(1,0,0,5);
        	  break;             
		 }

       }
     //cam.setView();
     glutPostRedisplay();
    }
}

void passiveMotion(int x,int y){
  /*if(GAME_CURRENT_DISPLAY_MODE==PLAYING_MODE)
    {*/
  float shiftx=0,shifty=0;
  if(pointerx-x<0)
    shiftx=-5.0f/60.0f;
  else if(pointerx-x>0)
         shiftx=5.0f/60.0f;
  pointerx=x;
  cam.rotateGlobal(shiftx,0,1,0);    
  if(y-pointery<0)
    shifty=-5.0f/60.0f;
  else if(y-pointery>0)
         shifty=5.0f/60.0f;
  pointery=y;
  cam.rotateGlobal(shifty,1,0,0); 
  glutPostRedisplay();
  /*  }
  else
    {pointerx=x;
     pointery=y;
    }*/
}

void idle(){
  if(GAME_CURRENT_DISPLAY_MODE==PLAYING_MODE||
     GAME_CURRENT_DISPLAY_MODE==DYING_MODE)
    {
     /*glutPostRedisplay();*/
    }
  else
    {if(current_menu_texture_index!=(GAME_CURRENT_DISPLAY_MODE*4)+3)
       current_menu_texture_index++;
     else
       current_menu_texture_index=GAME_CURRENT_DISPLAY_MODE*4;
     //cout<<current_menu_texture_index<<" "<<menu_textures_ID[current_menu_texture_index]<<" \n";     
     //I should use a timer here
     glutPostRedisplay();
    }
}

int main(int argc,char* argv[]){
  GAME_CURRENT_DISPLAY_MODE=0;
  glutInit(&argc,argv);
  glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH);
  glutCreateWindow("");
  glutFullScreen();
  init();  
  glutIdleFunc(idle);
  glutPassiveMotionFunc(passiveMotion);
  glutDisplayFunc(display);
  glutSpecialFunc(special);
  glutKeyboardFunc(keyboard);
  glutMainLoop();
  exit(EXIT_SUCCESS);
}

 Conclusion

D'autre part, ce code permet de faire bouger un petit bras robot avec les touches Haut, Bas, Gauche, Droite, F1 et F2. F3 permet de quitter l'application. Vous pouvez essayer de bouger avec la souris, avancer et reculer avec Z et W, faire des pas de côté avec Q et S.

Je remercie Alexander Festini pour ses conseils et sa caméra UVN, mais également Ben Kenwright, Ashley James, Vic Hollis et M. Karlsson pour leur aide.

N.B: j'essayerai de mettre mon code à jour tous les jours saufs le weekend.

Merci d'avance pour votre aide.

 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Historique

06 avril 2006 18:49:01 :
J'ajoute un zip à la demande de LE_DUCHE
07 avril 2006 12:53:03 :
J'ai réussi à me débarasser du gimbal lock. Cependant, au bout d'un moment, au lieu de tourner sur moi-même, je me mets à tourner autour d'un point fixe. Le problème vient de la fonction rotateGlobal.
11 avril 2006 17:37:59 :
ça marche beaucoup mieux, on peut même limiter l'angle de vue pour un FPS par exemple
14 avril 2006 17:06:25 :
Le code marche pleinement sous windows et linux. Seule la fonction rotateLocal n'a pas été testé. L'angle autour de x est limité pour un FPS mais vous pouvez le changer.
10 mai 2006 10:35:37 :
Ajout de plusieurs classes : FlatSurface (surfaces planaires) et Collidable (gestion des collisions). Vous pouvez ainsi faire une caméra qui ne passe pas à travers les murs!!!
15 mai 2006 16:53:18 :
Le système de collision est presque fini. J'ai corrigé quelques erreurs dans le calcul du point le plus loin du centre de l'ellipsoïde et alligné avec le point de collision éventuel.
24 mai 2006 16:55:49 :
J'ai corrigé un bug persistant dans la caméra. Par moment, les mouvements restaient bloqués dans une seule position. J'ai presque fini la gestion des collisions. Je commence à gérer l'affichage de murs, décors etc au niveau purement logiciel en utilisant entre autres des vertex arrays. Si vous avez des suggestions à faire, je suis tout ouï.

 Sources du même auteur

Source avec Zip SIMULATEUR D'ORDONNANCEMENT DE PROCESSUS

 Sources de la même categorie

Source avec Zip Source avec une capture AFFICHER DES COURBES DE BEZIER par shorzy
Source avec Zip Source avec une capture BASE/MOTEUR 3D EN QT/OPENGL (COMPLET ET FONCTIONNEL!) POUR U... par envi33
Source avec Zip Source avec une capture CLASSE AVEC OPENGL - OBJETS 3D ET ANIMATIONS par rasta63
Source avec Zip Source avec une capture LETTRES 3D AVEC OPENGL ET QT par opossum_farceur
Source avec Zip CUBE 3D GLUT32 VC++ ET DEVC++ par bobby03

 Sources en rapport avec celle ci

Source avec Zip Source avec une capture AFFIMOFF : UNE VISIONNEUSE 3D AVEC PARAMÉTRISATION ET TEXTUR... par pgl10
Source avec Zip Source avec une capture AFFICHER DES COURBES DE BEZIER par shorzy
Source avec Zip Source avec une capture BASE/MOTEUR 3D EN QT/OPENGL (COMPLET ET FONCTIONNEL!) POUR U... par envi33
Source avec Zip Source avec une capture OPENCL : CALCUL ET AFFICHAGE DU GRADIENT COULEUR D'UNE WEBCA... par ciddiju
Source avec Zip Source avec une capture CLASSE AVEC OPENGL - OBJETS 3D ET ANIMATIONS par rasta63

Commentaires et avis

Commentaire de le_duche le 06/04/2006 17:44:51

Un zip serait le bienvenu pour les gens comme moi qui n'ont pas le net chez eux...

Commentaire de gouessej le 06/04/2006 18:39:54

Bonjour LE_DUCHE

Ok je vais arranger ça si tu permets. Je mets un zip. Je n'ai pas internet chez moi non plus, j'aurais dû y penser.

Commentaire de gouessej le 12/05/2006 15:10:16

Je ne comprends pas pourquoi personne n'a mis de note à ma source. Je sais que ça manque de commentaires mais je suis ouvert à vos questions.

Commentaire de gouessej le 24/05/2006 16:57:10

J'ai oublié de préciser que les deux loaders ne sont pas de mon cru. L'un a été fait par un élève en IUP et l'autre par... je ne sais pas qui.

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Quaternions et opengl [ par acropole ] Bonjour,Je cherche de l'aide pour programmer en C++&nbsp;les mouvement d'objets dans un environnement openGl. J'ai commenc&#233; &#224; programmer l'a Tutoriaux Complet SDL OpenGL C++ [ par Fireflect ] Bonjours, Je recherche des bons tutoriaux sur le m&#233;lange OpenGL SDL C++ sans glut ou quoi que ce soit d'autre avec des sources bien optimis&#233 Problème OpenGL (GL_POINT) [ par olivier_job ] Bonjour, &nbsp; J'utilise VC++ 7.0, avec wxWindows. Le probl&#232;me est le suivant. Sur mon ordinateur, les GL_POINTS apparaissent comme des cercle Transparence avec glBlend [ par smoove5198 ] Bonjour, A l'aide d'un tutorial j'ai cr&#233;e une classe qui affiche du texte sous opengl a partir d'une texture bmp listant tous les caracteres. D GRAPHISME....OPENGL,WIN32 [ par kenza_sana ] HELOOO.. je voudrai 'minitaliser avec le mode graphique mais je n'ay arrive pas car je en comprend pas deja j'entned tj parler de WIN32 et OPENGL..jhe Plusieurs View dans une MFC et affichage opengl [ par Fipovi3 ] Bonjour,Je suis en train de cr&#233;er une application mfc en sdi. J'ai cr&#233;&#233; des splitters pour diviser ma fen&#234;tre principale en 4 vues de Blender, en passant par OpenGL, jusqua mon programme win32 [ par Muner ] Bonjour,existe t'il un programme qui convertisse les projets Blender en fichiers OpenGL (ou 3ds (si c'est les m&#234;mes ou pas (je n'en sais rien))) transparences en openGL [ par vangeurmasker ] J'ai un probleme dans un projet en OpenGL. J'utilise le canal alpha de mes textures pour g&#233;r&#233;r les transparences. Mais le probleme est qu'au Tutz texture opengl??? [ par Slown ] Salut a tous. Voila, j'suis a la recherche d'un tutorial COMPLET sur la pose de texture en opengl. Pour l'instant j'utilise le code: http://www.linuxg opengl : lumière, fog pose problème quand picking [ par kortin ] &nbsp;&nbsp;&nbsp;Bonjour,j'aimerais ajout&#233; le fog et la lumi&#232;re dynamique dans mon projet openGL.Tout fonctionne bien, mais lors de la s&#2


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Mai 2012
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

Consulter la suite du CalendriCode

A découvrir



 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 1,045 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales