Last active
December 5, 2016 22:27
-
-
Save offchan42/af3a62543a8a80baf8662ef3a80142f3 to your computer and use it in GitHub Desktop.
OpenGL Prototype - template for good code design, less overwhelming, less headache for maintenance
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <gl/glut.h> | |
using namespace std; | |
int W = 500; // window width | |
int H = 500; // window height | |
float time = 0; // เวลาปลอมๆสำหรับทำอนิเมชัน | |
float timeRate = 0.001; // timeRate นี่เป็นเรทเวลาจำลอง ปรับได้ถ้าอยากให้อนิเมชันมันช้าหรือเร็วขึ้น | |
// your global variables here ... | |
// e.g. float x = 10; | |
float x = 10; // ลบได้ | |
float angleA = 0; // ลบได้ | |
float armAngle = 0; // ลบได้ | |
// หน้าที่ของฟังก์ชันนี้คือวาด A อย่างเดียว "อย่าใช้มันเคลื่อนที่ทำอนิเมชัน" | |
// ที่สำคัญคือ ควรให้เป็นการวาดที่จุด (0, 0) อยู่ตรงกลาง เพราะเวลา transform มันจะได้ง่ายๆ | |
void drawA() { | |
glPushMatrix(); // จงมี push, pop ครอบในฟังก์ชันเสมอ เพื่อป้องกันไม่ให้มันส่ง effect กับรูปอื่นๆ | |
// ... transformation (translate, rotate, scale) ... | |
// draw your A (glBegin, glEnd) | |
glPopMatrix(); | |
} | |
// drawB, drawC, drawD ... | |
void display() { | |
glClear(GL_COLOR_BUFFER_BIT); | |
glClearColor(1.0f, 1.0f, 1.0f, 1.0f); | |
glMatrixMode(GL_MODELVIEW); | |
glLoadIdentity(); | |
// start drawing | |
glPushMatrix(); // เริ่มต้นวาดรูป แล้วใส่อนิเมชันด้วย | |
// transformation for animation | |
glTranslatef(x, 0, 0); // ตัวแปร x จะเปลี่ยนไปเรื่อยตามกาลเวลา ทำให้ drawA() ขยับ | |
// และสามารถวาดได้หลายอัน โดยการันตีได้ว่าจะไม่ transform ส่งผลต่อกัน | |
// เพราะข้างในฟังก์ชัน drawA() มี push, pop ครอบอยู่ | |
drawA(); | |
glTranslatef(20, 0, 0); // อย่างงี้จะได้ตัว A สองตัวที่วิ่งไปทางขวาเหมือนกัน อยู่ห่างกัน 20 | |
glRotate(angleA, 0, 0, 1); // แถมตัวที่สองจะหมุน และจะไม่ส่งผลต่อรูปที่อยู่ข่างล่างๆ | |
drawA(); | |
// หรือแม้กระทั่งใช้ for loop เพื่อวาด A สิบตัว | |
for (int i = 0; i < 10; i++) { | |
glTranslatef(20, 0, 0); | |
drawA(); | |
} | |
glPopMatrix(); | |
// end of drawing | |
// draw something else ... | |
// push, draw, pop ... do it like this forever... | |
glutSwapBuffers(); // ทำให้ภาพไม่กระพริบ | |
} | |
// ทำอนิเมชัน การเคลื่อนไหว ในนี้ โดยการปรับค่าตัวแปร global ต่างๆ ที่นิยามไว้ข้างบน | |
void idleFunc() { | |
// เช่น x += 0.01; เพื่อทำให้รูป A มันขยับทุกๆเฟรม ไปทีละ 0.01 หน่วย | |
x += 0.01 * timeRate; // ถ้าเป็นไปได้ให้คูณกับเวลาจำลอง timeRate แบบนี้ เพื่อเวลาเราแก้ timeRate ความเร็วมันจะได้เปลี่ยนกันทั้งจอ | |
// ฟังก์ชัน idleFunc() นี้จะถูกเรียกซ้ำๆ ถี่ๆยิบ เป็นพันครั้งต่อวินาที หรือตกต่ำได้ถึง 50 ครั้งต่อวินาที แล้วแต่ความเร็วคอมพิวเตอร์ | |
// ดังนั้นถ้าคอมเร็วต้องปรับค่า x += เลขน้อยๆ | |
// ฟังก์ชันทำ animation ที่แนะนำคือ sin, cos เพราะมันจะสวยงามกว่าการเช็ค if, else อย่างเช่นเวลาต้องการให้ | |
// แขนขยับไปมาอยู่ในช่วงมุม -90 ถึง 90 อย่างงี้ใช้ armAngle = sin(time) * 90; แทนเช็ค if-else แบบดิบๆ จะได้ความเป็นธรรมชาติมากกว่า | |
// แถมมันเขียนง่ายกว่า if-else ยาวๆอีก แล้วมันยังแสดงถึงความเป็นคณิตศาสตร์อีกด้วย | |
// (ฟังก์ชัน sine จะคืนค่าในช่วง -1 ถึง 1 มาให้ พอคูณ 90 มันเลยเป็น -90 ถึง 90) | |
armAngle = sinf(time * 0.5) * 90; // ใช้ sinf เพราะเป็น float | |
// เห็นตรง 0.5 หรือไม่ ตัวนี้เปลี่ยนได้ เป็นความถี่การเหวี่ยงแขน เช่นเดียวกับ 90 เป็นมุม | |
glutPostRedisplay(); // คำสั่งนี้จะเป็นการบอกคอมพิวเตอร์ว่า "เห้ย วาดรูปใหม่เดี๋ยวนี้เพราะข้าเปลี่ยนตัวแปร x แล้วนะ" | |
// โดยคอมพิวเตอร์มันจะไปเรียก display() อีกที ซึ่งแล้วแต่อารมณ์ความเร็วของมัน ว่ามันจะเรียกเมื่อไร | |
// แต่ส่วนใหญ่แล้วไม่ต้องกังวลเพราะใน 1 วิตาเรามองได้ทันแค่ 90 เฟรมต่อวิเท่านั้นแหละ | |
time += timeRate; | |
} | |
int main(int argc, char **argv) { | |
glutInit(&argc, argv); | |
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); | |
glutInitWindowSize(W, H); | |
gluOrtho2D(0, W, 0, H); | |
glutCreateWindow("Your Beautiful Window Name"); | |
glutDisplayFunc(display); | |
glutIdleFunc(idleFunc); | |
glutMainLoop(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment