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
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.
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.
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).
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; }
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.
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.
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; }