Sabtu, 07 Juni 2014

Tutorial OPENGL dengan GLUT Bagian - 2

Tutorial 13 :
Objek Kompleks

Dalam latihan ke 13 ini kita akan membuat ilustrasi tentang bagaimana kita membaca file model 3D dan menggunakannya dalam program berbasis openGL dan GLUT. Pertama file dalam world .txt yang kita buat sendiri. dan disetiap bagian diberi gambar texture, sama dengan langkah sebelumnya (Pada Tutorial ke 1) buat sebuah Project dengan nama Tutor13 dan di tambah File : Tutor13.cpp, yang kita butuhkan kemudian anda ketikan Source Code dibawah ini

#include <windows.h>
#include <math.h> // Math Library Header File
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <GL/glut.h>
#include <GL/glaux.h>

const float piover180 = 0.0174532925f;
float heading;
float xpos;
float zpos;
GLfloat yrot; // Y Rotation
GLfloat walkbias = 0;
GLfloat walkbiasangle = 0;
GLfloat lookupdown = 0.0f;
GLfloat z=0.0f; // Depth Into The Screen
GLuint filter; // Which Filter To Use
GLuint texture[3]; // Storage For 3 Textures

typedef struct tagVERTEX
{
       float x, y, z;
       float u, v;
} VERTEX;

typedef struct tagTRIANGLE
{
       VERTEX vertex[3];
} TRIANGLE;

typedef struct tagSECTOR
{
       int numtriangles;
       TRIANGLE* triangle;
} SECTOR;

SECTOR sector1; // Our Model Goes Here:

void readstr(FILE *f,char *string)
{
       do
       {
              fgets(string, 255, f);
       } while ((string[0] == '/') || (string[0] == '\n'));
       return;
}

void SetupWorld()
{
       float x, y, z, u, v;
       int numtriangles;
       FILE *filein;
       char oneline[255];
       filein = fopen("Data/World.txt", "rt"); // File To Load World Data From
       readstr(filein,oneline);

       sscanf(oneline, "NUMPOLLIES %d\n", &numtriangles);
       sector1.triangle = new TRIANGLE[numtriangles];
       sector1.numtriangles = numtriangles;
       for (int loop = 0; loop < numtriangles; loop++)
       {
              for (int vert = 0; vert < 3; vert++)
              {
                     readstr(filein,oneline);
                     sscanf(oneline, "%f %f %f %f %f", &x, &y, &z, &u, &v);
                     sector1.triangle[loop].vertex[vert].x = x;
                     sector1.triangle[loop].vertex[vert].y = y;
                     sector1.triangle[loop].vertex[vert].z = z;
                     sector1.triangle[loop].vertex[vert].u = u;
                     sector1.triangle[loop].vertex[vert].v = v;
              }
       }
       fclose(filein);
       return;
}

AUX_RGBImageRec *LoadBMP(char *Filename) // Loads A Bitmap Image
{
       FILE *File=NULL; // File Handle
       if (!Filename) // Make Sure A Filename Was Given
       {
       return NULL; // If Not Return NULL
       }
       File=fopen(Filename,"r"); // Check To See If The File Exists
       if (File) // Does The File Exist?
       {
       fclose(File); // Close The Handle
       return auxDIBImageLoad(Filename); // Load The Bitmap And Return A Pointer
       }
       return NULL; // If Load Failed Return NULL
}

int LoadGLTextures() // Load Bitmaps And Convert To Textures
{
       int Status=FALSE; // Status Indicator
       AUX_RGBImageRec *TextureImage[1]; // Create Storage Space For The Texture
       memset(TextureImage,0,sizeof(void *)*1); // Set The Pointer To NULL

       // Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit
       if (TextureImage[0]=LoadBMP("Data/Mud.bmp"))
       {
              Status=TRUE; // Set The Status To TRUE
              glGenTextures(3, &texture[0]); // Create Three Textures
              // Create Nearest Filtered Texture
              glBindTexture(GL_TEXTURE_2D, texture[0]);
              glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
              glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
              glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX,
              TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
              // Create Linear Filtered Texture
              glBindTexture(GL_TEXTURE_2D, texture[1]);
              glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
              glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
              glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX,
              TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
              // Create MipMapped Texture
              glBindTexture(GL_TEXTURE_2D, texture[2]);
              glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
              glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
              gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0]->sizeX,
              TextureImage[0]->sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
              }
              if (TextureImage[0]) // If Texture Exists
              {
                     if (TextureImage[0]->data) // If Texture Image Exists
                     {
                           free(TextureImage[0]->data); // Free The Texture Image Memory
                     }
              free(TextureImage[0]); // Free The Image Structure
              }
       return Status; // Return The Status
}

void resize(int width, int height) // Resize And Initialize The GL Window
{
       if (height==0)
       // Prevent A Divide By Zero By
       {
              height=1;
       // Making Height Equal One
       }
       glViewport(0,0,width,height); // Reset The Current Viewport
       glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
       glLoadIdentity(); //Reset The Projection Matrix
       // Calculate The Aspect Ratio Of The Window
       gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
       glMatrixMode(GL_MODELVIEW); //Select The Modelview Matrix
       glLoadIdentity(); //Reset The Modelview Matrix
}

void init() // All Setup For OpenGL Goes Here
{
       if (!LoadGLTextures()) //Jump To Texture Loading Routine
       {
              return; //If Texture Didn't Load Return FALSE
       }
       glEnable(GL_TEXTURE_2D); //Enable Texture Mapping
       glBlendFunc(GL_SRC_ALPHA,GL_ONE); // Set The Blending Function For Translucency
       glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
       glClearDepth(1.0);
       // Enables Clearing Of The Depth Buffer
       glDepthFunc(GL_LESS); //The Type Of Depth Test To Do
       glEnable(GL_DEPTH_TEST); //Enables Depth Testing
       glShadeModel(GL_SMOOTH); //Enables Smooth Color Shading
       glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
       SetupWorld();
       return; //Initialization Went OK
}

void myTimeOut(int id)
{
       // called if timer event
       // ...advance the state of animation incrementally...
       //rot+=1;
       glutPostRedisplay(); // request redisplay
       glutTimerFunc(100, myTimeOut, 0); // request next timer event
}

void myKeyboard(unsigned char key,int x, int y)
{
}

