Rabu, 25 November 2015

Membuat Animasi Hely 3D dengan OpenGL



Membuat objek Hely 3D yang baling-balingnya bisa berputar (animasi) dengan menggunakan Visual Studio 2013 Express.


Selamat Pagi rekan-rekan sekalian, kabar baik bukan? Ogut berharap keadaan rekan-rekan sehat selalu, pagi ini ogut akan memulai seri pemrograman game 3D sederhana, dimulai dari membuat objek 3D yang sederhana dahulu.


Dari gambar di atas rekan-rekan bisa melihat Hely 3D yang akan ogut bahas di artikel kali ini.


Untuk membuat objek 3D seperti di atas ogut sarankan Anda membaca artikel yang membahas tentang teori animasi 3D dengan vektor R3, metode 3 daftar dan membuat objek dengan 3ds max. Ketiga artikel sudah ogut bahas di blog ini rekan-rekan dapat membaca di link yang sudah ogut sertakan.

Ok...lanjut.....ogut anggap rekan-rekan sudah paham tentang ketiga artikel di atas.


Perhatikan gambar di atas. Hely ogut buat dengan menggunakan software 3ds max, dan ogut membuat 24 frame supaya Hely 3D baling-baling-nya beranimasi  (berputar).


Pada gambar di atas Anda dapat melihat posisi baling-baling yang berbeda dengan gambar sebelumnya. Setiap frame baling-baling ogut putar sebesar 15° agar animasi saat ditampilkan di program menjadi halus, untuk lebih jelasnya perhatikan oret-oretan di bawah ini.


Dari gambar di atas terlihat untuk Frame 0 posisi baling-baling searah dengan sumbu, untuk frame 1 posisi baling-baling berada 15° dari sumbu. Untuk frame-frame yang lain juga sama, setiap frame mempunyai selisih 15°, sehingga untuk berputar satu lingkaran penuh sebesar 360° diperlukan 24 frame (360° / 15°).


Gambar di atas menunjukan posisi baling-baling untuk frame ke-24 (karena frame dimulai dari 0 maka di gambar frame di tulis 23).

Ok sampai disini jelas ya, apa itu frame dan kenapa Hely 3D membutuhkan 24 frame. Lanjut ke tahap berikutnya.

Pada artikel metode 3 daftar telah di jelaskan tentang daftar face (list of face), daftar TK (list of TK) dan daftar vertex (list of vertex). Hely 3D yang ogut buat juga menggunakan metode 3 daftar seperti gambar di bawah ini.


Pada gambar di atas Anda dapat melihat struktur objek Hely 3D yang ogut simpan dalam sebuah file text (Hely3D. MESH3DANIM). Pada gambar tampak posisi total face, total TK, total vertex per frame dan sebagainya dan sebagainya. Untuk lebih jelasnya Anda dapat melihat isi dari file Hely3D. MESH3DANIM dengan menggunakan editor Notepad.


Dari gambar di atas Anda dapat melihat bahwa objek Hely 3D   memerlukan Face sebanyak 580, TK sebanyak 839, Vertex sebanyak 332  (untuk 1 frame perlu 332 vertex) dan frame sebanyak 24. Di bawah baris pertama itulah isi dari daftar face (list of face).


Di bawah list of face disimpan list of TK, seperti yang Anda lihat pada gambar di atas.


Dan terakhir di bawah list of TK ogut simpan list of vertex (jumlah total vertex = 332 X 24). Jadi prinsipnya sama saja dengan menggunakan 3 daftar, tetapi 3 daftar untuk Hely 3D ogut simpan di satu buah file.

Sekarang timbul pertanyaan, bagaimana cara membuat list of face, list of TK dan lain-lain? Jawabnya dengan menggunakan script dan sudah ogut bahas di artikel membuat objek 3D dengan menggunakan 3ds max.

Bagian terakhir yang harus ogut jelaskan........animasi 3D. Teorinya sudah ogut bahas di artikel teori animasi 3D dengan vektor R3, Anda tinggal klik link-nya untuk membaca artikel. Jadi ogut tidak perlu menjelaskan lagi ya......

Kita langsung ke programming-nya, pertama deklarasi variable dan structure yang diperlukan

typedef struct
{
int indexV1;
int indexV2;
int indexV3;

int indexTK1;
int indexTK2;
int indexTK3;
}Face;

typedef struct
{
float X;
float Y;
float Z;
}Vertex;

typedef struct
{
float s;
float t;
}TK;

