Tampilkan postingan dengan label Animasi 3D. Tampilkan semua postingan
Tampilkan postingan dengan label Animasi 3D. Tampilkan semua postingan

Jumat, 15 Januari 2016

Membuat Bayangan Objek 3D OpenGL

Selamat Pagi everyone, postingan kali ini akan membahas cara sederhana untuk membuat bayangan 3D. Objek 3D yang akan ogut buat bayangannya adalah Objek helikopter atau Hely 3D yang telah ogut posting di artikel sebelumnya.


Pada tanggal 8 Jan 2015, saat ogut nongkrong dan makan sore di sebuah warung (RAZA) di sekitar jalan Cargo, munculah ide ini. Makan nasi sayur dengan tempe dan tahu lalu tiba-tiba ini datang, langsung ogut corat-coret dan jadilah seperti di bawah ini.


Corat-coret tersebut menghasilkan program seperti berilut ini.


Ada juga videonya, biar lebih keren



Untuk membuat programnya ogut ceritakan dahulu skenario atau teorinya...jangan baca coretan ogut di atas...pusing karena tulisan tangan ogut susah untuk dimengerti....lihat aja gambar di bawah ini


Pada gambar terlihat sebuah objek 3D dan bayangannya, Titik Cahaya yang menjadi sumber cahaya untuk membuat bayangan.

Vektor TL dan Vektor Bayangan ogut gunakan untuk mencari Titik Bayangan.


Dari aturan dasat trigonometri diketahui  nilai Cos α° dapat dicari dengan membagi panjang X dengan Panjang R.

Untuk mencari panjang Vektor Bayangan dapat digunakan aturan dasar trigonometri ini, sudut α° dapat dicari dengan memanfaatkan sudut vektor, jika panjang Vektor Bayangan diketahui maka Titik Bayangan akan dapat ditentukan dan bayangan 3D dapat dibuat.

Ada beberapa hal yang harus rekan-rekan perhatikan waktu membuat program bayangan Hely 3D. Pertama dekalrasikan variable dan class yang diperlukan

//bayangan
unsigned int TeksturHitam;
unsigned int TeksturKuning;
Vertex DispV_Bayangan3DAnim[3];
Vertex Titik_Cahaya;
Vector Vektor_TL; //vektor Tegak Lurus
Vector Vektor_Bayangan; //vektor Tegak Lurus
VectorClass VektorClass;

Kedua setting nilai awalnya.

////set nilai awal bayangan
Titik_Cahaya.X = -2.5f; Titik_Cahaya.Y = 6.5f; Titik_Cahaya.Z = 0.0f;
Vektor_TL.i = 0.0f; Vektor_TL.j = -(Titik_Cahaya.Y - 0.07f); Vektor_TL.k = 0.0f;

Dan waktu Displaynya.

//=========================================
//hitung vertex bayangan 0
//=========================================
Vektor_Bayangan = VektorClass.CreateVector(DispV_Hely3DAnim[0].X, DispV_Hely3DAnim[0].Y, DispV_Hely3DAnim[0].Z,
Titik_Cahaya.X, Titik_Cahaya.Y, Titik_Cahaya.Z);

CosDuaVektor = VektorClass.CosSudutVector(Vektor_TL, Vektor_Bayangan);
PanjangVektorBayangan = VektorClass.LVector(Vektor_TL) / CosDuaVektor;
Vektor_Bayangan = VektorClass.Normalisasi(Vektor_Bayangan);
Vektor_Bayangan = VektorClass.SkalaVector(Vektor_Bayangan, PanjangVektorBayangan);

//Vertex bayangan [0]
DispV_Bayangan3DAnim[0].X = Titik_Cahaya.X + Vektor_Bayangan.i;
DispV_Bayangan3DAnim[0].Y = Titik_Cahaya.Y + Vektor_Bayangan.j;
DispV_Bayangan3DAnim[0].Z = Titik_Cahaya.Z + Vektor_Bayangan.k;
//=========================================

Bravo vektor R3, sebab dengan bantuannya program bayangan 3D bisa dibuat, bagaimana rekan-rekan, sangat sederhana perhitungannya tetapi bermanfaat besar sekali dalam dunia grafik komputer.

