Tugas Akhir
untuk memenuhi sebagian persyaratan mencapai
derajat Sarjana Teknik
oleh
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.
Pembimbing I Pembimbing II
Mengetahui
a.n. Dekan
Ketua Jurusan Teknik Elektro
Fakultas Teknik Universitas Diponengoro
Tanda tangan
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.
Penulis
i
DAFTAR ISI
ii
iii
BAB I PENDAHULUAN
Gambar 1.1 Aplikasi komputer grafis: Blender .......................................................1
Gambar 1.2 3DS Max 8: Aplikasi Penampil Objek 3D ...........................................2
v
vi
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.
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.
ix
BAB I
PENDAHULUAN
1
2
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.
5
6
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 0
0 1 0 0
T = (2.3)
0 0 1 0
t x t y tz 1
1 0 0 0
0 1 0 0
[x ' y ' z ' 1] = [x y z 1] ⋅
0 0 1 0 (2.5)
t x t y t z 1
[x ' [
y ' z ' 1] = x + t x 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 0 0
0 sy 0 0
S= (2.6)
0 0 sz 0
0 0 0 1
Berikut contoh penggunaanya.
P' = P ⋅ S (2.7)
s x 0 0 0
0 sy 0 0
[x ' y ' z ' 1] = [x y z 1] ⋅
0 0 sz 0 (2.8)
0 0 0 1
[x ' [
y ' z ' 1] = x ⋅ s x y ⋅ sy 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.
1 0 0 0
0 Cos (θ ) Sin(θ ) 0
Rx (θ ) = (2.9)
0 − Sin(θ ) Cos (θ ) 0
0 0 0 1
P ' = P ⋅ Rx (θ ) (2.10)
Cos (θ ) 0 − Sin(θ ) 0
0 1 0 0
R y (θ ) = (2.11)
Sin(θ ) 0 Cos (θ ) 0
0 0 0 1
8
P ' = P ⋅ R y (θ ) (2.12)
Cos (θ ) Sin(θ ) 0 0
− Sin(θ ) Cos (θ ) 0 0
Rz (θ ) = (2.13)
0 0 1 0
0 0 0 1
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).
1 Shxy Shxz 0
0 1 0 0
M xshear = (2.15)
0 0 1 0
0 − Shxy ⋅ X ref − Shxz ⋅ X ref 1
1 0 0 0
Sh 1 Shyz 0
=
yx
M yshear (2.17)
0 0 1 0
− Shyx ⋅ Yref 0 − Shyz ⋅ Yref 1
1 0 0 0
0 1 0 0
M zshear = (2.19)
Shzx Shzy 1 0
− Shzx ⋅ Z ref − Shzy ⋅ Z ref 0 1
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 Y Y
X α X X α X X
β θ β
Z Z Z Z Z
sx 0 0 0
0 sy 0 0
MK = (2.23)
0 0 sz 0
(−t x ⋅ s x ) + t x ( −t y ⋅ s y ) + t y ( −t z ⋅ s z ) + t z 1
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);
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);
Procedure glScaled(x,y,z:PGLdouble);
Procedure glScalef(x,y,z:PGLfloat);
Procedure glScale(x,y,z:GLdouble);
Procedure glScale(x,y,z:GLfloat);
glMatriksMode(GL_MODELVIEW);
glLoadIndentity; //jika diperlukan menggunakan matriks identitas
<perintah transformasi, glTranslate, glRotate, atau glScale>
uses
OpenGL, Windows, Messages, SysUtils, Variants, Classes,
Graphics, Controls, Forms, Dialogs;
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
8 7
5 6
4 3
1 2
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.
PERANCANGAN
APLIKASI GRAFIKA KOMPUTER UNTUK
TRANSFORMASI GEOMETRI OBJEK 3 DIMENSI
17
18
Penskalaan
Transformasi
Pengguna
Rotasi
Transformasi
Geometri Matriks
nama : String
perkalianMatriks()
index : Integer
MatriksIdentitas()
jenis : String Mentransformasi
Translasi()
posisi : Single
Penskalaan()
sudut : Single 1..* 1 Rotasi()
pusat : Single Shearing()
Transform()
gambar() nolkanTransformasi()
ambilPos3d()
Memilih objek
yang akan dibuat
dan nilai atributnya
gambar objek
Membuat objek geometri
pada layar
Menampilkan objek geometri
Memilih jenis
transformasi dan
nilainya Memberi nilai sesuai input Gambar
Mentransformasi objek pada
objek geometri layar
Menampilkan
objek geometri
hasil
transformasi
Memilih
objek yang
akan Menghapus objek geometri Hapus
dihapus
objek pada
layar
Meampilkan hasil menghapus objek geometri
Menutup
Aplikasi
Selesai
Objek transformasi
terhapus
(a)
Objek geometri
Menunggu transformasi
tercipta
selanjutnya
Menghapus
objek geometri
(b)
Gambar 3.4 Diagram statechart aplikasi grafika komputer
untuk transformasi objek 3 dimensi: (a) diagram statechart objek transformasi
(b) diagram statechart objek geometri.
transformasi selanjutnya. Objek akan terhapus jika dilakukan operasi hapus objek
pada objek tersebut.
Menu Bar
Tool Bar
Tab Layar
Objek
Status Bar
Gambar 3.5 Desain antarmuka aplikasi grafika komputer
untuk transformasi objek 3 dimensi.
BAB IV
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.
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 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.6 Form untuk transformasi translasi, penskalaan, rotasi dan shearing.
28
5 4
2 dan 6 3
b. Kubus
Geometri kubus (gambar 4.8) terdiri dari 9 titik. Inisialisasi nilai koordinat titik-
titik tersebut dilakukan ketika objek kubus diciptakan.
8 7
5 6
4 3
1 2
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
17 24
18
19
12
1
8
2
3
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. Objek-
objek 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.
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
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;
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.
. . .
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.
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:
1 0 0 0
0 1 0 0
[x ' y ' z ' 1] = [x y z 1] ⋅
0 0 1 0
t x ty tz 1
[x ' [
y ' z ' 1] = x + t x y + ty z + tz 1 ]
1 0
0 0
0 1 0 0
[x ' y ' z ' 1] = [− 0,5 − 0,5 0,5 1]⋅
0 0 1 0
1 1 − 1 1
[x ' y ' z ' 1] = [− 0,5 + 1 − 0,5 + 1 0,5 + (−1) 1]
[x ' 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.
tabel 4.1 akan diskalakan dengan sx=2, sy=2, dan sz=2 (gambar 4.15).
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:
sx 0 0 0
0 sy 0 0
[x ' y ' z ' 1] = [x y z 1]⋅
0 0 sz 0
0 0 0 1
[x ' [
y ' z ' 1] = x ⋅ s x y ⋅ sy z ⋅ sz 1 ]
47
2 0 0 0
0 2 0 0
[x ' y ' z ' 1] = [−,5 − 0,5 0,5 1]⋅
0 0 2 0
0 0 0 1
[x ' y ' z ' 1] = [− 0,5 ⋅ 2 − 0,5 ⋅ 2 0,5 ⋅ 2 1]
[x ' 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.
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
2 2 2
s = 0 2 + 12 + 0 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
u 2 = 0 2 + 12 + 0 2 = 1
u2 =
(0
1 0)
= (0 1 0 )
1
α = arccos( u 2 • s )
α = 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
u1 =
(1 0 0)
= (1 0 0 )
1
u = 02 + 02 + 02 = 0
u=
(0
0 0)
= (~ ~ ~ )
0
β = arccos(u1 • u )
β = 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 − Sin( β ) 0
0 1 0 0
[x ' y ' z ' 1] = [x y z 1] ⋅
Sin( β ) 0 Cos ( β ) 0
0 0 0 1
Cos (0 0 ) 0 − Sin(0 0 ) 0
[x ' y ' z ' 1] = [− 0,5 − 0,5 0,5 1] ⋅
0
Sin(00 )
1 0 0
0 Cos (0 0 ) 0
0 0 0 1
50
1 0 0 0
0 1 0 0
[x ' y ' z ' 1] = [− 0,5 − 0,5 0,5 1]*
0 0 1 0
0 0 0 1
[x ' y ' z ' 1] = [− 0,5 − 0,5 0,5 1]
Langkah keenam adalah memutar titik pada sumbu z sehingga terletak di bidang
di sumbu y.
Cos (α ) Sin(α ) 0 0
− Sin(α ) Cos (α ) 0 0
[x ' y ' z ' 1] = [x y z 1] ⋅
0 0 1 0
0 0 0 1
Cos (0 0 ) Sin(0 0 ) 0 0
− Sin(0 0 ) Cos (0 0 )
[x ' y ' z ' 1] = [− 0,5 − 0,5 0,5 1] ⋅
0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
[x ' y ' z ' 1] = [− 0,5 − 0,5 0,5 1] ⋅
0 0 1 0
0 0 0 1
[x ' y ' z ' 1] = [− 0,5 − 0,5 0,5 1]
Langkah keenam adalah memutar titik pada sumbu z sebesar sudut yang
ditentukan untuk transformasi rotasi.
Cos (θ ) 0 − Sin(θ ) 0
0 1 0 0
[x ' y ' z ' 1] = [x y z 1] ⋅
Sin(θ ) 0 Cos (θ ) 0
0 0 0 1
0,866 0 − 0,5
0
0 1 0
0
[x ' y ' z ' 1] = [− 0,5 − 0,5 0,5 1] ⋅
0,5 0 0,866 0
0 0 0 1
[x ' y ' z ' 1] = [0,183 − 0,5 0,683 1]
Langkah ketujuh adalah memutar balik titik sebesar –α pada sumbu Z.
Cos (−α ) Sin(−α ) 0 0
− Sin(−α ) Cos (−α ) 0 0
[x ' y ' z ' 1] = [x y z 1] ⋅
0 0 1 0
0 0 0 1
Dengan cara perhitungan yang sama, untuk titik-titik piramida yang lain, titik-titik
hasil penskalaannya dapat dilihat pada tabel 4.4.
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:
1 Shxy Shxz 0
0 1 0 0
[x ' y ' z ' 1] = [x y z 1] ⋅
0 0 1 0
0 − Shxy ⋅ X ref − Shxz ⋅ X ref 1
1 1 1 0
0 1 0 0
[x ' y ' z ' 1] = [− 0,5 − 0,5 0,5 1] ⋅
0 0 1 0
0 − 1 ⋅ 1 − 1 ⋅ 1 1
[x ' y ' z ' 1] = [− 0,5 − 2,0 − 1,0 1]
Dengan cara perhitungan yang sama, untuk titik-titik piramida yang lain, titik-titik
hasil shearing-nya dapat dilihat pada tabel 4.5.
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.
(a)
(b)
Gambar 2.21 Pengujian framerate untuk penskalaan: (a) aplikasi menggunakan fungsi
transformasi buatan sendiri dan (b) aplikasi menggunakan fungsi transformasi bawaan OpenGL.
Framerate (FPS)
No. Gambar Jumlah Verteks
Aplikasi OpenGL Selisih
7. 200 kursi 9800 60 60 0
8. 250 Meja 10250 60 60 0
9. 2 potatohead 17152 59 60 1
10. 3 potatohead 25728 40 60 10
11. 4 potatohead 34304 31 46 15
12. 5 potatohead 42880 27 30 3
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
Bab V berisi kesimpulan dan saran. Kesimpulan yang ditulis merupakan hal-
hal 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 verteks-
verteks 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 geometri dapat
ditransformasi sehingga bentuk objek tersebut berubah.
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, Addison-
Wesley 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
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
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] of GLFloat=(5.0,5.0,5.0,1.0);
light_position2:array[0..3] of GLFloat=(5.0,5.0,5.0,1.0);
light_position3:array[0..3] of GLFloat=(5.0,5.0,-5.0,1.0);
light_position4:array[0..3] of GLFloat=(-5.0,5.0,-5.0,1.0);
var
FormUtama: TFormUtama;
Grid:Tgrid;
implementation
{$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 Begin X:=1; Y:=1;Z:=1; end;
if sComboBox2.ItemIndex=1 then Begin X:=1; Y:=0;Z:=0; end;
if sComboBox2.ItemIndex=2 then Begin X:=0; Y:=1;Z:=0; end;
if sComboBox2.ItemIndex=3 then Begin X:=0; Y:=0;Z:=1; end;
// 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;
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); // Clear The
Screen And The Depth Buffer
glLoadIdentity(); // Reset The
View
if ModeWireframe1.Checked=true then
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; //Gambar Grid
glBegin(GL_LINES);
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;
gluLookAt(Kamera.posX,Kamera.posY,Kamera.posZ,Fokus.posX,Fokus.posY,
Fokus.posZ,atasKam.posX,atasKam.posY,atasKam.posZ);
't':ToolButton7.Click;
'p':ToolButton8.Click;
'r':ToolButton9.Click;
's':ToolButton10.Click;
'd':ToolButton15.Click;
else
Exit;
end;
end;
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;
ObjekBaru:=nil;
ObjekBaru:=Tkursi.Create(titikPusat);
DaftarGeometri.TambahGeometri(ObjekBaru);
end;
titikPusat.posZ:=StrToFloat(sDecimalSpinEdit8.Text);
ObjekBaru:=nil;
ObjekBaru:=Tkubus.create(sisi,titikPusat);
DaftarGeometri.TambahGeometri(ObjekBaru);
end;
ObjekBaru:=nil;
ObjekBaru:=TSilinder.Create(Radius,tinggi,titikPusat);
DaftarGeometri.TambahGeometri(ObjekBaru);
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;
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;
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;
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;
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;
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
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
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;
ObjekBaru:=nil;
ObjekBaru:=Tmeja.Create(titikPusat);
DaftarGeometri.TambahGeometri(ObjekBaru);
end;
modeTransformasi:=6;
sStatusBar1.Panels[2].Text:='Mode: Rotasi Kamera';
end;
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;
end;
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;
if SavePictureDialog1.Execute then
bmp.SaveToFile(SavePictureDialog1.FileName);
bmp.Free;
end;
end.
Vektor.pas
unit vektor;
interface
uses sysutils,geometri,OBJLoader;
function DotProduct(va,vb:Ttitik3d):real;
function CrossProduct(va,vb:Ttitik3d):Ttitik3d;
function BuatVektor(x,y,z:real):Ttitik3d;
function Normalisasi(va:Ttitik3d):Ttitik3d;
function 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}
//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;
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
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;
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}
end;
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
{$R *.dfm}
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;
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;
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;
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);
procedure TOBJLoader.gambarKotak;
begin
// RED GREEN BLUE ALPHA
warna[0]:=1.0;warna[1]:=1.0;warna[2]:=1.0;warna[3]:=1.0;
glMaterialfv(GL_FRONT, GL_DIFFUSE, @warna);
glBegin(GL_QUADS);
//Sisi Depan
glVertex3f(titikMin.posX,titikMin.posY,titikMax.posZ);
glVertex3f(titikMax.posX,titikMin.posY,titikMax.posZ);
glVertex3f(titikMax.posX,titikMax.posY,titikMax.posZ);
glVertex3f(titikMin.posX,titikMax.posY,titikMAx.posZ);
//Sisi Belakang
glVertex3f(titikMin.posX,titikmin.posY,titikmin.posZ);
glVertex3f(titikMax.posX,titikMin.posY,titikMin.posZ);
glVertex3f(titikMax.posX,titikMax.posY,titikMin.posZ);
glVertex3f(titikMin.posX,titikMax.posY,titikMin.posZ);
//sisi kiri
glVertex3f(titikMin.posX,titikmin.posY,titikMin.posZ);
glVertex3f(titikMin.posX,titikMin.posY,titikMax.posZ);
glVertex3f(titikMin.posX,titikMax.posY,titikMax.posZ);
glVertex3f(titikMin.posX,titikMax.posY,titikMin.posZ);
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 Rotasi(sudut:real;xr,yr,zr:real);
Procedure Shearing(sumbu:integer;ref,shear1,shear2:real);
procedure Transform(P:Ttitik3d;var Q:TTitik3d);
procedure nolkanTransformasi;
procedure ambilPos3d(X,Y:integer;var titik:TArTitik3d);
end;
implementation
uses unitUtama;
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.nolkanTransformasi;
begin
MatriksIdentitas(MAtriks);
end;
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
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.
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 1-
based indices into the list of points, in the order they occurred in the file. For example, the
following describes a simple triangle:
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.
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.
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 about the Wavefront OBJ format, see the specification.
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
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
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.
1
Transformasi 3 dimensi terdiri dari beberapa fungsi PROJECTION, dan TEXTURE. MODELVIEW adalah
transformasi, yaitu translasi, rotasi, penskalaan, dan matriks yang digunakan untuk melakukan transformasi.
shearing. Matriks masing-masing transformasi adalah PROJECTION adalah matriks yang digunakan untuk
sebagai berikut. proyeksi, dan TEXTURE adalah mariks yang digunakan
untuk mengatur tekstur/tampilan permukaan.
1 0 0 0
0 1 0 0 (2.3) glLoadIndentity;
MT = Procedure glTranslate(x,y,z);
0 0 1 0 Procedure glRotate(degree,x,y,z);
tx ty tz 1 Procedure glScale(x,y,z);
2
rotasi, dan shearing. Use case buat objek merupakan • Tinggi
include dari use case hapus objek dan transformasi karena Operasi:
• Gambar
sebelum melakukan rotasi dan hapus objek perlu membuat
• Create
objek terlebih dahulu. Diagramnya dapat dilihat pada
gambar 3.1. Tabel 3.5 Kartu index CRC kelas meja.
Kelas: Meja
Tanggung Jawab: Kolaborator:
Atribut:
Buat Objek • - • -
Operasi:
Translasi
<<include>> • Gambar
• Create
Penskalaan
Tabel 3.6 Kartu index CRC kelas kursi.
<<include>> Kelas: kursi
Transformasi Tanggung Jawab: Kolaborator:
Pengguna
Atribut:
Rotasi
• - • -
Operasi:
• Gambar
Hapus Objek Shearing • Create
• Sisi • - gambar()
Transform()
nolkanTransformasi()
ambilPos3d()
Operasi:
• Create
• Gambar
Kubus Piramid Meja Kursi
Silinder
Tabel 3.3 Kartu index CRC kelas piramid. sisi : Single
radius : Single tinggi : Single
sisi : Single gambar() gambar()
Kelas: Piramid gambar()
tinggi : Single
create() create()
create() gambar()
Tanggung Jawab: Kolaborator: gambar()
create()
Atribut:
• Tinggi • - Gambar 3.2 Diagram kelas aplikasi grafika komputer untuk
• Sisi transformasi objek 3 dimensi.
Operasi:
• Gambar 3.4. Model Hubungan Objek (Object Relationship)
• Create
Model hubungan objek (object relationship model)
Tabel 3.4 Kartu index CRC kelas silinder. dapat digambarkan dengan menggunakan diagram runtun
Kelas: Silinder (sequence diagram). Pada gambar 3.3 terdapat 3 skenario,
Tanggung Jawab: Kolaborator: yaitu menciptakan objek geometri, mentransformasi objek
Atribut: geometri, dan menghapus objek geometri.
• Radius • -
3
4. Implementasi dan Pengujian Aplikasi Grafika
Komputer untuk Transformasi 3D
: Pengguna
Panel : Transformasi : Geometri Layar Hasil pembuatan aplikasi dapat dilihat pada gambar
Memilih objek
4.1-4.6. Gambar 4.1 merupakan tampilan form utama
yang akan dibuat
dan nilai atributnya aplikasi grafika komputer untuk transformasi 3 dimensi.
gambar objek
Membuat objek geometri
pada layar
Memilih jenis
transformasi dan
nilainya Memberi nilai sesuai input Gambar
Mentransformasi objek pada
objek geometri layar
Menampilkan
objek geometri
hasil
transformasi
Memilih
objek yang
akan Menghapus objek geometri Hapus
dihapus
objek pada
layar
Menghapus
objek
geometri
Selesai
Objek transformasi
terhapus
(a)
Mulai Posisi, sudut, dan
bentuk yang baru
Objek geometri
Menunggu transformasi
tercipta
selanjutnya
Gambar 4.3 Tampilan tab-tab untuk objek kubus, kursi, meja, piramida,
Menghapus
objek geometri
silinder, dan kamera.
Objek geometri
Status bar (gambar 4.4) digunakan untuk menampilkan
Selesai
terhapus informasi mode transformasi yang sedang aktif, posisi
kursor pada koordinat world, posisi kursor pada layar, dan
(b) sumbu putar yang sedang aktif
.
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)
Form-form transformasi (gambar 4.6) digunakan untuk Tabel 4.1. Perbandingan antara hasil perhitungan dan hasil
aplikasi untuk translasi (1,00 1,00 -1,00);
mentransformasi objek geometri. Transformasi melalui Hasil Transformasi
Koordinat
form transformasi dapat dilakukan lebih presisi daripada Titik
Awal Aplikasi Perhitungan
menggunakan mouse karena nilai-nilai untuk parameter 0 0,00 0,00 0,00 1,00 1,00 -1,00 1,00 1,00 -1,00
transformasi diberikan dengan angka. 1 0,00 0,50 0,00 1,00 1,50 -1,00 1,00 1,50 -1,00
2 -0,50 -0,50 0,50 0,50 0,50 -0,50 0,50 0,50 -0,50
3 0,50 -0,50 0,50 1,50 0,50 -0,50 1,50 0,50 -0,50
4 0,50 -0,50 -0,50 1,50 0,50 -1,50 1,50 0,50 -1,50
5 -0,50 -0,50 -0,50 0,50 0,50 -1,50 0,50 0,50 -1,50
6 -0,50 -0,50 0,50 0,50 0,50 -0,50 0,50 0,50 -0,50
(c) (d)
5
5. Kesimpulan dan Saran [13] ---, Tutorial on UML, Chapter 12, TIMe Electronic
Kesimpulan Textbook version 4.0, SINTEF, July 16th, 1999.
1. Fleksibilitas fungsi-fungsi transformasi yang dibuat
sendiri lebih tinggi daripada menggunakan fungsi-
fungsi bawaan OpenGL karena OpenGL hanya BIOGRAFI PENULIS
mendukung transformasi translasi, rotasi, dan
penskalaan tetapi tidak untuk shearing. Fungsi-fungsi Alfa Ryano Yohannis, lahir di Kendari,
transformasi yang dibuat sendiri juga dapat dimodifikasi Sulawesi Tenggara, 16 juli 1984.
dengan mudah sesuai kebutuhan. Menempuh pendidikan di SD Kristen
2. Rotasi pada suatu objek geometri yang menggunakan Kendari, SLTP Negeri 1 Kendari, dan
sumbu putar yang tidak melewati titik origin dapat SMU Negeri 1 Makassar. Saat ini sedang
dilakukan dengan mentranslasikan terlebih dahulu menyelesaikan pendidikan program
sumbu tersebut ke titik origin. Kemudian objek dirotasi Strata 1 Jurusan Teknik Elektro
sesuai dengan sudut yang ditentukan. Setelah itu, Universitas Diponegoro dengan
sumbu ditranslasikan kembali ke posisi semula. mengambil konsentrasi teknik informatika dan komputer.
3. Perbandingan antara hasil perhitungan dan hasil Topik Tugas Akhir yang diambil tentang transformasi objek
transformasi aplikasi menunjukkan bahwa aplikasi 3 dimensi pada grafika komputer.
grafika komputer untuk transformasi 3 dimensi ini dapat
melakukan transformasi dengan tepat.
4. Untuk beberapa komputer dan sistem operasi, aplikasi Menyetujui dan mengesahkan,
grafika komputer untuk transformasi 3 dimensi ini
hanya dapat berjalan jika regional and language options Dosen Pembimbing I
diubah ke regional dan bahasa Indoensia. Ini terjadi
karena format penulisan angka yang digunakan
menggunakan koma (,) untuk desimal.
Agung B. P., S.T., M.I.T.
Saran NIP. 132 137 932
1. Aplikasi dapat dikembangkan lebih lanjut dengan Tanggal………………...
menambahkan fasilitas pewarnaan (coloring) dan
texture mapping sehingga warna suatu objek dapat
diubah sesuai kehendak pengguna dan objek memiliki Dosen Pembimbing II
tekstur yang membuat tampilannya menjadi lebih
realistis.
2. Aplikasi dapat dikembangkan lebih lanjut dengan
menambahkan fasilitas untuk memuat objek geometri Eko Handoyo, S.T., M.T.
dari berkas berekstensi .obj sehingga objek yang dapat NIP. 132 309 142
ditampilkan lebih bervariasi. 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, McGraw-
Hil 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.