void mySpecialKeyboard(int key,int x, int y)
{
       if(key==GLUT_KEY_UP)
       {
              xpos -= (float)sin(heading*piover180) * 0.05f;
              zpos -= (float)cos(heading*piover180) * 0.05f;
              if (walkbiasangle >= 359.0f)
              {
                     walkbiasangle = 0.0f;
              }
              else
              {
                     walkbiasangle+= 10;
              }
              walkbias = (float)sin(walkbiasangle * piover180)/20.0f;
       }
       else if(key==GLUT_KEY_DOWN)
       {
              xpos += (float)sin(heading*piover180) * 0.05f;
              zpos += (float)cos(heading*piover180) * 0.05f;
              if (walkbiasangle <= 1.0f)
              {
                     walkbiasangle = 359.0f;
              }
              else
              {
                     walkbiasangle-= 10;
              }
              walkbias = (float)sin(walkbiasangle * piover180)/20.0f;
              }
       else if(key==GLUT_KEY_RIGHT)
       {
              heading -= 1.0f;
              yrot = heading;
       }
       else if(key==GLUT_KEY_LEFT)
       {
              heading += 1.0f;
              yrot = heading;
       }
       else if(key==GLUT_KEY_PAGE_UP)
       {
              z-=0.02f;
              lookupdown-= 1.0f;
       }
       else if(key==GLUT_KEY_PAGE_DOWN)
       {
              z+=0.02f;
              lookupdown+= 1.0f;
       }
}

void mydisplay(void)
{
       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
       glLoadIdentity(); //Reset The View
       GLfloat x_m, y_m, z_m, u_m, v_m;
       GLfloat xtrans = -xpos;
       GLfloat ztrans = -zpos;
       GLfloat ytrans = -walkbias-0.25f;
       GLfloat sceneroty = 360.0f - yrot;
       int numtriangles;
       glRotatef(lookupdown,1.0f,0,0);
       glRotatef(sceneroty,0,1.0f,0);
       glTranslatef(xtrans, ytrans, ztrans);
       glBindTexture(GL_TEXTURE_2D, texture[filter]);
       numtriangles = sector1.numtriangles;
       // Process Each Triangle
       for (int loop_m = 0; loop_m < numtriangles; loop_m++)
       {
              glBegin(GL_TRIANGLES);
              glNormal3f( 0.0f, 0.0f, 1.0f);
              x_m = sector1.triangle[loop_m].vertex[0].x;
              y_m = sector1.triangle[loop_m].vertex[0].y;
              z_m = sector1.triangle[loop_m].vertex[0].z;
              u_m = sector1.triangle[loop_m].vertex[0].u;
              v_m = sector1.triangle[loop_m].vertex[0].v;
              glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m);
              x_m = sector1.triangle[loop_m].vertex[1].x;
              y_m = sector1.triangle[loop_m].vertex[1].y;
              z_m = sector1.triangle[loop_m].vertex[1].z;
              u_m = sector1.triangle[loop_m].vertex[1].u;
              v_m = sector1.triangle[loop_m].vertex[1].v;
              glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m);
              x_m = sector1.triangle[loop_m].vertex[2].x;
              y_m = sector1.triangle[loop_m].vertex[2].y;
              z_m = sector1.triangle[loop_m].vertex[2].z;
              u_m = sector1.triangle[loop_m].vertex[2].u;
              v_m = sector1.triangle[loop_m].vertex[2].v;

              glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m);
              glEnd();
       }
       glFlush();
       glutSwapBuffers();
}

int main(int argc, char** argv)
{
       glutInit(&argc,argv);
       glutInitDisplayMode( GLUT_DOUBLE | GLUT_DEPTH );
       glutInitWindowSize(500,500);
       glutInitWindowPosition(0,0);
       glutCreateWindow("simple");
       // callbacks
       glutDisplayFunc(mydisplay);
       glutKeyboardFunc(myKeyboard);
       glutSpecialFunc(mySpecialKeyboard);
       glutTimerFunc(100, myTimeOut, 0);
       glutReshapeFunc(resize);
       init();
       glutMainLoop();
       return 0;
}

Penjelasan :
Apabilan program 13 kita jalankan akan membuat file model 3D dengan format kita sendiri. File format kita adalah file World.txt yang formatnya akan berupa aturan sebagai berikut:
-      Kita dapat memasukkan baris kosong semau kita agar file lebih mudah dibaca
-      Kita dapat memasukkan baris komentar dengan menambahkan “//” pada awal
baris
-      Hanya terkait dengan satu file texture
-      Primitif yang digunakan hanya GL_TRIANGLES
-      Informasi awalnya akan berupa frasa NUMPOLLIES xx, dengan xx adalah
jumlah primitif
-      Setelah itu kita harus memberi spesifikasi triangle-nya dengan menuliskan daftar
vertex perbaris dengan format baris sbb.
X Y Z S Tdengan X,Y, Z adalah posisi vertex sedangkan S, T adalah pixel texture yang bersesuaian.





Link ke File Source Tutorial 13

Tutorial 14 :
3D rendering

Dalam latihan ke 14 ini kita akan membuat ilustrasi tentang bagaimana kita membuat object 3 dimensi seperti pesawat. Dimana object adalah sebuah pesawat yang bergerak, sama dengan langkah sebelumnya (Pada Tutorial ke 1) buat sebuah Project dengan nama Tutor14 dan di tambah File : Tutor14.cpp, di tambah dengan file bmp.h, bmp.cpp dan file : material.h yang kita butuhkan kemudian anda ketikan Source Code dibawah ini
3dsloader.h
/**********************************************************
 *
 * FUNCTION Load3DS (obj_type_ptr, char *)
 *
 * This function loads a mesh from a 3ds file.
 * Please note that we are loading only the vertices, polygons and mapping lists.
 * If you need to load meshes with advanced features as for example:
 * multi objects, materials, lights and so on, you must insert other chunk parsers.
 *
 *********************************************************/

extern char Load3DS (obj_type_ptr ogg, char *filename);

3dsloader.cpp
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <io.h>
#include "tutorial4.h"
#include "3dsloader.h"

/**********************************************************
 *
 * FUNCTION Load3DS (obj_type_ptr, char *)
 *
 * This function loads a mesh from a 3ds file.
 * Please note that we are loading only the vertices, polygons and mapping lists.
 * If you need to load meshes with advanced features as for example:
 * multi objects, materials, lights and so on, you must insert other chunk parsers.
 *
 *********************************************************/

