Membuat Segitiga dalam Segitiga 3 Dimensi (Sierpinski Gasket) dengan Inputan Mouse dan Keyboard

Cerita begini, dosen kuliah komputer grafik memberi tugas kedua dengan ketentuan membuat gambar 3 dimensi (3D) dengan betuk segitiga dalam segitiga atau bahasa kerennya Sierpinski Gasket. Program ini juga harus bisa menerima inputan dan berinteraksi dengan user dengan menggunakan OpenGL, terserah bahasa program apa saja. kebetulan di komputer saya telah terinstal Dev C++, nah tinggal nambahi library OpenGL dech. untuk cara menginstal OpenGL di Dev C++, silakan ikuti Tutorial Instalasi OpenGL di Dev C++ .
nah, kalo di Dev C++ sudah terinstal OpenGL silakan mencoba tutorial berikut.

  1. Klik File --> New --> Project
  2. Tuliskan nama project lalu pilih Empty Project setelah itu Save project Anda 
  3. Klik Kanan pada project Anda lalu pilih New File.
  4. Nah, Saatnya koding. masukkan kode berikut ini:
    //includes
    #include <iostream>
    #include <math.h>
    #include <gl/glut.h> //NOTE: This file may be included in the system.
    
    //functions
    void ReshapeGlutWindow(int _width, int _height);
    void IdleGlutFunction();
    void KeyboardGlutFunction(unsigned char _key, int _x, int _y);
    void KeyboardUpGlutFunction(unsigned char _key, int _x, int _y);
    void MouseButtonGlutFunction(int _button, int _state, int _x, int _y);
    void MouseMotionGlutFunction(int _x, int _y);
    void DisplayGlutWindow();
    void SierpinskiGasket3f(float _rad, int _count);
    void SierpinskiGasket3f_A(float _point0Arr[], float _point1Arr[], float _point2Arr[], float _point3Arr[], int _count);
    void SierpinskiGasket3f_LineMidPoint(float _midPointOut[], float _point0Arr[], float _point1Arr[]);
    
    //camera position and rotation
    float camPos[3] = {0.0f, 0.0f, 370.0f}; //x,y,z position
    float camRot[3] = {0.0f, 0.0f, 0.0f}; //x,y,z rotation
    float camPosKeyDown[3] = {0, 0, 0}; //strafe-left-right, move-forward-backward, rise-down-up
    bool camRotMouseMoveEnable = false;
    int camRotMouseCord[2] = {0, 0}; //rotate-horozontal, rotate-verical
    
    int main(int argc, char **argv)
    {
     //initialize GLUT
     glutInit(&argc, argv);
    
     //position of the viewport
     glutInitWindowPosition(10, 10);
    
     //size of viewable window
     glutInitWindowSize(800, 600);
    
     //what type of display to show
     // GLUT_DEPTH - enable depth buffer
     // GLUT_DOUBLE - set tp double buffering
     // GLUT_RGBA - set red, green, blue, and alpha color mode
     glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
    
     //create window with specified titile
     glutCreateWindow("Andi Sholihin - 09.04.111.00011 --> Sierpinski Gasket dgn Input Mouse dan Keyboard");
    
     //reshaping function
     glutReshapeFunc(ReshapeGlutWindow);
    
     //idle function
     glutIdleFunc(IdleGlutFunction);
    
     //keyboard key-down function
     glutKeyboardFunc(KeyboardGlutFunction);
    
     //keyboard key-up function
     glutKeyboardUpFunc(KeyboardUpGlutFunction);
    
     //mouse-click function
     glutMouseFunc(MouseButtonGlutFunction);
    
     //mouse-clicked-move funtion
     glutMotionFunc(MouseMotionGlutFunction);
    
     //display function
     glutDisplayFunc(DisplayGlutWindow);
    
     //begin loop
     glutMainLoop();
     
     //end with success
     return 0;
    }
    
    void ReshapeGlutWindow(int _width, int _height)
    {
     //fix width
     if(_width < 1)
     {
      _width = 1;
     }
    
     //fix height
     if(_height < 1)
     {
      _height = 1;
     }
    
     //determine the aspect ratio of viewport
     float ratio = ((float)_width)/((float)_height);
    
     //set our current working matrix to the projection matrix stack
     glMatrixMode(GL_PROJECTION);
    
     //replace the current matrix with the identity matrix
     glLoadIdentity();
    
     //set our viewport
     glViewport(0, 0, _width, _height);
    
     //set up our perspective projection matrix
     // 45 - field of view degrees in y
     // ratio - field of view degrees in x
     // 0 - distance of viewer to near clipping plane
     // 1000 - distance of viewer to far clipping plane
     gluPerspective(45, ratio, 0, 1000);
    
     //set our current working matrix to the view matrix stack
     glMatrixMode(GL_MODELVIEW);
    
     //enable depth (i.e. z-buffer)
     glEnable(GL_DEPTH_TEST);
    
     //replace the current matrix with the identity matrix
     glLoadIdentity();
    }
    
    void IdleGlutFunction()
    {
     glutPostRedisplay();
    }
    
    void KeyboardGlutFunction(unsigned char _key, int _x, int _y)
    {
     switch(_key)
     {
     case 'a': //strafe-left
      camPosKeyDown[0] = -1.0f;
      break;
    
     case 'd': //strafe-right
      camPosKeyDown[0] = 1.0f;
      break;
    
     case 's': //move-down
      camPosKeyDown[1] = -1.0f;
      break;
    
     case 'w': //move-up
      camPosKeyDown[1] = 1.0f;
      break;
    
     case 'c': //rise-down
      camPosKeyDown[2] = -1.0f;
      break;
    
     case ' ': //rise-up
      camPosKeyDown[2] = 1.0f;
      break;
     }
    }
    
    void KeyboardUpGlutFunction(unsigned char _key, int _x, int _y)
    {
     switch(_key)
     {
     case 'a': //left
      camPosKeyDown[0] = 0.0f;
      break;
    
     case 'd': //right
      camPosKeyDown[0] = 0.0f;
      break;
    
     case 's': //down
      camPosKeyDown[1] = 0.0f;
      break;
    
     case 'w': //up
      camPosKeyDown[1] = 0.0f;
      break;
    
     case 'c': //lower
      camPosKeyDown[2] = 0.0f;
      break;
    
     case ' ': //rise
      camPosKeyDown[2] = 0.0f;
      break;
     }
    }
    
    void MouseButtonGlutFunction(int _button, int _state, int _x, int _y)
    {
     if(_button == 0)
     {
      if(_state == 0)
      {
       camRotMouseMoveEnable = true;
       camRotMouseCord[0] = _x;
       camRotMouseCord[1] = _y;
      }
      else if(_state == 1)
      {
       camRotMouseMoveEnable = false;
      }
     }
    }
    
    void MouseMotionGlutFunction(int _x, int _y)
    {
     if(camRotMouseMoveEnable)
     {
      camRot[0] += (((float)(camRotMouseCord[1] - _y)) / 10);
      camRotMouseCord[1] = _y;
      camRot[2] += (((float)(camRotMouseCord[0] - _x)) / 10);
      camRotMouseCord[0] = _x;
     }
    }
    
    void DisplayGlutWindow()
    {
     //update camera position
     //NOTE: camera rotation is already updated
     float zRowRad = camRot[2]*(3.141592653589793238462643f/180.0f);
     camPos[0] += 0.5f*camPosKeyDown[0]*cosf(zRowRad); //strafe-left-right on x
     camPos[1] += 0.5f*camPosKeyDown[0]*sinf(zRowRad); //strafe-left-right on y
     camPos[0] -= 0.5f*camPosKeyDown[1]*sinf(zRowRad);
     camPos[1] += 0.5f*camPosKeyDown[1]*cosf(zRowRad);
     camPos[2] += 0.5f*camPosKeyDown[2];
    
     //load identity
     glLoadIdentity();
    
     //set clear color
     glClearColor(0, 0, 0, 1);
    
     //clear specified buffers
     // GL_COLOR_BUFFER_BIT - color writing buffers
     // GL_DEPTH_BUFFER_BIT - depth buffer
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
     //translate and rotate for camera
     glRotatef(-camRot[0], 1, 0, 0);
     glRotatef(-camRot[1], 0, 1, 0);
     glRotatef(-camRot[2], 0, 0, 1);
     glTranslatef(-camPos[0], -camPos[1], -camPos[2]);
    
     //push the current matrix
     //NOTE: This is useless for this particular application, since there
     //is ONLY 1 static object at the origin.
     glPushMatrix();
    
     //move the position of the object
     //glTranslatef(200.0f, 0, 0);
    
     //draw
     SierpinskiGasket3f(300.0f, 7);
    
     //pop the current matrix
     glPopMatrix();
    
     //swap buffers
     glutSwapBuffers();
    }
    
    void SierpinskiGasket3f(float _rad, int _count)
    {
     float points0Arr[3] = {_rad, 0, 0};
     float points1Arr[3] = {_rad*(-0.5f), _rad*(0.866025404f), 0};
     float points2Arr[3] = {_rad*(-0.5f), _rad*(-0.866025404f), 0};
     float points3Arr[3] = {0, 0, _rad};
     glBegin(GL_TRIANGLES);
     SierpinskiGasket3f_A(points0Arr, points1Arr, points2Arr, points3Arr, _count);
     glEnd();
    }
    
    void SierpinskiGasket3f_A(float _point0Arr[], float _point1Arr[], float _point2Arr[], float _point3Arr[], int _count)
    {
     if(_count > 0)
     {
      //reduce count
      _count -= 1;
    
      //new points array
      float newPoint01Arr[3];
      float newPoint12Arr[3];
      float newPoint20Arr[3];
      float newPoint03Arr[3];
      float newPoint13Arr[3];
      float newPoint23Arr[3];
    
      //fill points
      SierpinskiGasket3f_LineMidPoint(newPoint01Arr, _point0Arr, _point1Arr);
      SierpinskiGasket3f_LineMidPoint(newPoint12Arr, _point1Arr, _point2Arr);
      SierpinskiGasket3f_LineMidPoint(newPoint20Arr, _point2Arr, _point0Arr);
      SierpinskiGasket3f_LineMidPoint(newPoint03Arr, _point0Arr, _point3Arr);
      SierpinskiGasket3f_LineMidPoint(newPoint13Arr, _point1Arr, _point3Arr);
      SierpinskiGasket3f_LineMidPoint(newPoint23Arr, _point2Arr, _point3Arr);
    
      //  sub-triangle 1
      SierpinskiGasket3f_A(newPoint01Arr, _point1Arr, newPoint12Arr, newPoint13Arr, _count);
    
      //  sub-triangle 2
      SierpinskiGasket3f_A(newPoint12Arr, _point2Arr, newPoint20Arr, newPoint23Arr, _count);
    
      //  sub-triangle 3
      SierpinskiGasket3f_A(newPoint01Arr, _point0Arr, newPoint20Arr, newPoint03Arr, _count);
    
      //  sub-triangle 4
      SierpinskiGasket3f_A(newPoint03Arr, newPoint13Arr, newPoint23Arr, _point3Arr, _count);
     }
     else
     {
      //draw faces
      //side 0 (bottom)
      glColor4f(1, 0, 0, 1); //0
      glVertex3fv(_point0Arr);
      glColor4f(0, 1, 0, 1); //1
      glVertex3fv(_point1Arr);
      glColor4f(0, 0, 1, 1); //2
      glVertex3fv(_point2Arr);
      //side 1
      glColor4f(1, 0, 0, 1); //0
      glVertex3fv(_point0Arr);
      glColor4f(0, 1, 0, 1); //1
      glVertex3fv(_point1Arr);
      glColor4f(0.7, 0.7, 0.7, 1); //3
      glVertex3fv(_point3Arr);
      //side 2
      glColor4f(0, 1, 0, 1); //1
      glVertex3fv(_point1Arr);
      glColor4f(0, 0, 1, 1); //2
      glVertex3fv(_point2Arr);
      glColor4f(0.7, 0.7, 0.7, 1); //3
      glVertex3fv(_point3Arr);
      //side 3
      glColor4f(0, 0, 1, 1); //2
      glVertex3fv(_point2Arr);
      glColor4f(1, 0, 0, 1); //0
      glVertex3fv(_point0Arr);
      glColor4f(0.7, 0.7, 0.7, 1); //3
      glVertex3fv(_point3Arr);
     }
    }
    
    void SierpinskiGasket3f_LineMidPoint(float _midPointOut[], float _point0Arr[], float _point1Arr[])
    {
     _midPointOut[0] = (_point0Arr[0] + _point1Arr[0]) / 2;
     _midPointOut[1] = (_point0Arr[1] + _point1Arr[1]) / 2;
     _midPointOut[2] = (_point0Arr[2] + _point1Arr[2]) / 2;
    }
    


  • Sebelum di Compile, terlebih dahulu klik menu Project --> Project Options (Alt+P)


  • Klik Tab Parameter dan masukkan kode berikut ini agar proses compile berjalan lancar.
    -lglut32 -lglu32 -lopengl32 -lwinmm -lgdi32
    perhatikan gambar berikut ini.


  • Setelah itu, klik Menu Execute --> Compile and Run, simpan file terlebih dahulu.


  • Hasilnya seperti berikut ini.

  • Mudah kan sobat? karena saya masih pemula, saya tunggu kritik dan sarannya. Semoga bermanfaat ^_^

    Referensi : http://www.st0rm.net/forum/showthread.php?12001-3D-Sierpinski-Gasket-(OpenGL)

    BAGIKAN KE:

    3 komentar: