Document

Report
01418341 สภาพแวดล้อมการทางานคอมพิวเตอร์กราฟิ กส์
การบรรยายครั้งที่ 2
ประมุข ขันเงิน
[email protected]
CULLING
Culling
• รูปหลายเหลี่ยมมีสองหน้ า: ด้ านหน้ า กับ ด้ านหลัง
• เวลาวาดรูปทรงสามมิติ ส่วนมากด้ านหน้ าจะหันหน้ ามาหาเรา
• ฉะนันโดยมากไม่
้
มีความจาเป็ นต้ องวาดรูปเหลี่ยมที่หนั หลังสส่เรา
– ช่วยสห้ โปรแกรมเร็วขึ ้น
– ช่วยทาเอฟเฟกต์บางอย่าง เช่นมองเห็นภาพภายนอกจากภายสนวัตถุ
• เราสามารถสัง่ สห้ OpenGL ไม่วาดรูปหลายเหลี่ยมที่หนั หน้ าที่เราไม่
ต้ องการเห็นมาสห้ ได้
• การเลือกไม่วาดรูปหลายเหลี่ยม เราเรี ยกว่า Culling
glCullFace
• glCullFace(GLenum mode)
– กาหนดรูปแบบการ cull รูปหลายเหลี่ยม
– mode มีคา่ ได้ สามแบบ
• GL_FRONT = ไม่วาดด้ านหน้ า
• GL_BACK = ไม่วาดด้ านหลัง
• GL_FRONT_AND_BACK = ไม่วาดทังสองด้
้
าน
– ห้ ามเรี ยกสน glBegin(…) และ glEnd()
– ก่อนการทา culling จะมีผล จะต้ องสัง่
glEnable(GL_CULL_FACE) เสียก่อน
– ยกเลิกการทา culling (วาดหมดทุกด้ าน) โดยการสัง่
glDisable(GL_CULL_FACE)
แล้วอะไรคือด้านหน้า อะไรคือด้านหลัง?
• โดยปกติ รูปหลายเหลี่ยมที่เรามองแล้ วเห็นจุดมุมเรี ยงกันตามแนวทวน
เข็มนาฬิกา ถือว่าหัน “ด้ านหน้ า” สห้ เรา
• ถ้ าเห็นจุดมุมเรี ยงกันตามเข็มนาฬิกา ถือว่าหัน “ด้ านหลัง” สห้
• แต่เราสามารถเปลี่ยนได้ ด้ วย glFrontFace
– glFrontFace(GL_CCW) = ถือว่า “ทวนเข็ม” เป็ นด้ านหน้ า
– glFrontFace(GL_CW) = ถือว่า “ตามเข็ม” เป็ นด้ านหน้ า
ดู demo
ANIMATION WITH GLUT
สร้างภาพเคลื่อนไหวด้วย GLUT
• เราสามารถสร้ างภาพเคลื่อนไหวโดยการวาดภาพสหม่เป็ นระยะๆ
• กล่าวคือ ทุกช่วงเวลาจากัด เราจะต้ องมีการเรี ยกฟั งก์ชนั ทีเ่ ราสห้ ไปสน
glutDisplayFunc สหม่
– ถ้ าต้ องการความเร็วประมาณ 30 เฟรม/วินาที (ลื่นไหลพอสช้ ได้ ) ต้ องมีการ
เรี ยกฟั งก์ชนั นี ้ทุกๆ 33 มิลลิวินาที
– ถ้ าต้ องการความเร็วประมาณ 60 เฟรม/วินาที (ลื่นไหลมากๆ) ต้ องมีการ
เรี ยกฟั งก์ชนั นี ้ทุกๆ 17 มิลลิวินาที
แล้วจะเรี ยกฟังก์ชนั display อย่างไร?
• เรี ยกตรงๆ ความจริงก็ได้ อยู่ แต่มนั จะไปซ ้าซ้ อนกับการเรี ยกสน
glutMainLoop
• เราสามารถสัง่ สห้ glutMainLoop เรี ยกฟั งก์ชนั display ได้ ด้วย
คาสัง่ glutPostRedisplay()
• glutPostRedisplay()
– บอก GLUT ว่าเราต้ องการสห้ มนั เรี ยกฟั งก์ชนั ที่สห้ ไปกับ
glutDisplayFunc สนลูปครัง้ ต่อไป
– ถ้ าเรี ยก glutPostRedisplay หลายครัง้ ก่อนลูปต่อไป ฟั งก์ชนั
display จะถูกเรี ยกเพียงครัง้ เดียว
แล้วจะเรี ยก glutPostRedisplay
ทุกๆ X มิลลิวนิ าทีได้อย่างไร?
• glutTimerFunc(unsigned int msecs,
void (*func)​(int value), value)
– เรี ยกฟั งก์ชนั func ที่สห้ มาเป็ น argument ที่สองหลังจากเวลาผ่านไปได้
msecs มิลลิวินาที
– func จะได้ รับ value ที่สห้ มาเป็ น argument ที่ 3 เป็ น
argument
– จะเรี ยก func เพียงครัง้ เดียวเท่านัน้
– ดังนันถ้
้ าต้ องการสห้ เรี ยกเป็ นคาบๆ สน func จะต้ องมีการเรี ยก
glutTimerFunc สห้ ตวั เองสหม่
ตัวอย่าง 1
void printInt(int value)
{
printf("Got an integer: %d\n", value);
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE);
glutCreateWindow("glutTimerFunc Example 01");
glutDisplayFunc(display);
glutTimerFunc(2000, printInt, 123);
glutTimerFunc(3000, printInt, 456);
glutTimerFunc(4000, printInt, 789);
glutMainLoop();
}
ตัวอย่าง 2
void printAndReschedule(int interval)
{
printf("I'm printing this every %d milliseconds\n", interval);
glutTimerFunc(interval, printAndReschedule, interval);
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE);
glutCreateWindow("glutTimerFunc Example 01");
glutDisplayFunc(display);
glutTimerFunc(0, printAndReschedule, 500);
glutTimerFunc(0, printAndReschedule, 1000);
glutTimerFunc(0, printAndReschedule, 2000);
glutMainLoop();
}
ANIMATION &
MVC DESIGN PATTERN
หลักการทา animation แบบ
Model-View-Controller
• เราแบ่งโปรแกรมของเราออกเป็ นสามส่วน
– Model = ส่วนที่จดั การกับข้ อมูล สนที่นี ้คือโมเดลสามมิติหรื อสองมิติที่เรา
ต้ องการแสดง
– View = ส่วนที่นาโมเดลไปแสดง
– Controller = ส่วนที่ทาการเปลี่ยนแปลงโมเดล ซึง่ อาจเป็ นผลมาจาก
เวลาที่ผ่านไป หรื อการสัง่ งานของผู้สช้
• มีการแบ่งหน้ าที่กนั ชัดเจน
– Controller ทาหน้ าที่เปลี่ยนแปลงโมเดลอย่างเดียว ไม่มีหน้ าที่แสดง
– View ทาหน้ าที่แสดงโมเดลอย่างเดียว ไม่มีเปลี่ยนแปลงโมเดลเอง
หลักการทา animation แบบ
Model-View-Controller (ต่อ)
• สนโปรแกรมกราฟฟิ กส์ที่สช้ GLUT ของเรา
– Model = ส่วนที่เก็บข้ อมูลต่างๆ
– View = callback ของ glutDisplayFunc
– Controller = callback function อื่นๆ
• callback ของ glutTimerFunc
• callback สาหรับเวลาผู้สช้ สช้ keyboard หรื อ mouse
Animation ลูกบอลเด้งกระทบกาแพง
• Model
–
–
–
–
–
ข้ อมูลของลูกบอล
ตาแหน่งของจุดศูนย์กลางลูกบอล
ความเร็วของลูกบอล
รัศมี
สี
• ข้ อมูลลูกบอลควรประกาศไว้ เป็ น
global variable เพื่อที่จะได้ สช้
ร่วมกันได้ หลายฟั งก์ชนั
struct Ball
{
double x, y;
double vx, vy;
double radius;
double r, g, b;
};
Ball ball;
Animation ลูกบอลเด้งกระทบกาแพง (ต่อ)
• View
– วาดลูกบอลเป็ นวงกลมทึบด้ วย OpenGL
void drawBall(Ball &b)
{
glColor3d(b.r, b.g, b.b);
glBegin(GL_TRIANGLE_FAN);
glVertex2d(b.x, b.y);
for(int i=0;i<CORNERS;i++)
{
double theta = 2*M_PI*i/CORNERS;
double x = b.x + b.radius * cos(theta);
double y = b.y + b.radius * sin(theta);
glVertex2d(x,y);
}
glVertex2d(b.x + b.radius, b.y);
glEnd();
}
Animation ลูกบอลเด้งกระทบกาแพง (ต่อ)
• View (ต่อ)
– สัง่ สห้ วาดลูกบอลสหม่ทกุ ครัง้ ที่มีการเรี ยกฟั งก์ชนั display
void display()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
drawBall(ball);
glFlush();
}
int main(int argc, char **argv)
{
...
glutDisplayFunc(display);
...
}
Animation ลูกบอลเด้งกระทบกาแพง (ต่อ)
• Controller
– ทาสห้ ลกู บอลเปลี่ยนตาแหน่ง
– เช็คว่าลูกบอลชนกาแพงหรื อไม่
– ถ้ าชน สห้ เปลี่ยนทิศทางการเคลื่อนที่ของมันด้ วยการเปลี่ยนความเร็ว
• ฟั งก์ชนั ที่ทาหน้ าที่เป็ น controller จะถูกเรี ยกเป็ นช่วงๆ
– สช้ glutTimerFunc
– ต้ องลงทะเบียนตัวเองกับ glutTimerFunc สหม่ทกุ ครัง้ ที่ถกู เรี ยก
– ต้ องเรี ยก glutPostRedisplay เพื่อสห้ ความเปลี่ยนแปลงถูกแสดงผล
Animation ลูกบอลเด้งกระทบกาแพง (ต่อ)
void updateBall(Ball &b)
{
b.x += b.vx;
b.y += b.vy;
if (b.x + b.radius > 1)
{
b.x = 1 - b.radius;
b.vx = -fabs(b.vx);
}
if (b.x - b.radius < -1)
/* handle collision with left wall */
if (b.y + b.radius > 1)
/* handle collision with top wall */
if (b.y - b.radius < -1)
/* handle collision with bottom wall */
}
Animation ลูกบอลเด้งกระทบกาแพง (ต่อ)
void updateBall(Ball &b)
{
b.x += b.vx;
เคลื่อนที่ลกู บอล
b.y += b.vy;
if (b.x + b.radius > 1)
{
b.x = 1 - b.radius;
b.vx = -fabs(b.vx);
}
if (b.x - b.radius < -1)
/* handle collision with left wall */
if (b.y + b.radius > 1)
/* handle collision with top wall */
if (b.y - b.radius < -1)
/* handle collision with bottom wall */
}
Animation ลูกบอลเด้งกระทบกาแพง (ต่อ)
void updateBall(Ball &b)
{
b.x += b.vx;
b.y += b.vy;
if (b.x + b.radius > 1)
{
b.x = 1 - b.radius;
b.vx = -fabs(b.vx);
}
if (b.x - b.radius < -1)
/* handle collision
if (b.y + b.radius > 1)
/* handle collision
if (b.y - b.radius < -1)
/* handle collision
}
เช็คว่าชนกับกาแพงด้ านขวาหรื อไม่
with left wall */
with top wall */
with bottom wall */
Animation ลูกบอลเด้งกระทบกาแพง (ต่อ)
void updateBall(Ball &b)
{
b.x += b.vx;
b.y += b.vy;
if (b.x + b.radius > 1)
{
b.x = 1 - b.radius;
b.vx = -fabs(b.vx);
}
if (b.x - b.radius < -1)
/* handle collision
if (b.y + b.radius > 1)
/* handle collision
if (b.y - b.radius < -1)
/* handle collision
}
ถ้ าชนสห้ เปลี่ยนทิศทางสห้ วิ่งไปด้ านซ้ าย
with left wall */
with top wall */
with bottom wall */
Animation ลูกบอลเด้งกระทบกาแพง (ต่อ)
void updateBall(Ball &b)
{
b.x += b.vx;
b.y += b.vy;
if (b.x + b.radius > 1)
{
b.x = 1 - b.radius;
b.vx = -fabs(b.vx);
}
if (b.x - b.radius < -1)
/* handle collision with left wall */
if (b.y + b.radius > 1)
/* handle collision with top wall */
if (b.y - b.radius < -1)
/* handle collision with bottom wall */
}
โค้ ดของด้ านอื่นๆ
ก็คล้ ายๆ กัน
Animation ลูกบอลเด้งกระทบกาแพง (ต่อ)
void animate(int param)
{
updateBall(ball);
glutTimerFunc(INTERVAL, animate, 0);
glutPostRedisplay();
}
int main(int argc, char **argv)
{
...
glutTimerFunc(0, animate, 0);
...
}
Animation ลูกบอลเด้งกระทบกาแพง (ต่อ)
void animate(int param)
{
updateBall(ball); เปลี่ยนโมเดลของลูกบอล (ทาสห้ มนั เคลื่อนที่)
glutTimerFunc(INTERVAL, animate, 0);
glutPostRedisplay();
}
int main(int argc, char **argv)
{
...
glutTimerFunc(0, animate, 0);
...
}
Animation ลูกบอลเด้งกระทบกาแพง (ต่อ)
void animate(int param)
{
สัง่ สห้ เรี ยกฟั งก์ชนั นี ้สหม่อีกครัง้
updateBall(ball);
หลังจากเวลาผ่านไป
glutTimerFunc(INTERVAL, animate, 0); INTERVAL มิลลิวินาที
glutPostRedisplay();
}
int main(int argc, char **argv)
{
...
glutTimerFunc(0, animate, 0);
...
}
Animation ลูกบอลเด้งกระทบกาแพง (ต่อ)
void animate(int param)
{
updateBall(ball);
glutTimerFunc(INTERVAL, animate, 0);
้
glutPostRedisplay(); สัง่ สห้ วาดทังฉากสหม่
}
int main(int argc, char **argv)
{
...
glutTimerFunc(0, animate, 0);
...
}
Animation ลูกบอลเด้งกระทบกาแพง (ต่อ)
void animate(int param)
{
updateBall(ball);
glutTimerFunc(INTERVAL, animate, 0);
glutPostRedisplay();
}
int main(int argc, char **argv)
{
...
glutTimerFunc(0, animate, 0);
...
}
ลงทะเบียนสห้ เรี ยก animate
เป็ นครัง้ แรกหลัง glutMainLoop
เริ่มทางาน (แล้ วมันจะจัดการสห้ มนั
ถูกเรี ยกครัง้ ต่อๆ ไปเอง)
Animation ลูกบอลเด้งกระทบกาแพง (ต่อ)
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE);
glutInitWindowSize(600,600);
glutCreateWindow("Bouncing Ball");
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutTimerFunc(0, animate, 0);
ball.x = 0;
ball.y = 0;
ball.vx = 0.02;
ball.vy = 0.03;
ball.radius = 0.05;
ball.r = 1.0;
ball.g = 0.5;
ball.b = 0.5;
glutMainLoop();
}
Animation ลูกบอลเด้งกระทบกาแพง (ต่อ)
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE);
glutInitWindowSize(600,600);
glutCreateWindow("Bouncing Ball");
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutTimerFunc(0, animate, 0);
ball.x = 0;
ball.y = 0;
ball.vx = 0.02;
ball.vy = 0.03;
ball.radius = 0.05;
ball.r = 1.0;
ball.g = 0.5;
ball.b = 0.5;
glutMainLoop();
}
เริ่มต้ น GLUT
สร้ างวินโดว์
ลงทะเบียนฟั งก์ชนั
ฯลฯ
Animation ลูกบอลเด้งกระทบกาแพง (ต่อ)
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE);
glutInitWindowSize(600,600);
glutCreateWindow("Bouncing Ball");
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutTimerFunc(0, animate, 0);
ball.x = 0;
ball.y = 0;
ball.vx = 0.02;
ball.vy = 0.03;
ball.radius = 0.05;
ball.r = 1.0;
ball.g = 0.5;
ball.b = 0.5;
glutMainLoop();
}
กาหนดค่าเริ่มต้ นของลูกบอล
ดู demo
DOUBLE BUFFERING
Flickering
•
•
•
•
ทาไมภาพมันกระพริ บๆ (ภาษาฝรั่งเรี ยกว่า flickering)
จอภาพจะแสดงภาพสหม่เป็ นช่วงๆ (ส่วนมากความถี่อยูท่ ี่ 60-72 เฮิร์ตซ์)
เวลาจอภาพ มันจะไปเอาข้ อมูลมาจาก framebuffer
การวาดภาพของเรามีหลายขันตอน
้
– ล้ าง framebuffer สห้ เป็ นสีดา
– วาดลูกบอลทีละกลีบ
• เพราะฉะนันข้
้ อมูลสน framebuffer บางเวลาจึงไม่สช่ภาพที่สมบูรณ์
• เมื่อเวลาประจวบเหมาะ จอภาพจะเอาภาพที่ไม่สมบูรณ์ไปแสดง ทาสห้
ภาพกระพริ บ
Double Buffering
•
•
•
•
•
•
แก้ ไขได้ โดยการสห้ มี framebuffer สองอัน
อันหนึง่ อยูห่ ลัง อันหนึง่ อยูห่ น้ า
เวลาวาดสห้ วาดสส่ framebuffer ที่อยูข่ ้ างหลัง
เวลาแสดงสห้ เอา framebuffer ที่อยูข่ ้ างหลังไปแสดง
ภาพที่แสดงจึงเป็ นภาพที่สมบูรณ์เสมอ
ไม่เกิด flickering
การใช้ double buffering ใน GLUT
• สช้ GLUT_DOUBLE แทน GLUT_SINGLE สน
glutInitDisplayMode
• สช้ glutSwapBuffers() แทน glFlush()
Animation ลูกบอลเด้งกระทบกาแพง (แก้ใหม่)
void display()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
drawBall(ball);
glFlush();
}
Animation ลูกบอลเด้งกระทบกาแพง (แก้ใหม่)
void display()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
drawBall(ball);
glutSwapBuffers();
}
Animation ลูกบอลเด้งกระทบกาแพง (แก้ใหม่)
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE);
glutInitWindowSize(600,600);
...
}
Animation ลูกบอลเด้งกระทบกาแพง (แก้ใหม่)
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(600,600);
...
}
KEYBOARD INPUT
รับอินพุตจากแป้ นพิมพ์
• glutKeyboardFunc(void (*func)​(unsigned char
key, int x, int y))
– สห้ ฟังก์ชนั ที่รับ unsigned char และ int สองตัว
– key คือ ascii code ของปุ่ มที่กด
– x และ y คือตาแหน่งของ mouse
ตัวอย่าง 1
void printKey(unsigned char key, int x, int y)
{
printf("You type key %d. The mouse is at (%d, %d)\n", key, x, y);
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE);
glutCreateWindow("glutKeyboardFunc Example");
glutDisplayFunc(display);
glutKeyboardFunc(printKey);
glutMainLoop();
}
ตัวอย่าง 2
•
•
•
•
โปรแกรมลูกบอลเด้ งชนกาแพง เวอร์ ชนั 2
ตอนนี ้มีลกู บอลได้ หลายลูกแล้ ว
กด space bar แล้ วมีลกู บอลเพิ่ม
กด Esc เป็ นการออกจากโปรแกรม
ตัวอย่าง 2
void keyboard(unsigned char key, int x, int y)
{
if (key == ' ')
{
newRandomBall();
glutPostRedisplay();
}
else if (key == 27)
exit(0);
}
ดู demo
3D LINEAR ALGEBRA
เวกเตอร์สามมิติ
• ลาดับของจานวนจริงสามตัว
(x; y; z)
• สัญลักษณ์: ตัวอักษรตัวพิมพ์เล็กหนา
u; v; w
• เซตของเวกเตอร์ สามมิติ
R3 = f (x; y; z) : x; y; z 2 Rg
• เวกเตอร์ พิเศษ
x = (1; 0; 0); y = (0; 1; 0); z = (0; 0; 1); 0 = (0; 0; 0)
เวกเตอร์สามมิติ (ต่อ)
• ความหมาย
– จุดสนสามมิติ
– ทิศทางสนสามมิติ
x
x
x
x
y
y
O
z
y
O
z
z
y
z
ปฏิบตั ิการบนเวกเตอร์สามมิติ
• กาหนดสห้
u
= (x 1 ; y1 ; z1 )
v
= (x 2 ; y2 ; z2 )
• การบวกและลบเวกเตอร์
u + v = (x 1 + x 2 ; y1 + y2 ; z1 + z2 )
• การคูณเวกเตอร์ ด้วยสเกลาร์
cu = (cx 1 ; cx 2 ; cx 3 )
ปฏิบตั ิการบนเวกเตอร์สามมิติ (ต่อ)
• การบวก = เอาท้ ายต่อหัว
x
u+ v
v
O
u
z
y
ปฏิบตั ิการบนเวกเตอร์สามมิติ (ต่อ)
• การคูณด้ วยสเกลาร์ = การยืด/หด
x
c1 u
u
c2 u
z
O
y
Linear Combination
• สห้ v 1; v 2; : : : ; v n เป็ นเวกเตอร์ สดๆ
และ c1; c2; : : : ; cn คือจานวนจริงสดๆ
เราเรี ยก
c1 v 1 + c2 v 2 + : : : + cn v n
ว่า linear combination ของ v 1; v 2; : : : ; v n
Linear Combination (ต่อ)
• เวกเตอร์ สามมิติทกุ เวกเตอร์ เป็ น linear combination ของ
x, y, และ z
(x; y; z) = x(1; 0; 0) + y(0; 1; 0) + z(0; 0; 1) = xx + yy + zz
Span
• ถ้ า v 1; v 2; : : : ; v n เป็ นเวกเตอร์ สดๆ แล้ ว
เราเรี ยกเซต
f c1v 1 + c2v 2 + ¢¢¢+ cn v n : c1; c2; : : : ; cn 2 Rg
ว่า span ของ
v 1; v 2; : : : ; v n
Span (ต่อ)
•
•
•
•
•
•
•
Span ของ
Span ของ
Span ของ
Span ของ
Span ของ
Span ของ
Span ของ
x, y, และ z มีคา่ เท่ากับ R3
x มีคา่ เท่ากับแกน x
y มีคา่ เท่ากับแกน y
z มีคา่ เท่ากับแกน z
x และ y มีคา่ เท่ากับระนาบ xy
x และ z มีคา่ เท่ากับระนาบ xz
y และ z มีคา่ เท่ากับระนาบ yz
Linear Dependence
• เรากล่าวว่า v 1; v 2; : : : ; v n
เป็ นกลุม่ ของเวกเตอร์ ที่ linearly dependent
ถ้ ามีสเกลาร์ c1; c2; : : : ; cn ที่มีตวั สดตัวหนึง่ มีคา่ ไม่เท่ากับ 0
ที่ทาสห้
c1 v 1 + c2 v 2 + : : : + cn v n = 0
Linear Independence
• ตรงข้ ามกับ linear dependence
• เรากล่าวว่า v 1; v 2; : : : ; v n
เป็ นกลุม่ ของเวกเตอร์ ที่ linearly independent
ถ้ าค่า c1; c2; : : : ; cn ที่ทาสห้
c1 v 1 + c2 v 2 + : : : + cn v n = 0
คือ
c1 = c2 = ¢¢¢= cn = 0
เท่านัน้
Linear Independence (ต่อ)
• x, y, และ z --- linearly independent
• (1,2,0) และ (2,4,0) --- linearly dependent
เพราะ 2*(1,2,0) – (2,4,0) = (0,0,0)
• (1,0,1), (2,3,0), (2,1.5,1) --- linearly dependent
เพราะ (1,0,1) + 0.5*(2,3,0) – (2,1.5,1) = (0,0,0)
• (0,0,0) --- linearly dependent
เพราะ c(0,0,0) = (0,0,0) สาหรับค่า c สดๆ ที่ไม่เท่ากับ 0
เส้นตรง
• ถ้ า u 6= 0 แล้ ว span ของ u คือเส้ นตรงที่ผ่านจุด O และ u
x
f cu : c 2 Rg
u
O
z
y
ระนาบ
• ถ้ า u และ v เป็ นเวกเตอร์ ที่ linearly independent กันแล้ ว
span ของ u และ v คือระนาบที่ผา่ นจุด O, u, และ v
x
f c1u + c2v : c1; c2 2 Rg
u
O
y
v
z
ปริ ภูมิเวกเตอร์
• ถ้ า u, v, และ w เป็ นเวกเตอร์ ที่ linearly independent กัน
แล้ ว span ของ u, v, และ w เซตของเวกเตอร์ สามมิตทิ งหมด
ั้
x
u
y
O
v
z
f c1 u + c2 v + c3 w : c1 ; c2 ; c3 2 Rg
Basis
• ถ้ า span ของ u, v, และ w
มีคา่ เท่ากับเซตของเวกเตอร์ สามมิตทิ งหมด
ั้
เราเรี ยก u, v, และ w ว่าเป็ น basis ของปริภมู ิเวกเตอร์ สามมิติ
Basis (ต่อ)
• x, y, และ z เป็ น basis ของปริภมู ิเวกเตอร์ สามมิติ
• (1,1,0), (0,1,1), และ (1,0,1) ก็เป็ น basis
• แต่ (1,0,1), (2,3,0), (2,1.5,1) ไม่สช่
เพราะมันไม่ linearly independent
ผลคูณสเกลาร์
• ผลคูณสเกลาร์ (dot product)
u ¢v = x1x2 + y1y2 + z1z2
• ขนาดเวกเตอร์
kuk =
p
1
x 21 + y12 + z12 = (u ¢u) 2
• สมบัตติ า่ งๆ
u ¢v = v ¢u
u ¢(v + w ) = u ¢v + u ¢w
u ¢(cv ) = c(u ¢v )
ku + v k2 = kuk2 + kv k2 + 2(u ¢v )
kcuk = ckuk
ผลคูณสเกลาร์ (ต่อ)
• สมบัติ
u ¢v = kukkvk cosµ
เมื่อ  คือมุมระหว่าง u กับ v
u

