Thread: Help with OpenGL camera

  1. #1
    Registered User
    Join Date
    Apr 2013
    Posts
    2

    Help with OpenGL camera

    Hello,i have a project for school to make a snake3d game.This is the code i've got so far:

    Code:
    #include <stdio.h>
    #include <time.h>
    #include <windows.h>
    #include <gl/glut.h>
    
    
    #define UP 1
    #define Down 2
    #define LEFT 3
    #define RIGHT 4
    
    
    // Variabile de stare
    GLint   lvl      = 1;
    GLint   points = 0;
    GLint   size  = 0;
    GLbyte  gameOver = true;
    GLbyte  EnableLight = true;    
    
    
    // Variabilele la vierme
    GLint   bodyPos[2][100] = {{}};
    GLint   _x       = 5;
    GLint   _z       = 10;
    GLint   _oldX[2] = {};
    GLint   _oldZ[2] = {};
    GLbyte  direction  = 0;
    
    
    // Variabile la mancare
    GLint   _bx      = 0;
    GLint   _bz      = 0;
    
    
    // Variabile de ecran
    GLint   _w       = 800;
    GLint   _h       = 550;
    GLint   _Giw     = 0;
    GLint   _Gih     = 0;
    GLint   _Gfw     = 150;
    GLint   _Gfh     = 150;
    
    
    //Variabile pentru unghiul camerei
    static GLfloat view_rotx=45.0F ;
    static GLfloat view_roty=0.0F ;
    static GLfloat view_rotz=0.0F ;
    
    
    static GLfloat headRotation=90.0F ;
    static GLfloat zoom=-300.0F ;
    
    
    // Variabile pentru FPS
    DWORD   g_dwLastFPS = 0;
    int		g_nFPS = 0, g_nFrames = 0;
    
    
    //Configurarea Luminii
    void initLight()
    {
        //Adaugam lumina ambientala
        GLfloat ambientColor[] = {0.3f, 0.4f, 0.8f, 1.0f}; 
        glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientColor);
    
    
        //Lumina pozitionata
        GLfloat lightColor0[] = {0.5f, 0.5f, 0.5f, 1.0f}; 
        GLfloat lightPos0[] = {4.0f, 0.0f, 8.0f, 1.0f}; 
        glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor0);
        glLightfv(GL_LIGHT0, GL_POSITION, lightPos0);
    
    
        //Adaugam lumina directa
        GLfloat lightColor1[] = {0.5f, 0.2f, 0.2f, 1.0f}; 
        //Vine din directia (-1, 0.5, 0.5)
        GLfloat lightPos1[] = {-1.0f, 0.5f, 0.5f, 0.0f};
        glLightfv(GL_LIGHT1, GL_DIFFUSE, lightColor1);
        glLightfv(GL_LIGHT1, GL_POSITION, lightPos1);
    }
    
    
    //Initializarea primelor configuratii
    void Initialize(void) 
    {
        glEnable(GL_DEPTH_TEST);
        glClearColor(0.7f, 0.9f, 0.3f,0.7f); //Schimbam culoarea "cerului" intr-un...verde sau ce o fi iesit pe aici
        if(EnableLight){
            glEnable(GL_COLOR_MATERIAL); //Dam enable la culoare
            glEnable(GL_LIGHTING); //Dam enable la lumina
            glEnable(GL_LIGHT0); //Dam enable la lumina #0
            glEnable(GL_LIGHT1); //Dam enable la lumina #1
            glEnable(GL_NORMALIZE); //Automatizarea normalizarii normalelor
        }
    }
    
    
    //Redimensionarea ferestrei
    void resize (int w, int h)
    {
        glViewport(0, 0, w, h);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45.0, (double)w / (double)h, 1, 800.0);
    }
    
    
    void Write(char *string){//Scriem un string pe ecran
        while(*string)
            glutBitmapCharacter(GLUT_BITMAP_8_BY_13, *string++);
    }
    //Aceasta functie va intoarce obiectele in functie de unghi
    void ManipulateViewAngle() {
        glRotatef(view_rotx,1.0,0.0,0.0);//Intoarcem in jurul la axa X
        glRotatef(view_roty,0.0,1.0,0.0);//Intoarcem in jurul la axa Y
        glRotatef(view_rotz,0.0,0.0,1.0);//Intoarcem in jurul la axa Z
    }
    
    
    //Resetam dimensiunea la vierme si locatia lui(sau sa ii zicem mai bine "joc nou" HAHA HIHI HEHE HOHO)
    void Reset(){
        _x       = 5;
        _z       = 10;
        direction  = 0;
        lvl      = 1;
        points = 0;
        size  = 0;
        gameOver = false;
        view_rotx=45.0F ;
        view_roty=0.0F ;
        view_rotz=0.0F ;
        headRotation=90.0F ;
        zoom=-300.0F ;
    }
    
    
    //WELCOOOOOMEEEE SCREEEEEENNNN YUPYYY
    void WelcomeScreen(){
        char tmp_str[40];
    
    
        glColor3f(1, 0, 0);
        glRasterPos2f(0, 20);
        Write("Snake 3D");
    
    
        glColor3f(0, 0, 1);
        glRasterPos2f(0, 10);
        Write("Marin Alexandru Radu");
        
        glColor3f(0, 0, 1);
        glRasterPos2f(0, 0);
        Write("Apasati 'n' pentru joc nou.");
    }
    
    
    void DrawSnake(){
        int  i;
    
    
        //Desenam capul si suprafata
        glPushMatrix();
        ManipulateViewAngle();
            //Suprafata de marshaluire a sarpelui
            glPushMatrix();
            glColor3f(0.5f, 0.0f, 1.0f);
            glTranslatef(75.0, -16.0, 75.0);
            glScalef(155,5.0,155);
            glutSolidCube(1);
            glPopMatrix();
        //HEAD OF THE WORM
        glColor3f(1.0,0.0,0.0);//Culoare..
        glTranslatef(_x,-10.0,_z);//Ii dam locatia in functie de _x si _z
        glScalef(0.5,0.5,0.5);
        glutSolidSphere(10,20,20);//Ii facem capul mai tuguiat(o sfera putin mai mare decat celalte sfere)
        glRotatef(headRotation, 0.0, 1.0, 0.0);
        glColor3f(1.0,1.0,0.0);
        glTranslatef(0,0.0,6.0);
        glScalef(0.8,1.0,1.0);
        glutSolidCone(10,10,20,20);
        glColor3f(0,0,0);
        glTranslatef(-4.0,10.0,0.0);
        glScalef(0.3,0.3,0.3);
        glutSolidSphere(10,20,20);
        glTranslatef(26.0,0.0,0.0);
        glutSolidSphere(10,20,20);
        glPopMatrix();
    
    
        //Desenarea corpului
        for(i=0; i<size; i++){//Loop-ul va da lungimea corpului si va desena sfere 
            glPushMatrix();
            ManipulateViewAngle();
            glTranslatef(bodyPos[0][i],-10.0,bodyPos[1][i]);//Localizarea sferelor
            glColor3f(0.8,0.4,0.4);
            glScalef(0.5,0.5,0.5);
            glutSolidSphere(7,20,20);
            glPopMatrix();
        }
    }
    
    
    void DrawFood()
    {
        //Desenam sferele AKA mancarea pentru vierme
        glPushMatrix();
        ManipulateViewAngle();
        glTranslatef(_bx,-10.0,_bz);
        glColor3f(0.8, 0.4, 0.4);//MEMO "SCHIMBA CULOAREA LA MANCARE CA ESTE FOARTE ENERVANTA ASA!!!!!!!"
        glScalef(0.5,0.5,0.5);
        glutSolidSphere(7,20,20);
        glPopMatrix();
    }
    
    
    void GameStatus(){
    
    
        char tmp_str[40];
    
    
        // Vom face un "status" al jocului ce il vom afisa pe ecran
        glColor3f(0, 0, 0);
        glRasterPos2f(5, 50);
    
    
        sprintf(tmp_str, "Nivel: %d Puncte: %d", lvl, points);
        Write(tmp_str);
    }
    
    
    //Generam numere aleatoare pentru locatia mancarii viermelui
    int RandomNumber(int high, int low)
    {
        return (rand() % (high-low))+low;
    }
    
    
    //Generam noua mancare pentru vierme
    void newFood(){
        time_t seconds;
        time(&seconds);
        srand((unsigned int) seconds);
        _bx = RandomNumber(_Gfw-_Giw, _Giw+10);
        _bz = RandomNumber(_Gfh-_Gih, _Gih+10);
    }
    
    
    //Functie de calcul FPS
    void getFPS(){
        char tmp_str[40]; 
    
    
        if( GetTickCount() - g_dwLastFPS >= 1000 )				// Cand a trecut o secunda...
        {
            g_dwLastFPS = GetTickCount();					// Updatam variabila de timp
            g_nFPS = g_nFrames;						// Salvam FPS
            g_nFrames = 0;							// Resetam FPS 
        }
        g_nFrames++;
    
    
        glRasterPos2f(75, 50);
        sprintf(tmp_str, "FPS: %d", g_nFPS);
        Write(tmp_str);
        
        glRasterPos2f(50, 60);
        sprintf(tmp_str, "Poz X: %d Poz Z: %d", _x, _z);//Afisam pozitia X si Z
        Write(tmp_str);
    }
    
    
    //Functia de "accidentare"
    bool collision(){
        int i;
    
    
        for(i=0; i<size; i++){
            if((bodyPos[0][i] == _x && bodyPos[1][i] == _z) || 
            ((bodyPos[0][i] >= _x) && (bodyPos[0][i] <= _x + 5) && (bodyPos[1][i] >= _z) && (bodyPos[1][i] <= _z + 5)) ||
            ((bodyPos[0][i] <= _x) && (bodyPos[0][i] >= _x - 5) && (bodyPos[1][i] <= _z) && (bodyPos[1][i] >= _z - 5)) ||
            ((bodyPos[0][i] <= _x) && (bodyPos[0][i] >= _x - 5) && (bodyPos[1][i] >= _z) && (bodyPos[1][i] <= _z + 5)) ||
            ((bodyPos[0][i] >= _x) && (bodyPos[0][i] <= _x + 5) && (bodyPos[1][i] <= _z) && (bodyPos[1][i] >= _z - 5)))
            return true;
        }
        return false;
    }
    
    
    //Functie pentru miscarea sarpelui in functie de directie
    //Putin logic,dar vom folosi tastatura (old school: sus,jos,dreapta,stanga)
    void Run(int value){
        int i;
    
    
        _oldX[1] = _x;
        _oldZ[1] = _z;
        switch(direction){
          case RIGHT:
              headRotation =90;
              _x += 6;    
              if(_x > _Gfw-2) _x = _Giw-1;//Daca viermele se duce intr-o margine,aici il vom face sa "apara" in partea cealalta (no walls)
              break;
          case LEFT:
              headRotation =-90;
              _x -= 6;    
             if(_x < 0) _x = _Gfw-2;//Acelasi lucru ca mai sus
              break;
          case UP:
              headRotation =0;
              _z += 6;    
              if(_z > _Gfh-2) _z = _Gih-1;//Acelasi lucru ca mai sus
              break;
          case Down:
              headRotation =180;
              _z -= 6;    
              if(_z < 2) _z = _Gfh-2;//Acelasi lucru ca mai sus
              break;
        }
    
    
        //Verificat daca s-a papat singur,IF DAAAA,atunci GAME OVER
        if(collision()) gameOver = true;
    
    
        //Vedem daca viermele isi mananca mancarea (verificam X si Y)
        // Daca da crestem numarul de puncte,marimea viermelui si creeam o sfera (mancare YUM YUM) noua
        if((_x == _bx && _z == _bz) || 
        ((_x >= _bx) && (_x <= _bx + 4) && (_z >= _bz) && (_z <= _bz + 4)) ||
        ((_x <= _bx) && (_x >= _bx - 4) && (_z <= _bz) && (_z >= _bz - 4)) ||
        ((_x <= _bx) && (_x >= _bx - 4) && (_z >= _bz) && (_z <= _bz + 4)) ||
        ((_x >= _bx) && (_x <= _bx + 4) && (_z <= _bz) && (_z >= _bz - 4))){
            points++;
            if(points < 100) size++;
            if(points%5 == 0 && lvl < 15) lvl++;
            newFood();
        }
    
    
        for(i = 0; i<size; i++){// Salvam pozitiile partilor corpului la "el vierme"
            _oldX[0]       = _oldX[1];
            _oldZ[0]       = _oldZ[1];
            _oldX[1]       = bodyPos[0][i];
            _oldZ[1]       = bodyPos[1][i];
            bodyPos[0][i] = _oldX[0];
            bodyPos[1][i] = _oldZ[0];
        }
    
    
        //Setam timpul
        glutTimerFunc(130-lvl*4, Run, 0);                    
    }
    
    
    void Display(void){//Draw Function
        //Golire ecran
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        if(EnableLight) initLight();
    
    
        glTranslatef (-60.0, 40.0, zoom);
        //Daca "Game over" e adavarat,naspa,daca nu continuam jocul.
        if(!gameOver){
            GameStatus();
            DrawFood();
            DrawSnake();
        }
        else
            WelcomeScreen();
     
        getFPS();
    
    
        // Updatam ecranul
        glutPostRedisplay();
        glutSwapBuffers();
    }
    
    
    void Special(int key, int x, int y){
        switch(key){
        case GLUT_KEY_RIGHT     :
            if(direction != LEFT)
                direction = RIGHT;
            break;
        case GLUT_KEY_LEFT      :
            if(direction != RIGHT)
                direction = LEFT;
            break;
        case GLUT_KEY_UP        :
            if(direction != UP)
                direction = Down;
            break;
        case GLUT_KEY_DOWN      :
            if(direction != Down)
                direction = UP;
            break;
        }
    }
    
    
    void keyboard (unsigned char key, int x, int y)//Functii de baza pt miscarea viermelui
    {
        switch (key) {
          //Toate rotatiile viermelui peste unghiurile X, Y, Z
          case 'x'    : view_rotx +=2 ;
              glutPostRedisplay();
              break;
          case 'X'    : view_rotx -=2 ;
              glutPostRedisplay();
              break;
          case 'y'    : view_roty +=2 ;
              glutPostRedisplay();
              break;
          case 'Y'    : view_roty -=2 ;
              glutPostRedisplay();
              break;
          case 'z'    : view_rotz +=2 ;
              glutPostRedisplay();
              break;
          case 'Z'    : view_rotz -=2 ;
              glutPostRedisplay();
              break;
          case 'a'    : size++ ;//Functie ascunsa pentru utilizator (HAHA HIHI HEHE HOHO) cu care putem sa facem marimea sarpelui mai mare
              glutPostRedisplay();
              break;
          case 'A'    : size-- ;//Functie ascunsa pentru utilizator (HAHA HIHI HEHE HOHO) cu care putem sa facem marimea sarpelui mai mica
              glutPostRedisplay();
              break;
          case '+'    : zoom++ ;//Functie ascunsa pentru utilizator (HAHA HIHI HEHE HOHO) cu care putem sa facem zoom inspre plansa
              glutPostRedisplay();
              break;
          case '-'    : zoom-- ;//Functie ascunsa pentru utilizator (HAHA HIHI HEHE HOHO) cu care putem sa facem zoom mai departe de plansa (O facem miica mica mica)
              glutPostRedisplay();
              break;
          case 'n'    : Reset() ;//Functie de reset,care noi il mintim pe utilizator ca este de fapt pentru inceperea jocului (HAHA HIHI HEHE HOHO)
              glutPostRedisplay();
              break;
    
    
          //ESC pentru a iesi.
          case 27:
              exit(0);
              break;
          default:
              break;
        }
    }
    
    
    int main(void){
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
        glutInitWindowSize(_w,_h);
        glutInitWindowPosition(80,80);
        glutCreateWindow("Snake Game ");
        glutSpecialFunc(Special);
        glutKeyboardFunc(keyboard);
        glutDisplayFunc(Display);
        glutReshapeFunc(resize);
    
    
        newFood();
        Run(0);
        
        Initialize();
        glutMainLoop();
    }
    The problem is that i am trying to change the camera mode to follow the head object.The problem is that i've find the function gluLookAt(),but i don't understand what variables to put in there.
    Should i put something like:


    Code:
    glMatrixMode
    Code:
    (GL_MODELVIEW);    glLoadIdentity();    gluLookAt(        cameraPosition.x, cameraPosition.y, cameraPosition.z,        _x, -10.0, _z,0.0,1.0,0.0);
    

    And now where do i modify this in my code?I would apreciate if somebody can help me,thank you.

  2. #2
    Registered User
    Join Date
    May 2012
    Posts
    505
    OpenGl has two matrices, the model view matrix and the projection matrix.
    The modelview matrix is used for converting objects into "world space", and is popped and pushed continuously.
    The projection matrix converts from world space to 2d screen x, y co-ordinates. So the camera needs to affect the projection matrix. A look at matrix will point the camera in the right direction, but it won't do the perspective calculations.

    So you need to multiply the projection matrix by the look at matrix. Then you don't touch it.

    3D graphics cameras are different from real cameras in that they need a near and far clipping plane. This is because otherwise the z values go to infinity as you perspective correct. It's a common error not to set the clipping planes to sensible values.
    I'm the author of MiniBasic: How to write a script interpreter and Basic Algorithms
    Visit my website for lots of associated C programming resources.
    https://github.com/MalcolmMcLean


  3. #3
    Registered User
    Join Date
    Apr 2013
    Posts
    2
    Ok,so i need to redo the whole snake by using a pojection matrix i understand?

  4. #4
    Registered User
    Join Date
    May 2012
    Posts
    505
    Most of it shouldn't need redoing.

    Code:
    //Redimensionarea ferestreivoid resize (int w, int h){    glViewport(0, 0, w, h);    glMatrixMode(GL_PROJECTION);    glLoadIdentity();    gluPerspective(45.0, (double)w / (double)h, 1, 800.0);}
    This is where you set up your perspective transform, which is half of the camera. You need to add a line to multiply by the look at matrix, which means passing in camera x,y,z, target x, y, z (presumably the snake's head or something), and the up direction. You do that every frame, then you don't touch it again, all the other matrix operations are with the modelview matrix, moving the snake and food into world space.
    Check at 1 and 800 are Ok for near and far clipping planes. No object can come closer than 1 worldspace unit to the camera, or move further than 800 units away.

    I'm deeply suspicious of your manipulateviewangle function. It looks like you are trying to do some of the camera work on the modelview matrix (this will work, because ultimately everything is multiplied together into one transform, but it will quickly get you into a mess). However I would have to actually run the program to be sure what you are doing here.
    I'm the author of MiniBasic: How to write a script interpreter and Basic Algorithms
    Visit my website for lots of associated C programming resources.
    https://github.com/MalcolmMcLean


Popular pages Recent additions subscribe to a feed

Similar Threads

  1. OpenGL Camera Transformations
    By MacNilly in forum Game Programming
    Replies: 0
    Last Post: 11-13-2012, 06:33 PM
  2. opengl camera for beginners
    By blubee in forum Game Programming
    Replies: 5
    Last Post: 08-29-2012, 11:23 PM
  3. Please help openGL program -camera
    By evildotaing in forum C++ Programming
    Replies: 0
    Last Post: 05-30-2012, 11:55 PM
  4. Really Need Help With My Opengl Camera!!!!
    By psychopath in forum Game Programming
    Replies: 13
    Last Post: 05-28-2004, 03:05 PM
  5. OpenGL Camera
    By frenchfry164 in forum Game Programming
    Replies: 15
    Last Post: 12-10-2003, 02:50 PM