//===================
//variabel Hely3DAnim
//===================
int TotalF_Hely3DAnim;
int TotalTK_Hely3DAnim;
int TotalV_Hely3DAnim;
int TotalFr_Hely3DAnim;

int CurrFr_Hely3DAnim = 0;
int NextFr_Hely3DAnim = 1;
float Skala_Hely3DAnim = 0.0f;

Face *Face_Hely3DAnim;
TK *TK_Hely3DAnim;
Vertex *V_Hely3DAnim;
Vertex DispV_Hely3DAnim[3];

unsigned int Tekstur1;

Load objek Hely 3D.

bool LoadMesh3DAnim(char *FileName)
{
FILE *file;
errno_t err;
int i;

if ((err = fopen_s(&file, FileName, "r")) != 0)
{
MessageBox(NULL, _T("Mesh3DAnim load error"), _T("File tidak ditemukan!"), MB_OK);
return false;
}

fscanf_s(file, "%d", &TotalF_Hely3DAnim);
fscanf_s(file, "%d", &TotalTK_Hely3DAnim);
fscanf_s(file, "%d", &TotalV_Hely3DAnim);
fscanf_s(file, "%d", &TotalFr_Hely3DAnim);

//siapkan tempat untuk data mesh
Face_Hely3DAnim = new Face[TotalF_Hely3DAnim];
TK_Hely3DAnim = new TK[TotalTK_Hely3DAnim];
V_Hely3DAnim = new Vertex[TotalV_Hely3DAnim * TotalFr_Hely3DAnim];
//DispV_Hely3DAnim = new Vertex[TotalV_Hely3DAnim];

//load Face
for (i = 0; i < TotalF_Hely3DAnim; i++)
{
fscanf_s(file, "%d", &Face_Hely3DAnim[i].indexV1);
fscanf_s(file, "%d", &Face_Hely3DAnim[i].indexV2);
fscanf_s(file, "%d", &Face_Hely3DAnim[i].indexV3);

fscanf_s(file, "%d", &Face_Hely3DAnim[i].indexTK1);
fscanf_s(file, "%d", &Face_Hely3DAnim[i].indexTK2);
fscanf_s(file, "%d", &Face_Hely3DAnim[i].indexTK3);

Face_Hely3DAnim[i].indexV1--;
Face_Hely3DAnim[i].indexV2--;
Face_Hely3DAnim[i].indexV3--;

Face_Hely3DAnim[i].indexTK1--;
Face_Hely3DAnim[i].indexTK2--;
Face_Hely3DAnim[i].indexTK3--;
}

//load TK
for (i = 0; i < TotalTK_Hely3DAnim; i++)
{
fscanf_s(file, "%f", &TK_Hely3DAnim[i].s);
fscanf_s(file, "%f", &TK_Hely3DAnim[i].t);
}

//load Vertex
for (i = 0; i < (TotalV_Hely3DAnim * TotalFr_Hely3DAnim); i++)
{
fscanf_s(file, "%f", &V_Hely3DAnim[i].X);
fscanf_s(file, "%f", &V_Hely3DAnim[i].Y);
fscanf_s(file, "%f", &V_Hely3DAnim[i].Z);

//rotasi berdasarkan sumbu X, karena coordinat cartesius di 3ds max 
//berbeda dengan yang ogut setting di OpenGL
RotasiX(-180.0, V_Hely3DAnim[i].X, V_Hely3DAnim[i].Y, V_Hely3DAnim[i].Z);
}

fclose(file);

return true;
}

Lalu tampilkan animasi Hely 3D ke layar monitor

//Hely3D disini  ////////////////////////////////////////////
glBindTexture(GL_TEXTURE_2D, Tekstur1);

Skala_Hely3DAnim += 0.05f;
if (Skala_Hely3DAnim >= 1.0f)
{
Skala_Hely3DAnim = 0.0f;
CurrFr_Hely3DAnim++;
NextFr_Hely3DAnim++;

if (CurrFr_Hely3DAnim >= TotalFr_Hely3DAnim)
CurrFr_Hely3DAnim = 0;

if (NextFr_Hely3DAnim >= TotalFr_Hely3DAnim)
NextFr_Hely3DAnim = 0;
}