char Load3DS (obj_type_ptr p_object, char *p_filename)
{
  int i; //Index variable

  FILE *l_file; //File pointer

  unsigned short l_chunk_id; //Chunk identifier
  unsigned int l_chunk_lenght; //Chunk lenght

  unsigned char l_char; //Char variable
  unsigned short l_qty; //Number of elements in each chunk

  unsigned short l_face_flags; //Flag that stores some face information

  if ((l_file=fopen (p_filename, "rb"))== NULL) return 0; //Open the file

  while (ftell (l_file) < filelength (fileno (l_file))) //Loop to scan the whole file
  {
    //getche(); //Insert this command for debug (to wait for keypress for each chuck reading)

    fread (&l_chunk_id, 2, 1, l_file); //Read the chunk header
    printf("ChunkID: %x\n",l_chunk_id);
    fread (&l_chunk_lenght, 4, 1, l_file); //Read the lenght of the chunk
    printf("ChunkLenght: %x\n",l_chunk_lenght);

    switch (l_chunk_id)
    {
      //----------------- MAIN3DS -----------------
      // Description: Main chunk, contains all the other chunks
      // Chunk ID: 4d4d
      // Chunk Lenght: 0 + sub chunks
      //-------------------------------------------
      case 0x4d4d:
        break;

      //----------------- EDIT3DS -----------------
      // Description: 3D Editor chunk, objects layout info
      // Chunk ID: 3d3d (hex)
      // Chunk Lenght: 0 + sub chunks
      //-------------------------------------------
      case 0x3d3d:
        break;

      //--------------- EDIT_OBJECT ---------------
      // Description: Object block, info for each object
      // Chunk ID: 4000 (hex)
      // Chunk Lenght: len(object name) + sub chunks
      //-------------------------------------------
      case 0x4000:
        i=0;
        do
        {
          fread (&l_char, 1, 1, l_file);
          p_object->name[i]=l_char;
          i++;
        }while(l_char != '\0' && i<20);
        break;

      //--------------- OBJ_TRIMESH ---------------
      // Description: Triangular mesh, contains chunks for 3d mesh info
      // Chunk ID: 4100 (hex)
      // Chunk Lenght: 0 + sub chunks
      //-------------------------------------------
      case 0x4100:
        break;

      //--------------- TRI_VERTEXL ---------------
      // Description: Vertices list
      // Chunk ID: 4110 (hex)
      // Chunk Lenght: 1 x unsigned short (number of vertices)
      //             + 3 x float (vertex coordinates) x (number of vertices)
      //             + sub chunks
      //-------------------------------------------
      case 0x4110:
        fread (&l_qty, sizeof (unsigned short), 1, l_file);
        p_object->vertices_qty = l_qty;
        printf("Number of vertices: %d\n",l_qty);
        for (i=0; i<l_qty; i++)
        {
          fread (&p_object->vertex[i].x, sizeof(float), 1, l_file);
          printf("Vertices list x: %f\n",p_object->vertex[i].x);
          fread (&p_object->vertex[i].y, sizeof(float), 1, l_file);
          printf("Vertices list y: %f\n",p_object->vertex[i].y);
          fread (&p_object->vertex[i].z, sizeof(float), 1, l_file);
          printf("Vertices list z: %f\n",p_object->vertex[i].z);
        }
        break;

      //--------------- TRI_FACEL1 ----------------
      // Description: Polygons (faces) list
      // Chunk ID: 4120 (hex)
      // Chunk Lenght: 1 x unsigned short (number of polygons)
      //             + 3 x unsigned short (polygon points) x (number of polygons)
      //             + sub chunks
      //-------------------------------------------
      case 0x4120:
        fread (&l_qty, sizeof (unsigned short), 1, l_file);
        p_object->polygons_qty = l_qty;
        printf("Number of polygons: %d\n",l_qty);
        for (i=0; i<l_qty; i++)
        {
          fread (&p_object->polygon[i].a, sizeof (unsigned short), 1, l_file);
          printf("Polygon point a: %d\n",p_object->polygon[i].a);
          fread (&p_object->polygon[i].b, sizeof (unsigned short), 1, l_file);
          printf("Polygon point b: %d\n",p_object->polygon[i].b);
          fread (&p_object->polygon[i].c, sizeof (unsigned short), 1, l_file);
          printf("Polygon point c: %d\n",p_object->polygon[i].c);
          fread (&l_face_flags, sizeof (unsigned short), 1, l_file);
          printf("Face flags: %x\n",l_face_flags);
        }
        break;

      //------------- TRI_MAPPINGCOORS ------------
      // Description: Vertices list
      // Chunk ID: 4140 (hex)
      // Chunk Lenght: 1 x unsigned short (number of mapping points)
      //             + 2 x float (mapping coordinates) x (number of mapping points)
      //             + sub chunks
      //-------------------------------------------
      case 0x4140:
        fread (&l_qty, sizeof (unsigned short), 1, l_file);
        for (i=0; i<l_qty; i++)
        {
          fread (&p_object->mapcoord[i].u, sizeof (float), 1, l_file);
          printf("Mapping list u: %f\n",p_object->mapcoord[i].u);
          fread (&p_object->mapcoord[i].v, sizeof (float), 1, l_file);
          printf("Mapping list v: %f\n",p_object->mapcoord[i].v);
        }
        break;

      //----------- Skip unknow chunks ------------
      //We need to skip all the chunks that currently we don't use
      //We use the chunk lenght information to set the file pointer
      //to the same level next chunk
      //-------------------------------------------
      default:
        fseek(l_file, l_chunk_lenght-6, SEEK_CUR);
    }
  }
  fclose (l_file); // Closes the file stream
  return (1); // Returns ok
}

Texture.h
extern int num_texture;

extern int LoadBitmap(char *filename);

Texture.cpp
#include <stdio.h>
#include <windows.h>
#include <GL/glut.h>
#include "texture.h"

/**********************************************************
 *
 * VARIABLES DECLARATION
 *
 *********************************************************/
int num_texture=-1; //Counter to keep track of the last loaded texture

/**********************************************************
 *
 * FUNCTION LoadBitmap(char *)
 *
 * This function loads a bitmap file and return the OpenGL reference ID to use that texture
 *
 *********************************************************/