Ogut lagi menyiapkan program bayangan 3D yang lebih expert, tunggu tanggal mainnya, berangkat dari ide yang sederhana juga maka akan muncul bayangan 3D, seperti program di artikel ini.

Salam Grafik 3D

Heriady
heriady.yoh@gmail.com




Artikel terkait
Jaring / Jala 3D Dengan OpenGL

Matematika Vektor R3

Program Animasi Game MoTer 3D dengan OpenGL

Jumat, 18 Desember 2015

Membuat Terrain untuk Hely 3D

Membuat terrain untuk melengkapi program animasi Hely 3D. Program dibuat dengan menggunakan Visual Studio 2013 Express dan OpenGL 3D.



Selamat Pagi rekan-rekan sekalian, jumpa lagi dengan ogut, setelah urusan pompa air di villa bule mulai teratasi  ogut langsung lanjut nge-blog lagi. Kali ini ogut akan menyatukan program-program yang telah ogut buat di artikel-artikel sebelumnya. Artikel yang telah ogut tulis beberapa bulan yang lalu (mulai mei 2015) ogut kumpulkan dan jadilah seperti ini.





Bagaimana keren bukan, pada gambar di atas rekan-rekan bisa melihat program yang ogut buat, objek Hely 3D sudah ogut lengkapi dengan objek tambahan langit/sky,  pohon kelapa dan tanah, semuanya jika disatukan akan membentuk yang namanya terrain atau gampangnya kita sebut aja daerah perang.

Cara untuk membuat objek-objek di atas sudah semuanya ogut bahas, rekan-rekan tinggal membaca di artikel-artikel terdahulu (klik beberapa link artikel terkait di bagian bawah artikel ini). Jika rekan-rekan telah menguasai cara membuat terrain seperti contoh ini maka rekan-rekan telah maju selangkah lagi, tinggal menunggu detik-detik game 3D rekan-rekan jadi.

Objek tanah/ground ogut buat dengan 3ds max, begitu pula pohon kelapa. Cara menampilkan ke layar monitor dengan menggunakan metode 3 daftar, semuanya sudah ogut bahas rekan-rekan tinggal membaca di artikel yang telah tersedia.



Untuk  sky/langit ogut menggunakan balok 3D  5 sisi, tanpa perlu menggunakan 3ds max.

 ////////////////////////////////////////////////////
//Sky langit
////////////////////////////////////////////////////
//Depan
glBindTexture(GL_TEXTURE_2D, Sky_Depan_Text);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-33.0f, -5.0f, -33.0f);

glTexCoord2f(1.0f, 0.0f);
glVertex3f(33.0f, -5.0f, -33.0f);

glTexCoord2f(1.0f, 1.0f);
glVertex3f(33.0f, 20.0f, -33.0f);

glTexCoord2f(0.0f, 1.0f);
glVertex3f(-33.0f, 20.0f, -33.0f);
glEnd();

//Belakang
glBindTexture(GL_TEXTURE_2D, Sky_Belakang_Text);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-33.0f, -5.0f, 33.0f);

glTexCoord2f(1.0f, 0.0f);
glVertex3f(33.0f, -5.0f, 33.0f);

glTexCoord2f(1.0f, 1.0f);
glVertex3f(33.0f, 20.0f, 33.0f);

glTexCoord2f(0.0f, 1.0f);
glVertex3f(-33.0f, 20.0f, 33.0f);
glEnd();

//Kiri
glBindTexture(GL_TEXTURE_2D, Sky_Kiri_Text);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-33.0f, -5.0f, 33.0f);

glTexCoord2f(1.0f, 0.0f);
glVertex3f(-33.0f, -5.0f, -33.0f);

glTexCoord2f(1.0f, 1.0f);
glVertex3f(-33.0f, 20.0f, -33.0f);

glTexCoord2f(0.0f, 1.0f);
glVertex3f(-33.0f, 20.0f, 33.0f);
glEnd();

//Kanan
glBindTexture(GL_TEXTURE_2D, Sky_Kanan_Text);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(33.0f, -5.0f, 33.0f);

glTexCoord2f(1.0f, 0.0f);
glVertex3f(33.0f, -5.0f, -33.0f);

glTexCoord2f(1.0f, 1.0f);
glVertex3f(33.0f, 20.0f, -33.0f);