for (i = 0; i < TotalF_Hely3DAnim; i++)
{
j = Face_Hely3DAnim[i].indexV1 + (TotalV_Hely3DAnim * CurrFr_Hely3DAnim);
k = Face_Hely3DAnim[i].indexV1 + (TotalV_Hely3DAnim * NextFr_Hely3DAnim);
DispV_Hely3DAnim[0].X = V_Hely3DAnim[j].X + (V_Hely3DAnim[k].X - V_Hely3DAnim[j].X) * Skala_Hely3DAnim;
DispV_Hely3DAnim[0].Y = V_Hely3DAnim[j].Y + (V_Hely3DAnim[k].Y - V_Hely3DAnim[j].Y) * Skala_Hely3DAnim;
DispV_Hely3DAnim[0].Z = V_Hely3DAnim[j].Z + (V_Hely3DAnim[k].Z - V_Hely3DAnim[j].Z) * Skala_Hely3DAnim;

j = Face_Hely3DAnim[i].indexV2 + (TotalV_Hely3DAnim * CurrFr_Hely3DAnim);
k = Face_Hely3DAnim[i].indexV2 + (TotalV_Hely3DAnim * NextFr_Hely3DAnim);
DispV_Hely3DAnim[1].X = V_Hely3DAnim[j].X + (V_Hely3DAnim[k].X - V_Hely3DAnim[j].X) * Skala_Hely3DAnim;
DispV_Hely3DAnim[1].Y = V_Hely3DAnim[j].Y + (V_Hely3DAnim[k].Y - V_Hely3DAnim[j].Y) * Skala_Hely3DAnim;
DispV_Hely3DAnim[1].Z = V_Hely3DAnim[j].Z + (V_Hely3DAnim[k].Z - V_Hely3DAnim[j].Z) * Skala_Hely3DAnim;

j = Face_Hely3DAnim[i].indexV3 + (TotalV_Hely3DAnim * CurrFr_Hely3DAnim);
k = Face_Hely3DAnim[i].indexV3 + (TotalV_Hely3DAnim * NextFr_Hely3DAnim);
DispV_Hely3DAnim[2].X = V_Hely3DAnim[j].X + (V_Hely3DAnim[k].X - V_Hely3DAnim[j].X) * Skala_Hely3DAnim;
DispV_Hely3DAnim[2].Y = V_Hely3DAnim[j].Y + (V_Hely3DAnim[k].Y - V_Hely3DAnim[j].Y) * Skala_Hely3DAnim;
DispV_Hely3DAnim[2].Z = V_Hely3DAnim[j].Z + (V_Hely3DAnim[k].Z - V_Hely3DAnim[j].Z) * Skala_Hely3DAnim;

glBegin(GL_TRIANGLES);
//glBegin(GL_LINE_LOOP);
glTexCoord2f(TK_Hely3DAnim[Face_Hely3DAnim[i].indexTK1].s, TK_Hely3DAnim[Face_Hely3DAnim[i].indexTK1].t);
glVertex3f(DispV_Hely3DAnim[0].X, DispV_Hely3DAnim[0].Y, DispV_Hely3DAnim[0].Z);

glTexCoord2f(TK_Hely3DAnim[Face_Hely3DAnim[i].indexTK2].s, TK_Hely3DAnim[Face_Hely3DAnim[i].indexTK2].t);
glVertex3f(DispV_Hely3DAnim[1].X, DispV_Hely3DAnim[1].Y, DispV_Hely3DAnim[1].Z);

glTexCoord2f(TK_Hely3DAnim[Face_Hely3DAnim[i].indexTK3].s, TK_Hely3DAnim[Face_Hely3DAnim[i].indexTK3].t);
glVertex3f(DispV_Hely3DAnim[2].X, DispV_Hely3DAnim[2].Y, DispV_Hely3DAnim[2].Z);
glEnd();
}

Update 28 Des 2015

Jika rekan-rekan sudah paham tentang membuat Hely 3D rekan-rekan bisa melanjutkan program ini dengan menambah beberapa objek tambahan seperti langit/sky dan ground/tanah agar program ini menjadi lebih menarik seperti gambar di bawah ini.




Update 15 Jan 2015

Ada artikel tambahan tentang hely 3D, yaitu membuat bayangan Hely 3D seperti video berikut ini.



Sampai disini dulu rekan-rekan, ogut sudah musti berangkat kerja nih, lain kali kita terusin obrolan tentang game 3D sederhana kita...ok......

Salam Hely 3D


Heriady
heriady.yoh@gmail.com




Artikel terkait
Membuat Terrain untuk Hely 3D

Program Animasi Game MoTer 3D dengan OpenGL

Model / Objek 3D dengan 3ds max

Konsep Face dan Metode 3 Daftar

Teori Animasi 3D dengan Vektor R3

Contoh Program Animasi 3D dengan OpenGL

Animasi dengan Vektor Translasi

Animasi dengan Vektor Translasi 2

Animasi 3D dengan Objek MD2

Matematika Vektor R3

Matematika Vektor R2