int LoadBitmap(char *filename)
{
    int i, j=0; //Index variables
    FILE *l_file; //File pointer
    unsigned char *l_texture; //The pointer to the memory zone in which we will load the texture

    // windows.h gives us these types to work with the Bitmap files
    BITMAPFILEHEADER fileheader;
    BITMAPINFOHEADER infoheader;
    RGBTRIPLE rgb;

    num_texture++; // The counter of the current texture is increased

    if( (l_file = fopen(filename, "rb"))==NULL) return (-1); // Open the file for reading

    fread(&fileheader, sizeof(fileheader), 1, l_file); // Read the fileheader

    fseek(l_file, sizeof(fileheader), SEEK_SET); // Jump the fileheader
    fread(&infoheader, sizeof(infoheader), 1, l_file); // and read the infoheader

    // Now we need to allocate the memory for our image (width * height * color deep)
    l_texture = (byte *) malloc(infoheader.biWidth * infoheader.biHeight * 4);
    // And fill it with zeros
    memset(l_texture, 0, infoheader.biWidth * infoheader.biHeight * 4);

    // At this point we can read every pixel of the image
    for (i=0; i < infoheader.biWidth*infoheader.biHeight; i++)
    {
            // We load an RGB value from the file
            fread(&rgb, sizeof(rgb), 1, l_file);

            // And store it
            l_texture[j+0] = rgb.rgbtRed; // Red component
            l_texture[j+1] = rgb.rgbtGreen; // Green component
            l_texture[j+2] = rgb.rgbtBlue; // Blue component
            l_texture[j+3] = 255; // Alpha value
            j += 4; // Go to the next position
    }

    fclose(l_file); // Closes the file stream

    glBindTexture(GL_TEXTURE_2D, num_texture); // Bind the ID texture specified by the 2nd parameter

    // The next commands sets the texture parameters
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // If the u,v coordinates overflow the range 0,1 the image is repeated
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // The magnification function ("linear" produces better results)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); //The minifying function

    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); // We don't combine the color with the original surface color, use only the texture map.

    // Finally we define the 2d texture
    glTexImage2D(GL_TEXTURE_2D, 0, 4, infoheader.biWidth, infoheader.biHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, l_texture);

    // And create 2d mipmaps for the minifying function
    gluBuild2DMipmaps(GL_TEXTURE_2D, 4, infoheader.biWidth, infoheader.biHeight, GL_RGBA, GL_UNSIGNED_BYTE, l_texture);

    free(l_texture); // Free the memory we used to load the texture

    return (num_texture); // Returns the current texture OpenGL ID
}

Main.h
#define MAX_VERTICES 8000 // Max number of vertices (for each object)
#define MAX_POLYGONS 8000 // Max number of polygons (for each object)

// Our vertex type
typedef struct {
  float x,y,z;
} vertex_type;

// The polygon (triangle), 3 numbers that aim 3 vertices
typedef struct {
  int a,b,c;
} polygon_type;

// The mapcoord type, 2 texture coordinates for each vertex
typedef struct {
  float u,v;
} mapcoord_type;

// The object type
typedef struct {
  char name[20];
  int vertices_qty;
  int polygons_qty;
  vertex_type vertex[MAX_VERTICES];
  polygon_type polygon[MAX_POLYGONS];
  mapcoord_type mapcoord[MAX_VERTICES];
  int id_texture;
} obj_type, *obj_type_ptr;

Main.cpp
#include <windows.h>
#include <GL/glut.h>
#include "tutorial4.h"
#include "texture.h"
#include "3dsloader.h"

// The width and height of your window, change them as you like
int screen_width=640;
int screen_height=480;

// Absolute rotation values (0-359 degrees) and rotation increments for each frame
double rotation_x=0, rotation_x_increment=0.1;
double rotation_y=0, rotation_y_increment=0.05;
double rotation_z=0, rotation_z_increment=0.03;

// Flag for rendering as lines or filled polygons
int filling=1; //0=OFF 1=ON

//Now the object is generic, the cube has annoyed us a little bit, or not?
obj_type object;

void init(void)
{
  glClearColor(0.0, 0.0, 0.0, 0.0); // This clear the background color to black
  glShadeModel(GL_SMOOTH); // Type of shading for the polygons

  // Viewport transformation
  glViewport(0,0,screen_width,screen_height);

  // Projection transformation
  glMatrixMode(GL_PROJECTION); // Specifies which matrix stack is the target for matrix operations
  glLoadIdentity(); // We initialize the projection matrix as identity

  gluPerspective(45.0f,(GLfloat)screen_width/(GLfloat)screen_height,10.0f,10000.0f); // We define the "viewing volume"

  glEnable(GL_DEPTH_TEST); // We enable the depth test (also called z buffer)
  glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); // Polygon rasterization mode (polygon filled)
  glEnable(GL_TEXTURE_2D); // This Enable the Texture mapping
  Load3DS (&object,"spaceship.3ds");
  object.id_texture=LoadBitmap("spaceshiptexture.bmp"); // The Function LoadBitmap() return the current texture ID

  // If the last function returns -1 it means the file was not found so we exit from the program
  if (object.id_texture==-1)
  {
    MessageBox(NULL,"Image file: spaceshiptexture.bmp not found","Zetadeck",MB_OK | MB_ICONERROR);
    exit (0);
  }
}

void resize (int width, int height)
{
  screen_width=width; // We obtain the new screen width values and store it
  screen_height=height; // Height value

  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // We clear both the color and the depth buffer so to draw the next frame
  glViewport(0,0,screen_width,screen_height); // Viewport transformation
  glMatrixMode(GL_PROJECTION); // Projection transformation
  glLoadIdentity(); // We initialize the projection matrix as identity
  gluPerspective(45.0f,(GLfloat)screen_width/(GLfloat)screen_height,10.0f,10000.0f);
  glutPostRedisplay (); // This command redraw the scene (it calls the same routine of glutDisplayFunc)
}

void keyboard (unsigned char key, int x, int y)
{
  switch (key)
  {
    case ' ':
      rotation_x_increment=0;
      rotation_y_increment=0;
      rotation_z_increment=0;
      break;
    case 'r': case 'R':
      if (filling==0)
      {
        glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); // Polygon rasterization mode (polygon filled)
        filling=1;
      }
      else
      {
        glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); // Polygon rasterization mode (polygon outlined)
        filling=0;
      }
      break;
  }
}

void keyboard_s (int key, int x, int y)
{
  switch (key)
  {
    case GLUT_KEY_UP:
      rotation_x_increment = rotation_x_increment +0.005;
      break;
    case GLUT_KEY_DOWN:
      rotation_x_increment = rotation_x_increment -0.005;
      break;
    case GLUT_KEY_LEFT:
      rotation_y_increment = rotation_y_increment +0.005;
      break;
    case GLUT_KEY_RIGHT:
      rotation_y_increment = rotation_y_increment -0.005;
      break;
    case GLUT_KEY_PAGE_UP:
      rotation_z_increment = rotation_z_increment +0.005;
      break;
    case GLUT_KEY_PAGE_DOWN:
      rotation_z_increment = rotation_z_increment -0.005;
      break;
  }
}

