Transcript Document
01418341 สภาพแวดล ้อมการทางาน คอมพิวเตอร์กราฟิ กส ์ การบรรยายครัง้ ที่ 2 ประมุข ขันเงิน [email protected] CULLING Culling • รูปหลายเหลีย ่ มมีสองหน ้า: ด ้านหน ้า กับ ด ้านหลัง • เวลาวาดรูปทรงสามมิต ิ สว่ นมากด ้านหน ้าจะหัน หน ้ามาหาเรา • ฉะนัน ้ โดยมากไม่มค ี วามจาเป็ นต ้องวาดรูป เหลีย ่ มทีห ่ น ั หลังใสเ่ รา – ชว่ ยให ้โปรแกรมเร็วขึน ้ ่ มองเห็นภาพ – ชว่ ยทาเอฟเฟกต์บางอย่าง เชน ภายนอกจากภายในวัตถุ • เราสามารถสงั่ ให ้ OpenGL ไม่วาดรูปหลาย 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 ้ ้ keyboard หรือ mouse • callback สาหรับเวลาผู ้ใชใช 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 ใหม่ทก ุ ครัง้ ทีถ ่ ก ู เรียก 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 v 1; v 2; : : : ; v n ว่า linear combination ของ Linear Combination (ต่อ) • เวกเตอร์สามมิตท ิ ก ุ เวกเตอร์เป็ น linear combination ของ x, y, (x;และ y; z) = zx(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 เราเรียกเซต v 1; v 2; : : : ; v n ว่า span ของ Span (ต่อ) • • • • • • • Span ของ Span ของ Span ของ Span ของ Span ของ Span ของ Span ของ x, y, และ z มีRค3า่ เท่ากับ 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 xคือระนาบทีผ ่ า่ นจุด O, u, f c1u + c2v : c1; c2 2 Rg และ v 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อ =อ 0 • u กับ v ตัง้ ฉากกันก็ต ่¢vเมื ่ เวกเตอร์หนึง่ หน่วย • เวกเตอร์ทม ี่ ข ี นาดเท่ากับ 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 ตัง้ ฉากกับทัง้ u และ v ku £ vk = kukkvk sin µ 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) ั (y; หรือจะเขียA((x; นแบบฟั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) R2 สาหรับเวกเตอร์ u, v ใดๆ ใน และค่าคงที่ c ใดๆ ตัวอย่าง • การแปลงเอกลักษณ์ I เป็ นการแปลงเชงิ เสน้ เพราะ 1. I (u + v ) = u + v = I (u) + I (v ) 2. I (cu) = cu = cI (u) A : (x; y) 7 ! (y; ¡ x) • การแปลงB : (x; y) 7 ! (x + 2; y + 3) เป็ นการแปลงเชงิ เสน้ ก็ •Bแต่ ารแปลง ไม่ใ1)) ช่ ((2;ก2)) = (4; 5) 6 = (6; 8) = B ((1; 1)) + B ((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 µ ั :ลั(x; •R สµญ กษณ์ y) 7 ! (x โดย cosµ ¡ y sin µ; y cosµ + x sin µ) x µ y ตัวอย่าง • I = R0 (หมุน 0 เรเดียนเท่ากับไม่หมุนเลย) ³ ¼ ((1; 0)) = R • 6 • 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 ดังนัน ้ I = T(0,0) (เขียนง่ายๆ ว่า T0,0) ่ ารแปลง • 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 เป็ นการแปลงแอฟไฟน์ (อย่างเห็นได ้ ั ¼2 )T0;1 ช Rด ิ • ก็Rเ¼ป็Tนการแปลงแอฟไฟน์ เ ช ง เดี ย วกั น ¼ 0;1 (v ) = R 2 (v + (0; 1)) 2 เพราะ ¼ ¼ = 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 ข ้อสงั เกต • เราสามารถพิสจ ู น์ได ้ทานองเดียวกันว่า ถ ้าแต่ละ ตั1ว;ของการแปลง A 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 e B= b d ; u= µ· ¸¶ · ¸· ¸ จะได ้ว่า x a c x A = y b d y · ax + cy + = bx + dy + f · ¸ 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 ่ y) 7 A : เช (x;น ! (x; 0) • การแปลงบางตัวไม่ม ี inverse • การแปลงแอฟไฟน์ A จะมี inverse ก็ตอ ่ เมือ ่ det (A) =อีก 0นัยหนึง่ คือ ์ อง A มี inverse เมตริกซข พูด6 การแปลงผันกลับของการแปลงแอฟ ไฟน์ทส ี่ าคัญ 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 µ