glTexCoord2f(0.0f, 1.0f);
glVertex3f(33.0f, 20.0f, 33.0f);
glEnd();

//Atas
glBindTexture(GL_TEXTURE_2D, Sky_Atas_Text);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-33.0f, 20.0f, 33.0f);

glTexCoord2f(1.0f, 0.0f);
glVertex3f(33.0f, 20.0f, 33.0f);

glTexCoord2f(1.0f, 1.0f);
glVertex3f(33.0f, 20.0f, -33.0f);

glTexCoord2f(0.0f, 1.0f);
glVertex3f(-33.0f, 20.0f, -33.0f);
glEnd();
//==============================================

Update 16 Jan 2015

Rekan-rekan ogut juga punya program animasi 3D baru, yaitu membuat bayangan objek 3D seperti video berikut ini.



OK....sampai disini dulu rekan-rekan, ogut harus berangkat kerja lagi nih, lain kali kita terusin obrolannya.....OK


Salam Game 3D


Heriady
heriady.yoh@gmail.com




Artikel terkait
Program Animasi Game MoTer 3D dengan OpenGL

Membuat Animasi Hely 3D dengan OpenGL

Objek 3D low polygon dengan 3ds max

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


Jumat, 27 November 2015

Program Animasi Game MoTer 3D dengan OpenGL

Membuat objek Game  MoTer 3D yang bisa berubah bentuk menjadi mobil atau MoTer (animasi lebih dari satu) dengan menggunakan Visual Studio 2013 Express dan OpenGL.




Selamat Pagi, akhirnya setelah sekian lama tertunda ogut berhasil menulis tentang animasi untuk objek game 3D. Kali ini ogut akan membahas cara membuat objek game 3D yang bisa berubah bentuk atau lebih tepatnya bisa beranimasi lebih dari satu.




Seperti yang Anda lihat di atas MoTer bisa berubah bentuk menjadi mobil dan kembali berubah menjadi MoTer, lalu ada juga animasi baling-baling berputar, total ada 5 animasi.

Untuk mempelajari pembuatan objek ini ogut sarankan rekan-rekan membaca artikel yang ogut buat sebelumnya, tentang Hely 3D.


Pada Hely 3D animasi hanya ada satu yaitu baling-baling yang berputar, sedangkan MoTer 3D mempunyai 5 animasi. Cara pembuatan keduanya hampir sama hanya berbeda di jumlah animasi yang bisa ditampilkan di layar monitor. Ogut tidak akan membahas ulang yang sudah dibahas pada artikel Hely 3D, jadi rekan-rekan harus membacanya terlebih dahulu untuk bisa lanjut membaca artikel ini.



Objek MoTer 3D dibuat dengan menggunakan 3ds max lalu di konversi menjadi file text dengan bantuan script (artikel membuat objek 3D dengan 3ds max). Hasil konversi berupa fie text dengan nama MoTer3D.MESH3DANIMX, jika Anda buka file tersebut dengan editor Notepad isinya akan seperti berikut.


Isi file di atas menggunakan konsep 3 daftar, apa itu konsep 3 daftar sudah ogut jelaskan di artikel Hely 3D. Di dalam file terdapat total face, total TK, total vertex per frame, dan yang membuat berbeda dengan Hely 3D adalah total frame animasi dan total animasi. Total frame animasi dan total animasi adalah tambahan di objek 3D MoTer yang tidak ada di Hely 3D. Di bawah baris pertama terdapat daftar animasi (list of animasi) dan baris berikutnya adalah daftar face (list of face).

Pada daftar animasi (list of animasi) terdapat angka 1 (looping) dan angka 0 (non looping), maksudnya adalah sebagai flag/tanda jika animasi bersifat looping atau tidak looping. Animasi looping adalah animasi yang terus menerus berulang contohnya putaran baling-baling pada objek MoTer 3D. Sedangkan contoh animasi yang tidak looping adalah animasi perubahan bentuk dari mobil ke MoTer. Kenapa tidak looping sebab setelah mobil berubah menjadi MoTer dia tidak bisa berubah lagi jadi mobil  lalu jadi MoTer kembali.


Isi berikutnya dari file MoTer3D.MESH3DANIMX adalah daftar TK (list of TK) seperti yang Anda lihat di gambar.


Dan terakhir adalah daftar vertex (list of vertex).