void display(void)
{
  int l_index;
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glMatrixMode(GL_MODELVIEW); // Modeling transformation
  glLoadIdentity(); // Initialize the model matrix as identity

  glTranslatef(0.0,0.0,-300); // We move the object forward (the model matrix is multiplied by the translation matrix)
  rotation_x = rotation_x + rotation_x_increment;
  rotation_y = rotation_y + rotation_y_increment;
  rotation_z = rotation_z + rotation_z_increment;

  if (rotation_x > 359) rotation_x = 0;
  if (rotation_y > 359) rotation_y = 0;
  if (rotation_z > 359) rotation_z = 0;

  glRotatef(rotation_x,1.0,0.0,0.0); // Rotations of the object (the model matrix is multiplied by the rotation matrices)
  glRotatef(rotation_y,0.0,1.0,0.0);
  glRotatef(rotation_z,0.0,0.0,1.0);
  glBindTexture(GL_TEXTURE_2D, object.id_texture); // We set the active texture

  glBegin(GL_TRIANGLES); // glBegin and glEnd delimit the vertices that define a primitive (in our case triangles)
    for (l_index=0;l_index<object.polygons_qty;l_index++)
    {
      //----------------- FIRST VERTEX -----------------
      // Texture coordinates of the first vertex
      glTexCoord2f( object.mapcoord[ object.polygon[l_index].a ].u,
                    object.mapcoord[ object.polygon[l_index].a ].v);
      // Coordinates of the first vertex
      glVertex3f( object.vertex[ object.polygon[l_index].a ].x,
                  object.vertex[ object.polygon[l_index].a ].y,
                  object.vertex[ object.polygon[l_index].a ].z);   //Vertex definition

      //----------------- SECOND VERTEX -----------------
      // Texture coordinates of the second vertex
      glTexCoord2f( object.mapcoord[ object.polygon[l_index].b ].u,
                    object.mapcoord[ object.polygon[l_index].b ].v);
      // Coordinates of the second vertex
      glVertex3f( object.vertex[ object.polygon[l_index].b ].x,
                  object.vertex[ object.polygon[l_index].b ].y,
                  object.vertex[ object.polygon[l_index].b ].z);

      //----------------- THIRD VERTEX -----------------
      // Texture coordinates of the third vertex
      glTexCoord2f( object.mapcoord[ object.polygon[l_index].c ].u,
                    object.mapcoord[ object.polygon[l_index].c ].v);
      // Coordinates of the Third vertex
      glVertex3f( object.vertex[ object.polygon[l_index].c ].x,
                  object.vertex[ object.polygon[l_index].c ].y,
                  object.vertex[ object.polygon[l_index].c ].z);
    }
  glEnd();
  glFlush(); // This force the execution of OpenGL commands
  glutSwapBuffers(); // In double buffered mode we invert the positions of the visible buffer and the writing buffer
}

int main(int argc, char **argv)
{
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize(screen_width,screen_height);
  glutInitWindowPosition(0,0);
  glutCreateWindow("SpaceShip dari File 3DS Simple");
  glutDisplayFunc(display);
  glutIdleFunc(display);
  glutReshapeFunc (resize);
  glutKeyboardFunc (keyboard);
  glutSpecialFunc (keyboard_s);
  init();
  glutMainLoop();
  return(0);
}

Tutorial4.h
/**********************************************************
 *
 * TYPES DECLARATION
 *
 *********************************************************/

#define MAX_VERTICES 8000 // Max number of vertices (for each object)
#define MAX_POLYGONS 8000 // Max number of polygons (for each object)

// Our vertex type
typedef struct {
  float x,y,z;
} vertex_type;

// The polygon (triangle), 3 numbers that aim 3 vertices
typedef struct {
  int a,b,c;
} polygon_type;

// The mapcoord type, 2 texture coordinates for each vertex
typedef struct {
  float u,v;
}mapcoord_type;

// The object type
typedef struct {
  char name[20];

  int vertices_qty;
  int polygons_qty;

  vertex_type vertex[MAX_VERTICES];
  polygon_type polygon[MAX_POLYGONS];
  mapcoord_type mapcoord[MAX_VERTICES];
  int id_texture;
} obj_type, *obj_type_ptr;

Saat file Tutor14.cpp di jalankan akan terjadi Error, untuk menghindari Error tersebut, tambahkan file glaux.lib pada bagian :
Klik kanan pada Project Tutor14 anda, kemudian pilih Properties di bagian bawah popup menu,kemudian tampil dialog menu. Kemudian pilih Linker, pilih Input, pada bagian Properties, additional dependencies, klik combobox, kemudian pilih <edit>, akan tampil dialog menu, ketikan glaux.lib, pada kotak isian, kemudian klik OK, dan OK untuk dialog terakhir.
Kemudian membutuhkan file : spaceship.3ds dan spaceshiptexture.bmp
Apabila source code tersebut di jalankan, akan ditampilkan gambar berikut seperti sebuah pesawat yang sedang berputar dan bergerak ke atas ke kiri dan ke kanan.





Link ke File Source Tutorial 14



Tutorial 16 :
Sistem partikel

Dalam latihan ke 16 ini kita akan membuat ilustrasi tentang bagaimana kita membuat partikel seperti kembang api. Dimana object seolah olah memudah menjadi besar dari kecil, sama dengan langkah sebelumnya (Pada Tutorial ke 1) buat sebuah Project dengan nama Tutor16 dan di tambah File : Tutor16.cpp, di tambah dengan file bmp.h, bmp.cpp dan file : material.h yang kita butuhkan kemudian anda ketikan Source Code dibawah ini
Bmp.h
#include <GL/glaux.h>
AUX_RGBImageRec *LoadBMP(char *Filename);

Bmp.cpp
#include <windows.h>
#include <stdio.h> // Header File For Standard Input/Output
#include <gl\gl.h> // Header File For The OpenGL32 Library
#include <gl\glu.h> // Header File For The GLu32 Library
#include <gl\glaux.h> // Header File For The Glaux Library
#include "bmp.h"

AUX_RGBImageRec *LoadBMP(char *Filename) // Loads A Bitmap Image
{
       FILE *File=NULL; // File Handle
       if (!Filename)
       // Make Sure A Filename Was Given
       {
       return NULL;
       // If Not Return NULL
       }
       File=fopen(Filename,"r"); // Check To See If The File Exists
       if (File)
       // Does The File Exist?
       {
       fclose(File);
       // Close The Handle
       return auxDIBImageLoad(Filename); // Load The Bitmap And Return A Pointer
       }
       return NULL;
       // If Load Failed Return NULL
}


