본문 바로가기
[그래픽스]

[그래픽스] CTM이란?, OpenGL Coordinate System 실습

by seom-j 2024. 2. 7.

📌 Current Transformation Matrix (ctm)

4*4 동차좌표에서, 사용자 프로그램에서 정의 & 변환 장치에 로드

ctm을 운영하여 동차좌표계에서의 변환 수행

 

 

📌 CTM 종류

행렬 로드 C ← I

임의의 행렬 로드 C ← M

 

변환 행렬 로드 C ← T

t회전 행렬 로드 C ← R

r스케일링 행렬 로드 C ← S

 

임의의 행렬 곱 C ← CM

변환 행렬 곱 C ← CT

회전 행렬 곱 C ← CR

스케일링 행렬 곱 C ← CS

 

 

📌 고정점 중심 회전

행렬 로드 C ← I

고정점 원점으로 이동 C ← CT

회전 C ← CR

고정점 돌아가기 C ← CT(-1)

결과 C = TRT(-1)

 

수행해야할 것

행렬 로드 C ← I

고정점 원점으로 이동 C ← CT(-1)

회전 C ← CR

고정점 돌아가기 C ← CT

결과 C = T(-1)RT

→ 함수 호출에 해당하므로 가장 마지막 연산이 가장 먼저 실행

 

ex)

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(1.0, 2.0, 3.0);
glRotatef(30.0, 0.0, 0.0, 1.0);
glTranslatef(-1.0, -2.0, -3.0);

 

 

📌 OpenGL의 CTM

Model View와 Projection matrix가 존재, 이는 서로 연결되어 ctm 형성

올바른 모드를 설정하여 각각을 조작할 수 있음

glLoadIdentity()
glRotatef(theta, vx, vy, vz)
glTranslatef(dx, dy, dz)
glScalef(sx, sy, sz)

//ex
//고정점 (1.0, 2.0, 3.0)을 사용하여 z축을 중심으로 30도 회전
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(1.0, 2.0, 3.0) // 3 - 다시 돌아오기 ~!
glRotatef(30.0, 0, 0, 1.0) // 2 - 회전
glTranslatef(-1.0, -2.0, -3.0) // 1 - 원점으로 이동
//여기서 빼서 0으로 만드는 것이 가장 먼저 적용되는 행렬임을 기억하자이

 

 

📌 임의 행렬

application program에 의해 정의된 행렬을 로드하고 곱할 수 있음

glLoadMatrixf(const Glfloat*m);
glMultMatrixf(const Glfloat*m);

행렬m은 16개의 요소로 구성된 1차원 배열로, 4*4의 열로 저장

glMultMatrixf에서 m은 오른쪽의 기존 행렬에 곱

 

 

📌 row vs column - major order

a b c d

e f g h

i j k l

m n o p

rows : a b c d e f g h i j k l m n o p

columns : a e i m b f j n c g k o d h l p

OpenGL은 column major을 필요로 함

C는 row major이므로 OpenGL에 보내기 전에 transpose 필요

 

 

📌 행렬 스택

변환한 행렬을 저장(추후 사용을 위함)

OpenGL은 각 행렬 유형에 대한 스택 저장 (as set by glMatrixMode)

glPushMatrix()
glPopMatrix()

 

 

📌 OpenGL Coordinate System 실습 코드

#include<GL/glut.h>
// opengl libraries

float angle = 120;

void drawAxes() {
	glBegin(GL_LINES);
	glVertex2f(0, -.2);
	glVertex2f(0, .2);
	glEnd(); // 세로선

	glBegin(GL_LINES);
	glVertex2f(-.2, 0);
	glVertex2f(.2, .0);
	glEnd(); // 가로선

	glFlush();
}

void display() {
	glClear(GL_COLOR_BUFFER_BIT);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glColor3f(1, .5, .5);
	drawAxes(); // 기본(1) 좌표 그리기

	glTranslatef(.2, .2, 0);
	glColor3f(0, 1, 1);
	drawAxes(); // .2, .2만큼 옮긴(2) 좌표 그리기

	glRotatef(110, 0, 0, 1); // (2)를 기준으로 110도 회전
	glTranslatef(.35, .35, 0); // 기준 좌표 이동 .35, .35 (3)
	glRotatef(-110, 0, 0, 1); // 모양, 방향 유지되면서 회전하도록! (3) 기준으로 -110도 회전해주기
	glColor3f(1, 0, 0);
	drawAxes();
}

void init() {
	glClearColor(0.0, 0.0, 0.0, 1.0); // 배경 (r, g, b, 투명도)
	glColor3f(1.0, 1.0, 1.0);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity(); // 카메라 설정

	gluOrtho2D(-1.0, 1.0, -1.0, 1.0); // 2차원
}

int main(int argc, char** argv) {

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
	glutInitWindowSize(500, 500);
	glutInitWindowPosition(0, 0);

	glutCreateWindow("Coordinate System");
	glutDisplayFunc(display);
	init();
	glutMainLoop();
}