APLIKASI GRAFIKA KOMPUTER UNTUK TRANSFORMASI GEOMETRI 3 DIMENSI Tugas Akhir untuk memenuhi sebagian persyaratan mencapai derajat Sarjana Teknik
oleh
Alfa Ryano Yohannis L2F002548
JURUSAN TEKNIK ELEKTRO FAKULTAS TEKNIK UNIVERSITAS DIPONEGORO SEMARANG 2006
HALAMAN PENGESAHAN Laporan Tugas Akhir dengan judul “APLIKASI GRAFIKA KOMPUTER UNTUK TRANSFORMASI GEOMETRI 3 DIMENSI” yang disusun oleh Nama : Alfa Ryano Yohannis NIM
: L2F002548
Telah disetujui dan disahkan untuk dijadikan laporan Tugas Akhir sebagai salah satu syarat menyelesaikan program Strata Satu Jurusan Teknik Elektro Fakultas Teknik Universitas Diponegoro Semarang. Menyetujui dan mengesahkan Pembimbing I
Pembimbing II
Agung B.P., S.T., M.I.T.
Eko Handoyo, S.T., M.T.
NIP. 132 137 932
NIP. 132 309 142
Tanggal
September 2006
Tanggal Mengetahui a.n. Dekan
Ketua Jurusan Teknik Elektro Fakultas Teknik Universitas Diponengoro
Ir. Sudjadi, M.T. NIP. 131 558 567 Tanggal
September 2006
September 2006
Tugas Akhir APLIKASI GRAFIKA KOMPUTER UNTUK TRANSFORMASI GEOMETRI 3 DIMENSI yang dipersiapkan dan disusun oleh Alfa Ryano Yohannis L2F002548 Telah dipertahankan di depan para Dosen Penguji Pada tanggal September 2006 Dan dinyatakan telah memenuhi syarat Susunan Dosen Penguji
Tanda tangan Ketua
: Aghus Sofwan, S.T., M.T. NIP. 132 163 757
Tanggal:
September 2006
Tanggal:
September 2006
Tanggal:
September 2006
Sekretaris : Maman Somantri, S.T., M.T. NIP. 132 231 133 Anggota
: Imam Santoso, S.T., M.T. NIP. 132 162 546
KATA PENGANTAR
Puji syukur kepada Allah Bapa yang bertahta di dalam Kerajaan Sorga yang telah memberikan karunia-Nya sehingga penyusun dapat menyelesaikan Tugas Akhir ini. Terpujilah nama-Nya kekal selama-lamanya. Tugas Akhir ini dibuat sebagai syarat untuk memenuhi gelar Sarjana Teknik di Jurusan Teknik Elektro Fakutas Teknik Universitas Diponegoro. Penyusun mengharapkan Tugas Akhir ini dapat bermanfaat bagi pengembangan ilmu pengetahuan di bidang grafika komputer khususnya di Teknik Elektro Universitas Diponegoro.. Penyusun mengucapkan terima kasih kepada pihak-pihak yang telah membantu dalam penyelesaian Tugas Akhir, yaitu: 1.
Bapak Agung B.P. sebagai Dosen Pembimbing I. Terima kasih karena beliau sudah membimbing, mengarahkan, mengkoreksi, dan memberi masukan dalam penyelesaian Tugas Akhir ini,
2.
Bapak Eko Handoyo sebagai Dosen Pembimbing II. Terima kasih karena beliau telah menolong dalam analisis dan perancangan Tugas Akhir serta mengkoreksi tata penulisan laporan,
3.
Orang tua penyusun yang terus mengingatkan dan mendorong agar segera menyelesaian Tugas Akhir, dan
4.
Pihak-pihak yang tidak bisa penyusun sebutkan satu per satu. Terima kasih buat setiap bantuan kalian. Tugas Akhir ini masih memiliki kekurangan. Oleh karena itu, penyusun
meminta maaf. Saran dan kritik Anda sangat diperlukan bagi menyempurnakan Tugas Akhir ini. Terima kasih. Semarang, 19 September 2006
Penulis
i
DAFTAR ISI
KATA PENGANTAR ............................................................................................ i DAFTAR ISI .......................................................................................................... ii DAFTAR GAMBAR ..............................................................................................v DAFTAR TABEL ............................................................................................... vii ABSTRAK .......................................................................................................... viii
BAB I PENDAHULUAN .......................................................................................1 1.1. Latar Belakang .............................................................................................1 1.2. Identifikasi Masalah .....................................................................................2 1.3. Batasan Masalah ...........................................................................................3 1.4. Tujuan Penelitian..........................................................................................3 1.5. Kegunaan Hasil Penelitian ...........................................................................3 1.6. Sistematika Penulisan ...................................................................................4
BAB II TRANSFORMSI GEOMETRI PADA RUANG 3 DIMENSI .................................................................................5 2.1. Transformasi 3 Dimensi ...............................................................................5 2.1.1. Translasi ...........................................................................................6 2.1.2. Penskalaan ........................................................................................7 2.1.3. Rotasi ................................................................................................7 2.1.4. Shearing ............................................................................................8 2.1.5. Transformasi Komposit ....................................................................9 2.1.6. Rotasi menggunakan sumbu yang tidak melewati titik origin .........9 2.1.7. Penskalaan Menggunakan Sembarang Titik Pusat .........................10 2.2. Transformasi 3 Dimensi pada OpenGL .....................................................10 2.3. Penggunaan OpenGL pada Delphi untuk Transformasi 3D.......................12 2.4. Representasi Objek 3 Dimensi ...................................................................14 2.5. Interaksi Pengguna dengan Aplikasi ..........................................................15
ii
iii
BAB III PERANCANGAN APLIKASI GRAFIKA KOMPUTER UNTUK TRANSFORMASI OBJEK 3D ...........................................................17 3.1. Use Case ....................................................................................................17 3.2. Kartu Index CRC ........................................................................................18 3.3. Diagram Kelas ............................................................................................21 3.4. Model Hubungan Objek (Object Relationship) .........................................21 3.5. Model Tingkah Laku Objek (Object Behaviour) .......................................23 3.6. Perancangan Antarmuka ............................................................................24 BAB IV IMPLEMENTASI DAN PENGUJIAN APLIKASI GRAFIKA KOMPUTER UNTUK TRANSFORMASI OBJEK 3D ...............25 4.1. Implementasi Aplikasi ...............................................................................25 4.1.1. Implementasi Tampilan ..................................................................25 4.1.2. Implementasi Objek Geometri .......................................................28 a. Piramida .....................................................................................28 b. Kubus .........................................................................................29 c. Silinder .......................................................................................30 d. Daftar Geometri .........................................................................32 4.1.3. Implementasi Vektor ......................................................................33 4.1.4. Implementasi Transformasi 3D ......................................................35 a. Perkalian Matriks .......................................................................35 b. Matriks Identitas ........................................................................35 c. Translasi .....................................................................................36 d. Penskalaan .................................................................................36 e. Rotasi .........................................................................................37 f. Shearing .....................................................................................38 g. Matriks Transform .....................................................................39 4.1.5. Implementasi Transformasi Menggunakan Mouse ........................39 4.1.6. Implementasi Benda Rumit ............................................................41 4.2. Pengujian Validasi Fungsi Transformasi Aplikasi .....................................43 4.2.1. Pengujian Transformasi Rotasi.......................................................44 a. Contoh perhitungan ...................................................................45 b. Perbandingan antara hasil perhitungan dan hasil aplikasi .........45 4.2.2. Pengujian Transformasi Penskalaan ...............................................45
iv
a. Contoh perhitungan ...................................................................46 b. Perbandingan antara hasil perhitungan dan hasil aplikasi .........47 4.2.3. Pengujian Transformasi Rotasi.......................................................47 a. Contoh perhitungan ...................................................................48 b. Perbandingan antara hasil perhitungan dan hasil aplikasi .........52 4.2.4. Pengujian Transformasi Shearing ..................................................52 a. Contoh perhitungan ...................................................................53 b. Perbandingan antara hasil perhitungan dan hasil aplikasi .........53 4.3. Pengujian Framerate..................................................................................54 5.3.1. Pengujian Framerate Rotasi ............................................................56 5.3.2. Pengujian Framerate Translasi .......................................................57 5.3.3. Pengujian Framerate Penskalaan ....................................................58 5.3.4. Pengujian Framerate Rotasi ............................................................59 BAB V KESIMPULAN DAN SARAN ...............................................................61 5.1. Keimpulan ..................................................................................................61 5.2. Saran ...........................................................................................................62 DAFTAR PUSTAKA ..........................................................................................63 LAMPIRAN A KODE PROGRAM ...................................................................65 PtugasAkhir.dpr .....................................................................................................65 unitUtama.pas.........................................................................................................65 Vektor.pas ..............................................................................................................84 unitPenskalaan.pas .................................................................................................85 unitRotasi.pas .........................................................................................................87 unitShearing.pas .....................................................................................................88 unitTranslasi.pas.....................................................................................................90 unitAbout.pas .........................................................................................................91 Geometri.pas ..........................................................................................................91 Transformasi.pas ..................................................................................................108 LAMPIRAN B WAVEFRONT OBJ FILE FORMAT SUMMARY ............112 LAMPIRAN C PERINTAH OPENGL PADA APLIKASI GRAFIKA KOMPUTER UNTUK TRANSFORMASI 3D ...........................117 LAMPIRAN D MAKALAH SEMINAR..........................................................120
DAFTAR GAMBAR
BAB I PENDAHULUAN Gambar 1.1 Aplikasi komputer grafis: Blender .......................................................1 Gambar 1.2 3DS Max 8: Aplikasi Penampil Objek 3D ...........................................2 BAB II TRANSFORMSI GEOMETRI Gambar 2.1 Rotasi menggunan sumbu yang tidak melewati titik origin .................9 Gambar 2.2 Objek geometri kubus ........................................................................14 BAB III ANALISIS DAN PENCANGAN APLIKASI Gambar 3.1 Diagram use case aplikasi grafika komputer untuk transformasi dimensi ....................................................................................18 Gambar 3.2 Diagram kelas aplikasi grafika komputer untuk transformasi 3 dimensi ................................................................................21 Gambar 3.3 Diagram runtun aplikasi grafika komputer untuk transformasi 3 dimensi ................................................................................22 Gambar 3.4 Diagram statechart aplikasi grafika komputer untuk transformasi 3 dimensi ................................................................................23 Gambar 3.5 Desain antarmuka aplikasi grafika komputer untuk transformasi 3 dimensi ................................................................................24 BAB IV IMPLEMENTASI DAN PENGUJIAN APLIKASI Gambar 4.1 Tampilan aplikasi grafika komputer untuk transformasi 3 dimensi ..25 Gambar 4.2 Toolbar dan menu aplikasi .................................................................26 Gambar 4.3 Tampilan tab-tab untuk objek kubus, piramid, silinder, meja, dan kursi .........................................................................................26 Gambar 4.4 Status bar ............................................................................................27 Gambar 4.5 Tampilan popup menu hasil klik kanan .............................................27 Gambar 4.6 Form untuk transformasi translasi, penskalaan, rotasi, dan shearing .27 Gambar 4.7 Objek geometri piramida....................................................................28 Gambar 4.8 Objek geometri kubus ........................................................................29
v
vi
Gambar 4.9 Objek geometri silinder ......................................................................30 Gambar 4.10 Objek mobil dan bola menggunakan obj loader (a) posisi awal (b) posisi setelah rotasi ...........................................................................................42 Gambar 4.11 Posisi awal piramida pada layar aplikasi..........................................43 Gambar 4.12 Form untuk memasukkan nilai translasi ..........................................44 Gambar 4.13 Piramida: (a) sebelum translasi (b) sesudah translasi.......................44 Gambar 4.14 Form untuk memasukkan nilai penskalaan ......................................46 Gambar 4.15 Piramida: (a) sebelum penskalaan (b) sesudah penskalaan ..............46 Gambar 4.16 Form untuk memasukkan nilai rotasi ...............................................47 Gambar 4.17 Piramida: (a) sebelum rotasi (b) sesudah rotasi ...............................48 Gambar 4.18 Form untuk memasukkan nilai shearing ..........................................52 Gambar 4.19 Piramida: (a) sebelum shearing (b) sesudah shearing ......................53 Gambar 2.20 Pengujian framerate untuk penskalaan (a) aplikasi yang menggunakan fungsi transformasi bawaan sendiri (b) aplikasi menggunakan fungsi transformasi bawaan OpenGL. .........................56
DAFTAR TABEL
BAB II TRANSFORMASI GEOMETRI PADA RUANG 3D Tabel 2.1 Verteks penyusun kubus ........................................................................15 BAB III ANALISIS DAN PENCANGAN APLIKASI Tabel 3.1 Kartu indeks CRC kelas objek geometri ................................................19 Tabel 3.2 Kartu indeks CRC kelas kubus...............................................................19 Tabel 3.3 Kartu indeks CRC kelas piramid ............................................................19 Tabel 3.4 Kartu indeks CRC kelas silinder ............................................................19 Tabel 3.5 Kartu indeks CRC kelas meja ................................................................20 Tabel 3.6 Kartu index CRC kelas kursi ..................................................................20 Tabel 3.7 Kartu indeks CRC kelas Transformasi ...................................................20 BAB IV IMPLEMENTASI DAN PENGUJIAN APLIKASI Tabel 4.1 Koordinat awal titik-titik piramida ........................................................44 Tabel 4.2 Perbandingan antara hasil perhitungan dan hasil aplikasi untuk translasi ................................................................................45 Tabel 4.3 Perbandingan antara hasil perhitungan dan hasil aplikasi untuk pensklaan ................................................................................47 Tabel 4.4 Perbandingan antara hasil perhitungan dan hasil aplikasi untuk rotasi .......................................................................................52 Tabel 4.5 Perbandingan antara hasil perhitungan dan hasil aplikasi untuk shearing................................................................................54 Tabel 4.6 Perbandingan framerate transformasi aplikasi dan OpenGL untuk transformasi rotasi ........................................................................................57 Tabel 4.7 Perbandingan framerate transformasi aplikasi dan OpenGL untuk transformasi translasi ...................................................................................57 Tabel 4.8 Perbandingan framerate transformasi aplikasi dan OpenGL untuk transformasi penskalaan ...............................................................................58 Tabel 4.9 Perbandingan framerate ransformasi aplikasi dan OpenGL. .................59
vii
ABSTRAK Perkembangan teknologi di bidang grafika komputer begitu pesat. Ini terbukti dengan banyaknya aplikasi yang menggunakan grafika komputer antara lain video game, CAD, dan simulator. Grafika komputer sendiri tidak lepas dari transformasi geometri. Dengan transformasi geometri, suatu objek geometri dapat dipindahkan dan diubah bentuknya. Masalah yang timbul, yaitu bagaimana mengimplementasikan transformasi geometri tersebut ke dalam suatu aplikasi. Transformasi geometri yang dapat dilakukan oleh aplikasi berupa translasi, rotasi, penskalaan, dan shearing. Selain itu, aplikasi tersebut dapat digunakan dengan mudah oleh pengguna untuk menampilkan objek 3 dimensi dan mentransformasinya. Agar menghasilkan suatu aplikasi yang dapat mengimplementasikan transformasi geometri, aplikasi dibuat dengan menggunakan bahasa pemrograman Delphi dan API OpenGL. OpenGL digunakan untuk menampilkan objek 3 dimensi dan Delphi digunakan untuk membuat antarmuka pengguna, struktur data, dan fungsi-fungsi transformasi. Perancangan dilakukan dengan menggunakan pendekatan berorientasi objek. Sebagai parameter aplikasi dapat berjalan baik, aplikasi dapat mentransformasi objek 3 dimensi melalui antarmuka pengguna yang dibuat dan hasil transformasinya sesuai dengan persamaan transformasi geometri. Sebagai implementasi, aplikasi dibuat dalam bentuk aplikasi studio yang dapat menerapkan transformasi 3 dimensi pada objek geometri. Pengujian dilakukan dengan membandingkan hasil transformasi aplikasi dan hasil transformasi melalui perhitungan untuk melihat apakah aplikasi dapat mentransformasi dengan tepat. Hasilnya, koordinat-koordinat hasil transformasi aplikasi sama dengan hasil perhitungan. Pengujian juga dilakukan dengan membandingkan framerate antara fungsi transformasi aplikasi dan fungsi transformasi bawaan OpenGL. Hasilnya, fungsi transformasi bawaan OpenGL memiliki framerate lebih tinggi dibandingkan fungsi aplikasi. Kata kunci: transformasi, rotasi, penskalaan, translasi, shearing, OpenGL
viii
ABSTRACT Computer graphics technology grows rapidly. It can be seen by many application that use computer graphics such as video game, CAD, and simulator. Computer graphics itselves are not free from gometric transformation. By goemetric transformation, an geometric object can be moved and it’s shape can be changed. The problem that appear is how to implement geometric transformation into an application. Geometric transformations that can be done by the application are translation, rotation, scaling, and shearing. Beside that, the application can be used easily by user to show 3 dimension objects and transform them. In order to produce an application that can implement geometric transformation, the application is made by using Delphi programming language OpenGL API. OpenGL is used to show 3 dimension object and Delphi is used to make user interface, data stucture, and functions of tranformation. Design is performed by using object oriented approach. As parameters if the application run well, the application can transform 3 dimension object by using it’s user interface and the it’s transformation result equal to the geometric transformation equation. As implementation, application is made in a studio form that can do 3 dimension transfomation on geometric objects. The testing is performed by comparing application transformation results with transformation results from calculation to show if the application can transform correctly. The results, coordinates from the application transformation results are equal with the results from calculation. The testing is also performed by comparing framerate between application transformation functions and OpenGL transformation functions. The results, OpenGL transformation functions has higher framerate than the application functions have. Keywords: transformation, translation, rotation, scaling, shearing, and OpenGL
ix
BAB I PENDAHULUAN
1.1
Latar Belakang Masalah Grafika komputer–salah satu cabang ilmu komputer–berkembang cukup
pesat. Ini terbukti dengan banyaknya bidang yang menerapkan grafika komputer seperti video game, CAD (Computer Aided Design), animasi, simulasi, dan lainlain. Gambar 1.1 memperlihatkan aplikasi komputer grafis bernama Blender[17] yang biasa digunakan untuk pemodelan dan animasi.
Gambar 1.1 Aplikasi komputer grafis: Blender.
Grafika komputer sendiri terbagi beberapa bagian, yaitu transformasi (transformation), pewarnaan (colouring), shading, dan ray tracing. Transformasi memiliki bagian yang penting pada grafika komputer. Dengan transformasi, suatu objek dapat dipindahkan dari satu tempat ke tempat yang lain, ukurannya dapat diperbesar atau diperkecil, objek dapat mengalami shearing, atau objek dapat diputar dengan besar sudut dan arah tertentu. Transformasi juga memiliki peran penting dalam membentuk animasi, misalnya animasi suatu objek begerak dari titik A ke titik B. Objek tersebut mengalami transformasi translasi dari titik A ke titik B dalam selang waktu tertentu.
1
2
Tugas akhir ini mencoba mengimplementasikan transformasi 3 dimensi dalam bentuk suatu aplikasi studio. Aplikasi dapat membuat suatu objek yang kemudian dapat ditransformasikan sesuai dengan transformasi yang dimiliki oleh aplikasi tersebut. Transformasi yang dapat dilakukan berupa translasi, penskalaan, rotasi, dan shearing. Analisis dan perancangan aplikasi menggunakan pendekatan berorientasi objek. Aplikasi dibuat dengan menggunakan bahasa pemrograman Delphi dan OpenGL API (Application Programming Interface).
Gambar 1.2 3DS Max 8: Aplikasi Penampil Objek 3 Dimensi.
Tugas Akhir ini diharapkan dapat menghasilkan suatu aplikasi studio yang dapat melakukan transformasi 3 dimensi pada objek yang dibuat. Aplikasi dapat melakukan transformasi translasi, penskalaan, rotasi, dan shearing seperti yang terdapat pada aplikasi-aplikasi pemodelan 3 dimensi, antara lain 3DS Max[16] (gambar 1.2) atau Blender (gambar 1.1). Aplikasi juga diharapkan memiliki antarmuka yang mudah digunakan (user friendly) sehingga mempermudah melakukan transformasi 3 dimensi pada objek. 1.2
Identifikasi Masalah Dalam mengimplementasikan aplikasi grafika komputer untuk transformasi
3 dimensi dapat diidentifikasi 3 masalah utama, yaitu:
3
1. Bagaimana merepresentasikan objek 3 dimensi sehingga dapat ditampilkan pada layar. 2. Melakukan transformasi pada objek 3 dimensi pada aplikasi tersebut. Tansformasi meliputi translasi, penskalaan, shearing, dan rotasi. 3. Antarmuka pengguna dengan program sehingga pengguna dapat melakukan transformasi pada objek sesuai yang dikehendaki. 1.3
Batasan Masalah
1. Tugas Akhir ini membahas mengenai implementasi transformasi 3 dimensi dalam bentuk suatu aplikasi studio penampil objek 3 dimensi. 2. Implementasi transformasi 3 dimensi menggunakan bahasa pemrograman Delphi dan API OpenGL. 3. Analisis dan perancangan aplikasi menggunakan pendekatan berorientasi objek. 1.4
Tujuan Penelitian Tujuan penelitian adalah implementasi fungsi-fungsi transformasi 3 dimensi
dalam bentuk suatu aplikasi studio. 1.5
Kegunaan Hasil Penelitian Kegunaan dari Tugas Akhir Implementasi Transformasi 3 Dimensi
Komputer Grafis Pada Aplikasi Penampil Objek 3 Dimensi, yaitu: 1. Mengetahui bagaimana mengimplementasikan transformasi 3 dimensi pada aplikasi 3 dimensi menggunakan OpenGL dan Delphi dengan pendekatan berorientasi objek. 2. Menghasilkan suatu aplikasi yang dapat melakukan transformasi 3 dimensi. Aplikasi ini dapat dikembangkan lebih untuk fungsi-fungsi yang lebih luas yang berkaitan dengan Grafika Komputer, seperti pewarnaan, texture mapping, rendering, dan animasi. 1.6
Sistematika Penulisan Laporan Laporan Tugas Akhir yang berjudul Aplikasi Grafika Komputer untuk
Transformasi Geometri 3 Dimensi tersusun dari lima bab, yaitu Bab I Pendahuluan, Bab II Transformasi Geometri pada Ruang 3 Dimensi, Bab III
4
Perancangan Aplikasi Grafika Komputer untuk Transformasi Geometri 3 Dimensi, Bab IV Implementasi dan Pengujian Aplikasi Grafika Komputer untuk Transformasi Geometri 3 Dimensi, dan Bab V Kesimpulan dan Saran. Berikut penjelasan gambaran singkat bab-bab tersebut: Bab I Pendahuluan. Bab ini berisi latar belakang yang menjadi alasan mengapa penulis mengambil topik tugas akhir di bidang grafika komputer, identifikasi masalah yang diperkirakan ada selama pembuatan aplikasi, batasan masalah tugas akhir, tujuan penelitian, dan kegunaan hasil penelitian. Bab II Transformasi Geometri pada Ruang 3 Dimensi. Bab II memuat teoriteori tentang transformasi geometri pada ruang 3 dimensi, bagaimana melakukan transformasi tersebut pada OpenGL, bagaimana menghubungkan OpenGL dengan bahasa pemrograman Delphi, dan landasan teori bagaimana pengguna dapat mentransformasi objek 3 dimensi dengan menggunakan antarmuka yang disediakan aplikasi. Bab III Perancangan Aplikasi Grafika Komputer untuk Transformasi Geometri 3 Dimensi. Bab III berisi perancangan yang dilakukan sebelum membuat aplikasi. Perancangan dilakukan dengan menggunakan pendekatan berorientasi objek. Langkah-langkah yang dilakukan, yaitu membuat use case, kartu indeks CRC, diageam kelas, model hubungan objek, model tingkah laku objek, dan perancangan antarmuka. Bab IV Implementasi dan Pengujian Aplikasi Grafika Komputer untuk Transformasi Geometri 3 Dimensi. Pada bab ini, hasil penelitian dipaparkan dalam bentuk penjelasan implementasi aplikasi yang dibuat. Pada bagian ini pula, pengujian aplikasi dilakukan dengan menguji validasi hasil transformasi aplikasi dengan hasil transformasi melalui perhitungan. Pengujian juga dilakukan dengan membandingkan framerate transformasi aplikasi dan framerate transformasi bawaan OpenGL. Bab V Kesimpulan dan Saran. Bab V, bab yang terakhir, berisi kesimpulankesimpulan penelitian dan saran-saran untuk bagi pengembangan penelitian selanjutnya.
BAB II TRANSFORMASI GEOMETRI PADA RUANG TIGA DIMENSI
Untuk membangun suatu aplikasi studio yang mendukung fungsi transformasi 3 dimensi setidaknya dibutuhan 5 bagian penting. Bagian-bagian tersebut, yaitu pemahaman teori transformasi 3 dimensi, transformasi 3 dimensi menggunakan OpenGL, penggunaan OpenGL API pada bahasa pemrograman Delphi, representasi objek 3 dimensi, dan interaksi pengguna dengan aplikasi. Pada subbab-subbab selanjutnya akan dijelaskan mengenai bagian-bagian tersebut. 2.1
Transformasi Geometri 3 Dimensi Teori transformasi geometri 3 dimensi memegang peranan penting karena
bagian ini merupakan ilmu dasar yang akan diimplentasikan pada program aplikasi. Sebelum melangkah lebih jauh, sangat penting untuk mengetahui arti dari transformasi geometri. Menurut Hearn-Baker, transformasi geometri adalah operasi yang diberikan pada gambaran geometri dari suatu objek untuk mengubah posisinya, orientasinya, atau ukurannya[1]. Jadi setiap operasi yang dapat mengubah posisi, orientasi, dan ukuran dari gambaran objek geometri dapat disebut sebagai transformasi geoemetri. Pada tugas akhir ini hanya akan membahas dan menggunakan transformasi translasi, rotasi, penskalaan, dan shearing. Translasi, rotasi, penskalaan, dan shearing memiliki persamaan, yaitu samsama dapat memindahkan verteks-verteks (titik-titik) penyusun objek geometri. Yang membedakan keempatnya adalah cara atau bagaimana memindahkan verteks-vereteks tersebut. Ini ditandai dengan berbedanya persamaan yang digunakan oleh tiap-tiap transformasi tersebut. Pada tugas akhir ini digunakan system koordinat homogen. Sistem koordinat homogen menggunakan empat ordinat untuk menyatakan titik-titiknya. P = (xp, yp, zp, s) Ordinat keempat menyatakan faktor skala. konversi ke sistem koordinat kartesian dapat dilakukan dengan membagi ketiga ordinat yang lain dengan ordinat keempat sehingga titik (xp, yp, zp, s) memiliki koordinat kartesian (xp/s, yp/s, zp/s).
5
6
Titik hasil transformasi dapat diperoleh melalui persamaan 2.1: Q=P· M
(2.1)
dengan : Q = [xq, yq, zq, s] menyatakan matriks 1x4 yang berisi titik hasil transformasi. P = [xp, yp, zp, s] menyatakan matriks 1x4 yang berisi titik yang akan ditransformasikan M = Matriks transformasi berukuran 4x4 seperti pada persamaan 2.2.
m00 m M = 10 m20 m30
m01 m02 m11 m12 m21 m22 m31 m32
m03 m13 m23 m33
(2.2)
Transformasi 3 dimensi terdiri dari beberapa fungsi transformasi, yaitu translasi, rotasi, penskalaan, dan shearing. Transformasi-transformasi tersebut akan dijelaskan satu per satu. 2.1.1. Translasi Transformasi
translasi
merupakan
transformasi
yang
berfungsi
memindahkan suatu objek dari posisi satu ke posisi lainnya melalui suatu garis lurus[1]. Translasi memiliki matriks seperti pada persamaan 2.3.
1 0 0 1 T = 0 0 t x t y
0 0 0 1
0 0 1 tz
(2.3)
Berikut contoh penggunaanya. P' = P ⋅ T M 0t = T
(2.4)
x
[x '
y ' z ' 1] = [x
[x '
y ' z ' 1] = x + t x
[
y
1 0 0 0 0 1 0 0 z 1] ⋅ 0 0 1 0 (2.5) t x t y t z 1 y + t y z + tz 1
]
Operasi invers dapat dilakukan dengan memberikan tanda negatif (-) pada tx, ty, dan tz sehingga hasil perkalian matriks menjadi [x-tx y-ty z-tz 1].
7
2.1.2. Penskalaan Transformasi penskalaan merupakan transformasi yang berfungsi mengubah ukuran suatu objek[1]. Ukurannya dapat menjadi lebih kecil atau lebih besar. Penskalaan memiliki matriks seperti pada persamaan 2.6. sx 0 S= 0 0
0
0
sy 0 0
0 sz 0
0 0 0 1
(2.6)
Berikut contoh penggunaanya. P' = P ⋅ S
(2.7)
[x '
y ' z ' 1] = [x
[x '
y ' z ' 1] = x ⋅ s x
[
y
s x 0 z 1] ⋅ 0 0 y ⋅ sy
0 sy 0 0
]
0 0 sz 0
0 0 0 1
(2.8)
z ⋅ sz 1
Operasi invers dapat dilakukan dengan mengubah sx, sy, dan sz menjadi 1/sx, 1/sy, 1/sz sehingga hasil perkalian matriks menjadi [x/sx y/sy z/sz 1].
2.1.3. Rotasi Menurut Hearn-Baker, transformasi rotasi dilakukan dengan memindahkan semua titik-titik dari suatu objek ke posisi yang baru dengan memutar titik-titik tersebut dengan sudut dan sumbu putar yang ditentukan[1]. Rotasi memiliki matriks seperti pada persamaan 2.9, 2.11, dan 2.13. Tiap sumbu memiliki matriks rotasi yang bebeda. 0 0 1 0 Cos (θ ) Sin(θ ) Rx (θ ) = 0 − Sin(θ ) Cos (θ ) 0 0 0
0 0 0 1
P ' = P ⋅ Rx (θ )
Cos (θ ) 0 R y (θ ) = Sin(θ ) 0
(2.9)
(2.10) 0 − Sin(θ ) 0 1 0 0 0 Cos (θ ) 0 0 0 1
(2.11)
8 P ' = P ⋅ R y (θ )
(2.12)
Cos (θ ) Sin(θ ) − Sin(θ ) Cos (θ ) Rz (θ ) = 0 0 0 0
0 0 0 0 1 0 0 1
(2.13)
P' = P ⋅ Rz (θ )
(2.14)
Operasi invers dapat dilakukan dengan memberikan tanda negatif (-) pada θ.
2.1.4. Shearing Shearing adalah transformasi yang mendistorsi bentuk dari suatu objek seakan-akan objek tersebut tersusun atas lapisan-lapisan yang mengalami kemiringan (slide) satu sama yang lain[1]. Shearing memiliki matriks seperti pada persamaan 2.15 (sumbu X), 2.17 (sumbuY), dan 2.19 (sumbu Z).
M xshear
Shxy 1 0 1 = 0 0 0 − Shxy ⋅ X ref
Shxz 0 1 − Shxz ⋅ X ref
0 0 0 1
P' = P ⋅ M xshear
M yshear
1 Sh yx = 0 − Shyx ⋅ Yref
(2.16)
0 0 Shyz 1 0 1 0 − Shyz ⋅ Yref
0 0 0 1
P' = P ⋅ M yshear
M zshear
1 0 = Shzx − Shzx ⋅ Z ref
(2.15)
(2.17)
(2.18)
0 1 Shzy − Shzy ⋅ Z ref
P' = P ⋅ M zshear
0 0 1 0
0 0 0 1
(2.19)
(2.20)
Sh menyatakan besar shearing yang akan dilakukan dan *ref menyatakan titik referensi pada sumbu yang akan digunakan. Operasi invers dapat dilakukan dengan memberikan tanda negatif (-) pada Sh.
9
2.1.5. Transformasi Berturut-turut Transformasi berturut-turut atau transformasi komposit dapat dilakukan dengan cara mengalikan matriks-matriks transformasi sesuai ururtan transformasi. Misalnya suatu titik akan ditranslasi dan diskala dengan matriks T dam S, maka matriks yang digunakan adalah matriks MK = T · S P’ = P · MK P’ = P · (T · S) 1 0 P' = [x y z 1] ⋅ 0 t x P' = [x' y ' z ' 1]
0
0
1
0
0
1
ty
tz
0 s x 0 0 ⋅ 0 0 1 0
0
0
sy
0
0
sz
0
0
0 0 0 1
(2.21)
Dengan P adalah titik awal dan P’ merupakan titik hasil transformasi.
2.1.6. Rotasi Menggunakan Sumbu yang Tidak Melewati Titik Origin Langkah-langkah yang dilakukan agar benda dapat dirotasi menggunakan sumbu yang tidak melewati titik origin adalah sebagai berikut: 1. Mentranslasikan objek sehingga sumbu putar melewati titik origin (gambar 2.1a). 2. Merotasi objek sehingga sumbu putar berimpit dengan salah satu sumbu koordinat (gambar 2.1b). 3. Lakukan rotasi yang telah ditentukan pada sumbu koordinat yang ditentukan pada no 2 (gambar 2.1c). 4. Lakukan rotasi invers agar objek kembali ke orientasi semula (gambar 2.1d). 5. Lakukan translasi invers agar objek kembali ke posisi semula (gambar 2.1e). Y
Y
Y
X
α Z
Z
(a)
(b)
α
X
X
β Z
Y
Y
X
X
β
θ
Z
Z
(c)
(d)
(e)
Gambar 2.1 Rotasi Menggunakan Sumbu yang Tidak Melewati Titik Origin.
10
2.1.7. Penskalaan Menggunakan Sembarang Titik Pusat Langkah-langkah yang dilakukan agar benda dapat diskalakan menggunakan sembarang titik pusat (tx, ty, tz) adalah sebagai berikut: 1. Lakukan translasi sebesar T-1(tx, ty, tz). Langkah ini akan membuat titik (tx, ty, tz) berimpit dengan titik (0, 0, 0). 2. Lakukan pensakalaan sebesar S(sx, sy, sz). 3. Lakukan translasi sebesar T(-tx, -ty, -tz). Langkah ini akan mengembalikan benda ke lokasi semula. 4. Dengan demikian matriks transformasi yang diperlukan untuk melalukan penskalaan menggunakan titik origin O = (0, 0, 0) sebagai titik pusat dapat diperoleh melalui: M K = T −1 ⋅ S ⋅ T 1 0 MK = 0 − t x
0
0
1
0
0
1
− ty
− tz
sx 0 MK = 0 (−t x ⋅ s x ) + t x
2.2
0 s x 0 0 * 0 0 1 0
0 sy 0 ( −t y ⋅ s y ) + t y
0
0
sy
0
0
sz
0
0
0 1 0 0 * 0 0 1 t x
0 0 sz ( −t z ⋅ s z ) + t z
0
0
1
0
0
1
ty
tz
0 0 0 1
0 0 0 1
(2.22)
(2.23)
Transformasi 3 Dimensi pada OpenGL OpenGL sendiri sudah menyediakan perintah-perintah untuk melakukan
transformasi. Perintah-perintah yang berhubungan dengan transformasi akan dijelaskan secara singkat pada subbab ini. Procedure glMatriksMode(m:GLenum);
Perintah di atas mengatur pemakaian matriks. Ada tiga macam matriks yang dapat digunakan, yaitu: MODELVIEW, PROJECTION, dan TEXTURE. MODELVIEW adalah matriks yang digunakan untuk melakukan transformasi. PROJECTION adalah matriks yang digunakan untuk proyekdi, dan TEXTURE adalah mariks yang digunakan untuk mengatur tekstur/tampilan permukaan.
11
glLoadIndentity;
Perintah di atas mengatur agar matriks yang digunakan diisi dengan matriks identitas. Matriks indentitas adalah matriks yang elemen diagonal ke kanan bawah berisi angka 1 dan elemen yang lain berisi 0. Procedure glTranslated(x,y,z:GLdouble); Procedure glTranslatef(x,y,z:GLfloat); Procedure glTranslate(x,y,z:GLdouble); Procedure glTranslate(x,y,z:GLfloat);
Perintah-perintah di atas menggunakan transformasi translasi matriks yang sedang digunakan. Parameter x, y, z menyatakan besarnya translasi yang dilaluksn pada sumbu x, y, dan z. Procedure glRotated(angle,x,y,z:GLdouble); Procedure glRotatef(angle,x,y,z:GLfloat); Procedure glRotate(angle,x,y,z:GLdouble); Procedure glRotate(angle,x,y,z:GLfloat);
Perintah-perintah di ats menggunakan rotasi untuk matriks yang sedang digunakan. Parameter x, y, z menyatakan vektor yang digunakan sebagai sumbu putar. Vektor sumbu dibentuk dari titik (0, 0, 0) ke (x, y, z). Apabila salah satu dari parameter diisi dengan nilai 1 dan parameter yang lain diisi dengan 0 maka perputaran terhadap sumbu sesuai dengan yang bernilai 1. Parameter angle menatakan besar sudut rotasi yang dilakukan. Procedure glScaled(x,y,z:PGLdouble); Procedure glScalef(x,y,z:PGLfloat); Procedure glScale(x,y,z:GLdouble); Procedure glScale(x,y,z:GLfloat);
Perintah-perintah di atas menggunakan transformasi penskalaan pada matriks yang sedang digunakan. Parameter x, y, dan z menyatakan besar penskalaan. Agar OpenGL dapat melakukan translasi maka perintah-perintah yang
12
digunakan disusun dalam urutan berikut: glMatriksMode(GL_MODELVIEW); glLoadIndentity; //jika diperlukan menggunakan matriks identitas
Perintah
glMatriksMode(GL_MODELVIEW)
memberitahukan
OpenGL
agar
perintah-perintah transformasi berikutnya diterapkan pada matriks. Perintahperintah transformasi yang telah disediakan oleh OpenGL akan digunakan dalam membangun aplikasi studio, tentunya digunakan bersama-sama dengan bahasa pemrograman Delphi. Perintah-perintah transformasi OpenGL diharapkan dapat mempercepat membangun aplikasi. 2.3
Penggunaan OpenGL pada Delphi Di dalam sistem operasi Windows, OpenGL diimplementasikan ke dalam 2
buah berkas, yaitu opengl32.dll dan glut32,dll. Opengl32.dll merupakan pustaka program yang menyediakan perintah-perintah utama dari OpenGL dan glut32.dll menyediakan perintah-perintah tambahan (utility) dari OpenGL. OpenGL dan Delphi perlu dihubungkan sehingga transformasi 3 dimensi menggunakan OpenGL dapat dilakukan. Untuk menghubungkannya, yaitu dengan menggunakan file opengl.dcu yang biasanya terdapat di direktori …\lib pada direktori Delphi. Penggunaannya cukup dengan menambahkan klausa OpenGL pada kode program di bagian uses. uses OpenGL, Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs;
OpenGL bukan merupakan bagian dari system operasi Windows sehingga diperlukan memberitahu Windows bahwa program menggunakan API dari OpenGL. Informasi yang perlu disampaikan, yaitu: 1. Format Pixel yang disampaikan melalui struktur data TPIXELFORMATDESCRIPTOR.
Format Pixel (pfd) memberikan informasi mengenai jumlah
warna dalam bit per pixel, versi OpenGL yang digunakan, kedalaman sumbu z, tipe pixel, dan lain-lain.
13
2. Device Context yang merupakan perangkat yang akan digunakan oleh OpenGL untuk menggambar. Device context yang disediakan oleh Windows dan rendering context yang disediakan oleh OpenGL harus dihubungkan sehingga apa yang digambar oleh OpenGL akan ditampilkan oleh Windows. type TForm1 = class(TForm) private { Private declarations } rc : HGLRC;
//rendering context OpenGL
dc : HDC;
//device context windows
Atribut pfd merupakan atribut yang digunakan untuk memyimpan informasi pixel, sedangkan dc merupakan atribut untuk menyimpan device context yang dibuat oleh Window dan atribut rc digunakan untuk menyimpan rendering context yang dibuat oleh OpenGL. Antara device context yang dibuat melalui windows (dc) dan rendering context yang dibuat melalui OpenGL (rc) nantinya akan dihubungkan melalui wglMakeCurrent. procedure TForm1.FormCreate(Sender: TObject); var pfd : TPIXELFORMATDESCRIPTOR; pf
: Integer;
begin dc:=GetDC(Form1.Handle); pfd.nSize:=sizeof(pfd); pfd.nVersion:=1; pfd.dwFlags:=PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER or 0; pfd.iPixelType:=PFD_TYPE_RGBA; pfd.cColorBits:=32; pfd.cDepthBits:=32; pf :=ChoosePixelFormat(dc, @pfd); SetPixelFormat(dc, pf, @pfd); rc :=wglCreateContext(dc); wglMakeCurrent(dc,rc); end;
14
Perintah dc:=GetDC(Form1.Handle) digunakan untuk menangkap device context dari Handle yang diliki oleh Form1 dan hasilnya diberikan ke varaibel dc. Perintah berikutnya mengisi struktur pfd dengan nilai yang diinginkan, dua diantaranya, yaitu iPixelType yang menggunakan PFD_TYPE_RGBA untuk mendukung warna 32 bit per pixel dan cDepthBits untuk kedalaman sumbu z sebesar 32 bit. Setelah pfd selesai diisi maka isi pfd digunakan untuk memformat rc
dan indeks format pixel dari format yang dikembalikan melalui variabel pf.
Langkah selanjutnya adalah mengatur agar device context dc menggunakan format tersebut. Rendering context dari OpenGL dibuat berdasarkan device context dc. Antara rc dan dc dihubungkan satu sama lain menggunakan wglMakeCurrent(dc,rc)
yang menyatakan mulai saat itu OpenGL menggunakan
dc sebagai kanvas untuk menggambar. 2.4
Representasi Objek 3 Dimensi Objek 3 dimensi disusun dengan menghubungkan sejumlah verteks (titik).
Struktur data untuk verteks 3 dimensi adalah sebagai berikut: type Ttitik3d =
record
posX,posY,posZ:GLFloat; end;
Garis-garis yang menghubungkan suatu kumpulan verteks-verteks disebut sebagai wireframe atau kerangka dan benda yang dibentuk oleh dari kumpulan titik-titik dan garis-garis tersebut disebut sebagai Mesh. Pada gambar 2.2 suatu objek (mesh) kubus terbentuk dari 9 buah verteks. Verteks 0 digunakan sebagai titik pusat sedangkan verteks-verteks dari 1 sampai 8 dihubungkan dengan garis-garis membentuk kerangka kubus. 7
8 5
6
0
4 1
3 2
Gambar 2.2 Objek geometri kubus.
15
Karena suatu objek terdiri dari satu verteks atau lebih maka perlu membuat struktur data untuk menampung informasi koordinat verteks-verteks penyusunnya. Struktur data yang digunakan, yaitu array dengan tipe Ttitik3d yang telah didefiniskan di atas. verteks:array of Ttitik3d;
Jika diimplementasikan pada objek kubus di atas maka panjang arraynya adalah sembilan. verteks:array[0..8] of Ttitik3d;
Kubus pada gambar 2.2 dapat disusun berdasrkan data yang ad pada tabel 2.1. Tabel 2.1 Verteks penyusun kubus. Verteks 0 1 2 3 4 5 6 7 8
2.5
X 0 -1 1 1 -1 -1 1 1 -1
Y 0 -1 -1 -1 -1 1 1 1 1
Z 0 1 1 -1 -1 1 1 -1 -1
Interaksi Pengguna dengan Aplikasi Antarmuka diperlukan agar pengguna dapat berinteraksi dengan aplikasi.
Interaksi yang digunakan pada aplikasi dibagi menjadi 3, yaitu interaksi menggunakan
button,
interaksi
menggunakan
keyboard,
dan
interaksi
menggunakan mouse. 1. Interaksi menggunakan button Interaksi menggunakan button dilakukan dengan memakai event handling bawaan Delphi seperti onClick, onChange, dan lain-lain untuk operasi-operasi tertentu. 2. Interaksi menggunakan keyboard Interaksi menggunakan keyboard juga dilakukan dengan memakai event handling bawaan Delphi. Salah satunya event onKeyPress. Event pada keyboard digunakan sebagai shortcut untuk melakukan operasi tertentu, misalnya mengatifkan mode transformasi rotasi dengan menekan tombol ‘r’. 3. Interaksi menggunakan mouse Interaksi menggunakan mouse tetap menggunakan event handling bawaan
16
Delphi tetapi mengkombinasikannya dengan perintah bawaan OpenGL, yaitu gluUnProject. Perintah ini digunakan untuk mengubah koordinat 2 dimensi pointer mouse pada layar window dan mengembalikan nilai berupa koordinat 3 dimensi dari gambar OpenGL. Dalam implementasinya, mouse digunakan untuk mentransformasi objek 3 dimensi dengan cara mengeser mouse tersebut. Perbedaan kordinat 2 dimensi setelah pergesesan menjadi acuan untuk transformasi 3 dimensi pada koordinat 3 dimensi.
BAB III PERANCANGAN APLIKASI GRAFIKA KOMPUTER UNTUK TRANSFORMASI GEOMETRI OBJEK 3 DIMENSI
Perancangan aplikasi grafika komputer untuk transformasi objek 3 dimensi menggunakan pendekatan berorientasi objek. Langkah-langkah perancangan yang dilakukan mengikuti model yang diutarakan oleh Pressman[6], yaitu: 1. Use case, 2. Kartu Index CRC, 3. Diagram Kelas, 4. Model Hubungan Objek (Object Relationship), dan 5. Model Tingkah Laku Objek (Object Behaviour). 3.1
Use case Use case merupakan rangkaian skenario yang mengidentifikasikan urutan
pemakaian aplikasi yang akan dibangun[6]. Skenario penggunaan aplikasi grafika komputer untuk transformasi objek 3 dimensi adalah sebagai berikut: 1.
Pengguna membuat objek geometri. Pengguna dapat memilih objek geometri yang akan dibuat, yaitu kubus, piramid, silinder, meja, dan kursi.
2.
Pengguna melakukan transformasi terhadap objek geometri. Objek yang akan ditransformasi dipilih terlebih dahulu kemudian pengguna menentukan transformasi apa yang akan dilakukan. Transformasi yang dapat dilakukan, meliputi translasi, penskalaan, rotasi, dan shearing. Tiap-tiap transformasi memiliki parameter-parameter tersendiri dan pengguna dapat menentukan nilai parameter-parameter tersebut. Misalnya: Rotasi pada suatu kubus. Pengguna dapat menentukan besar sudut rotasi dan sumbu rotasi.
3.
Pengguna menghapus objek. Pengguna memilih objek yang telah dibuat kemudian menghapusnya. Skenario di atas kemudian diubah ke dalam bentuk diagram use case yang
bentuknya seperti gambar 3.1.
17
18
Buat Objek
Translasi
Penskalaan Transformasi
Pengguna
Rotasi
Hapus Objek
Shearing
Gambar 3.1 Diagram use case aplikasi grafika komputer untuk transformasi objek 3 dimensi.
Sistem hanya memiliki satu aktor, yaitu pengguna. Pengguna dapat melakukan tiga use case, yaitu membuat objek, melakukan transformasi pada objek, dan menghapus objek. Pada diagram terlihat bahwa use case transformasi merupakan generalisasi dari 4 macam use case, yaitu translasi, penskalaan, rotasi, dan shearing. Artinya, transformasi masih dapat lebih spesifikkan, yaitu translasi, penskalaan, rotasi, atau pun shearing. 3.2
Kartu Index CRC (Class-Responsibility-Collaborator) Setelah melakukan analisis use case, selanjutnya adalah membuat kartu
index CRC. Pemodelan CRC memberikan cara sederhana untuk mengidentifikasi dan mengumpulkan kelas-kelas yang relevan[6] yang nantinya akan digunakan untuk aplikasi grafika komputer untuk transformasi objek 3 dimensi. Dari analisis use case, dapat diidentifikasi 2 kelas utama, yaitu kelas objek geometri
dan kelas transfomasi. Kelas objek geometri diturunkan menjadi
subkelas-subkelas menurut kekhasan objek geometri itu sendiri, misalnya kelas kubus, kelas piramid, kelas silinder, kelas meja, dan kelas kursi. Kelas transformasi memiliki operasi, yaitu translasi, rotasi, penskalaan, dan shearing. Tabel 3.1 menunjukkan kartu index CRC untuk kelas-kelas objek geometri dan turunannya.
19
Tabel 3.1 Kartu index CRC kelas objek geometri. Kelas: Objek Geometri Tanggung Jawab: Kolaborator: Atribut: • nama • • index • jenis • pusat • jumTitik • titik • sudut • Aktif Operasi: • Gambar Tabel 3.2 Kartu index CRC kelas kubus. Kelas: Kubus Tanggung Jawab: Atribut: • Sisi Operasi: • Create • Gambar
Kolaborator: •
-
Tabel 3.3 Kartu index CRC kelas piramid. Kelas: Piramid Tanggung Jawab: Atribut: • Tinggi • Sisi Operasi: • Gambar • Create
Kolaborator: •
-
Tabel 3.4 Kartu index CRC kelas silinder. Kelas: Silinder Tanggung Jawab: Atribut: • Radius • Tinggi Operasi: • Gambar • Create
Kolaborator: •
-
20
Tabel 3.5 Kartu index CRC kelas meja. Kelas: Meja Tanggung Jawab: Atribut: • Operasi: • Gambar • Create
Kolaborator: •
-
Tabel 3.6 Kartu index CRC kelas kursi. Kelas: kursi Tanggung Jawab: Atribut: • Operasi: • Gambar • Create
Kolaborator: •
-
Kelas objek geometri dapat diturunkan menjadi subkelas-subkelas objek geometri seperti kelas kubus, kelas piramid, kelas silinder, kelas meja, dan kelas kursi. Karena merupakan turunan dari kelas objek geometri, maka kelas-kelas tersebut memiliki atribut yang sama dengan kelas objek geometri. Selain itu, tiaptiap kelas memiliki atribut tersendiri yang membedakannya dengan kelas lain yang berasal dari kelas induk yang sama, misalnya objek kubus memiliki atribut ukuran sisi sedangkan piramid memiliki atribut tinggi dan sisi untuk alasnya. Kelas transformasi memiliki operasi-operasi seperti yang ditunjukkan tabel 3.2, yaitu operasi translasi, rotasi, penskalaan, shearing, dan lain-lain. Tabel 3.7 Kartu index CRC Transformasi. Kelas: Transformasi Tanggung Jawab: Atribut: • Matriks Operasi: • PerkalianMatriks • MatriksIdentitas • Translasi • Penskalaan • Rotasi • Shearing • Transform • nolkanTransformasi • ambilPos3d
Kolaborator: • Objek Geometri
21
3.3
Diagram Kelas Diagram kelas (gambar 3.2) dibuat dari kartu index CRC pada subbab 3.2.
Diagram kelas memberikan gambaran tentang kelas-kelas apa saja yang perlu dibuat untuk membangun aplikasi, lengkap dengan atribut dan operasinya. Pada gambar 3.2, kelas geometri memiliki 5 kelas turunan, yaitu kubus, silinder, piramid, meja, dan kursi. Kelas transformasi tidak memiliki turunan tetapi memiliki operasi-operasi untuk melakukan transformasi 3 dimensi.
Transformasi Matriks
Geometri nama : String index : Integer jenis : String posisi : Single sudut : Single 1..* pusat : Single
Mentransformasi
1
gambar()
Kubus sisi : Single gambar() create()
Piramid
Silinder radius : Single tinggi : Single
tinggi : Single sisi : Single
gambar() create()
gambar()
Meja
Kursi
gambar() create()
gambar() create()
perkalianMatriks() MatriksIdentitas() Translasi() Penskalaan() Rotasi() Shearing() Transform() nolkanTransformasi() ambilPos3d()
Gambar 3.2 Diagram kelas aplikasi grafika komputer untuk transformasi objek 3 dimensi.
3.4
Model Hubungan Objek Model hubungan objek (object relationship model) dapat digambarkan
dengan menggunakan diagram runtun (sequence diagram). Dengan diagram runtun, interaksi antarobjek dapar diperlihatkan. Pada gambar 3.3 terdapat 3 skenario, yaitu menciptakan objek geometri, mentransformasi objek geometri, dan menghapus objek geometri. Pengguna membuat objek dengan objek dan mendefinisikan nilai atributatributnya pada antarmuka. Setelah itu, objek geometri dibuat dan digambarkan pada layar sehingga dapat dilihat oleh pengguna.
22
Antarmuka
: Geometri
: Transformasi
Layar
: Pengguna Memilih objek yang akan dibuat dan nilai atributnya
gambar objek pada layar
Membuat objek geometri Menampilkan objek geometri
Memilih jenis transformasi dan Memberi nilai sesuai input nilainya
Mentransformasi objek geometri
Gambar objek pada layar
Menampilkan objek geometri hasil transformasi Memilih objek yang akan dihapus
Menghapus objek geometri
Meampilkan hasil menghapus objek geometri
Hapus objek pada layar
Gambar 3.3 Diagram runtun aplikasi grafika komputer untuk transformasi objek 3 dimensi.
Untuk
melakukan
transformasi
pada
objek
geometri,
pengguna
mendefinisikan transformasi yang akan dilakukan beserta nilai-nilainya pada antarmuka. Antarmuka kemudian memberi nilai-nilai tersebut ke objek transformasi. Objek transformasi kemudian menerapkan transfomasi pada objek geometri. Akibatnya, objek berubah pada bentuk, posisi, atau sudut. Objek digambar ulang pada layar dan hasilnya ditampilkan pada pengguna. Pengguna dapat menghapus objek dengan terlebih dahulu memilih objek tersebut antarmuka. Antarmuka kemudian menghapus objek geometri tersebut. Hasilnya, objek geometri akan terhapus pada layar. Layar kemudian ditampilkan pada pengguna sehingga pengguna mengetahui bahwa objek telah terhapus.
23
3.5
Model Tingkah Laku Objek Gambar 3.4 merupakan diagram statechart yang menggambarkan perilaku
dua objek, yaitu objek transformasi (a) dan objek geometri (b). Model tingkah laku objek menunjukkan bagaimana sistem akan merespon kejadian atau stimulus eksternal. Mulai Mentransformasi objek geometri
Membuat objek transformasi
Menunggu perintah transformasi selanjutnya
Objek transformasi tercipta
Menutup Aplikasi Selesai
Objek transformasi terhapus
(a) Mulai
Membuat objek geometri
Posisi, sudut, dan bentuk yang baru Mentransformasi objek geometri
Objek geometri tercipta
Menunggu transformasi selanjutnya Menghapus objek geometri
Selesai
Objek geometri terhapus
(b) Gambar 3.4 Diagram statechart aplikasi grafika komputer untuk transformasi objek 3 dimensi: (a) diagram statechart objek transformasi (b) diagram statechart objek geometri.
Ketika
aplikasi
dijalankan,
operasi
membuat
objek
transformasi
mengakibatkan objek transformasi tercipta. Objek transformasi kemudian menunggu perintah transformasi untuk mentransformasi objek geometri. Pada saat aplikasi ditutup, maka objek transformasi akan terhapus. Operasi buat objek geometri akan membuat objek geometri tercipta. Operasi transformasi (rotasi, translasi, penskalaan, dan shearing) akan mentransformasi objek tersebut sehingga nilai atribut-atribut seperti posisi dan ukuran akan berubah. Setelah operasi transformasi dilakukan, objek akan menunggu
24
transformasi selanjutnya. Objek akan terhapus jika dilakukan operasi hapus objek pada objek tersebut. 3.6
Desain Antarmuka Aplikasi grafika komputer untuk transformasi objek 3 dimensi terdiri dari
satu form utama. Form utama terdiri dari beberapa bagian, yaitu menubar, toolbar, tab objek, layar, dan statusbar. Menubar berisi menu-menu untuk melakukan operasi-operasi pada aplikasi. Toolbar berisi tombol-tombol untuk melakukan operasi-operasi pada aplikasi. Layar digunakan untuk menampilkan gambar 3 dimensi. Tab objek digunakan untuk membuat objek geometri yang dikehendaki. Statusbar digunakan untuk melihat status-status seperti posisi mouse, mode transformasi yang sedang aktif, dan sumbu koordinat yang sedang aktif. Perancangan antarmuka aplikasi dapat dilihat pada gambar 3.5.
Menu Bar Tool Bar Layar
Tab Objek
Status Bar Gambar 3.5 Desain antarmuka aplikasi grafika komputer untuk transformasi objek 3 dimensi.
BAB IV IMPLEMENTASI DAN PENGUJIAN APLIKASI GRAFIKA KOMPUTER UNTUK TRANSFORMASI 3 DIMENSI
Bab IV membahas mengenai implementasi dan pengujian pada aplikasi grafika komputer untuk transformasi 3 dimensi. Implementasi adalah bagaimana mewujudnyatakan hasil dari perancangan sehingga menghasilkan suatu aplikasi yang dapat bekerja dengan baik. Setelah itu, pengujian dilakukan untuk mengetahui apakah aplikasi sudah dapat bekerja sebagaimana mestinya atau belum. Jika hasilnya belum maka aplikasi masih perlu disempurnakan. 4.1. Implementasi Implementasi aplikasi grafika komputer untuk transformasi 3 dimensi memiliki 4 bagian penting, yaitu implementasi tampilan aplikasi, implementasi objek geometri, implementasi vektor, dan implementasi transformasi 3 dimensi. 4.1.1. Implementasi Tampilan Aplikasi
Gambar 4.1 Tampilan aplikasi grafika komputer untuk transformasi geometri.
Gambar 4.1 merupakan tampilan aplikasi grafika komputer untuk
25
26
transformasi 3 dimensi yang terdiri dari satu form utama. Form utama terdiri dari beberapa bagian, yaitu toolbar, menu, tab objek, layar, log, dan statusbar.
Gambar 4.2 Toolbar dan menu aplikasi.
Gambar 4.2 menujukkan tampilan toolbar dan menu. Toolbar terdiri dari 10 tombol dan 1 combo box. Button transalasi untuk melakukan translasi, tombol penskalaan untuk transformasi penskalaan, tombol rotasi untuk rotasi, tombol shearing untuk operasi shearing, tombol reset untuk kembali ke mode awal, button zoom untuk memperbesar atau memperkecil tampilan pada layar, tombol rotasi kamera untuk memutar kamera dengan sumbu pada titik fokus kamera, tombol rotasi fokus untuk memutar titik fokus kamera, tombol geser kamera digunakan untuk menggeser layar, dan tombol fokus ke objek digunakan untuk memindahkan fokus kamera ke objek terpilih, dan tombol reset kamera untuk mengembalikan kamera ke posisi awal. Combo box digunakan untuk memilih sumbu atau arah vektor.
Gambar 4.3 Tampilan tab-tab untuk objek kubus, kursi, meja, piramida, silinder, kamera, dan OBJ Loader serta Memo untuk menampilkan log.
27
Gambar 4.3 adalah tampilan tab-tab objek. Tab piramida unuk membuat piramida, tab kubus untuk membuat kubus, tab silinder untuk membuat silinder, tab meja untuk membuat meja, tab kursi untuk membuat kursi, dan tab kamera untuk memindah posisi kamera atau titik fokusnya, dan tab OBJ Loader untuk memuat berkas OBJ.
Gambar 4.4 Status Bar.
Gambar 4.4 memperlihatkan statusbar. Statusbar berfungsi untuk menampilkan posisi mouse pada koordinat world, posisi mouse pada layar, mode transformasi yang sedang aktif, arah vektor/sumbu putar, dan framerate.
Gambar 4.5 Tampilan popup menu klik kanan.
Gambar 4.5 memperlihatkan popup menu aplikasi. Menu terdiri dari beberapa pilihan. Pilihan translasi akan menampilkan form translasi. Pilihan rotasi akan menampilkan form rotasi. Pilihan penskalaan akan menampilkan form penskalaan. Pilihan shearing akan menampilkan form shearing. Pilihan hapus akan menghapus objek terpilih. Form-form tersebut dapat dilihat pada gambar 4.6.
Gambar 4.6 Form untuk transformasi translasi, penskalaan, rotasi dan shearing.
28
4.1.2. Implementasi Objek Geometri a.
Piramida Geometri piramida (gambar 4.7) terdiri dari 7 titik dengan titik 2 dan 6 berada
pada posisi yang sama. 1
0
5
4
2 dan 6
3
Gambar 4.7 Objek geometri piramida.
Inisialisasi nilai koordinat titik-titik tersebut dilakukan ketika objek piramida diciptakan.Ini dilakukan pada konstruktor create. constructor Tpiramid.create(pTinggi,pSisi:GLfloat; titikPusat:Ttitik3d);
Konstruktor ini membutuhkan nilai tinggi, sisi, dan titik pusat yang akan dilewatkan pada parameter pTinggi, pSisi, dan titikPusat. Dari ketiga nilai tersebut, konstruktor akan menghitung nilai-nilai untuk setiap titik. Detil prosesnya dapat dilihat pada source code di lampiran A. Setelah
setiap
titik
memiliki
nilai
koordinat,
piramida digambar
menggunakan prosedur Gambar. procedure TPiramid.Gambar;
Pada prosedur gambar, bagian atas piramida digambar dahulu kemudian bagian alasnya. Bagian atas piramida digambar dengan perintah berikut: glBegin(GL_TRIANGLE_FAN); for i:=1 to 6 do glVertex3f(titik[i].posX,titik[i].posY,titik[i].posZ); glEnd;
Bagian alas piramida digambar dengan perintah berikut: glBegin(GL_QUADS); for i:=2 to 5 do glVertex3f(titik[i].posX,titik[i].posY,titik[i].posZ); glEnd;
29
b. Kubus Geometri kubus (gambar 4.8) terdiri dari 9 titik. Inisialisasi nilai koordinat titiktitik tersebut dilakukan ketika objek kubus diciptakan. 7
8 5
6
0
4
3
1
2
Gambar 4.8 Objek geometri kubus.
Ini dilakukan pada konstruktor create. constructor Tkubus.create(pSisi:GLFloat; titikPusat:Ttitik3d);
Konstruktor ini membutuhkan nilai tinggi, sisi, dan titik pusat yang akan dilewatkan pada parameter pSisi dan titikPusat. Dari kedua nilai tersebut, konstruktor akan menghitung nilai-nilai untuk setiap titik. Detil prosesnya dapat dilihat pada source code di lampiran A. Setelah
setiap
titik
memiliki
nilai
koordinat,
piramida digambar
menggunakan prosedur Gambar. procedure TKubus.Gambar;
Pada prosedur gambar, bagian depan, belakang, kiri, kanan, atas, dan bawah kubus dibuat berurutan. Bagian depan kubus digambar dengan perintah berikut: glBegin(GL_QUADS); glVertex3f(titik[1].posX,titik[1].posY,titik[1].posZ); glVertex3f(titik[2].posX,titik[2].posY,titik[2].posZ); glVertex3f(titik[6].posX,titik[6].posY,titik[6].posZ); glVertex3f(titik[5].posX,titik[5].posY,titik[5].posZ);
Bagian belakang kubus digambar dengan perintah berikut: glVertex3f(titik[4].posX,titik[4].posY,titik[4].posZ); glVertex3f(titik[3].posX,titik[3].posY,titik[3].posZ); glVertex3f(titik[7].posX,titik[7].posY,titik[7].posZ); glVertex3f(titik[8].posX,titik[8].posY,titik[8].posZ);
Bagian kiri kubus digambar dengan perintah berikut:
30
glVertex3f(titik[4].posX,titik[4].posY,titik[4].posZ); glVertex3f(titik[1].posX,titik[1].posY,titik[1].posZ); glVertex3f(titik[5].posX,titik[5].posY,titik[5].posZ); glVertex3f(titik[8].posX,titik[8].posY,titik[8].posZ);
Bagian kanan kubus digambar dengan perintah berikut: glVertex3f(titik[2].posX,titik[2].posY,titik[2].posZ); glVertex3f(titik[3].posX,titik[3].posY,titik[3].posZ); glVertex3f(titik[7].posX,titik[7].posY,titik[7].posZ); glVertex3f(titik[6].posX,titik[6].posY,titik[6].posZ);
Bagian atas kubus digambar dengan perintah berikut: glVertex3f(titik[5].posX,titik[5].posY,titik[5].posZ); glVertex3f(titik[6].posX,titik[6].posY,titik[6].posZ); glVertex3f(titik[7].posX,titik[7].posY,titik[7].posZ); glVertex3f(titik[8].posX,titik[8].posY,titik[8].posZ);
Bagian bawah kubus digambar dengan perintah berikut: glVertex3f(titik[1].posX,titik[1].posY,titik[1].posZ); glVertex3f(titik[2].posX,titik[2].posY,titik[2].posZ); glVertex3f(titik[3].posX,titik[3].posY,titik[3].posZ); glVertex3f(titik[4].posX,titik[4].posY,titik[4].posZ); glEnd;
c.
Silinder Geometri silinder (gambar 4.9) terdiri dari 33 titik. Inisialisasi nilai koordinat
titik-titik tersebut dilakukan ketika objek silinder diciptakan. 18
24
17 18 19
0
12
1
8 2 3
Gambar 4.9 Objek geometri silinder.
Ini dilakukan pada konstruktor create. constructor Tsilinder.Create(pRadius,pTinggi:GLfloat; titikPusat:Ttitik3d);
31
Konstruktor ini membutuhkan nilai tinggi, sisi, dan titik pusat yang akan dilewatkan pada parameter pTinggi, pRadius, dan titikPusat. Dari ketiga nilai tersebut, konstruktor akan menghitung nilai-nilai untuk setiap titik. Detil prosesnya dapat dilihat pada source code di lampiran A. Setelah
setiap
titik
memiliki
nilai
koordinat,
silinder
digambar
menggunakan prosedur Gambar. procedure TSilinder.Gambar;
Pada prosedur gambar, bagian atas, alas, dan badan silnder dibuat berurutan. Bagian tutup silinder digambar dengan perintah berikut: glBegin(GL_POLYGON); for i:=1 to 16 do begin glVertex3f(titik[i].posX,titik[i].posY,titik[i].posZ); end; glEnd;
Bagian alas silinder digambar dengan perintah berikut: glBegin(GL_POLYGON); for i:=17 to 32 do begin glVertex3f(titik[i].posX,titik[i].posY,titik[i].posZ); end; glEnd;
Bagian badan silinder digambar dengan perintah berikut: i:=1; glBegin(GL_QUAD_STRIP); while i<=16 do begin glVertex3f(titik[i].posX,titik[i].posY,titik[i].posZ); glVertex3f(titik[i+16].posX,titik[i+16].posY, titik[i+16].posZ); i:=i+1; end; glVertex3f(titik[32].posX,titik[32].posY,titik[32].posZ); glVertex3f(titik[1].posX,titik[1].posY,titik[1].posZ); glEnd;
32
d. Daftar Geometri Objek-objek geometri yang dibuat perlu ditampung sehingga objek-objek dapat dikelola lebih mudah. Misalnya mentranfomasi hanya objek yang aktif terpilih, menghapus objek-objek tertentu, dan sebagainya. Objek-objek tersebut disimpan pada daftar geometri yang berwujud kelas TdaftarGeometri. Objekobjek tersebut disimpan varaibel f yang bertipe Tlist. Tlist merupakan kelas linked list bawaan OpenGL. constructor TDaftarGeometri.Create(Owner:Tcomponent); begin f:=TList.Create; end;
Constructor digunakan untuk inisialisasi pada saat objek dari kelas TdaftarGeometri dibuat. Pada saat contructor dipanggil, objek f dibuat dari kelas Tlist. destructor TDaftarGeometri.Destroy; begin f.Free; end;
Destructor digunakan untuk menghapus objek dari kelas TdaftarGeometri. Pada saat destructor dipanggil, variabel f akan dikosongkan. Dengan demikian semua informasi objek yan disipan pada f akan terhapus. procedure TDaftarGeometri.TambahGeometri(var O:TGeometri); var item:TGeometri;i:integer; begin i:=f.Add(O); FormUtama.sMemo1.Lines.add('Index Objek: '+IntToStr(i)); item:=f.Items[i]; item.index:=i; f.Items[i]:=item; end;
Prosedur TambahGeometri digunakan untuk menambahkan objek yang dibuat ke f yang merupakan objek dari kelas Tlist. Pertama-tama, objek geometri O disimpan ke f dengan perintah f.add(O). Perintah f.add(O) akan mengembalikan nilai integer yang merupakan nilai index O pada f. Kedua, Index objek tersebut ditampilkan pada bagian log, yaitu komponen sMemo1. Ketiga, variabel item yang bertipe Tgeometri digunakan untuk menyimpan sementara isi dari f.items[i]
33
yang berisi objek dari kelas Tgeometri yang baru dibuat. Keempat, atribut index dari item kemudian diisi dengan nilai i. Kelima, setelah atribut index terisi, nilai item kemudian diberikan kembali ke f.items[i]. procedure TDaftarGeometri.Gambar; var index:integer; item:Tgeometri; begin for index:=0 to f.Count-1 do begin item:=f.Items[index]; glLoadName(item.index+100); item.Gambar; glEnd(); end; end;
Prosedur Gambar digunakan untuk menggambarkan selurug objek geometri yang terdapat pada daftar geometri. Setiap objek yang akan digambarkan diberi nama dengan perintah glLoadName(item.index+100). Nama yang diberikan akan digunakan pada saat objek tersebut diklik pada layar. Jika nama yang dihasilkan ketika mengklik objek sama dengan nilai index objek dikurangi 100, maka objek akan menjadi aktif. 4.1.3. Implementasi Vektor Transformasi membutuhkan operasi vektor. Operasi vektor yang digunakan pada aplikasi ini, yaitu: 1.) Mengubah koordinat 3 dimensi menjadi vektor 3 dimensi. Operasi ini dinyatakan dalam bentuk fungsi buatVektor. function BuatVektor(x,y,z:real):Ttitik3d; var va:Ttitik3d; begin va.posX:=x; va.posY:=y; va.posZ:=z; result:=va; end;
2.) Menghitung panjang vektor. Operasi ini dinyatakan dalam bentuk fungsi PanjangVektor. function PanjangVektor(va:Ttitik3d):real; begin
34
Result:=abs(sqrt(va.posx*va.posx+va.posy*va.posy+ va.posz*va.posz)); end;
3.) Normalisasi
vektor.
Operasi
ini
dinyatakan
dalam
bentuk
fungsi
Normalisasi. function Normalisasi(va:Ttitik3d):Ttitik3d; var l:real; v:Ttitik3d; begin l:=PanjangVektor(va); if l=0 then exit else begin v.posx:=va.posx/l; v.posy:=va.posy/l; v.posz:=va.posz/l; result:=v; end; end;
4.) Operasi dot product. Operasi ini dinyatakan dalam bentuk fungsi DotProduct. function DotProduct(va,vb:Ttitik3d):real; var s:real; begin s:=va.posx*vb.posx+va.posy*vb.posy+va.posz*vb.posz; result:=s; end;
5.) Operasi cross product. Operasi ini dinyatakan dalam bentuk fungsi CrossProduct. function CrossProduct(va,vb:Ttitik3d):Ttitik3d; var vs:Ttitik3d; begin vs.posx:=(va.posy*vb.posz)-(va.posz*vb.posy); vs.posy:=(va.posz*vb.posx)-(va.posx*vb.posz); vs.posz:=(va.posx*vb.posy)-(va.posy*vb.posx); result:=vs; end;
35
4.1.4. Implementasi Transformasi Dalam mengimplementasikan transformasi diperlukan beberapa operasi seperti perkalian matriks, mengidentitaskan matriks, translasi, penskalaan, rotasi, dan shearing. Operasi-operasi tersebut dibuat dalam bentuk prosedur-prosedur seperti berikut. a. Perkalian Matriks Perkalian matriks dibutukan untuk melakukan transformasi geometri. Misalnya mengalikan matriks translasi dengan matriks penskalaan untuk transformasi berturut-turut. Operasi perkalian matriks dinyatakan dalam bentuk prosedur PerkalianMatriks. procedure TTransformasi.PerkalianMatriks(Matriks1,Matriks2: Matriks4x4;var Matriks3:Matriks4x4); var baris,kolom:byte; matriksTemp:Matriks4x4; begin for baris:=0 to 3 do begin for kolom:=0 to 3 do begin matriksTemp[baris,kolom]:=Matriks1[baris,0]*Matriks2 [0,kolom]+ Matriks1[baris,1]*Matriks2[1,kolom]+ Matriks1[baris,2]*Matriks2[2,kolom]+ Matriks1[baris,3]*Matriks2[3,kolom]; end; end; for baris:=0 to 3 do for kolom:=0 to 3 do Matriks3[baris,kolom]:=matriksTemp[baris,kolom]; end;
b. Mantriks Identitas Matriks identitas digunakan untuk menolkan suatu matriks transformasi. Operasi MatriksIdentitas dinyatakan dalam bentuk prosedur MatriksIdentitas. procedure TTransformasi.MatriksIdentitas(var m:Matriks4x4);
36
begin m[0,0]:=1;m[0,1]:=0;m[0,2]:=0;m[0,3]:=0; m[1,0]:=0;m[1,1]:=1;m[1,2]:=0;m[1,3]:=0; m[2,0]:=0;m[2,1]:=0;m[2,2]:=1;m[2,3]:=0; m[3,0]:=0;m[3,1]:=0;m[3,2]:=0;m[3,3]:=1; end;
c. Translasi Persamaan tranasformasi translasi yang terdapat pada persamaan 2.3 dan 2.4 dibuat ke dalam bentuk prosedur translasi di bawah ini. Prosedur ini digunakan untuk mentranslasikan suatu titik sebesar parameter x,y, dan z-nya. procedure TTransformasi.Translasi(x,y,z:real); var matriksTranslasi:Matriks4x4; begin MatriksIdentitas(MatriksTranslasi); MAtriksTranslasi[3,0]:=x; MAtriksTranslasi[3,1]:=y; MAtriksTranslasi[3,2]:=z; PerkalianMatriks(MAtriks,MAtriksTranslasi,MAtriks); end;
d. Penskalaan Persamaan transformasi penskalaan yang terdapat pada persamaan 2.5 dan 2.6 dibuat ke dalam bentuk prosedur penskalaan di bawah ini. Prosedur ini digunakan untuk menskalakan suatu titik sebesar parameter sx, sy, dan sz dengan titik acuan xc, xy, dan xz. procedure TTransformasi.Penskalaan(sx,sy,sz,xc,yc,zc:real); var matriksPenskalaan:Matriks4x4; begin MatriksIdentitas(matriksPenskalaan); Translasi(-xc,-yc,-zc); matriksPenskalaan[0,0]:=sx; matriksPenskalaan[1,1]:=sy; matriksPenskalaan[2,2]:=sz; PerkalianMatriks(Matriks,matriksPenskalaan,Matriks); Translasi(xc,yc,zc); end;
37
e. Rotasi Persamaan transformasi rotasi yang terdapat pada persamaan 2.6, 2.7, dan 2.8 serta pemahaman tentang subbab 2.1.6 maka dapat dibuat prosedur rotasi
di bawah ini. Prosedur ini digunakan untuk merotasikan suatu titik sebesar
parameter sudut dengan sumbu xr, yr, dan zr. procedure TTransformasi.Rotasi(sudut:real;xr,yr,zr:real); var alpha,betha,radian:real; ryb,rza,ryb_1,rza_1,ry:Matriks4x4; u,u1,u2,s:Ttitik3d; begin MatriksIdentitas(ryb); MatriksIdentitas(rza); MatriksIdentitas(ry); MatriksIdentitas(ryb_1); MatriksIdentitas(rza_1); MatriksIdentitas(Matriks);
radian:=sudut*PI/180;
u1:=Normalisasi(BuatVektor(1,0,0)); u2:=Normalisasi(buatVektor(0,1,0)); s :=Normalisasi(BuatVektor(xr,yr,zr)); u :=BuatVektor(xr,0,zr); if PanjangVektor(u)=0 then betha:=0 //Sumbu putar berhimpit dengan sumbu Y else begin u:=normalisasi(u); betha:=arcCos(DotProduct(u1,u)); if u.posZ<0 then betha:=-betha; end;
alpha:=arcCos(DotProduct(u2,s));
ryb[0,0]:=cos(betha);ryb[0,2]:=-sin(betha); ryb[2,0]:=sin(betha);ryb[2,2]:=cos(betha); //Ry(-betha)
38
perkalianMatriks(Matriks,ryb,Matriks);
rza[0,0]:=cos(alpha);rza[0,1]:=sin(alpha); rza[1,0]:=-sin(alpha);rza[1,1]:=cos(alpha); //Ry(-betha)*Rz(-alpha) PerkalianMatriks(MAtriks,rza,Matriks);
ry[0,0]:=cos(radian);ry[0,2]:=-sin(radian); ry[2,0]:=sin(radian);ry[2,2]:=cos(radian); //Ry(Degree) PerkalianMatriks(Matriks,ry,Matriks);
rza_1[0,0]:=cos(-alpha);rza_1[0,1]:=sin(-alpha); rza_1[1,0]:=-sin(-alpha);rza_1[1,1]:=cos(-alpha); //Rz(degree) PerkalianMAtriks(Matriks,rza_1,MAtriks);
ryb_1[0,0]:=cos(-betha);ryb_1[0,2]:=-sin(-betha); ryb_1[2,0]:=sin(-betha);ryb_1[2,2]:=cos(-betha); //Ry(betha) PerkalianMatriks(Matriks,ryb_1,MAtriks); end;
f. Shearing Persamaan transformasi shearing yang terdapat pada persamaan 2.9, 2.10, dan 2.11 dibuat ke dalam bentuk prosedur shearing di bawah ini. Prosedur ini digunakan untuk melakukan shearing pada suatu titik dengan sumbu sumbu, nilai referensi ref, dan nilai shearing shear. Procedure TTransformasi.Shearing(sumbu:integer;ref,shear1,shear2:real ); var matriksShearing:Matriks4x4; begin MatriksIdentitas(matriksShearing); if sumbu=1 then begin matriksShearing[3,1]:=-shear1*ref; matriksShearing[3,2]:=-shear2*ref;
39
matriksShearing[0,1]:=shear1; matriksShearing[0,2]:=shear2; end; if sumbu=2 then begin matriksShearing[3,0]:=-shear1*ref; matriksShearing[3,2]:=-shear2*ref; matriksShearing[1,0]:=shear1; matriksShearing[1,2]:=shear2; end; if sumbu=3 then begin matriksShearing[3,0]:=-shear1*ref; matriksShearing[3,1]:=-shear2*ref; matriksShearing[2,0]:=shear1; matriksShearing[2,1]:=shear2; end; PerkalianMatriks(Matriks,matriksShearing,Matriks); end;
g. Matriks Transformasi Operasi matriks transformasi digunakan untuk mengalikan suatu titik 3 dimensi
dengan
matriks
transformasi
sehingga
diperoleh
titik
hasil
transformasinya. Operasi ini dinyatakan dalam bentuk prosedur Transform. procedure TTransformasi.Transform(P:Ttitik3d; var Q:Ttitik3d); begin Q.posX:=P.posX*Matriks[0,0]+P.posY*Matriks[1,0]+ P.posZ*MAtriks[2,0]+1*Matriks[3,0]; Q.posY:=P.posX*Matriks[0,1]+P.posY*Matriks[1,1]+ P.posZ*MAtriks[2,1]+1*Matriks[3,1]; Q.posZ:=P.posX*Matriks[0,2]+P.posY*Matriks[1,2]+ P.posZ*MAtriks[2,2]+1*Matriks[3,2]; end;
4.1.5. Implementasi Transformasi Menggunakan Mouse Konversi koordinat 2 dimensi layar ke koordinat 3 dimensi OpenGL dilakukan oleh kelas Ttransformasi melalui prosedur ambilPos3d(X,Y:integer;
40
var titik:TArTitik3D). Procedure TTransformasi.ambilPos3d(X,Y:integer; var titik:TArTitik3D); var viewport : array[1..4]
of Integer;
modelview: array[1..16] of Double; proyeksi : array[1..16] of Double; winZ
: Single;
begin glGetDoublev(GL_MODELVIEW_MATRIX, @modelview); glGetDoublev(GL_PROJECTION_MATRIX,@proyeksi); glGetIntegerv(GL_VIEWPORT,@viewport); if Y=0 then Y:=1; glReadPixels(X,-Y,1,1,GL_DEPTH_COMPONENT,GL_FLOAT,@winZ); gluUnProject(X,viewport[4]Y,winZ,@modelview, @proyeksi,@viewport,titik[1],titik[2],titik[3]); end;
Nilai koordinat yang diperoleh pada variabel titik akan digunakan untuk transformasi 3 dimensi menggunakan mouse. Transformasi dengan mouse dilakukan dengan menggunakan 3 prosedur dari
kelas
Tform,
yaitu
Panel1MouseDown,
Panel1MouseMove,
dan
Panel1MouseUp. Pada prosedur Panel1MouseDown, membuat variabel mouse Turun menjadi true agar transformasi pada prosedur Panel1MouseMode dapat dilakukan. Pada saat mouse bergerak, koordinat 2 dimensi layar dan 3 dimensi OpenGL diambil dengan perintah berikut: Transform.ambilPos3d(X,Y,titikPro3D); dx:=titikPro3D[1]-awalX; dy:=titikPro3D[2]-awalY; dz:=titikPro3D[3]-awalZ; deltaX:=X-X2; deltaY:=Y-Y2;
Variabel X dan Y di atas diambil dari prosedur TFormUtama.Panel1MouseMove (Sender:
TObject;
Shift:
TShiftState;X,
Y:
Integer).
Selanjutnya
prosedur akan melakukan transformasi. Kode program untuk melakukan transformasi dapat dilihat pada lampiran A. Pada akhir prosedur ini dilakukan memberikan nilai posisi mouse sekarang ke poisisi mouse awal. X2:=X; Y2:=Y;
41
awalX:=titikPro3d[1]; awalY:=titikPro3d[2]; awalZ:=titikPro3d[3];
Pada prosedur Panel1MouseUp variabel mouseTurun dibuat menjadi false agar transformasi menggunakan mouse menjadi tidak aktif. 4.1.6. Implementasi Benda Rumit Aplikasi ini juga dapat menampilkan objek rumit, yaitu dengan memuat berkas berektensi obj dan menampilkan objeknya pada layar. Untuk memuat berkas berkestensi obj, penulis menggunakan berkas kode program yang dibuat oleh Jan Horn[7]. Penggunaannya cukup dengan menambahkan klausa OBJLoader pada bagian uses (berkas OBJLoader ada pada direktori yang sama dengan aplikasi). Berkas ini berfungsi seperti kodek yang membaca isi berkas obj dan menterjemahkannya ke OpenGL. Dalam mengimplementasikan Obj Loader, penyusun membuat kelas baru yang merupakan turunan dari kelas Tgeometri. Kodenya dapat dilihat seperti di bawah ini: TOBJLoader = class(Tgeometri) private titikMin,titikMax:Ttitik3d; procedure hitungMinMax(i:integer); procedure gambarKotak; public m:Tmodel; berkas:string; constructor create(fileObj:string); procedure Gambar;override; end;
Pada saat objek dari kelas TOBJLoader diciptakan melalui konstruktor, berkas dimuat dengan perintah m:=LoadModel(berkas). Objek tersebut di simpan ke variabel m. Constructor TOBJLoader.create(fileObj:string); var i:integer; begin berkas:=fileObj; m:=LoadModel(berkas);
42
. . . End;
Untuk memgambar objek yang terdapat pada variabel m cukup dengan menggunakan
perintah
DrawModel(m)
yang
terdapat
pada
prosedur
TOBJLoader.Gambar. procedure TOBJLoader.Gambar; var i:integer; begin . . . DrawModel(m); . . . end;
Semua fungsi-fungsi di atas dilakukan pada saat tombol gambar (sButton4) pada tab OBJ Loader ditekan. Kodenya seperti di bawah ini: procedure TFormUtama.sButton4Click(Sender: TObject); Var ObjekBaru:Tgeometri; begin if sOpenDialog1.execute then begin ObjekBaru:=nil; ObjekBaru:=TOBJLoader.create(sOpenDialog1.FileName); DaftarGeometri.TambahGeometri(ObjekBaru); end; end;
Hasil dari implentasi obj loader dapat dilihat pada gambar 4.10.
Gambar 4.10a Objek mobil dan bola menggunakan obj loader pada posisi awal.
43
Gambar 4.10b Objek mobil dan bola menggunakan obj loader pada posisi setelah rotasi (-30o, 0, 1, 0).
Objek bola dan mobil dimuat menggunakan obj loader (gambar 4.10a). Objek bola dan mobil masing-masing terdiri dari 1761 dan 233 verteks, jauh lebih banyak dibandingkan kubus yang hanya memiliki 9 verteks. Keduanya kemudian di rotasi sebesar -30o dengan sumbu putar Y dan hasilnya dapat dilihat pada gambar 4.10b. 4.2. Pengujian Validasi Fungsi Transformasi Aplikasi Pada subbab ini, transformasi-transformasi 3D pada aplikasi diuji. Pengujian dilakukan dengan membandingkan hasil transformasi aplikasi dengan hasil transformasi menggunakan perhitungan. Pengujian dilakukan pada objek geometri piramida yang memiliki 7 titik. Gambar 4.11 menunjukkan posisi awal piramida ketika dibuat pada aplikasi.
Gambar 4.11 Posisi awal piramida pada layar aplikasi.
44
Titik-titik penyusun piramida kemudian dibuat dalam bentuk tabel 4.1. Tabel 4.1 Koordinat awal titik-titik piramida. Titik
Koordinat Awal
0 1 2 3 4 5 6
0,00 0,00 0,00 0,00 0,50 0,00 -0,50 -0,50 0,50 0,50 -0,50 0,50 0,50 -0,50 -0,50 -0,50 -0,50 -0,50 -0,50 -0,50 0,50
4.2.1. Pengujian Transformasi Translasi Keadaan awal piramida seperti yang ditunjukkan pada gambar 4.12 dan tabel 4.1 akan ditranslasikan dengan tx=1, ty=1, dan tz=-1 (gambar4.11).
Gambar 4.11 Form untuk memasukkan nilai translasi.
Hasil yang diperoleh pada layar aplikasi seperti gambar 4.13 dengan koordinat baru pada tabel 4.2.
(a)
(b)
Gambar 4.13 Piramida: (a) sebelum translasi (1, 1, -1); (b) sesudah translasi (1, 1, -1).
45
a. Contoh Perhitungan Sebagai contoh perhitungan digunakan titik 2 pada piramida. Titik 2 memiliki koordinat awal (-0,50, -0,50, 0,50) ditranslasikan sebesar (1,00 1,00 1,00). Dengan menggunakan persamaan 2.3, 2.4, dan 2.5 maka:
[x '
y ' z ' 1] = [x
[
y
1 0 z 1] ⋅ 0 t x
0
0
1
0
0
1
ty
tz
]
[x '
y ' z ' 1] = x + t x
[x '
1 0 y ' z ' 1] = [− 0,5 − 0,5 0,5 1]⋅ 0 1
[x ' [x '
y + ty
0 0 0 1
z + tz 1
0 1 0 0 0 1 0 1 − 1 1 y ' z ' 1] = [− 0,5 + 1 − 0,5 + 1 0,5 + (−1) 1] 0
0
y ' z ' 1] = [0,5 0,5 − 0,5 1]
Dengan cara perhitungan yang sama, untuk titik-titik piramida yang lain, titik-titik hasil translasinya dapat dilihat pada tabel 4.3.
b. Perbandingan antara hasil perhitungan dan hasil aplikasi Perbandingan antara hasil perhitungan dan hasil aplikasi dapat dilihat pada tabel 4.2. Hasil yang ditunjukkan aplikasi sama dengan hasil perhitungan. Ini menandakan aplikasi dapat melakukan translasi dengan tepat. Tabel 4.2. Perbandingan antara hasil perhitungan dan hasil aplikasi untuk translasi (1,00, 1,00, -1,00);
Titik 0 1 2 3 4 5 6
Koordinat Awal 0,00 0,00 0,00 0,00 0,50 0,00 -0,50 -0,50 0,50 0,50 -0,50 0,50 0,50 -0,50 -0,50 -0,50 -0,50 -0,50 -0,50 -0,50 0,50
Hasil Transformasi Aplikasi Perhitungan 1,00 1,00 -1,00 1,00 1,00 -1,00 1,00 1,50 -1,00 1,00 1,50 -1,00 0,50 0,50 -0,50 0,50 0,50 -0,50 1,50 0,50 -0,50 1,50 0,50 -0,50 1,50 0,50 -1,50 1,50 0,50 -1,50 0,50 0,50 -1,50 0,50 0,50 -1,50 0,50 0,50 -0,50 0,50 0,50 -0,50
4.2.2. Pengujian Transformasi Penskalaan Keadaan awal piramida seperti yang ditunjukkan pada gambar 4.11 dan
46
tabel 4.1 akan diskalakan dengan sx=2, sy=2, dan sz=2 (gambar 4.15).
Gambar 4.15 Form untuk memasukkan nilai penskalaan.
Hasil yang diperoleh pada layar aplikasi seperti gambar 4.16 dengan koordinat baru pada tabel 4.3.
(a)
(b)
Gambar 4.16 Piramida: (a) sebelum penskalaan (2, 2, 2); (b) sesudah penskalaan (2, 2, 2).
a. Contoh Perhitungan Sebagai contoh perhitungan digunakan titik 2 pada piramida. Titik 2 memiliki koordinat awal (-0,50, -0,50, 0,50) diskalakan sebesar (2,00, 2,00, 2,00). Dengan menggunakan persamaan 2.8 maka:
[x '
y ' z ' 1] = [x
[x '
y ' z ' 1] = x ⋅ s x
[
y
sx 0 z 1]⋅ 0 0 y ⋅ sy
0 sy 0 0
]
z ⋅ sz 1
0 0 sz 0
0 0 0 1
47
[x ' [x ' [x '
2 0 y ' z ' 1] = [−,5 − 0,5 0,5 1]⋅ 0 0
0 0 0 2 0 0 0 2 0 0 0 1 y ' z ' 1] = [− 0,5 ⋅ 2 − 0,5 ⋅ 2 0,5 ⋅ 2 1] y ' z ' 1] = [− 1 − 1 1 1]
Dengan cara perhitungan yang sama, untuk titik-titik piramida yang lain, titik-titik hasil penskalaannya dapat dilihat pada tabel 4.3.
b. Perbandingan antara hasil perhitungan dan hasil aplikasi Perbandingan antara hasil perhitungan dan hasil aplikasi dapat dilihat pada tabel 4.3. Hasil yang ditunjukkan aplikasi sama dengan hasil perhitungan. Ini menandakan aplikasi dapat melakukan penskalaan dengan tepat. Tabel 4.3. Perbandingan antara hasil perhitungan dan hasil aplikasi untuk transformasi penskalaan (2,00 2,00 2,00);
Titik 0 1 2 3 4 5 6
Hasil Transformasi Koordinat Awal Aplikasi Perhitungan 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,50 0,00 0,00 1,00 0,00 0,00 1,00 0,00 -0,50 -0,50 0,50 -1,00 -1,00 1,00 -1,00 -1,00 1,00 0,50 -0,50 0,50 1,00 -1,00 1,00 1,00 -1,00 1,00 0,50 -0,50 -0,50 1,00 -1,00 -1,00 1,00 -1,00 -1,00 -0,50 -0,50 -0,50 -1,00 -1,00 -1,00 -1,00 -1,00 -1,00 -0,50 -0,50 0,50 -1,00 -1,00 1,00 -1,00 -1,00 1,00
4.2.3. Pengujian Transformasi Rotasi Keadaan awal piramida seperti yang ditunjukkan pada gambar 4.11 dan tabel 4.1 akan dirotasikan dengan sudut putar sebesar 30o dan sumbu putar ry=1 (gambar 4.17).
Gambar 4.17 Form untuk memasukkan nilai rotasi.
48
Hasil yang diperoleh pada layar aplikasi seperti gambar 4.18 dengan koordinat baru pada tabel 4.4.
(a)
(b)
Gambar 4.18 Piramida: (a) sebelum rotasi
(30o,
0,00, 1,00, 0,00);
(b) sesudah rotasi (30o, 0,00, 1,00m 0,00).
a. Contoh Perhitungan Sebagai contoh perhitungan digunakan titik 2 pada piramida. Titik 2 memiliki koordinat awal (-0,50, -0,50, 0,50) dirotasikan dengan sudut 30o dan sumbu ry=1. Dengan menggunakan persamaan 2.11, maka yang pertama dilakukan adalah menghitung panjang vektor koordinat awal.
s = ( x2 − x1
y 2 − y1
z 2 − z1 )
s = (0 − 0 1 − 0 0 − 0) s = (0 1 0 )
Langkah kedua adalah vektor s diubah menjadi unit vektor dengan membagi vektor dengan panjang absolut vektor. s =
xr + y r + z r
s =
0 2 + 12 + 0 2
2
2
2
s =1 x yr z r s = r s s s 0 1 0 s= 1 1 1 s = (0 1 0 )
Langkah ketiga adalah mencari besar sudut alpha (α) yang dibentuk oleh vektor s
49
dan u2 (vektor searah sumbu y positif).
u 2 = 0 2 + 12 + 0 2 = 1
(0
1 0) = (0 1 0 ) 1 α = arccos( u 2 • s ) u2 =
α = arccos ((0 1 0 ) • (0 1 0 )) α = arccos(1) α = 00
Langkah keempat adalah mencari besar sudut betha (β) yang dibentuk oleh vektor u (x, 0, z) dan u1 (vektor searah sumbu x positif).
u1 = 12 + 0 2 + 0 2 = 1
(1
u1 =
0 0) = (1 0 0 ) 1
u = 02 + 02 + 02 = 0
0 0) = (~ ~ ~ ) 0 β = arccos(u1 • u )
u=
(0
β = arccos((1 0 0) • (~ ~ ~ )) β = arccos(~)
Karena vektor u bernilai 0 maka sudut β yang dibentuk oleh vektor u dan u1 bernilai 0o. Langkah kelima adalah memutar titik pada sumbu Y sehingga terletak di bidang XY. Cos ( β ) 0 z 1] ⋅ Sin( β ) 0
0 − Sin( β ) 1 0 0 Cos ( β ) 0 0
[x '
y ' z ' 1] = [x
[x '
Cos (0 0 ) 0 y ' z ' 1] = [− 0,5 − 0,5 0,5 1] ⋅ Sin(00 ) 0
y
0 0 0 1
0 − Sin(0 0 ) 1 0 0 Cos (0 0 ) 0 0
0 0 0 1
50
[x ' [x '
1 0 y ' z ' 1] = [− 0,5 − 0,5 0,5 1]* 0 0 y ' z ' 1] = [− 0,5 − 0,5 0,5 1]
0 0 0 1 0 0 0 1 0 0 0 1
Langkah keenam adalah memutar titik pada sumbu z sehingga terletak di bidang di sumbu y. Cos (α ) Sin(α ) − Sin(α ) Cos (α ) z 1] ⋅ 0 0 0 0
0 0 0 0 1 0 0 1
[x '
y ' z ' 1] = [x
[x '
Cos (0 0 ) Sin(0 0 ) − Sin(0 0 ) Cos (0 0 ) y ' z ' 1] = [− 0,5 − 0,5 0,5 1] ⋅ 0 0 0 0
[x ' [x '
y
1 0 y ' z ' 1] = [− 0,5 − 0,5 0,5 1] ⋅ 0 0 y ' z ' 1] = [− 0,5 − 0,5 0,5 1]
0 0 0 0 1 0 0 1
0 0 0 1 0 0 0 1 0 0 0 1
Langkah keenam adalah memutar titik pada sumbu z sebesar sudut yang ditentukan untuk transformasi rotasi. Cos (θ ) 0 z 1] ⋅ Sin(θ ) 0
0 − Sin(θ ) 0 1 0 0 0 Cos (θ ) 0 0 0 1
[x '
y ' z ' 1] = [x
[x '
Cos (30 0 ) 0 y ' z ' 1] = [− 0,5 − 0,5 0,5 1] ⋅ Sin(30 0 ) 0
y
0 − Sin(30 0 ) 1 0 0 Cos (30 0 ) 0 0
0 0 0 1
51
[x ' [x '
0,866 0 y ' z ' 1] = [− 0,5 − 0,5 0,5 1] ⋅ 0,5 0 y ' z ' 1] = [0,183 − 0,5 0,683 1]
− 0,5 0
0 0 0 0,866 0 0 0 1
0 1
Langkah ketujuh adalah memutar balik titik sebesar –α pada sumbu Z. Cos (−α ) Sin(−α ) − Sin(−α ) Cos (−α ) z 1] ⋅ 0 0 0 0
0 0 0 1
0 0 1 0
[x '
y ' z ' 1] = [x
[x '
Cos (−0 0 ) Sin(−0 0 ) − Sin(−0 0 ) Cos (−0 0 ) y ' z ' 1] = [− 0,183 − 0,5 0,683 1] ⋅ 0 0 0 0
[x ' [x '
y
1 0 y ' z ' 1] = [− 0,183 − 0,5 0,683 1] ⋅ 0 0 y ' z ' 1] = [− 0,183 − 0,5 0,683 1]
0 0 0 0 1 0 0 1
0 0 0 1 0 0 0 1 0 0 0 1
Langkah kedelapan adalah memutar balik titik sebesar –β pada sumbu Y. Cos (− β ) 0 z 1] ⋅ Sin(− β ) 0
0 − Sin(− β ) 0 1 0 0 0 Cos (− β ) 0 0 0 1
[x '
y ' z ' 1] = [x
[x '
Cos (−0 0 ) 0 y ' z ' 1] = [− 0,183 − 0,5 0,683 1] ⋅ Sin(−0 0 ) 0
[x ' [x '
y
1 0 y ' z ' 1] = [− 0,183 − 0,5 0,683 1] ⋅ 0 0 y ' z ' 1] = [− 0,183 − 0,5 0,683 1]
0 − Sin(−0 0 ) 0 1 0 0 0 Cos (−0 0 ) 0 0 0 1
0 0 0 1 0 0 0 1 0 0 0 1
52
Dengan cara perhitungan yang sama, untuk titik-titik piramida yang lain, titik-titik hasil penskalaannya dapat dilihat pada tabel 4.4. b. Perbandingan antara hasil perhitungan dan hasil aplikasi Perbandingan antara hasil perhitungan dan hasil aplikasi dapat dilihat pada tabel 4.4. Hasil yang ditunjukkan aplikasi sama dengan hasil perhitungan. Ini menunjukkan aplikasi dapat melakukan rotasi dengan tepat. Tabel 4.4. Perbandingan antara hasil perhitungan dan hasil aplikasi untuk transformasi rotasi (30o 0,00 1,00 0,00).
Titik 0 1 2 3 4 5 6
Hasil Transformasi Koordinat Awal Aplikasi Perhitungan 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,50 0,00 0,00 0,50 0,00 0,00 0,50 0,00 -0,50 -0,50 0,50 -0,18 -0,50 0,68 -0,18 -0,50 0,68 0,50 -0,50 0,50 0,68 -0,50 0,18 0,68 -0,50 0,18 0,50 -0,50 -0,50 0,18 -0,50 -0,68 0,18 -0,50 -0,68 -0,50 -0,50 -0,50 -0,68 -0,50 -0,18 -0,68 -0,50 -0,18 -0,50 -0,50 0,50 -0,18 -0,50 0,68 -0,18 -0,50 0,68
4.2.4. Pengujian Transformasi Shearing Keadaan awal piramida seperti yang ditunjukkan pada gambar 4.11 dan tabel 4.1 akan dilakukan shearing dengan sumbu X, faktor shearing 1,00, dan titik referensi di X=1,00. (gambar 4.19).
Gambar 4.19 Form untuk memasukkan nilai shearing.
Hasil yang diperoleh pada layar aplikasi seperti gambar 4.20 dengan koordinat baru pada tabel 4.5.
53
(a)
(b)
Gambar 4.20 Piramida: (a) sebelum shearing (X 1,00 1,00); (b) sesudah shearing (X 1,00 1,00).
a. Contoh Perhitungan Sebagai contoh perhitungan digunakan titik 2 pada piramida. Titik 2 memiliki koordinat awal (-0,50 -0,50 0,50) dilakukan shearing dengan (X 1,00 1,00). Karena menggunakan sumbu X sebagai sumbu shearing maka persamaan yang digunakan adalah persamaan 2.15 (untuk sumbu lain persamaan yang digunakan menyesuaikan). Dengan demikian:
Shxy 1 0 1 z 1] ⋅ 0 0 0 − Shxy ⋅ X ref
Shxz 0 1 − Shxz ⋅ X ref
[x '
y ' z ' 1] = [x
[x '
1 1 1 0 1 0 y ' z ' 1] = [− 0,5 − 0,5 0,5 1] ⋅ 0 0 1 0 − 1 ⋅ 1 − 1 ⋅ 1
[x '
y
y ' z ' 1] = [− 0,5 − 2,0 − 1,0 1]
0 0 0 1
0 0 0 1
Dengan cara perhitungan yang sama, untuk titik-titik piramida yang lain, titik-titik hasil shearing-nya dapat dilihat pada tabel 4.5. b. Perbandingan antara hasil perhitungan dan hasil aplikasi Perbandingan antara hasil perhitungan dan hasil aplikasi dapat dilihat pada tabel 4.5. Hasil yang ditunjukkan aplikasi sama dengan hasil perhitungan. Ini menandakan aplikasi dapat melakukan shearing dengan tepat.
54
Tabel 4.5 Perbandingan antara hasil perhitungan dan hasil aplikasi untuk transformasi shearing (X 1,00 1,00).
Titik 0 1 2 3 4 5 6
Hasil Transformasi Koordinat Awal Aplikasi Perhitungan 0,00 0,00 0,00 0,00 -1,00 -1,00 0,00 -1,00 -1,00 0,00 0,50 0,00 0,00 -0,50 -1,00 0,00 -0,50 -1,00 -0,50 -0,50 0,50 -0,50 -2,00 -1,00 -0,50 -2,00 -1,00 0,50 -0,50 0,50 0,50 -1,00 0,00 0,50 -1,00 0,00 0,50 -0,50 -0,50 0,50 -1,00 -1,00 0,50 -1,00 -1,00 -0,50 -0,50 -0,50 -0,50 -2,00 -2,00 -0,50 -2,00 -2,00 -0,50 -0,50 0,50 -0,50 -2,00 -2,00 -0,50 -2,00 -2,00
Dari semua pengujian yang dilakukan, hasil pengujian aplikasi dan perhitungan menunjukkan kesamaan. Jika hanya dari hasil tersebut, dapat dikatakan bahwa aplikasi dapat menjalankan fungsi-fungsi transformasi dengan tepat. 4.3. Pengujian Framerate Selain pengujian validasi fungsi transformasi aplikasi, pengujian juga dilakukan dengan membandingkan framerate hasil aplikasi tugas akhir dengan framerate yang dihasilkan aplikasi yang menggunakan fungsi transformasi OpenGL. Tujuan pengujian ini adalah untuk mengetahui kecepatan transformasi aplikasi dengan transformasi bawaan OpenGL. Pengujian dilakukan pada komputer dengan spesifikasi berikut: prosesor AMD Athlon +2500 1,8 GHz, RAM 512 MB, motherboard ECS N2U400-A, dan kartu VGA GeForce FX 5700 128 MB AGP 8X. Framerate adalah banyaknya gambar yang ditampilkan oleh aplikasi dalam waktu satu detik. Makin tinggi framerate maka pergerakan gambar yang ditampilkan makin halus. Dengan menggunakan spesifikasi komputer yang disebutkan sebelumnya, framerate gambar polos tanpa objek yang dapat ditampilkan adalah 60 FPS (frame per second). Gambar dibuat tiap kali aplikasi berada dalam kondisi idle, yaitu kondisi di mana aplikasi menunggu atau tanpa beban matematis. Jika framerate 60 FPS berarti aplikasi menggambar sebanyak 60 kali per detik pada saat aplikasi idle. Perintah Application.OnIdle := Idle digunakan agar aplikasi menggambar pada saat aplikasi idle.
55
procedure TFormUtama.FormCreate(Sender: TObject); var . . .; begin . . . // when the app has spare time, render the GL scene Application.OnIdle := Idle; . . . end;
Kode di bawah merupakan prosedur yang dieksekusi pada saat aplikasi idle. Di dalam prosedur tersebut terdapar prosedur untuk menggambar dan meampilkan scene, yaitu glDraw() dan SwapBuffers(DC). procedure TFormUtama.Idle(Sender: TObject; var Done: Boolean); begin . . . glDraw();
// Draw the scene
SwapBuffers(DC);
// Display the scene
. . . end;
Nilai framerate berkaitan erat dengan beban matematis. Jika beban matematis ditambah seperti menjalankan operasi translasi, rotasi, atau penskalaan maka komputer harus mengerjakan beban matematis itu terlebih dahulu lalu menggambarkan hasilnya. Akibatnya jika beban matematisnya berat atau banyak maka jumlah gambar yang dapat dibuat dalam satu detik akan menurun sehingga mengakibatkan terjadinya penurunan framerate. Pada akhirnya pergerakan gambar yang ditampilkan menjadi tidak halus. Dua aplikasi berbeda dipakai pada saat pengujian. Aplikasi pertama (gambar 4.21a) menggunakan fungsi transformasi buatan sendiri dan aplikasi kedua (gambar 4.21b) menggunakan fungsi transformasi bawaan OpenGL. Pengujian dilakukan hanya pada transformasi rotasi, translasi, dan penskalaan sedangkan shearing tidak dilakukan karena OpenGL tidak memiliki fungsi transformasi shearing. Gambar 4.21 menunjukkan gambar pengujian framerate pada pengujian transformasi penskaalan untuk 3 objek potatohead. Perhatikan bagian gambar 4.21a dan bagian 4.21b. Di situ ditampilkan framerate aplikasi.
56
(a)
(b) Gambar 2.21 Pengujian framerate untuk penskalaan: (a) aplikasi menggunakan fungsi transformasi buatan sendiri dan (b) aplikasi menggunakan fungsi transformasi bawaan OpenGL.
4.3.1. Pengujian Framerate Rotasi Pengujian framerate rotasi dilakukan dengan menguji framerate pada saat objek dirotasi dengan sudut 1o pada sumbu Y secara terus-menerus. Hasilnya dapat dilihat pada tabel 4.6.
57
Tabel 4.6 Perbandingan framerate transformasi aplikasi dan OpenGL untuk transformasi rotasi. No.
Gambar
Jumlah Verteks
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
1 kursi 2 bola 110 kursi 120 kursi 4 bola 1 potatohead 200 kursi 250 Meja 2 potatohead 3 potatohead 4 potatohead 5 potatohead
48 3522 5390 5880 7044 8576 9800 10250 17152 25728 34304 42880
Framerate (FPS) Aplikasi OpenGL Selisih 60 60 0 59 60 1 50 60 10 47 60 13 43 60 17 37 60 23 30 60 30 20 60 40 18 60 42 12 59 48 9 45 36 6 30 24
Hasil (tabel 4.6) menunjukkan aplikasi mengalami penurunan framerate pada saat jumlah verteks 3522 (No.2) sedangkan OpenGL mengalami penurunan framerate pada saat jumlah verteks 25728 (No. 10). Ini menunjukkan bahwa fungsi transformasi OpenGL lebih stabil dibandingkan fungsi transformasi aplikasi. Tabel 4.6 juga memperlihatkan bahwa tiap data pengujian nilai framerate transformasi OpenGL hampir selalu lebih tinggi daripada framerate transformasi aplikasi. Ini menunjukkan transformasi rotasi OpenGL lebih cepat dibandingkan transformasi rotasi aplikasi. 4.3.2. Pengujian Framerate Translasi Pengujian framerate translasi dilakukan dengan menguji framerate pada saat objek dari z=0 ke z=-3 lalu kembali lagi ke z=0, balik lagi ke z=-3, dan seterusnya. Tiap frame-nya objek dipindah sejauh 0,01. Hasilnya dapat dilihat pada tabel 4.7. Tabel 4.7 Perbandingan framerate transformasi aplikasi dan OpenGL untuk transformasi translasi. No.
Gambar
Jumlah Verteks
1. 2. 3. 4. 5. 6.
1 kursi 2 bola 110 kursi 120 kursi 4 bola 1 potatohead
48 3522 5390 5880 7044 8576
Framerate (FPS) Aplikasi OpenGL Selisih 60 60 0 60 60 0 60 60 0 60 60 0 60 60 0 60 60 0
58
No.
Gambar
Jumlah Verteks
7. 8. 9. 10. 11. 12.
200 kursi 250 Meja 2 potatohead 3 potatohead 4 potatohead 5 potatohead
9800 10250 17152 25728 34304 42880
Framerate (FPS) Aplikasi OpenGL Selisih 60 60 0 60 60 0 59 60 1 40 60 10 31 46 15 27 30 3
Hasil (tabel 4.7) menunjukkan aplikasi mengalami penurunan framerate pada saat jumlah verteks 17152 (No.9) sedangkan OpenGL mengalami penurunan framerate pada saat jumlah verteks 25728 (No. 10). Ini menunjukkan bahwa fungsi transformasi OpenGL lebih stabil dibandingkan fungsi transformasi aplikasi. Tabel 4.7 juga memperlihatkan bahwa mulai data no. 9 pengujian nilai framerate transformasi OpenGL lebih tinggi daripada framerate transformasi aplikasi. Ini menunjukkan transformasi rotasi OpenGL lebih cepat dibandingkan transformasi translasi aplikasi jika jumlah verteksnya dari 17152 ke atas. 4.3.3. Pengujian Framerate Penskalaan Pengujian framerate penskalaan dilakukan dengan menguji framerate pada saat objek diskalakan dari skala=1 ke skala=4, lalu kembali lagi ke skala=1, kembali lagi ke skala=4, dan seterusnya. Tiap framenya, skala objek ditambah atau dikurangi 0,01. Hasilnya dapat dilihat pada tabel 4.8. Tabel 4.8 Perbandingan framerate transformasi aplikasi dan OpenGL untuk transformasi penskalaan. No.
Gambar
Jumlah Verteks
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
1 kursi 2 bola 110 kursi 120 kursi 4 bola 1 potatohead 200 kursi 250 Meja 2 potatohead 3 potatohead 4 potatohead 5 potatohead
48 3522 5390 5880 7044 8576 9800 10250 17152 25728 34304 42880
Framerate (FPS) Aplikasi OpenGL Selisih 60 60 0 60 60 0 30 60 30 20 60 40 50 60 10 60 60 0 15 60 45 15 60 45 41 60 19 27 60 33 17 45 43 15 30 15
Hasil (tabel 4.8) menunjukkan pada transformasi penskalaan aplikasi terjadi naik turun atau ketidakstabilan penurunan framerate seiring dengan pertambahan
59
jumlah verteks sedangkan pada OpenGL framerate mengalami penurunan pada saat jumlah verteks 25728 (No. 10). Ini menunjukkan bahwa fungsi transformasi OpenGL lebih stabil dibandingkan fungsi transformasi aplikasi. Tabel 4.8 juga memperlihatkan bahwa hampir semua data pengujian nilai framerate transformasi OpenGL lebih tinggi daripada framerate transformasi aplikasi. Ini menunjukkan transformasi rotasi OpenGL lebih cepat dibandingkan transformasi penskalaan aplikasi. 4.3.4. Perbandingan Framerate Transformasi Aplikasi dan OpenGL Pada subbab ini akan dilakukan perbadingan secara keseluruhan ketiga transformasi tersebut, yaitu perbandingan antara jumlah verteks dengan framerate dan pengaruh jenis transformasi dengan framerate. Hasilnya dapat dilihat pada tabel 4.9. Tabel 4.9 Perbandingan framerate ransformasi aplikasi dan OpenGL. No.
Gambar
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
1 kursi 2 bola 110 kursi 120 kursi 4 bola 1 potatohead 200 kursi 250 Meja 2 potatohead 3 potatohead 4 potatohead 5 potatohead
Jumlah Verteks
48 3522 5390 5880 7044 8576 9800 10250 17152 25728 34304 42880 Total =
Rotasi Aplikasi OpenGL
60 59 50 47 43 37 30 20 18 12 9 6 391
60 60 60 60 60 60 60 60 60 59 45 30 674
Framerate (FPS) Translasi Aplikasi OpenGL
60 60 60 60 60 60 60 60 59 40 31 27 637
60 60 60 60 60 60 60 60 60 60 46 30 676
Penskalaan Aplikasi OpenGL
60 60 30 20 50 60 15 15 41 27 17 15 410
60 60 60 60 60 60 60 60 60 60 45 30 675
Dari ketiga pengujian (tabel 4.9) transformasi aplikasi, dengan melihat jumlah total framerate dari 12 data maka framerate transformasi translasi paling mendekati nilai framerate tranformasi OpenGL, kedua adalah penskalaan, dan ketiga adalah rotasi. Ini disebabkan beban komputasi translasi lebih rendah dibandingkan rotasi dan penskalaan. Mansing-masing tranformasi tersebut memiliki persamaan tersendiri, yaitu: Translasi
: z’ = z + tz
(4.1)
Rotasi
: x’ = x cos(θ) - z sin(θ) dan y = x sin(θ) + z cos(θ)
(4.2)
Penskalaan : x’ = sx · x ,
y’ = sy · y , dan z’ = sz · z
(4.3)
60
Translasi hanya memiliki beban operasi penjumlahan. Ini tentu lebih ringan daripada penskalaan yang memiliki beban operasi perkalian dan rotasi yang memiliki beban mencari nilai kosinus terlebih dahulu lalu melakukan operasi perkalian serta penjumlahan. Jadi, nilai framerate juga bergantung pada jenis transformasi yang digunakan. Tabel 4.9 memperlihatkan bahwa framerate hasil tranformasi dengan OpenGL, untuk jumlah verteks yang banyak, lebih tinggi daripada framerate hasil transformasi aplikasi. Ini menunjukkan bahwa transformasi menggunakan fugnsi bawaan OpenGL lebih cepat daripada fungsi tranformasi yang dibuat pada aplikasi Tugas Akhir. Beban matematis transformasi pada aplikasi banyak dibebankan ke prosesor dan beban matamatis diperkirakan juga mengoptimalkan pemakaian kartu grafis selain pengunaan prosesor. Tabel 4.9 juga memperlihatkan bahwa semakin tinggi jumlah verteks maka semakin rendah pula nilai framerate, baik dari hasil transformasi aplikasi maupun OpenGL. Transformasi dilakukan sekali pada satu verteks. Jika semakin banyak verteks maka semakin banyak transformasi yang dilakukan. Makin banyak transformasi dilakukan akan mengakibatkan turunya nilai framerate. Jadi, jumlah verteks berbanding terbalik dengan nilai framerate.
BAB V KESIMPULAN DAN SARAN
Bab V berisi kesimpulan dan saran. Kesimpulan yang ditulis merupakan halhal penting dan berkesan yang didapat selama pembuatan aplikasi grafika komputer untuk transformasi 3 dimensi. Saran yang diberikan merupakan pengembangan lebih lanjut untuk meningkatkan kualitas aplikasi.
5.1. Kesimpulan 1.
Aplikasi Tugas Akhir memiliki kemampuan melakukan transformasi geometri pada objek-objek 3 dimensi yang dibuat dalam aplikasi.
2.
Transformasi geometri yang dapat dilakukan oleh aplikasi, yaitu translasi, rotasi, penskalaan, dan shearing.
3.
Aplikasi Tugas Akhir memiliki perbedaan dengan OpenGL, yaitu aplikasi memiliki transformasi shearing yang tidak dimiliki oleh OpenGL. Shearing adalah transformasi geometri dimana benda dimiringkan dengan cara menggeser salah satu atau kedua tepi yang saling menghadap menurut titik acuan tertentu.
4.
Transformasi geometri dilakukan dengan pertama-tama mengambil nilai koordinat verteks-verteks objek, lalu mentranformasi nilai verteks-verteks tersebut, kemudian nilai hasil transformasi diberikan kembali ke verteksverteks objek tadi, dan terakhir menggambar ulang objek dengan nilai koordinat verteks yang baru.
5.
Aplikasi Tugas Akhir dapat mentransformasi objek geoemetri melalui penggunaan mouse dan masukan nilai parameter tranformasi. Melalui penggunaan mouse berarti objek ditransformasi berdasarkan perubahan posisi mouse yang dilakukan oleh pengguna. Melalui masukan parameter berarti objek ditransformasi berdasarkan masukan nilai yang dilakukan oleh pengguna melalui form yang disediakan.
61
62
6.
Aplikasi Tugas Akhir dapat membuat objek-objek muai dari yang sederhana seperti piramida yang terdiri dari 6 verteks, kubus (9 verteks), silinder (33 verteks), meja (41 verteks), kursi (48 verteks) hingga memuat objek-objek yang rumit seperti mobil (233 verteks), bola (1761), dan potatohead (8576).
7.
Perbandingan framerate hasil penggunaan fungsi transformasi geometri aplikasi Tugas Akhir lebih rendah daripada framerate hasil penggunaan fungsi transformasi geometri bawaan OpenGL.
8.
Makin banyak verteks yang menyusun suatu objek maka makin lama pula waktu yang dibutuhkan untuk mentranformasi objek secara keseluruhan.
9.
Nilai framerate berbanding terbalik dengan jumlah verteks yang akan ditransformasi dan jumlah operasi matematis pada transformasi yang dilakukan. Makin tinggi jumlah verteks dan operasi matematis makin rendah nilai framerate. Makin rendah jumlah verteks dan operasi matematis makin tinggi nilai framerate.
5.2. Saran 1.
Aplikasi dapat dikembangkan lebih lanjut dengan menambahkan fasilitas pewarnaan (coloring) dan texture mapping sehingga warna suatu objek dapat diubah sesuai kehendak pengguna dan objek memiliki tekstur yang membuat tampilannya menjadi lebih realistis.
2.
Aplikasi dapat dikembangkan lebih lanjut dengan menambahkan fasilitas vertex modifer Dengan verteks modifier bentuk objek geometri dapat diubah dengan
fleksibel.
Verteks-verteks
penyusun
objek
ditransformasi sehingga bentuk objek tersebut berubah.
geometri
dapat
DAFTAR PUSTAKA [1]. Baker, M.P., Hearn, D., Computer Graphics with OpenGL, Third Edition, Prentice Hall, New Jersey, 2004. [2]. Bambang, H., Grafik komputer dengan C, Penerbit ANDI, 2004. [3]. Benstead, L., Using gluUnProject, http://nehe.gamedev.net/, Maret 2006. [4]. Davis, T., Neider, J., dan Woo, M., OpenGL Programming Guide, AddisonWesley Publishing Company, ISBN: 0-201-63274-8. [5]. Dharwiyanti S., Wahono R.S., Pengantar Unified Modelling Language (UML), ilmukomputer.com, 2003. [6]. Fernandes, A.R., Picking Tutorial, http://www.lighthouse3d.com/opengl/, Mei 2006. [7]. Kronberger, M., OpenGL Tutorial, http://www.sulaco.co.za/, Maret 2006. [8]. Maksimchuk, R.A., Naiburg, E.J., UML for Mere Mortals, Addison Wesley Proffesional, October 26th, 2004. [9]. Martz, P., OpenGL® Distilled, Addison Wesley Proffesional, 2004. [10]. Munir, R., Pengolahan Citra Digital dengan Pendekatan Algoritmik, Penerbit Informatika, Bandung, 2004. [11]. Nugroho, Edi., Teori dan Praktek Grafika Komputer Menggunakan Delphi dan OpenGL, Penerbit Graha ilmu, Yogyakarta, 2005. [12]. Nuydens, T., Dot Project, http://www.delphi3d.net/, Maret 2006. [13]. Philips, D., Image Processing in C, Second Edition, R & D Publications, Kansas, 2000. [14]. Pressman, R.S., Rekayasa Perangkat Lunak Pendekatan Praktisi, Buku Satu dan Dua, McGraw-Hil Book Co., Penerbit ANDI, Yogyakarta, 2003. [15]. Susilo, D., Grafika Komputer dengan Delphi, Penerbit Graha ilmu, Yogyakarta, 2005. [16]. ---, 3DS Max Application, http://www.autodesk.com/, Maret 2006. [17]. ---, Blender Application, http://www.blender.org/, Maret 2006. [18]. ---, Delphi Help, Borland Delphi Corporation, 2001. [19]. ---, GLScene Demo, http://www.caperaven.co.za/, Maret 2006. [20]. ---, OpenGL Specification, http://www.opengl.org/, Maret 2006.
63
[21]. ---, Tutorial on UML, Chapter 12, TIMe Electronic Textbook version 4.0, SINTEF, July 16th, 1999. [22]. --, Wavefront OBJ File Format Summary, http://www.fileformat.info/ resource/book/1565921615/index.htm, Agustus 2006. [23]. ---, Win32 Developer’s References, Borland Delphi Corporation, 2001.
64
LAMPIRAN
D
LAMPIRAN A KODE PROGRAM GRAFIKA KOMPUTER UNTUK TRANSFORMASI 3D
PtugasAkhir.dpr program PTugasAkhir; uses Forms, unitUtama in 'unitUtama.pas' {FormUtama}, Geometri in 'Geometri.pas', Transformasi in 'Transformasi.pas', unitTranslasi in 'unitTranslasi.pas' {FormTranslasi}, unitPenskalaan in 'unitPenskalaan.pas' {FormPenskalaan}, unitRotasi in 'unitRotasi.pas' {FormRotasi}, vektor in 'vektor.pas', unitShearing in 'unitShearing.pas' {FormShearing}, unitAbout in 'unitAbout.pas' {FormAbout}; {$R *.res} begin Application.Initialize; Application.Title := 'A-Studio'; Application.CreateForm(TFormUtama, FormUtama); Application.Run; end.
unitUtama.pas unit unitUtama; interface uses GLext,OpenGL,Windows, Messages, SysUtils, Variants, Classes,Graphics,Controls, Forms,Dialogs, ToolWin, ComCtrls, sToolBar, ImgList, Menus,sSkinProvider, sSkinManager, ExtCtrls, sPanel, StdCtrls, sHintManager, sAdapter, sGridAdapter, sMemo, sButton, sEdit, sSpinEdit, sGroupBox, sLabel, sPageControl, sScrollBox, sFrameBar, sComboBox, sStatusBar, Grids,Buttons, ValEdit,Geometri,Transformasi,vektor,OBJloader, sDialogs,Math, ExtDlgs; type TFormUtama = class(TForm) sSkinManager1: TsSkinManager; sSkinProvider1: TsSkinProvider; MainMenu1: TMainMenu; File1: TMenuItem; Help1: TMenuItem; ImageList1: TImageList; sStatusBar1: TsStatusBar; sToolBar1: TsToolBar; Exit1: TMenuItem; ToolButton1: TToolButton; Panel1: TPanel; sGridAdapter1: TsGridAdapter; Button1: TButton;
65
66
sFrameBar1: TsFrameBar; tabObjek: TsPageControl; sTabSheet1: TsTabSheet; sTabSheet2: TsTabSheet; sTabSheet3: TsTabSheet; sTabSheet4: TsTabSheet; About1: TMenuItem; sGroupBox1: TsGroupBox; sLabel1: TsLabel; sLabel2: TsLabel; sLabel3: TsLabel; sDecimalSpinEdit1: TsDecimalSpinEdit; sDecimalSpinEdit2: TsDecimalSpinEdit; sDecimalSpinEdit3: TsDecimalSpinEdit; sLabel4: TsLabel; sLabel5: TsLabel; sDecimalSpinEdit4: TsDecimalSpinEdit; sDecimalSpinEdit5: TsDecimalSpinEdit; sButton1: TsButton; PopupMenu1: TPopupMenu; ransformasi1: TMenuItem; ranslasi1: TMenuItem; Rotasi1: TMenuItem; Penskalaan1: TMenuItem; sGroupBox2: TsGroupBox; sLabel6: TsLabel; sLabel7: TsLabel; sLabel8: TsLabel; sDecimalSpinEdit6: TsDecimalSpinEdit; sDecimalSpinEdit7: TsDecimalSpinEdit; sDecimalSpinEdit8: TsDecimalSpinEdit; sGroupBox3: TsGroupBox; sLabel9: TsLabel; sLabel10: TsLabel; sLabel11: TsLabel; sDecimalSpinEdit9: TsDecimalSpinEdit; sDecimalSpinEdit10: TsDecimalSpinEdit; sDecimalSpinEdit11: TsDecimalSpinEdit; sGroupBox4: TsGroupBox; sLabel12: TsLabel; sLabel13: TsLabel; sLabel14: TsLabel; sDecimalSpinEdit12: TsDecimalSpinEdit; sDecimalSpinEdit13: TsDecimalSpinEdit; sDecimalSpinEdit14: TsDecimalSpinEdit; sGroupBox5: TsGroupBox; sLabel15: TsLabel; sLabel16: TsLabel; sLabel17: TsLabel; sDecimalSpinEdit15: TsDecimalSpinEdit; sDecimalSpinEdit16: TsDecimalSpinEdit; sDecimalSpinEdit17: TsDecimalSpinEdit; sComboBox1: TsComboBox; sLabel18: TsLabel; sLabel19: TsLabel; sLabel20: TsLabel; sDecimalSpinEdit18: TsDecimalSpinEdit; sButton5: TsButton; sLabel21: TsLabel; sLabel22: TsLabel; sDecimalSpinEdit19: TsDecimalSpinEdit; sDecimalSpinEdit20: TsDecimalSpinEdit; sButton7: TsButton; sMemo1: TsMemo; ToolButton7: TToolButton;
67
ToolButton8: TToolButton; ToolButton9: TToolButton; ToolButton10: TToolButton; Hapus1: TMenuItem; sTabSheet5: TsTabSheet; sTabSheet6: TsTabSheet; sGroupBox6: TsGroupBox; sLabel23: TsLabel; sLabel24: TsLabel; sLabel25: TsLabel; sDecimalSpinEdit21: TsDecimalSpinEdit; sDecimalSpinEdit22: TsDecimalSpinEdit; sDecimalSpinEdit23: TsDecimalSpinEdit; sGroupBox7: TsGroupBox; sLabel26: TsLabel; sLabel27: TsLabel; sLabel28: TsLabel; sDecimalSpinEdit24: TsDecimalSpinEdit; sDecimalSpinEdit25: TsDecimalSpinEdit; sDecimalSpinEdit26: TsDecimalSpinEdit; sButton2: TsButton; sButton3: TsButton; sHintManager1: TsHintManager; sComboBox2: TsComboBox; ToolButton14: TToolButton; ToolButton2: TToolButton; ToolButton3: TToolButton; ToolButton4: TToolButton; ToolButton5: TToolButton; ToolButton6: TToolButton; ToolButton11: TToolButton; ToolButton12: TToolButton; Shearing1: TMenuItem; sTabSheet7: TsTabSheet; sButton4: TsButton; sOpenDialog1: TsOpenDialog; ToolButton13: TToolButton; Options1: TMenuItem; ModeWireframe1: TMenuItem; ModeAnimasi1: TMenuItem; ToolButton15: TToolButton; Smooth1: TMenuItem; ransformasi2: TMenuItem; Kamera1: TMenuItem; ranslasi2: TMenuItem; Penskalaan2: TMenuItem; Rotasi2: TMenuItem; Shearing2: TMenuItem; Edit1: TMenuItem; Hapus2: TMenuItem; Zoom1: TMenuItem; RotasiKamera1: TMenuItem; RotasiFokus1: TMenuItem; Geser1: TMenuItem; FokusObjek1: TMenuItem; Reset1: TMenuItem; Timer1: TTimer; Reset2: TMenuItem; Grid1: TMenuItem; sButton6: TsButton; SavePictureDialog1: TSavePictureDialog; SaveAsBMP1: TMenuItem; procedure SaveAsBMP1Click(Sender: TObject); procedure sButton6Click(Sender: TObject);
68
procedure Exit1Click(Sender: TObject); procedure FormResize(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure Panel1Resize(Sender: TObject); procedure FormKeyPress(Sender: TObject; var Key: Char); procedure Panel1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure sButton1Click(Sender: TObject); procedure ranslasi1Click(Sender: TObject); procedure sButton3Click(Sender: TObject); procedure sButton5Click(Sender: TObject); procedure sButton7Click(Sender: TObject); procedure Penskalaan1Click(Sender: TObject); procedure Rotasi1Click(Sender: TObject); procedure Panel1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure Panel1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure sComboBox1Change(Sender: TObject); procedure ToolButton8Click(Sender: TObject); procedure Hapus1Click(Sender: TObject); procedure ToolButton7Click(Sender: TObject); procedure ToolButton9Click(Sender: TObject); procedure sMemo1DblClick(Sender: TObject); procedure sButton2Click(Sender: TObject); procedure ToolButton2Click(Sender: TObject); procedure ToolButton10Click(Sender: TObject); procedure ToolButton3Click(Sender: TObject); procedure ToolButton4Click(Sender: TObject); procedure ToolButton5Click(Sender: TObject); procedure ToolButton6Click(Sender: TObject); procedure Shearing1Click(Sender: TObject); procedure sComboBox2Change(Sender: TObject); procedure sButton4Click(Sender: TObject); procedure ToolButton13Click(Sender: TObject); procedure ToolButton15Click(Sender: TObject); procedure Hapus2Click(Sender: TObject); procedure ranslasi2Click(Sender: TObject); procedure Penskalaan2Click(Sender: TObject); procedure Rotasi2Click(Sender: TObject); procedure Shearing2Click(Sender: TObject); procedure Timer1Timer(Sender: TObject); procedure About1Click(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); private { Private declarations } rc : HGLRC; // Rendering Context dc : HDC; // Device Context FPSCount:integer; function DapatIndexObjek(x, y: integer): integer; procedure glDraw; procedure modePutar; procedure Idle(Sender: TObject; var Done: Boolean); public { Public declarations } deltaX,deltaY,X2,Y2,ModeOperasi:integer; DaftarGeometri:TdaftarGeometri; modeTransformasi:integer; Transform:Ttransformasi; dX,dY,dZ,awalX,awalY,awalZ:double; MouseTurun:boolean; titikPro3d:TArTitik3D; sudut,tempX,tempY,tempZ:real;
69
JarakKamFoc,kamera,fokus,atasKam,Dump3d,SumbuX,SumbuY:Ttitik3d; end; const light_position1:array[0..3] light_position2:array[0..3] light_position3:array[0..3] light_position4:array[0..3]
of of of of
GLFloat=(5.0,5.0,5.0,1.0); GLFloat=(5.0,5.0,5.0,1.0); GLFloat=(5.0,5.0,-5.0,1.0); GLFloat=(-5.0,5.0,-5.0,1.0);
var FormUtama: TFormUtama; Grid:Tgrid; implementation uses unitTranslasi, unitPenskalaan, unitRotasi, unitShearing, unitAbout; {$R *.dfm} procedure glInit(); begin glClearColor(0.6, 0.6, 0.6, 1); // Black Background glShadeModel(GL_FLAT); // Enables Smooth Color Shading glClearDepth(1.0); // Depth Buffer Setup glEnable(GL_DEPTH_TEST); // Enable Depth Buffer glEnable(GL_NORMALIZE); glDepthFunc(GL_LESS); // The Type Of Depth Test To Do glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); //Realy Nice perspective calculations glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_LIGHT1); glEnable(GL_LIGHT2); glEnable(GL_LIGHT3); glLightfv(GL_LIGHT0,GL_POSITION,@light_position1); glLightfv(GL_LIGHT1,GL_POSITION,@light_position2); glLightfv(GL_LIGHT2,GL_POSITION,@light_position3); glLightfv(GL_LIGHT3,GL_POSITION,@light_position4); end; procedure TFormUTama.modePutar; var index,i,X,Y,Z:integer; item:TGeometri; begin if sComboBox2.ItemIndex=0 then if sComboBox2.ItemIndex=1 then if sComboBox2.ItemIndex=2 then if sComboBox2.ItemIndex=3 then
Begin Begin Begin Begin
X:=1; X:=1; X:=0; X:=0;
Y:=1;Z:=1; Y:=0;Z:=0; Y:=1;Z:=0; Y:=0;Z:=1;
end; end; end; end;
for index:=0 to DaftarGeometri.f.Count-1 do begin item:=DaftarGeometri.f.Items[index]; if item.Aktif=true then begin for i:=0 to item.jumTitik do begin Transform.nolkanTransformasi; Transform.Rotasi(0.3,X,Y,Z); Transform.Transform(Item.Titik[i],item.Titik[i]); end; end; DaftarGeometri.f.Items[index]:=item; end; end;
70
procedure TFormUtama.Exit1Click(Sender: TObject); begin if Application.MessageBox('Apakah Anda ingin keluar?','Konfirmasi',MB_YESNO or MB_ICONINFORMATION)=IDYES then Application.terminate; end; procedure TFormUtama.FormResize(Sender: TObject); begin Panel1.Width:=FormUtama.Width-223; Panel1.Height:=FormUtama.Height-125; Panel1Resize(Sender); sMemo1.Height:=FormUtama.Height-480; end; procedure TFormUtama.FormCreate(Sender: TObject); var pfd : TPIXELFORMATDESCRIPTOR; pf : Integer; begin DaftarGeometri:=TDaftarGeometri.Create(self); Transform:=TTransformasi.Create; //inisialisasi openGL dc:=GetDC(Panel1.Handle); // PixelFormat pfd.nSize:=sizeof(pfd); pfd.nVersion:=1; pfd.dwFlags:=PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER or 0; pfd.iPixelType:=PFD_TYPE_RGBA; // PFD_TYPE_RGBA or PFD_TYPEINDEX pfd.cColorBits:=32; pf :=ChoosePixelFormat(dc, @pfd); matches above pixel format SetPixelFormat(dc, pf, @pfd); rc :=wglCreateContext(dc); glCreateContext wglMakeCurrent(dc,rc); Context
// Returns format that most closely
// Rendering Context = window// Make the DC (Form1) the rendering
// Initialist GL environment variables glInit; Panel1Resize(sender); // sets up the perspective //AppStart :=GetTickCount(); // when the app has spare time, render the GL scene Application.OnIdle := Idle; kamera.posX:=0;kamera.posY:=2;kamera.posZ:=6; fokus.posX:=0;fokus.posY:=0;fokus.posZ:=0; atasKam.posX:=0;atasKam.posY:=1;atasKam.posZ:=0; sumbuX.posX:=1;sumbuX.posY:=0;sumbuX.posZ:=0; sumbuY.posX:=0;sumbuY.posY:=1;sumbuY.posZ:=0; end; procedure TFormUtama.glDraw(); begin glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); Screen And The Depth Buffer glLoadIdentity(); View if ModeWireframe1.Checked=true then
// Clear The // Reset The
71
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) else glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); if Smooth1.Checked=true then glShadeModel(GL_SMOOTH) else glShadeModel(GL_FLAT); glInitNames(); glPushName(0); if Grid1.Checked=true then begin Grid.Gambar; glBegin(GL_LINES);
//Gambar Grid
glVertex3f(0,0,0);glVertex3f(SumbuX.posX,SumbuX.posY,sumbuX.posZ); glVertex3f(0,0,0);glVertex3f(sumbuY.posX,sumbuY.posY,sumbuY.posZ); glEnd; end; DaftarGeometri.Gambar; //Gambar Objek glPopName(); end; procedure TFormUtama.FormDestroy(Sender: TObject); begin wglMakeCurrent(0,0); wglDeleteContext(rc); end; procedure TFormUtama.Idle(Sender: TObject; var Done: Boolean); begin Done := false; Panel1Resize(Sender); if modeAnimasi1.Checked=true then modePutar; glDraw(); // Draw the scene SwapBuffers(DC); // Display the scene Inc(FPSCount); end; procedure TFormUtama.Panel1Resize(Sender: TObject); begin glViewport(0, 0, Panel1.Width, Panel1.Height); // Set the viewport for the OpenGL window glMatrixMode(GL_PROJECTION); // Change Matrix Mode to Projection glLoadIdentity(); // Reset View gluPerspective(45.0, Panel1.Width/Panel1.Height, 1.0, 500.0); // Do the perspective calculations. Last value = max clipping depth gluLookAt(Kamera.posX,Kamera.posY,Kamera.posZ,Fokus.posX,Fokus.posY, Fokus.posZ,atasKam.posX,atasKam.posY,atasKam.posZ); glMatrixMode(GL_MODELVIEW); end;
// Return to the modelview matrix
procedure TFormUtama.FormKeyPress(Sender: TObject; var Key: Char); begin case key of #27:Self.Close; //exit app //mode kamera 'z':ToolButton2.Click; 'k':ToolButton3.Click; 'l':ToolButton4.Click; 'g':ToolButton5.Click; 'e':ToolButton13.Click; //Mode Transformasi
72
't':ToolButton7.Click; 'p':ToolButton8.Click; 'r':ToolButton9.Click; 's':ToolButton10.Click; 'd':ToolButton15.Click; else Exit; end; end; procedure TFormUtama.sButton1Click(Sender: TObject); var i:integer; ObjekBaru:TGeometri; tinggi,sisi:Glfloat; titikPusat:Ttitik3d; begin tinggi:=StrToFloat(sDecimalSpinEdit4.Text); sisi:=StrToFloat(sDecimalSpinEdit5.Text); titikPusat.posX:=StrToFloat(sDecimalSpinEdit1.Text); titikPusat.posY:=StrToFloat(sDecimalSpinEdit2.Text); titikPusat.posZ:=StrToFloat(sDecimalSpinEdit3.Text); ObjekBaru:=nil; ObjekBaru:=Tpiramid.create(tinggi,sisi,titikPusat); DaftarGeometri.TambahGeometri(ObjekBaru); sMemo1.Lines.Add(ObjekBaru.jenis); for i:=0 to ObjekBaru.jumTitik do begin sMemo1.Lines.Add('Titik'+IntToStr(i)+' ('+ Format('%.2f',[objekBaru.titik[i].posX])+' '+ Format('%.2f',[objekBaru.titik[i].posY])+' '+ Format('%.2f',[objekBaru.titik[i].posZ])+')'); end; end; procedure TFormUtama.ranslasi1Click(Sender: TObject); begin TFormTranslasi.Create(self); end; procedure TFormUtama.sButton3Click(Sender: TObject); var ObjekBaru:TGeometri; titikPusat:Ttitik3d; begin titikPusat.posX:=StrToFloat(sDecimalSpinEdit21.Text); titikPusat.posY:=StrToFloat(sDecimalSpinEdit22.Text); titikPusat.posZ:=StrToFloat(sDecimalSpinEdit23.Text); ObjekBaru:=nil; ObjekBaru:=Tkursi.Create(titikPusat); DaftarGeometri.TambahGeometri(ObjekBaru); end; procedure TFormUtama.sButton5Click(Sender: TObject); var sisi:Glfloat; titikPusat:Ttitik3d; objekBaru:Tgeometri; begin sisi:=StrToFloat(sDecimalSpinEdit18.Text); titikPusat.posX:=StrToFloat(sDecimalSpinEdit6.Text); titikPusat.posY:=StrToFloat(sDecimalSpinEdit7.Text);
73
titikPusat.posZ:=StrToFloat(sDecimalSpinEdit8.Text); ObjekBaru:=nil; ObjekBaru:=Tkubus.create(sisi,titikPusat); DaftarGeometri.TambahGeometri(ObjekBaru); end; procedure TFormUtama.sButton7Click(Sender: TObject); var titikPusat:Ttitik3d; RAdius,tinggi:Glfloat; objekbaru:TGeometri; begin titikPusat.posX:=StrToFloat(sDecimalSpinEdit9.Text); titikPusat.posY:=StrToFloat(sDecimalSpinEdit10.Text); titikPusat.posZ:=StrToFloat(sDecimalSpinEdit11.Text); Radius:=StrToFloat(sDecimalSpinEdit20.Text); tinggi:=StrToFloat(sDecimalSpinEdit19.Text); ObjekBaru:=nil; ObjekBaru:=TSilinder.Create(Radius,tinggi,titikPusat); DaftarGeometri.TambahGeometri(ObjekBaru); end; procedure TFormUtama.Penskalaan1Click(Sender: TObject); begin TFormPenskalaan.Create(self); end; procedure TFormUtama.Rotasi1Click(Sender: TObject); begin TFormRotasi.Create(self); end; procedure TFormUtama.Panel1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var indexObjek,index: integer; item:Tgeometri; begin indexObjek:=DapatIndexObjek(X,Y); if(button=mbLeft)then begin mouseTurun:=true; for index:=0 to daftarGeometri.f.Count-1 do begin item:=daftarGeometri.f.Items[index]; if item.index=indexObjek-100 then begin item.Aktif:=true; sMEmo1.Lines.Add(item.jenis); end; daftarGeometri.f.Items[index]:=item; end; end; if(button=mbMiddle)then begin for index:=0 to daftarGeometri.f.Count-1 do begin item:=daftarGeometri.f.Items[index]; if item.index=indexObjek-100 then begin item.Aktif:=false; sMEmo1.Lines.Add(item.jenis); end;
74
daftarGeometri.f.Items[index]:=item; end; end; if(Button=mbRight)then begin PopupMenu1.AutoPopup:=true; PopupMenu1.Popup(X+FormUtama.Left+Panel1.Left, Y+FormUTama.Top+Panel1.Top); end; end; procedure TFormUtama.Panel1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); var i,index:integer; faktor,dDump:real; item:Tgeometri; uz:Ttitik3d; begin if modeTransformasi=8 then Panel1.Cursor:=crHandPoint else Panel1.Cursor:=crCross; if Y < 0 then y:=0; Transform.ambilPos3d(X,Y,titikPro3D); dx:=titikPro3D[1]-awalX; dy:=titikPro3D[2]-awalY; dz:=titikPro3D[3]-awalZ; deltaX:=X-X2; deltaY:=Y-Y2; //################################################################### if sComboBox2.ItemIndex=1 then begin if dx=0 then dx:=dz; dy:=0;dz:=0; end; if sComboBox2.ItemIndex=2 then begin if dy=0 then dy:=dx; dx:=0;dz:=0; end; if sComboBox2.ItemIndex=3 then begin if dz=0 then dz:=dx; dx:=0;dy:=0; end; //################### SHEARING DENGAN MOUSE ########################## if(mouseTurun=true)and(modeTransformasi=4)and(sComboBox2.itemIndex>0)then begin for index:=0 to DaftarGeometri.f.Count-1 do begin item:=DaftarGeometri.f.Items[index]; tempX:=item.titik[0].posX; tempY:=item.titik[0].posY; tempZ:=item.titik[0].posZ; if item.Aktif=true then begin for i:=0 to item.jumTitik do begin Transform.nolkanTransformasi; Transform.Translasi(-tempX,-tempY,-tempZ); Transform.Transform(Item.Titik[i],item.Titik[i]); Transform.nolkanTransformasi;
75
Transform.Shearing(scomboBox2.ItemIndex,0,deltaX/100,deltaX/100); Transform.Transform(Item.Titik[i],item.Titik[i]); Transform.nolkanTransformasi; Transform.Translasi(tempX,tempY,tempZ); Transform.Transform(Item.Titik[i],item.Titik[i]); end; end; DaftarGeometri.f.Items[index]:=item; end; end; //################ ZOOMING KAMERA ###################################### if(mouseTurun=true)and(modeTransformasi=5)then begin if deltaX > 0 then dDump:=0.1; if deltaX < 0 then dDump:=-0.1; JarakKamFoc.posX:=kamera.posX-fokus.posX; JarakKamFoc.posY:=kamera.posY-fokus.posY; JarakKamFoc.posZ:=kamera.posZ-fokus.posZ; faktor:=PanjangVektor(JarakKamFoc); Transform.nolkanTransformasi; Transform.Translasi(dDump*JarakKamFoc.posX/faktor, dDump*JarakKamFoc.posY/faktor, dDump*JarakKamFoc.posZ/faktor); Transform.Transform(kamera,kamera); end; //################### TRANSLASI DENGAN MOUSE ########################## if(mouseTurun=true)and(modeTransformasi=1)then begin JarakKamFoc.posX:=kamera.posX-fokus.posX; JarakKamFoc.posY:=kamera.posY-fokus.posY; JarakKamFoc.posZ:=kamera.posZ-fokus.posZ; faktor:=PanjangVektor(JarakKamFoc); for index:=0 to DaftarGeometri.f.Count-1 do begin item:=DaftarGeometri.f.Items[index]; if item.Aktif=true then begin for i:=0 to item.jumTitik do begin Transform.nolkanTransformasi; Transform.Translasi(dx*faktor,dy*faktor,dz*faktor); Transform.Transform(Item.Titik[i],item.Titik[i]); end; end; DaftarGeometri.f.Items[index]:=item; end; end; //################### ROTASI DENGAN MOUSE ########################## if(mouseTurun=true)and(modeTransformasi=3)then begin for index:=0 to DaftarGeometri.f.Count-1 do begin item:=DaftarGeometri.f.Items[index]; item:=FormUtama.DaftarGeometri.f.Items[index]; tempX:=item.titik[0].posX; tempY:=item.titik[0].posY; tempZ:=item.titik[0].posZ; if item.Aktif=true then begin
76
for i:=0 to item.jumTitik do begin //Transform.nolkanTransformasi; //Transform.Translasi(-tempX,-tempY,-tempZ); //Transform.Transform(Item.Titik[i],item.Titik[i]); if sComboBox2.ItemIndex=0 then begin Transform.nolkanTransformasi; Transform.Rotasi(deltaY,sumbuX.posX,sumbuX.posY,sumbuX.posZ); Transform.Transform(Item.Titik[i],item.Titik[i]); Transform.nolkanTransformasi; Transform.Rotasi(deltaX,SumbuY.posX,sumbuY.posY,SumbuY.posZ); Transform.Transform(Item.Titik[i],item.Titik[i]); end; Transform.nolkanTransformasi; if sComboBox2.ItemIndex=1 then Transform.Rotasi(deltaX,1,0,-1); if sComboBox2.ItemIndex=2 then Transform.Rotasi(deltaX,0,1,1); if sComboBox2.ItemIndex=3 then Transform.Rotasi(deltaX,0,0,1); Transform.Transform(Item.Titik[i],item.Titik[i]); //Transform.nolkanTransformasi; //Transform.Translasi(tempX,tempY,tempZ); //Transform.Transform(Item.Titik[i],item.Titik[i]); end; end; DaftarGeometri.f.Items[index]:=item; end; end; //################### DILATASI DENGAN MOUSE ########################## if(mouseTurun=true)and(modeTransformasi=2)then begin if deltaX > 0 then dDump:=0.01; if deltaX < 0 then dDump:=-0.01; if sComboBox2.ItemIndex=0 then begin dx:=dDump;dy:=dDump;dz:=dDump;end; if sComboBox2.ItemIndex=1 then begin dx:=dDump;dy:=0;dz:=0;end; if sComboBox2.ItemIndex=2 then begin dx:=0;dy:=dDump;dz:=0;end; if sComboBox2.ItemIndex=3 then begin dx:=0;dy:=0;dz:=dDump;end; for index:=0 to DaftarGeometri.f.Count-1 do begin item:=DaftarGeometri.f.Items[index]; if item.Aktif=true then begin for i:=0 to item.jumTitik do begin Transform.nolkanTransformasi; Transform.Translasi(-tempX,-tempY,-tempZ); Transform.Transform(Item.Titik[i],item.Titik[i]); Transform.nolkanTransformasi; Transform.Penskalaan(1+dx,1+dy,1+dz,0,0,0); Transform.Transform(Item.Titik[i],item.Titik[i]); Transform.nolkanTransformasi; Transform.Translasi(tempX,tempY,tempZ); Transform.Transform(Item.Titik[i],item.Titik[i]); end; end; DaftarGeometri.f.Items[index]:=item; end; end; //################ ROTASI KAMERA ###################################### if(mouseTurun=true)and(modeTransformasi=6)then begin if deltaX > 0 then dDump:=1;
77
if deltaX < 0 then dDump:=-1; //if sComboBox2.ItemIndex=0 then begin dx:=0;dy:=0;dz:=0;end; Transform.nolkanTransformasi; Transform.Translasi(-fokus.posX,-fokus.posY,-fokus.posZ); Transform.Transform(kamera,kamera); if sComboBox2.ItemIndex=0 then begin Transform.nolkanTransformasi; Transform.Rotasi(deltaY/10,sumbuX.posX,SumbuX.posY,sumbuX.posZ); Transform.Transform(Kamera,Kamera); Transform.Transform(atasKam,atasKam); Transform.Transform(sumbuY,sumbuY); Transform.nolkanTransformasi; Transform.Rotasi(deltaX/10,sumbuY.posX,sumbuY.posY,sumbuY.posZ); Transform.Transform(Kamera,Kamera); Transform.Transform(atasKam,atasKam); Transform.Transform(sumbuX,sumbuX); end; if sComboBox2.ItemIndex=1 then begin Transform.nolkanTransformasi; Transform.Rotasi(deltaX,sumbuX.posX,0,sumbuX.posZ); Transform.Transform(Kamera,Kamera); Transform.Transform(atasKam,atasKam); Transform.Transform(sumbuY,sumbuY); Transform.Transform(sumbuX,sumbuX); end; if sComboBox2.ItemIndex=2 then begin Transform.nolkanTransformasi; Transform.Rotasi(deltaX,0,1,0); Transform.Transform(Kamera,Kamera); Transform.Transform(atasKam,atasKam); Transform.Transform(sumbuX,sumbuX); Transform.Transform(sumbuY,sumbuY); end; if sComboBox2.ItemIndex=3 then begin Transform.nolkanTransformasi; Transform.Rotasi(deltaX,kamera.posX,kamera.posY,kamera.posZ); Transform.Transform(atasKam,atasKam); Transform.Transform(sumbuY,sumbuY); Transform.Transform(sumbuX,sumbuX); end; Transform.nolkanTransformasi; Transform.Translasi(fokus.posX,fokus.posY,fokus.posZ); Transform.Transform(kamera,kamera); end; //################ ROTASI TITIK FOKUS KAMERA ################################ if(mouseTurun=true)and(modeTransformasi=7)then begin if deltaX > 0 then dDump:=1; if deltaX < 0 then dDump:=-1;
Transform.nolkanTransformasi; Transform.Translasi(-kamera.posX,-kamera.posY,-kamera.posZ); Transform.Transform(fokus,fokus); if sComboBox2.ItemIndex=0 then begin Transform.nolkanTransformasi; Transform.Rotasi(deltaY,sumbuX.posX,SumbuX.posY,sumbuX.posZ);
78
Transform.Transform(Fokus,Fokus); Transform.Transform(atasKam,atasKam); Transform.Transform(sumbuY,sumbuY); Transform.nolkanTransformasi; Transform.Rotasi(deltaX,sumbuY.posX,SumbuY.posY,sumbuY.posZ); Transform.Transform(Fokus,Fokus); Transform.Transform(atasKam,atasKam); Transform.Transform(sumbuX,sumbuX); end; if sComboBox2.ItemIndex=1 then begin Transform.nolkanTransformasi; Transform.Rotasi(-deltaX,sumbuX.posX,0,sumbuX.posZ); Transform.Transform(fokus,fokus); Transform.Transform(atasKam,atasKam); Transform.Transform(sumbuY,sumbuY); Transform.Transform(sumbuX,sumbuX); end; if sComboBox2.ItemIndex=2 then begin Transform.nolkanTransformasi; Transform.Rotasi(-deltaX,0,1,0); Transform.Transform(fokus,fokus); Transform.Transform(atasKam,atasKam); Transform.Transform(sumbuX,sumbuX); Transform.Transform(sumbuY,sumbuY); end; if sComboBox2.ItemIndex=3 then begin Transform.nolkanTransformasi; Transform.Rotasi(-deltaX,fokus.posX,fokus.posY,fokus.posZ); Transform.Transform(atasKam,atasKam); Transform.Transform(sumbuY,sumbuY); Transform.Transform(sumbuX,sumbuX); end; Transform.nolkanTransformasi; Transform.Translasi(kamera.posX,kamera.posY,kamera.posZ); Transform.Transform(fokus,fokus); end; //################ HAND KAMERA ###################################### if(mouseTurun=true)and(modeTransformasi=8)then begin Transform.nolkanTransformasi; Transform.Translasi(dx,dy,dz); Transform.Transform(kamera,kamera); Transform.Transform(fokus,fokus); end; //################### MENAMPILKAN POSISI MOUSE ########################## sStatusBar1.Panels[0].Text:='Posisi World: x='+Format('%.2f',[titikPro3D[1]])+ ' y='+Format('%-.2f',[titikPro3D[2]])+ ' z='+Format('%-.2f',[titikPro3D[3]]); sStatusBar1.Panels[1].Text:='Posisi Layar: X='+IntToStr(x)+ ' Y='+IntToStr(Y); sDecimalSpinEdit12.Text:=Format('%.2f',[kamera.posX]); sDecimalSpinEdit13.Text:=Format('%.2f',[kamera.posY]); sDecimalSpinEdit14.Text:=Format('%.2f',[kamera.posZ]); sDecimalSpinEdit15.Text:=Format('%.2f',[fokus.posX]); sDecimalSpinEdit16.Text:=Format('%.2f',[fokus.posY]); sDecimalSpinEdit17.Text:=Format('%.2f',[fokus.posZ]); X2:=X; Y2:=Y;
79
awalX:=titikPro3d[1]; awalY:=titikPro3d[2]; awalZ:=titikPro3d[3]; end; procedure TFormUtama.Panel1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin MouseTurun:=false; end;
procedure TFormUtama.sComboBox1Change(Sender: TObject); begin if sComboBox1.Text='Depan' then begin sDecimalSpinEdit12.Text:='0';sDecimalSpinEdit13.Text:='0'; sDecimalSpinEdit14.Text:='6'; Kamera.posX:=0;Kamera.posY:=0;Kamera.posZ:=6; SumbuX.posX:=1;SumbuX.posY:=0;SumbuX.posZ:=0; SumbuY.posX:=0;SumbuY.posY:=1;SumbuY.posZ:=0; end; if sComboBox1.Text='Belakang'then begin sDecimalSpinEdit12.Text:='0';sDecimalSpinEdit13.Text:='0'; sDecimalSpinEdit14.Text:='-6'; Kamera.posX:=0;Kamera.posY:=0;Kamera.posZ:=-6; SumbuX.posX:=-1;SumbuX.posY:=0;SumbuX.posZ:=0; SumbuY.posX:=0;SumbuY.posY:=1;SumbuY.posZ:=0; end; if sComboBox1.Text='Atas' then begin sDecimalSpinEdit12.Text:='0';sDecimalSpinEdit13.Text:='6'; sDecimalSpinEdit14.Text:=FloatToStr(0.01); Kamera.posX:=0;Kamera.posY:=6;Kamera.posZ:=0.01; SumbuX.posX:=1;SumbuX.posY:=0;SumbuX.posZ:=0; SumbuY.posX:=0;SumbuY.posY:=0;SumbuY.posZ:=-1; end; if sComboBox1.text='Bawah'then begin sDecimalSpinEdit12.Text:='0';sDecimalSpinEdit13.Text:='-6'; sDecimalSpinEdit14.Text:=FloatToStr(0.01); Kamera.posX:=0;Kamera.posY:=-6;Kamera.posZ:=0.01; SumbuX.posX:=1;SumbuX.posY:=0;SumbuX.posZ:=0; SumbuY.posX:=0;SumbuY.posY:=0;SumbuY.posZ:=1; end; if sComboBox1.Text='Kiri'then begin sDecimalSpinEdit12.Text:='6';sDecimalSpinEdit13.Text:='0'; sDecimalSpinEdit14.Text:='0'; Kamera.posX:=-6;Kamera.posY:=0;Kamera.posZ:=0; SumbuX.posX:=0;SumbuX.posY:=0;SumbuX.posZ:=1; SumbuY.posX:=0;SumbuY.posY:=1;SumbuY.posZ:=0; end; if sComboBox1.Text='Kanan'then begin sDecimalSpinEdit12.Text:='6';sDecimalSpinEdit13.Text:='0'; sDecimalSpinEdit14.Text:='0'; Kamera.posX:=6;Kamera.posY:=0;Kamera.posZ:=0; SumbuX.posX:=0;SumbuX.posY:=0;SumbuX.posZ:=-6; SumbuY.posX:=0;SumbuY.posY:=1;SumbuY.posZ:=0; end; end;
80
function TFormUTama.DapatIndexObjek(x, y: integer): integer; var objectsFound: integer; viewportCoords: array [0..3] of integer; selectBuffer: array[0..511] of cardinal; lowestDepth: cardinal; selectedObject: GLuint; i: integer; begin ZeroMemory(@viewportCoords, sizeof(viewportCoords)); ZeroMemory(@selectBuffer, sizeof(selectBuffer)); glSelectBuffer(512, @selectBuffer); glRenderMode(GL_SELECT); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity();
//
mereset matriks proyeksi
glGetIntegerv(GL_VIEWPORT, @viewportCoords); gluPickMatrix(x, viewportCoords[3]-y, 1, 1, @viewportCoords); gluPerspective(45.0, Panel1.Width/Panel1.Height, 1.0, 1000.0);
gluLookAt(Kamera.posX,Kamera.posY,Kamera.posZ,Fokus.posX,Fokus.posY, Fokus.posZ,atasKam.posX,atasKam.posY,atasKam.posZ); glMatrixMode(GL_MODELVIEW); // kembali ke model view matriks glDraw; ke daerah objek pinpoint glMatrixMode(GL_PROJECTION); proyeksi ke normal glPopMatrix(); mempengaruhi matriks proyeksi glMatrixMode(GL_MODELVIEW);
// menggambarkan kembali objek
// mengembalikan matriks //berhenti //kembali model view matriks
objectsFound := glRenderMode(GL_RENDER); // kembali ke render mode dan mendapatkan jumlah objek if (objectsFound > 0) then begin sMemo1.Lines.Add('Index: '+IntToStr(selectBuffer[3])); lowestDepth := selectBuffer[1]; selectedObject := selectBuffer[3]; for i := 1 to objectsFound - 1 do begin if (selectBuffer[(i * 4) + 1] < lowestDepth) then begin lowestDepth := selectBuffer[(i * 4) + 1]; selectedObject := selectBuffer[(i * 4) + 3]; end end; result := selectedObject; exit; end; result :=-1; end; procedure TFormUtama.Hapus1Click(Sender: TObject); var index,jumlahGeometri:integer; item:Tgeometri; begin index:=0; jumlahGeometri:=DaftarGeometri.f.Count;
81
repeat item:=DaftarGeometri.f.Items[index]; if item.Aktif=true then begin DaftarGeometri.f.Delete(index); jumlahGeometri:=DaftarGeometri.f.Count; index:=-1; end; inc(index); until(index=jumlahGeometri); end; procedure TFormUtama.ToolButton7Click(Sender: TObject); begin modeTransformasi:=1; sStatusBar1.Panels[2].Text:='Mode: Translasi'; end; procedure TFormUtama.ToolButton8Click(Sender: TObject); begin ModeTransformasi:=2; sStatusBar1.Panels[2].Text:='Mode: Penskalaan'; end; procedure TFormUtama.ToolButton9Click(Sender: TObject); begin modeTransformasi:=3; sStatusBar1.Panels[2].Text:='Mode: Rotasi'; end; procedure TFormUtama.sMemo1DblClick(Sender: TObject); begin sMemo1.Clear; end;
procedure TFormUtama.sButton2Click(Sender: TObject); var ObjekBaru:TGeometri; titikPusat:Ttitik3d; begin titikPusat.posX:=StrToFloat(sDecimalSpinEdit24.Text); titikPusat.posY:=StrToFloat(sDecimalSpinEdit25.Text); titikPusat.posZ:=StrToFloat(sDecimalSpinEdit26.Text); ObjekBaru:=nil; ObjekBaru:=Tmeja.Create(titikPusat); DaftarGeometri.TambahGeometri(ObjekBaru); end; procedure TFormUtama.ToolButton2Click(Sender: TObject); begin modeTransformasi:=5; sStatusBar1.Panels[2].Text:='Mode: Zoom'; end; procedure TFormUtama.ToolButton10Click(Sender: TObject); begin ModeTransformasi:=4; sStatusBar1.Panels[2].Text:='Mode: Shearing'; end; procedure TFormUtama.ToolButton3Click(Sender: TObject); begin
82
modeTransformasi:=6; sStatusBar1.Panels[2].Text:='Mode: Rotasi Kamera'; end; procedure TFormUtama.ToolButton4Click(Sender: TObject); begin modeTransformasi:=7; sStatusBar1.Panels[2].Text:='Mode: Rotasi Fokus Kamera'; end; procedure TFormUtama.ToolButton5Click(Sender: TObject); begin modeTransformasi:=8; sStatusBar1.Panels[2].Text:='Mode: Geser Kamera'; end; procedure TFormUtama.ToolButton6Click(Sender: TObject); var item:Tgeometri; index:integer; begin for index:=0 to DaftarGeometri.f.Count-1 do begin item:=DaftarGeometri.f.Items[index]; if item.Aktif=true then begin sudut:=arcCos(DotProduct(fokus,item.titik[0])); fokus.posX:=item.titik[0].posX; fokus.posY:=item.titik[0].posY; fokus.posZ:=item.titik[0].posZ; sDecimalSpinEdit15.Text:=Format('%.2f',[item.titik[0].posX]); sDecimalSpinEdit16.Text:=Format('%.2f',[item.titik[0].posY]); sDecimalSpinEdit17.Text:=Format('%.2f',[item.titik[0].posZ]); exit; end; end; end; procedure TFormUtama.Shearing1Click(Sender: TObject); begin TFormShearing.Create(self); end; procedure TFormUtama.sComboBox2Change(Sender: TObject); begin sStatusBar1.Panels[3].Text:='Sumbu Putar/Arah Vektor: '+ sComboBox2.text; end; procedure TFormUtama.sButton4Click(Sender: TObject); Var ObjekBaru:Tgeometri; begin if sOpenDialog1.execute then begin ObjekBaru:=nil; ObjekBaru:=TOBJLoader.create(sOpenDialog1.FileName); DaftarGeometri.TambahGeometri(ObjekBaru); end; end; procedure TFormUtama.ToolButton13Click(Sender: TObject); begin sDecimalSpinEdit12.Text:='0'; sDecimalSpinEdit13.Text:='2'; sDecimalSpinEdit14.Text:='6'; sDecimalSpinEdit15.Text:='0';
83
sDecimalSpinEdit16.Text:='0'; sDecimalSpinEdit17.Text:='0'; Kamera.posX:=0;Kamera.posy:=2;Kamera.posZ:=6; Fokus.posX:=0;Fokus.posy:=0;Fokus.posZ:=0; atasKam.posX:=0;atasKam.posY:=1;atasKam.posZ:=0; sumbuX.posX:=1;sumbuX.posY:=0;sumbuX.posZ:=0; sumbuY.posX:=0;sumbuY.posY:=1;sumbuY.posZ:=0; end; procedure TFormUtama.ToolButton15Click(Sender: TObject); begin modeTransformasi:=0; sStatusBar1.Panels[2].Text:='Mode: Awal'; end; procedure TFormUtama.Hapus2Click(Sender: TObject); begin Hapus1.Click; end; procedure TFormUtama.ranslasi2Click(Sender: TObject); begin ranslasi1.Click; end; procedure TFormUtama.Penskalaan2Click(Sender: TObject); begin Penskalaan1.Click; end; procedure TFormUtama.Rotasi2Click(Sender: TObject); begin Rotasi1.Click; end; procedure TFormUtama.Shearing2Click(Sender: TObject); begin Shearing1.Click; end; procedure TFormUtama.Timer1Timer(Sender: TObject); begin sStatusBar1.Panels.Items[4].Text:='Framerate: '+IntToStr(FPSCount)+' FPS'; FPSCount:=0; end; procedure TFormUtama.About1Click(Sender: TObject); begin TFormAbout.Create(self); end; procedure TFormUtama.sButton6Click(Sender: TObject); var sudut1,sudut2:real; begin kamera.posX:=StrToFloat(sDecimalSpinEdit12.Text); kamera.posY:=StrToFloat(sDecimalSpinEdit13.Text); kamera.posZ:=StrToFloat(sDecimalSpinEdit14.Text); fokus.posX:=StrToFloat(sDecimalSpinEdit15.Text); fokus.posY:=StrToFloat(sDecimalSpinEdit16.Text); fokus.posZ:=StrToFloat(sDecimalSpinEdit17.Text); sudut1:=arcTan(kamera.posX/kamera.posZ)*180/PI;
84
sudut2:=arcTan(kamera.posY/sqrt(sqr(Kamera.posX)+sqr(kamera.posZ)))*180/P I; sMemo1.Lines.Add('Sudut= '+FloatToStr(sudut1)); Transform.nolkanTransformasi; Transform.Rotasi(sudut1,0,1,0); sumbuX.posX:=1;SumbuX.posY:=0;SumbuX.posZ:=0; Transform.Transform(sumbuX,sumbuX); Transform.nolkanTransformasi; Transform.Rotasi(sudut2,sumbuX.posX,0,sumbuX.posZ); sumbuY.posX:=0;SumbuY.posY:=1;SumbuY.posZ:=0; Transform.Transform(sumbuY,sumbuY); end; procedure TFormUtama.SaveAsBMP1Click(Sender: TObject); var bmp: TBitmap; i: Integer; dest: Pointer; begin bmp := TBitmap.Create; bmp.PixelFormat := pf24bit; bmp.Width := Panel1.Width; bmp.Height := Panel1.Height; for i := 0 to Panel1.Height-1 do begin dest := bmp.ScanLine[(Panel1.Height-1)-i]; glReadPixels(0,i,Panel1.Width,1,GL_BGR,GL_UNSIGNED_BYTE,dest); end; if SavePictureDialog1.Execute then bmp.SaveToFile(SavePictureDialog1.FileName); bmp.Free; end; procedure TFormUtama.FormClose(Sender: TObject; var Action: TCloseAction); begin if Application.MessageBox('Apakah Anda ingin keluar?','Konfirmasi',MB_YESNO or MB_ICONINFORMATION)=IDNO then Action:=caNone; end; end.
Vektor.pas unit vektor; interface uses sysutils,geometri,OBJLoader; function function function function function
DotProduct(va,vb:Ttitik3d):real; CrossProduct(va,vb:Ttitik3d):Ttitik3d; BuatVektor(x,y,z:real):Ttitik3d; Normalisasi(va:Ttitik3d):Ttitik3d; PanjangVektor(va:Ttitik3d):real;
implementation uses unitUtama; function BuatVektor(x,y,z:real):Ttitik3d; var va:Ttitik3d;
85
begin va.posX:=x; va.posY:=y; va.posZ:=z; result:=va; end; function PanjangVektor(va:Ttitik3d):real; begin Result:=abs(sqrt(va.posx*va.posx+va.posy*va.posy+va.posz*va.posz)); end; function Normalisasi(va:Ttitik3d):Ttitik3d; var l:real; v:Ttitik3d; begin l:=PanjangVektor(va); if l=0 then exit raise ERangeError.CreateFmt( 'Panjang Vektor = %f tidak dapat dinormalisasi',[l]) else begin v.posx:=va.posx/l; v.posy:=va.posy/l; v.posz:=va.posz/l; result:=v; end; end; function DotProduct(va,vb:Ttitik3d):real; var s:real; begin s:=va.posx*vb.posx+va.posy*vb.posy+va.posz*vb.posz; result:=s; end; function CrossProduct(va,vb:Ttitik3d):Ttitik3d; var vs:Ttitik3d; begin vs.posx:=(va.posy*vb.posz)-(va.posz*vb.posy); vs.posy:=(va.posz*vb.posx)-(va.posx*vb.posz); vs.posz:=(va.posx*vb.posy)-(va.posy*vb.posx); result:=vs; end; end.
unitPensklaan.pas unit unitPenskalaan; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, sSkinProvider, sSkinManager, StdCtrls, sButton, sEdit, sSpinEdit, sLabel,OpenGL,Geometri,Transformasi; type TFormPenskalaan = class(TForm) sSkinManager1: TsSkinManager; sSkinProvider1: TsSkinProvider; sLabel1: TsLabel; sLabel2: TsLabel; sLabel3: TsLabel; sDecimalSpinEdit1: TsDecimalSpinEdit; sDecimalSpinEdit2: TsDecimalSpinEdit; sDecimalSpinEdit3: TsDecimalSpinEdit;
86
sButton1: TsButton; sButton2: TsButton; sLabel4: TsLabel; sLabel5: TsLabel; sDecimalSpinEdit4: TsDecimalSpinEdit; sDecimalSpinEdit5: TsDecimalSpinEdit; sDecimalSpinEdit6: TsDecimalSpinEdit; sLabel6: TsLabel; sLabel7: TsLabel; sLabel8: TsLabel; procedure sButton2Click(Sender: TObject); procedure sButton1Click(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private declarations } Transform:TTransformasi; public { Public declarations } end; var FormPenskalaan: TFormPenskalaan; implementation uses unitUtama; {$R *.dfm} procedure TFormPenskalaan.sButton2Click(Sender: TObject); begin close; end; procedure TFormPenskalaan.sButton1Click(Sender: TObject); var sx,sy,sz,xc,yc,zc,tempX,tempY,tempZ:GLFloat; i,index:integer; item:Tgeometri; begin sx:=StrToFloat(sDecimalSpinEdit1.text); sy:=StrToFloat(sDecimalSpinEdit2.text); sz:=StrToFloat(sDecimalSpinEdit3.text); xc:=StrToFloat(sDecimalSpinEdit4.text); yc:=StrToFloat(sDecimalSpinEdit5.text); zc:=StrToFloat(sDecimalSpinEdit6.text); //Transformasi penskalaan for index:=0 to FormUtama.DaftarGeometri.f.Count-1 do begin item:=FormUtama.DaftarGeometri.f.Items[index]; tempX:=item.titik[0].posX; tempY:=item.titik[0].posY; tempZ:=item.titik[0].posZ; if item.Aktif=true then for i:=0 to item.jumTitik do begin //Ditranslasi terlebih dahulu ke titik origin Transform.nolkanTransformasi; Transform.Translasi(-tempX,-tempY,-tempZ); Transform.Transform(item.Titik[i],item.Titik[i]); //Di dilatasikan Transform.nolkanTransformasi; Transform.Penskalaan(sx,sy,sz,xc,yc,zc); Transform.Transform(item.Titik[i],item.Titik[i]); //dikembalikan ke titik semula
87
Transform.nolkanTransformasi; Transform.Translasi(tempX,tempY,tempZ); Transform.Transform(item.Titik[i],item.Titik[i]); FormUtama.sMemo1.Lines.Add('Titik'+IntToStr(i)+' ('+ Format('%.2f',[item.titik[i].posX])+' '+ Format('%.2f',[item.titik[i].posY])+' '+ Format('%.2f',[item.titik[i].posZ])+')'); end; FormUtama.DaftarGeometri.f.Items[index]:=item; end; end; procedure TFormPenskalaan.FormCreate(Sender: TObject); begin Transform:=TTransformasi.Create; Transform.NolkanTransformasi; end; end.
unitRotasi.pas unit unitRotasi; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, sSkinProvider, sSkinManager, StdCtrls, sLabel, sButton, sEdit, sSpinEdit,Transformasi,openGL, sComboBox,Geometri; type TFormRotasi = class(TForm) sSkinManager1: TsSkinManager; sSkinProvider1: TsSkinProvider; sLabel1: TsLabel; sLabel5: TsLabel; sDecimalSpinEdit4: TsDecimalSpinEdit; sButton1: TsButton; sButton2: TsButton; sDecimalSpinEdit1: TsDecimalSpinEdit; sDecimalSpinEdit2: TsDecimalSpinEdit; sDecimalSpinEdit3: TsDecimalSpinEdit; sLabel2: TsLabel; sLabel3: TsLabel; sLabel4: TsLabel; procedure sButton1Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure sButton2Click(Sender: TObject); private { Private declarations } public Transform:Ttransformasi; { Public declarations } end; var FormRotasi: TFormRotasi; implementation uses unitUtama; {$R *.dfm}
88
procedure TFormRotasi.sButton1Click(Sender: TObject); var sudut,sumbuX,sumbuY,sumbuZ,tempX,tempY,tempZ:real; i,index:integer; item:Tgeometri; begin sudut:=StrToFloat(sDecimalSpinEdit4.Text); sumbuX:=StrToFloat(sDecimalspinEdit1.Text); sumbuY:=StrToFloat(sDecimalspinEdit2.Text); sumbuZ:=StrToFloat(sDecimalspinEdit3.Text); for index:=0 to FormUtama.DaftarGeometri.f.Count-1 do begin item:=FormUtama.DaftarGeometri.f.Items[index]; tempX:=item.titik[0].posX; tempY:=item.titik[0].posY; tempZ:=item.titik[0].posZ; if item.Aktif=true then for i:=0 to item.jumTitik do begin //Ditranslasi terlebih dahulu ke titik origin Transform.nolkanTransformasi; Transform.Translasi(-tempX,-tempY,-tempZ); Transform.Transform(item.Titik[i],item.Titik[i]); //Dirotasi Transform.nolkanTransformasi; Transform.Rotasi(sudut,sumbuX,sumbuY,sumbuZ); Transform.Transform(item.Titik[i],item.Titik[i]); //dikembalikan ke titik semula Transform.nolkanTransformasi; Transform.Translasi(tempX,tempY,tempZ); Transform.Transform(item.Titik[i],item.Titik[i]); FormUtama.sMemo1.Lines.Add('Titik'+IntToStr(i)+' ('+ Format('%.2f',[item.titik[i].posX])+' '+ Format('%.2f',[item.titik[i].posY])+' '+ Format('%.2f',[item.titik[i].posZ])+')'); end; FormUtama.DaftarGeometri.f.Items[index]:=item; end; end; procedure TFormRotasi.FormCreate(Sender: TObject); begin Transform:=TTransformasi.Create; Transform.NolkanTransformasi; end; procedure TFormRotasi.sButton2Click(Sender: TObject); begin Close; end; end.
unitShearing.pas unit unitShearing; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, sButton, sEdit, sSpinEdit, sComboBox, sLabel, sSkinProvider, sSkinManager, Geometri,Transformasi;
89
type TFormShearing = class(TForm) sSkinManager1: TsSkinManager; sSkinProvider1: TsSkinProvider; sLabel1: TsLabel; sLabel2: TsLabel; sLabel3: TsLabel; sComboBox1: TsComboBox; sDecimalSpinEdit1: TsDecimalSpinEdit; sDecimalSpinEdit2: TsDecimalSpinEdit; sButton1: TsButton; sButton2: TsButton; sDecimalSpinEdit3: TsDecimalSpinEdit; sLabel4: TsLabel; procedure sButton2Click(Sender: TObject); procedure sButton1Click(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } Transform:TTransformasi; end; var FormShearing: TFormShearing; implementation uses unitUtama; {$R *.dfm} procedure TFormShearing.sButton2Click(Sender: TObject); begin close; end; procedure TFormShearing.sButton1Click(Sender: TObject); var sumbu:integer; Ref,shear1,shear2:real; i,index:integer; item:Tgeometri; begin sumbu:=sComboBox1.itemindex; ref:=StrToFloat(sDecimalSpinEdit1.text); shear1:=StrToFloat(sDecimalSpinEdit2.text); shear2:=StrToFloat(sDecimalSpinEdit3.text);
for index:=0 to FormUtama.DaftarGeometri.f.Count-1 do begin item:=FormUtama.DaftarGeometri.f.Items[index]; if item.Aktif=true then for i:=0 to item.jumTitik do begin Transform.nolkanTransformasi; Transform.Shearing(sumbu+1,ref,shear1,shear2); Transform.Transform(item.Titik[i],item.Titik[i]); FormUtama.sMemo1.Lines.Add('Titik'+IntToStr(i)+' ('+ Format('%.2f',[item.titik[i].posX])+' '+ Format('%.2f',[item.titik[i].posY])+' '+ Format('%.2f',[item.titik[i].posZ])+')'); end; FormUtama.DaftarGeometri.f.Items[index]:=item;
90
end; end; procedure TFormShearing.FormCreate(Sender: TObject); begin Transform:=TTransformasi.Create; Transform.NolkanTransformasi; end; end.
unitTranslasi.pas unit unitTranslasi; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, sCheckBox, sEdit, sSpinEdit, sLabel, sSkinProvider, sSkinManager, sButton, sComboBox,openGL,Transformasi; type TFormTranslasi = class(TForm) sSkinManager1: TsSkinManager; sSkinProvider1: TsSkinProvider; sLabel1: TsLabel; sLabel2: TsLabel; sLabel3: TsLabel; sDecimalSpinEdit1: TsDecimalSpinEdit; sDecimalSpinEdit2: TsDecimalSpinEdit; sDecimalSpinEdit3: TsDecimalSpinEdit; sButton1: TsButton; sButton2: TsButton; procedure sButton1Click(Sender: TObject); procedure sButton2Click(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private declarations } Transform:TTransformasi; public { Public declarations } end; var FormTranslasi: TFormTranslasi; implementation uses unitUtama, Geometri; {$R *.dfm} procedure TFormTranslasi.sButton1Click(Sender: TObject); var x,y,z:GLFloat; i,index:integer; item:Tgeometri; begin x:=StrToFloat(sDecimalSpinEdit1.text); y:=StrToFloat(sDecimalSpinEdit2.text); z:=StrToFloat(sDecimalSpinEdit3.text); for index:=0 to FormUtama.DaftarGeometri.f.Count-1 do begin
91
item:=FormUtama.DaftarGeometri.f.Items[index]; if item.Aktif=true then for i:=0 to item.jumTitik do begin Transform.nolkanTransformasi; Transform.Translasi(x,y,z); Transform.Transform(item.Titik[i],item.Titik[i]); FormUtama.sMemo1.Lines.Add('Titik'+IntToStr(i)+' ('+ Format('%.2f',[item.titik[i].posX])+' '+ Format('%.2f',[item.titik[i].posY])+' '+ Format('%.2f',[item.titik[i].posZ])+')'); end; FormUtama.DaftarGeometri.f.Items[index]:=item; end; end; procedure TFormTranslasi.sButton2Click(Sender: TObject); begin close; end; procedure TFormTranslasi.FormCreate(Sender: TObject); begin Transform:=TTransformasi.Create; Transform.NolkanTransformasi; end; end.
unitAbout.pas unit unitAbout; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, sSkinProvider, sSkinManager; type TFormAbout = class(TForm) Image1: TImage; Label1: TLabel; Shape1: TShape; Label2: TLabel; Label3: TLabel; private { Private declarations } public { Public declarations } end; var FormAbout: TFormAbout; implementation {$R *.dfm} end.
Geometri.pas unit Geometri; interface
92
uses OpenGL,classes,SysUtils,Math,OBJloader; type Ttitik3d = record posX,posY,posZ:GLFloat; end; TArrTitik3d=Array[1..8]of Ttitik3d; Tgeometri = class(Tobject) public nama:String; index:integer; jenis:string; pusat:Ttitik3d; jumTitik:integer; titik:array of Ttitik3d; sudut:GLFloat; Aktif:Boolean; warna:array [0..3] of GLfloat; procedure Gambar;Virtual; end; Tpiramid = class(TGeometri) public tinggi,sisi:GLFloat; Constructor create(pTinggi,pSisi:GLfloat;titikPusat:Ttitik3d); procedure Gambar;override; end; Tkubus = class(Tgeometri) public sisi:GLfloat; constructor create(pSisi:GLFloat;titikPusat:Ttitik3d); procedure Gambar;override; end; TSilinder = class(Tgeometri) public Radius,tinggi:GLfloat; constructor Create(pRadius,pTinggi:GLfloat;titikPusat:Ttitik3d); procedure Gambar;override; end; Tmeja = class(Tgeometri) public constructor Create(titikPusat:TTitik3d); procedure Gambar;override; end; Tkursi = class(Tgeometri) public constructor Create(titikPusat:TTitik3d); procedure Gambar;override; end; TOBJLoader = class(Tgeometri) private titikMin,titikMax:Ttitik3d; procedure hitungMinMax(i:integer); procedure gambarKotak; public m:Tmodel; berkas:string;
93
constructor create(fileObj:string); procedure Gambar;override; end; TDaftarGeometri=class(TObject) public f:Tlist; constructor Create(Owner:Tcomponent); destructor Destroy;override; procedure TambahGeometri(var O:TGeometri); procedure Gambar; end; TGrid = class(Tobject) public warna:array [0..3] of GLfloat; procedure Gambar; end; implementation uses unitUtama; procedure buatTitik(titik:Ttitik3d); begin glVertex3f(titik.posX,titik.posY,titik.posZ); end; procedure buatSisi(titik1,titik2,titik3,titik4:Ttitik3d); begin buatTitik(titik1);buatTitik(titik2); buatTitik(titik3);buatTitik(titik4); end; procedure buatKotak(titik1,titik2,titik3,titik4,titik5,titik6, titik7,titik8:Ttitik3d); begin buatSisi(titik1,titik2,titik3,titik4);//Atas buatSisi(titik5,titik6,titik7,titik8);//Bawah buatSisi(titik1,titik2,titik6,titik5);//Depan buatSisi(titik3,titik4,titik8,titik7);//Belakang buatSisi(titik1,titik5,titik8,titik4);//Kiri buatSisi(titik2,titik3,titik7,titik6);//Kanan end; procedure TGeometri.Gambar; begin end; procedure Tgrid.Gambar; var i:integer; warna:array [0..3] of GLfloat; begin warna[0]:=0.0; warna[2]:=0.0; warna[1]:=0.0; warna[3]:=0.0; glMaterialfv(GL_FRONT, GL_DIFFUSE, @warna); glPushMAtrix(); for i:=-10 to 10 do begin if i<>0 then begin glBegin(GL_LINES); glVertex(i,0,-10);glVertex(i,0,10);
94
glEnd; glBegin(GL_LINES); glVertex(-10,0,i);glVertex(10,0,i); glEnd; end; end; glBegin(GL_LINES); glVertex(-10,0,0);glVertex(0,0,0); glVertex(0,0,-10);glVertex(0,0,0); glEnd; warna[0]:=0.0;warna[1]:=0.0;warna[2]:=1.0;warna[3]:=1.0; glMaterialfv(GL_FRONT, GL_DIFFUSE, @warna); glBegin(GL_LINES); glVertex(0,0,10);glVertex(0,0,0); warna[0]:=0.0;warna[1]:=1.0;warna[2]:=0.0;warna[3]:=1.0; glMaterialfv(GL_FRONT, GL_DIFFUSE, @warna); glVertex(0,10,0);glVertex(0,0,0); warna[0]:=1.0;warna[1]:=0.0;warna[2]:=0.0;warna[3]:=1.0; glMaterialfv(GL_FRONT, GL_DIFFUSE, @warna); glVertex(10,0,0);glVertex(0,0,0); glEnd; glPopMatrix(); end; constructor Tpiramid.create(pTinggi,pSisi:GLfloat;titikPusat:Ttitik3d); var stghSisi:GLfloat; begin self.tinggi:=pTinggi; self.sisi:=pSisi; self.pusat:=titikPusat; self.jenis:='Piramid'; jumTitik:=6; setLength(titik,jumTitik+1); stghSisi:=sisi/2; //buat titik pusat awal titik[0].posX:=pusat.posX; titik[0].posY:=pusat.posY; titik[0].posZ:=pusat.posZ; //buat titik puncak (titik 1) awal titik[1].posX:=pusat.posX; titik[1].posY:=Pusat.posY+tinggi/2; titik[1].posZ:=pusat.posZ; //buat titik 2 awal titik[2].posX:=pusat.posX-stghSisi; titik[2].posY:=Pusat.posY-tinggi/2; titik[2].posZ:=pusat.posZ+stghSisi; //buat titik3 awal titik[3].posX:=pusat.posX+stghSisi; titik[3].posY:=Pusat.posY-tinggi/2; titik[3].posZ:=pusat.posZ+stghSisi; //buat titik 4 awal titik[4].posX:=pusat.posX+stghSisi; titik[4].posY:=Pusat.posY-tinggi/2; titik[4].posZ:=pusat.posZ-stghSisi; //buat titik 5 awal titik[5].posX:=pusat.posX-stghSisi; titik[5].posY:=Pusat.posY-tinggi/2; titik[5].posZ:=pusat.posZ-stghSisi; //buat titik 6 awal titik[6].posX:=pusat.posX-stghSisi; titik[6].posY:=Pusat.posY-tinggi/2;
95
titik[6].posZ:=pusat.posZ+stghSisi; end; procedure TPiramid.Gambar; var i,j:integer; begin // RED GREEN BLUE ALPHA warna[0]:=0.0;warna[1]:=0.5;warna[2]:=0.0;warna[3]:=1.0; //Gambar highlight jika objek terpilih if aktif=true then begin // RED GREEN BLUE ALPHA warna[0]:=0.0;warna[1]:=1.0;warna[2]:=0.0;warna[3]:=1.0; end; glPushMAtrix(); for j:=0 to 1 do begin if j= 1 then begin glLineWidth(1.5); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); warna[0]:=0.0;warna[1]:=0.0;warna[2]:=0.0; end; glMaterialfv(GL_FRONT, GL_DIFFUSE, @warna); //Gambar atas glBegin(GL_TRIANGLE_FAN); for i:=1 to 6 do glVertex3f(titik[i].posX,titik[i].posY,titik[i].posZ); glEnd; //Gambar alas glBegin(GL_QUADS); for i:=2 to 5 do glVertex3f(titik[i].posX,titik[i].posY,titik[i].posZ); glEnd; if j= 1 then begin glLineWidth(1.0); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); end; end; glPopMAtrix(); end; constructor Tkubus.create(pSisi:GLFloat;titikPusat:Ttitik3d); var stghSisi:GLfloat; begin self.sisi:=pSisi; self.pusat:=titikPusat; jumTitik:=8; setLength(titik,jumTitik+1); self.jenis:='Kubus'; stghSisi:=sisi/2; //titik pusat titik[0].posX:=pusat.posX; titik[0].posY:=pusat.posY; titik[0].posZ:=pusat.posZ; //titik 1 self.titik[1].posX:=pusat.posX-StghSisi; titik[1].posY:=pusat.posY-StghSisi; titik[1].posZ:=pusat.posZ+StghSisi; //titik 2 titik[2].posX:=pusat.posX+StghSisi; titik[2].posY:=pusat.posY-StghSisi; titik[2].posZ:=pusat.posZ+StghSisi;
96
//titik 3 titik[3].posX:=pusat.posX+StghSisi; titik[3].posY:=pusat.posY-StghSisi; titik[3].posZ:=pusat.posZ-StghSisi; //titik 4 titik[4].posX:=pusat.posX-StghSisi; titik[4].posY:=pusat.posY-StghSisi; titik[4].posZ:=pusat.posZ-StghSisi; //titik 5 titik[5].posX:=pusat.posX-StghSisi; titik[5].posY:=pusat.posY+StghSisi; titik[5].posZ:=pusat.posZ+StghSisi; //titik 6 titik[6].posX:=pusat.posX+StghSisi; titik[6].posY:=pusat.posY+StghSisi; titik[6].posZ:=pusat.posZ+StghSisi; //titik 7 titik[7].posX:=pusat.posX+StghSisi; titik[7].posY:=pusat.posY+StghSisi; titik[7].posZ:=pusat.posZ-StghSisi; //titik 8 titik[8].posX:=pusat.posX-StghSisi; titik[8].posY:=pusat.posY+StghSisi; titik[8].posZ:=pusat.posZ-StghSisi; end; procedure Tkubus.Gambar; var j:integer; begin // RED GREEN BLUE ALPHA warna[0]:=0.0;warna[1]:=0.0;warna[2]:=0.5;warna[3]:=1.0; //Gambar highlight jika objek terpilih if aktif=true then begin // RED GREEN BLUE ALPHA warna[0]:=0.0;warna[1]:=0.0;warna[2]:=1.0;warna[3]:=1.0; end; glPushMAtrix(); for j:=0 to 1 do begin if j= 1 then begin glLineWidth(1.5); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); warna[0]:=0.0;warna[1]:=0.0;warna[2]:=0.0; end; glMaterialfv(GL_FRONT, GL_DIFFUSE, @warna); glBegin(GL_QUADS); //Sisi Depan glVertex3f(titik[1].posX,titik[1].posY,titik[1].posZ); glVertex3f(titik[2].posX,titik[2].posY,titik[2].posZ); glVertex3f(titik[6].posX,titik[6].posY,titik[6].posZ); glVertex3f(titik[5].posX,titik[5].posY,titik[5].posZ); //Sisi Belakang glVertex3f(titik[4].posX,titik[4].posY,titik[4].posZ); glVertex3f(titik[3].posX,titik[3].posY,titik[3].posZ); glVertex3f(titik[7].posX,titik[7].posY,titik[7].posZ); glVertex3f(titik[8].posX,titik[8].posY,titik[8].posZ); //sisi kiri glVertex3f(titik[4].posX,titik[4].posY,titik[4].posZ); glVertex3f(titik[1].posX,titik[1].posY,titik[1].posZ); glVertex3f(titik[5].posX,titik[5].posY,titik[5].posZ); glVertex3f(titik[8].posX,titik[8].posY,titik[8].posZ); //sisi kanan glVertex3f(titik[2].posX,titik[2].posY,titik[2].posZ);
97
glVertex3f(titik[3].posX,titik[3].posY,titik[3].posZ); glVertex3f(titik[7].posX,titik[7].posY,titik[7].posZ); glVertex3f(titik[6].posX,titik[6].posY,titik[6].posZ); //sisi atas glVertex3f(titik[5].posX,titik[5].posY,titik[5].posZ); glVertex3f(titik[6].posX,titik[6].posY,titik[6].posZ); glVertex3f(titik[7].posX,titik[7].posY,titik[7].posZ); glVertex3f(titik[8].posX,titik[8].posY,titik[8].posZ); //sisi bawah glVertex3f(titik[1].posX,titik[1].posY,titik[1].posZ); glVertex3f(titik[2].posX,titik[2].posY,titik[2].posZ); glVertex3f(titik[3].posX,titik[3].posY,titik[3].posZ); glVertex3f(titik[4].posX,titik[4].posY,titik[4].posZ); glEnd; if j= 1 then begin glLineWidth(1.0); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); end; end; glPopMatrix; end; constructor Tsilinder.Create(pRadius,pTinggi:GLfloat;titikPusat:Ttitik3d); var i:integer; sudut,totalSudut,stghTinggi:real; begin //mengeset sudut yang dibentuk tiap potongan self.Radius:=pRadius; Self.tinggi:=pTinggi; self.pusat:=TitikPusat; jumTitik:=32; self.jenis:='Silinder'; setLength(titik,jumTitik+1); totalSudut:=0; sudut:=360/16; stghTinggi:=tinggi/2; //memberi nilai x,y,z pada titik yang telah dibuat //titik 0 = titik pusat Titik[0].posX:=Pusat.posX; Titik[0].posY:=Pusat.posY; Titik[0].posZ:=Pusat.posZ; //titik 1-2*potongan for i:=1 to 16 do begin totalSudut:=totalSudut+sudut; titik[i].posX:=titik[0].posX+Cos(totalSudut*2*PI/360)*radius; titik[i].posY:=titik[0].posY+stghTinggi; titik[i].posZ:=titik[0].posZ+Sin(totalSudut*2*PI/360)*radius; end; for i:=17 to 32 do begin totalSudut:=totalSudut+sudut; titik[i].posX:=titik[0].posX+Cos(totalSudut*2*PI/360)*radius; titik[i].posY:=titik[0].posY-stghTinggi; titik[i].posZ:=titik[0].posZ+Sin(totalSudut*2*PI/360)*radius; end; end; procedure TSilinder.Gambar; var i,j:integer;
98
begin // RED GREEN BLUE ALPHA warna[0]:=0.5;warna[1]:=0.0;warna[2]:=0.0;warna[3]:=1.0; //Gambar highlight jika objek terpilih if aktif=true then begin // RED GREEN BLUE ALPHA warna[0]:=1.0;warna[1]:=0.0;warna[2]:=0.0;warna[3]:=1.0; end; glPushMAtrix(); for j:=0 to 1 do begin if j= 1 then begin glLineWidth(1.5); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); warna[0]:=0.0;warna[1]:=0.0;warna[2]:=0.0; end; glMaterialfv(GL_FRONT, GL_DIFFUSE, @warna); //Tutup silinder glBegin(GL_POLYGON); for i:=1 to 16 do begin glVertex3f(titik[i].posX,titik[i].posY,titik[i].posZ); end; glEnd; //alas silinder glBegin(GL_POLYGON); for i:=17 to 32 do begin glVertex3f(titik[i].posX,titik[i].posY,titik[i].posZ); end; glEnd; //Badan silinder i:=1; glBegin(GL_QUAD_STRIP); while i<=16 do begin glVertex3f(titik[i].posX,titik[i].posY,titik[i].posZ); glVertex3f(titik[i+16].posX,titik[i+16].posY,titik[i+16].posZ); i:=i+1; end; glVertex3f(titik[1].posX,titik[1].posY,titik[1].posZ); glVertex3f(titik[17].posX,titik[17].posY,titik[17].posZ); glEnd; if j= 1 then begin glLineWidth(1.0); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); end; end; glPopMatrix; end;
constructor Tmeja.Create(titikPusat:TTitik3d); begin self.pusat:=titikPusat; jumTitik:=40; self.jenis:='Meja'; setLength(titik,jumTitik+1); //TITIK PUAT MEJA================================================ //titik pusat
99
titik[0].posX:=pusat.posX; titik[0].posY:=pusat.posY; titik[0].posZ:=pusat.posZ; //BAGIAN ATAS MEJA=============================================== //titik 1 titik[1].posX:=pusat.posX-0.5; titik[1].posY:=pusat.posY+0.4; titik[1].posZ:=pusat.posZ+0.5; //titik 2 titik[2].posX:=pusat.posX+0.5; titik[2].posY:=pusat.posY+0.4; titik[2].posZ:=pusat.posZ+0.5; //titik 3 titik[3].posX:=pusat.posX+0.5; titik[3].posY:=pusat.posY+0.4; titik[3].posZ:=pusat.posZ-0.5; //titik 4 titik[4].posX:=pusat.posX-0.5; titik[4].posY:=pusat.posY+0.4; titik[4].posZ:=pusat.posZ-0.5; //titik 5 titik[5].posX:=pusat.posX-0.5; titik[5].posY:=pusat.posY+0.5; titik[5].posZ:=pusat.posZ+0.5; //titik 6 titik[6].posX:=pusat.posX+0.5; titik[6].posY:=pusat.posY+0.5; titik[6].posZ:=pusat.posZ+0.5; //titik 7 titik[7].posX:=pusat.posX+0.5; titik[7].posY:=pusat.posY+0.5; titik[7].posZ:=pusat.posZ-0.5; //titik 8 titik[8].posX:=pusat.posX-0.5; titik[8].posY:=pusat.posY+0.5; titik[8].posZ:=pusat.posZ-0.5; //KAKI MEJA BAGIAN DEPAN KIRI====================================== //titik 9 titik[9].posX:=pusat.posX-0.4; titik[9].posY:=pusat.posY-0.5; titik[9].posZ:=pusat.posZ+0.4; //titik 10 titik[10].posX:=pusat.posX-0.3; titik[10].posY:=pusat.posY-0.5; titik[10].posZ:=pusat.posZ+0.4; //titik 11 titik[11].posX:=pusat.posX-0.3; titik[11].posY:=pusat.posY-0.5; titik[11].posZ:=pusat.posZ+0.3; //titik 12 titik[12].posX:=pusat.posX-0.4; titik[12].posY:=pusat.posY-0.5; titik[12].posZ:=pusat.posZ+0.3; //titik 13 titik[13].posX:=pusat.posX-0.4; titik[13].posY:=pusat.posY+0.4; titik[13].posZ:=pusat.posZ+0.4; //titik 14 titik[14].posX:=pusat.posX-0.3; titik[14].posY:=pusat.posY+0.4; titik[14].posZ:=pusat.posZ+0.4; //titik 15 titik[15].posX:=pusat.posX-0.3; titik[15].posY:=pusat.posY+0.4; titik[15].posZ:=pusat.posZ+0.3;
100
//titik 16 titik[16].posX:=pusat.posX-0.4; titik[16].posY:=pusat.posY+0.4; titik[16].posZ:=pusat.posZ+0.3; //KAKI MEJA BAGIAN DEPAN KANAN====================================== //titik 17 titik[17].posX:=pusat.posX+0.4; titik[17].posY:=pusat.posY-0.5; titik[17].posZ:=pusat.posZ+0.4; //titik 18 titik[18].posX:=pusat.posX+0.3; titik[18].posY:=pusat.posY-0.5; titik[18].posZ:=pusat.posZ+0.4; //titik 19 titik[19].posX:=pusat.posX+0.3; titik[19].posY:=pusat.posY-0.5; titik[19].posZ:=pusat.posZ+0.3; //titik 20 titik[20].posX:=pusat.posX+0.4; titik[20].posY:=pusat.posY-0.5; titik[20].posZ:=pusat.posZ+0.3; //titik 21 titik[21].posX:=pusat.posX+0.4; titik[21].posY:=pusat.posY+0.4; titik[21].posZ:=pusat.posZ+0.4; //titik 22 titik[22].posX:=pusat.posX+0.3; titik[22].posY:=pusat.posY+0.4; titik[22].posZ:=pusat.posZ+0.4; //titik 23 titik[23].posX:=pusat.posX+0.3; titik[23].posY:=pusat.posY+0.4; titik[23].posZ:=pusat.posZ+0.3; //titik 24 titik[24].posX:=pusat.posX+0.4; titik[24].posY:=pusat.posY+0.4; titik[24].posZ:=pusat.posZ+0.3; //KAKI MEJA BAGIAN BELAKANG KIRI====================================== //titik 25 titik[25].posX:=pusat.posX-0.4; titik[25].posY:=pusat.posY-0.5; titik[25].posZ:=pusat.posZ-0.4; //titik 26 titik[26].posX:=pusat.posX-0.3; titik[26].posY:=pusat.posY-0.5; titik[26].posZ:=pusat.posZ-0.4; //titik 27 titik[27].posX:=pusat.posX-0.3; titik[27].posY:=pusat.posY-0.5; titik[27].posZ:=pusat.posZ-0.3; //titik 28 titik[28].posX:=pusat.posX-0.4; titik[28].posY:=pusat.posY-0.5; titik[28].posZ:=pusat.posZ-0.3; //titik 29 titik[29].posX:=pusat.posX-0.4; titik[29].posY:=pusat.posY+0.4; titik[29].posZ:=pusat.posZ-0.4; //titik 30 titik[30].posX:=pusat.posX-0.3; titik[30].posY:=pusat.posY+0.4; titik[30].posZ:=pusat.posZ-0.4; //titik 31 titik[31].posX:=pusat.posX-0.3;
101
titik[31].posY:=pusat.posY+0.4; titik[31].posZ:=pusat.posZ-0.3; //titik 32 titik[32].posX:=pusat.posX-0.4; titik[32].posY:=pusat.posY+0.4; titik[32].posZ:=pusat.posZ-0.3; //KAKI MEJA BAGIAN BELAKANG KANAN====================================== //titik 33 titik[33].posX:=pusat.posX+0.4; titik[33].posY:=pusat.posY-0.5; titik[33].posZ:=pusat.posZ-0.4; //titik 34 titik[34].posX:=pusat.posX+0.3; titik[34].posY:=pusat.posY-0.5; titik[34].posZ:=pusat.posZ-0.4; //titik 35 titik[35].posX:=pusat.posX+0.3; titik[35].posY:=pusat.posY-0.5; titik[35].posZ:=pusat.posZ-0.3; //titik 36 titik[36].posX:=pusat.posX+0.4; titik[36].posY:=pusat.posY-0.5; titik[36].posZ:=pusat.posZ-0.3; //titik 37 titik[37].posX:=pusat.posX+0.4; titik[37].posY:=pusat.posY+0.4; titik[37].posZ:=pusat.posZ-0.4; //titik 38 titik[38].posX:=pusat.posX+0.3; titik[38].posY:=pusat.posY+0.4; titik[38].posZ:=pusat.posZ-0.4; //titik 39 titik[39].posX:=pusat.posX+0.3; titik[39].posY:=pusat.posY+0.4; titik[39].posZ:=pusat.posZ-0.3; //titik 40 titik[40].posX:=pusat.posX+0.4; titik[40].posY:=pusat.posY+0.4; titik[40].posZ:=pusat.posZ-0.3; end; procedure Tmeja.Gambar; var j:integer; begin // RED GREEN BLUE ALPHA warna[0]:=0.0;warna[1]:=0.5;warna[2]:=0.5;warna[3]:=1.0; //Gambar highlight jika objek terpilih if aktif=true then begin // RED GREEN BLUE ALPHA warna[0]:=0.0;warna[1]:=1.0;warna[2]:=1.0;warna[3]:=1.0; end; glPushMAtrix(); for j:=0 to 1 do begin if j= 1 then begin glLineWidth(1.5); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); warna[0]:=0.0;warna[1]:=0.0;warna[2]:=0.0; end; glMaterialfv(GL_FRONT, GL_DIFFUSE, @warna); //Gambar meja bagian atas
102
glBegin(GL_QUADS); buatKotak(titik[1],titik[2],titik[3],titik[4],titik[5], titik[6],titik[7],titik[8]); glEnd; //Gambar Kaki meja kiri depan glBegin(GL_QUADS); buatKotak(titik[9],titik[10],titik[11],titik[12],titik[13], titik[14],titik[15],titik[16]); glEnd; //Gambar Kaki meja kanan depan glBegin(GL_QUADS); buatKotak(titik[17],titik[18],titik[19],titik[20],titik[21], titik[22],titik[23],titik[24]); glEnd; //Gambar Kaki meja kiri belakang glBegin(GL_QUADS); buatKotak(titik[25],titik[26],titik[27],titik[28],titik[29], titik[30],titik[31],titik[32]); glEnd; //Gambar Kaki meja kanan belakang glBegin(GL_QUADS); buatKotak(titik[33],titik[34],titik[35],titik[36],titik[37], titik[38],titik[39],titik[40]); glEnd; if j= 1 then begin glLineWidth(1.0); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); end; end; glPopMatrix; end; constructor Tkursi.Create(titikPusat:TTitik3d); begin self.pusat:=titikPusat; jumTitik:=48; self.jenis:='Kursi'; setLength(titik,jumTitik+1); //TITIK PUSAT KURSI================================================ //titik pusat titik[0].posX:=pusat.posX; titik[0].posY:=pusat.posY; titik[0].posZ:=pusat.posZ; //BAGIAN ATAS KURSI=============================================== //titik 1 titik[1].posX:=pusat.posX-0.5; titik[1].posY:=pusat.posY-0.1; titik[1].posZ:=pusat.posZ+0.5; //titik 2 titik[2].posX:=pusat.posX+0.5; titik[2].posY:=pusat.posY-0.1; titik[2].posZ:=pusat.posZ+0.5; //titik 3 titik[3].posX:=pusat.posX+0.5; titik[3].posY:=pusat.posY-0.1; titik[3].posZ:=pusat.posZ-0.5; //titik 4 titik[4].posX:=pusat.posX-0.5; titik[4].posY:=pusat.posY-0.1; titik[4].posZ:=pusat.posZ-0.5; //titik 5 titik[5].posX:=pusat.posX-0.5; titik[5].posY:=pusat.posY+0.0; titik[5].posZ:=pusat.posZ+0.5;
103
//titik 6 titik[6].posX:=pusat.posX+0.5; titik[6].posY:=pusat.posY+0.0; titik[6].posZ:=pusat.posZ+0.5; //titik 7 titik[7].posX:=pusat.posX+0.5; titik[7].posY:=pusat.posY+0.0; titik[7].posZ:=pusat.posZ-0.5; //titik 8 titik[8].posX:=pusat.posX-0.5; titik[8].posY:=pusat.posY+0.0; titik[8].posZ:=pusat.posZ-0.5; //KAKI KURSI BAGIAN DEPAN KIRI====================================== //titik 9 titik[9].posX:=pusat.posX-0.4; titik[9].posY:=pusat.posY-0.5; titik[9].posZ:=pusat.posZ+0.4; //titik 10 titik[10].posX:=pusat.posX-0.3; titik[10].posY:=pusat.posY-0.5; titik[10].posZ:=pusat.posZ+0.4; //titik 11 titik[11].posX:=pusat.posX-0.3; titik[11].posY:=pusat.posY-0.5; titik[11].posZ:=pusat.posZ+0.3; //titik 12 titik[12].posX:=pusat.posX-0.4; titik[12].posY:=pusat.posY-0.5; titik[12].posZ:=pusat.posZ+0.3; //titik 13 titik[13].posX:=pusat.posX-0.4; titik[13].posY:=pusat.posY-0.1; titik[13].posZ:=pusat.posZ+0.4; //titik 14 titik[14].posX:=pusat.posX-0.3; titik[14].posY:=pusat.posY-0.1; titik[14].posZ:=pusat.posZ+0.4; //titik 15 titik[15].posX:=pusat.posX-0.3; titik[15].posY:=pusat.posY-0.1; titik[15].posZ:=pusat.posZ+0.3; //titik 16 titik[16].posX:=pusat.posX-0.4; titik[16].posY:=pusat.posY-0.1; titik[16].posZ:=pusat.posZ+0.3; //KAKI MEJA BAGIAN DEPAN KANAN====================================== //titik 17 titik[17].posX:=pusat.posX+0.4; titik[17].posY:=pusat.posY-0.5; titik[17].posZ:=pusat.posZ+0.4; //titik 18 titik[18].posX:=pusat.posX+0.3; titik[18].posY:=pusat.posY-0.5; titik[18].posZ:=pusat.posZ+0.4; //titik 19 titik[19].posX:=pusat.posX+0.3; titik[19].posY:=pusat.posY-0.5; titik[19].posZ:=pusat.posZ+0.3; //titik 20 titik[20].posX:=pusat.posX+0.4; titik[20].posY:=pusat.posY-0.5; titik[20].posZ:=pusat.posZ+0.3; //titik 21 titik[21].posX:=pusat.posX+0.4; titik[21].posY:=pusat.posY-0.1;
104
titik[21].posZ:=pusat.posZ+0.4; //titik 22 titik[22].posX:=pusat.posX+0.3; titik[22].posY:=pusat.posY-0.1; titik[22].posZ:=pusat.posZ+0.4; //titik 23 titik[23].posX:=pusat.posX+0.3; titik[23].posY:=pusat.posY-0.1; titik[23].posZ:=pusat.posZ+0.3; //titik 24 titik[24].posX:=pusat.posX+0.4; titik[24].posY:=pusat.posY-0.1; titik[24].posZ:=pusat.posZ+0.3; //KAKI KURSI BAGIAN BELAKANG KIRI====================================== //titik 25 titik[25].posX:=pusat.posX-0.4; titik[25].posY:=pusat.posY-0.5; titik[25].posZ:=pusat.posZ-0.4; //titik 26 titik[26].posX:=pusat.posX-0.3; titik[26].posY:=pusat.posY-0.5; titik[26].posZ:=pusat.posZ-0.4; //titik 27 titik[27].posX:=pusat.posX-0.3; titik[27].posY:=pusat.posY-0.5; titik[27].posZ:=pusat.posZ-0.3; //titik 28 titik[28].posX:=pusat.posX-0.4; titik[28].posY:=pusat.posY-0.5; titik[28].posZ:=pusat.posZ-0.3; //titik 29 titik[29].posX:=pusat.posX-0.4; titik[29].posY:=pusat.posY-0.1; titik[29].posZ:=pusat.posZ-0.4; //titik 30 titik[30].posX:=pusat.posX-0.3; titik[30].posY:=pusat.posY-0.1; titik[30].posZ:=pusat.posZ-0.4; //titik 31 titik[31].posX:=pusat.posX-0.3; titik[31].posY:=pusat.posY-0.1; titik[31].posZ:=pusat.posZ-0.3; //titik 32 titik[32].posX:=pusat.posX-0.4; titik[32].posY:=pusat.posY-0.1; titik[32].posZ:=pusat.posZ-0.3; //KAKI KURSI BAGIAN BELAKANG KANAN====================================== //titik 33 titik[33].posX:=pusat.posX+0.4; titik[33].posY:=pusat.posY-0.5; titik[33].posZ:=pusat.posZ-0.4; //titik 34 titik[34].posX:=pusat.posX+0.3; titik[34].posY:=pusat.posY-0.5; titik[34].posZ:=pusat.posZ-0.4; //titik 35 titik[35].posX:=pusat.posX+0.3; titik[35].posY:=pusat.posY-0.5; titik[35].posZ:=pusat.posZ-0.3; //titik 36 titik[36].posX:=pusat.posX+0.4; titik[36].posY:=pusat.posY-0.5; titik[36].posZ:=pusat.posZ-0.3;
105
//titik 37 titik[37].posX:=pusat.posX+0.4; titik[37].posY:=pusat.posY-0.1; titik[37].posZ:=pusat.posZ-0.4; //titik 38 titik[38].posX:=pusat.posX+0.3; titik[38].posY:=pusat.posY-0.1; titik[38].posZ:=pusat.posZ-0.4; //titik 39 titik[39].posX:=pusat.posX+0.3; titik[39].posY:=pusat.posY-0.1; titik[39].posZ:=pusat.posZ-0.3; //titik 40 titik[40].posX:=pusat.posX+0.4; titik[40].posY:=pusat.posY-0.1; titik[40].posZ:=pusat.posZ-0.3; //BAGIAN SANDARAN KURSI=============================================== //titik 41 titik[41].posX:=pusat.posX-0.5; titik[41].posY:=pusat.posY-0.0; titik[41].posZ:=pusat.posZ-0.4; //titik 42 titik[42].posX:=pusat.posX+0.5; titik[42].posY:=pusat.posY-0.0; titik[42].posZ:=pusat.posZ-0.4; //titik 43 titik[43].posX:=pusat.posX+0.5; titik[43].posY:=pusat.posY-0.0; titik[43].posZ:=pusat.posZ-0.5; //titik 44 titik[44].posX:=pusat.posX-0.5; titik[44].posY:=pusat.posY-0.0; titik[44].posZ:=pusat.posZ-0.5; //titik 45 titik[45].posX:=pusat.posX-0.5; titik[45].posY:=pusat.posY+0.5; titik[45].posZ:=pusat.posZ-0.4; //titik 46 titik[46].posX:=pusat.posX+0.5; titik[46].posY:=pusat.posY+0.5; titik[46].posZ:=pusat.posZ-0.4; //titik 47 titik[47].posX:=pusat.posX+0.5; titik[47].posY:=pusat.posY+0.5; titik[47].posZ:=pusat.posZ-0.5; //titik 48 titik[48].posX:=pusat.posX-0.5; titik[48].posY:=pusat.posY+0.5; titik[48].posZ:=pusat.posZ-0.5; end; procedure Tkursi.Gambar; var j:integer; begin // RED GREEN BLUE ALPHA warna[0]:=0.7;warna[1]:=0.0;warna[2]:=0.5;warna[3]:=1.0; //Gambar highlight jika objek terpilih if aktif=true then begin // RED GREEN BLUE ALPHA warna[0]:=1.0;warna[1]:=0.0;warna[2]:=1.0;warna[3]:=1.0; end; glPushMAtrix();
106
for j:=0 to 1 do begin if j= 1 then begin glLineWidth(1.5); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); warna[0]:=0.0;warna[1]:=0.0;warna[2]:=0.0; end; glMaterialfv(GL_FRONT, GL_DIFFUSE, @warna); //Gambar kursi bagian atas glBegin(GL_QUADS); buatKotak(titik[1],titik[2],titik[3],titik[4],titik[5], titik[6],titik[7],titik[8]); glEnd; //Gambar Kaki kursi kiri depan glBegin(GL_QUADS); buatKotak(titik[9],titik[10],titik[11],titik[12],titik[13], titik[14],titik[15],titik[16]); glEnd; //Gambar Kaki kursi kanan depan glBegin(GL_QUADS); buatKotak(titik[17],titik[18],titik[19],titik[20],titik[21], titik[22],titik[23],titik[24]); glEnd; //Gambar Kaki kursi kiri belakang glBegin(GL_QUADS); buatKotak(titik[25],titik[26],titik[27],titik[28],titik[29], titik[30],titik[31],titik[32]); glEnd; //Gambar Kaki kursi kanan belakang glBegin(GL_QUADS); buatKotak(titik[33],titik[34],titik[35],titik[36],titik[37], titik[38],titik[39],titik[40]); glEnd; //Gambar sandaran kursi glBegin(GL_QUADS); buatKotak(titik[41],titik[42],titik[43],titik[44],titik[45], titik[46],titik[47],titik[48]); glend; if j= 1 then begin glLineWidth(1.0); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); end; end; glPopMatrix; end; constructor TDaftarGeometri.Create(Owner:Tcomponent); begin f:=TList.Create; end; destructor TDaftarGeometri.Destroy; begin f.Free; end; procedure TDaftarGeometri.TambahGeometri(var O:TGeometri); var item:TGeometri;i:integer; begin i:=f.Add(O); FormUtama.sMemo1.Lines.add('Index Objek: '+IntToStr(i));
107
item:=f.Items[i]; item.index:=i; f.Items[i]:=item; end; procedure TDaftarGeometri.Gambar; var index:integer; item:Tgeometri; begin for index:=0 to f.Count-1 do begin item:=f.Items[index]; glLoadName(item.index+100); item.Gambar; glEnd(); end; end; Constructor TOBJLoader.create(fileObj:string); var i:integer; begin berkas:=fileObj; m:=LoadModel(berkas); self.jenis:='OBJ'; jumTitik:=m.Vertices; setLength(titik,jumTitik+1); for i:=0 to m.Vertices do begin titik[i].posX:=m.vertex[i].X; titik[i].posY:=m.vertex[i].Y; titik[i].posZ:=m.vertex[i].Z; end; end; procedure TOBJLoader.hitungMinMax(i:integer); begin if titik[i].posX>titikMax.posX then titikMax.posX:=titik[i].posX; if titik[i].posY>titikMax.posY then titikMax.posY:=titik[i].posY; if titik[i].posZ>titikMax.posZ then titikMax.posZ:=titik[i].posZ; if titik[i].posX
108
//sisi kanan glVertex3f(titikMax.posX,titikmin.posY,titikMin.posZ); glVertex3f(titikMax.posX,titikMin.posY,titikMax.posZ); glVertex3f(titikMax.posX,titikMax.posY,titikMax.posZ); glVertex3f(titikMax.posX,titikMax.posY,titikMin.posZ); //sisi atas glVertex3f(titikMin.posX,titikMax.posY,titikMax.posZ); glVertex3f(titikMax.posX,titikMax.posY,titikMax.posZ); glVertex3f(titikMax.posX,titikMax.posY,titikMin.posZ); glVertex3f(titikMin.posX,titikMax.posY,titikMin.posZ); //sisi bawah glVertex3f(titikMin.posX,titikMin.posY,titikMax.posZ); glVertex3f(titikMax.posX,titikMin.posY,titikMax.posZ); glVertex3f(titikMax.posX,titikMin.posY,titikMin.posZ); glVertex3f(titikMin.posX,titikMin.posY,titikMin.posZ); glEnd; end; procedure TOBJLoader.Gambar; var i:integer; begin for i:=0 to m.vertices do begin hitungMinMax(i); m.Vertex[i].X:=titik[i].posX; m.Vertex[i].Y:=titik[i].posY; m.Vertex[i].Z:=titik[i].posZ; end; DrawModel(m); if self.Aktif=true then begin glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); self.gambarKotak; glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); self.titikMin.posX:=titik[0].posX; self.titikMin.posY:=titik[0].posY; self.titikMin.posZ:=titik[0].posZ; self.titikMax.posX:=titik[0].posX;; self.titikMax.posY:=titik[0].posY; self.titikMax.posZ:=titik[0].posZ; end; end;
end.
Transformasi.pas unit Transformasi; interface uses OpenGL,Geometri,vektor,Math,classes,SysUtils,OBJLoader; Type Matriks4x4=array[0..3,0..3] of double; MAtriks1x4=array[0..3] of double; TArTitik3D=array[1..3] of Double; TTransformasi = class(TObject) private Matriks:MAtriks4x4; procedure PerkalianMatriks(Matriks1,Matriks2:Matriks4x4; var Matriks3:Matriks4x4); public procedure MatriksIdentitas(var m:Matriks4x4); procedure Translasi(x,y,z:real); procedure Penskalaan(sx,sy,sz,xc,yc,zc:real);
109
Procedure Procedure procedure procedure procedure end;
Rotasi(sudut:real;xr,yr,zr:real); Shearing(sumbu:integer;ref,shear1,shear2:real); Transform(P:Ttitik3d;var Q:TTitik3d); nolkanTransformasi; ambilPos3d(X,Y:integer;var titik:TArTitik3d);
implementation uses unitUtama; procedure TTransformasi.MatriksIdentitas(var m:Matriks4x4); begin m[0,0]:=1;m[0,1]:=0;m[0,2]:=0;m[0,3]:=0; m[1,0]:=0;m[1,1]:=1;m[1,2]:=0;m[1,3]:=0; m[2,0]:=0;m[2,1]:=0;m[2,2]:=1;m[2,3]:=0; m[3,0]:=0;m[3,1]:=0;m[3,2]:=0;m[3,3]:=1; end; procedure TTransformasi.PerkalianMatriks(Matriks1,Matriks2:Matriks4x4; var Matriks3:Matriks4x4); var baris,kolom:byte; matriksTemp:Matriks4x4; begin for baris:=0 to 3 do begin for kolom:=0 to 3 do begin matriksTemp[baris,kolom]:=Matriks1[baris,0]*Matriks2[0,kolom]+ Matriks1[baris,1]*Matriks2[1,kolom]+ Matriks1[baris,2]*Matriks2[2,kolom]+ Matriks1[baris,3]*Matriks2[3,kolom]; end; end; for baris:=0 to 3 do for kolom:=0 to 3 do Matriks3[baris,kolom]:=matriksTemp[baris,kolom]; end; procedure TTransformasi.Translasi(x,y,z:real); var matriksTranslasi:Matriks4x4; begin MatriksIdentitas(MatriksTranslasi); MAtriksTranslasi[3,0]:=x; MAtriksTranslasi[3,1]:=y; MAtriksTranslasi[3,2]:=z; PerkalianMatriks(MAtriks,MAtriksTranslasi,MAtriks); end; procedure TTransformasi.Penskalaan(sx,sy,sz,xc,yc,zc:real); var matriksPenskalaan:Matriks4x4; begin MatriksIdentitas(matriksPenskalaan); Translasi(-xc,-yc,-zc); matriksPenskalaan[0,0]:=sx; matriksPenskalaan[1,1]:=sy; matriksPenskalaan[2,2]:=sz; PerkalianMatriks(Matriks,matriksPenskalaan,Matriks); Translasi(xc,yc,zc); end; procedure TTransformasi.Rotasi(sudut:real;xr,yr,zr:real); var alpha,betha,radian:real;
110
ryb,rza,ryb_1,rza_1,ry:Matriks4x4; u,u1,u2,s:Ttitik3d; begin MatriksIdentitas(ryb); MatriksIdentitas(rza); MatriksIdentitas(ry); MatriksIdentitas(ryb_1); MatriksIdentitas(rza_1); MatriksIdentitas(Matriks); radian:=sudut*PI/180; if zr<0 then radian:=-radian; u1:=Normalisasi(BuatVektor(1,0,0)); u2:=Normalisasi(buatVektor(0,1,0)); s :=Normalisasi(BuatVektor(xr,yr,zr)); u :=BuatVektor(xr,0,zr); if PanjangVektor(u)=0 then betha:=0 //Sumbu putar berhimpit dengan sumbu Y else begin u:=normalisasi(u); betha:=arcCos(DotProduct(u,u1)); if u.posZ<0 then betha:=-betha; end; alpha:=arcCos(DotProduct(u2,s)); ryb[0,0]:=cos(betha);ryb[0,2]:=-sin(betha); ryb[2,0]:=sin(betha);ryb[2,2]:=cos(betha); //Ry(-betha) perkalianMatriks(Matriks,ryb,Matriks); rza[0,0]:=cos(alpha);rza[0,1]:=sin(alpha); rza[1,0]:=-sin(alpha);rza[1,1]:=cos(alpha); //Ry(-betha)*Rz(-alpha) PerkalianMatriks(MAtriks,rza,Matriks); ry[0,0]:=cos(radian);ry[0,2]:=-sin(radian); ry[2,0]:=sin(radian);ry[2,2]:=cos(radian); //Ry(Degree) PerkalianMatriks(Matriks,ry,Matriks); rza_1[0,0]:=cos(-alpha);rza_1[0,1]:=sin(-alpha); rza_1[1,0]:=-sin(-alpha);rza_1[1,1]:=cos(-alpha); //Rz(degree) PerkalianMAtriks(Matriks,rza_1,MAtriks); ryb_1[0,0]:=cos(-betha);ryb_1[0,2]:=-sin(-betha); ryb_1[2,0]:=sin(-betha);ryb_1[2,2]:=cos(-betha); //Ry(betha) PerkalianMatriks(Matriks,ryb_1,MAtriks); end; Procedure TTransformasi.Shearing(sumbu:integer;ref,shear1,shear2:real); var matriksShearing:Matriks4x4; begin MatriksIdentitas(matriksShearing); if sumbu=1 then begin matriksShearing[3,1]:=-shear1*ref; matriksShearing[3,2]:=-shear2*ref; matriksShearing[0,1]:=shear1; matriksShearing[0,2]:=shear2; end;
111
if sumbu=2 then begin matriksShearing[3,0]:=-shear1*ref; matriksShearing[3,2]:=-shear2*ref; matriksShearing[1,0]:=shear1; matriksShearing[1,2]:=shear2; end; if sumbu=3 then begin matriksShearing[3,0]:=-shear1*ref; matriksShearing[3,1]:=-shear2*ref; matriksShearing[2,0]:=shear1; matriksShearing[2,1]:=shear2; end; PerkalianMatriks(Matriks,matriksShearing,Matriks); end;
procedure TTransformasi.Transform(P:Ttitik3d;var Q:Ttitik3d); begin Q.posX:=P.posX*Matriks[0,0]+P.posY*Matriks[1,0]+ P.posZ*MAtriks[2,0]+1*Matriks[3,0]; Q.posY:=P.posX*Matriks[0,1]+P.posY*Matriks[1,1]+ P.posZ*MAtriks[2,1]+1*Matriks[3,1]; Q.posZ:=P.posX*Matriks[0,2]+P.posY*Matriks[1,2]+ P.posZ*MAtriks[2,2]+1*Matriks[3,2]; end; procedure TTransformasi.nolkanTransformasi; begin MatriksIdentitas(MAtriks); end; Procedure TTransformasi.ambilPos3d(X,Y:integer;var titik:TArTitik3D); var viewport : array[1..4] of Integer; modelview: array[1..16] of Double; proyeksi : array[1..16] of Double; winZ : Single; begin glGetDoublev(GL_MODELVIEW_MATRIX, @modelview); glGetDoublev(GL_PROJECTION_MATRIX,@proyeksi); glGetIntegerv(GL_VIEWPORT,@viewport); //pada delphi jika nilai sama dengan 0 mengembalikan nilai unknown if Y=0 then Y:=1; glReadPixels(X,-Y,1,1,GL_DEPTH_COMPONENT,GL_FLOAT,@winZ); gluUnProject(X,viewport[4]-Y,winZ,@modelview,@proyeksi,@viewport, titik[1],titik[2],titik[3]); end; end.
LAMPIRAN B WAVEFRONT OBJ FILE FORMAT SUMMARY
Wavefront OBJ File Format Summary Also Known As: Wavefront Object, OBJ
Type
3D Vector
Colors
Unlimited
Compression
Uncompressed
Maximum Image Size
Unlimited
Multiple Images Per File Yes Numerical Format
NA
Originator
Wavefront
Platform
UNIX
Supporting Applications Advanced Visualizer See Also
Wavefront RLA
Usage Used to store and exchange 3D data. Comments The Wavefront OBJ format is a useful standard for representing polygonal data in ASCII form. Vendor specifications are available for this format.
Wavefront OBJ (object) files are used by Wavefront's Advanced Visualizer application to store geometric objects composed of lines, polygons, and free-form curves and surfaces. Wavefront is best known for its high-end computer graphics tools, including modeling, animation, and image compositing tools. These programs run on powerful workstations such as those made by Silicon Graphics, Inc. Wavefront OBJ files are often stored with the extension ".obj" following the UNIX convention of lowercase letters for filenames. The most recently documented version of OBJ is v3.0, superseding the previous v2.11 release. Contents: File Organization File Details For Further Information
112
113
In Wavefront's 3D software, geometric object files may be stored in ASCII format (using the ".obj" file extension) or in binary format (using the .MOD extension). The binary format is proprietary and undocumented, so only the ASCII format is described here. The OBJ file format supports lines, polygons, and free-form curves and surfaces. Lines and polygons are described in terms of their points, while curves and surfaces are defined with control points and other information depending on the type of curve. The format supports rational and non-rational curves, including those based on Bezier, B-spline, Cardinal (Catmull-Rom splines), and Taylor equations.
File Organization OBJ files do not require any sort of header, although it is common to begin the file with a comment line of some kind. Comment lines begin with a hash mark (#). Blank space and blank lines can be freely added to the file to aid in formatting and readability. Each non-blank line begins with a keyword and may be followed on the same line with the data for that keyword. Lines are read and processed until the end of the file. Lines can be logically joined with the line continuation character ( \ ) at the end of a line. The following keywords may be included in an OBJ file. In this list, keywords are arranged by data type, and each is followed by a brief description. Vertex data: v Geometric vertices vt Texture vertices vn Vertex normals vp Parameter space vertices Free-form curve/surface attributes: deg Degree bmat Basis matrix step Step size cstype Curve or surface type Elements: p Point l Line f Face curv Curve curv2 2D curve surf Surface Free-form curve/surface body statements: parm Parameter values trim Outer trimming loop hole Inner trimming loop scrv Special curve sp Special point end End statement Connectivity between free-form surfaces: con Connect Grouping: g Group name s Smoothing group
114
mg Merging group o Object name Display/render attributes: bevel Bevel interpolation c_interp Color interpolation d_interp Dissolve interpolation lod Level of detail usemtl Material name mtllib Material library shadow_obj Shadow casting trace_obj Ray tracing ctech Curve approximation technique stech Surface approximation technique
File Details The most commonly encountered OBJ files contain only polygonal faces. To describe a polygon, the file first describes each point with the "v" keyword, then describes the face with the "f" keyword. The line of a face command contains the enumerations of the points in the face, as 1based indices into the list of points, in the order they occurred in the file. For example, the following describes a simple triangle: # Simple Wavefront file v 0.0 0.0 0.0 v 0.0 1.0 0.0 v 1.0 0.0 0.0 f123
It is also possible to reference points using negative indices. This makes it easy to describe the points in a face, then the face, without the need to store a large list of points and their indexes. In this way, "v" commands and "f" commands can be interspersed. v -0.500000 0.000000 0.400000 v -0.500000 0.000000 -0.800000 v -0.500000 1.000000 -0.800000 v -0.500000 1.000000 0.400000 f -4 -3 -2 -1
OBJ files do not contain color definitions for faces, although they can reference materials that are stored in a separate material library file. The material library can be loaded using the "mtllib" keyword. The material library contains the definitions for the RGB values for the material's diffuse, ambient, and specular colors, along with other characteristics such as specularity, refraction, transparency, etc. The OBJ file references materials by name with the "usemtl" keyword. All faces that follow are given the attributes of this material until the next "usemtl" command is encountered. Faces and surfaces can be assigned into named groups with the "g" keyword. This is used to create convenient sub-objects to make it easier to edit and animate 3D models. Faces can belong to more than one group. The following demonstrate more complicated examples of smooth surfaces of different types, material assignment, line continuation, and grouping.
Cube with Materials # This cube has a different material
115
# applied to each of its faces. mtllib master.mtl v 0.000000 2.000000 v 0.000000 0.000000 v 2.000000 0.000000 v 2.000000 2.000000 v 0.000000 2.000000 v 0.000000 0.000000 v 2.000000 0.000000 v 2.000000 2.000000 # 8 vertices g front usemtl red f1234 g back usemtl blue f8765 g right usemtl green f4378 g top usemtl gold f5148 g left usemtl orange f5621 g bottom usemtl purple f2673 # 6 elements
2.000000 2.000000 2.000000 2.000000 0.000000 0.000000 0.000000 0.000000
Bezier Patch # 3.0 Bezier patch v -5.000000 -5.000000 0.000000 v -5.000000 -1.666667 0.000000 v -5.000000 1.666667 0.000000 v -5.000000 5.000000 0.000000 v -1.666667 -5.000000 0.000000 v -1.666667 -1.666667 0.000000 v -1.666667 1.666667 0.000000 v -1.666667 5.000000 0.000000 v 1.666667 -5.000000 0.000000 v 1.666667 -1.666667 0.000000 v 1.666667 1.666667 0.000000 v 1.666667 5.000000 0.000000 v 5.000000 -5.000000 0.000000 v 5.000000 -1.666667 0.000000 v 5.000000 1.666667 0.000000 v 5.000000 5.000000 0.000000 # 16 vertices cstype bezier deg 3 3 # Example of line continuation surf 0.000000 1.000000 0.000000 1.000000 13 14 \ 15 16 9 10 11 12 5 6 7 8 1 2 3 4 parm u 0.000000 1.000000 parm v 0.000000 1.000000 end # 1 element
Cardinal Curve # 3.0 Cardinal curve v 0.940000 1.340000 0.000000 v -0.670000 0.820000 0.000000 v -0.770000 -0.940000 0.000000 v 1.030000 -1.350000 0.000000 v 3.070000 -1.310000 0.000000 # 6 vertices cstype cardinal deg 3 curv 0.000000 3.000000 1 2 3 4 5 6 parm u 0.000000 1.000000 2.000000 3.000000 end
116
# 1 element
Texture-Mapped Square # A 2 x 2 square mapped with a 1 x 1 square # texture stretched to fit the square exactly. mtllib master.mtl v 0.000000 2.000000 0.000000 v 0.000000 0.000000 0.000000 v 2.000000 0.000000 0.000000 v 2.000000 2.000000 0.000000 vt 0.000000 1.000000 0.000000 vt 0.000000 0.000000 0.000000 vt 1.000000 0.000000 0.000000 vt 1.000000 1.000000 0.000000 # 4 vertices usemtl wood # The first number is the point, # then the slash, # and the second is the texture point f 1/1 2/2 3/3 4/4 # 1 element
For Further Information For further information about the Wavefront OBJ format, see the specification. You can also contact: Wavefront Technologies 530 East Montecito Street Santa Barbara, CA 93103 Voice: 805-962-8117 FAX: 805-963-0410 WWW: http://www.aw.sgi.com/ Wavefront also maintains a toll-free support number and a BBS for its customers. There are many Wavefront user groups, too.
This page is taken from the Encyclopedia of Graphics File Formats and is licensed by O'Reilly under the Creative Common/Attribution license. More Resources
Diambil dari http://www.fileformat.info/resource/book/1565921615/index.htm
LAMPIRAN C PERINTAH OPENGL PADA APLIKASI GRAFIKA KOMPUTER UNTUK TRANSFORMASI 3D
1.
glClearColor(R, G, B, A); Perintah untuk memberihkan layar dengan warna R, G, B, dan A.
2.
glShadeModel(jenisShading); Jenis shading yang digunakan, yaitu GL_FLAT untuk flat shading dan GL_SMOOTH untuk gouround shading.
3.
glClearDepth(1.0); Depth value yang digunakan ketika membersihkan depth buffer.
4.
glEnable(GL_DEPTH_TEST); Mengaktifkan pengujian depth.
5.
glEnable(GL_NORMALIZE); Mengaktifkan nomalisasi vektor normal.
6.
glDepthFunc(GL_LESS); Jenis pengujian depth yang akan dilakukan. GL_LESS hanya akan melewatkan nilai z yang kurang dari nilai z yang disimpan pada depth buffer.
7.
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST); Meningkatkan kualitas interpolasi warna dan koordinat tekstur pada proyeksi perspektif.
8.
glEnable(GL_LIGHTING); Mengaktifkan pencahayaan.
9.
glEnable(GL_LIGHT0); Mengaktifkan sumber cahaya 0.
10. glLightfv(GL_LIGHT0,GL_POSITION,@light_position); Menempatkan sumber cahaya 0 pada posisi light_position. 11. glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); Membersihkan bit-bit pada color buffer dan depth buffer. 12. glLoadIdentity(); Memuat matriks identitas. 13. glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
105
106
Mode ransterisasi poligon. GL_FRONT_AND_BACK untuk rasterisasi bagian muka dan belakang poligon. GL_LINE untuk mode wireframe, GL_FILL untuk mode rasterisasi penuh, dan GL_POINT untuk mode titiktitik. 14. glViewport(0, 0, 800,600); Membuat viewport dengan ukuran lebar 800 dan tinggi 600 dari posisi 0, 0. 15. glMatrixMode(GL_PROJECTION); Mengubah mode matriks ke mode proyeksi. GL_MODELVIEW untuk mode pemodelan–membentuk objek geometri. 16. gluPerspective(45.0, Width/ Height, 1.0, 500.0); Menggunakan proyeksi perspektif dengan sudut 45o, rasio width/height, Znear=1, dan Zfar=500. 17. gluLookAt(xs, ys, zs, xf, yf, zf, 0.0,1.0,0.0); Menggunakan kamera sintetis dengan arah kamera dari titik xs,ys,zs ke titik fokus xf,yf,zf. Sumbu Y+ sebagai sumbu kamera. 18. glSelectBuffer(512, @selectBuffer); Membuat buffer untuk mode seleksi. 19. glRenderMode(GL_SELECT); Memilih mode rasterisasi. GL_SELECT untuk mode seleksi. Model ini menembalikan nama-nama objek yang digambar pada mode GL_RENDER. GL_RENDER untuk mode render. 20. glPushMatrix(); Untuk melakukan push pada matrix stack yang sedang aktif. 21. glPopMatrix(); Untuk melakukan pop pada matrix stack yang sedang aktif. 22. glGetIntegerv(GL_VIEWPORT, @viewportCoords); Mengembalikan nilai pada viewport matrix stack. Ada 4 nilai yang dikembalikan. 23. gluPickMatrix(x, viewportCoords[3]-y, 1, 1, @viewportCoords); Mendefinisikan daerah untuk picking. 24. glMaterialfv(GL_FRONT, GL_DIFFUSE, @warna); Memberikan warna diffuse dengan spesifikasi @warna pada sisi depan poligon objek. 25. glBegin(param);
107
Awal untuk menggambar objek geometri. Param mendefinisikan mode cara menggambar, yaitu GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP, GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS, GL_QUAD_STRIP, and GL_POLYGON. 26. glVertex3f(X,Y,Z); Menggambar verteks pada posisi X,Y,Z. 27. glEnd; Akhir untuk mengambar objek geometri. GlEnd berpasangan dengan glBegin. 28. glGetDoublev(GL_MODELVIEW_MATRIX, @modelview); Mengmbalikan nilai matriks pada modelview matrix stack. Ada 16 nilai yang dikembalikan. 29. glGetDoublev(GL_PROJECTION_MATRIX,@proyeksi); Mengembalikan nilai pada projection matrix stack. Ada 4 nilai yang dikembalikan. 30. glReadPixels(X,Y,1,1,GL_DEPTH_COMPONENT,GL_FLOAT,@winZ); Membaca blok pixel dari frame buffer. 31. glLineWidth(x); Perintah ini digunakan untuk mengatur ketebalan garis. 32. gluUnProject(X,viewport[4]Y,winZ,@modelview,@proyeksi,@viewport,titik[1],titik[2],titik[3]); Memetakan koordinat window dengan koordinat objek.
Makalah Seminar Tugas Akhir
Aplikasi Grafika Komputer untuk Transformasi 3 Dimensi Alfa Ryano1, Agung B.P.2, Eko Handoyo2 1
Mahasiswa dan 2Dosen Jurusan Teknik Elektro, Fakultas Teknik, Universitas Diponegoro, Jl. Prof. Sudharto, Tembalang, Semarang, Indonesia
Abstrak Transformasi memiliki bagian yang penting pada grafika komputer. Dengan transformasi, suatu objek dapat dipindahkan dapat berubah posisi dan atau bentuk.Tugas akhir ini mengimplementasikan transformasi 3 dimensi dalam bentuk suatu aplikasi studio. Aplikasi dapat membuat suatu objek yang kemudian dapat ditransformasikan. Transformasi yang dapat dilakukan berupa translasi, penskalaan, rotasi, dan shearing. Analisis dan desain aplikasi menggunakan pendekatan berorientasi objek. Aplikasi dibuat menggunakan bahasa pemrograman Delphi dan OpenGL. Aplikasi yang dibuat diharapkan dapat mentransformasi objek 3 dimensi melalui antarmuka aplikasi. Kata kunci: transformasi, rotasi, penskalaan, translasi, shearing, OpenGL 1.5 Kegunaan Hasil Penelitian 1. Mengetahui bagaimana mengimplementasikan transformasi 3 dimensi Pada aplikasi 3 dimensi menggunakan OpenGL dan Delphi dengan pendekatan berorientasi objek. 2. Menghasilkan suatu aplikasi yang dapat melakukan transformasi 3 dimensi. Aplikasi ini dapat dikembangkan lebih untuk fungsi-fungsi yang lebih luas yang berkaitan dengan Grafika Komputer, seperti pewarnaan, texture mapping, rendering, dan animasi.
1. Pendahuluan 1.1 Latar Belakang Masalah Grafika komputer–salah satu cabang ilmu komputer–berkembang cukup pesat. Ini terbukti dengan banyaknya bidang yang menerapkan grafika komputer seperti video game, CAD (Computer Aided Design), animasi, simulasi, dan lain-lain. Transformasi 3 dimensi memiliki bagian yang penting pada grafika komputer. Dengan transformasi, ukuran dan bentuk suatu objek geometri dapat diubah. Tugas akhir ini mencoba mengimplementasikan transformasi 3 dimensi dalam bentuk suatu aplikasi studio. Transformasi yang dapat dilakukan, yaitu translasi, penskalaan, rotasi, dan shearing. Pertama-tama, aplikasi dimodelkan terlebih dahulu melalui pendekatan berorientasi objek menggunakan UML kemudian aplikasi dibuat menggunakan bahasa pemrograman Delphi dan OpenGL.
2.
Transformasi Geometri pada Ruang 3 Dimensi Untuk membangun suatu aplikasi studio yang mendukung fungsi transformasi 3 dimensi setidaknya dibutuhan tiga bagian penting. Bagian-bagian tersebut, yaitu pemahaman teori transformasi 3 dimensi, transformasi 3 dimensi menggunakan OpenGL, dan penggunaan OpenGL API pada bahasa pemrograman Delphi.
1.2 Identifikasi Masalah Dalam pembuatan aplikasi terdapat 3 masalah utama, yaitu: 1. Bagaimana merepresentasikan objek geometri yang terdiri dari verkteks-verkteks sehingga dapat ditampilkan di layar. 2. Bagaimana mentransformasi objek 3 dimensi pada aplikasi tersebut. Tansformasi meliputi translasi, penskalaan, shearing, dan rotasi. 3. Antarmuka pengguna dengan program sehingga pengguna dapat melakukan transformasi pada objek.
2.1 Transformasi 3 Dimensi Teori transformasi 3 dimensi memegang peranan penting karena bagian ini merupakan ilmu dasar yang akan diimplentasikan pada program aplikasi. Pada tugas akhir ini digunakan sistem koordinat homogen. Sistem koordinat homogen menggunakan empat ordinat untuk menyatakan titik-titiknya. Ordinat keempat menyatakan faktor skala. P = [px py pz s] Titik hasil transformasi dapat diperoleh melalui persamaan 2.1: Q = P*M (2.1) dengan : Q = [qx,qy,qz,1] menyatakan matriks 1x4 yang berisi titik hasil transformasi. P = [px,py,pz,1] menyatakan matriks 1x4 yang berisi titik yang akan ditransformasikan M = Matriks transformasi berukuran 4x4 seperti pada persamaan 2.2.
1.3 Batasan Masalah 1. Tugas Akhir ini membahas mengenai implementasi transformasi 3 dimensi dalam bentuk suatu aplikasi studio. 2. Implementasi transformasi 3 dimensi menggunakan bahasa pemrograman Delphi dan API OpenGL. 3. Analisis dan desain aplikasi menggunakan pendekatan berorientasi objek. 1.4 Tujuan Penelitian Tujuan penelitian adalah implementasi transformasi 3 dimensi dalam bentuk suatu aplikasi studio.
m00 m M = 10 m20 m30
1
m01
m02
m11 m21 m31
m12 m22 m32
m03 m13 m23 m33
(2.2)
Transformasi 3 dimensi terdiri dari beberapa fungsi transformasi, yaitu translasi, rotasi, penskalaan, dan shearing. Matriks masing-masing transformasi adalah sebagai berikut. 1 0 0 0 1 0 MT = 0 0 1 tx ty tz
0 0 0 1
(2.3)
sx 0 0 0 0 sy 0 0 MS = 0 0 sz 0 0 0 0 1
M Rx
M Ry
Cos (θ ) 0 = Sin(θ ) 0
M Rz
Cos(θ ) Sin(θ ) − Sin(θ ) Cos (θ ) = 0 0 0 0
0 0 0 1
0 − Sin (θ ) 0 1 0 0 0 Cos (θ ) 0 0 0 1
M xsh
M ysh
1 Sh = 0 − Sh ⋅ Yref
M zsh
1 0 = Sh − Sh ⋅ Zref
glLoadIndentity; Procedure glTranslate(x,y,z); Procedure glRotate(degree,x,y,z); Procedure glScale(x,y,z);
Perintah pertama mengatur agar matriks yang digunakan diisi dengan matriks identitas. Perintah kedua digunakan untuk melakukan translasi sebesar x, y, dan z. Perintah ketiga digunakan untuk rotasi sebesar sudut degree dengan sumbu x, y, dan z. Perintah keempat digunakan untuk penskalaan sebesar x, y, dan z.. Pada pembuatan aplikasi, penyusun tidak menggunakan prosedur transformasi bawaan OpenGL karena OpenGL tidak memiliki prosedur untuk shearing. Penyusun membuat prosedur transformasi sendiri.
(2.5)
0 0 1 0 Cos (θ ) Sin(θ ) = 0 − Sin(θ ) Cos (θ ) 0 0 0
Sh 1 0 1 = 0 0 0 − Sh ⋅ Xref
PROJECTION, dan TEXTURE. MODELVIEW adalah matriks yang digunakan untuk melakukan transformasi. PROJECTION adalah matriks yang digunakan untuk proyeksi, dan TEXTURE adalah mariks yang digunakan untuk mengatur tekstur/tampilan permukaan.
0 0 0 0 1 0 0 1
Sh 0 1 − Sh ⋅ Xref
0
0
1 Sh 0 1 0 − Sh ⋅ Yref 0 1 Sh − Sh ⋅ Zref
0 0 0 1 0 0 0 1
0 0 0 0 1 0 0 1
(2.6)
2.3 Penggunaan OpenGL dan Delphi untuk Transformasi 3 Dimensi OpenGL dan Delphi perlu dihubungkan sehingga transformasi 3 dimensi yang menggunakan Delphi dan OpenGL dapat dilakukan. OpenGL dapat digunakan dengan menambahkan klausa openGL pada bagian Uses kode sumber. OpenGL bukan merupakan bagian dari system operasi Windows sehingga diperlukan memberitahu Windows bahwa program menggunakan API dari OpenGL. Informasi yang perlu disampaikan, yaitu: 1. Format Pixel yang disampaikan melalui struktur data TPixelFormatDescriptor. Format Pixel memberikan informasi mengenai jumlah warna dalam bit per pixel, kedalaman sumbu z, serta tipe pixel. 2. Device Context yang menyatakan perangkat (device) yang akan digunakan oleh OpenGL untuk menggambar di layer. Perangkat yang disediakan oleh Windows dan perangkat yang disediakan oleh OpenGL harus dihubungkan sehingga apa yang digambar oleh OpenGL akan ditampilkan oleh Windows.
(2.7)
(2.8)
(2.9)
(2.10)
3.
Pemodelan Aplikasi Grafika Komputer untuk Transformasi 3D Pemodelan aplikasi grafika komputer untuk transformasi objek 3 dimensi menggunakan pendekatan berorientasi objek (objek oriented analysis and design). Langkah-langkah yang dilakukan seperti model yang diutarakan oleh Pressman[6], yaitu: 1. Use case, 2. Kartu Index CRC, 3. Diagram Kelas, 4. Model Hubungan Objek (Object Relationship), dan 5. Model Tingkah Laku Objek (Object Behaviour). Langkah-langkah tersebut kemudian dibuat dalam bentuk diagram UML seperti berikut.
(2.11)
Matriks-matriks di atas kemudian diubah ke dalam bentuk prosedur-prosedur bahasa pemrograman Delphi. Prosedurprosedur tersbut akan digunakan untuk mentransformasi verteks-verteks penyusun objek geometri. 2.2 Transformasi 3 Dimensi pada OpenGL OpenGL sendiri sudah menyediakan perintah-perintah untuk melakukan transformasi. Perintah-perintah yang berhubungan dengan transformasi adalah:
3.1. Use Case Aplikasi yang akan dibangun paling sedikit memiliki 3 use case utama, yaitu membuat objek, menghapus objek ,dan mentransformasi. Use case transformasi sendiri merupakan generaliasi dari use case translasi, penskalaan,
Procedure glMatriksMode(m:GLenum);
Untuk mengatur pemakaian matriks, ada tiga macam matriks yang dapat digunakan, yaitu: MODELVIEW, 2
• Tinggi Operasi: • Gambar • Create
rotasi, dan shearing. Use case buat objek merupakan include dari use case hapus objek dan transformasi karena sebelum melakukan rotasi dan hapus objek perlu membuat objek terlebih dahulu. Diagramnya dapat dilihat pada gambar 3.1.
Tabel 3.5 Kartu index CRC kelas meja. Kelas: Meja Tanggung Jawab: Kolaborator: Atribut: • • Operasi: • Gambar • Create
Buat Objek <>
Translasi
Penskalaan
Tabel 3.6 Kartu index CRC kelas kursi. Kelas: kursi Tanggung Jawab: Kolaborator: Atribut: • • Operasi: • Gambar • Create
<> Pengguna
Transformasi
Rotasi
Hapus Objek
Shearing
Tabel 3.7 Kartu index CRC Transformasi. Kelas: Transformasi Tanggung Jawab: Kolaborator: Atribut: • Objek Geometri • Matriks Operasi: • PerkalianMatriks • MatriksIdentitas • Translasi • Penskalaan • Rotasi • Shearing • Transform • nolkanTransformasi • ambilPos3d
Gambar 3.1 Diagram use case aplikasi grafika komputer untuk transformasi objek 3 dimensi.
3.2. Kartu Index CRC Dari use case pada subbab 3.1, aplikasi paling sedikit membutuhkan 2 buah kelas utama, yaitu kelas transformasi dan kelas geometri. Kelas geometri kemudian diturunkan sehingga terbentuk anak kelas objek kubus, piramida, silinder, meja, dan kursi. Tabel 3.1 Kartu index CRC kelas geometri. Kelas: Geometri Tanggung Jawab: Kolaborator: Atribut: • • nama • index • jenis • pusat • jumTitik • titik • sudut • Aktif Operasi: • Gambar
3.3. Diagram Kelas Dari kartu index CRC pada subbab 3.2, penyusun membuat diagram kelas-nya seperti pada gambar 3.2. Kelas objek kubus, piramida, silinder, meja, dan kursi memiliki parent kelas geometri. Kelas transformasi dan kelas geometri memiliki hubungan dari satu ke satu atau banyak. Artinya satu objek transformasi dapat mentransformasi satu atau lebih objek geometri. Transformasi Matriks
Geometri
Tabel 3.2 Kartu index CRC kelas kubus. Kelas: Kubus Tanggung Jawab: Kolaborator: Atribut: • • Sisi Operasi: • Create • Gambar
nama : String index : Integer jenis : String posisi : Single sudut : Single 1..* pusat : Single
Mentransformasi
1
gambar()
Kubus
Tabel 3.3 Kartu index CRC kelas piramid. Kelas: Piramid Tanggung Jawab: Kolaborator: Atribut: • • Tinggi • Sisi Operasi: • Gambar • Create
sisi : Single gambar() create()
Silinder
Piramid
radius : Single tinggi : Single
tinggi : Single sisi : Single
gambar() create()
gambar()
Meja gambar() create()
perkalianMatriks() MatriksIdentitas() Translasi() Penskalaan() Rotasi() Shearing() Transform() nolkanTransformasi() ambilPos3d()
Kursi gambar() create()
Gambar 3.2 Diagram kelas aplikasi grafika komputer untuk transformasi objek 3 dimensi.
3.4. Model Hubungan Objek (Object Relationship) Model hubungan objek (object relationship model) dapat digambarkan dengan menggunakan diagram runtun (sequence diagram). Pada gambar 3.3 terdapat 3 skenario, yaitu menciptakan objek geometri, mentransformasi objek geometri, dan menghapus objek geometri.
Tabel 3.4 Kartu index CRC kelas silinder. Kelas: Silinder Tanggung Jawab: Kolaborator: Atribut: • • Radius
3
4. Panel
: Geometri
: Transformasi
Implementasi dan Pengujian Aplikasi Grafika Komputer untuk Transformasi 3D Hasil pembuatan aplikasi dapat dilihat pada gambar 4.1-4.6. Gambar 4.1 merupakan tampilan form utama aplikasi grafika komputer untuk transformasi 3 dimensi.
Layar
: Pengguna Memilih objek yang akan dibuat dan nilai atributnya
gambar objek pada layar
Membuat objek geometri
Menampilkan objek geometri Memilih jenis transformasi dan Memberi nilai sesuai input nilainya
Gambar objek pada layar
Mentransformasi objek geometri
Menampilkan objek geometri hasil transformasi Memilih objek yang akan dihapus
Menghapus objek geometri
Hapus objek pada layar
Meampilkan hasil menghapus objek geometri
Gambar 4.1 Tampilan aplikasi grafika komputer untuk transformasi 3 dimensi.
Toolbar (gambar 4.2) digunakan untuk meemilih jenis transformasi yang akan dilakukan, mengubah arah kamera, dan memilih sumbu.
Gambar 3.3 Diagram runtun aplikasi grafika komputer untuk transformasi objek 3 dimensi.
3.5. Model Tingkah Laku Objek (Object Behaviour) Gambar 3.4 merupakan diagram statechart yang menggambarkan perilaku 2 objek, yaitu objek transformasi (a) dan objek geometri (b). Model tingkah laku objek menunjukkan bagaimana system akan merespon kejadian atau stimulus eksternal.
Gambar 4.2 Toolbar dan menu aplikasi.
Tab-tab objek (gambar 4.3) digunakan untuk membuat objek geometri seperti kubus, dilinder, piramida, meja, dan kursi.
Mulai Mentransform asi objek geometri
Membuat objek transform asi
Menunggu perintah transformasi selanjutnya
Objek transformasi tercipta
Menghapus objek geometri Selesai
Objek transformasi terhapus
(a) Mulai
Membuat objek geometri
Posisi, sudut, dan bentuk yang baru Mentransformasi objek geom etri
Objek geometri tercipta
Menunggu transformasi selanjutnya
Gambar 4.3 Tampilan tab-tab untuk objek kubus, kursi, meja, piramida, silinder, dan kamera.
Menghapus objek geometri
Selesai
Status bar (gambar 4.4) digunakan untuk menampilkan informasi mode transformasi yang sedang aktif, posisi kursor pada koordinat world, posisi kursor pada layar, dan sumbu putar yang sedang aktif .
Objek geometri terhapus
(b) Gambar 3.4 Diagram statechart aplikasi grafika komputer untuk transformasi objek 3 dimensi: (a) diagram statechart objek transformasi (b) diagram statechart objek geometri.
Gambar 4.4 Status Bar.
4
Popup menu (gambar 4.5) digunakan untuk menampilkan form-form transformasi (gambar 4.6) dan menghapus objek yang aktif terpilih.
(b) Gambar 4.7 Pengujian transformasi: (a) keadaan awal; (b) hasil translasi (1 1 -1); (c) hasil penskalaan (2 2 2); (d) hasil rotasi (30o 0 1 0); (e) hasil shearing (X 1 1).
Gambar 4.5 Tampilan popup menu klik kanan.
Tabel 4.1. Perbandingan antara hasil perhitungan dan hasil aplikasi untuk translasi (1,00 1,00 -1,00);
Form-form transformasi (gambar 4.6) digunakan untuk mentransformasi objek geometri. Transformasi melalui form transformasi dapat dilakukan lebih presisi daripada menggunakan mouse karena nilai-nilai untuk parameter transformasi diberikan dengan angka.
Titik 0 1 2 3 4 5 6
Koordinat Awal 0,00 0,00 0,00 0,00 0,50 0,00 -0,50 -0,50 0,50 0,50 -0,50 0,50 0,50 -0,50 -0,50 -0,50 -0,50 -0,50 -0,50 -0,50 0,50
Hasil Transformasi Aplikasi Perhitungan 1,00 1,00 -1,00 1,00 1,00 -1,00 1,00 1,50 -1,00 1,00 1,50 -1,00 0,50 0,50 -0,50 0,50 0,50 -0,50 1,50 0,50 -0,50 1,50 0,50 -0,50 1,50 0,50 -1,50 1,50 0,50 -1,50 0,50 0,50 -1,50 0,50 0,50 -1,50 0,50 0,50 -0,50 0,50 0,50 -0,50
Tabel 4.2. Perbandingan antara hasil perhitungan dan hasil aplikasi untuk transformasi penskalaan (2,00 2,00 2,00); Titik 0 1 2 3 4 5 6
Gambar 4.6 Form untuk transformasi translasi, penskalaan, rotasi dan shearing.
Koordinat Awal 0,00 0,00 0,00 0,00 0,50 0,00 -0,50 -0,50 0,50 0,50 -0,50 0,50 0,50 -0,50 -0,50 -0,50 -0,50 -0,50 -0,50 -0,50 0,50
Hasil Transformasi Aplikasi Perhitungan 0,00 0,00 0,00 0,00 0,00 0,00 0,00 1,00 0,00 0,00 1,00 0,00 -1,00 -1,00 1,00 -1,00 -1,00 1,00 1,00 -1,00 1,00 1,00 -1,00 1,00 1,00 -1,00 -1,00 1,00 -1,00 -1,00 -1,00 -1,00 -1,00 -1,00 -1,00 -1,00 -1,00 -1,00 1,00 -1,00 -1,00 1,00
Tabel 4.3. Perbandingan antara hasil perhitungan dan hasil aplikasi untuk transformasi rotasi (30o 0,00 1,00 0,00).
Transformasi-transformasi 3D pada aplikasi diuji. Pengujian dilakukan dengan membandingkan hasil transformasi aplikasi dengan hasil transformasi melalui perhitungan. Pengujian dilakukan pada objek geometri piramida yang memiliki 7 titik. Gambar 4.7a menunjukkan posisi awal piramida ketika dibuat pada aplikasi. Untuk translasi digunakan translasi (1 1 -1) (gambar 4.7b).Untuk penskalaan digunakan penskalaan (2 2 2) (gambar 4.7c). Untuk rotasi digunakan rotasi (30o 0 1 0). Untuk shearing digunakan shearing (X 1 1).
Titik 0 1 2 3 4 5 6
Koordinat Awal 0,00 0,00 0,00 0,00 0,50 0,00 -0,50 -0,50 0,50 0,50 -0,50 0,50 0,50 -0,50 -0,50 -0,50 -0,50 -0,50 -0,50 -0,50 0,50
Hasil Transformasi Aplikasi Perhitungan 0,00 0,00 0,00 0,00 0,00 0,00 0,00 0,50 0,00 0,00 0,50 0,00 -0,18 -0,50 0,68 -0,18 -0,50 0,68 0,68 -0,50 0,18 0,68 -0,50 0,18 0,18 -0,50 -0,68 0,18 -0,50 -0,68 -0,68 -0,50 -0,18 -0,68 -0,50 -0,18 -0,18 -0,50 0,68 -0,18 -0,50 0,68
Tabel 4.4 Perbandingan antara hasil perhitungan dan hasil aplikasi untuk transformasi shearing (X 1,00 1,00). Titik
(a)
0 1 2 3 4 5 6
(b)
Koordinat Awal 0,00 0,00 0,00 0,00 0,50 0,00 -0,50 -0,50 0,50 0,50 -0,50 0,50 0,50 -0,50 -0,50 -0,50 -0,50 -0,50 -0,50 -0,50 0,50
Hasil Transformasi Aplikasi Perhitungan 0,00 -1,00 -1,00 0,00 -1,00 -1,00 0,00 -0,50 -1,00 0,00 -0,50 -1,00 -0,50 -2,00 -1,00 -0,50 -2,00 -1,00 0,50 -1,00 0,00 0,50 -1,00 0,00 0,50 -1,00 -1,00 0,50 -1,00 -1,00 -0,50 -2,00 -2,00 -0,50 -2,00 -2,00 -0,50 -2,00 -2,00 -0,50 -2,00 -2,00
Hasil pengujian pada tabel 4.1-4.4 memperlihatkan kesamaan antara hasil aplikasi dan hasil melalui perhitungan. Dengan demikian, jika dilihat dari pengujian, aplikasi dapat melakukan transformasi dengan tepat.
(c)
(d)
5
[13] ---, Tutorial on UML, Chapter 12, TIMe Electronic Textbook version 4.0, SINTEF, July 16th, 1999.
5. Kesimpulan dan Saran Kesimpulan 1. Fleksibilitas fungsi-fungsi transformasi yang dibuat sendiri lebih tinggi daripada menggunakan fungsifungsi bawaan OpenGL karena OpenGL hanya mendukung transformasi translasi, rotasi, dan penskalaan tetapi tidak untuk shearing. Fungsi-fungsi transformasi yang dibuat sendiri juga dapat dimodifikasi dengan mudah sesuai kebutuhan. 2. Rotasi pada suatu objek geometri yang menggunakan sumbu putar yang tidak melewati titik origin dapat dilakukan dengan mentranslasikan terlebih dahulu sumbu tersebut ke titik origin. Kemudian objek dirotasi sesuai dengan sudut yang ditentukan. Setelah itu, sumbu ditranslasikan kembali ke posisi semula. 3. Perbandingan antara hasil perhitungan dan hasil transformasi aplikasi menunjukkan bahwa aplikasi grafika komputer untuk transformasi 3 dimensi ini dapat melakukan transformasi dengan tepat. 4. Untuk beberapa komputer dan sistem operasi, aplikasi grafika komputer untuk transformasi 3 dimensi ini hanya dapat berjalan jika regional and language options diubah ke regional dan bahasa Indoensia. Ini terjadi karena format penulisan angka yang digunakan menggunakan koma (,) untuk desimal.
BIOGRAFI PENULIS Alfa Ryano Yohannis, lahir di Kendari, Sulawesi Tenggara, 16 juli 1984. Menempuh pendidikan di SD Kristen Kendari, SLTP Negeri 1 Kendari, dan SMU Negeri 1 Makassar. Saat ini sedang menyelesaikan pendidikan program Strata 1 Jurusan Teknik Elektro Universitas Diponegoro dengan mengambil konsentrasi teknik informatika dan komputer. Topik Tugas Akhir yang diambil tentang transformasi objek 3 dimensi pada grafika komputer.
Menyetujui dan mengesahkan, Dosen Pembimbing I
Agung B. P., S.T., M.I.T. NIP. 132 137 932 Tanggal………………...
Saran 1. Aplikasi dapat dikembangkan lebih lanjut dengan menambahkan fasilitas pewarnaan (coloring) dan texture mapping sehingga warna suatu objek dapat diubah sesuai kehendak pengguna dan objek memiliki tekstur yang membuat tampilannya menjadi lebih realistis. 2. Aplikasi dapat dikembangkan lebih lanjut dengan menambahkan fasilitas untuk memuat objek geometri dari berkas berekstensi .obj sehingga objek yang dapat ditampilkan lebih bervariasi.
Dosen Pembimbing II
Eko Handoyo, S.T., M.T. NIP. 132 309 142 Tanggal………………...
6. Referensi [1] Baker, H., Computer Graphics with OpenGL, Third Edition, Prentice Hall, New Jersey, 2004. [2] Bambang, H., Grafik komputer dengan C, Penerbit ANDI, 2004. [3] Dharwiyanti S., Wahono R.S., Pengantar Unified Modelling Language (UML), ilmukomputer.com, 2003. [4] Maksimchuk, R.A., Naiburg, E.J., UML for Mere Mortals, Addison Wesley Proffesional, October 26th, 2004. [5] Nugroho, Edi., Teori dan Praktek gafika Komputer Menggunakan Delphi dan OpenGL, Penerbit Graha ilmu, 2005. [6] Pressman, R.S., Rekayasa Perangkat Lunak Pendekatan Praktisi, Buku Satu dan Dua, McGrawHil Book Co., Penerbit ANDI, 2003. [7] Susilo, D., Gafika Komputer dengan Delphi, Penerbit Graha ilmu, 2005. [8] ---, http://www.autodesk.com/, Maret 2006. [9] ---, http://www.caperaven.co.za/, Maret 2006. [10] ---, http://www.blender.org/, Maret 2006. [11] ---, http://www.delphi3d.net/, Maret 2006. [12] ---, http://www.sulaco.co.za/, Maret 2006.
6