Particle.h
#ifndef PARTICLE_H_
typedef struct
{
float lifetime; // total lifetime of the particle
float decay; // decay speed of the particle
float r,g,b; // color values of the particle
float xpos,ypos,zpos; // position of the particle
float xspeed,yspeed,zspeed; // speed of the particle
bool active; // is particle active or not?
} PARTICLE;
void CreateParticle(int i);
void InitParticle();
void EvolveParticle();
#endif

Particle.cpp
#include <windows.h>
#include <stdlib.h>
#include <math.h>
#include "particle.h"
const short maxparticle=2000;       // set maximum number of particles
PARTICLE particle[maxparticle];
void CreateParticle(int i)
{
  particle[i].lifetime= (float)(500000*rand()/RAND_MAX)/500000.0;
  particle[i].decay=0.001;
  particle[i].r = 0.7;
  particle[i].g = 0.7;
  particle[i].b = 1.0;
  particle[i].xpos= 0.0;
  particle[i].ypos= 0.0;
  particle[i].zpos= 0.0;
  particle[i].xspeed = 10*(0.0005-(float)(100*rand()/RAND_MAX)/100000.0);
  particle[i].yspeed = 0.01-(float)(100*rand()/RAND_MAX)/100000.0;
  particle[i].zspeed = 0.0005-(float)(100*rand()/RAND_MAX)/100000.0;
  particle[i].active = true;
}
//---------------------------------------------------------------------------
void InitParticle()
{
  for (int i=0;i<=maxparticle;i++){ // initialize the particle parameters
    CreateParticle(i);
    particle[i].active = false;     // set all particles inactive
  }
}
//---------------------------------------------------------------------------
void EvolveParticle()
{
  for (int i=0;i<=maxparticle;i++){ // evolve the particle parameters
    particle[i].lifetime-=particle[i].decay;
    particle[i].xpos+=particle[i].xspeed;
    particle[i].ypos+=particle[i].yspeed;
    particle[i].zpos+=particle[i].zspeed;
    particle[i].yspeed-=0.00010;
  }
}

Tutor16.cpp
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <GL/glut.h>
#include "bmp.h"
#include "particle.h"

float z_pos=-5.0f;
float rot=0.0f;
GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat LightPosition[]= { 0.0f, 0.0f, 2.0f, 1.0f };

/* array to hold texture handles */
GLuint filter; // Which Filter To Use
GLuint texture[1]; // Storage For 3 Textures

/* Particle System */
extern int const maxparticle=2000; // set maximum number of particles
extern PARTICLE particle[maxparticle];

int LoadGLTextures() //Load Bitmaps And Convert To Textures
{
       int Status=FALSE; //Status Indicator
       AUX_RGBImageRec *TextureImage[1]; // Create Storage Space For The Texture
       memset(TextureImage,0,sizeof(void *)*1); // Set The Pointer To NULL
       // Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit
       if (TextureImage[0]=LoadBMP("particle.bmp"))
       {
       Status=TRUE;
       // Set The Status To TRUE
       glGenTextures(1, &texture[0]); //Create Three Textures
       // Create Nearest Filtered Texture
       glBindTexture(GL_TEXTURE_2D, texture[0]);
       glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
       glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
       glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX,
       TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
       }
       if (TextureImage[0]) // If Texture Exists
       {
       if (TextureImage[0]->data) // If Texture Image Exists
       {
       free(TextureImage[0]->data); // Free The Texture Image Memory
       }
       free(TextureImage[0]); //Free The Image Structure
       }
       glEnable(GL_TEXTURE_2D); //Enable Texture Mapping
       return Status;
       // Return The Status
}

void resize(int width, int height)
{
       glViewport(0, 0, width, height);
       //glMatrixMode(GL_PROJECTION);
       //glLoadIdentity();
       //gluPerspective(45.0, (float)width/(float)height, 0.0, 300.0);
       glMatrixMode(GL_PROJECTION); // the following operations affect the projection matrix
       glLoadIdentity(); // restore matrix to original state
       glOrtho( -0.60,0.60,-0.20,0.60,-0.60,0.60); // defines the viewing volume
       glMatrixMode(GL_MODELVIEW);
       glLoadIdentity();
}

void myTimeOut(int id)
{
       // called if timer event
       // ...advance the state of animation incrementally...
       rot+=1;
       glutPostRedisplay(); // request redisplay
       glutTimerFunc(100, myTimeOut, 0); // request next timer event
}

void myKeyboard(unsigned char key,int x, int y)
{
       if((key=='<')||(key==',')) z_pos-=0.1f;
       else if((key=='>')||(key=='.')) z_pos+=0.1f;
       else if((key=='F')||(key='f'))
       {
       filter+=1;
       if (filter>2)
       {
       filter=0;
       }
       printf("filter: %i",filter);
       }
}

void mydisplay(void)
{
       glClear(GL_COLOR_BUFFER_BIT);
       //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
       glLoadIdentity();
       glRotatef(50.0,1.0,0.0,0.0); // show scene from top front
       glBindTexture(GL_TEXTURE_2D,texture[0]); // choose particle   texture
       for (int i=0;i<=maxparticle;i++){
              if(particle[i].ypos<0.0) particle[i].lifetime=0.0;
                     if((particle[i].active==true) && (particle[i].lifetime>0.0)){
                           glColor3f(particle[i].r,particle[i].g,particle[i].b);
                           glBegin(GL_TRIANGLE_STRIP);
                           glTexCoord2f(0.0,1.0); glVertex3f(particle[i].xpos+0.005,particle[i].ypos+0.005, particle[i].zpos+0.0); // top right
                           glTexCoord2f(0.0,0.0); glVertex3f(particle[i].xpos-0.005,particle[i].ypos+0.005, particle[i].zpos+0.0); // top left
                           glTexCoord2f(1.0,1.0); glVertex3f(particle[i].xpos+0.005,particle[i].ypos-0.005, particle[i].zpos+0.0); // bottom right
                           glTexCoord2f(1.0,0.0); glVertex3f(particle[i].xpos-0.005,particle[i].ypos-0.005, particle[i].zpos+0.0); // bottom left
                           glEnd();
              } else CreateParticle(i);
       }
       EvolveParticle();
       glFlush();
       glutSwapBuffers();
}

