Disusun Oleh :
Homogeneus coordinates biasanya digunakan untuk transformasi dalam grafik 3D. Mereka
biasa digunakan karena rotasi, penskalaan, translasi dan perspektif yang semuanya linier
dalam ruang homogen. Akibatnya, transformasi dapat diekspresikan secara seragam dalam
matriks bentuk dan dapat dengan mudah digabungkan menjadi matriks komposit tunggal.
Sementara homogeneus coordinates digunakan untuk transformasi 3D, poin dikonversi
kembali ke 3D yang sebenarnya setelah hither clipping. Satu dari alasan bahwa hither
clipping diperlukan adalah untuk menghindari singularitas dalam konversi.
Segitiga mungkin yang paling penting diisi primitif. Beberapa alasan untuk ini adalah:
Segitiga minimal
Suatu poligon cembung jika dan hanya jika setiap ruas garis yang menghubungkan
dua titik pada batasnya terdapat seluruhnya di dalam poligon atau salah satu sisinya.
Segitiga secara matematis sangat sederhana
Bentuk 2 dimensi apa pun dapat didekati dengan poligon menggunakan pendekatan
linier lokal ke permukaan. Untuk meningkatkan kualitas kecocokan, kita hanya perlu
menambah jumlah tepi.
Sebuah poligon bersisi-n cembung, dengan simpul-simpul terurut {v 0 , v 1 , ... v n } di
sepanjang kelilingnya, dapat diuraikan menjadi segitiga-segitiga {(v 0 ,v 1 ,v 2 ),
{v 0 ,v 2 ,v 3 ), (v 0 ,v i ,v i+1 ), ... (v 0 ,v n-1 ,v n )}.
Kita biasanya dapat menguraikan poligon tidak cembung menjadi segitiga, tetapi
poligon ini non-trivial, dan dalam beberapa kasus yang tumpang tindih, kita harus
memasukkan simpul baru.
Ada dua strategi umum untuk memindai-mengonversi segitiga. Yang pertama
menggunakan edge walking dan yang kedua menggunakan edge equations.
Edge-walking
Sarat dengan kasus khusus (breakpoint kiri dan kanan, tidak ada breakpoints)
Sulit untuk mendapatkan yang benar
Membutuhkan komputasi offset fraksional saat menginterpolasi parameter melintasi
segitiga
Umumnya sangat cepat
Edge equations
Pendekatan lain untuk rasterisasi segitiga menggunakan edge equations untuk menentukan
piksel mana yang akan diisi. Edge equations adalah nama lain untuk fungsi pembeda yang
kita gunakan dalam algoritma kurva dan gambar garis. Edge equations membagi daerah
planar menjadi tiga bagian, batas, dan dua setengah ruang. Batas diidentifikasi oleh titik-titik
di mana persamaan tepi sama dengan nol. Setengah ruang dibedakan oleh perbedaan tanda
persamaan tepi. Kita dapat memilih setengah ruang mana yang memberikan tanda positif
dengan mengalikan dengan -1.
Berikut adalah contoh implementasi rasterizer segitiga yang menggunakan persamaan tepi.
class EdgeEqn {
public final static int FRACBITS = 12;
public int A, B, C;
public int flag;
A = (int) (a * (1<<FRACBITS));
B = (int) (b * (1<<FRACBITS));
C = (int) (c * (1<<FRACBITS));
flag = 0;
if (A >= 0) flag += 8;
if (B >= 0) flag += 1;
}
Kita menentukan koefisien persamaan tepi menggunakan dua titik di tepi. Setiap titik
menentukan persamaan dalam hal tiga tidak diketahui, A , B , dan C .
Kita dapat menyelesaikan A dan B dalam suku C dengan menyiapkan sistem linier homogen
berikut.
Mengalikan kedua ruas dengan invers matriks.
Untuk memahami ekspresi yang digunakan untuk C , kita perlu mendiskusikan presisi
numerik dari perhitungan floating point yang digunakan oleh komputer. Komputer mewakili
angka floating-point secara internal dalam format yang mirip dengan notasi ilmiah. Setiap
angka disimpan dengan bagian pecahan yang memiliki jumlah angka penting yang tetap
bersama dengan eksponen. Jika kita mengingat kembali pelajaran kimia atau fisika, hal yang
paling buruk yang dapat kita lakukan dengan angka yang direpresentasikan dalam notasi
ilmiah adalah mengurangi angka dengan besaran yang sama. Inilah yang terjadi. Misalkan
kita memiliki empat angka penting dalam notasi kita. Jika kita mengurangkan bilangan-
bilangan yang besarnya sama seperti gambar di bawah ini:
Dalam kasus segitiga, kita dapat mengharapkan masalah presisi semacam ini sering terjadi,
karena secara umum simpul segitiga biasanya relatif dekat satu sama lain.
Untungnya, kita dapat menghindari pengurangan bilangan besar ini saat menghitung ekspresi
untuk C. Mengingat bahwa kita mengetahui A dan B , kita dapat menyelesaikan C sebagai
berikut:
atau
Untuk menghilangkan bias yang tidak perlu terhadap salah satu simpul dalam perhitungan,
dapat menghitung rata-rata nilai C ini sebagai berikut.
Ini adalah ekspresi untuk C yang muncul dalam metode, dan ini menghindari banyak masalah
numerik yang mengganggu pendekatan lain.
Bendera digunakan dalam menghitung kotak pembatas. Selanjutnya, mari kita lihat loop
utama dari rasterizer.
public FlatTri()
{
}
/*
... Our policy is to assign a triangle
the average of it's vertex colors ...
*/
int a = ((v0.argb >> 24) & 255) + ((v1.argb >> 24) & 255) +
((v2.argb >> 24) & 255);
int r = ((v0.argb >> 16) & 255) + ((v1.argb >> 16) & 255) +
((v2.argb >> 16) & 255);
int g = ((v0.argb >> 8) & 255) + ((v1.argb >> 8) & 255) +
((v2.argb >> 8) & 255);
int b = (v0.argb & 255) + (v1.argb & 255) + (v2.argb & 255);
a = (a + a + 3) / 6;
r = (r + r + 3) / 6;
g = (g + g + 3) / 6;
b = (b + b + 3) / 6;
int x, y;
int A0 = edge[0].A;
int A1 = edge[1].A;
int A2 = edge[2].A;
int B0 = edge[0].B;
int B1 = edge[1].B;
int B2 = edge[2].B;
yMin *= r.width;
yMax *= r.width;
Ketiga sisi diuji dengan perbandingan tunggal dengan menyatukan ketiga sisi dan
memeriksa apakah hasilnya positif. Jika salah satu dari ketiganya negatif maka bit
tandanya akan diset ke 1, dan hasil dari or akan negatif.
Karena segitiga adalah cembung, kita hanya bisa berada di dalam untuk satu interval
pada setiap garis pindai yang diberikan. Variabel xflag digunakan untuk melacak saat
kita keluar dari interior segitiga. Jika kita menemukan diri kita berada di luar segitiga
yang telah menetapkan beberapa piksel pada rentang, maka kita dapat melewati sisa
garis pindaian.
/*
Compute the three edge equations
*/
edge[0] = new EdgeEqn(v[0], v[1]);
edge[1] = new EdgeEqn(v[1], v[2]);
edge[2] = new EdgeEqn(v[2], v[0]);
/*
Trick #1: Orient edges so that the
triangle's interior lies within all
of their positive half-spaces.
/*
Trick #2: compute bounding box
*/
int xflag = edge[0].flag + 2*edge[1].flag + 4*edge[2].flag;
int yflag = (xflag >> 3) - 1;
xflag = (xflag & 7) - 1;
xMin = (int) (v[sort[xflag][0]].x);
xMax = (int) (v[sort[xflag][1]].x + 1);
yMin = (int) (v[sort[yflag][1]].y);
yMax = (int) (v[sort[yflag][0]].y + 1);
/*
clip triangle's bounding box to raster
*/
xMin = (xMin < 0) ? 0 : xMin;
xMax = (xMax >= r.width) ? r.width - 1 : xMax;
yMin = (yMin < 0) ? 0 : yMin;
yMax = (yMax >= r.height) ? r.height - 1 : yMax;
return true;
}
Dalam metode ini dilakukan dua hal penting. Kita mengorientasikan edge equations, dan
menghitung kotak pembatas.