Untuk membuat animasi 3D dengan vektor R3 teorinya sudah ogut tulis di artikel ini, silahkan Anda baca terlebih dahulu supaya tidak bingung.

Teori sudah sekarang saat koding, pertama deklarasikan variabel dan struct yang dibutuhkan.

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;

typedef struct
{
char AnimName[16];
int Looping_YN;
int FrameStart;
int FrameEnd;
}Animasi;


//===================
//variabel MoTer3D
//===================
int TotalF_MoTer3DAnim;
int TotalTK_MoTer3DAnim;
int TotalV_MoTer3DAnim;
int TotalFr_MoTer3DAnim;
int TotalAnim_MoTer3DAnim;

int CurrFr_MoTer3DAnim;
int NextFr_MoTer3DAnim;
float Skala_MoTer3DAnim = 0.0f;
int IndexAnimasi = 0;

Face *Face_MoTer3DAnim;
TK *TK_MoTer3DAnim;
Vertex *V_MoTer3DAnim;
Vertex DispV_MoTer3DAnim[3];
Animasi *Anim_MoTer3DAnim;

Lalu load objek animasi MoTer 3D dengan fungsi di bawah ini.

bool LoadMesh3DAnimX(char *FileName, float skala)
{
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_MoTer3DAnim);
fscanf_s(file, "%d", &TotalTK_MoTer3DAnim);
fscanf_s(file, "%d", &TotalV_MoTer3DAnim);
fscanf_s(file, "%d", &TotalFr_MoTer3DAnim);
fscanf_s(file, "%d", &TotalAnim_MoTer3DAnim);



//siapkan tempat untuk data mesh
Face_MoTer3DAnim = new Face[TotalF_MoTer3DAnim];
TK_MoTer3DAnim = new TK[TotalTK_MoTer3DAnim];
V_MoTer3DAnim = new Vertex[TotalV_MoTer3DAnim * TotalFr_MoTer3DAnim];
Anim_MoTer3DAnim = new Animasi[TotalAnim_MoTer3DAnim];

//load animasi
for (i = 0; i < TotalAnim_MoTer3DAnim; i++)
{
fscanf_s(file, "%s", &Anim_MoTer3DAnim[i].AnimName, 16);
fscanf_s(file, "%d", &Anim_MoTer3DAnim[i].Looping_YN);
fscanf_s(file, "%d", &Anim_MoTer3DAnim[i].FrameStart);
fscanf_s(file, "%d", &Anim_MoTer3DAnim[i].FrameEnd);
}


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

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

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

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

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

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

V_MoTer3DAnim[i].X = skala * V_MoTer3DAnim[i].X;
V_MoTer3DAnim[i].Y = skala * V_MoTer3DAnim[i].Y;
V_MoTer3DAnim[i].Z = skala * V_MoTer3DAnim[i].Z;

RotasiX(-90.0, V_MoTer3DAnim[i].X, V_MoTer3DAnim[i].Y, V_MoTer3DAnim[i].Z);
}

fclose(file);

return true;
}

Terakhir tampilkan di layar monitor.

//...........................
//display object  di sini
//...........................
Sudut_Putar = Sudut_Putar + 0.1f;
if (Sudut_Putar >= 360.0f)
Sudut_Putar = 0.0f;

glTranslatef(0.0f, 0.0f, -8.0f);
glPushMatrix();
glRotatef(Sudut_Putar, 1.0f, 1.0f, 0.0f);

glBindTexture(GL_TEXTURE_2D, Tekstur1);

if (GetKeyState('0') & 0x80)
{
Baling2Sound.Stop();
BerubahSound.Stop();

IndexAnimasi = 0;
CurrFr_MoTer3DAnim = Anim_MoTer3DAnim[IndexAnimasi].FrameStart;
NextFr_MoTer3DAnim = CurrFr_MoTer3DAnim + 1;
}

if (GetKeyState('1') & 0x80)
{
Baling2Sound.Stop();
BerubahSound.Play(false);

IndexAnimasi = 1;
CurrFr_MoTer3DAnim = Anim_MoTer3DAnim[IndexAnimasi].FrameStart;
NextFr_MoTer3DAnim = CurrFr_MoTer3DAnim + 1;
}

