카테고리 없음

[OpenGL] 오일러 앵글 Euler angle

usingsystem 2024. 4. 18. 10:18
728x90

오일러 앵글

임의의 좌표를 그려 회전한다면 다양한 각도를 만들 수 있지만 1개의 좌표축을 사용한다면 절대 못 만드는 각도가 존재하게 된다. 하지만 비교적 간단한 행렬식이 나타난다.

 

이런 특정좌표축 1개를 사용한 문제를 해결하기 위해 좌표축 중심의 3D rotation x,y,z를 차례로 사용하여 모든 각도를 표현하는 방식을 Euler rotation이라고 하며 x, y, z를 rotation한 3가지 각도를 Euler Angle이라고 한다(세타1, 세타2, 세타3)

 

x, y ,z를 회전하는건 순서와 상관없지만 순서가달라지면 결과값도 달라진다.

 

행렬식은 반대 순서로 적용 : p' = z * y * x * p

각도 변환 행렬 왼쪽 부터 z, y, x opengl에서 계산할 때는 반대로 계산되기 때문

 

Euler angle의 결과값은 unique하지 않는다 이뜻은 input값이 달라도 결과값이 같을 수 있다는 것 이다. 예를 들어 (90º, 90º, 0)의 값을 넣고 회전시킨 값과 (0, 90º, 90º)의 결과 값이 같다는 걸 알수있다. 이런 문제를 해결하기 위해.

구현

GLfloat rotX[16];
GLfloat rotY[16];
GLfloat rotZ[16];
GLfloat reg[16]; // reg = rotY * rotX
GLfloat mat[16]; // mat = regZ * reg = rotZ * (rotY * rotX)

void matMult(GLfloat c[16], const GLfloat a[16], const GLfloat b[16]) {
	c[0] = a[0] * b[0] + a[4] * b[1] + a[8] * b[2] + a[12] * b[3];
	c[1] = a[1] * b[0] + a[5] * b[1] + a[9] * b[2] + a[13] * b[3];
	c[2] = a[2] * b[0] + a[6] * b[1] + a[10] * b[2] + a[14] * b[3];
	c[3] = a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + a[15] * b[3];
	//
	c[4] = a[0] * b[4] + a[4] * b[5] + a[8] * b[6] + a[12] * b[7];
	c[5] = a[1] * b[4] + a[5] * b[5] + a[9] * b[6] + a[13] * b[7];
	c[6] = a[2] * b[4] + a[6] * b[5] + a[10] * b[6] + a[14] * b[7];
	c[7] = a[3] * b[4] + a[7] * b[5] + a[11] * b[6] + a[15] * b[7];
	//
	c[8] = a[0] * b[8] + a[4] * b[9] + a[8] * b[10] + a[12] * b[11];
	c[9] = a[1] * b[8] + a[5] * b[9] + a[9] * b[10] + a[13] * b[11];
	c[10] = a[2] * b[8] + a[6] * b[9] + a[10] * b[10] + a[14] * b[11];
	c[11] = a[3] * b[8] + a[7] * b[9] + a[11] * b[10] + a[15] * b[11];
	//
	c[12] = a[0] * b[12] + a[4] * b[13] + a[8] * b[14] + a[12] * b[15];
	c[13] = a[1] * b[12] + a[5] * b[13] + a[9] * b[14] + a[13] * b[15];
	c[14] = a[2] * b[12] + a[6] * b[13] + a[10] * b[14] + a[14] * b[15];
	c[15] = a[3] * b[12] + a[7] * b[13] + a[11] * b[14] + a[15] * b[15];
}

system_clock::time_point lastTime = system_clock::now();

void updateFunc(void) {
	system_clock::time_point curTime = system_clock::now();
	milliseconds elapsedTimeMSEC = duration_cast<milliseconds>(curTime - lastTime); // in millisecond
	GLfloat theta = (elapsedTimeMSEC.count() / 1000.0F) * (float)M_PI; // in <math.h>, M_PI = pi
	angle += theta * dir;
	lastTime = curTime;
	// rotX : rotation about X axis
	rotX[0] = 1.0F; rotX[4] = 0.0F; rotX[8] = 0.0F; rotX[12] = 0.0F;
	rotX[1] = 0.0F; rotX[5] = cosf(angle.x); rotX[9] = -sinf(angle.x); rotX[13] = 0.0F;
	rotX[2] = 0.0F; rotX[6] = sinf(angle.x); rotX[10] = cosf(angle.x); rotX[14] = 0.0F;
	rotX[3] = 0.0F; rotX[7] = 0.0F; rotX[11] = 0.0F; rotX[15] = 1.0F;
	// rotY : rotation about Y axis
	rotY[0] = cosf(angle.y); rotY[4] = 0.0; rotY[8] = sinf(angle.y); rotY[12] = 0.0F;
	rotY[1] = 0.0F; rotY[5] = 1.0F; rotY[9] = 0.0F; rotY[13] = 0.0F;
	rotY[2] = -sinf(angle.y); rotY[6] = 0.0; rotY[10] = cosf(angle.y); rotY[14] = 0.0F;
	rotY[3] = 0.0F; rotY[7] = 0.0F; rotY[11] = 0.0F; rotY[15] = 1.0F;
	// rotZ : rotation about Z axis
	rotZ[0] = cosf(angle.z); rotZ[4] = -sinf(angle.z); rotZ[8] = 0.0F; rotZ[12] = 0.0F;
	rotZ[1] = sinf(angle.z); rotZ[5] = cosf(angle.z); rotZ[9] = 0.0F; rotZ[13] = 0.0F;
	rotZ[2] = 0.0F; rotZ[6] = 0.0F; rotZ[10] = 1.0F; rotZ[14] = 0.0F;
	rotZ[3] = 0.0F; rotZ[7] = 0.0F; rotZ[11] = 0.0F; rotZ[15] = 1.0F;
	// combine them into a single matrix
	matMult(reg, rotY, rotX);
	matMult(mat, rotZ, reg);
}

 

 

728x90