v
• u กับ v ตังฉากกั
้
นก็ตอ่ เมื่อ u ¢v = 0
เวกเตอร์หนึ่งหน่วย
• เวกเตอร์ ที่มีขนาดเท่ากับ 1
• kuk = 1
• ถ้ า u เป็ นเวกเตอร์ หนึง่ หน่วยแล้ ว
u ¢v = kvk cosµ คือความยาวของ v เมื่อแตกแรงไปสนทิศของ u
ผลคูณเวกเตอร์
• ผลคูณเวกเตอร์ (cross product)
u £ v = (y1 z2 ¡ y2 z1 ; z1 x 2 ¡ z2 x 1 ; x 1 y2 ¡ x 2 y1 )
= (y1 z2 ¡ y2 z1 )x + (z1 x 2 ¡ z2 x 1 )y + (x 1 y2 ¡ x 2 y1 )z
¯
¯
¯x y z ¯
¯
¯
¯
= ¯x 1 y1 z1 ¯
¯
¯x 2 y2 z2 ¯
•
u£ v
•
ku £ vk = kukkvk sin µ
ตังฉากกั
้
บทัง้ u และ v
u£ v

ผลคูณเวกเตอร์ (ต่อ)
• ทิศทางของ u £ v คิดตามกฎมือขวา
– เอามือขวาชี ้ไปตามทิศของ u สห้ ฝ่ามือหันไปทาง v
– u £ v ตังฉากกั
้
บระนาบที่นิยามโดย u กับ v พุง่ ออกไปฝั่ งที่นิ ้วโป้งขวาอยู่
u
v
v
u £ v พุง่ เข้ ากระดาษ
u
u £ v พุง่ ออกกระดาษ
ผลคูณเวกเตอร์ (ต่อ)
• สมบัติตา่ งๆ
u£ v = ¡ v£ u
u £ (v + w ) = u £ v + u £ w
u £ (r v ) = (r u) £ v = r (u £ v )
การแปลง
การแปลง (Transformations)
• ตัวอย่าง
– “เลื่อนไปทางซ้ าย 1 หน่วย”
– “หมุนรอบแกน y 90 องศา”
– “ขยายขนาดตามแกน z 2 เท่า”
• เอาไปสช้ ที่ไหน?
– Modeling
– Animation
– Rendering Pipeline
ตัวอย่าง
• สมมติเรารู้วิธีสร้ างวงกลมรัศมี 1 หน่วย จุดศูนย์กลางอยู่ที่ (0,0)
• อยากได้ วงกลมรัศมี 2 หน่วย จุดศูนย์กลางอยูท่ ี่เดิม
ขยาย 2 เท่า
ตัวอย่าง
• อยากได้ วงรี แกนเอกยาว 2 หน่วย แกนโทยาว 1 หน่วย
ขยาย 2 เท่าตามแกน x
ตัวอย่าง
• อยากได้ วงกลมรัศมี 0.5 หน่วย จุดศูนย์กลางอยูท่ ี่จดุ (1,1)
ย่อ 0.5 เท่า
เลื่อนแกน x และ y 1 หน่วย
การแปลงในสองมิติ
• การแปลงในสองมิติ คือ ฟั งก์ชนั ที่สง่ เวกเตอร์ (หรื อจุด) สองมิติไปยัง
เวกเตอร์ สองมิติ
– สัญลักษณ์ : ตัวอักษรภาษาอังกฤษตัวสหญ่ A, B, C, D, …
– เวลานิยาม:
ชื่อการแปลง
A : (x; y) 7
! (y; ¡ x)
หรื อจะเขียนแบบฟั งก์ชนั ก็ได้
A((x; y)) = (y; ¡ x)
จุดที่ (x,y) ถูกส่งไปหา
ตัวอย่าง
B : (x; y) 7
! (x + 2; y + 3)
C : (x; y) 7
! (x + y; 0)
D : (x; y) 7
! (1:5x; 3y)
E : (x; y) 7
! (x; ex )
F : (x; y) 7
! C(D ((x; y)) = (1:5x + 3y; 0)
การแปลงเอกลักษณ์
• การแปลงเอกลักษณ์ (Identity Transformation) คือ การ
แปลงที่สง่ จุดทุกจุดไปหาตัวมันเอง
I : (x; y) 7
! (x; y)
การแปลงเชิงเส้น
• เรากล่าวว่าการแปลง A เป็ นการแปลงเชิงเส้ น (linear
transformation) ถ้ ามันสอดคล้ องกับสมบัติตอ่ ไปนี ้
1. A(u + v ) = A(u) + A(v )
2. A(cu) = cA(u)
สาหรับเวกเตอร์ u, v สดๆ สน R2 และค่าคงที่ c สดๆ
ตัวอย่าง
• การแปลงเอกลักษณ์ I เป็ นการแปลงเชิงเส้ น เพราะ
1. I (u + v ) = u + v = I (u) + I (v )
2. I (cu) = cu = cI (u)
! (y; ¡ x) ก็เป็ นการแปลงเชิงเส้ น
• การแปลง A : (x; y) 7
! (x + 2; y + 3) ไม่สช่การแปลง
• แต่การแปลง B : (x; y) 7
เชิงเส้ น เพราะ
B ((2; 2)) = (4; 5) 6
= (6; 8) = B ((1; 1)) + B ((1; 1))
ข้อสังเกต
• ถ้ า A เป็ น linear transformation แล้ ว
A(0) = 0
เพราะ 2A(0) = A(2 £ 0) = A(0)
การแปลงเชิงเส้นที่สาคัญ 2 ชนิด
• การย่อขยาย (Scaling)
• การหมุน (Rotation)
การย่อขยาย
• การย่ อขยาย (Scaling) คือการแปลงที่อยูส่ นรูป
S®;¯ : (x; y) 7
! (®x; ¯y)
มีความหมายคือ
– ขยายสนแนวแกน x เป็ นจานวน α เท่า
– ขยายสนแนวแกน y เป็ นจานวน β เท่า
ตัวอย่าง
• เนื่องจาก S1;1 ((x; y)) = (1x; 1y) = (x; y)
ดังนัน้ S1;1 = I
• S2;2((1; 3)) = (2; 6)
• S1;0:5 ((3; 10)) = (3; 5)
•
S1;2
การหมุน
• การหมุน (rotation) สนที่นี ้จะต้ องกาหนดมุม θ และเราจะหมุน
ทวนเข็มนาฬิการอบจุด origin ไปเป็ นมุม θ
• สัญลักษณ์ R µ โดย
Rµ : (x; y) 7
! (x cosµ ¡ y sin µ; y cosµ + x sin µ)
x
µ
y
ตัวอย่าง
• I = R0 (หมุน 0 เรเดียนเท่ากับไม่หมุนเลย)
³
• R ¼6 ((1; 0)) =
•
p
´
³
´
¼
¼
3 1
cos ; sin
=
;
6
6
2 2
R ¼4
Linear Transformation และ Basis
• สห้ x = (1,0) และสห้ y = (0,1)
เราได้ วา่ สาหรับจุด (x,y) สดๆ
(x,y) = x(1,0) + y(0,1) = xx + yy
• ถ้ า A เป็ น linear transformation เราจะได้ วา่
A((x; y)) = A(xx + yy )
= A(xx ) + A(yy )
= xA(x ) + yA(y )
Linear Transformation และ Basis
• กล่าวคือถ้ าเรารู้ A(x) และ A(y) เราก็สามารถคานวณ
A((x,y)) สาหรับเวกเตอร์ (x,y) สดๆ ได้ ทงหมด
ั้
• พูดอีกแบบคือ linear transformation จะถูกนิยามด้ วยค่า
ของมันที่ basis ของ vector space
การแทนการแปลงเชิงเส้นด้วยเมตริ กซ์
• สมมติวา่ A(x) = (a,b) และ A(y) = (c,d)
จะได้ วา่
A((x; y)) = x(ax + by ) + y(cx + dy )
= (ax + cy)x + (bx + dy)y
= (ax + cy; bx + dy)
การแทนการแปลงเชิงเส้นด้วยเมตริ กซ์
· ¸
x
• ถ้ าเขียนคูล่ าดับ (x,y) ด้ วย column vector y
จะได้ วา่
µ· ¸¶
·
¸
x
ax + cy
A
=
y
bx + dy
·
¸· ¸
a c x
=
b d y
• ฉะนันการแปลงเชิ
้
งเส้ นสองมิตคิ ือเมตริกซ์ 2x2
การแทนการแปลงเชิงเส้นด้วยเมตริ กซ์
• สังเกต
·
¸
a c
A=
b d
A(x)
การแทนการแปลงเชิงเส้นด้วยเมตริ กซ์
• สังเกต
·
¸
a c
A=
b d
A(y )
ตัวอย่าง
• I เป็ นการแปลงเชิงเส้ น และ I(x) = (1,0), I(y) = (0,1)
ดังนัน้
·
¸
1 0
I =
0 1
เมตริกซ์เอกลักษณ์
• เนื่องจาก S®;¯ (x) = (®; 0); S®;¯ (y) = (0; ¯)
ดังนัน้
·
¸
S®;¯
® 0
=
0 ¯
ตัวอย่าง
• เนื่องจาก
Rµ (x ) = (cosµ; sin µ)
Rµ (y ) = (¡ sin µ; cosµ)
ดังนัน้
·
¸
cosµ ¡ sin µ
Rµ =
sin µ cosµ
การเลื่อนแกนขนาน
• การเลื่อนแกนขนาน (translation) คือ การแปลงที่อยูส่ นรูป
Tu : v 7
! v+u
มีความหมายคือ ถ้ า u = (u1, u2) แล้ ว
เราจะเลื่อนรูปไปตามแกน x เท่ากับ u1 หน่วย
และเลื่อนรูปไปตามแกน y เท่ากับ u2 หน่วย
ตัวอย่าง
• I เป็ นการเลื่อนแกนขนาน เพราะ I(u) = u + 0 ดังนัน้
T(0,0) (เขียนง่ายๆ ว่า T0,0)
I=
• T2,3 (0,0) = (2,3) ดังนัน้ T2,3 ไม่สช่การแปลงเชิงเส้ น
• กล่าวคือ ถ้ า u ไม่สช่ 0 แล้ ว Tu ไม่เป็ นการแปลงเชิงเส้ น เนื่องจาก
Tu(0) = u ซึง่ มีคา่ ไม่เท่ากับ 0
ตัวอย่าง
•
T1;1
Composition
• Composition คือการนาเอาการแปลงสองอันมารวมสห้ เป็ นอัน
เดียววิธีหนึง่
• สห้ A กับ B เป็ นการแปลง composition ของมันคือการแปลง
BA โดยที่
B A : (x; y) 7
! B (A((x; y))
กล่าวคือเป็ นการแปลงที่เกิดขึ ้นจากการนาเวกเตอร์ ข้อมูลเข้ าไปแปลง
ด้ วย A ก่อนแล้ วจึงแปลงด้ วย B
ตัวอย่าง
• T0;1 R ¼2 คือการหมุน 90 องศาแล้ วเลื่อนทางแกน y หนึง่ หน่วย
R ¼2
T0;1 R ¼2
T0;1
ข้อสังเกต
• ถ้ า A เป็ นการแปลงสดๆ แล้ ว IA = AI = A
• ระวัง! โดยทัว่ ไปแล้ ว AB 6= B A
• ดู R ¼2 T0;1
T0;1
R T0;1
¼
2
R ¼2
การแปลงแอฟไฟน์
• เรากล่าวว่าการแปลง A เป็ นการแปลงแอฟไฟน์ (affine
transformation) ถ้ า
A = Tu B
โดยที่ Tu เป็ นการเลื่อนแกนขนานและ B เป็ นการแปลงเชิงเส้ น
ตัวอย่าง
• I เป็ นการแปลงแอฟไฟน์เพราะ I = T0,0I
• T0;1 R ¼2 เป็ นการแปลงแอฟไฟน์ (อย่างเห็นได้ ชดั )
• R ¼2 T0;1 ก็เป็ นการแปลงแอฟไฟน์เชิงเดียวกัน เพราะ
R ¼2 T0;1 (v ) = R ¼2 (v + (0; 1))
= R ¼2 (v ) + R ¼2 ((0; 1))
= R ¼2 (v ) + (¡ 1; 0)
= T¡
(v )
1;0 R ¼
2
ข้อสังเกต
• ถ้ า B เป็ นการแปลงเชิงเส้ นแล้ ว BTu จะเป็ นการแปลงแอฟไฟน์เสมอ
เนื่องจาก
BTu (v) = B(v + u) = B(v) + B(u) = TB (u ) B(v)
กล่าวคือ
BTu = TB (u ) B
ข้อสังเกต
• เราสามารถพิสจู น์ได้ ทานองเดียวกันว่า ถ้ าแต่ละตัวของการแปลง
A 1; A 2; : : : ; A n¡ 1; A n เป็ นการเลื่อนแกนขนานหรื อการแปลงเชิง
เส้ นแล้ ว การแปลง A n A n ¡ 1 ¢¢¢A 2A 1จะเป็ นการแปลงแอฟไฟน์
• ดังนันการแปลงแอฟไฟน์
้
จงึ เป็ นกลุม่ ของการแปลงที่รวม
– การย่อขยาย
– การหมุน
– การเลื่อนแกนขนาน
– การแปลงเชิงเส้ น
เอาไว้ ทงหมด
ั้
Homogeneous Coordinates
• Homogeneous coordinates เป็ นวิธีการแทนจุดสองมิติ
ด้ วยเวกเตอร์ สามมิตแิ บบหนึง่ โดยที่
เวกเตอร์ (x,y,w) หมายถึงจุด (x/w,y/w) ถ้ า w ≠ 0
• ตัวอย่าง
– (1,2,1) หมายถึงจุด (1,2)
– (2,4,2) หมายถึงจุด (1,2) เช่นเดียวกัน
– (w,2w,w) ก็หมายถึงจุด (1,2) สาหรับค่า w สดๆ
การแทนการแปลงแอฟไฟน์ดว้ ยเมตริ กซ์
• สมมติวา่ เรามีการแปลงแอฟไฟน์ A = Tu B โดยที่
·
¸
a c
B=
;
b d
จะได้ วา่
· ¸
e
u=
f
µ· ¸¶
·
¸· ¸
x
a c x
A
=
y
b d y
·
ax + cy +
=
bx + dy +
· ¸
e
+
f
¸
e
f
การแทนการแปลงแอฟไฟน์ดว้ ยเมตริ กซ์
• สห้
2
3
a c e
N = 4b d f 5
0 0 1
เมื่อเราคูณ N ด้ วย (x,y,1) ซึง่ เป็ น homogeneous
coordiate ของ (x,y) จะได้ วา่
2 3 2
32 3 2
x
a c e x
ax + cy +
N 4 y 5 = 4 b d f 5 4 y 5 = 4 bx + dy +
1
0 0 1 1
1
homogeneous coordinate ของ A((x; y))
3
e
f5
การแทนการแปลงแอฟไฟน์ดว้ ยเมตริ กซ์
• ฉะนัน้ affine transform คือเมตริกซ์ 3x3 ที่แถวล่างเท่ากับ
(0,0,1)
การแทนการแปลงแอฟไฟน์ดว้ ยเมตริ กซ์
• สังเกต
2
3
a c e
A = 4b d f 5
0 0 1
A(x) ¡ u = B (x)
การแทนการแปลงแอฟไฟน์ดว้ ยเมตริ กซ์
• สังเกต
2
3
a c e
A = 4b d f 5
0 0 1
A(y ) ¡ u = B (y )
การแทนการแปลงแอฟไฟน์ดว้ ยเมตริ กซ์
• สังเกต
2
3
a c e
A = 4b d f 5
0 0 1
u = A(0)
ตัวอย่าง
•
•
•
•
T0;1 R ¼2 ((0; 0)) = (0; 1)
T0;1 R ¼2 ((1; 0)) ¡ (0; 1) = (0; 2) ¡ (0; 1) = (0; 1)
T0;1R ¼2 ((0; 1)) ¡ (0; 1) = (¡ 1; 1) ¡ (0; 1) = (¡ 1; 0)
ดังนัน้
2
T0;1 R ¼2
3
0 ¡ 1 0
= 4 1 0 15
0 0 1
เมตริ กซ์ของการแปลงแอฟไฟน์ที่สาคัญ
2
S®;¯
3
® 0 0
= 4 0 ¯ 05
0 0 1
2
3
1 0 u1
Tu = 4 0 1 u2 5
0 0 1
2
3
cosµ ¡ sin µ 0
R µ = 4 sin µ cosµ 05
0
0
1
2
3
1 0 0
I = 4 0 1 05
0 0 1
Composition และเมตริ กซ์
• Composition คือการคูณเมตริกซ์
• ตัวอย่าง
2
T0;1 R ¼2
32
3 2
3
1 0 0 0 ¡ 1 0
0 ¡ 1 0
= 4 0 1 15 4 1 0 05 = 4 1 0 15
0 0 1 0 0 1
0 0 1
การแปลงผันกลับ
• การแปลงผันกลับ (inverse) ของการแปลง A คือการแปลง A-1
ที่ทาสห้
AA ¡ 1 = A ¡ 1A = I
• การแปลงบางตัวไม่มี inverse เช่น A : (x; y) 7
! (x; 0)
• การแปลงแอฟไฟน์ A จะมี inverse ก็ตอ่ เมื่อเมตริกซ์ของ A มี
inverse พูดอีกนัยหนึง่ คือ det (A) 6
= 0
การแปลงผันกลับของการแปลงแอฟไฟน์ที่สาคัญ
2
¡
S®;¯
¢¡
1
3¡
® 0 0
= 4 0 ¯ 05
0 0 1
2
¡
Tu
¢¡
1
3¡
1 0 u1
= 4 0 1 u2 5
0 0 1
1
21
®
= 40
0
1
2
0
1
¯
0
3
0
05 = S 1 ; 1
® ¯
1
3
1 0 ¡ u1
= 4 0 1 ¡ u2 5 = T¡
0 0
1
u
การแปลงผันกลับของการแปลงแอฟไฟน์ที่สาคัญ
2
¡
Rµ
¢¡
1
3¡ 1
cosµ ¡ sin µ 0
= 4 sin µ cosµ 05
0
0
1
2
3
¡ cosµ ¡ sin µ 0
= 4 sin µ ¡ cosµ 05
0
0
1
2
3
cos(¡ µ) ¡ sin(¡ µ) 0
cos(¡ µ) 05 = R ¡
= 4 sin(¡ µ)
0
0
1
µ

similar documents