void init()
{
       glDisable(GL_DEPTH_TEST); // deactivate hidden surface removal
       glDisable(GL_CULL_FACE); // show backside of polygons
       glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Black Background
       glColor4f(1.0f, 1.0f, 1.0f, 0.5); // Full Brightness. 50% Alpha
       if (!LoadGLTextures()) // Jump To Texture Loading Routine
       {
       return; // If Texture Didn't Load Return FALSE
       }
       InitParticle();
       glMatrixMode(GL_MODELVIEW);
       return;
}

int main(int argc, char** argv)
{
       glutInit(&argc,argv);
       glutInitDisplayMode( GLUT_DOUBLE);
       glutInitWindowSize(500,500);
       glutInitWindowPosition(0,0);
       glutCreateWindow("simple");
       // callbacks
       glutDisplayFunc(mydisplay);
       glutKeyboardFunc(myKeyboard);
       glutTimerFunc(100, myTimeOut, 0);
       glutReshapeFunc(resize);
       init();
       glutMainLoop();
       return 0;
}

Saat file Tutor16.cpp di jalankan akan terjadi Error, untuk menghindari Error tersebut, tambahkan file glaux.lib pada bagian :
Klik kanan pada Project Tutor16 anda, kemudian pilih Properties di bagian bawah popup menu,kemudian tampil dialog menu. Kemudian pilih Linker, pilih Input, pada bagian Properties, additional dependencies, klik combobox, kemudian pilih <edit>, akan tampil dialog menu, ketikan glaux.lib, pada kotak isian, kemudian klik OK, dan OK untuk dialog terakhir.
Apabila source code tersebut di jalankan, akan ditampilkan partikel mengembang dari kecil menjadi besar, dimana butiran butilan kecil disimpan dalam file particle yang kemudian di setting pada mydisplay(), yang dapat kita lihat seperti gambar dibawah ini.





Link ke File Source Tutorial 16

Tutorial 17 :
Lighting

Dalam latihan ke 17 ini kita akan membuat ilustrasi tentang bagaimana kita memberikan pencahayaan ke sebuah object. Dimana object dan background seperti terlihat mendapatkan cahaya, sama dengan langkah sebelumnya (Pada Tutorial ke 1) buat sebuah Project dengan nama Tutor17 dan di tambah File : Tutor17.cpp, di tambah dengan file glm.h, glm.cpp dan file : material.h yang kita butuhkan kemudian anda ketikan Source Code dibawah ini

Link ke File Source Tutorial 17

Apabila source code tersebut di jalankan, akan ditampilkan gambar berikut, dimana object material dalam bentuk vas donut akan di load dan seolah olah dibagian sisi depan object tersebut mendapat cahaya, sementara sisi yang lain yang terkena cahaya. Dan seperti terlihat dibawah ini




Tutorial 18 :
Lighting Position

Dalam latihan ke 18 ini kita akan membuat ilustrasi tentang bagaimana kita memberikan pencahayaan ke sebuah object dari sebuah posisi. Dimana object bisa terlihat di satu sisi dan gelap disisi yang lian dengan teknik lighting position, sama dengan langkah sebelumnya (Pada Tutorial ke 1) buat sebuah Project dengan nama Tutor18 dan di tambah File : Tutor18.cpp, di tambah dengan (file glm.h, glm.cpp yang dipergunakan pada latihan 17) dan file : material.h yang kita butuhkan kemudian anda ketikan Source Code dibawah ini

Link ke File Source Tutorial 18

Apabila source code tersebut di jalankan, akan ditampilkan gambar berikut, dimana object material dalam bentuk vas bunga akan di load dan seolah olah disatu sisi lebih terang di banding sisi yang lain yang terkena cahaya. Dan seperti terlihat dibawah ini.




Tutorial 19 :
Vertex Animation

Dalam latihan ke 19 ini kita akan membuat ilustrasi tentang bagaimana kita membuat gambar yang di gerakan seolah olah seperti tertiup angin istilah ini disebut dengan Vertex Animation. dan disetiap bagian diberi gambar texture, sama dengan langkah sebelumnya (Pada Tutorial ke 1) buat sebuah Project dengan nama Tutor19 dan di tambah File : Tutor19.cpp, yang kita butuhkan kemudian anda ketikan Source Code dibawah ini
#include <windows.h>
#include <math.h>                                     // Math Library Header File
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <GL/glut.h>
#include <GL/glaux.h>

/* array to hold texture handles */
GLuint filter;                                        // Which Filter To Use
float z_pos=-12.0f;

float points[45][45][3];                              // The Array For The Points On The Grid Of Our "Wave"
int wiggle_count = 0;                                 // Counter Used To Control How Fast Flag Waves

GLfloat xrot;                                         // X Rotation ( NEW )
GLfloat yrot;                                         // Y Rotation ( NEW )
GLfloat zrot;                                         // Z Rotation ( NEW )
GLfloat hold;                                         // Temporarily Holds A Floating Point Value

GLuint texture[1];                                    // Storage For One Texture ( NEW )

AUX_RGBImageRec *LoadBMP(char *Filename)              // Loads A Bitmap Image
{
  FILE *File=NULL;                                    // File Handle

  if (!Filename)                                      // Make Sure A Filename Was Given
  {
    return NULL;                                      // If Not Return NULL
  }

  File=fopen(Filename,"r");                           // Check To See If The File Exists
  if (File)                                           // Does The File Exist?
  {
    fclose(File);                                     // Close The Handle
    return auxDIBImageLoadA(Filename);                // Load The Bitmap And Return A Pointer
  }

  return NULL;                                        // If Load Failed Return NULL
}

int LoadGLTextures()                                  // Load Bitmaps And Convert To Textures
{
  int Status=FALSE;                                   // Status Indicator

  AUX_RGBImageRec *TextureImage[1];                   // Create Storage Space For The Texture

  memset(TextureImage,0,sizeof(void *)*1);            // Set The Pointer To NULL

  // Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit
  if (TextureImage[0]=LoadBMP("Data/glass.bmp"))
  {
    Status=TRUE;                                      // Set The Status To TRUE

    glGenTextures(1, &texture[0]);                    // Create The Texture

    // Typical Texture Generation Using Data From The Bitmap
    glBindTexture(GL_TEXTURE_2D, texture[0]);
    glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  }

  if (TextureImage[0])                                // If Texture Exists
  {
    if (TextureImage[0]->data)                        // If Texture Image Exists
    {
      free(TextureImage[0]->data);                    // Free The Texture Image Memory
    }
    free(TextureImage[0]);                            // Free The Image Structure
  }

  return Status;                                      // Return The Status
}