if (GetKeyState('2') & 0x80)
{
Baling2Sound.Stop();
BerubahSound.Play(false);

IndexAnimasi = 2;
CurrFr_MoTer3DAnim = Anim_MoTer3DAnim[IndexAnimasi].FrameStart;
NextFr_MoTer3DAnim = CurrFr_MoTer3DAnim + 1;
}

if (GetKeyState('3') & 0x80)
{
Baling2Sound.Stop();
BerubahSound.Stop();

IndexAnimasi = 3;
CurrFr_MoTer3DAnim = Anim_MoTer3DAnim[IndexAnimasi].FrameStart;
NextFr_MoTer3DAnim = CurrFr_MoTer3DAnim + 1;
}

if (GetKeyState('4') & 0x80)
{
Baling2Sound.Play(true);
BerubahSound.Stop();

IndexAnimasi = 4;
CurrFr_MoTer3DAnim = Anim_MoTer3DAnim[IndexAnimasi].FrameStart;
NextFr_MoTer3DAnim = CurrFr_MoTer3DAnim + 1;
}

Skala_MoTer3DAnim += 0.025f;
if (Skala_MoTer3DAnim > 1.0f)
{
Skala_MoTer3DAnim = 0.0f;
CurrFr_MoTer3DAnim++;
NextFr_MoTer3DAnim++;

if ((NextFr_MoTer3DAnim > Anim_MoTer3DAnim[IndexAnimasi].FrameEnd) &&
(Anim_MoTer3DAnim[IndexAnimasi].Looping_YN == 1))
{
NextFr_MoTer3DAnim = Anim_MoTer3DAnim[IndexAnimasi].FrameStart;
}

if ((CurrFr_MoTer3DAnim > Anim_MoTer3DAnim[IndexAnimasi].FrameEnd) &&
(Anim_MoTer3DAnim[IndexAnimasi].Looping_YN == 1))
{
CurrFr_MoTer3DAnim = Anim_MoTer3DAnim[IndexAnimasi].FrameStart;
}

if ((NextFr_MoTer3DAnim > Anim_MoTer3DAnim[IndexAnimasi].FrameEnd) &&
(Anim_MoTer3DAnim[IndexAnimasi].Looping_YN == 0))
{
NextFr_MoTer3DAnim = Anim_MoTer3DAnim[IndexAnimasi].FrameEnd;
}

if ((CurrFr_MoTer3DAnim > Anim_MoTer3DAnim[IndexAnimasi].FrameEnd) &&
(Anim_MoTer3DAnim[IndexAnimasi].Looping_YN == 0))
{
CurrFr_MoTer3DAnim = Anim_MoTer3DAnim[IndexAnimasi].FrameEnd;
}
} //if (Skala_MoTer3DAnim > 1.0f) 


