การแปลงในสามมิติ
Download
Report
Transcript การแปลงในสามมิติ
418382 สภาพแวดล้อมการทางานคอมพิวเตอร์กราฟิ กส์
การบรรยายครั้งที่ 3
ประมุข ขันเงิน
[email protected]
การแปลงในสามมิติ
ในปริ ภูมิสามมิติ
• พิกดั ในสามมิติแทนด้ วยลาดับ (x,y,z)
• หรื อด้ วย (x,y,z,w) ถ้ าอยูใ่ นรูป homogeneous
coordinate
• homogeneous coordinate (x,y,z,w) หมายถึงพิกดั
(x/w, y/w, z/w) ในปริภมู ิสามมิติ
ในปริ ภูมิสามมิติ (ต่อ)
• พิกดั ในสามมิติสามารถเขียนได้ อีกแบบหนึง่ ในรูป matrix
x
y
z
1
• มีความหมายเหมือนกับ homogeneous coordinate
(x,y,z,1)
การแปลงในปริ ภูมิสามมิติ
• การแปลงแอฟไฟน์สามชนิดที่เรี ยนผ่านมา
– การเลื่อนแกนขนาน (translation)
– การย่อขยาย (scaling)
– การหมุน (rotation)
สามารถแทนได้ ด้วย matrix 4 คูณ 4
การเลื่อนแกนขนาน
• สัญลักษณ์ Ta,b,c
• ส่งพิกดั (x,y,z) ไปยังพิกดั (x+a, y+b, z+c)
• มี matrix เป็ น
1
0
0
0
0
1
0
0
0
0
1
0
a
b
c
1
การย่อขยายขนาด
• สัญลักษณ์ Sa ,b,c
• ส่งพิกดั (x,y,z) ไปยังพิกดั (ax, by, cz)
• นี่เป็ นการย่อขยายรอบพิกดั (0,0,0) เนื่องจากพิกดั (0,0,0) ไม่
เปลี่ยนแปลง
• มี matrix เป็ น a 0 0 0
0 b 0 0
0 0 c 0
0 0 0 1
การหมุน
• เวลาหมุนจะต้ องบอกสองอย่าง
– แกนที่จะใช้ หมุน
– มุมที่จะใช้ หมุน
• เวลาระบุแกนเราจะระบุด้วยเวกเตอร์ (a,b,c)
• แกนคือเส้ นตรงที่เกิดจากจุดทังหมดที
้
่อยูใ่ นรูป (at, bt, ct) เมื่อ t เป็ น
จานวนจริ งใดๆ
• แกนจะผ่านจุด (0,0,0) เสมอ
• เวลาทาการหมุน จุดที่อยูบ่ นแกนจะไม่เคลื่อนที่
• มุมที่จะใช้ หมุนส่วนใหญ่จะใช้ สญ
ั ลักษณ์ θ
การหมุนรอบแกน z
•
•
•
•
แกน z คือเซตของพิกดั ต่างๆ ที่อยูใ่ นรูป (0, 0, t)
สามารถระบุได้ ด้วยเวกเตอร์ (0,0,1)
สัญลักษณ์ R ,0,0,1
ส่งพิกดั x ไปยังพิกดั x cos y sin
y
x sin y cos
z
z
1
1
การหมุนรอบแกน z (ต่อ)
• มี matrix เป็ น
cos
sin
0
0
sin
cos
0
0
0
0
1
0
0
0
0
1
การหมุนรอบแกน x
•
•
•
•
แกน x คือเซตของพิกดั ต่างๆ ที่อยูใ่ นรูป (t, 0, 0)
สามารถระบุได้ ด้วยเวกเตอร์ (1,0,0)
สัญลักษณ์ R ,1,0,0
ส่งพิกดั x ไปยังพิกดั
x
y
y cos z sin
z
y sin z cos
1
1
การหมุนรอบแกน x (ต่อ)
• มี matrix เป็ น
0
1
0 cos
0 sin
0
0
0
sin
cos
0
0
0
0
1
การหมุนรอบแกน y
•
•
•
•
แกน z คือเซตของพิกดั ต่างๆ ที่อยูใ่ นรูป (0, t, 0)
สามารถระบุได้ ด้วยเวกเตอร์ (0,1,0)
สัญลักษณ์ R ,0,1,0
ส่งพิกดั x ไปยังพิกดั z sin x cos
y
y
z
z cos x sin
1
1
การหมุนรอบแกน y (ต่อ)
• มี matrix เป็ น
cos
0
sin
0
0 sin
1
0
0 cos
0
0
0
0
0
1
การหมุนรอบแกนใดๆ
• สัญลักษณ์ R ,a,b,c
• มี matrix เป็ น
a 2 (1 C ) C ab(1 C ) cS ac(1 C ) bS
2
ba
(
1
C
)
cS
b
(1 C ) C bc(1 C ) aS
ca(1 C ) bS cb(1 C ) aS c 2 (1 C ) C
0
0
0
เมื่อ C cos และ S sin
0
0
0
1
การแปลง affine
• การแปลง affine คือการแปลงที่สามารถเขียนอยูใ่ นรูป matrix
a
b
c
0
d
e
f
0
i l
j m
k n
0 1
ระบบพิกดั
• ระบบพิกดั เป็ นตัวกาหนดว่าพิกดั ใดแทนจุดใด
• พิกดั และจุด?
– พิกดั คือลาดับของเลขสามตัว: (x,y,z)
– จุดคือจุดที่เราเห็นด้ วยตา
• ระบบพิกดั ในสามมิตมิ ีสว่ นประกอบอยูส่ ามส่วน
– จุดออริจิน o: จุดนี ้จะแทนด้ วยพิกดั (0,0,0) ในระบบพิกดั
– เวกเตอร์ สามตัว i, j, และ k สาหรับกาหนดทิศทางแกน x, y, และ z
ตามลาดับ
ระบบพิกดั (ต่อ)
• พิกดั (x,y,z) ในระบบพิกดั นี ้จึงหมายถึงจุด
o + xi + yj + zk
กล่าวคือมันคือจุดที่อยูห่ ่างจากจุด o
ไปตามแนวเวกเตอร์ i เป็ นระยะ x เท่าของความยาวเวกเตอร์ I
ไปตามแนวเวกเตอร์ j เป็ นระยะ y เท่าของความยาวเวกเตอร์ j
ไปตามแนวเวกเตอร์ k เป็ นระยะ z เท่าของความยาวเวกเตอร์ k
ระบบพิกดั
• เขียนได้ อีกแบบหนึง่ ว่าพิกดั (x,y,z) หมายถึงจุด
i
x
y
j k o
z
1
ระบบพิกดั กับการแปลง
• พิจารณาการแปลง affine
a d
b e
M
c f
0 0
i l
j m
k n
0 1
ระบบพิกดั กับการแปลง (ต่อ)
• มันส่งพิกดั x ไปยังพิกดั
y
z
1
ax dy iz l
bx ey jz m
cx fy kz n
1
ระบบพิกดั กับการแปลง (ต่อ)
• พูดได้ อีกอย่างหนึง่ คือ M ส่งจุด
i
x
y
j k o
z
1
ไปยังจุด
i
ax dy iz l
bx ey jz m
i
j k o
cx fy kz n
1
a d
b e
j k o
c f
0 0
i l x
j m y
k n z
0 1 1
ระบบพิกดั กับการแปลง (ต่อ)
• แต่เราอาจมองได้ อีกว่า
i
a d
b e
j k o
c f
0 0
i l x
j m y
k n z
0 1 1
มีคา่ เท่ากับ
x
y
ai bj ck di ej fk ii jj kk o li mj nk
z
1
ระบบพิกดั กับการแปลง (ต่อ)
• ดังนันการแปลง
้
M จึงสามารถมองได้ วา่ เป็ นการเปลี่ยนระบบพิกดั
จากระบบพิกดั ที่
– มี o เป็ นจุดออริ จิน
– มี i เป็ นตัวกาหนดทิศทางแกน x
– มี j เป็ นตัวกาหนดทิศทางแกน y
– มี k เป็ นตัวกาหนดทิศทางแกน z
เป็ นระบบพิกดั ที่
– มี o+li+mj+nk เป็ นจุดออริ จิน
– มี ai+bj+ck เป็ นตัวกาหนดทิศทางแกน x
– มี di+ej+fk เป็ นตัวกาหนดทิศทางแกน y
– มี ii+jj+kk เป็ นตัวกาหนดทิศทางแกน z
ระบบพิกดั กับการแปลง (ต่อ)
• หรื อกล่าวได้ อีกอย่างหนึง่ คือ
– จุดออริจินใหม่คือจุดที่มีพิกดั (l,m,n) ในระบบพิกดั เดิม
– เวกเตอร์ แกน x ใหม่ คือเวกเตอร์ (a,b,c) ในระบบพิกดั เดิม
– เวกเตอร์ แกน y ใหม่ คือเวกเตอร์ (d,e,f) ในระบบพิกดั เดิม
– เวกเตอร์ แกน z ใหม่ คือเวกเตอร์ (i,j,k) ในระบบพิกดั เดิม
ระบบพิกดั กับการแปลง (ต่อ)
a
b
c
0
d
e
f
0
i l
j m
k n
0 1
แกน x ใหม่
ระบบพิกดั กับการแปลง (ต่อ)
a
b
c
0
d
e
f
0
i l
j m
k n
0 1
แกน y ใหม่
ระบบพิกดั กับการแปลง (ต่อ)
a
b
c
0
d
e
f
0
i l
j m
k n
0 1
แกน z ใหม่
ระบบพิกดั กับการแปลง (ต่อ)
a
b
c
0
d
e
f
0
i l
j m
k n
0 1
จุด origin ใหม่
Homogeneous Coordinate กับเวกเตอร์
• Homogeneous coodinate สามารถใช้ แทนได้ ทงจุ
ั ้ ดและ
เวกเตอร์
• ถ้ า w ใน (x,y,z,w) เป็ น 1 แสดงว่ามันแทนจุด
– ถ้ ามันไม่ใช่ 1 ให้ เอา w ไปหาทุกตัวเพื่อทาให้ มนั เป็ น 1 เสีย
• ถ้ า w ใน (x,y,z,w) เป็ น 0 แสดงว่ามันแทนเวกเตอร์ (ทิศทาง)
จุดกับเวกเตอร์
• จุด คือ “ตาแหน่ง”
• เวกเตอร์ คือ “ทิศทาง”
• คุณเอาเวกเตอร์ สองเวกเตอร์ มาบวกกันได้
v2
v1
v3 v1 v2
จุดกับเวกเตอร์ (ต่อ)
• แต่คณ
ุ เอาจุดสองจุดมาบวกกันไม่ได้
p1 p2 ???
p2
p1
• แต่เอาจุดมาบวกกันเวกเตอร์ ได้ จะได้ จดุ อีกจุดหนึง่
v
p1
p2
p1 v p2
จุดกับเวกเตอร์ (ต่อ)
• ในทานองเดียวกัน คุณสามารถหาผลต่างของจุดได้ ซึง่ จะได้ ผลลัพธ์
ออกมาเป็ นเวกเตอร์
v
p2
p1
• ยกตัวอย่างเช่น 3 3 0
4 2 2
5 1 3
1 1 0
p1 v p2
จุดกับเวกเตอร์ (ต่อ)
• การแปลง affine มีผลต่อจุดและเวกเตอร์ ตา่ งกัน
a d
b e
c f
0 0
i l x (ax dy iz ) l
j m y (bx ey jz ) m
k n z (cx fy kz) n
0 1 1
1
แต่
a d
b e
c f
0 0
i l x ax dy iz
j m y bx ey jz
k n z cx fy kz
0 1 0
0
จุดกับเวกเตอร์ (ต่อ)
• ให้
– M เป็ นการแปลง affine
– p เป็ นจุด
– ให้ v เป็ นเวกเตอร์
• ได้ วา่
– Mp เป็ นจุด
– Mv เป็ นเวกเตอร์
• ในการแปลงจุดจะมีการเลื่อนแกนขนานติดมาด้ วย
• แต่ในการแปลงเวกเตอร์ จะไม่มีการเลื่อนแกนขนานติดมาด้ วย
TRANSFORMATIONS IN THE
GRAPHICS PIPELINE
OpenGL Vertex Transformations
• ลาดับของ transform ที่ vertex หนึง่ จะต้ องผ่านไปก่อนที่มนั จะ
ถูกเปลี่ยนเป็ น fragment
OpenGL Vertex Transformation (ต่อ)
xw
xo
y Viewport Perspective Projection View Model y
w
o
0 T ransform Divide T ransform T ransform T ransform zo
1
1
Modeling Transform
• Object space คือระบบพิกดั ที่ศิลปิ นทาการขึ ้นโมเดลมาให้
• World space คือระบบพิกดั กลางของฉากที่โมเดลหลายๆ โมเดล
มาอยูร่ ่วมกัน
• Modeling transform ทาหน้ าที่เปลี่ยน vertex จากที่อยูใ่ น
object space มาอยูใ่ น world space
• ในขณะเดียวกันมันอาจจะเปลี่ยนแปลงหน้ าตาหรื อท่าทางของโมเดลได้
ด้ วย
Modeling Transform (ต่อ)
View Transform
• View transform ใช้ ในการเซตมุมกล้ อง
• Eye space คือระบบพิกดั ที่
– ตาเราอยูท่ ี่จดุ (0,0,0)
– เรามองไปในทิศทางแกน z ทางลบ (ในทิศทางของเวกเตอร์ –k)
– ทิศทางแกน y คือ “ด้ านบน”
• View transform เปลี่ยน vertex ที่อยูใ่ น world space
มาอยูใ่ น eye space
View Transform (ต่อ)
View Transform (ต่อ)
eye
point
lookat
point
y
y
x
x
z
Modelview Matrix
• OpenGL รวมขันตอนการท
้
า modeling transform และ
view transform เข้ าด้ วยกันเป็ นขันตอนเดี
้
ยว
• แทนการแปลงจาก object space ไปเป็ น eye space ด้ วย
modelview matrix
Modelview
View Model
การจัดการกับ Modelview Matrix
• เปลี่ยน mode ของ matrix เป็ น modelview matrix ด้ วย
คาสัง่ glMatrixMode(GL_MODELVIEW)
• หลังจากนันใช้
้ คาสัง่ อื่นๆ
– glLoadIdentity
– glTranslate[fd]
– glScale[fd]
– glRotate[fd]
– glMultMatrix[fd]
คาสัง่ เกี่ยวกับ matrix
• glLoadIdentity()
– ทาให้ คา่ ของ matrix ใน mode ปั จจุบนั ที่ OpenGL จาไว้ เป็ น
identity matrix
• glTranslate[fd](a,b,c)
– สมมติวา่ matrix ใน mode ปั จจุบนั คือ M
– คาสัง่ นี ้จะทาให้ matrix ปั จจุบนั กลายเป็ น MTa,b,c
• glScale[fd](a,b,c)
– คาสัง่ นี ้จะทาให้ matrix ปั จจุบนั กลายเป็ น MSa,b,c
คาสัง่ เกี่ยวกับ matrix (ต่อ)
• glRotate[fd](a, x, y, z)
– a คือ มุมที่จะหมุน หน่วยเป็ นองศา (ไม่ใช่เรเดียน!)
– x, y, และ z ระบุแกนที่จะหมุน
– คาสัง่ นี ้จะทาให้ matrix ปั จจุบนั กลายเป็ น MRa,x,y,z
คาสัง่ เกี่ยวกับ matrix (ต่อ)
• glMultMatrix[fd](m)
– m คือ list ของเลข 16 ตัว
– สมมติวา่ ให้ m = [a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p]
– คาสัง่ นี ้จะทาให้ matrix ปั จจุบนั กลายเป็ น
a
b
M
c
d
e
f
g
h
i m
j n
k o
l p
LookAt Transform
• การเซตมุมกล้ องอย่างง่ายแบบหนึง่
• บอก
– eye = ตาแหน่งของตา
– at = ตาแหน่งที่ตามอง
– up = ทิศทางด้ านบน
การเปลี่ยนระบบพิกดั ของ LookAt Transform
Eye Space
y
World
Space
eye
point
at
point
up
y
x
z
z
x
gluLookAt
• gluLookAt(eyeX, eyeY, eyeZ, atX, atY, atZ, upX,
upY, upZ)
– คูณ matrix ของ mode ปั จจุบนั ด้ วย matrix ที่ transform
ระบบพิกดั โดยทาให้
• จุด (0,0,0) ในระบบพิกดั ใหม่คือจุด eye
• ทิศทาง –z ของระบบพิกดั ใหม่คือทิศทางจากจุด eye ไปยังจุด at
– กล่าวคือแกน z มีทิศทางเดียวกับเวกเตอร์ eye – at
• ทิศทางของแกน y จะคล้ ายๆ กับทิศทาง up
ตัวอย่าง
• ต้ องการเซตมุมกล้ องให้ กล้ องอยูท่ ี่จดุ (-5,-5,-5) แล้ วมองไปที่จดุ
(0,0,0) และมีเวกเตอร์ (1,-1,0) เป็ นด้ านบน
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(-5,-5,-5,0,0,0,1,-1,0);
(วาดรูปอะไรอย่างอื่นต่อไป)
Projection Transformation
• เปลี่ยน eye space เป็ น clip space
• พิกดั ใน clip space จะใช้ เป็ นตัวบอกว่าเราจะเห็น vertex ใด
หรื อไม่เห็น vertex ใด
• กระบวนการตัดสินใจ: vertex ที่เห็นจะต้ องมี
– -1 ≤ x ≤ 1
– -1 ≤ y ≤ 1
– -1 ≤ z ≤ 1
• Projection transform ยังมีผลต่อลักษณะภาพที่เราเห็นอีก
ด้ วย
Projection Transform ใน OpenGL
• OpenGL จะจา matrix ของ projection transform
เอาไว้
• เวลาต้ องการเปลี่ยนแปลง projection matrix ให้ เปลี่ยน
mode ของ matrix เป็ น GL_PROJECTION ด้ วยคาสัง่
glMatrixMode(GL_PROJECTION);
• หลังจากนันใช้
้ คาสัง่ ในการเปลี่ยนแปลง matrix อื่นแบบเดิม เช่น
glLoadIdentity(), glMultMatrix(…), ฯลฯ
• ส่วนมากเราจะสัง่ glLoadIdentity() ทันทีหลังจากสัง่
glMatrixMode(GL_PROJECTION) เสร็จแล้ ว เพื่อเคลียร์
ค่า projection matrix ก่อนใส่คา่ ใหม่
Projection Transformation ที่สาคัญ 2 แบบ
• Orthographic Projection
• Perspective Projection
Orthographic Projection
• ปริมาตรของบริเวณที่เห็นเป็ นปริซมึ
• ไม่มี foreshortening กล่าวคือ ไม่วา่ วัตถุจะอยูใ่ กล้ ไกลก็เห็น
ขนาดเท่ากันหมด
• หลังจากฉาก เส้ นขนานยังเป็ นเส้ นขนานอยู่
• ใช้ ในโปรแกรมช่วยเขียนแบบ/CAD เนื่องจากขนาดของวัตถุเป็ นเรื่ อง
สาคัญ
Orthographic Projection (ต่อ)
http://www2.arts.ubc.ca/TheatreDesign/crslib/drft_1/orthint.htm
Orthographic Projection (ต่อ)
http://www2.arts.ubc.ca/TheatreDesign/crslib/drft_1/cad/wdstv.htm
การนิยาม Orthographic Projection
• นิยามได้ โดยการนิยามปริ ซมึ ของปริ มาตรที่เราต้ องการมองเห็น
• ปริ ซมึ นี ้สามารถนิยามได้ ด้วยตัวเลข 3 คู่
– left และ right --- ขอบเขตในแนวแกน x
– top และ bottom --- ขอบเขตในแนวแกน y
– near และ far --- ขอบเขตในแนวแกน -z (เพราะเรามองในแนว -z)
• ค่าทังหกเป็
้
นพิกดั ใน eye space
• ปริ ซมึ ที่นิยามคือ
{(x,y,z) : left ≤ x ≤ right, top ≤ y ≤ bottom,
near ≤ -z ≤ far}
ปริ ซึมปริ มาตรที่มองเห็น
การนิยาม Orthographic Projection (ต่อ)
• Matrix ของ orthographic projection ต้ องทาอะไรบ้ า
– ส่ง x = left ไป x = -1
– ส่ง x = right ไป x = 1
– ส่ง y = bottom ไป y = -1
– ส่ง y = top ไป y = 1
– ส่ง z = -far ไป z = 1
– ส่ง z = -near ไป z = -1
Matrix ของ Orthographic Projection
2
r l
0
0
0
0
0
2
t b
0
0
0
2
f n
0
r l
r l
t b
t b
f n
f n
1
คาสัง่ OpenGL เกี่ยวกับ
Orthographic Projection
• glOrtho(left, right, bottom, top, near, far)
– คูณ matrix ปั จจุบนั ด้ วย matrix ของ orthographic
projection ในหน้ าก่อน
– ก่อนใช้ ควรเรี ยก
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
ก่อนเพื่อเปลี่ยน mode และเคลียร์ คา่ projection matrix เดิม
• glOrtho2D(left, right, bottom, top)
– เหมือนกับ glOrtho แต่ให้ คา่ near เป็ น 0 และ ค่า far เป็ น 1
Perspective Projection
•
•
•
•
ปริมาตรของบริเวณที่เห็นเป็ น frustum (ปี ระมิดยอดตัด)
มี foreshortening กล่าวคือ อะไรที่อยูใ่ กล้ จะเห็นใหญ่กว่า
หลังจากฉายแล้ ว เส้ นขนานอาจจะไม่ขนานกันเหมือนเดิม
ให้ ความเป็ นสามมิติ เพราะเหมือนกับที่ตาคนทางาน ทาให้ เหมือนเข้ า
ไปอยูใ่ นฉากจริงๆ
• ใช้ กบั โปรแกรมทางความบันเทิง
Perspective Projection (ต่อ)
Perspective Projection (cont.)
orthographic
perspective
การนิยาม Perspective Projection
• นิยามด้ วยเลข 6 ตัวเหมือนกับ orthographic projection
การนิยาม Perspective Projection (ต่อ)
• ปริมาตรที่มองเห็นคือปี ระมิดยอดตัดที่มียอดเป็ นสี่เหลีย่ ม
{(x,y,z) : left ≤ x ≤ right, bottom ≤ y ≤ top,
z = -near}
ซึง่ ยอดของมันถูกฉายต่อไปจนถึง z = -far
การนิยาม Perspective Projection (ต่อ)
• ให้ จดุ (x,y,z) มาใน eye space แล้ วมันจะถูกแปลงเป็ นอะไรใน
clip space?
xclip 1
xclip 1
zeye f
(x,y,z)
zeye z
zeye n
xeye l
xeye r
(0,0,0)
การนิยาม Perspective Projection (ต่อ)
• หา x ใน clip space
xclip 1
xclip ??? x 1
clip
zeye f
(x,y,z)
zeye z
zeye n
xeye l
xeye r
(0,0,0)
การนิยาม Perspective Projection (ต่อ)
• เริ่มจากการหา x ใน eye space ของจุดปลายสองจุด
xclip 1
xeye,left ???
xclip ??? x 1
clip
(x,y,z)
xeye,right
zeye f
???
zeye z
zeye n
xeye l
xeye r
(0,0,0)
การนิยาม Perspective Projection (ต่อ)
• อาศัยความรู้เรื่ องสามเหลี่ยมคล้ าย ได้ วา่
zr
ดังนัน้ xeye,right n
xeye,right
r
z
n
xeye,right ???
zeye z
zeye n
xeye r
(0,0,0)
การนิยาม Perspective Projection (ต่อ)
• ทานองเดียวกัน
xeye,left
l
z
n
xeye,left ???
ดังนัน้
xeye,left
zl
n
zeye z
zeye n
xeye l
(0,0,0)
การนิยาม Perspective Projection (ต่อ)
• เรารู้วา่ xclip ax b สาหรับค่าคงที่ a และ b บางตัว
xclip 1 xclip ??? xclip 1
(x,y,z)
xeye,left
zl
n
zeye z
xeye,right
(0,0,0)
zr
n
การนิยาม Perspective Projection (ต่อ)
• เนื่องจากถ้ า x = -zl/n แล้ ว xclip = -1
และถ้ า x = -zr/n แล้ ว xclip = 1
• ได้ วา่
zl
1 a
b
n
zr
1 a b
n
• เมื่อแก้ สมการออกมาจะได้ วา่
2n
(r l ) z
r l
b
r l
a
การนิยาม Perspective Projection (ต่อ)
• กล่าวคือ
2n
r l
xclip
x
(r l ) z
r l
• ในทานองเดียวกันเราก็จะได้ วา่
2n
t b
yclip
y
(t b) z
t b
การนิยาม Perspective Projection (ต่อ)
• แล้ ว zclip ควรจะมีคา่ เท่าไหร่?
• ค่า zclip จะถูกใช้ เป็ น “ความลึก” ของ fragment
• zclip จะต้ องมีคณ
ุ สมบัติสองประการ
– ถ้ า z น้ อย zclip ก็ต้องน้ อยตามไปด้ วย
– perspective matrix จะต้ องส่งเส้ นตรงไปยังเส้ นตรง
• ตัวอย่าง zclip ที่ใช้ ไม่ได้
– zclip=z
– zclip
x y z
2
2
2
การนิยาม Perspective Projection (ต่อ)
• zclip ที่ OpenGL ใช้ มีรูป
B
z clip A
z
• เนื่องจาก zclip= -1 ถ้ า z = -n
และ zclip= 1 ถ้ า z = -f
จะได้ วา่
B
1 A
n
B
1 A
f
การนิยาม Perspective Projection (ต่อ)
• เมื่อแก้ สมการออกมาแล้ วจะได้ วา่
• กล่าวคือ
2 fn
B
f n
f n
A
f n
f n
2 fn
zclip
f n ( f n) z
การนิยาม Perspective Projection (ต่อ)
• กล่าวคือ perspective projection matrix จะต้ องส่ง
x
y
z
1
ไปยัง
2n
r l 2n
r l
x
x
z
(r l ) z
r l
r l
r l
2
n
t
b
2
n
t
b
y
y
z
(t b) z
t b t b
t b
f n
2 fn f n z 2 fn
f n
f
n
f
n
(
f
n
)
z
z
1
Matrix ของ Perspective Projection
2n
r l
0
0
0
0
2n
t b
0
0
r l
r l
t b
t b
f n
f n
1
0
0
2 fn
f n
0
คาสัง่ OpenGL เกี่ยวกับ
Perspective Projection
• glFrustum(left, right, bottom, top, near, far)
– คูณ matrix ปั จจุบนั ด้ วย matrix ของ perspective
projection ในหน้ าก่อน
– ก่อนใช้ ควรเรี ยก
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
ก่อนเพื่อเปลี่ยน mode และเคลียร์ คา่ projection matrix เดิม
คาสัง่ OpenGL เกี่ยวกับ
Perspective Projection (ต่อ)
• gluPerspective(fovy, aspect, near, far)
– คูณ matrix ปั จจุบนั ด้ วย perspective projection matrix
เช่นเดียวกับ glFrustrum
– มีผลเหมือนกับสัง่ glFrustum โดยได้
•
•
•
•
top = near * tan(fovy / 2)
bottom = -top
right = aspect * top
left = -right
คาสัง่ OpenGL เกี่ยวกับ
Perspective Projection (ต่อ)
– fovy ย่อมาจาก field of view Y หมายถึงความกว้ างของมุมมองตาม
แนวแกน y (มีหน่วยเป็ นองศา)
– aspect คือ aspect ratio ของหน้ าตัดของปี ระมิด
– ปี ระมิดที่ gluPerspective สร้ างมีหน้ าตาเป็ นดังข้ างล่าง
คาสัง่ OpenGL เกี่ยวกับ
Perspective Projection (ต่อ)
• สังเกตว่าคาสัง่ glFrustum สามารถสร้ างปี ระมิดที่ไม่สมมาตรรอบ
แกน z ได้
• แต่ปีระมิดที่สร้ างด้ วย gluPerspective จะเป็ นปี ระมิดที่สมมาตร
รอบแกน z เสมอ
TRANSFORMATIONS IN MODELING
การแปลงกับการวาดภาพ
• การแปลงสามารถนามาใช้ สร้ างภาพที่มีความซับซ้ อนได้ มากมาย
• เราจะมาดูตวั อย่างการสร้ าง แฟรกตัล (fractal)
– รูปที่พอเอาแว่นขยายส่องดูแล้ วเห็นเป็ นลักษณะเหมือนกับตอนไม่ได้ ใช้ แว่น
ขยายดู
Sierpinski Triangle
Sierpinski Triangle
• เพื่อความง่ายในการสร้ าง เราจะแบ่ง Sierpinski triangle
ออกเป็ นชันๆ
้
• ชันที
้ ่ 0 เป็ นสามเหลี่ยมด้ านเท่าธรรมดา
Sierpinski Triangle
• ชันที
้ ่ 1 เกิดจากการเอา Sierpiński triangle ชันที
้ ่ 0 ที่
ย่อส่วนลงสองเท่ามาเรี ยงกันตามรูปข้ างล่างนี ้
Sierpinski Triangle
• Sierpiński Triangle ชันที
้ ่ 2 เกิดจากการเอา Sierpiński
triangle ชันที
้ ่ 1 ที่ยอ่ ส่วนลงสองเท่ามาเรี ยงกันตามรูปข้ างล่างนี ้
Sierpinski Triangle
• Sierpiński Triangle ชันที
้ ่ 3 เกิดจากการเอา Sierpiński
triangle ชันที
้ ่ 2 ที่ยอ่ ส่วนลงสองเท่ามาเรี ยงกันตามรูปข้ างล่างนี ้
Sierpinski Triangle
• Sierpiński Triangle ชันที
้ ่ k เกิดจากการเอา Sierpiński
triangle ชันที
้ ่ k-1 ที่ยอ่ ส่วนลงสองเท่ามาเรี ยงกันตามรู ปเดิม
• ข้ างล่างนี ้คือ Sierpiński triangle ประมาณชันที
้ ่8
เราจะวาด Sierpinski Triangle ได้อย่างไร?
• เขียนฟั งก์ชนั void draw_sierpinski(int k) ที่ทาการวาด
Sierpinski Triangle ชันที
้ ่k
• มีกฎอยูส่ องข้ อในการวาด Sierpinski Triangle
– ถ้ า k = 0 ให้ วาดสามเหลี่ยมด้ านเท่า
– ถ้ า k > 0 ให้ วาด Sierpinski Triangle ชันที
้ ่ k-1 สามอันเรี ยงกัน
ตามรูปที่เราเคยเห็นมา
วาดสามเหลี่ยมด้านเท่า
• ต้ องการวาดสามเหลี่ยมด้ านเท่าความยาวด้ านละ 1 หน่วย
• จุดศูนย์กลาง (จุด centroid) อยูท่ ี่จดุ (0,0)
¡
¡
¡
1
p1
;
2 2 3
¢
0;
p1
3
¢
¡1
p1
2; 2 3
¢
วาดสามเหลี่ยมด้านเท่า
void draw_triangle()
{
glBegin(GL_LINE_LOOP);
glVertex2d( 0.0, 1.0/sqrt(3.0));
glVertex2d( 0.5, -0.5/sqrt(3.0));
glVertex2d(-0.5, -0.5/sqrt(3.0));
glEnd();
}
ผลลัพธ์
ฟังก์ชนั draw_sierpinski
void draw_sierpinski(int k)
{
if (k == 0)
draw_triangle();
else
{
//
//
}
}
วาด Sierpinski
ชัน้ ที่ k-1 สามอัน
triangle
วาด Sierpinski Triangle ชั้นที่ k-1 สามอัน
• วาดอย่างไร?
– เรี ยก draw_sierpinski(k-1)
• วาดตรงไหน?
¡
cent roid = 0; 2
cent roid =
¡
¡
1
p1
4; ¡ 4 3
¢
p1
¢
3
cent roid =
¡1
4; ¡
p1
4 3
¢
วาด Sierpinski Triangle ชั้นที่ k-1 สามอัน
• วาด Sierpinski Triangle อันบน
¡
¢
– Translate centroid ไปเป็ นจุด 0;
– Scale ขนาดลดลง 2 เท่า (= ขยาย 0.5 เท่า)
p1
2 3
• วาด Sierpinski Triangle อันล่างขวา
¡1
– Translate centroid ไปเป็ นจุด 4 ; ¡
– Scale ขนาดลดลง 2 เท่า (= ขยาย 0.5 เท่า)
p1
4 3
¢
• วาด Sierpinski Triangle อันล่างซ้ าย
¡
– Translate centroid ไปเป็ นจุด ¡
– Scale ขนาดลดลง 2 เท่า (= ขยาย 0.5 เท่า)
1
p1
4; ¡ 4 3
¢
วาด Sierpinski Triangle ชั้นที่ k-1 สามอัน
void draw_sierpinski(int k)
{
if (k == 0)
draw_triangle();
else
{
glLoadIdentity();
glTranslated(0.0, 0.5 / sqrt(3.0), 0.0);
glScaled(0.5, 0.5, 0.5);
draw_sierpinski(k-1);
glLoadIdentity();
glTranslated(0.25, -0.25 / sqrt(3.0), 0.0);
glScaled(0.5, 0.5, 0.5);
draw_sierpinski(k-1);
glLoadIdentity();
glTranslated(-0.25, -0.25 / sqrt(3.0), 0.0);
glScaled(0.5, 0.5, 0.5);
draw_sierpinski(k-1);
}
}
วาด Sierpinski Triangle ชั้นที่ k-1 สามอัน
• draw_siepinski(0)
วาด Sierpinski Triangle ชั้นที่ k-1 สามอัน
• draw_siepinski(1)
วาด Sierpinski Triangle ชั้นที่ k-1 สามอัน
• draw_siepinski(2)
วาด Sierpinski Triangle ชั้นที่ k-1 สามอัน
• draw_siepinski(2)
เกิดอะไรขึ้น?
ระบบพิกดั สาหรับวาด Siepinski triangle ระดับ k = I
เกิดอะไรขึ้น?
ระบบพิกดั สาหรับวาด
Siepinski triangle บน
คือ TUS0.5 =MU
ระบบพิกดั สาหรับวาด
Siepinski triangle ซ้ าย
คือ TLS0.5 =ML
ระบบพิกดั สาหรับวาด
Siepinski triangle ขวา
คือ TRS0.5 =MR
เกิดอะไรขึ้น?
MUMU
MUML
MLMU
MLML
MLMR
MUMR
MRMU
MRML
MRMR
พิจารณา code ใหม่อีกครั้ง
glLoadIdentity();
glTranslated(...);
glScaled(...);
draw_sierpinski(k-1);
glLoadIdentity();
glTranslated(...);
glScaled(...);
draw_sierpinski(k-1);
MODELVIEW = M
MODELVIEW = I
MODELVIEW = T
MODELVIEW = TS
MODELVIEW = ???
MODELVIEW = I
MODELVIEW = T
MODELVIEW = TS
พิจารณา code ใหม่อีกครั้ง
glLoadIdentity();
glTranslated(...);
glScaled(...);
draw_sierpinski(k-1);
glLoadIdentity();
glTranslated(...);
glScaled(...);
draw_sierpinski(k-1);
MODELVIEW = M
MODELVIEW = I
MODELVIEW = T
MODELVIEW = TS
MODELVIEW = ???
MODELVIEW = I
MODELVIEW = T
MODELVIEW = TS
ความจริงแล้ ว MODELVIEW ควรมีค่าเท่ ากับ MTS!!!
พิจารณา code ใหม่อีกครั้ง
glLoadIdentity();
glTranslated(...);
glScaled(...);
draw_sierpinski(k-1);
glLoadIdentity();
glTranslated(...);
glScaled(...);
draw_sierpinski(k-1);
MODELVIEW = M
MODELVIEW = I
MODELVIEW = T
MODELVIEW = TS
MODELVIEW = ???
MODELVIEW = ???
MODELVIEW = I
MODELVIEW = T
MODELVIEW = TS
MODELVIEW = ???
ตรงจุดสองจุดนี ้ MODELVIEW ควรมีค่าเท่ ากับ M
แล้วจะต้องทาอะไร?
• ก่อนสัง่ glTranslated(…) ต้ องมีการจาค่าเมตริกซ์
MODELVIEW อันเดิมเอาไว้
• หลังเรี ยก draw_sierpinski(…) ต้ องมีการเอาค่า
MODELVIEW อันเดิมคืนกลับมา
glPushMatrix() และ glPopMatrix()
• glPushMatrix()
– ทาการ push ค่าของเมตริกซ์ใน mode ปั จจุบนั ลง stack
• glPopMatrix()
– pop stack ที่เก็บค่าเมตริกซ์เอาไว้ แล้ วนาค่าที่ได้ ไปให้
• เราสามารถใช้ ฟังก์ชนั สองฟั งก์ชนั นี ้ในการ “จา” transform ได้
เขียนใหม่
MODELVIEW = M
glPushMatrix();
glTranslated(...);
glScaled(...);
draw_sierpinski(k-1);
glPopMatrix();
MODELVIEW
MODELVIEW
MODELVIEW
MODELVIEW
MODELVIEW
=
=
=
=
=
M (จา)
MT
MTS
???
M
glPushMatrix();
glTranslated(...);
glScaled(...);
draw_sierpinski(k-1);
glPopMatrix();
MODELVIEW
MODELVIEW
MODELVIEW
MODELVIEW
MODELVIEW
=
=
=
=
=
M (จา)
MT
MTS
???
M
ทั้งฟังก์ชนั
void draw_sierpinski(int k)
{
if (k == 0)
draw_triangle();
else
{
glPushMatrix();
glTranslated(0.0, 0.5 / sqrt(3.0), 0.0);
glScaled(0.5, 0.5, 0.5);
draw_sierpinski(k-1);
glPopMatrix();
glPushMatrix();
glTranslated(0.25, -0.25 / sqrt(3.0), 0.0);
glScaled(0.5, 0.5, 0.5);
draw_sierpinski(k-1);
glPopMatrix();
glPushMatrix();
glTranslated(-0.25, -0.25 / sqrt(3.0), 0.0);
glScaled(0.5, 0.5, 0.5);
draw_sierpinski(k-1);
glPopMatrix();
}
}
ผลลัพธ์
• draw_sierpinski(2)
ผลลัพธ์
• draw_sierpinski(3)
ผลลัพธ์
• draw_sierpinski(4)
ผลลัพธ์
• draw_sierpinski(8)
HIERARCHICAL
SCENE ORGANIZATION
การจัดฉาก
• ฉากประกอบด้ วยวัตถุหลายๆ อย่าง
• ศิลปิ นสร้ างวัตถุแต่ละชิ ้นขึ ้นมาใน object space ของมันเอง
• วัตถุแต่ละวัตถุจะต้ องถูกแปลงจากที่อยูใ่ น object space ให้ มาอยู่
ใน world space
ตัวอย่างฉาก
ภาพจาก Durand and Cutler, 6.837 Fall 2003 Lecture Note: Transformations 2: In Modeling
ฉากตัวอย่าง
y=1.2
y=0
(0,0)
y=-1
x=-2
x=0
x=2
วัตถุ
• สมมติวา่ ศิลปิ นสร้ างวัตถุให้ เรามาสองอย่าง
– Circle: วงกลมรัศมีหนึง่ หน่วยที่มีจดุ ศูนย์กลางอยูท่ ี่จดุ (0,0)
– Square: สี่เหลี่ยมจัตรุ ัสที่มีจดุ มุมล่างซ้ ายอยูท่ ี่จดุ (-1,-1) และมุมบน
ขวาอยูท่ ี่ (1,1)
• เราจะสร้ างฉากที่เห็นในสไลด์ที่แล้ วอย่างไร?
y
y
2
2
1
-2
1
-1
1
-1
-2
2
-2
x
-1
1
-1
-2
2
x
การจัดฉากแบบเป็ นลาดับขึ้น
• เวลาจัดฉากเรามักจะแบ่งมันเป็ นลาดับขัน้
ฉาก
เก้ าอี ้
Square
Square
โต๊ ะและถาดผลไม้
Square
Square
Square
โต๊ ะ
Square
พื ้น
ถาดผลไม้
Square
Circle
Square
Circle
วาดเก้าอี้
• เราเลือก object space ของเก้ าอี ้ให้ มมุ ล่างซ้ ายของมันอยูท่ ี่จดุ
(0,0)
y=2
y=1
(0,0)
y=0
วาดเก้าอี้
• ขาหน้ า
– ย้ ายจุดศูนย์กลางไปอยู่ที่ (0.1, 0.35)
– ขยายตามแกน x = 0.1 เท่า ตามแกน y = 0.35 เท่า
– วาด Square
• พื ้น
– ย้ ายจุดศูนย์กลางไปอยู่ที่ (0.3, 0.8)
– ขยายตามแกน x = 0.3 เท่า ตามแกน y = 0.1 เท่า
– วาด Square
• ขาหลังและพนัก
– ย้ ายจุดศูนย์กลางไปอยู่ที่ (0.7, 1.1)
– ขยายตามแกน x = 0.1 เท่า ตามแกน y = 1.1 เท่า
– วาด Square
Scene Graph
• เราสามารถแทนการแปลงและการวาดภาพในสไลด์ที่แล้ วได้ ด้วย
แผนภาพที่เรี ยกว่า scene graph
เก้ าอี ้
T0:1;0:35;0:0
T0:3;0:8;0:0
T0:7;1:1;0:0
S0:1;0:35;1:0
S0:3;0:1;1:0
S0:1;1:1;1:0
Square
Square
Square
โค้ด
• เราสามารถเปลี่ยน scene graph เป็ นโค้ ดได้ อย่างง่ายดาย
void draw_chair()
{
glPushMatrix();
glTranslated(0.1, 0.35, 0.0);
glScaled(0.1, 0.35, 1.0);
draw_square(...);
glPopMatrix();
glPushMatrix();
glTranslated(0.3, 0.8, 0.0);
glScaled(0.3, 0.1, 1.0);
draw_square(...);
glPopMatrix();
glPushMatrix();
glTranslated(0.7, 1.1, 0.0);
glScaled(0.1, 1.1, 1.0);
draw_square(...);
glPopMatrix();
}
วาดส่ วนประกอบอื่นๆ ของฉาก
• สมมติวา่ เราสร้ างฟั งก์ชนั
– draw_table() เพื่อวาดโต๊ ะ โดยที่มมุ ล่างซ้ ายของมันอยูท่ ี่จดุ (0,0)
– draw_tray() เพื่อวาดถาดผลไม้ โดยที่มมุ ล่างซ้ ายของมันอยูจ่ ดุ (0,0)
– draw_floor() เพื่อวาดพื ้น
• ฟั งก์ชนั พวกนี ้สามารถสร้ างได้ เหมือน draw_chair()
• โค้ ดจริงๆ ไปดูได้ ในโค้ ดตัวอย่าง
วาดส่ วนประกอบอื่นๆ ของฉาก
• เราสามารถวาดโต๊ ะและถาดผลไม้ ได้ ดงั ต่อไปนี ้
– วาดโต๊ ะโดยการเรี ยก draw_table()
– วาดถาดผลไม้
• ย้ ายจุดมุมซ้ ายไปอยู่ที่จดุ (0.8, 1.3)
• แล้ วเรี ยก draw_tray()
Scene Graph ของโต๊ะและถาด
โต๊ ะและถาด
โต๊ ะ
T0:8;1:3;0:0
ถาด
โค้ด
void draw_table_and_tray()
{
draw_table();
glPushMatrix();
glTranslated(0.8, 1.3, 0.0);
draw_tray();
glPopMatrix();
}
Scene Graph ของฉาก
ฉาก
T¡
1:7;¡ 1:0;0:0
พื ้น
T0:9;¡
โต๊ ะและถาด
โต๊ ะ
1:0;0:0
เก้ าอี ้
T0:1;0:35;0:0
T0:3;0:8;0:0
T0:7;1:1;0:0
S0:1;0:35;1:0
S0:3;0:1;1:0
S0:1;1:1;1:0
T0:8;1:3;0:0
ถาด
Square
Square
Square
โค้ด
void draw_scene()
{
glPushMatrix();
glTranslated(-1.7, -1.0, 0.0);
draw_table_and_tray();
glPopMatrix();
draw_floor();
glPushMatrix();
glTranslated(0.9, -1.0, 0.0);
draw_chair();
glPopMatrix();
}
ผลลัพธ์
บทเรี ยน
• เราสามารถสร้ างฉากที่มีความซับซ้ อนได้ จาก
– วัตถุง่ายๆ
– การแปลง
• เพื่อความสะดวกและความเข้ าใจง่าย เราสามารถจับกลุม่ วัตถุเป็ นกลุม่ ๆ
แล้ วสร้ างฉากจากกลุม่ ของวัตถุได้
• เราสามารถแทนการจัดฉากได้ ด้วยแผนภาพที่เรี ยกว่า scene graph ซึง่
ประกอบด้ วย
– กล่องสาหรับแทนวัตถุ
– กล่องสาหรับแทนกลุม่ ของวัตถุ
– กล่องสาหรับแทนการแปลง
บทเรี ยน
• เมื่อเขียน scene graph แล้ วเราสามารถเขียนโค้ ดเพื่อวาดฉากที่
scene graph บรรยายได้ อย่างง่ายดาย
– กล่องวัตถุหรื อกลุม่ ของวัตถุ -> ฟั งก์ชนั
– กล่องการแปลง -> การเรี ยกฟั งก์ชนั ทาการแปลง เช่น glTranslate,
glScale หรื อ glRotate
– แขนงของกล่อง -> การเรี ยก glPushMatrix() แล้ วลงไปจัดการแขนง
นัน้ แล้ วจึงเรี ยก glPopMatrix()