void resize(GLsizei width, GLsizei height)            // Resize And Initialize The GL Window
{
  if (height==0)                                      // Prevent A Divide By Zero By
  {
    height=1;                                         // Making Height Equal One
  }
  glViewport(0,0,width,height);                       // Reset The Current Viewport

  glMatrixMode(GL_PROJECTION);                        // Select The Projection Matrix
  glLoadIdentity();                                   // Reset The Projection Matrix

  // Calculate The Aspect Ratio Of The Window
  gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

  glMatrixMode(GL_MODELVIEW);                         // Select The Modelview Matrix
  glLoadIdentity();                                   // Reset The Modelview Matrix
}

int init(GLvoid)                                      // All Setup For OpenGL Goes Here
{
  if (!LoadGLTextures())                              // Jump To Texture Loading Routine ( NEW )
  {
    return FALSE;                                     // If Texture Didn't Load Return FALSE
  }

  glEnable(GL_TEXTURE_2D);                            // Enable Texture Mapping ( NEW )
  glShadeModel(GL_SMOOTH);                            // Enable Smooth Shading
  glClearColor(0.0f, 0.0f, 0.0f, 0.5f);               // Black Background
  glClearDepth(1.0f);                                 // Depth Buffer Setup
  glEnable(GL_DEPTH_TEST);                            // Enables Depth Testing
  glDepthFunc(GL_LEQUAL);                             // The Type Of Depth Testing To Do
  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  // Really Nice Perspective Calculations
  glPolygonMode( GL_BACK, GL_FILL );                  // Back Face Is Solid
  glPolygonMode( GL_FRONT, GL_LINE );                 // Front Face Is Made Of Lines

  for(int x=0; x<45; x++)
  {
    for(int y=0; y<45; y++)
    {
      points[x][y][0]=float((x/5.0f)-4.5f);
      points[x][y][1]=float((y/5.0f)-4.5f);
      points[x][y][2]=float(sin((((x/5.0f)*40.0f)/360.0f)*3.141592654*2.0f));
    }
  }

  return TRUE;                                        // Initialization Went OK
}

void mydisplay(GLvoid)                                // Here's Where We Do All The Drawing
{
  int x, y;
  float float_x, float_y, float_xb, float_yb;

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
  glLoadIdentity();                                   // Reset The View

  glTranslatef(0.0f,0.0f,z_pos);

  glRotatef(xrot,1.0f,0.0f,0.0f);
  glRotatef(yrot,0.0f,1.0f,0.0f);
  glRotatef(zrot,0.0f,0.0f,1.0f);

  glBindTexture(GL_TEXTURE_2D, texture[0]);

  glBegin(GL_QUADS);
    for( x = 0; x < 44; x++ )
    {
      for( y = 0; y < 44; y++ )
      {
        float_x = float(x)/44.0f;
        float_y = float(y)/44.0f;
        float_xb = float(x+1)/44.0f;
        float_yb = float(y+1)/44.0f;

        glTexCoord2f( float_x, float_y);
        glVertex3f( points[x][y][0], points[x][y][1], points[x][y][2] );

        glTexCoord2f( float_x, float_yb );
        glVertex3f( points[x][y+1][0], points[x][y+1][1], points[x][y+1][2] );

        glTexCoord2f( float_xb, float_yb );
        glVertex3f( points[x+1][y+1][0], points[x+1][y+1][1], points[x+1][y+1][2] );

        glTexCoord2f( float_xb, float_y );
        glVertex3f( points[x+1][y][0], points[x+1][y][1], points[x+1][y][2] );
      }
    }
  glEnd();

  if( wiggle_count == 2 )
  {
    for( y = 0; y < 45; y++ )
    {
      hold=points[0][y][2];
      for( x = 0; x < 44; x++)
      {
        points[x][y][2] = points[x+1][y][2];
      }
      points[44][y][2]=hold;
    }
    wiggle_count = 0;
  }

  wiggle_count++;

  xrot+=0.3f;
  yrot+=0.2f;
  zrot+=0.4f;

  glFlush();
  glutSwapBuffers();
}

void myTimeOut(int id)
{
  // called if timer event
  // ...advance the state of animation incrementally...
  //rot+=1;
  glutPostRedisplay();                                // request redisplay
  glutTimerFunc(10, myTimeOut, 0);                    // request next timer event
}

void myKeyboard(unsigned char key,int x, int y)
{
  if((key=='<')||(key==',')) z_pos-=0.1f;
  else if((key=='>')||(key=='.')) z_pos+=0.1f;
}

void mySpecialKeyboard(int key,int x, int y)
{
}

int main(int argc, char** argv)
{
  printf("Simple Vertex Animation Demo \n\n");
  printf("Press '<' key to move object farther (alongside -Z axis) \n");
  printf("Press '>' key to move object nearer (alongside +Z axis) \n");
  glutInit(&argc,argv);
  glutInitDisplayMode( GLUT_RGB |GLUT_DOUBLE| GLUT_DEPTH );
  glutInitWindowSize(500,500);
  glutInitWindowPosition(0,0);
  glutCreateWindow("Animasi Bendera Simple");

  // callbacks
  glutDisplayFunc(mydisplay);
  glutKeyboardFunc(myKeyboard);
  glutSpecialFunc(mySpecialKeyboard);
  glutTimerFunc(100, myTimeOut, 0);
  glutReshapeFunc(resize);

  init();

  glutMainLoop();

  return 0;
}

PENJELASAN :
Apabila source code tersebut di jalankan, akan ditampilkan gambar berikut, dimana object digerakan seperti tertiup angi yang di setting pada mydisplay. Dan seperti terlihat dibawah ini.



Link ke File Source Tutorial 19

Untuk file lengkap tutorial dalam bentu PDF, berikut ini adalah linknya : http://inafile.com/i4zj3dqaaiot

Terima kasih, semoga dapat membantu dalam mepelajari OPENGL dengan GLUT

3 komentar:

  1. trimasih gan,,, penjelasnnya mudah dipahami

    BalasHapus
  2. keren sudah saya coba semua berhasil...

    saya tambahkan sedikit tentang programing openGL 2D, 3D dan animasinya di blog ane untuk referency :
    ==================================================
    Myblog
    ==================================================

    BalasHapus
  3. Gold Casino - Gold Casino 카지노 카지노 우리카지노 우리카지노 349Slingo Mango Habanero Hot Sauce, 4 fl oz - Thai

    BalasHapus