World Frame: 감독 관점, 물체를 배치하기 위해 필요
Object Frame: 물체 디자인을 위해 필요 (Model Frame이라고도 함)
View Frame: 카메라를 시뮬레이션하기 위해 필요
큐브 만들기
8개의 꼭짓점과 12개의 삼각형으로 정육면체를 만듦
피라미드 만들기
5개의 꼭짓점과 6개의 삼각형으로 사각뿔을 만듦
Model Transform
물체를 배치하기 위해 월드 좌표계 기준으로 Scale/Rotate/Translate 적용
M_model: Model Transform 행렬
q_model: Model Frame 상의 물체의 좌표
물체의 좌표 q_model에 대해 M_model 행렬 연산을 진행하면 World Frame 기준의 좌표로 변환됨
// 한 면을 2개의 삼각형으로 표현
// 좌표와 색상을 구조체로 묶어 사용
glm::vec4 vertCube[] = { // 12 * 3 = 36 (vertices + color)
// face 0,1: v0-v3-v2, v0-v2-v1, red
{ -0.5F, -0.5F, +0.5F, 1.0F }, { 1.0F, 0.3F, 0.3F, 1.0F }, // v0
{ -0.5F, -0.5F, -0.5F, 1.0F }, { 1.0F, 0.3F, 0.3F, 1.0F }, // v3
{ +0.5F, -0.5F, -0.5F, 1.0F }, { 1.0F, 0.3F, 0.3F, 1.0F }, // v2
{ -0.5F, -0.5F, +0.5F, 1.0F }, { 1.0F, 0.3F, 0.3F, 1.0F }, // v0
{ +0.5F, -0.5F, -0.5F, 1.0F }, { 1.0F, 0.3F, 0.3F, 1.0F }, // v2
{ +0.5F, -0.5F, +0.5F, 1.0F }, { 1.0F, 0.3F, 0.3F, 1.0F }, // v1
...
};
glm::vec4 vertPyramid[] = { // 6 * 3 = 18 (vertices + color)
// face 0: v0-v1-v2, red
{ 0.0F, 0.5F, 0.0F, 1.0F }, { 1.0F, 0.3F, 0.3F, 1.0F, }, // v0
{ 0.5F, -0.3F, 0.0F, 1.0F }, { 1.0F, 0.3F, 0.3F, 1.0F, }, // v1
{ 0.0F, -0.3F, -0.5F, 1.0F }, { 1.0F, 0.3F, 0.3F, 1.0F, }, // v2
...
};
// 단위행렬로 초기화
glm::mat4 matPyramid = glm::mat4( 1.0F );
glm::mat4 matCube = glm::mat4( 1.0F );
void updateFunc(void) {
...
// 변환을 적용하는 순서와 함수를 호출하는 순서는 반대
// Scale -> Rotate -> Translate 순서대로 변환이 적용됨
matPyramid = glm::mat4( 1.0F );
matPyramid = glm::translate( matPyramid, glm::vec3(-0.4F, 0.0F, 0.0F));
matPyramid = glm::rotate( matPyramid, theta, glm::vec3(0.0F, 1.0F, 0.0F));
matPyramid = glm::scale( matPyramid, glm::vec3(0.5F, 0.5F, 0.5F));
matCube = glm::mat4( 1.0F );
matCube = glm::translate( matCube, glm::vec3(0.4F, 0.0F, 0.0F));
matCube = glm::rotate( matCube, theta, glm::vec3(1.0F, 0.0F, 0.0F));
matCube = glm::scale( matCube, glm::vec3(0.3F, 0.3F, 0.3F));
}
void drawFunc(void) {
...
GLuint locPos = glGetAttribLocation(prog, "aPos");
GLuint locColor = glGetAttribLocation(prog, "aColor");
GLuint locMat = glGetUniformLocation(prog, "uMat");
glEnableVertexAttribArray(locPos);
glEnableVertexAttribArray(locColor);
// 포지션을 설정
glVertexAttribPointer(locPos, 4, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), glm::value_ptr(vertPyramid[0]));
// 컬러를 지정
glVertexAttribPointer(locColor, 4, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), glm::value_ptr(vertPyramid[1]));
// 유니폼 변수에 Model Transform 행렬 적용
glUniformMatrix4fv(locMat, 1, GL_FALSE, glm::value_ptr(matPyramid));
glDrawArrays(GL_TRIANGLES, 0, 18); // 18 vertices
glVertexAttribPointer(locPos, 4, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), glm::value_ptr(vertCube[0]));
glVertexAttribPointer(locColor, 4, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), glm::value_ptr(vertCube[1]));
glUniformMatrix4fv(locMat, 1, GL_FALSE, glm::value_ptr(matCube));
// 각자 다른 변환 행렬을 적용하고 있으므로 회전 방향도 다르게 적용
glDrawArrays(GL_TRIANGLES, 0, 36); // 36 vertices
...
}
피라미드와 큐브 별로 각자의 변환 행렬이 적용되는 것을 확인
(피라미드는 y축, 큐브는 x축 회전)
