2006년 4월 16일 일요일

[CG]오차누적 - rotation transformation

수학적으로는 360도 회전하는 것이나 5도씩 72번 회전하는 것이 같다.
하지만 numerical하게는 변수에 값을 누적하기 시작하면 오차가 매우 커진다.

5도씩 100번 회전하면 물체의 크기가 30%나 적어진다.
5도 회전할 때마다 오차가 0.3%있는 것이다.
또한 도형이 shearing되기 시작한다.
(shearing + scale down)

시뮬레이션)
#include "math.h"
#include <iostream>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
long double x0 = 100;
long double y0 = 100;
long double x = 0;
long double y = 0;
float theta = 5.0 * 3.141592 / 180.0;

for (int i = 0; i < 100; i++)
{
x0 = x + (x0 - x) * cos(theta) - (y0 - y) * sin(theta);
y0 = y + (y0 - y) * cos(theta) + (x0 - x) * sin(theta);

cout << "i : (x0, y0), d : " << i << ", " << x0 << ", " << y0 << ", " << sqrt(pow(x0, 2) + pow(y0, 2)) << endl;
}

cout << "theta : " << theta << endl;
cout << "cos(theta) : " << cos(theta) << endl;
cout << "sin(theta) : " << sin(theta) << endl;
cout << "sqrt(pow(cos(0.1), 2) + pow(sin(0.1), 2)) : " << sqrt(pow(cos(0.1), 2) + pow(sin(0.1), 2)) << endl;

return 0;
}

해결책 1)
. 원본과 transformation을 항상 저장한다.
- 복잡한 transformation을 했을 경우 모두 저장하기 힘들고 performance가 떨어진다.

가짜 해결책 2)
Rotation 각도를 크게 해서 한, 두 번만 한다.

가짜 해결책 3)
Rotation 각도를 작게 해서 잠시만 보여준다.

가짜 해결책 4)
Rotation과 함께 scale을 시도한다.

실패한 해결책 5)
변수를 double, long double 등으로 바꾼다.
(truncation error를 줄이려는 생각이었으나 실패.)

진짜 해결책)
사실은 vector, matrix 곱셈을 잘못한 것이다.
x0의 값이 바뀐 후 값이 y0의 계산에 이용되고 있다.
따라서 임시변수 2개를 만들어서 x0, y0값을 따로 저장해두고 계산이 끝난 후 복사해야 한다.
(혹은 먼저 값을 복사해두고 계산해야 한다.)

댓글 없음:

댓글 쓰기