for (i = 0; i < TotalF_MoTer3DAnim; i++)
{
j = Face_MoTer3DAnim[i].indexV1 + (TotalV_MoTer3DAnim * CurrFr_MoTer3DAnim);
k = Face_MoTer3DAnim[i].indexV1 + (TotalV_MoTer3DAnim * NextFr_MoTer3DAnim);
DispV_MoTer3DAnim[0].X = V_MoTer3DAnim[j].X + (V_MoTer3DAnim[k].X - V_MoTer3DAnim[j].X) * Skala_MoTer3DAnim;
DispV_MoTer3DAnim[0].Y = V_MoTer3DAnim[j].Y + (V_MoTer3DAnim[k].Y - V_MoTer3DAnim[j].Y) * Skala_MoTer3DAnim;
DispV_MoTer3DAnim[0].Z = V_MoTer3DAnim[j].Z + (V_MoTer3DAnim[k].Z - V_MoTer3DAnim[j].Z) * Skala_MoTer3DAnim;

j = Face_MoTer3DAnim[i].indexV2 + (TotalV_MoTer3DAnim * CurrFr_MoTer3DAnim);
k = Face_MoTer3DAnim[i].indexV2 + (TotalV_MoTer3DAnim * NextFr_MoTer3DAnim);
DispV_MoTer3DAnim[1].X = V_MoTer3DAnim[j].X + (V_MoTer3DAnim[k].X - V_MoTer3DAnim[j].X) * Skala_MoTer3DAnim;
DispV_MoTer3DAnim[1].Y = V_MoTer3DAnim[j].Y + (V_MoTer3DAnim[k].Y - V_MoTer3DAnim[j].Y) * Skala_MoTer3DAnim;
DispV_MoTer3DAnim[1].Z = V_MoTer3DAnim[j].Z + (V_MoTer3DAnim[k].Z - V_MoTer3DAnim[j].Z) * Skala_MoTer3DAnim;

j = Face_MoTer3DAnim[i].indexV3 + (TotalV_MoTer3DAnim * CurrFr_MoTer3DAnim);
k = Face_MoTer3DAnim[i].indexV3 + (TotalV_MoTer3DAnim * NextFr_MoTer3DAnim);
DispV_MoTer3DAnim[2].X = V_MoTer3DAnim[j].X + (V_MoTer3DAnim[k].X - V_MoTer3DAnim[j].X) * Skala_MoTer3DAnim;
DispV_MoTer3DAnim[2].Y = V_MoTer3DAnim[j].Y + (V_MoTer3DAnim[k].Y - V_MoTer3DAnim[j].Y) * Skala_MoTer3DAnim;
DispV_MoTer3DAnim[2].Z = V_MoTer3DAnim[j].Z + (V_MoTer3DAnim[k].Z - V_MoTer3DAnim[j].Z) * Skala_MoTer3DAnim;

glBegin(GL_TRIANGLES);
//glBegin(GL_LINE_LOOP);
glTexCoord2f(TK_MoTer3DAnim[Face_MoTer3DAnim[i].indexTK1].s, TK_MoTer3DAnim[Face_MoTer3DAnim[i].indexTK1].t);
glVertex3f(DispV_MoTer3DAnim[0].X, DispV_MoTer3DAnim[0].Y, DispV_MoTer3DAnim[0].Z);

glTexCoord2f(TK_MoTer3DAnim[Face_MoTer3DAnim[i].indexTK2].s, TK_MoTer3DAnim[Face_MoTer3DAnim[i].indexTK2].t);
glVertex3f(DispV_MoTer3DAnim[1].X, DispV_MoTer3DAnim[1].Y, DispV_MoTer3DAnim[1].Z);

glTexCoord2f(TK_MoTer3DAnim[Face_MoTer3DAnim[i].indexTK3].s, TK_MoTer3DAnim[Face_MoTer3DAnim[i].indexTK3].t);
glVertex3f(DispV_MoTer3DAnim[2].X, DispV_MoTer3DAnim[2].Y, DispV_MoTer3DAnim[2].Z);
glEnd();
}
glPopMatrix();

display_text(My_ListBase1, -2.5, 1.6, "Tekan key '0', '1', '2', '3' atau '4'");
display_text(My_ListBase1, -2.5, 1.5, "Animasi    :");
display_text(My_ListBase1, -1.75, 1.5, Anim_MoTer3DAnim[IndexAnimasi].AnimName);

display_text(My_ListBase1, -2.5, 1.4, "Looping    :");

if (Anim_MoTer3DAnim[IndexAnimasi].Looping_YN == 1)
display_text(My_ListBase1, -1.75, 1.4, "Yes");
else
display_text(My_ListBase1, -1.75, 1.4, "No");

display_text(My_ListBase1, -2.5, 1.3, "FrameStart :");
_itoa_s(Anim_MoTer3DAnim[IndexAnimasi].FrameStart, buffer, 10);
display_text(My_ListBase1, -1.75, 1.3, buffer);

display_text(My_ListBase1, -2.5, 1.2, "FrameEnd   :");
_itoa_s(Anim_MoTer3DAnim[IndexAnimasi].FrameEnd, buffer, 10);
display_text(My_ListBase1, -1.75, 1.2, buffer);

Untuk memainkan sound effect Anda dapat membaca link artikel ini jika kurang jelas.

Ok rekan-rekan sekalian, tuntas sudah artikel kali ini, ngak nyangka ya selesai juga. Di artikel berikutnya ogut masih terus akan membahas tentang animasi 3D yang sangat berguna untuk membuat game 3D, jangan bosan ya, dan jangan lupa rekan-rekan harus perdalam ilmu matematika terutama vektor R3.

Salam MoTer 3D


Heriady
heriady.yoh@gmail.com




Artikel terkait
Membuat Terrain untuk Hely 3D

Membuat Animasi Hely 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


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