반응형



베지어 곡선

 

http://kin.naver.com/open100/detail.nhn?d1id=11&dirId=1113&docId=234193&qb=67Kg7KeA7Ja0IOqzoeyEoA==&enc=utf8&section=kin&rank=2&search_sort=0&spq=0&pid=gkyGCz331yVssc%2B5Lg8ssv--496937&sid=Tby37L6VvE0AACnTDDU

 

1. 수학적으로 N차 베지어 곡선은 다음과 같이 정의된다.

 

t가 0에서 1까지일때, 벡터 B_N이 그리는 궤적이 베지어 곡선이다.

벡터 p_k 는 조정점(control point)이고, N C k는 조합, N!/k!/(N-k)!을 의미한다.

 

어도브사에서 정한 ps 규약 중의 하나인 3차 베지어 곡선의 경우, 다음과 같이 요약할 수 있다.

 

(편의상 B, p의 벡터 기호는 생략한 것임)

 

2. 베지어 곡선의 성질은 여러가지가 있는데, 대표적으로

 

1) 시작점:t=0일 때, p_0점

2) 끝점:t=1일 때, p_N점

3) 시작점에서 접선은 p_0, p_1의 변위와 평행

4) 끝점에서 접선은 p_N-1, p_N의 변위와 평행

5) 언제나 조정점들의 convex hull안에 들어간다.

6) 조정점들 중 여러 개를 같은 좌표로 설정하면, 그 부분에서 convex hull에 점점 가까워진다. 즉, 곡률이 더 심해진다.

 

3. 역사

수학적으로 예전에 알려진 곡선이지만, 피에르 베지어(Pierre Bézier)가 1960년대에 자동차 모델, 르노를 CAD로 디자인 할 때, 사용했는데, 그의 이름이 붙었다.

 

 


 

http://seirion.com/130

 

3차 베지어 커브 일반식 유도

혹자는 왜 하필이면 3차 베지어 커브이냐 ... 라고 궁금증을 가질 수도 있지만,
대부분의 폰트는 3차 이하의 베지어 커브들로 구성된다는 점,
3차 베지어 커브이면 원에 가까이 근사할 수 있다는 점 등이 그 이유일 것이다.
실제로 베지어 커브로는 완벽한 원을 만들 수 없다.

따지고 보면 1차 베지어 커브(사실은 직선)로도 원하는 모양을 만들 수 있긴 하다.
물론 이건 매우 비효율적이다. 어차피 픽셀로 표현되는 컴퓨터 나라에서 곡선이란 게 무의미 할 수도 있다.
아무튼 그건 그거고 ...

3차 베지어 커브의 일반식을 유도하기 위한 조건은 다음과 같다.
1. 컨트롤 포인트는 4개이다. (P0P1P2 and P3)
2. 곡선은 첫번째 포인트와 마지막 포인트를 지난다.
3. 곡선의 첫 지점에서의 기울기는 P0 과 P을 이은 직선의 기울기의 3배이다.
4. 곡선의 마지막 지점에서의 기울기는 P2 와 P을 이은 직선의 기울기의 3배이다.

 


*원본에 내용을 덧붙인다,

4. 곡선의 마지막 지점에서의 기울기는 P2  P3 을 이은 직선의 기울기의 3배이다.

 3배가 되는 이유는

 에서 N=3, 일경우 이것은 3차 방정식형태로 전계되며 (1-t)^3 에 관한 계수들은

파스칼의 삼각형( 이항계수: n개 중에서 k개를 뽑을 수 있는 개수) 에 의하여 3이 곱해진다

2차일때 1,2,1 이 곱해지듯 전개되는 두번째와 세번째 항에 3에 곱해짐으로

이항계수는 다음과 같다.

 {n \choose k} = \frac{n!}{k!(n-k)!} \quad \mbox{if } n\geq k\geq 0  \qquad \mbox{(1)}

 {n \choose k} = 0 \quad \mbox{if } k<0 \mbox{ or } k>n


{n \choose k}    =nCkC(n,k)

ex)  {7 \choose 3} = \frac{7\cdot 6 \cdot 5}{3\cdot 2\cdot 1} = 35

 

 

파스칼의 삼각형은 수학에서 이항계수를 삼각형 모양의 기하학적 형태로 배열한 것이다. 이것은 블레즈 파스칼에 의해 이름 붙여졌으나 이미 수세기 전에 다른 사람들에게서 연구된 것이다.


Pascal triangle.svg

 

 

파스칼 삼각형의 응용

파스칼의 삼각형은 이항 전개에서 계수들의 값을 계산하는 데에 사용된다. 예를 들어

(x + 1)^2 = 1 \cdot x^2 + 2 \cdot x + 1

라는 식에서, 각 계수의 값인 1, 2, 1은 파스칼의 삼각형의 3번째 줄에 대응된다.

일반적으로,

(x + y)^n = a_0 x^n + a_1 x^{n-1} y^1 + a_2 x^{n-2} y^2 + \cdots + a_n y^n

와 같은 전개식에서, a_i = {n \choose i} 가 성립한다. 즉, ai는 파스칼의 삼각형의 (n+1) 번째

줄의 (i+1) 번째 값과 대응된다.


 

 

 

 

위 사실에 근거하여,
3차 식을 다음과 같이 u에 대한 3차 식으로 두고,

사용자 삽입 이미지






이놈을 매트릭스로 표현하면,

사용자 삽입 이미지







즉, 

사용자 삽입 이미지






그리고 미분한 식은 다음과 같다.

사용자 삽입 이미지






위 조건 1,2,3,4 를 적용하여 보면,

[식 1.1]

사용자 삽입 이미지



 

사용자 삽입 이미지



 

사용자 삽입 이미지



 

사용자 삽입 이미지






 

사용자 삽입 이미지

이 식에서 

사용자 삽입 이미지

로 치환하면, 다음과 같다.

사용자 삽입 이미지




조건 1,2,3,4 로부터 유도된 식으로부터 

사용자 삽입 이미지


 

사용자 삽입 이미지

를 구할 수 있고, 값은 다음과 같다.

사용자 삽입 이미지
사용자 삽입 이미지






 

*원본에 덧붙인다.
결론적으로 ([계수행렬][t])^T * [P] 로써 베지어 곡선이 표현되며,

계수 행렬을 구하면 핵심적인 것이 정리된다,

이 계수 행렬은 [식 1.1] 들의 P 들로 풀이되는Pn 들을 P0~3 까지 서로 연립하여 풀면 Pn 들에 붙는

 Mb 같은 계수행렬 형태로 정리할 수 있게 된다

한가지 힌트는 Mb 행렬중 가장 오른쪽 열이 P0에 대하여 풀어 나온 나온 계수가 된다.

마찬가지로 3 열이 P0 의 계수는 -3, P1 의 계수는 3 이다.


 

사용자 삽입 이미지

라고 치환하면,

사용자 삽입 이미지

이렇게 되고, 

고로, 

사용자 삽입 이미지

다음을 통해서 b(u) 를 구할 수 있다.


*원본에 덧붙인다.

결과적으로 계수행렬  Mb^T 와 U 를 곱하여  (1-t)^3 즉 3차에 관한 항들로 전계가 되고

이것이 P 와 곱해짐으로써 베지어 곡선을 만들 수 있게 된다.

Tip : 3차식=3차곡선= N=4= N-1 곡선,  점이 4개면 3차 곡선 형태가 된다





이제 다 끝났다.

사용자 삽입 이미지



이었으므로, 다음과 같은 일반항이 도출된다.

사용자 삽입 이미지








references : 
http://en.wikipedia.org/wiki/B%C3%A9zier_curve
Interactive Computer Graphics 2nd Edition (Addison Wesley) p434-436


 

 

 

Bézier curves


Written by Paul Bourke
Original: April 1989, Updated: December 1996

 

이 문서는 베지어 곡선이라는 특수한 곡선에 대한 수학적인 설명을 담고 있습니다. 이 곡선의 이름은, 1970년대 Renault car를 디자인하는 과정에서 이 곡선을 사용했던 Pierre Bézier라는 프랑스 엔지니어의 이름을 따서 만들어졌습니다. 그때부터 이 곡선은 식자 산업(typesetting industry)에서 절대적인 우위를 점하게 되었고, 특히 Adobe Postscript, 폰트 제품 등에서 널리 사용되었습니다.

3차원 공간에 있는 N+1개의 조절점(control point) pk (k=0,1,...,N)를 생각해봅시다. 베지어 parametric 곡선 공식은 다음과 같습니다.

B(u)는 서로 다른 위치에 있는(discrete) N개의 조절점에 의해 얻어지는 곡선을 구하기 위한 연속함수입니다. u=0이면 첫번째 조절점(k=0)에, u=1이면 마지막 조절점(k=N)에 도달합니다. 아래는 N=4, 즉 조절점이 4개인 경우의 곡선 모습입니다.
역자 주 : 첫번째 조절점이 시작점, 마지막 조절점이 끝점이라고 생각하시면 쉽겠죠? ^_^ 
그리고, N개의 조절점이 아니라 N+1의 조절점이라고 해야 하는 듯. 
나중에 나오지만, 조절점의 위치가 모두 각각 다를 필요는 없습니다.

주의점:

  • 이 베지어 곡선은, 조절점 중 처음과 끝 점을 빼고는 보통 어느 조절점과도 만나지 않습니다. 공식을 사용하면 B(0) = P0 이고 B(1) = PN 이 되겠지요.

  • 곡선은, 항상 조절점으로 이루어진 다각형 안에 들어가게 됩니다. 곡선이 조절점들 사이에서 크게 벗어나거나 하는 일은 없습니다.

  • 조절점이 P0 하나뿐이라면, 즉 N=0 이라면 모든 u에 대해 B(u) = P0 입니다. (역자 주 : u는 0이상 1 이하의 실수)

  • 조절점이 P0 , P1 두개뿐이라면, 즉 N=1이라면 이 공식은 두 점 사이를 잇는 선분을 만들어냅니다.


  • 라는 부분은 blending 함수라고 하는데, 이 부분에서 조절점들을 blend해서 곡선을 생성하기 때문입니다.

  • blending 함수는 조절점의 갯수보다 차수가 하나 낮은 다항함수입니다. 예를 들어, 3개의 조절점이 있다면 베지어 곡선은 포물선을 그리고, 4개의 조절점으로는 3차곡선을 얻게 됩니다.

  • 첫번째 조절점의 위치와 마지막 조절점의 위치가 같을 경우 폐곡선이 생깁니다. 이때 처음의 두 조절점 사이의 접선(tangent)과 끝의 두 조절점의 접선이 같을 경우, first order continuity가 가능합니다. (역자 주 : P0 - P1 간의 기울기와 PN-1 - PN 간의 기울기가 같을 경우..라고 보시면 되겠습니다. first order continuity는, 두 곡선의 (1계)도함수가 같은, 즉 접선의 기울기가 서로 같은 상태를 의미합니다.) 

  • 비슷한 위치에 여러 조절점이 있을 경우, 그쪽으로 베지어 곡선을 "당기는" 정도가 증가합니다.

  • 조절점의 갯수가 많아지면, 좀더 높은 차수의 식과, 많은 횟수의 팩토리얼 값을 계산해야 합니다. 그래서 보통 긴 곡선을 만들 때는, 그 곡선을 다시 여러 곡선으로 작게 쪼개는 방법을 씁니다. 이렇게 하면, 전체적인 모습에 변화를 주지 않고도 곡선의 부분적인 형태를 쉽게 바꿀 수 있는 효과도 얻게 됩니다. 물론 곡선이 첫번째 조절점에서 시작해서 마지막 조절점에서 끝나기 때문에, (나눠진) 곡선 조각들을 이어붙이기는 쉽습니다. 또한 베지어 곡선에서는 마지막 점에서의 접선이 마지막 두 조절점을 이은 선과 같기 때문에, (나누어진 곡선들의) 첫번째 조절점의 기울기도 맞출 수 있습니다. 
    Second order continuity는 보통 불가능합니다. (역자 주 : Second order continuity는, 이계도함수의 값이 같을 때의 상태입니다. 즉, 곡선의 변화율이 같다는 뜻입니다.) 

  • 조절점이 2개인 특수한 경우(직선)을 제외하고는, 한 베지어 곡선에 평행한 다른 베지어 곡선을 유도(derive)해내는 것은 불가능한 것으로 알려져 있습니다.

  • 베지어 곡선으로 원을 완벽하게 표현할 수는 없습니다.

  • coincident parallel curves나 직선인 베지어 곡선의 경우를 제외하고는, 한 베지어 곡선에 평행한 베지어 곡선을 만드는 것은 불가능합니다.

  • 조절점이 3개일 경우는 공식이 다음과 같이 정리됩니다 : 

    B(u) = P0 * ( 1 - u ) 2 + P1 * 2 * u ( 1 - u ) + P2 u2

  • 조절점이 4개일 경우는 공식이 다음과 같이 정리됩니다 : 

    B(u) = P0 * ( 1 - u )3 + P1 * 3 * u * ( 1 - u )2 + P2 * 3 * u2 * ( 1 - u ) + P3 * u3

베지어 곡선은 굉장히 안정적인 형태를 만들고, 계산하기도 쉽기 때문에 널리 쓰이고 있습니다. 이런 형태의 베지어 곡선 말고도 조금 다른 모습을 만들어 내는, 또다른 베지어 곡선 공식이 있습니다. 대체로 모습은 비슷하지만, 곡선이 각 조절점을 모두 통과한다는 점이 다릅니다. Spline 곡선을 참조하세요.


예제

분홍색 선이 조절점들을 이은 선이고, 회색 선이 베지어 곡선입니다.

베지어 곡선을 표현하는 다항식의 차수는 조절점의 갯수보다 하나 낮기 때문에, 조절점이 세 개인 이 경우에는 2차곡선이 만들어집니다. 두 곡선의 조절점의 모양이 대칭을 이루면, 곡선 또한 항상 대칭입니다.

곡선은 항상 끝점을 지나며, 처음의 두 점을 이은 선에 접하고 끝의 두 점을 이은 선에도 접합니다. 이 성질로 인해, first order continuity를 유지하면서 여러 베지어 곡선을 이을 수 있게 됩니다.

곡선은 항상 조절점들로 이루어진 볼록다각형(convex hull) 안에 있게 됩니다. 그래서 곡선은 "안정적이고", 엉뚱하게 튀어나가는 일이 없습니다.

시작점과 끝점을 갖게 했을때 곡선이 생깁니다. 시작점과 끝점의 접선(tangents)이 일치할 경우 곡선은 first order continuity를 유지하면서 닫히게 됩니다. 또, 조절점을 한 곳에 여러번 지정하게 되면, 그 쪽으로 곡선이 쏠리게 됩니다.


C source

typedef struct XYZ

{

    double x;

    double y;

    double z;

}XYZ;

/*

조절점이 3개인 베지어 곡선 예제

mu는 0(곡선의 시작)부터 1(곡선의 끝) 사이의 값을 가질 수 있습니다.

*/

XYZ Bezier3(XYZ p1,XYZ p2,XYZ p3,double mu)

{

    double mum1,mum12,mu2;

    XYZ p;

    mu2 = mu * mu;

    mum1 = 1 - mu;

    mum12 = mum1 * mum1;

    p.x = p1.x * mum12 + 2 * p2.x * mum1 * mu + p3.x * mu2;

    p.y = p1.y * mum12 + 2 * p2.y * mum1 * mu + p3.y * mu2;

    p.z = p1.z * mum12 + 2 * p2.z * mum1 * mu + p3.z * mu2;

    return(p);

}

/*

조절점이 4개인 베지어 곡선 예제

mu는 0(곡선의 시작)부터 1(곡선의 끝) 사이의 값을 가질 수 있습니다.

*/

XYZ Bezier4(XYZ p1,XYZ p2,XYZ p3,XYZ p4,double mu)

{

    double mum1,mum13,mu3;

    XYZ p;

    mum1 = 1 - mu;

    mum13 = mum1 * mum1 * mum1;

    mu3 = mu * mu * mu;

    p.x = mum13*p1.x + 3*mu*mum1*mum1*p2.x + 3*mu*mu*mum1*p3.x + mu3*p4.x;

    p.y = mum13*p1.y + 3*mu*mum1*mum1*p2.y + 3*mu*mu*mum1*p3.y + mu3*p4.y;

    p.z = mum13*p1.z + 3*mu*mum1*mum1*p2.z + 3*mu*mu*mum1*p3.z + mu3*p4.z;

    return(p);

}

/*

일반적인 베지어 곡선 예제

조절점의 갯수는 n+1개가 됩니다.

0 <= mu < 1 *중요!* 마지막 조절점은 계산하지 않습니다.

*/

XYZ Bezier(XYZ *p,int n,double mu)

{

    int k,kn,nn,nkn;

    double blend,muk,munk;

    XYZ b = {0.0,0.0,0.0};

    muk = 1;

    munk = pow(1-mu,(double)n);

    for (k=0;k<=n;k++)

    {

        nn = n;

        kn = k;

        nkn = n - k;

        blend = muk * munk;

        muk *= mu;

        munk /= (1-mu);

        while (nn >= 1) {

            blend *= nn;

            nn--;

            if (kn > 1) {

                blend /= (double)kn;

            kn--;

            }

            if (nkn > 1) {

                blend /= (double)nkn;

                nkn--;

            }

        }

        b.x += p[k].x * blend;

        b.y += p[k].y * blend;

        b.z += p[k].z * blend;

    }

    return(b);

}


  • FAQ
    > 1. SpLines 코드 - 코드를 이해하기 위한, 간단한 테스트
    > 프로그램이 있습니다. 정말 괜찮게 구현해놓았네요. 질문이 하나 있습니다:
    > 어떻게 동적인 결과(dynamic resolution)를 얻을 수 있을까요?
    > 2. Bezier 코드에서 - 어떻게 이 코드를 쓰는지에 대한 예제가 없네요.. 
    > 세 함수 모두 곡선을 만드는 대신, 단지 점 하나만을 리턴하네요. 
    > 게다가 double형 인자인 mu( 0 < mu <1) 는 뭐죠?
    
    함수를 호출할 때는, 0부터 1 사이의 범위에서 mu값을 바꾸면서 함수들을
    호출하세요. mu의 값을 증가시킴에 따라, 곡선 위에서 (곡선 방향으로) 이동하는 
    점들을 얻게 됩니다. 그러므로 mu에 0.5를 넣는다면, 전체 곡선(길이)의 딱 중간에
    있는 점을 함수가 리턴하겠지요. 하나 예를 들어볼게요.
    
       #define NSTEPS 100
       int ncontrolpoints=0;
       XYZ p,*controlpoints;
       
       ... 이곳에 조절점 배열과, 데이터들을 만들고 읽는 루틴이 들어가겠지요.
    
       for (i=0;i%lt;NSTEPS;i++) {
          p = Bezier(controlpoints,ncontrolpoints,i/(double)N));
    
          .... 이제 p 변수를 이용하세요. 예를 들어, 화면에 찍는다거나 등등.
    
       }
    
    spline 코드가 호출되는 방식도, 이와 같습니다.

출처 : http://eunchul.com/Algorithms/BezierCurves/BezierCurves.htm

 

 


 

베지어 곡선뒤에 숨겨진 수학원리 #

좋습니다. 가장먼저 짚고 넘어가야할 것은 번스타인(Bernstein) 정리 공식"들"입니다. 자, 이제 공식하나를 보여줄 예정인데, 초조해할 필요는 없습니다. 단지 이 공식을 보면 정말로 간단하다는 것을 금방 알 수 있을거니까요.
1 = t + (1 - t)
t는 어떠한 상수라도 될 수 있으며 이 공식은 모든 경우의 수에 대하여 언제나 참입니다. 그러나 이 아티클에서는 t가 0과 1사이일 경우만 고려하도록 하겠습니다.

이제 번스타인 정리 공식을 알았습니다. 그러나 이전에 제가 공식"들"이라고 복수형으로 말했던 것을 기억하세요! 자, 잘 동작하는 곡선을 얻기위한 다음 단계는 우리의 자그마한 데모에서 어떤 종류의 곡선을 사용할 것인지 선택하는 것입니다. 초심자를 위해서, 여기서는 가장 쉬운 형태인 2차 베지어 곡선을 사용하도록 하겠습니다.

자, 그리하여 2차 베지어 곡선을 택하게 되었습니다. 이제 전지전능한 정리 공식으로부터 몇가지 공식들을 끌어내야할 필요가 있습니다. 2차 베지어 곡선을 위해서는, 우선 번스타인 정리 공식의 양변을 제곱합니다. 3차 베지어 곡선을 얻으려면, 양변을 3제곱합니다. 그 이상의 차수에도 마찬가지입니다. 양변을 제곱하면 다음과 같은 결과가 나올겁니다.
1^2 = (t + (1 - t))^2
1 = t^2 + 2*t*(1-t) + (1-t)*(1-t)

You'll notice that a lot of this I didn't simplify, that's because it's easier to understand and code if you leave it this way.

Ok, now we have our 3 functions, which we derived from our basis. But where you ask. Well, right in front of you! Our functions are each of the terms to the right side of the equation. We'll call our functions Bx(t). It should be noted that the code is in bold.

#define	B1(t)		(t*t)
#define	B2(t)		(2*t*(1-t))
#define	B3(t)		((1-t)*(1-t))
2차 베지어 곡선인 경우에는 위 3개의 공식만 알고 있으면 됩니다.

참고로 3차(cubic) 곡선인 경우는 아래와 같습니다.
B1(t) = t * t * t
B2(t) = 3 * t * t * (1 - t)
B3(t) = 3 * t * (1 - t) * (1 - t)
B4(t) = (1 - t) * (1 - t) * (1 - t)

4차(quartic) 곡선인 경우입니다.
B1(t) = t * t * t * t
B2(t) = 4 * t * t * t * (1 - t)
B3(t) = 6 * t * t * (1 - t) * (1 - t)
B4(t) = 4 * t * (1 - x) * (1 - t) * (1 - t)
B5(t) = (1 - t) * (1 - t) * (1 - t) * (1 - t)

이렇게 분해해놓은 공식만있으면 수학공식정리를 하지 않아도 됩니다! 이제 베지어 곡선뒤에 숨은 간단한 수학을 건너뛰었습니다. 이들을 가지고 프로그램을 논하도록 하죠!


베지어 곡선

번스타인(Bernstein) 정리 공식들 

1 = t + ( 1 - t ) 
▒ 0 ≤ t ≤ 1 

2차 베지어 곡선이라면 양변에 제곱 
3차 베지어 곡선이라면 양변에 세제곱 
... 

2차 베지어 곡선 

1^2 = t^2 + 2 * t * ( 1 - t) + ( 1 - t ) * ( 1 - t )

3차(cubic) 베지어 곡선 

1^3 = t * t * t + 3 * t * t * (1 - t) + 3 * t * (1 - t) * (1 - t) + (1 - t) * (1 - t) * (1 - t)

4차(quartic) 베지어 곡선 

1^4 = t * t * t * t + 4 * t * t * t * (1 - t) + 6 * t * t * (1 - t) * (1 - t) + 4 * t * (1 - x) * (1 - t) * (1 - t) + (1 - t) * (1 - t) * (1 - t) * (1 - t)

제어점은 각 식에 대해서 곱의 합으로 분리했을때 곱의 갯수이고 
각 제어점들을 각 곱에 곱해줌으로써 값들은 베지어 곡선을 이루게 된다. 

2차 베지어 곡선의 예제 코드 

public double B1(double t) 

    return t*t; 

public double B2(double t) 

    return 2 * t * (1 - t); 

public double B3(double t) 

    return (1 - t) * (1 - t); 

... 

    double x, y; 
    double detailBias = 1.0 / 50.0; 
    double count = 0; 

    do 

      x = pt0].X * B1(count) + pt[1?.X * B2(count) + pt[2].X * B3(count); 
      y = pt0].Y * B1(count) + pt[1?.Y * B2(count) + pt[2].Y * B3(count); 

      image.SetPixel?((int)x, (int)y, Color.Black); 

      count += detailBias; 

    } while (count <= 1); 

출처 : http://www.synch3d.com/wiki/moin/moin.cgi/_ba_a3_c1_f6_be_ee_20_b0_ee_bc_b1

반응형
반응형

블로그 이미지

3DMP engines

3D그래픽스 물리 수학, 프로그래밍 GPU Shader 게임엔진 알고리즘 디자인패턴 matlab etc..


Herimit Curve

 





에르미트 곡선을 3차 다항식으로부터 도출 하여, 곡선 임의의 한 점에서의 근사적 좌표 프레임을 얻어오는

과정 까지를 진행하겠습니다

 

먼저 기호들을 살펴보자 아래의 그림과 같다

P0, p1 은 각각 점이고 Q0은 곡선을 뜻한다 이때 Q0 ~ Qn 까지 생성 될 수 있다( P0~Pn 에 의하여.. )

P'0 과  P'1 은 각 점에서의 접선벡터(속도벡터)를 뜻한다

일반적으로

 

    Q(t) = ( x(t),y(t),z(t) )

 

로 표현 할 수 있다

 또한 이것의 1차 미분은

    Q'(t) = ( x'(t),y'(t),z'(t) )

 

이다, 즉 각 성분을 미분한다 이때의 인자는 t 이므로 t 에 대해서 미분하지만 아래설명에서 t 와 u 를 혼용해서

쓰는데, 개의치 말고 t,u 모두 그냥 실수 범위라고 생각 하면 되겠다

 

* 일반적인 3차방정식으로부터 에르미트 곡선 공식의 유도식은 다음가 같다

 

 

 

원래의 Q 와 Q' 의 식으로 0,1 인자를 이용한 고정된 값을 도출 하는 것이 포인트이다

도출된 값들을 다시 원래의 식에 대입하여 a,b 에 대해 정리 한 후.... 

 

 

* 아래 내용은 어떻게 저 a,b 가 나왔는지에 대한 풀이이다...

 

 

 

구한 상수 값들 ( a,b,c,D ) 을 원래의 3차 다항식에 대입하여 푼다

 

 

 

 

 

이렇게 푼 것을 행렬의 형태로 맞추기 위해 식을 각 포인트( 2개의 점과 2개의 접선) 를 기준으로 식을 다시

정리한다

 

 

 

 

 

 

 

여기까지다 에르미트 곡선의 도출 과정이다

 

 

 

이제는 근사적 좌표계를 어떻게 구할 껏인가에 대한 과정이 되겠다

 

먼저 r(t) 곡선에 대해 생각하면

 

r(t)를 한번 미분하면 속도벡터 v(t) 이고 v(t) 를 한번더 미분하면 a(t) 가속도 벡터를 구할 수 있게 된다

(단, 단위원의 경우)

 

 

 

 

위의 식을 따라가보면 알 수 있는 것은 속도 벡터가 일정한 상수값으로 나올때 가속도 벡터와 속도 벡터의

 

내적은 0 즉 수직이라는 말이 된다

(여기서 유추해 볼 수 있는 것은 이 둘을 외적하면 up 벡터를 구할 수있다는 것)

 

예를 들어보자 PI/4 일경우를 기준으로 어떤 벡터가 나오는지를 확인해보자

 

 

 

그림에서 잘 설명 되어 있으니 , 별 다른 설명은 하지않겠다 , 다만 sin 미분하면 cos , cos 미분하면 - sin 이 된다

 

 

 

이부분이 실질적인 근사적인 좌표프레임을 구하는 부분이다

 

위의 과정을 이해했다면 마지막 과정을 대강 어느정도 이해할 수 있을 것이다

 

근사적이기 때문에 완전한 가속도 벡터가 될 수 없다

 

가속도벡터를 제대로 구하고 싶다면 벡터 미분을 참고하여야 한다

 

근사적으로 구하면 속도에서 좀 이득을 볼 수있을 것이다

 

 

Copyright : 송 정 헌

 


반응형

'수학 (Mathematics) > 3D수학' 카테고리의 다른 글

NDC 공간이란  (0) 2012.11.02
베지어 곡선(Bezier Curve) 유도와 설명  (1) 2012.11.02
두 벡터 사이의 각  (0) 2012.11.02
벡터 미적분, 접선과 가속도 - 공간 곡선  (0) 2012.11.02
두직선의 교점  (0) 2012.11.02
반응형

http://egohim.blog.me/70012169260



vector의 cross product를 사용하면 될 것 같습니다. 

먼저 두 벡터 사이의 각도는 사실 0~180밖에 나올수 없지만, 0~360가 나오도록 한다면 기준이 있어야할 것입니다. 

기준1. vector a(기준)에서 vector b까지의 
기준2. 시계 방향(기준) 혹은 시계 반대방향(기준) 

위의 기준은 cross product의 순서로 정할 수 있는 것 같네요. 
vector a에서 vector b로의 각도가 [0,180]이면 
vector a와 vector b이 cross product의 z값은 0과 같거나 크고 
vector a에서 vector b로의 각도가 (180,360) 또는 (-180,0) 이면 
vector a와 vector b이 cross product의 z값은 0보다 작을 것입니다. 



vector a=(ax, ay, az) 
vector b=(bx, by, bz) 
일 때 cross product(axb)의 z-component는 -ay bx + ax by이므로 

아래와 같이 하면 가능하겠네요. 


float cosAng1 = DotProduct(vector1, vector2); 

return (vector1.y*vector2.x + vector1.x*vector2.y > 0.0f) ? (float)(acos(cosAng1)) : - (float)(acos(cosAng1)); 


실제로 곱하기 계산도 한번 줄었네요.(dot product-> 곱하기 3번 ---> 곱하기 2번)

반응형
반응형

원문 http://pinkwink.kr/197

 


google_protectAndRun("ads_core.google_render_ad", google_handleError, google_render_ad); 
본 자료는 국립 창원대학교 메카트로닉스 공학부 학생을 대상으로 한 공업수학 수업 자료입니다. 본 자료는 수업의 교재인 공업수학I 개정3판 (고형준 외, 도서출판 텍스트북스) 의 내용을 재구성한 것으로 수업보조 자료 이외의 목적이 없음을 알립니다.




곡선운동

위치벡터를 한번 미분하면 속도벡터가 됩니다. 속도벡터를 한번 미분하면 가속도 벡터가 되구요.


속도의 크기를 의미하는 속력은 곡선의 길이를 구하듯이 계산하면 됩니다.


이때 만약 크기(속력)가 일정한 속도벡터가 있었다면, 위 과정처럼 내적을 이용한 풀이를 응용해보면 속도성분과 가속도성분이 서로 수직이라는 것을 알 수 있습니다.

 
즉, 위치벡터의 미분치인 속도벡터에 가속도벡터가 수직하면서, 본래의 위치벡터와 방향이 반대(구심가속도)라는 것을 알 수 있는것이지요.


물론, 위치벡터를 직접 두번 미분해보면 위에서처럼 알 수 있습니다. (단, 크기가 일정할때 말이지요..) 이를 구심가속도벡터라고 부릅니다.

 
위에서처럼 초기 높이가 s0이고 초기속도가 위와 같은 포물선운동을 하는 물체의 경우 , 만약 그 물체자체에는 추진력이 없고 외부의 힘이 없다면, 작용하는 힘은 중력만 존재할 것입니다.

 
이를 적분하면 당연히 속도가 될텐데요. 이때 초기치를 대입하고 다시 풀어보면


위와 같을 것이고 이때 얻은 속도를 다시 적분해서 위치벡터를 찾을 수 있습니다. 단, 위 식을 보실때 적분인자가 시간 t라는 걸 기억하셔야합니다.

 
그러면, 위에서처럼 x,,y쪽 성분을 구할 수 있는것이지요.


google_protectAndRun("ads_core.google_render_ad", google_handleError, google_render_ad); 




google_protectAndRun("ads_core.google_render_ad", google_handleError, google_render_ad); 


곡률과 가속도의 접선 가속도 벡터 및 법선 가속도 벡터

단위접선벡터를 이야기하는 것은 이미 지난번에 했었는데요.


이를 이용하면 곡률을 정의할 수 있습니다.

 
위 그림과 수식들을 보시면, 속도벡터와 가속도벡터들을 찾고 있고, 그 와중에 곡률을 정의하고 있구요.

 
만들어진 가속도벡터에서 위치벡터와 수직한방향의 접선가속도벡터와 법선가속도벡터성분을 정의내릴수있습니다.


즉, 접선가속도 성분은 속도와 가속도벡터의 내적으로, 법선가속도 성분은 외적으로 찾을 수 있다는 것을 알 수 있습니다.

 
접선과 법선으로 이루어진 평면의 수직한 방향의 벡터를 종법선벡터라고 하는데요 이는 당연히 외적으로 구할 수 있겠죠. 

반응형
반응형

http://www.gisdeveloper.co.kr/15


두 선의 교차점 구하기 
이 글은 두 선분의 교차점을 구하는 알고리즘이 작업에 필요해서 작성해둔 글이다. 참고로, 예전에 두선분의 교차점을 구하는 것 자체가 쉬울 것으로 생각하고 흔히 생각하는 기울기, y 절편을 이용하여 접근하려고 하였다. 이는 상당히 비효율적 방법이였고 조금 더 효율적인 방법으로 접근하였다. 

먼저 직선의 방정식으로써, 기울기와 절편으로 나타내지 말고, t 매개변수를 이용해 나타내면 다음과 같다.


P1과 P2는 직선의 시작점과 끝점을 나타내며, t의 범위는 0에서 1까지이다. (P1, P2에서 1, 2는 아래첨자로 생각하기 바란다)

선의 식을 알았으니, 이제 두선의 교점을 구해보는 것으로 응용해보자. 먼저 아래 그림을 보자.


Line1은 P1과 P2로 이루어져 있으며, Line2는 P3와 P4로 이루어져 있다. 두개의 라인을 식으로 표현해보면 다음과 같다.


이미 알겠지만, t와 s는 0에서 1부터의 값이며, 두선의 교점은 두선의 공통된 값이므로 P(t)와 P(s)는 같으므로 위의 2개의 식은 아래의 1개의 식으로 나타낼 수 있다.


다시 위의 식을 x, y로 분리해보면 아래와 같은 두개의 식들로 분리된다.


위의 식을 t와 s에 대해서 정리를 해보면 다음과 같다.


즉, 위의 t와 s는 두선이 서로 만날때의 값이므로, 최종적으로 두선의 교점은 다음과 같이 나타낼 수 있다.


위의 x, y가 우리가 구하고자하는 두 직선의 교점이다. 

마지막으로 t와 s에 대해 정리해 보도록 하자.

s와 t의 값이 0과 1 사이를 벗어나는 경우, 두 선은 교차하지 않는다고 판정해야 한다. 그리고 s와 t를 구하는 공식에서 분모가 0인 경우 두 선은 평행하다는 의미이므로 교점은 존재하지 않다. 분모와 분자 모두 0인 경우 두 선은 동일한 선이다.

아래의 코드는 위의 설명을 토대로 작성하였다.
bool GetIntersectPoint(const POINT& AP1, const POINT& AP2, 
                       const POINT& BP1, const POINT& BP2, POINT* IP) 
{
    double t;
    double s; 
    double under = (BP2.y-BP1.y)*(AP2.x-AP1.x)-(BP2.x-BP1.x)*(AP2.y-AP1.y);
    if(under==0) return false;

    double _t = (BP2.x-BP1.x)*(AP1.y-BP1.y) - (BP2.y-BP1.y)*(AP1.x-BP1.x);
    double _s = (AP2.x-AP1.x)*(AP1.y-BP1.y) - (AP2.y-AP1.y)*(AP1.x-BP1.x); 

    t = _t/under;
    s = _s/under; 

    if(t<0.0 || t>1.0 || s<0.0 || s>1.0) return false;
    if(_t==0 && _s==0) return false; 

    IP->x = AP1.x + t * (double)(AP2.x-AP1.x);
    IP->y = AP1.y + t * (double)(AP2.y-AP1.y);

    return true;
}

반응형

'수학 (Mathematics) > 3D수학' 카테고리의 다른 글

두 벡터 사이의 각  (0) 2012.11.02
벡터 미적분, 접선과 가속도 - 공간 곡선  (0) 2012.11.02
사각형 무게중심  (0) 2012.11.02
벡터의 내적과 외적  (0) 2012.11.02
한 축에 대한 기저 생성  (0) 2012.11.02
반응형


 

 http://blog.daum.net/anil-gifted/12850152


        

 

 

1. 한개의 사각형을 두개의 삼각형으로 나누어 세 중선을 통해 각 삼각형의 교점을 찾는다. 선분을 연결한다.

2. 1과 같이 다른 삼각형에도 교점을 표시한다.그리고 선분연결

3. 이게 바로 사각형의 무게  중심점이 된다.

 

 

각 꼭지점에서 마주보는 변의 중점으로 선을 그엇을 때 만나는 점입니다.
좌표(x1,y1)-(x2,y2)-(x3,y3)으로 표현된 경우에는 ((x1+x2+x3)/3. (y1+y2+y3)/3)으로 간단하게 계산할 수도 있습니다.

특징은 중학교 수학책을 참고하시고...

갑자기 궁금해져서 사각형의 무게중심을 구하는 방법을 찾아봤습니다.


오른쪽 그림과 같이 사각형을 두 개의 삼각형으로 쪼갭니다. 
(물론 서로 마주보는 두 꼭지점을 연결해야죠)

그러면 삼각형 둘로 나뉘는데, 
각각 삼각형의 무게중심을 구합니다.

왼쪽에 있는 삼각형을 A, 오른쪽을 B라고 하면 오른쪽과 같은 그림이 나오게 됩니다. GA는 A의 무게중심, GB는 B의 무게중심입니다.
다음은 GA-GB를 잇는 선분을 면적의 역수로 내분한 점을 찾으면 됩니다.

즉, A의 면적이 4B의 면적이 1이라고 하면 GA- GB를 1:4로 내분한 점이 사각형의 무게중심이 됩니다. (4:1이 아닙니다. 그렇게 되면 큰 삼각형 쪽으로 중심이 잔뜩 쏠릴 겁니다)

반응형
반응형

http://sayzy.blog.me/70080729572



벡터의 내적

 

내적의 특성

▣ 만약 두 벡터가 UㆍV = 0 라면, U와 V는 직각이다.
▣ 만약 두 벡터가 UㆍV > 0 라면, 두 벡터 간의 각도는 90도 보다 작다.
▣ 만약 두 벡터가 UㆍV < 0 라면, 두 벡터 간의 각도는 90도 보다 크다.
 

가장 중요한 것은 두 벡터의 내적은 그 결과가 항상 스칼라라는 것입니다. 이 때문에 스칼라 적이라고도 하며 점곱 이라고도 불립니다.

 

공간상에 임의의 두 벡터 A, B가 있을때..


 

두 벡터 사이의 각 구하기

우리는 위의 공식을 이용하여 두 벡터간의 각을 알아낼수가 있습니다.

위 식이 성립됩니다.

코싸인 세타 값을  M이라고 한다면..

  라는 라디안 값을 얻을 수 있습니다.

 

투영 벡터

우리는 여기서 어느 한 면에서의 점(G)와 원 사이의 거리를 알고 싶습니다.

그러려면 B_P의 투영 벡터인 X벡터의 스칼라 값을 구하여야 됩니다.

원점에서부터 오는 벡터 P가 있습니다.

그리고 마찬가지로 원점에서부터 오는 벡터 B가 있습니다.

B_P는 B벡터 - P벡터를 한 벡터입니다.

벡터 X의 길이를 s라 하면 s =  가 됩니다.

B_P벡터와 점(G)의 노말 벡터인 N과 내적을 하게 된다면...

내적 값은 N은 길이가 1이므로 이것도 역시  가 되게 됩니다.

결과를 보면 X의 스칼라 값 s와 N의 내적 값이 같다는걸 보게 됩니다.

따라서 길이가 1인 벡터 N과 B_P의 내적값은 X벡터의 스칼라 값인 길이가 됩니다.

여기에  x N벡터를 하면 크기와 방향을 가지는 투영 벡터인 X벡터가 나오게 됩니다.

 

투영벡터에 관한 정보는 아래 사이트에서 보고 글을 올린 것이니 이해가 안되시면 링크를 따라가셔서 보시면 됩니다.

http://wibler.egloos.com/3574643

 

벡터의 외적

 

공간상에 임의의 두 벡터 A, B가 있을때..

벡터의 내적이 두 벡터간의 사잇각을 나타내는 스칼라임에 비하여 벡터의 외적은 두 벡터에 모두 수직한

벡터를 결과 값으로 받는다는 점 때문에 크로스곱 또는 벡터적이라고도 합니다.

벡터 A와 B를 포함하는 평면에는 수직인 두개의 방향인 위쪽과 아랫쪽이 있습니다.

 

위 그림과 같이 오른손 법칙이나 왼손 법칙으로 두 벡터의 외적 벡터인 z 방향을 알아 낼수가 있습니다.

반응형
반응형

임의의 한 축 r

 

1. r의 최소 성분을 찾아 0 으로 만든다

 

2. 나머지 두개의 성분을 교체한 후 이들의 첫번째 성분을 음수로 만든다

 ( 0 이 아닌 두개 중 어떤 것이든 음수가 될 수 있다 )

 

3. 이렇게 나온 s 는 r 과 수직인 벡터가 나온다

 

4 t = r X s  로 cross 벡터를 구한다   X : 외적

반응형
반응형

** 간단하고 안전한 방향전환 행렬 구하기 **
copyrightⓒ Gamza

 


두개의 단위 방향벡터가 주어지고 한 벡터를 다른 벡터로 회전하는 행렬을 구하는 문제는 게임에 종종 등장하곤 합니다.
그런데 문제는 이것이 참 구하기도 까다롭고 수치적으로 불안정 해지는등...여러모로 사용하기가 까다롭다는 것입니다.
만약 입력이 달랑 단위 방향벡터 두개가 아니라 두개의 완전한 좌표축으로 주어진다면 문제는 정말로 간단해집니다.

이 글은 두개의 좌표축이 주어지고 한 좌표축을 다른 좌표축으로 변환하는 회전행렬을 보.여.드리 위한 글입니다.

문 제
세개의 단위벡터로 표현되는 좌표축이 두개 있다.
A : Vside, Vup, Vdir
B : Vside, Vup, Vdir
Vsideside vector(일반적으로 x축)
Vupup vector(일반적으로 y축)
Vdirdirection vector(일반적으로 z축)
좌표축 A를 B가되도록 회전시키는 회전 행렬을 구하라. 
정 답
구하고자 하는 회전 행렬을 M 이라 하면,
B.Vside=A.Vsidex M
B.Vup=A.Vupx M
B.Vdir=A.Vdirx M
행렬로 간단히 표현하면...
B = A x M
A,B: 각행이 Vside, Vup, Vdir인 3x3행렬
M을 구하면...
M = inverse(A) x B = transpos(A) x B

뭐...계산이랄것이 하나도 없죠....그래서 보여드린다고 했던겁니다...ㅡ.ㅡ;;;
너무 간단해서 허탈하기까지...
어쨌든 입력이 달랑 단위 방향벡터 두개인 경우....Up vector만 적당히 잡아줄수 있으면, 이 방법을 써서 간단하고도 안전하게 완벽한 회전 행렬을 구할수 있습니다.

반응형

'수학 (Mathematics) > 3D수학' 카테고리의 다른 글

벡터의 내적과 외적  (0) 2012.11.02
한 축에 대한 기저 생성  (0) 2012.11.02
점과 직선/반직선/선분과의 거리  (0) 2012.11.02
선형변환 (Linear Transformations)  (0) 2012.11.02
동차 좌표  (0) 2012.11.02
반응형

출처: http://www.gamza.net

 

copyrightⓒ playUs [2003년 04월 19일]

 

1. 정사영(투영) 벡터

 


 
 
벡터A를 벡터B에 투영한 벡터[?]는 다음과 같이 표현됩니다.
[?] = ( 벡터A를 벡터B에 투영한 길이 ) N 
(N : B방향 단위벡터)
벡터A를 벡터B에 투영한 길이는 내적을 이용하면 구할 수 있고....
( 벡터A를 벡터B에 투영한 길이 ) = |A|cos@ = A • B / |B|
또, B방향 단위벡터는 N은 아래처럼 구해지니....
N = B / |B|
결국 벡터A를 벡터B에 투영한 벡터[?]를 다시 표현하면 아래와 같이 됩니다.
[?] = (A•B/|B|) (B/|B|) = ((A • B)/(|B|*|B|)) B = ((A•B)/(B•B)) B

2. 점과 직선과의 거리
점과 직선의 수직거리는 점에서 직선에 내린 수선(벡터H)의 크기입니다.
 

 
P : 거리를 알고 싶은 점
Lorg : 직선상의 임의의 한점
Ldir : 직선의 방향벡터
 
 
이때 벡터H는 아래그림과 같이 구할수 있죠.

 
Pprj : 벡터(P-Lorg)를 Ldir에 투영한 벡터

Pprj는 벡터(P-Lorg)를 Ldir에 투영한 투영벡터입니다.
저 위의 투영벡터 공식을 적용해보면...
Pprj = (((P-Lorg)•Ldir)/(Ldir•Ldir)) Ldir
최종적으로 벡터 H를 정리하면 다음과 같이 됩니다.
H = (P-Lorg) - Pprj = (P-Lorg) - (((P-Lorg)•Ldir)/(Ldir•Ldir)) Ldir
식은 길지만 따져보면 상당히 값싼 연산임을 알수 있습니다.
무엇보다도 이 식의 최대 장점은 단위벡터가 필요없다는 것입니다.
벡터를 정규화할 필요가 없으니 보기보다는 훨씬 값싼 연산이라 할수 있죠.

3. 점과 반직선과의 거리
 

 
P : 거리를 알고 싶은 점
Lorg : 반직선의 시작점
Ldir : 반직선의 방향벡터

위 그림에서 보듯, 점이 반직선의 시작점보다 뒤쪽(Ldir방향기준)에 있을 경우에 점과 반직선의 거리는 그냥 |P-Lorg|로 구해집니다.

4. 점과 선분과의 거리
벡터A를 벡터B에 투영한 벡터Aprj는 벡터B에 스칼라 값 ((A • B)/(|B|*|B|))을 곱한 벡터입니다.
따라서 계수가 되는 ((A • B)/(|B|*|B|)) 의 크기에 따라 아래와 같이 구분될 수 있습니다.
 
 

 
 
 
이것을 이용하면 다음 그림과 같이 점(P)과 선분(S0,S1)의 거리를 구할수 있습니다.
 

P : 거리를 알고 싶은 점
S0,S1 : 선분을 이루는 두점
V1 : S0에서 P를 향하는 벡터
V2 : S0에서 S1을 향하는 벡터

사실 점과 반직선의 거리는 위에서 세번째 경우를 두번째 경우로 대치시킨것 뿐입니다.
 

반응형
반응형

<선형대수학 개념이해 보충자료 1>

선형변환 (Linear Transformations)

Sang-Gu Lee, Sungkyunkwan Univ., Korea

 

  선형변환 개념의 시각적 이해를 위한  Flash tools, Animations, JAVA Applets 모음집입니다.

 (이에 보태어 행렬식의 기하학적 의미등도 추가 하였습니다.)

christmas.gif

    아래는 는 선형변환의 이미지가 아닙니다. 왜냐하면 선형변환은 선(line)을 선(line)으로 보낸답니다.

       

    아래에서 선형변환을 만지고  느껴봅시다.

  • SWF 1(LT), 평면상에서 x 축에 대한 대칭 이동이라는 선형변환의 행렬 표현
  • SWF 2(LT), 평면상에서 y 축에 대한 대칭 이동이라는 선형변환의 행렬 표현
  • SWF 3(LT), 평면상에서 원점에 대한 대칭 이동이라는 선형변환의 행렬 표현

 

  • SWF 4(LT), 평면상에서 직선 y = x 에 대한 대칭 이동이라는 선형변환의 행렬 표현
  • SWF 5(LT), 평면상에서 상자를 늘리기, 줄이기, 확대, 밀기에 대응하는 선형변환의 행렬 표현

 

  • SWF 6(LT-Movie) with , 단위원에 대한 행렬 A 에 의한 선형변환의 이미지 (또는 행렬의 대각화)
  • SWF Image (LT3D), 단위 Cube에 대한 3차 행렬 A에 의한 선형변환의 이미지<3차원>

 

SWF 6(LT-Movie) with , Image(LT3D),

 

  • SWF 7(Volume),  행렬식의 기하학적 의미 <3차원 경우는 부피, 2차원의 경우 면적>입니다.
    •  

 

    (ii) Understanding of Concepts

* Matrices of L.T.

 

<Appedix>

반응형
반응형

1.

*출처 OpenGL로 배우는 컴퓨터 그래픽스 주우석/한빛미디어

 

 

동차 좌표란 개념이 왜 생겼나?

 

V =     a*Vx + b * Vy + c * Vz    ->    Vector V 

P = r + a*Vx + b * Vy + c * Vz    ->    Vertex P 

 

원점 r 에 관한 정보를 제외 시켜버리면 벡터 V 와 정점 P 는 모두 ( a, b, c ) 이므로

이 둘을 구분할수 없다. 이러한 불편을 해소시키기 위한것이 동차 좌표 개념이다.

이는 3차원 좌표를 3개의 요소로 표시할것이 아니라 차원을 하나 높여 4개의 요소로 표현하자는

것이다.

 

* 여기서 r 은 임의 위치에서 원점 을 가르키는 벡터다. 즉 원점이라 할수 있다.

 

=  a * Vx + b * Vy  + c * Vz + 0 * r       ->      Vector V 는 ( a, b, c, 0 )

P = a * Vx + b * Vy  + c * Vz + 1 * r       ->        Vertex P 는 ( a, b, c, 1 )

 

즉 마지막 요소 가 0 이면 Vector를 나타내고,

마지막 요소가 1이면 정점을 의미 하도록 한것이다.

 

이렇게 함으로써 Vector와 정점을 동일한 방법으로 표현할수 있다.

 

 

 

 

 

좀더 쉽게 접근하기 위해 차수를 내려 2차원 평면의 예를 들어보자.

2차원 평면상의 점 ( 1, 2 ) 를 동차 좌표로 표시하면 ( 1, 2, 1 ) 이 된다.

이는 3차원으로 말하면 Z 축으로 높이 1 의 위치에 있는 점에 해당된다.

 

엄밀히 말해 2차원 평면상의 점을 3차원 공간 상의 직선에 사상( mapping ) 시킨 것이 동차 좌표다.

다시 말해 원점에서 출발해 ( 1, 2, 1 )를 통과하는 모든 3차원 좌표가 동일한 2차원 좌표 ( 1, 2) 를

의미한다.

 

즉 ( 1, 2, 1 ) =  ( 3, 6, 3 ) = ( 4, 8, 4 ) 이 된다.

 

따라서 동차 좌표의 마지막 요소로 앞 요소를 나눈 값이 실제 3차원 좌표가 된다.

 

같은 맥락에서 만일 3차원 동차 좌표를 4차원 ( x, y, z, w ) 좌표로 표시되면 3차원 실제 좌표는

( x / w, y / w, z / w )가 된다. 즉 ( 1, 2, 4, 1 ) = ( 2, 4, 8, 2 ) = ( 5, 10, 20, 5 ) 이며

w = 0 일 경우 그 자체가 Vector ( x, y, z ) 를 나타낸다.

 

 

2.동차좌표계(Homogeneous Coordinates) 간단한 정리

 

좌표계 차원을 n 이라 할때, n개로 이루어진 좌표 만으로는

표현할 수 없는 요소가 있으며 그 한계를 극복하기 위해

n + 1로 표현한 좌표계를 동차 좌표계 (Homogeneous Coordinates) 라 한다.         

 

- n + 1 좌표계에서는 논리상으로 어떤 무한대에 해당하는 좌표 영역이 있을때

특정 점 nx / 0 을 통해 어떤 점을 무한대로 표현할 수도 있다.

 

- Perspective Projection 할 시에 n 차원의 좌표계는 모니터 좌표계로 변환이

되며, 이 경우 거리 축의 거리에 따라 특정 위치의 Vertices는 크기 및 위치가

연산 되어 져야 하며 이때 사용되는 것이 동차좌표계 (Homogeneous Coordinates)의

w 다. 즉, 각각의 n 차원 좌표들을 w로 나누어 적용시킨다.


반응형
반응형

아핀 공간

위키백과, 우리 모두의 백과사전.
(아핀공간에서 넘어옴)

수학에서 아핀공간(affine space)은 유클리드 공간 아핀기하학적 성질들을 일반화해서 만들어지는 구조이다. 아핀공간에서는 점에서 점을 빼서 벡터를 얻거나 점에 벡터를 더해 다른 점을 얻을 수는 있지만 원점이 없으므로 점과 점을 더할 수는 없다. 1차원 아핀공간은 아핀직선(affine line)이라고 한다.

물리적 공간(상대론 이전의 의미에서)은 아핀공간일 뿐만 아니라 계량구조, 좀 더 구체적으로 말하면 등각구조를 갖고 있다.

[편집]정의

아핀공간은 벡터공간 정칙적으로 작용하는 집합이다. 즉, 이는 벡터공간의 주동차공간이다.

이를 풀어서 말하면, S가 집합이고 V가 벡터공간이라 하자. 이때 함수

\Theta : S \times S \to V : (a, b) \mapsto \Theta(a, b).

를 생각하고, 그 함수값 Θ(a,b)를 a - b로 적어서 벡터 b에서 벡터 a를 빼는 것으로 보자. 이때 이 함수가 다음의 두 조건을 만족하면 S를 아핀공간이라 한다:

1. S의 임의의 원소 b에 대해 Θb: S → V, Θb(a) = a - b는 전단사함수이고,
2. S의 임의의 원소 a,b,c에 대해 (a-b) + (b-c) = a-c이다.

 

 

 



볼록 집합

유클리드 공간에 속하는 집합 A에 대해, 그 안의 임의의 두 점을 골랐을 때 둘을 연결하는 선분이 A에 포함될 경우, A를 볼록 집합(convex set)이라 한다. 예를 들어 속이 찬 은 볼록 집합이지만, 안쪽에 구멍이 있거나 초승달처럼 오목하게 들어간 부분이 있을 경우 볼록 집합이 아니다.

볼록 집합은 구간 개념의 임의 차원에 대한 일반화로 볼 수 있다. 구간은 1차원에서의 볼록 집합이며, 임의 차원의 볼록 집합을 1차원에 임의 방향으로 투영하더라도 그 상은 구간이 된다.


이동: 둘러보기찾기
볼록 집합.
볼록 집합이 아닌 예.
 

 

반응형
반응형

 

 

기저(basis)와 좌표계(coordinate system), 고유값(eigenvalue)과 고유벡터(eigenvector)

 


 
>> 기저(basis)와 좌표계(coordinate system)
 
선형대수에서 기저(basis)라 함은 임의의 벡터공간 V에 대해서 어떤 벡터집합 S가 서로 “1차독립”이면서 벡터공간 V를 “생성”하면 벡터집합 S를 벡터공간 V의 기저라고 합니다.
 
사실 위의 기저에 대한 정의는 지극히 수학교과서적인 정의이죠. 기저에 대한 모든 의미가 다 담겨있기는 하지만 이런 딱딱한 정의 내용을 보고 해당 정의가 의미하는 모든 것을 집어내기에는 어지간한 수학적 감각이 있지 않다면 어려울 것으로 생각됩니다. 물론 질문자 분께서도 같은 이유로 인해서 좀 더 쉽게 이해할 수 있는 방법에 대해 질문을 했을 것으로 생각됩니다.
 
이런 엄밀하고 딱딱한 정의에서 벗어나 기존에 우리가 주로 활용하면서 익숙해져 있는 직각좌표계를 가지고 선형대수에서의 기저에 대한 이해를 할 수 있도록 설명을 한번 해 보고자 합니다. 물론 이런 느슨하고 부드러운 설명들은 수학적인 허점을 드러낼 수 있으므로 대충의 감과 이해를 얻고자 하는데 그 목적이 있으며, 이 이해를 바탕으로 다시 한번 엄밀한 정의를 검토함으로써, 해당 정의가 의미하는 바를 좀 더 깊이 있게 이해할 수 있도록 하면 되겠습니다.
 
우선 우리에게 익숙한 2D 직교좌표계를 떠올려 보죠. 두 좌표축을 각각 x, y라고 하고 이 x, y 좌표 평면위의 모든 점에 대해서 x, y에 대한 좌표값 (a, b)로 표현할 수 있다는 것을 배워왔습니다. 여기서 x, y 좌표 평면위의 모든 점을 나타내어 주는 좌표값들은 수의 순서 짝으로써 벡터로 해석될 수 있습니다. 그리고 이 각각의 좌표축을 나타내는 두 단위벡터를 다음과 같이 생각할 수 있겠죠.
 
v1 = (1, 0)
v2 = (0, 1)
 
여기서는 좌표축을 나타내는 기준벡터로써 길이가 1인 단위벡터를 사용했지만 벡터의 길이는 크게 중요하지 않습니다. 다만 길이가 0이 아닌 벡터이면 충분하다는 사실을 1차독립, 1차결합 등이 무엇을 의미하는지 아신다면 이해하실 겁니다. (1차독립과 1차결합은 기저를 이해하는데 중요한 개념이므로 이에 대한 이해가 없으시다면 먼저 교재를 통해서 이에 대한 이해를 구하시는 것이 좋겠습니다.)
 
위의 두 벡터 v1, v2는 서로 1차독립이면서 동시에 1차결합을 통해서 2D 직교좌표계의 모든 점을 표현할 수 있는 벡터공간을 생성함을 알 수 있습니다. 따라서 위의 두 벡터의 집합 S = {v1, v2}는 2D 직교좌표계의 벡터공간 V를 생성하는 기저라고 할 수 있습니다.
 
마찬가지로 3D 직교좌표계에 대해서 각각의 좌표축에 대한 단위벡터는 아래와 같습니다.
 
v1 = (1, 0, 0)
v2 = (0, 1, 0)
v3 = (0, 0, 1)
 
그리고 이 벡터들의 집합 S = {v1, v2, v3}는 3D 직교좌표계의 벡터 공간을 생성하는 기저라고 할 수 있습니다. 이해를 돕기 위해서 실제 예를 하나 들자면, 3D 직교좌표계 내의 한 점(벡터) (2, 5, 7)을 기저들의 일차결합으로 나타내면 아래와 같이 되겠죠.
 
2 (1, 0, 0) + 5 (0, 1, 0) + 7 (0, 0, 1) = (2, 5, 7)
 
그리고 3D 직교좌표계 내의 모든 점들은 위와 같이 기저 S를 사용한 1차결합으로 표현할 수 있으며, 따라서 집합 S는 3D 직교좌표계의 벡터 공간을 생성하는 기저라 할 수 있습니다.
 
이제 기저와 좌표계에 대해서 조금 이해가 되셨는지 모르겠네요. 선형대수를 공부하기 전까지 우리는 막연히 좌표계를 세우고 해당 좌표계 내에서의 모든 점들을 수의 순서 짝으로 표현 하는 방법에 대해서 배웁니다. 그리고 이 개념들이 선형대수를 배우면서 좌표계는 각 좌표축을 대표하는 벡터들을 기저로 하는 벡터공간이며, 이 공간내의 모든 점들은 수의 순서 짝으로써 벡터로 해석될 수 있으며, 해당 벡터들은 기저 벡터들의 일차결합으로 표현할 수 있다는 사실을 이해하게 됩니다.
 
그리고 이러한 사실들을 일반화함으로써, 기하학적으로 구상화할 수 없는 4차원 이상의 고차원에 대한 벡터에 대해서도 똑같이 적용할 수 있는 여러 벡터 연산들의 성질들을 연구할 수 있게 됩니다. 그리고 이런 수학적인 정리와 증명들은 각종 이공계의 여러 분야에서 상상 이상의 응용력을 발휘하며 인류 사회의 발전에 막대한 공헌을 한다고 할 수 있겠습니다.
 
사실 위에서는 직관적인 이해를 돕기 위해서 2D, 3D의 직교좌표계라는 벡터공간의 특수한 경우로만 설명을 했지만, 선형대수를 조금 더 공부하시다 보면 일반화에 의한 차원의 확장이라든지, 또는 직교좌표계는 직교기저들이 이루는 벡터공간으로써 일반적인 벡터공간의 특수한 한 경우에 불과하다는 점 등을 이해하게 되실 겁니다. 다만, 여러 응용분야에 있어서 정규직교기저에 의한 벡터공간은 특히 유용하게 사용되는 경우가 많으므로, 정규직교기저에 대한 성질이 더 중요하게 다루어지기도 합니다.
 
간단하게 실례를 든다면, 물리학에서 운동의 법칙을 배울 때, 처음에는 일차원 운동으로 개념을 잡습니다. 하지만 2, 3차원 혹은 그 이상의 차원으로 이 운동의 법칙을 확장하는 것은 의외로 쉽습니다. 그것을 가능하게 해주는 것이 바로 벡터공간에 대한 수학적 연구의 결과입니다. 그리고 혹시 컴퓨터 3D 게임을 하시는지는 모르겠지만, 선형대수에서의 3차원 정규직교기저에 대한 연구 결과의 응용 없이는 컴퓨터의 3D 그래픽스라는 분야 자체가 존재할 수 없습니다. 이것은 제가 3D 프로그래머로써 현업에서 응용을 하고 있기에 장담할 수 있습니다. 선형대수가 없는 3D 그래픽 소프트웨어 개발은 상상조차 할 수 없습니다.
 
설명이 많이 부족하기는 하지만 위에서 언급한 2/3 차원 직교좌표계가 어떻게 벡터공간으로 대응이 되는지에 대한 이해를 바탕으로 다시 한번 교재의 정의를 살펴봄으로써 기저에 대한 이해 및 기저와 좌표계 사이의 관계에 대한 이해를 구하시면 도움이 되실 것이라 생각합니다.
 
 
>> 고유값(eigenvalue)과 고유벡터(eigenvector)
 
고유값과 고유벡터에 대한 정의는 그리 어려운 것이 아닙니다만, 기저를 설명할 때 언급했던 것처럼 정의만 보고 고유값과 고유벡터가 도대체 뭔지 이해를 하는 것이 쉽지만은 않죠. 하지만 선형대수에 있어서 고유값과 고유벡터에 대한 이해는 상당히 중요합니다. 아마 질문자 분께서 이 고유값과 고유벡터에 대한 내용을 제대로 이해하신다면, 벡터에 선형변환을 가하는 선형 연산자로써의 행렬이라는 존재에 대해서 조금 더 깊이 이해할 수 있는 계기가 될 수 있을 것입니다.
 
다만, 걱정되는 것은 저의 짧은 지식에 의한 설명으로 제대로 의미 전달이 가능할 것인가가 문제라면 문제겠죠. 어쨌든 시작해 보도록 하겠습니다. 고유값, 고유벡터에 대한 교과서적인 정의는 다음과 같습니다.
 
A가 행렬이고 같은 차원의 벡터 x에 대해서 Ax = λx를 만족하면, 스칼라 λ를 행렬 A의 고유값이라 하고, 벡터 x를 스칼라 λ에 대응하는 행렬 A의 고유벡터라고 한다.
 
고유값과 고유벡터에 대한 정확한 이해를 위해서 먼저 고유값과 고유벡터의 기하학적인 성질을 설명을 드리자면, 행렬 A가 어떤 벡터 x에 선형변환을 가하는 선형연산자일 때, 즉 회전변환과 확대/축소 변환을 가하는 연산자일 때, 해당 벡터 x에 대해서 회전변환은 가하지 않고 확대/축소 변환만을 가한다면 이 벡터 x는 A의 고유벡터가 된다는 뜻입니다. 그리고 이런 경우 확대/축소의 양을 나타내는 스칼라를 따로 분리할 수 있게 되는데 이 스칼라 값이 고유값 λ가 된다는 의미입니다.
 
이해를 돕기 위해서 실제 계산을 한번 해 보겠습니다. 예를 들어서 확대연산자의 표준 행렬이라고 할 수 있는 다음 행렬에 아무 벡터나 곱해보면 위에서 보았던 Ax = λx를 만족한다는 것을 쉽게 알 수 있습니다.
 

 


위의 행렬에서는 결국 (1, 0)과 (0, 1) 두 개의 고유벡터가 존재하며 이들 각각에 대응되는 고유값은 k가 된다는 것을 알 수 있습니다. 여기서 자세한 계산 과정을 적지는 않겠습니다. 계산은 책을 보고 훈련을 통해서 익히면 그만입니다. 이해가 없는 계산은 아무짝에 쓸모없는 소모전에 불과 하므로 여기서는 이해에 중점을 맞출 것이며 될 수 있으면 구체적인 계산은 피하도록 하겠습니다. 위의 행렬로 직접 한번 고유값과 고유벡터를 계산해 보시고 결과를 확인해 보세요.
 
자, 이쯤 왔으면 뭔가 딱 느껴지는 것이 있어야 합니다. 위의 행렬은 어떤 벡터이든지 Ax = λx를 만족하는 변환을 가합니다. 그리고 이러한 벡터들은 고유벡터인 (1, 0), (0, 1) 두 벡터의 선형결합에 의해 표현될 수 있습니다. 그리고 이 두 고유벡터는 일반적으로 생각하는 2차원의 정규직교기저벡터와 정확하게 일치합니다.
 
우리는 고유값과 고유벡터의 기하학적 성질을 알 고 있으므로, 위 형태의 행렬이 2차원 정규직교기저가 생성하는 벡터 공간에서 확대/축소 연산을 가하는 표준 행렬이라는 것을 쉽게 알 수 있습니다. 그리고 이쯤에서 어떤 행렬 A가 있을 때, 그 행렬로부터 힘들게 계산해서 구해내는 고유값과 고유벡터가 어떤 의미인지를 어느 정도는 이해할 수 있을 것이라 생각합니다.
 
설명을 계속해 보겠습니다. 여기서 부터는 잘 따라오셔야 합니다. 일반적으로 우리가 머릿속에 그리는 2차원 직교좌표계에서의 벡터들에게 선형연산을 가하는 어떤 행렬 A가 있을 때, 이 행렬 A가 위에서 본 확대/축소 행렬의 형태가 아닌 이상, 그 행렬이 2차원 정규직교기저가 만드는 벡터공간 내에서는 확대/축소 뿐 아니라 회전변환까지도 가하게 됩니다. 즉, 이것은 이 행렬 A가 2차원 정규직교기저의 벡터 공간에서는 벡터들에게 어떤 변환을 가할지 계산하기가 복잡하다는 의미가 됩니다. 단순히 확대/축소 변환만 가하는 행렬과 확대/축소 및 회전변환까지 가하는 행렬 중 어느 행렬이 더 이해하기 쉽고 계산하기 쉬우며 더 나아가 어떤 문제 해결에 응용하기 쉬운지는 이견의 여지가 없을 것입니다.
 
이제 어느 정도 결론에 도달해 가는 것 같습니다. 이제 우리는 어떤 선형연산자로써의 행렬이 있을 때, 이 행렬로부터 고유값과 고유벡터를 계산해 냄으로써, 이 행렬이 벡터에 가하는 변환을 고유벡터들이 기저를 이루는 고유공간에서의 변환으로 해석함으로써, 회전 변환은 배제하고 확대/축소 변환만으로 이해하고 응용할 수 있게 되었습니다.
 
확실한 이해를 위해서 구체적인 예를 한 가지만 들어 보겠습니다. 다음과 같은 행렬 A가 있습니다.

 
위 행렬 A의 고유벡터는 v1 = (1, 1), v2 = (-1, 1) 이고, 고유값은 λ1 = 3, λ2 = -1입니다. 그러면 이 행렬 A가 벡터 x = (x1, x2) 에 변환을 가할 때, 이 변환을 고유벡터 v1, v2가 기저를 이루어 생성하는 고유벡터 공간에서 이해를 하면, v1 방향으로는 3배, v2 방향으로는 -1배한 벡터들의 합으로 변환이 가해진다는 것을 알 수 있습니다.
 
위 설명이 사실인지 직접 계산을 통해서 이해를 해 보죠.

 

 
위의 풀이 과정으로 x = (2, 3) 인 경우를 계산해 보면 Ax = (8, 7) 이 나온다는 것을 알 수 있습니다. 그리고 이것은 실제 Ax를 행렬 계산으로 계산했을 때 구해지는 값이기도 하다는 것을 확인해 보시기 바랍니다. 그리고 이것을 그림으로 나타내면 아래 그림과 같습니다.

 

 

 

 
위 그림을 보시면 보다 더 명확하게 이해가 가실 겁니다. 즉, 행렬 A가 벡터 x에 가하는 변환을 행렬 A의 고유벡터들이 기저를 이루어서 생성되는 고유공간에서 이해를 하면, 고유 벡터들의 확대/축소 연산만을 가지고도 이 변환을 이해할 수 있게 된다는 것입니다. 이것이 원래의 직교기저가 생성하는 벡터 공간에서의 변환을 이해하는 것 보다 훨씬 쉽다는 것을 그림을 통해서 이해해 보시기 바랍니다. 그리고 이러한 결과로 인해서 고유값과 고유벡터의 개념은 이공계 분야에서 상당히 중요한 응용에 사용되는 경우가 아주 아주 많습니다.
 
자, 이제 어느 정도 이해가 되셨으리라 생각합니다. 항상 느끼는 거지만, 수학이란 학문은 수식을 제외하고 말로만 설명을 하려면 상당히 힘들죠. 하지만 바꾸어 말하면 수식으로만 설명이 된 내용들은 탁월한 감각이 있지 않은 사람들이 보기에는 쉽게 이해하기가 힘들다는 것도 분명한 사실입니다. 저 역시도 후자에 속하는 한 사람으로써 고유값과 고유벡터를 이해하는데 애를 먹었던 기억이 있습니다.
 
짧은 지식으로, 그리고 말로 수학을 설명 하느라 핵심 내용이 어느 정도로 잘 전달되었는지 모르겠지만, 그래도 어렴풋이나마 이해를 하셨다면 여기서의 이해를 잘 떠올리면서 다시 한번 교재의 정의들과 응용에 활용되는 예제들을 풀어 보시기 바랍니다. 분명 이전에 잘 모르고 공식으로만 풀어내던 고유값과 고유벡터에 대해 새로운 눈을 뜨게 되실 것이라 생각합니다. 아울러 아까도 잠깐 업급 했지만, 선형연산자로써의 행렬을 바라보는 눈도 이전 보다는 한층 더 발전된 시각으로 바로 볼 수 있게 되었기를 바래봅니다.
 
그럼 행운을 빕니다.

 

 

참고]

NAVER 지식인


반응형

'수학 (Mathematics) > 3D수학' 카테고리의 다른 글

동차 좌표  (0) 2012.11.02
아핀공간과 볼록집합  (0) 2012.11.02
IntersectTriangle 분석  (0) 2012.11.02
픽킹 ( 광선과 오브젝트 충돌판정 )  (0) 2012.11.02
3D 기하학  (0) 2012.11.02
반응형

출처: http://www.gamza.net

 

copyrightⓒ 김성수 [2002년 05월 26일]

 

이글은 D3D의 Pick예제에 나와있는 IntersectTriangle에 관한 설명입니다. 이 함수가 하는일이나 사용법에 대해선 예제에 잘 나와있기때문에 이런것을 설명하지는 않습니다. 이글의 목적은 함수 자체가 어떤 원리로 동작을 하는지를 이해하는것이죠.

IntersectTriangle은 단순히 소스분석만해서는 도저히 이해를 할 수 없습니다.
가뜩이나 벡터연산이 복잡해 머리가 아픈데, 수학적인 레벨에서 최적화를 해놓았으니 더욱 암호처럼 보일수 밖에....
그럼 IntersectTriangle의 동작원리에 대해 하나씩 알아보겠습니다.

1. 삼각형 점포함 테스트
IntersectTriangle이 반직선과 삼각형의 교차판정을 하는방법은 2차원적으로 해석될수 있습니다.
반직선과 삼각형 평면의 교점이 삼각형에 포함되는지를 검사하는것이죠.
그런데 특별한 사정때문에 이전에 제가 썼던 글에 있는 점포함테스트를 사용하지 않습니다.
약간은 특이한 방법을 쓰게되죠.


 
 
그림을 보시면 벡터가 세개 나옵니다. OA,OB는 고정된 벡터이고 OP는 임의의 벡터입니다.
임의의 벡터 OP를 벡터 OA,OB를 가지고 표현해 봅시다.
OP = u * OA + v * OB ( u,v는 임의의 실수 )
벡터의 영역문제에서 자주본 꼴이죠? (생각이안나는 사람은..정석을 뒤져봅시다)
u와 v에 제약을 가하면 점P는 특정한 영역을 표현하게 됩니다.
옴옴...뭘하려는지 알겠다고요?
그렇습니다. u,v에 어떤 조건을 붙여서 P가 삼각형 OAB영역을 표현하도록 하려는겁니다.
P가 OAB영역을 표현하기위한 조건은, 삼각형의 변(①②③)에대해 각각 하나씩 있습니다.
① : 0 ≤ u
② : 0 ≤ v
③ : u + v ≤ 1
이 조건들은 알아서덜 증명을... (①②번 조건은 말이 필요없고...③번조건은 직선 AB가 t*OA + (1-t)*OB 임을 이용)
위조건을 만족하는 u,v에 대해 P가 표현하는 영역은 삼각형 OAB입니다.
점 P가 삼각형 OAB에 포함되는지를 검사하는것은 u,v가 위조건을 만족하는지를 검사하는것과 같다는 얘기.
IntersectTriangle이 출력하는 u,v가 지금껏 이야기해온 u,v입니다. 반직선과 삼각형 평면의 교점이 P, 삼각형의 각 꼭지점이 O,A,B인 셈이죠. 따라서 반직선과 삼각형의 교차판정은 코드중에 다음처럼 나타납니다.
    if( *u < 0.0f || *u > det )
        return FALSE;
    if( *v < 0.0f || *u + *v > det )
        return FALSE;
Picking일 경우 IntersectTriangle이 출력하는 u,v를 사용하면 마우스의 3차원 위치와 카메라와의 거리를 쉽게 구할수 있습니다.
마우스의 3차원좌표 = v0 + u * ( v1 - v0 ) + v * ( v2 - v0 )
카메라와의 거리 = |마우스의 3차원좌표-orig|

2. 벡터분해
문제는 OP를 OA,OB로 표현하는것. 다시말해 u,v값을 어떻게 구하는가 하는것입니다.
이제 OP를 OA,OB로 분해하는법을 생각해봅시다.

 
 
왼쪽그림을 보면 v = |Ob| / |OB| 임을 쉽게 알 수 있죠?
이때 벡터 OB와 Ob를 OA에 수직인 벡터 nA에 투영을 한것이 오른쪽 그림입니다.
보다시피 한쌍의 닮은꼴 삼각형이...... 옴옴...그냥 아래식을 주욱 읽으시면 걍 이해가....
(도데체 그림때문에 설명할게 없잖아!...ㅡ.ㅡ;;)
v = |Ob|/|OB| = |Ob||nA|cosθ/|OB||nA|cosθ = Ob•nA/OB•nA
여기서 벡터 Ob와 OP는 법선 nA에 대해 같은 정사영을 갖습니다.
Ob•nA = OP•nA
v = Ob•nA/OB•nA = OP•nA/OB•nA
같은 방법으로 u를 표현하면..
u = OP•nB/OA•nB
이제 법선과 내적값을 구하는일만 남았군요.

3. 내적값(OP•N)과 법선(N)
실제로 IntersectTriangle은 공간상의 반직선과 평면의 교점(P)을 구하지 않고 u,v값을 계산해 냅니다.
교점이 없이도 OP•N 값을 알아내는 방법이 있기때문인데요, 바라보는 방향에 비책이 숨어 있습니다
 

 
 
왼쪽그림은 IntersectTriangle의 입력들을 그려놓은것입니다. 오른쪽 그림은 이것을 dir과 평행한 방향으로 바라본 그림이고요.
그림에 표시된 법선(N)은 V0,V2를 포함하고 바라보는 방향과 평행한 평면의 법선벡터입니다.
이때, 점 P와 orig는 이 벡터(N)에대해 '같은 정사영'을 갖는 점들임을 알수 있습니다. 즉 다음이 성립한다는 말이죠.
(orig-V0)•N == (P-V0)•N
N을 법선으로 하는 평면은 V0,V2,(V0+dir)을 포함하는 평면이고(dir과 평행한 방향으로 바라봤으므로),
따라서 법선 N은 다음과같이 구해집니다.
N = dir ⅹ ( V2 - V0 )
연산자 'ⅹ' 가 외적인건 아시죠?
이제 모든값을 알았으니 정리를 좀 해볼까요?
u = tvec • ( dir ⅹ e2 ) / e1 • ( dir ⅹ e2 )
음...갑자기 이상한것들이 튀어나와서 죄송. 식을 쓰다보니 점점 길어지는것 같아서... 
앞으로는 아래와 같은 정의를 사용하도록 하겠습니다.
e1 = V1 - V0
e2 = V2 - V0
tvec = orig - V0
이제야 소스의 다음부분에 대한 설명이 끝났군요.
D3DXVec3Cross( &pvec, &dir, &edge2 );
FLOAT det = D3DXVec3Dot( &edge1, &pvec );
*u = D3DXVec3Dot( &tvec, &pvec );
FLOAT fInvDet = 1.0f / det;
*u *= fInvDet;
사실 여기까지가 설명의 끝입니다.
나머지는 최적회일 뿐이죠.

4. 최적화
u를 구한것과 같은 방법으로 v를 구해 봅시다.
v = tvec • ( e1 ⅹ dir ) / e2 • ( e1 ⅹ dir )
여기에 약간의 수학적성질을 적용해보면 재미있는 사실을 알게됩니다.
A•(BⅹC) = B•(CⅹA) = C•(AⅹB)
이것을 이용해서 v의 분모부분을 변형해볼까요?
e2 • ( e1 ⅹ dir ) = e1 • ( dir ⅹ e2 )
오호...잘보니 v,u의 분모부분이 같은넘이었군요!
분자부분도 같은방법으로 변형시켜보면 소스코드가 이해가 되실겁니다.
(이것두 역시 최적화. 나중에 t 를 계산할때 외적결과를 또 써먹으려고 변형을 해 놓은거죠. )
이것으로 다음소스에 대한 설명이 끝났습니다.
D3DXVec3Cross( &qvec, &tvec, &edge1 );
*v = D3DXVec3Dot( &dir, &qvec );
*v *= fInvDet;
IntersectTriangle은 연산을 수행하는 도중 판정결과를 알 수 있다면 바로 리턴하는 방식으로, 필요없는 연산이 일어나지 않도록 구성되어있습니다.
그중 하나가 첫번째 나온 비교문입니다. 
    if( det < 0.0001f )
        return FALSE;
이 비교문은 코딩 차원에서 본다면 0으로 나누는 에러방지와 det값과 u,v값의 비교를 쉽게해주는 역할을 합니다만, 수학적으로 보면 이코드의 또다른면을 볼 수 있게됩니다.
이 조건이 참이되는 경우를 생각해 보도록 합시다. det값은 법선벡터 N과 변벡터 e1의 내적값입니다.
이값이 0이면 삼각형은 dir과 평행한 평면에 존재하는것 입니다. 만약 이 값이 0보다 작으면 삼각형이 뒤집어져 있는경우죠.
 
 
 

 
 
여기서 잠깐!
D3D8.1 버젼부터는 det에 절대값을 취함으로써 뒤집어진 면도 교차라고 판정하도록 되어있습니다.
사실 이전 버젼의 예제들은 det값을 그대로 사용해서, IntersectTriangle함수가 반직선과 삼각형의 교차판정뿐 아니라 뒤집어진 삼각형이 아닌지까지 검사하도록 만들어져 있었던겁니다.
이것을 함수의 목적에 맞도록 수정했다고나 할까요?
하지만 det에 절대값을 취하는 부분만 없애면 '별도의 연산없이' 뒤집어진 삼각형을 검사해낼 수 있다는것을 꼭 알아두시길...

5. t : orig와 P 의 거리
소스에대한 의문들이 풀리셨나 모르겠습니다. 근데 교차판정과는 전혀 상관없는 코드가 하나 더있네염. 안그래두 엄청시리 길어졌는데...그렇다고 안하고 놔두자니 영 찜찜...
다음은 아직 설명하지 않은 '유일한' 코드입니다.
    *t = D3DXVec3Dot( &edge2, &qvec );
    *t *= fInvDet;
우선 설명을 하기전에 t와 det를 적당히 변형하도록 하겠습니다.
( 각종 연산결과들을 최대한 재사용하려고 변형해 놓은거라서 변형하지 않고는 설명이 넘 어렵습니다. )
det = e1 • ( dir ⅹ e2 ) = dir • ( e2 ⅹ e1 )
t = e2 • ( tvec ⅹ e1 ) = tvec • ( e1 ⅹ e2 ) = -tvec • ( e2 ⅹ e1 )
( ∵ AⅹB = -BⅹA )
공식을 보고 있자니 원래 문제를 e1,e2를 포함하는 평면과 평행한 방향으로 다시 보고싶어집니다.
(삼각형을 옆에서 바라봤으니 삼각형은 선분으로 보입니다.)
 
 

 
 
우리가 구하고자 하는 t는 dir을 단위로하는 시점에서 교점까지의 거리입니다.
|P-orig| = t * |dir|
∴ t = |P-orig|/|dir| = |P-orig||N|cosθ/|dir||N|cosθ = (P-orig)•N / dir•N
(여기서 N = e2 ⅹ e1 )
근데 N에 대해서 벡터 P-orig 와 -tvec이 같은 정사영을 갖습니다. 따라서...
(P-orig)•N == (-tvec)•N
∴ t = (P-orig)•N / dir•N = (-tvec)•N / dir•N

우~~~아~~~~~정말로 길군요.
말로 설명하면 금방될것을....황금같은 주말에 이틀동안 집에 틀어밖혀서 이것만 써댔네염.....T.T...
이것으로 소스가 완전히 이해되셨기를 바랍니다.
이해가 안되신다면 질문주세염.
거럼...오늘 프랑스전.... 2:1 에 5000원 걸었는데......
'한국승'에 걸었답니다. 코리아팀 파이팅! o(^O^)O
- 참고소스 DX8 -
//-----------------------------------------------------------------------------
// Name: IntersectTriangle()
// Desc: Given a ray origin (orig) and direction (dir), and three vertices of
//       of a triangle, this function returns TRUE and the interpolated texture
//       coordinates if the ray intersects the triangle
//-----------------------------------------------------------------------------
BOOL CMyD3DApplication::IntersectTriangle( const D3DXVECTOR3& orig,
                                       const D3DXVECTOR3& dir, D3DXVECTOR3& v0,
                                       D3DXVECTOR3& v1, D3DXVECTOR3& v2,
                                       FLOAT* t, FLOAT* u, FLOAT* v )
{
    // Find vectors for two edges sharing vert0
    D3DXVECTOR3 edge1 = v1 - v0;
    D3DXVECTOR3 edge2 = v2 - v0;

    // Begin calculating determinant - also used to calculate U parameter
    D3DXVECTOR3 pvec;
    D3DXVec3Cross( &pvec, &dir, &edge2 );

    // If determinant is near zero, ray lies in plane of triangle
    FLOAT det = D3DXVec3Dot( &edge1, &pvec );

    D3DXVECTOR3 tvec;
    if( det > 0 )
    {
        tvec = orig - v0;
    }
    else
    {
        tvec = v0 - orig;
        det = -det;
    }

    if( det < 0.0001f )
        return FALSE;

    // Calculate U parameter and test bounds
    *u = D3DXVec3Dot( &tvec, &pvec );
    if( *u < 0.0f || *u > det )
        return FALSE;

    // Prepare to test V parameter
    D3DXVECTOR3 qvec;
    D3DXVec3Cross( &qvec, &tvec, &edge1 );

    // Calculate V parameter and test bounds
    *v = D3DXVec3Dot( &dir, &qvec );
    if( *v < 0.0f || *u + *v > det )
        return FALSE;

    // Calculate t, scale parameters, ray intersects triangle
    *t = D3DXVec3Dot( &edge2, &qvec );
    FLOAT fInvDet = 1.0f / det;
    *t *= fInvDet;
    *u *= fInvDet;
    *v *= fInvDet;

    return TRUE;
}

반응형
반응형

픽킹 ( 광선과 오브젝트 충돌판정 )


http://blog.naver.com/zeowing/90082924441


copyrightⓒ 김성수 [2002년 05월 21일]

BLACK&WHITE 같은 마우스를 만들려면 마우스의 2D위치를 3D공간좌표로 변환하는것이 필요해집니다. 등장하는 '신의손'이 실제 공간좌표를 갖기때문이죠. 이것은 상당히 효과만점인 반면, 물체를 Pick할줄만 알면 아주 간단하게 끝나는 아주 쉬운 기법입니다.
D3D의 Pick예제를 보면 물체를 picking하는 기법이 깔끔하게 나와있으니 그걸 그대로 사용하도록 하겠습니다.
2D마우스 좌표를 3D좌표로 변환하는 순서는 다음과 같습니다.
(1) 마우스 좌표를 가지고 공간상에 반직선을 만든다. (언프로젝션)
(2) 반직선과 교차하는 폴리곤중 가장 가까운것을 택한다. ( picking )
(3) 직선과 폴리곤의 교점을 구한다.( == 3D마우스 좌표 )

1. 언프로젝션
우선 마우스 좌표에 해당하는 3D점을 하나 구합니다.
( 아래식이 이해가 안되시는 분들은 '언프로젝션 ( Unprojection )' 과 그것에 링크된문서들을 꼭 읽어보세요. 안읽어보셔도 당장 써먹는데야 지장이 없겠지만....배워서 남주는거 아니니깐요.)

 
 m_pd3dDevice->GetViewport(&vp);
 m_pd3dDevice->GetTransform( D3DTS_PROJECTION, &matProj );
 GetCursorPos( &ptCursor );
 ScreenToClient( m_hWnd, &ptCursor );
 v.x = ((  (((ptCursor.x-vp.X)*2.0f/vp.Width ) - 1.0f)) - matProjection._31 ) / matProjection._11;
 v.y = ((- (((ptCursor.y-vp.Y)*2.0f/vp.Height) - 1.0f)) - matProjection._32 ) / matProjection._22;
 v.z =  1.0f;

언프로젝션하는 부분을 주의하세요. D3D예제에 있는대로 하시면 안될경우가 있습니다.
( 투영행렬에 클리핑행렬이 포함된것 같은경우 )
...
이제 카메라 좌표와 구해진 점을 잇는 반직선을 만들면 되죠,

        m_pd3dDevice->GetTransform( D3DTS_VIEW, &matView );
        D3DXMatrixInverse( &m, NULL, &matView );
        vPickRayDir.x  = v.x*m._11 + v.y*m._21 + v.z*m._31;
        vPickRayDir.y  = v.x*m._12 + v.y*m._22 + v.z*m._32;
        vPickRayDir.z  = v.x*m._13 + v.y*m._23 + v.z*m._33;
        vPickRayOrig.x = m._41;
        vPickRayOrig.y = m._42;
        vPickRayOrig.z = m._43;

2. Picking
D3D예제를 보시면 IntersectTriangle 함수를 사용해서 위에서 구한 반직선이 삼각형에 교차하는지를 검사해서 Pick를 수행하게 됩니다.
근디 우리가 해야할건...그중에서 카메라에 젤 가까운넘을 골라내는겁니다.
거럼 ...어떤넘이 카메라에 가장 가까운 넘인가???

BOOL CMyD3DApplication::IntersectTriangle( const D3DXVECTOR3& orig,
                                       const D3DXVECTOR3& dir, D3DXVECTOR3& v0,
                                       D3DXVECTOR3& v1, D3DXVECTOR3& v2,
                                       FLOAT* t, FLOAT* u, FLOAT* v )

IntersectTriangle함수의 6번째 인자(t) 는 출력용 인자입니다. 폴리곤과 반직선의 교점이 카메라에서 얼마나 떨어져 있는지를 알려주죠.
다시말하면....교차가 발견될때마다 출력된 t 값을 조사해서...젤 작은넘을 유지하도록 하면 됩니다.
t가 제일 작은 폴리곤이 실제로 picking된 폴리곤이죠.

3. 3D마우스 좌표계산
최종적인 3D좌표는 반직선과 IntersectTriangle함수의 출력으로 얻어진 t값으로부터 다음과 같이 구해집니다.

3D마우스 좌표 = vPickRayOrig + vPickRayDir * t ;



자...끝났습니다.

참....마우스가 화면상의 어떤것도 선택하고 있지 않을경우를 별도 처리 해야한다는 것을 잊지마세요.
아무것도 선택되지 않았다면 '카메라로부터의 기본거리'를 적용하는 것이 가장 자연스러울듯 합니다.

t = 기본거리 / D3DXVec3Length( vPickRayDir ) ;


이렇게 처리하면 되죠.

이거...응용할데가 많겠죠?
레벨편집기라던가, RPG, 전략시뮬같은데서도 유용하게 쓰일듯...

펌 http://www.gamza.net/









[출처] [Direct3D] 픽킹(Picking) - 지형 픽킹|작성자 dovcat

 

 

 

 

 

 

 

소스 코드

 

 FLOAT PointX;
 FLOAT PointY;

 // 뷰 포트 정보를 받아옵니다.
 D3DVIEWPORT9 ViewPortInfo;
 mDevice->GetViewport(&ViewPortInfo);

 // 프로젝션 매트릭스를 얻어옵니다.
 D3DXMATRIX Proj;
 mDevice->GetTransform(D3DTS_PROJECTION, &Proj);
  
 // 마우스 포인트를 투영창의 좌표로 변환합니다.
 PointX = (2.0f * LOWORD(lParam) / ViewPortInfo.Width - 1.0f) / Proj(0, 0);
 PointY = (-2.0f * HIWORD(lParam) / ViewPortInfo.Height + 1.0f) / Proj(1, 1);

 // 투영창의 좌표로 변환된 포인트를 가지고 광선을 생성합니다.
 RAY Ray;
 Ray.origin = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
 Ray.dir  = D3DXVECTOR3(PointX, PointY, 1.0f);

 // 뷰 매트릭스를 얻어옵니다.
 D3DXMATRIX View;
 mDevice->GetTransform(D3DTS_VIEW, &View);

 // 뷰 매트릭스의 역행렬을 구합니다.
 D3DXMATRIX ViewInverse;
 D3DXMatrixInverse(&ViewInverse, 0, &View);

 // 포인트를 월드 스페이스의 좌표로 변환합니다.
 D3DXVec3TransformCoord(&Ray.origin, &Ray.origin, &ViewInverse);
 D3DXVec3TransformNormal(&Ray.dir, &Ray.dir, &ViewInverse);
 D3DXVec3Normalize(&Ray.dir, &Ray.dir);

 

그리고 이 놈으로 광선과 지형(삼각형(face))의 교차를 검사하세요.

D3DXIntersectTri()

Direct3D에서 제공하는 제 입장에선 아주 강력한 함수로군요.

광선과 평면식의 조합을 어쩌구저쩌구 해서 교차 테스트릴 해도 마음대로 성공하지 못했는데...

이 녀석 하나로 코드도 줄고 테스트도 한 번에 되더군요... 흑흑....


 

 

한가지 덧붙이자면 월드까지 간 형태에서 로컬좌표까지 내려가 충돌판정을 할 수 있는데

 

이는 동일하게 광선을 로컬좌표까지 변환하여 충돌판정을 하면 된다

 

윈도우좌표부터 로컬좌표까지 어느좌표에서의 충돌판정이 좋다라기보다는 각 상황에 맞게 최적의 좌표에서 충돌판정하는 것이

 

최적이라 할 수 있겠다

 

 

 

IntersectTriangle 의 좀 더 자세한 설명을 감자닷넷에서 퍼왔다,

 

 

1. 삼각형 점포함 테스트
IntersectTriangle이 반직선과 삼각형의 교차판정을 하는방법은 2차원적으로 해석될수 있습니다.
반직선과 삼각형 평면의 교점이 삼각형에 포함되는지를 검사하는것이죠.
그런데 특별한 사정때문에 이전에 제가 썼던 글에 있는 점포함테스트를 사용하지 않습니다.
약간은 특이한 방법을 쓰게되죠.

그림을 보시면 벡터가 세개 나옵니다. OA,OB는 고정된 벡터이고 OP는 임의의 벡터입니다.
임의의 벡터 OP를 벡터 OA,OB를 가지고 표현해 봅시다.

OP = u * OA + v * OB   ( u,v는 임의의 실수 )

벡터의 영역문제에서 자주본 꼴이죠? (생각이안나는 사람은..정석을 뒤져봅시다)
u와 v에 제약을 가하면 점P는 특정한 영역을 표현하게 됩니다.
옴옴...뭘하려는지 알겠다고요?
그렇습니다. u,v에 어떤 조건을 붙여서 P가 삼각형 OAB영역을 표현하도록 하려는겁니다.
P가 OAB영역을 표현하기위한 조건은, 삼각형의 변(①②③)에대해 각각 하나씩 있습니다.
① :     0 ≤ u
② :     0 ≤ v
③ : u + v ≤ 1
이 조건들은 알아서덜 증명을... (①②번 조건은 말이 필요없고...③번조건은 직선 AB가 t*OA + (1-t)*OB 임을 이용)
위조건을 만족하는 u,v에 대해 P가 표현하는 영역은 삼각형 OAB입니다.
점 P가 삼각형 OAB에 포함되는지를 검사하는것은 u,v가 위조건을 만족하는지를 검사하는것과 같다는 얘기.
IntersectTriangle이 출력하는 u,v가 지금껏 이야기해온 u,v입니다. 반직선과 삼각형 평면의 교점이 P, 삼각형의 각 꼭지점이 O,A,B인 셈이죠. 따라서 반직선과 삼각형의 교차판정은 코드중에 다음처럼 나타납니다.

    if( *u < 0.0f || *u > det )
        return FALSE;
    if( *v < 0.0f || *u + *v > det )
        return FALSE;

Picking일 경우 IntersectTriangle이 출력하는 u,v를 사용하면 마우스의 3차원 위치와 카메라와의 거리를 쉽게 구할수 있습니다.

마우스의 3차원좌표 = v0 + u * ( v1 - v0 ) + v * ( v2 - v0 )
카메라와의 거리 = |마우스의 3차원좌표-orig|
 
 
 
p.s 좀더 자세한 설명은 다음에...

반응형
반응형

반응형
반응형

감자닷넷 주인장께서 홈페이지 리뉴얼을 하셨드라고요 다시 올립니다~

 

 

http://www.gamza.net/

 

 

 

반사벡터


 

전반사는 물체가 충돌하여 튕겨나갈때 라던가, 빛의 반사, 당구공등의 구현에 사용되는데, 이것은 벡터를 가지고 생각해보면 생각보다 매우 간단하게 구현됨을 알수 있습니다. 


전반사

전반사는 입사벡터와 반사벡터의 크기가 동일하고, 입사각과 반사각이 같은 것을 말합니다.




여기서 우리가 풀고자 하는 문제는 충돌면의 법선벡터(N)와 입사벡터(D)만을 가지고 반사벡터([?])를 만들고자 하는것입니다.
그림을 보고 머리를 굴려봅시다.


negDprj : 벡터-D를 법선N에 투영한 벡터

위에나오는 직각삼각형은 모두 '합동'입니다.
따라서 [?]는 벡터negDprj를 두배로 한 벡터와 벡터D의 더한 벡터임을 알 수 있습니다.

[?] = 2 negDprj + D

여기에 투영벡터공식(negDprj)을 적용하면.....

[?] = ( 2 * (-D•N)/(N•N) ) N + D

만약 법선 벡터 N이 단위벡터라고 가정하고 정리하면...

[?] = ( 2 * (-D•N) ) N + D

 


 

 

 

미끄러짐 벡터


 

 

충돌시엔 보통 미끄러짐 처리를 하게 됩니다. 이럴때 사용하는 미끄러짐 벡터를 구하는 법을 알아보도록 하겠습니다.

충돌시 속도벡터는 다음과 같이 충돌면에 수직인 성분과 평행인 성분으로 분리됩니다.
여기서 수직성분은 없애고 수평성분에 해당하는 이동을 하는것이 여기서 구현하고자 하는 '미끄러짐'입니다.

자, 이제 문제는 물체의 속도벡터(V)와 충돌면의 법선벡터(N)로부터 속도벡터의 수평성분을 구하는 것으로 정리되었습니다.
그런데 여기서 V의 수직성분이라 함은....V를 N에 투영한 벡터(Vprj)를 말합니다.
따라서 투영벡터공식을 적용해서 Vprj를 구하면...
Vprj = ( (V•N)/(N•N) ) N
V를 알고, V의 수직성분을 알게되었으니 우리의 목표인 V의 수평성분은 아래와 같이 구해집니다.
속도벡터의 수평성분 = V - Vprj = V - ( (V•N)/(N•N) ) N
만약 법선 벡터 N이 단위벡터라고 가정하고 정리하면...
속도벡터의 수평성분 = V - (V•N) N
 
 
 
 
 

반응형
반응형

■ 3D Engine

new RHW(Reciprocal Homogeneous W)란? < 김성완 - 2001년 7월 23일 >

"W는 Homogeneous coordinates의 네번째 성분이고 homogeneous coordinates 는 우리말로 동치 좌표라고 합니다. 일반적으로 3차원 좌표변환 행렬로 4*4 행렬을 사용하는데.. 그렇게 되면 버텍스 좌표계 값은 (x,y,z,1)로 사용합니다. "

Realtime Dynamic Level of Detail Terrain rendering with ROAM

번역 : 이봉식 - 2000년 4월 20일 >
원문 : By Bryan Turner Gamasutra April 03, 2000

"▶ Introduction to Terrain Visualization
▶ Explanation of Patch Class 
▶ Roam Engine Qualifiers"

Picking < 김성완 - 2000년 3월 25일 >

"D3D IM 에서 화면상의 객체를 마우스로 선택하는걸 Picking이라고 하는데... 
화면상의 마우스 좌표값에 대응되는 삼차원 물체를 찾아내는 거죠."

거울 효과 < 김성완 - 2000년 3월 25일 >

"물체가 바닥에 반사되는 효과는 보통 그 물체를 뒤집어서 반사되는 것 처럼 보이도록 하나 더 그립니다."

T&L 가속에 대해서 < 김성완 - 2000년 3월 20일 >

"제대로 T&L가속이 이루어 지려면 Vertex 데이타가 비디오 램에 있어야 합니다."

3D Programming 관련 서적 소개 < 김성완 - 2000년 2월 22일 >

"3차원 그래픽 프로그래밍을 공부하려면 책 한두권으로 되는게 아니라 여러권을 공부해야합니다."

*** g-Matrix3D Engine version 0.1 < 김성완 - 2000년 1월 24일 >

"g-Matrix 3D는 Win32 기반의 본격적인 3차원 엔진을 염두에 두고 개발중인 3차원 엔진으로 Software, OpenGL, Direct3D를 모두 지원 합니다."

D3DVERTEX, D3DLVERTEX, D3DTLVERTEX < 김성완 - 2000년 1월 24일 >

"Direct3D의 경우 3차원 게임 개발자들이 선택적으로 모듈을 사용할 수 있도록, 세가지의 꼭지점 데이타 형식을 지원합니다."

OpenGL과 Direct3D < 김성완 >

"1. OpenGL과 D3D의 선택 < 1999년 12월 3일 >
2. OpenGL과 D3D의 파이프라인 비교 < 2000년 1월 12일 >"

DirectX 7.0의 Direct3DX < 김성완 - 2000년 1월 10일>

"DirectX 7.0으로 버전업 되면서 가장 큰 변화를 겪은 Component가 아마 Direct3D Immediate Mode 일 겁니다."

3차원 엔진 < 김성완 >

"1. 상용 3차원 엔진 < 1999년 12월 21일 >
2. D3d와 OpenGL은 3차원 엔진이 아니다. < 1998년 12월 28일 >
3. 국내에서는 3D 엔진 안 만드는가?? < 1998년 1월 3일 >"

[강좌] Quaternion < 김성완 >

" 1. 복소수와 쿼터니온 그리고 회전 < 1999년 6월 24일 >
2. 쿼터니온의 유래와 Angular displacement < 1999년 7월 13일 >
3. 단위 쿼터니온과 임의축 회전의 대응 < 1999년 11월 11일 >"

Blade의 Projection shadow < 조기용 >

"1. Blade의 Omni라이트 구현법 < 1999년 6월 25일 >
2. Projection Shadow < 1999년 11월 9일 >"

회전 공식 증명 < 김성완 - 1999년 10월 21일 >

"증명방법은 두가지를 보통 접하는데..
한가지는 기하학적인 방법이고, 다른 하나는 대수적인 방법입니다."

Quake VS Blade < 조기용 - 1999년 6월 24일 >

"퀘이크3에선 BSP를 끝까지 고집하는 덕에 정적 LightMap과 그림자가 아예 없는데 반해, Blade에서 Project shadow라는 최첨단 기술로 빛과 그림자 처리를 동적으로 처리했어요."

Opengl을 겜에 적용할때... < 김성완 - 1999년 7월 19일 >

" 윈도우즈 시스템에 기본적으로 설치된 OpenGL 은 소프트웨어 드라이버로 구성된 OpenGL이라서 3차원 가속기와는 일단 무관합니다."

OpenglㆍDirectxㆍGlide < 조기용 - 1999년 7월 10일 >

"하나의 랜더러만을 고집하면서 퍼포먼스를 높이려는건... 
하루하루가 급변하는 현시점에선 자신의 무덤을 파는 행위라고 볼수있죠."

게임제작에 있어 매우 중요한 요소 < 조기용 - 1999년 7월 8일 >

"3차원 게임에선 이상할 정도로 모두 약속이라도 한듯...
FOV(field of view)를 90도 이상으로 하는데... 
이점이 바로 프로그래머의 고정관념이라는게 바로 제 주장이예요."

3차원 게임에서의 자료구조 < 조기용 >

"1. 3차원 게임에서의 자료 구조에 대해 < 1999년 7월 2일 >
2. 동적인 자료 구조에 대해 < 1999년 7월 2일 >"

D3dIM vs D3dRM < 김성완 - 1999년 6월 30일 >

"Immediate mode는 2차원 스크린상에 그려질 삼차원 물체를 최종적으로 삼각폴리곤 단위로 직접 다 처리해 주어야 하는 모드이고, Retained Mode는 삼차원 물체의 지오 메트리정보와 에니메이션 정보만 넘겨주면 알아서 해주는 모드입니다."

맥워리어3의 그림자 처리방법 < 조기용 - 1999년 6월 24일 >

"S 버텍스값으로 64x64비트맵에 단색으로 랜더링해요.
그 비트맵을 blur 를 해 주고, 그렇게 blur된 비트맵을 로보트 발바닥에 4각페이스로 랜더링 하면 돼요."

Euler Angles < 김성완 - 1999년 6월 23일 >

"Euler Angles는 3차원 공간에서 물체가 취할 수 있는 방향을 나타내는데 사용되는 세개의 각도 값의 조합을 말합니다."

광원 효과 < 김성완 - 1999년 6월 21일 >

"광원효과는 광원을 움직이거나 밝기를 변화시키는 걸 말합니다."

Quake3 범프 매핑 취소 < 김성완 - 1998년 10월 19일 >

"PC GAMER 1998.11월호에 독점기사로 퀘이크3의 전모가 실렸더군요."

인텔의 katmai < 김성완 - 1998년 9월 14일 >

"인텔도 1998년 4/4분기에 발표 예정인 katmai에 3차원 처리 명령어를 추가할 예정"

Portal 렌더링 엔진 소스 < 김성완 - 1998년 7월 25일 >

"Zen이라는 엔진의 링크가 등록되었는데.. 
소스가 완전히 공개되어 있습니다."

메시아의 3차원 모델 처리 < 김성완 - 1998년 7월 6일 >

"'메시아' 에 사용된 기법으로 모델의 폴리곤 수를 거리나 주변 배경의 조건에 따라 유연하게 변화시킨다고 하는 군요. "

듀크 뉴켐 3D 엔진 개발자는.. < 김성완 - 1998년 1월 26일 >

"켄 실버맨이라는 미국 고등학생으로 겐의 래버린스 라는 울펜스타인 3D 형식의 게임을 쉐어로 발표했던 친굽니다."

반응형
반응형

** [강좌] ** [강좌] Quaternion **Quaternion **

copyrightⓒ 김성완(kaswan) [1999년 11월 11일]

3. 단위 쿼터니온과 임의축 회전의 대응

전에 우리는 임의의 벡터 'r' 을 Angular displacement 시킨 결과가 Rr = (cosΘ)r+(1-cosΘ)n(n.r)
+(sinΘ)n×r 이 된다는 것을 알았다. 
더 전에 임의의 복소수에 단위 복소수를 곱한게 결국 임의의 복소수를 복소 평면상에서 회전시키는 것이랑 같다는 것도 알았다.

그렇다면 임의의 쿼터니온에 단위 쿼터니온을 곱한 것은 3차원 공간에서의 회전에 대응될 것인가...? 
답은 거의 그렇다이다.(곱하는 방법이 조금 특이함)

쿼터니온 q = w + xi + yj + zk 가 있을때, 
w는 스칼라 성분으로 나머지는 벡터 성분으로 볼 수 있다.
즉, q = (s, V) 라고 간단히 적을 수 있다. 
이때 물론 s = w 이고 V = xi + yj + zk 이다.

복소수에 공액 복소수가 있듯이 쿼터니온에도 공액 쿼터니온이 있다.
복소수 c = a + bi 의 공액복소수가 c~ = a - bi 로 정의되고..
복소수의 크기 |c| = √(cc~) = √(a²+ b²)로 정의 되듯이.. 
쿼터니온의 경우, 공액쿼터니온은 q~ = (s, -V) 로 정의되고, 쿼터니온의 크기도 마찬가지로 qq~ = s²+ |V|²= |q|² 로 정의된다.
그러므로 단위 쿼터니온은 qq~ = 1 인 쿼터니온이다.

이제 우리의 목표인 Angular displacement와 대등되는 결과가 나오려면.. 
p = (0, r)처럼 벡터성분만 있는 순수 쿼터니온에 qpq~ 처럼 단위쿼터니온과 그의 공액쿼터니온을 앞뒤로 곱해준다.
그러면 qpq~ = (0, (s²- V.V)r + 2V(V.r) + 2 sV x r) 가 되고, q 는 단위쿼터니온이므로 q = (cosΘ,sinΘn), |n| = 1 라고 둘 수 있다.
즉, s = cosΘ, V = sinΘn 이라는 얘기다. 
cos²Θ+ sin²Θ= 1 이므로 말된다.

좌우지간 이걸 위식에 대입하면..

qpq~ = (0, (cos²Θ- sin²Θ)r + 2sin²Θn(n.r) + 2cosΘsinΘn x r)
    = (0, cos2Θr + (1 - cos2Θ)n(n.r) + sin2Θn x r) 이 된다.

이걸 저번에 구해두었던 
Rr = (cosΘ)r + (1 - cosΘ)n(n.r) + (sinΘ) n x r 과 비교해보자. 
Θ에 2가 곱해진것 외에는 동일한 결과가 나왔다. 
이건 다시말하면 벡터 r을 Angular displacement (Θ, n)으로 회전 시키는 것은 Angular displacement를 쿼터니온 공간으로 옮겨와서 단위쿼터니온 q = (cos(Θ/2), sin(Θ/2)n) 로 표시하고 쿼터니온 (0,r) 에다 다음과 같은 계산을 하는 것이다.

q(0,r)q~

결론적으로 말하면 3차원 공간에서 (Θ, n)으로 표시되는 임의 회전축 n에 대한 회전은 쿼터니온 공간(일종의 4차원 공간)의 단위 쿼터니온 (cos(Θ/2), sin(Θ/2)n) 과 같다는 것이다.
2차원 평면에서 Θ만큼 회전 한 것이..

결국 복소평면의 단위복소수 (cosΘ, sinΘ) 에 대응되는 것과 흡사한 결과인 것이다.

그럼 이런 유용한 쿼터니온을 구체적으로 어떻게 활용하는 지는 다음에...

반응형
반응형

** [강좌] Quaternion **
copyrightⓒ 김성완(kaswan) [1999년 7월 13일]

2. 쿼터니온의 유래와 Angular displacement


쿼터니온은 복소수가 확장된 수로 해밀톤이란 위대한 수학자에 의해서 1843년에 발견(?)되었다. 

해밀톤은 복소수가 2차원 평면에 대응된다는 것에 착안하여 3차원 공간에 대응되는 복소수와 유사한 수가 존재할 수 있으리라고 추측했다.
복소수의 실수부와 허수부가 각각 2차원 평면의 X, Y축에 대응된다면 허수부와 비슷한 역할을 하는 항을 하나 더 늘리면.. 
즉, 실수부 하나에 허수부를 둘로 하면 3차원 공간에 대응되는 새로운 수가 만들어 질 것으로 기대했다.

하지만 기대와는 달리 10년을 넘게 매달렸음에도 찾을 수가 없었다. 
1843년 10월 16일 Dublin에 있는 Broome 다리를 건너 왕립 아일랜드 아카데미에서 열리는 회의의 참석차 가는 도중 해밀톤에게 불현듯 영감이 떠올랐고 허수에 해당하는 항을 두개가 아니라 세개로 하면 된다는 것을 깨닫게 되었다.
이때 세개의 허수들은 다음의 성질을 가진다고 가정했다.

i * i = j * j = k * k= -1
i * j = k 
j * i= -k
( i -> j -> k -> i 로 순환하면서 적용됨)

해밀톤은 너무 기쁜 나머지 이 공식들을 다리에다 새기고,
새로운 수: q = a + b * i + c * j + d * k 의 이름을 '넷'이라는 의미의 quaternion 이라고 지었다.

-------------------------------------------------

쿼터니온 이라는 수의 탄생 비화(?)를 간략히 알아 보았는데.. 
과연 쿼터니온 이란 수도 복소수가 2차원 평면에서의 회전에 대응되듯이 3차원 공간에서의 회전이나 방향과 대응되는 성질을 가지는 것일까?
물론 답은 그렇다이다. 
(아니라면 3차원 그래픽에서 이렇게 생소한 수를 사용하지도 않겠지요?^^;)

쿼터니온이 네개의 항으로 구성된다는 건 우리가 저번에 살펴본 Angular displacement 가 네개의 항으로 구성된다는 것과 우연의 일치가 아님을 짐작할 수 있다.

우선 Angular displacement에 대해서 먼저 알아보자.. 
Angular displacement 로 지정되는 회전행렬을 R(Θ, n)라고 하면... 
(여기서 n = (nx, ny, nz) 으로 임의의 회전축을 나타내는 단위벡터이다) 
임의의 벡터 r 을 축 n을 중심으로 Θ만큼 회전시킨 벡터는 Rr 이 될 것이다.

 

 

 

그림에서 처럼 벡터 r을 벡터 n에 수직인 성분 r⊥과 평행한 성분 r〃으로 나누면...
수직인 성분은 r 과 Rr이 만드는 면에 수직으로 지나가고, n 과 r〃에 평행한 성분은 회전후에도 변하지 않는다.

r〃 = (nㆍr)n
r⊥ = r -(rㆍn)n

r⊥은 회전하면 Rr⊥ 이 된다. 
r 과 Rr이 만드는 면에 포함되고 r⊥에 수직인 벡터 V를 만들면

V = n × r⊥ = n × r 이되고,
Rr⊥ = (cosΘ)r⊥ + (sinΘ)V 라고 적을 수 있다.

그러므로...

Rr = Rr〃+ Rr⊥
  = Rr〃+ (cosΘ)r⊥ + (sinΘ)V
  = (nㆍr)n + cosΘ( r -(rㆍn)n ) + (sinΘ) n × r
  = (cosΘ)r + ( 1 - cosΘ )n(nㆍr) + (sinΘ) n × r

이렇게 임의 회전축 n 을 중심으로 Θ만큼 회전한 벡터를 구하는 공식을 얻었다. 
이렇게 조금 복잡해 보이는 공식을 구한 이유는 복소수의 경우 단위길이의 복소수를 곱한 것이 곧 2차원에서의 회전변환에 대응되듯이.. 
쿼터니온의 경우도 단위길이의 쿼터니온을 곱하는 것이 곧 3차원에서의 회전변환에 대응된다는 걸 나중에 보여주기 위해서이다.

▶ 3. 단위 쿼터니온과 임의축 회전의 대응

반응형
반응형

** [강좌] Quaternion **
copyrightⓒ 김성완(kaswan) [1999년 6월 24일]

1. 복소수와 쿼터니온 그리고 회전쿼터니온과 3차원 회전의 연관성을 이해하려면 우선 쿼터니온의 할아버지인 복소수와 2차원 회전의 연관성을 먼저 살펴 보아야 합니다.

복소수(Complex number)야 여러분들이 이미 고등학교 수학에서 배웠으니 잘 아실 테고..

임의의 복소수 C = X + i*Y ( i² = -1 ) 가 있을때.. 
실수 성분 X와 허수 성분 Y를 각각 2차원 평면 좌표계의 x축 좌표와 y축 좌표로 대응시키면 임의의 실수를 수직선상에 표시할 수 있듯이 임의의 복소수를 2차원 평면상에 표시할 수 있지요. 
이런 평면을 복소평면이라고 한다는 것도 배웠을 겁니다.
이때 x축을 실수축, y축을 허수축이라고 하지요.

그럼 복소수와 2차원 회전의 연관성을 알아보지요.
복소평면상의 원점에서 1의 거리에 있는 모든 복소수들을 찍으면 반지름이 1인 단위원이 되죠.
실수축을 기준으로 반시계방향으로 잰 각도를 'θ'라고 하면 복소평면의 단위원상에 있는 복소수들은 R = cosθ + i*sinθ 로 나타낼 수 있습니다.

자! 이제 임의의 복소수 C와 단위원을 나타내는 복소수 R을 서로 곱해봅시다. 
복소수를 곱하는 법은 다들 아시죠? 
(기억이 안나시면 고등학교 수학책 한번 들춰보세요!) 
곱한 결과로 나온 복소수를 C'이라고하면

C' = C*R
  = X*cosθ - Y*sinθ + i*( X*sinθ + Y*cosθ )

이걸 각 성분 별로 적어보면

X' = X*cosθ - Y*sinθ 
Y' = X*sinθ + Y*cosθ

그런데 이건 2차원 평면에서의 회전공식이랑 똑 같네요.
우리는 그냥 복소수끼리 곱하기만 한 건데.. 
결과는 2차원 행백터( x, y )에다 2차원 회전행렬을 곱한 거랑 똑같군요.

             | cosθ  sinθ |
 ( x', y' ) = ( x , y ) * l           l
             | -sinθ   cosθ |

복소평면상에서의 의미를 살펴보면 임의의 복소수 C를 원점을 중심으로 θ 만큼 회전시킨 복소수가 바로 C' 이라는 것이죠.

여기서 우리가 알아낸 사실은 복소수의 곱이 의외로 2차원 회전과 연관되어있다는 겁니다. 
그러면 복소수의 확장인 쿼터니온도 뭔가 회전과 관련성이 있을 것이라고 짐작할 수 있겠죠.

▶ 2. Quaternion의 유래와 Angular displacement

반응형

'수학 (Mathematics) > 3D수학' 카테고리의 다른 글

3. 단위 쿼터니온과 임의축 회전의 대응  (0) 2012.11.02
2. 쿼터니온의 유래와 Angular displacement  (0) 2012.11.02
동차좌표  (0) 2012.11.02
원근투형 TM  (0) 2012.11.02
회전행렬  (0) 2012.11.02
반응형

동차 좌표란 개념이 왜 생겼나?

 

V =     a*Vx + b * Vy + c * Vz    ->    Vector V 

P = r + a*Vx + b * Vy + c * Vz    ->    Vertex P 

 

원점 r 에 관한 정보를 제외 시켜버리면 벡터 V 와 정점 P 는 모두 ( a, b, c ) 이므로

이 둘을 구분할수 없다. 이러한 불편을 해소시키기 위한것이 동차 좌표 개념이다.

이는 3차원 좌표를 3개의 요소로 표시할것이 아니라 차원을 하나 높여 4개의 요소로 표현하자는

것이다.

 

* 여기서 r 은 임의 위치에서 원점 을 가르키는 벡터다. 즉 원점이라 할수 있다.

 

=  a * Vx + b * Vy  + c * Vz + 0 * r       ->      Vector V 는 ( a, b, c, 0 )

P = a * Vx + b * Vy  + c * Vz + 1 * r       ->        Vertex P 는 ( a, b, c, 1 )

 

즉 마지막 요소 가 0 이면 Vector를 나타내고,

마지막 요소가 1이면 정점을 의미 하도록 한것이다.

 

이렇게 함으로써 Vector와 정점을 동일한 방법으로 표현할수 있다.

 

 

 

 

 

좀더 쉽게 접근하기 위해 차수를 내려 2차원 평면의 예를 들어보자.

2차원 평면상의 점 ( 1, 2 ) 를 동차 좌표로 표시하면 ( 1, 2, 1 ) 이 된다.

이는 3차원으로 말하면 Z 축으로 높이 1 의 위치에 있는 점에 해당된다.

 

엄밀히 말해 2차원 평면상의 점을 3차원 공간 상의 직선에 사상( mapping ) 시킨 것이 동차 좌표다.

다시 말해 원점에서 출발해 ( 1, 2, 1 )를 통과하는 모든 3차원 좌표가 동일한 2차원 좌표 ( 1, 2) 를

의미한다.

 

즉 ( 1, 2, 1 ) =  ( 3, 6, 3 ) = ( 4, 8, 4 ) 이 된다.

 

따라서 동차 좌표의 마지막 요소로 앞 요소를 나눈 값이 실제 3차원 좌표가 된다.

 

같은 맥락에서 만일 3차원 동차 좌표를 4차원 ( x, y, z, w ) 좌표로 표시되면 3차원 실제 좌표는

( x / w, y / w, z / w )가 된다. 즉 ( 1, 2, 4, 1 ) = ( 2, 4, 8, 2 ) = ( 5, 10, 20, 5 ) 이며

w = 0 일 경우 그 자체가 Vector ( x, y, z ) 를 나타낸다.

 

 

출처 : http://blog.naver.com/kzh8055/140049456910


반응형

'수학 (Mathematics) > 3D수학' 카테고리의 다른 글

2. 쿼터니온의 유래와 Angular displacement  (0) 2012.11.02
1. 복소수와 쿼터니온 그리고 회전  (0) 2012.11.02
원근투형 TM  (0) 2012.11.02
회전행렬  (0) 2012.11.02
회전 변환  (0) 2012.11.02
반응형

http://egohim.blog.me/70000858060



월드 어딘가에 존재하는 x, y에 대한 x’, y` (위치에 대한 모니터상으로 변환 공식)
————————————————————————————————————————————
x` = ((x-left) 2/right-left) - 1                       - 공식 x`
y’ = ((y-bottom) 2/top-bottom)) -1           - 공식 y`

공식 1과 공식 2는 3차원상의 어딘가의 점 x, y, z 에 대한
z = n (Z에 모니터위치 n) 의 어딘가에 찍히는 점 x`, y`, z` 의 공식이다.

x` (또는 y`) 는 -1 과 1사이 값이며, 곧 중심점 0을 기준으로 좌우측 또는 상하로
1만큼의 값의 x (또는 y)의 위치가 된다.

 

x’와 y` 구하는 공식 (원근이 가미된 투영 공식)
————————————————————————————————————————————
x, y, z를 기준으로 x`, y`, z` 각각의 기울기는 아래와 같다.

직선의 방정식 z = (p)z/(p)x * x 직선의 방정식 에서 z = n으로 대입
x = n(p)x / (p)z          - 원근공식 x

역시 직선의 방정식 z = (p)z/(p)y*y 직선의 방정식에 z = n 대입
y = n(p)y / (p)z          - 원근공식 y

시야절두체의 점은 left <= x <= right, bottom <= y <= top을 만족하므로

이 값을 -1, 1 사이의 값으로 변환 하려면
x` = ((x-left) 2/right-left) - 1(공식x`) 에 x = n(p)x / (p)z (원근공식 x) 를 대입한다.
x` = (( n(p)x / (p)z) -left) 2/right-left) - 1 인수분해
-> x` = 2n/right-left * ((p)x/(p)z) - (right+left/right-left) - 원근투영공식 x’

y’ = ((y-bottom) 2/top-bottom)) -1 (공식y`)에  y = n(p)y / (p)z (원근공식 y)를 대입한다.
y’ = (((n(p)y / (p)z)-bottom) 2/top-bottom)) -1 인수분해 
-> y` = 2n/top-bottom * ((p)y/(p)z) - (top+bottom/top-bottom) - 원근투영공식 y’

x`는 즉 어딘가에 있는 점 x 를 원점을 기준으로 직선을 그엇을때
z = n 에 (모니터가 z축에 위치한 점 n에 해당  ,n은 near) 걸쳐지는 직선상의 점을 x`로 정의 한다.

y`는 즉 어딘가에 있는 점 y 를 원점을 기준으로 직선을 그엇을때
z = n 에 (모니터가 z축에 위치한 점 n에 해당 ,n은 near) 걸쳐지는 직선상의 점을 y`로 정의 한다.

 

 z` 구하는 공식 (기울기가 가미)
————————————————————————————————————————————
z 는 near <= z <= far인데, 이 값을 0,1 사이의 값으로 변환 하여야 한다.
원근투영공식 x’ 와 원근투영공식 y’를 보면 z 값이 분모에 있으므로 아래와 같은 수식을 만족하는
A, B 항을 찾는다.

z` = A / z + B        공식 z` 

near = 0 이며 z = n, z` = 0 을 대입하고,  far = 1 이며 z = f, z` = 1 을 대입

0 = A/n + B      - 공식near 
1 = A/f + B       - 공식far
           (->n = near, f = far)

공식near - 공식far = 1 이므로 정리 해보면
1 = A/f - A/n      =>    1 = A(1/f - 1/n)       =>      1 = A(n-f/fn)      =>      A = fn / n-f
A = fn/n-f       -   공식 z’A

0 = (fn /n - f) / n + B     =>  0 = fn / n(n-f) + B    =>   B = f / f-n
B = f / f-n       -    공식 z`B 

공식  z`에 far의 A와 near의 B를 대입한다.
z` = (fn/n-f)(1/(p)z) + f/f-n

곧 원근투영 공식으로 어딘가의 점 z에 대한 모니터 화면 출력의 z`의 공식이 된다. 
z` = (fn/n-f)(1/(p)z) + f/f-n    - 원근투영공식 z`

 

 동차 좌표계 (homegeneous Coordinates)의

p’4 = (x`(p)z, y`(p)z, z`(p)z, (p)z) 점으로 변환
————————————————————————————————————————————
x`(p)z의 동차좌표계공식에 2n/right-left * ((p)x/(p)z) - (right+left/right-left)  원근투영공식 x’   대입
x`p(z) = (2n/right-left)(p)x - (right+left/right-left)p(z) - 동차좌표계 x`공식

 y`(p)z의 동차좌표계공식에  2n/top-bottom * ((p)y/(p)z) - (top+bottom/top-bottom) 원근투영공식 y’ 대입
y`p(z)=  (2n/top-bottom)(p)y - (top+bottom/top-bottom)(p)z- 동차좌표계의 y`공식

 z`(p)z의 공식에 (fn/n-f)(1/(p)z) + f/f-n = z` 공식 대입
z`p(z) = (-fn/f-n) + (f/f-n)(p)z  - 동차 좌표계의 z`공식 

위 공식 3개를 행렬로 대입시키면, 최종 원근 투영변환의 행렬 공식이 도출된다.
————————————————————————————————————————————
  2n / right - left                         0                                0                                    0
             0                   2n / top -bottomtom                    0                                    0
-(right+left / right-left) -(top+bottom/top-bottom)        far / far - near                        1
             0                                 0                -(far * near) / far - near                   0
————————————————————————————————————————————

right - left = width, top - bottom = height로,  left = -right, bottom = -top 으로 보고
————————————————————————————————————————————
    2n / width                            0                                 0                                    0
             0                      2n / height                             0                                    0    
             0                               0                      far / far - near                             1
             0                               0                 -(far * near) / far - near                    0
————————————————————————————————————————————

반응형

'수학 (Mathematics) > 3D수학' 카테고리의 다른 글

1. 복소수와 쿼터니온 그리고 회전  (0) 2012.11.02
동차좌표  (0) 2012.11.02
회전행렬  (0) 2012.11.02
회전 변환  (0) 2012.11.02
일차 독립, 일차 종속  (0) 2012.11.02
반응형

회전변환에 올렸던 내용중...

x ' = cos(a+b) = cos(a)cos(b) - sin(a)sin(b) = xcos(b) - ysin(b)   (왜냐하면 x=cos(a), y=sin(a)이므로.)

 

인데 여기서

 

이것을 행렬로 바꿔준다면 (다이렉트 기준)

 

        | cos    |     sin  |

(x,y) | ------- | ---------|

        | -sin    |    cos |

 

 이렇게 들어갈 수 있다

 

즉 첫번째 열에 대한 연산이 x' 이 되고 두번째 열에 대한 행렬 연산이 y' 이 된다

반응형

'수학 (Mathematics) > 3D수학' 카테고리의 다른 글

동차좌표  (0) 2012.11.02
원근투형 TM  (0) 2012.11.02
회전 변환  (0) 2012.11.02
일차 독립, 일차 종속  (0) 2012.11.02
3D 벡터 기초 연산  (0) 2012.11.02
반응형

 

[  cos(a+b) + i sin(a+b) ] =[  cos(a) +i sin(a) ] [  cos(b) +i sin(b) ]

는 삼각함수의 합성공식으로 증명할수 있습니다.

임의점은  (x,y)를 (x+iy)= r  [cos(b) + i sin(b) ]와 같이 복소수로 표현할수 있는데

a만큼 회전하면  r [cos(a+b) + i sin(a+b) ]가 되겠죠

위식을 이용하면

 r [cos(a+b) + i sin(a+b) ] =  r  [  cos(a) + i sin(a) ] [  cos(b) +i sin(b) ]

= [  cos(a) + i sin(a) ](x+iy) = xcos(a)-ysin(a) + i [ xsin(a)+ycos(b) ] 가 됩니다.

회전후 x좌표는   xcos(a)-ysin(a)

회전후 y좌표는   xsin(a)+ycos(b)

 

..복소수로 표현하지 않고, 단순히 (x',y')로 나타내도 된다.  또한 반지름을 일반적인 'r'이 아닌 '1'로 하면 더 간단하다.

(x ',y ') = Rotation(x,y)     :

x ' = cos(a+b) = cos(a)cos(b) - sin(a)sin(b) = xcos(b) - ysin(b)   (왜냐하면 x=cos(a), y=sin(a)이므로.)

같은 방식으로 y ' 도 나타낼 수 있다. 

 

출처 : http://blog.naver.com/kjj0124?Redirect=Log&logNo=100048801821

 

 

반응형

'수학 (Mathematics) > 3D수학' 카테고리의 다른 글

원근투형 TM  (0) 2012.11.02
회전행렬  (0) 2012.11.02
일차 독립, 일차 종속  (0) 2012.11.02
3D 벡터 기초 연산  (0) 2012.11.02
왼손 좌표계 vs 오른손 좌표계 의 외적  (0) 2012.11.02
반응형

 

 

일차독립 : 식을 만족하려면 계수들이 0이 되야한다

일차종속 : 식을 만족하기위해서는 계수들이 0 이 아닐 수도 있다

반응형

'수학 (Mathematics) > 3D수학' 카테고리의 다른 글

회전행렬  (0) 2012.11.02
회전 변환  (0) 2012.11.02
3D 벡터 기초 연산  (0) 2012.11.02
왼손 좌표계 vs 오른손 좌표계 의 외적  (0) 2012.11.02
directx 사원수 관련 함수 d3dx9math.h  (0) 2012.11.02
반응형

http://cafe.naver.com/ckgirl/90


[게임프로그래머를 위한 기초 수학과 물리]제4장 벡터연산 [완성]

 




1.  벡터 vs 스칼라

 

 우리가 흔히 하는 셈에서 다루는 값은 스칼라입니다. 그냥 스칼라는 그런수죠. 우리가 초,중,고 다니면서 수학시간에 열심히 계산할때 사용한 대부분의 수. 즉 방향이 없는 크기들입니다..

 벡터는 방향과 크기를 모두 함께 가지고 있는 값입니다. 내가 가고자 하는 목적지가 지금 위치로부터 100미터 떨어져 있다와 북쪽으로 100미터 떨어져있다가 스칼라와 백터의 차이점입니다.

 

거리나 속력은 스칼라값을 말하는 단위입니다. 변위나 속도는 벡터값을 말하는 단위이고요.

변위는 거리라는 스칼라값을 벡터로 표현한것이고 속도는 속력이라는 스칼라값을 벡터로 표현한 것입니다.

시속 100km 는 속력이고 동쪽으로 시속 100km 라고 하면 속도가 되는 것이죠.

 

 벡터의 값에는 방향이 있는데 이것을 다루는 방법을 이야기 하자면 1차원에서는 방향이 2개 입니다. 음수나 양수로 방향을 표시할 수 있습니다. 예를 들어서 오른쪽에서 왼쪽으로 스크롤되는 횡스크롤 게임(D&D같은)이 있다고 할때 캐릭터가 오른쪽으로 가면 양수이고 왼쪽으로 가면 음수가 되는 것입니다.

 마찬가지로 위에서 아래로 종스크롤되는 게임(1945 striker 같은)에서는 위로가면 양수 아래로 가면 음수가 됩니다.

 

 실제 수를 넣어서 문제를 보자면 위아래로만 움직일 수 있는 퐁 게임에서 반사판의 중심이 (20,400)에서 (20,50)까지 움직였다면 변위는 얼마일까요?

 위,아래로만 움직일 수 있기 때문에 x좌표의 값은 변화없이 20으로 고정이 됩니다. 그렇다면 y 값을 살펴볼까요. y의 값이 400 에서 50으로 달라졌네요. 따라서 변위는 -350 입니다.

 

 변위를 다룰때는 방향을 고려하는 것이 매우 중요합니다. 스칼라 양인 거리와 벡터량인 변위는 매우 큰 차이가 있기 때문입니다.  변위를 계산할때 고려해야 할 것은 시작점과 끝점의 위치뿐이고 그 사이에 일어나는 일은 그다지 중요하지 않습니다.

 풋볼경기를 예로 들어보면 다음과 같습니다.

 


[풋볼 선수의 변위]
 
 볼 경기에서 한 선수가 20야드 라인에서 공을 잡고 달리기 시작합니다. 도중에 수비수들을 피해 요리조리 빠져나가며 계속 달려나가다가 50 야드 라인에서 태클을 당했다면 이 선수의 전진 거리로 인정되는건 A라인이 아니라 B 라인이 됩니다. 벡터도 이와 마찬가지입니다. 도중에 지그재그로 가던지 곧바로 가던지 결국 중요한것은 출발점과 도착점 뿐이라는 것이죠.
 
 위의 그림에서 A 값은 스칼라 값이고 B 값은 벡터 값이 되는 것입니다.
=================================================
|      변위
|      ΔX = X2 - X2
================================================= 
 
 자자 그럼 문제 나갑니다.  슈퍼마리오 게임을 하고 있는데 수평위치 200픽셀에서 시작햇습니다. 오른쪽으로 마구마구 이동하다가 250픽셀쯤 왔을때 버섯을 놓친 것을 깨닫고 다시 100픽셀에 있는 버섯을 먹고 왔습니다. 그 후 마리오는 다시 데이지 공주가있는 450 픽셀까지 달려가 공주를 만났다면 이 마리오의 최종 변위는 몇일까요? 또 실제 이동거리는 얼마일까요?
 
 최종변위부터 계산할까요? 시작점이 200픽셀이고 도착점이 450픽셀이니 450 - 200 =  250 간단하죠?
실제 이동거리도 간단합니다. 처음 200픽셀에서 250픽셀까지 갔을때 50픽셀을 이동했고 다시 버섯이 있는 100픽셀까지 이동했으니 150 픽셀을 더 가서 현재까지 200픽셀을 이동했습니다. 그 후에 공주가 있는 450픽셀까지 이동했으니 추가로 350 픽셀을 더 이동했네요. 그래서 실제 이동거리는 550픽셀이 되는 것입니다.
 
 
 
 
 2. 벡터의 기술 방법
 
 앞에서 우리는 1차원 벡터의 방향을 기술할때 양수와 음수만으로 충분하다는 것을 알았습니다.
하지만 2차원과 3차원에서는 이것만으로는 충분하지 않습니다.
 2차원에서 벡터를 기술하는 방법은 2가지가 있습니다. 그것은 바로 극좌표와 데카르트 좌표계입니다. 먼저 극좌표계부터 살펴보겠습니다.
[극좌표로 표현한 벡터 A]
 
극좌표는 벡터가 실제로 어떤 모양인지를 파악하는 가장 쉬운 방법입니다.
===================================================================
|   벡터 A 의 크기를  ||A|| 라 하고, 벡터의 방향을 θ라 할때
|   벡터 A = ||A|| @ θ
===================================================================
 
 
 
데카르트 좌표는 조금 덜 직관적이지만, 벡터를 코딩할때 사용하는 형식입니다.

극좌표와 같이 길이와 방향으로 벡터를 기술하는 대신, 벡터를 수평과 수직 변위로 나타낼 수도 있으며 이것은 데카르트 좌표계의 방식과 매우 유사합니다. 데카르트 좌표를 구성하는 두가지 요소는 수평과 수직성분이며 이렇게 표현한 형식을 i j  형식이라고 합니다.

 

====================================================================

|   데카르트 좌표 (벡터 성분)

|   벡터의 x 축 방향의 단위벡터를  i^ ,  y 축 방향의 단위벡터를 j^ 라고하면,

|   벡터 B = b1 i^  + b2 j^

======================================================================

** 단위벡터를 나타내는 문자가 원래는 i 위에 ^ 이 모자처럼 씌어진 그림입니다만 키보드에서 적절한 문자를 찾을 수 없어서 뒤에다가 썻으니 이점을 숙지하여 다른 책이나 자료를 볼때 혼동하지 마시길바랍니다. 아래 그림을 참고하시기 바랍니다.

 

[데카르트 좌표로 표현된 벡터 B]

 

 

컴퓨터의 화면은 격자 형태로 설정되습니다. 그렇기 때문에 코딩을 할때 데카르트 좌표를 사용합니다.

혹 극좌표를 사용하려고 한다고 해도 결국은 데카르트 좌표로 변환하여 사용해야 합니다. 극좌표에서 데카르트좌표로 변환하는 방법은 아래 그림과 같습니다.

 

[극좌표에서 데카르트 좌표로의 변환]
 
=====================================================
|   극좌표에서 데카르트 좌표로의 변환
|   벡터 A 가 ||A|| @ θ  일때
|   A = b1 i^  +  b2 j^
|   단, b1 = ||A|| cos θ , b2 = ||A|| sin θ
=====================================================
 
 그럼 예문을 하나 보면서 확실히 기억해볼까요?
벡터 A가 변위 벡터이고,  A = 20m @ 30˚ 일때  이 벡터를 데카르트 좌표 형식으로 변환해 보세요.
 
위의 공식을 잘 보세용 먼저 A를 두 요소로 분해하기 위해 사인과 코사인을 사용합니다.
 
b1 =   || A || cos θ    =     20 cos 30˚   =  20(0.8660)  =  17.32
b2 =   || A || sin θ    =    20 sin 30˚   =   20(0.5)   =   10
 
그래서 A = 17.32 i^  +  10 j^ 입니다.
 
 
 반대로 데카르트 좌표를 극좌표로 변환도 가능합니다.
========================================================
|   벡터 B 가   b1 i^ + b2 j^ 일 때,
 ||B|| = √(b1)² + (b2)² ,  θ = tan-1 (b2 / b1)     <--- tan-1 이 아크탄젠트라는거 알고 계시죠? ^^;;
========================================================
 
예제를 하나 살펴볼께요.
벡터 3i^ + 4j^ 를 극좌표로 변화하여 보세요.
 
먼저 B 의 크기를 계산합니다
||B|| = √(b1)² + (b2)²  =  √ 3² + 4²  =  √ 9 +16 = √25 = 5
 
B의 크기를 구한 다음에는 방향을 계산합니다.
θ = tan-1 ( b2 / b1 ) = tan-1 (4/3) = 53.1˚ (근사값입니다.)
 
따라서, 극좌표로는 B = 5 @ 53.1˚ 입니다.
 
 데카르트 좌표를 2차원에서 3차원으로 확장 할 수도 있습니다. 2차원에는 없는 z 축을 추가해주기만 하면 됩니다. 간단하죠? 공식은 다음과 같습니다.
 
====================================================================================
|   3차원 데카르트 좌표 ( 벡터 성분 )
|   벡터의 x 축 방향의 단위벡터를 i^  , y축 방향의 단위벡터를 j^  ,  z 축 방향의 단위벡터를  k^ 라고 하면,
|   벡터 B = b1 i^ + b2 j^ + b3 k^
=====================================================================================
 
 데카르트 좌표 형식의 벡터는 i, j 형식 대신 종종 행렬의 한 열이나 한 행으로 표기 되기도 합니다.
                                                                                    5
예를 들어보면 2차원 벡터 A = 5 i^  +  6 j^  는  [5,6]  또는  [  6  ] 으로 표기할 수 있습니다. 
                                                                                            7
마찬가지로 3차원 벡터 B = 7 i^  +  8 j^  +  9 k^ 는 [ 7, 8 ,9 ] 또는 [ 8 ] 라고 표기할 수 있습니다.
                                                                                            9
 
 
 
 
3 벡터의 합과 차
 
   벡터량을 시각적으로 구성할 때는, 각 벡터에 화살표를 사용하는 것이 일반적입니다. 화살의 길이는 벡터의 크기를 나타내고,  화살표의 끝이 가리키는 방향이 벡터의 방향을 나타냅니다. 화살은 비례에 맞도록 그려야 하기 때문에 모든 벡터가 같은 비례를 가지도록 그리는 것이 중요합니다.  아래의 그림처럼 크기가 5m 인 벡터는 크기가 10m 인  벡터의 절반에 해당하는 길이를 가지게 됩니다. 

[화살 표로 표현한 두 벡터]
 
 
벡터를 화살표로 표시할 때,  화살표의 촉 부분을 끝점이라고 하고 그 반대쪽을 시작점이라고 부릅니다.
벡터는 어느 한점에 고정된것이 아니기 때문에 화살표의 길이와 방향만 같다면 어디든지 이동이 가능합니다. 아래의 그림처럼 끝점이 같은 두 벡터 A 와 B에서 벡터 B의 끝점을 벡터 A의 시작점으로 옮기는 것도 가능합니다.

[벡터 A의 끝점과 벡터 B의 시작점을 일치하록 옮긴 벡터의 그림]

 

 

  두 벡터의 시작점과 끝점을 일치하도록 만들었다면, 움직이지 않은 벡터의 시작점과 움직인 벡터의 끝점을 연결하여 새로운 벡터를 그리면 이 새 벡터가 바로 두 벡터의 합입니다.


[ 벡터 A 와  벡터 B 의 합 ]
 
이렇게 벡터의 합을 구할때  둘중 어떤 벡터를 옮기더라도 새롭게 만들어지는 합의 벡터는 언제나 같습니다.
즉 벡터의 합에는 교환법칙이 성립한다는 이야기가 되는 것이죠.

[ A + B  =  B + A ]
 
 
=============================================
|   벡터 합의 교환법칙
|   임의의 벡터 A, B 에 대하여,
|   A + B  =  B + A
=============================================
 
 위의 그림에서 각각의 벡터 A 가 5m 라고 가정하고  벡터 B가 6m 라고 가정할때 A+B 의 벡터의 길이는 어떤가요? A=5 이고 B=6 이니 A+B =11 이라고 생각하기 쉽지만 그림을 잘 보시면 새롭게 만들어진 붉은 벡터가 기존의 두개의 검은 벡터를 더한것보다 짧게 보이죠? 이 것은 벡터의 방향이 고려되었기 때운입니다.
 
결국 방향이 같지 않다면  || A+B || ≠ ||A|| + ||B||   라는 말이 됩니다.
 
그래서 극 좌표로 표현된 벡터는 같은 방향이 아닌이상 항상 데카르트 좌표로 변환하여 더해야 합니다.
두 벡터가 데카르트 좌표로 표현되었다면, 같은 성분의 벡터끼리 더하기만 하면 됩니다.
 다시말해서 두개의 i^ 와 두개의 j^를 더하는 것이죠.
 
=================================================================
|  두 벡터의 합 계산
|  두 벡터 A = a1 i^ + a2 j ^  ,    B = b1 i^ + b2 j^ 에 대하여,
 A + B = ( a1 + b1 ) i^  +  (a2 + b2) j^
================================================================= 
 역시 예제를 살펴보면서 확실히 이해해 봅시다.
두 벡터 C = 8i^ + 3j^ ,   D = 5i^ + 12j^ 에 대하여, C+D를 구하세요.
 
 먼저 이 두 벡터를 그린후에 D의 시작점을 C의 끝점으로 옮깁니다. 거듭 강조하지만 벡터를 옮기는 과정에서 길이와 방향이 변하지 않도록 주의해 주세요.
 C 의 시작점과 D의 끝점을 이어서 새로운 벡터 C + D 를 그려줍니다. 그림은 아래와 같습니다.

 [ 벡터 C + D ]
 
C + D 를 계산하는 방법은  x축 방향으로의 총 이동량과  y축 방향으로의 총 이동량을 계산하는 것입니다.  즉 두개의 i^와 두개의 j^ 를 각각 성분별로 더하는 것이죠.  이 경우에는, 다음과 같이 계산할 수 있습니다.
 
C + D = (8+5) i^ + (3+12) j^  =  13 i^ + 15 j^
 
 벡터의 합을 구하는 이같은 방법은 3차원에서도 그대로 적용됩니다. 마찬가지로 3차원에서의 벡터의 합을 계산하려면 벡터는 반드시 데카르트 좌표 형식이어야 합니다.
 
=============================================================================
|  3차원 벡터의 합 계산
|  두 벡터 A = a1 i^ + a2 j^ + a3 k^,    B = b1 i^ + b2 j^ + b3 k^ 에 대하여,
|  A + B = (a1+b1) i^ + (a2+b2) j^ + (a3+b3) k^
=============================================================================
 
 지금까지 보아온 벡터의 합과 같은 방법으로 두 벡터의 차도 구할 수 있습니다. 각 성분의 합을 구한것처럼 각 성분의 차를 구하면 됩니다. 2차원과 3차원에서의 벡터의 차 공식 나갑니다!!!!!!!!]
 
=================================================================
|  두 벡터 사이의 차 계산
|  두 벡터 A = a1 i^ + a2 j ^  ,    B = b1 i^ + b2 j^ 에 대하여,
 A - B = ( a1 - b1 ) i^  +  (a2 - b2) j^
================================================================= 
=============================================================================
|  3차원 벡터의 차 계산
|  두 벡터 A = a1 i^ + a2 j^ + a3 k^,    B = b1 i^ + b2 j^ + b3 k^ 에 대하여,
|  A - B = (a1-b1) i^ + (a2-b2) j^ + (a3-b3) k^
=============================================================================
 
 
 
4. 벡터의 스칼라 곱
 
 우리들은 지금까지 공부하면서 수많은 종류의 곱셈을 해왔습니다. 양수끼리의 곱셈, 음수와 양수의 곱셈, 정수와 소수와 곱셈 등등등.......  이들 곱셈은 모두 스칼라값과 스칼라값 사이의 곱셈이었습니다.  이제 위에서 배운 백터를 써먹을 때가 됬네요.  바로 벡터와 스칼라의 곱셈을 할 차례입니다!!!!
 벡터에 스칼라를 곱한다는 것은 벡터의 크기를 늘리거나 줄이는 결과를 가져옵니다. 곱하는 스칼라가 1보다 크다면 벡터는 커지고, 스칼라가 1보다 작다면 벡터의 크기는 작아집니다.
 
============================================================================
|   극좌표 형식 벡터의 스칼라 곱
|   임의의 벡터 A = c ||A|| @ θ 에 대하여,
|   cA = c ||A|| @ θ
============================================================================
 
 예제를 하나 살펴볼까요?
 벡터 A = 3ft @ 22˚ 일때 5A 를 구하세요.
 
위의 공식에 바로 대입해 볼께요.
5A = 5(3ft) @ 22˚ = 15ft @ 22˚
 
벡터가 극좌표의 형식이 아닌 데카르트좌표 형식으로 되어 있어도 극좌표로 변환하지 않고 스칼라 곱을 구할 수 있는 방법이 있습니다.  각 성분별로 스칼라를 곱하기만 하면 됩니다. 공식은 아래와 같습니다.
 
=============================================================================
|  데카르트 형식 벡터의 스칼라 곱
|  임의의 스칼라 c와 임의의 벡터 A = a1 i^ + a2 j^ 에 대하여,
|  cA = ca1 i^ + ca2 j^
=============================================================================
 
예제 고고싱~~~!!!
벡터 A = 12 i^ + 4 j^ 일때, 1/2A 를 구하세요.
 
바로 공식에 대입합니다.
1/2A = 1/2(12 i^) + 1/2(4 j^) = 6 i^ + 2 j^
 
 
 프로그래밍에서는 정규화(normalization)라는 용어를 종종 쓰이곤 합니다. 이 용어는 벡터의 크기를 1로 맞추는 것을 뜻합니다. 벡터의 정규화는 벡터의 크기보다는 벡터의 방향만을 필요로 할 때 이용됩니다. B = i^ + j^ 에서 i^는 x 축의 양의 방향을,  j^ 는 y축의 양의 방향을 가리키는 크기가 1인 벡터입니다.
 
 벡터의 정규화는 벡터가 극좌표 형식일때는 매우 간단합니다. 단지 벡터의 크기를 1로 바꾸고 방향을 변경하지 않으면 됩니다. 예를 들어 3m @ 15˚ 의 벡터가 있다면 1m @ 15˚ 가 되는 것이죠. 너무 간단하죠? ^^;
 
 그렇지만 프로그래밍에서는 데카르트좌표로 표현되는 경우가 많습니다. 이런 경우에는 벡터의 크기를 계산하여 각 성분을 크기로 나누면 됩니다.
 
==============================================================================
|  2차원 벡터의 정규화
|  임의의 벡터 A = [a1 a2] 에 대하여
|  A^  = ( 1 / ||A|| ) A = [ a1 / ||A||    a2 / ||A|| ]
==============================================================================
 
==============================================================================
|  3차원 벡터의 정규화
|  임의의 벡터 A = [a1  a2  a3 ] 에 대하여,
|  A^ = ( 1 / ||A|| ) A = [ a1 / ||A||    a2 / ||A||    a3 / ||A|| ]
============================================================================== 
** 정규화된 벡터 표시인 A^ 역시 위의 i^, j^  와 마찬가지고 기호가 문자 위에 모자처럼 씌어야하는 것임을 알려드립니다.
 
 예제를 하나 볼까용?
 벡터 A = [5  0  -12] 를 정규하 하세요.
 
 가장먼저 해야 할 일은 A의 크기를 구하는 것입니다.
 ||A|| = √ 5² + 0² + (-12)²  =  √ 25 + 0 + 144 = √ 169 = 13
 
이제 크기를 알았으니 벡터의 각 성분을 크기로 나눕니다.
A^ = [ a1 / ||A||    a2 / ||A||   a3 / ||A|| ]  =  [ 5/13  0/13  -12/13 ]
 
벡터를 정규화 한 후에 답이 맞는지 검산하려면 ||A^|| 를 구해보면 됩니다. 이 결과는 항상 1이 나와야 합니다.
 
 
 
5. 벡터의 내적
 
 두 벡터의 내적은 그 결과가 항상 스칼라 값이 나옵니다. 그래서 다른 이름으로 스칼라적 이라고 부르기도 합니다. 
 
======================================================================
|  2차원 벡터의 내적
|  임의의 2차원 벡터 A = [ a1  a2 ] ,  B = [ b1  b2 ] 에 대하여,
|  A●B = a1 b1 + a2 b2
======================================================================
 
========================================================================
|  3차원 벡터의 내적
|  임의의 3차원 벡터 A = [ a1  a2  a3 ],  B = [ b1  b2  b3 ] 에 대하여,
|  A●B = a1 b1 + a2 b2 + a3 b3
========================================================================
 
벡터의 내적은 수 많은 정보를 제공합니다. 그 중 가장 먼저 살펴볼 부분이 바로 벡터의 내적을 통해 두 벡터 사이의 각을 구할 수 있다는 것입니다. 만일 두 벡터의 내적의 값이 0이다면 두 벡터는 서로 직교한다는 것을 알 수 있습니다. 그리고 두 벡터의 내적의 값이 0 보다 작다면 두 벡터 사이의 각은 90도 보다 큰것이고 0보다 크다면 두 벡터 사이의 각은 90도 보다 작게 되는 것입니다.
 
=========================================================================
내적의 부호
두 벡터 A 와  B 사이의 각을 θ 라고 할 때,
A●B < 0 이면 , θ > 90˚
A●B = 0 이면 , 서로 직교
A●B > 0 이면 , θ < 90˚
=========================================================================
 
 게임상에서 카메라의 위치가 (1,4)이고, 벡터 C = [ 5  3 ] 가 이 카메라의 방향을 나타내고 있습니다. 이 때 어떤 물체의 위치가 (7,2)이고 이 카메라의 시야가 90˚라면 이 물체는 카메라의 시야에 들어올까요?
 

[ 카메라의 시야 ]
 
먼저 위의 그림과 같이 카메라의 위치에서 물체의 위치를 가리키는 벡터를 구해야 합니다. 이 벡터를 D = [(7-1)  (2-4)] = [ 6  -2 ] 라고 합니다. 이제 벡터 C 와 벡터 D를 내적합니다.
 
 C●D = 5(6) + 3(-2) = 30 - 6 = 24
 
두 내적의 결과가 양수이므로 두 벡터 사이의 각 θ 는 90˚ 보다 작음을 알 수 있습니다. 카메라의 시야가 90˚이므로 이 물체는 카메라의 시야에 들어옴을 알 수 있습니다.
 
 간단한 계산만으로 두 벡터 사이의 각이 90˚ 에 대하여 큰지 작은지, 혹은 직교하는 지를 알 수 있었습니다. 만일 두 벡터 사이의 정확한 각을 구할 때에도 내적을 통해 알 수 있습니다.
 
===============================================================
|   두 벡터 사이의 각
|   임의의 두 벡터 A, B 사이의 각을 θ 라 하면,
|   A●B = ||A|| ||B|| cos θ
===============================================================
 
 예제를 볼께요.
 캐릭터가 벡터 C = [5  2  -3 ]가 가리키는 방향으로 이동중이었습니다. 그런데 플레이어가 새로운 목적지를 설정해 주어서 벡터 D = [8  1  -4 ]가 가리키는 방향으로 이동하게 되었습니다.  이 캐릭터는 얼마의 각을 꺽어야 새로운 경로로 이동 할 수 있을까요?
 
 위의 공식에 대입하려면 먼저 두 벡터의 내적을 구해야 합니다.
 C●D = 5(8) + 2(1) -3(-4) = 40 + 2 + 12 = 54
 
 이제 두 벡터의 크기를 각각 구해줍니다.
 ||C|| = √5² + 2² + (-3)² = √25 + 4 + 9 = √38
 ||D|| = √8² +1² + (-4)² = √64 + 1 + 16 = √81
 
이제 각각의 결과를 공식에 대입합니다.
C●D = ||C|| ||D|| cos θ
54 = (√38)(√81) cos θ
54 / (√38)(√81) = cos θ
54 / ( 6.16 * 9 ) = 54 / 55.44 = cos θ
θ = 13.08˚  <---근사값입니다.
 
따라서 이 캐릭터는 13.08˚ 꺽어서 움직이면 됩니다.
 
 
 
6. 벡터의 외적
 
 내적은 벡터를 곱하는 방법에 해당합니다. 이번에는 외적을 다뤄볼 차례 입니다.  내적과 외적의 가장 큰 차이점이라면 결과값의 형태이겠네요.  내적은 결과값이 스칼라이고 외적의 결과는 벡터입니다.
 
============================================================
|  외 적
|  임의의 두 벡터 A = [a1 a2 a3],  B = [b1 b2 b3]에 대하여,
|  A x B = [(a2b3 - a3b2) (a3b1 - a1b3) (a1b2 - a2b1)]
============================================================
 
예제를 하나 볼께요
 두 벡터 A = [ 5  -6  0 ],  B = [1  2  3 ]의 외적을 구하세요.
 
외적의 결과는 또 다른 벡터가 나오므로, 위의 공식을 사용하여 각 성분을 계산하면 됩니다.
A x B = [(a2b3 - a3b2)  (a3b1 - a1b3)  (a1b2 - a2b1)]
         = [(-6(3) - 0(2))   (0(1) - 5(3))   (5(2) - -6(1)) ]
         = [ (-18-0)  (0-15)  (10+6) ]
         = [-18  -15  16 ]
 
 
외적의 가장 중요한 성질은 바로 외적의 결과로 만들어진 벡터가 원래 두 벡터와 모두 직교하는 벡터라는 것입니다. 이러한 이유 때문에 외적은 3차원 벡터에 대해서만 정의 됩니다.
 
================================================================
|  직교 벡터
|  A x B 는 두 벡터  A, B 에 모두 수직
================================================================

[ 직교 벡터 ]
 
벡터 A 와 B 를 포함하는 평면에는 수직인 두개의 방향이 있습니다. 바로 위쪽과 아래쪽이죠. 외적의 결과 주어지는 벡터를 결정하는데 오른손 법칙을 쓸 수 있습니다. 손가락을 벡터 A와 B가 교차하는 부분에 두고 손가락을 벡터 A와 같은 방향으로 둡니다.  그런 후에 손가락이 벡터 B를 향하도록 구부리면,  이때 엄지가 향하는 방향이 AxB 의 방향입니다. 반대로 A와 B의 순서를 바꾸어 시도해보면 BxA는 방향이 정반대라는 것을 알 수 있습니다. 그래서 외적은 교환법칙이 성립하지 않습니다.
 
=====================================================================
 외적은 교환법칙이 성립하지 않음
|  A x B ≠ B x A
|  단, 임의의 3차원 벡터 A , B에 대해서 A x B = -(B x A)
=====================================================================
 
 외적은 결과가 원래의 두 벡터와 수직인 세번째 벡터를 만든다는 독특한 성질 덕뿐에 표면 법선(surface normal)을 계산하는데 사용할 수 있습니다. 임의의 두 3차원 벡터는 하나의 면을 정의합니다. 표면 법선은 주어진 면에 수직인 길이가 1인 벡터를 말합니다.
 
============================================================
|  표면 법선
|  임의의 두 3차원 벡터 A, B에 대하여,
|  표면 법선 = (A x^ B) = AxB / ||AxB||
=============================================================
**위의 공식에서 x^ 또한 위의 벡터의 부호처럼 ^ 이 x 위에 모자처럼 씌어져야 합니다
 
역시 예제를 살펴보면 실력을 다져 볼까요?
두 벡터 A = [5  -2  0 ], B = [1  2  3 ]으로 정의되는 면이 있을때, 이 면과 충돌한 물체의 운동을 결정하는데 사용할 수 있도록 표면 법선을 구하십시오.
 
외적의 결과는 주어진 두 벡터와 직교하는 새로운 벡터이죠? 먼저 외적을 합니다.
A x B = [ (a2b3 - a3b2)  (a3b1 - a1b3)  (a1b2 - a2b1) ]
          = [ (-2(3) - 0(2))   (0(1) - 5(3))   (5(2) - -2(1)) ]
          = [ (-6 - 0)   (0 - 15)   (10 + 2) ]
          = [ -6  -15  12 ]
 
외적을 구했으니 이제 외적의 크기를 구합니다.
||A x B|| = √(-6)² + (-15)² + (12)²
             = √36 + 225 + 144
             = √405
             = 20.125 
 
이제 공식에 대입하면 됩니다.
[ -6/20.125   -15/20.125   12/20.125 ] = [0.298   0.745   0.596 ]
 
 
이미 위에서 두 벡터 사이의 각을 내적을 사용하여 구하는 법을 배웠습니다. 각을 구하는 데에는 내적이 더 빠릅니다만 이미 외적의 값을 알고 있다면 외적을 사용하여 각을 구하는 법을 사용하는것이 좋습니다.
 
=========================================================================
|   두 벡터 사이의 각(외적)
|   임의의 두 3차원 벡터 A, B에 대하여
|   ||AxB|| = ||A|| ||B|| sin θ
=========================================================================
 
자 예제 나갑니다. 단 이번에는 풀이가 없고 답만 알려드릴께요. 한번 직접 풀어보시고 답이랑 맞는지 맞춰보세요 ㅋㅋㅋ
 
<문제> 두 벡터 A = [5  -2  0],  B = [1  2  3] 사이의 각을 구하세요.
<답> 약 87.2˚ 
 
////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
//////
 
에고 에고 평상시보다 양이 배는 많은것 같네 ㅠㅠ 갈수록 올리는 속도가 느려지네 -.-a
 



 









아래 설명의 출처 Direct 3D 기초 수학 #1 벡터 |작성자 야누스


Direct 3D 기초 수학 #1 벡터





* 벡터 : 크기와 방향을 가지는 물리량

* 포인트 (점,Vertex): 한점또는 위치만을 가진다

* 스칼라(Scalar :  크기 . 길이등 한가지만을 표현할때 사용

* 단위벡터 : 크기가 1인 벡터 표기는 ||V|| 와 같이한다.

                         - 단위벡터는 광선의 방향,  편명의 법선방향 , 카메라의 방향등 방향을 나타낼때

                            사용된다 크기가 1이 아닌 벡터를 단위벡터로 만들어주는 과정을 정규화(Normalize)

                            라고 하며 벡터를 자신의 크기로 나눠줌으로 얻을수 있다

                             벡터의크기 : 벡터 U의 크기 ||U|| = sqrt(Ux^,Uy^,Uz^);

                             단위벡터       :  U / ||U|| ;

*내적의 정의 : 내적의 곱의 결과값은 스칼라이므로 스칼라곱(scalar product)이라고 한다 .

 

두개 의 벡터 A , B 의 내적을 구해보자

∮(각 세타이다)

내적구하는공식

A * B = = AxBx + AyBy + AzBz ;

두벡터간의 사이갓을 구하는공식

A * B = || A || * || B || cos∮  = cos∮ = A * B / || A || || B ||  =

         ∮ = 1/cos(A * B / || A || || B ||)  ;

 

두벡터의 사잇각의 관계

 

A * B = 0  이면  A ⊥ B 이다

A * B > 0   이면  사잇각은 90보다 작다 

A * B < 0 이면 사잇각은 90 보다 크다

 

A 투영 B ( B에 평행한 분해 벡터) = ((내적) / (B의 Length) * (B의 Length)) * B벡터 ;

A 수직 B ( B에 수직한 분해 벡터 ) = A -  ((내적) / (B의 Length) * (B의 Length)) * B벡터 ;

 

외적의 정의 : 원전에 접선된 두개의 접선벡터에 수직한 벡터를 결과로 갖는 값 .

                          법선벡터를 구할때 사용한다 .

 

한평면의 세점 A , B , C 에 대하여 A(Ax,Ay,Az),B(Bx,By,Bz) ,C(Cx,Cy,Cz)에 대하여

점 A를 기준으로 점 B 와 C 에 대한 벡터를 각각 U , V 라 할때 수식을 통하여 벡터를 구할수잇다

 

U = B(Bx,By,Bz) - A(Ax,Ay,Az) = [Bx -Ax , By - Ay , Bz - Az];

V = C(Cx,Cy,Cz) - A(Ax,Ay,Az) = [Cx - Ax , Cy - Ay, Cz - Az];

두벡터간의 법선 벡터를 구하면 외적을 구할수 있다

외적구하는 공식

x = Uy * Vz - Uz * Vy;

y = Uz * Vx - Ux * Vz;

Z = Ux * Vy - Uy * Vx;       새로운 벡터 E(Ex,Ey,Ez) 두벡터 U,V에 직각인 법선벡터이다 .

 

D3DX에서 사용되는 함수 이다 ,  D3DXVECTOR3 클래스는 라이브러리에서 지원되는 클래스이다

 

크기 : float D3DXVec3Length(D3DXVECTOR* pV);

설명 : 반환값은 스칼라이고 전달인자는 벡터의 &(포인터)이다.

ex) float magnitude = D3DXVec3Length(&V);

 

단위벡터(Normalize : 정규화) :

D3DXVECTOR3* D3DVec3Normalize(D3DXVECTOR3* pOut,D3DXVECTOR3* pV);

설명 : 반환값은 벡터의 포인터 형태이고 전달인자는 정규화가 끝난 값을 보관할 벡터의 포인터형과 정규화할 벡터의 포인터형태이다

ex) D3DXVECTOR3 U = D3DXVec3Normalize(&pOut,&pV);

 

내적(Dot product) float D3DXVec3Dot(D3DVECTOR3* pV1 , D3DVECTOR3* pV2);

설명 : 반환값은 스칼라이며 인자는 왼쪽의 피연산벡터의 포인터 , 오른쪽 피연산벡터의 포인터이다

ex)float result  = D3DXVec3Dot(&pV1, &pV2);

 

외적(Corss product) :

 D3DVECTOR3* D3DXVec3Cross(D3DXVECTOR3* pOut,D3DVECTOR3* pV1,D3DVECTOR3* pV2);

설명 : 반환값은 연산이 완료된 벡터의 포인터이고 인자는 리턴하기전 결과를 저장할 벡터의 포인터, 왼쪽 피연산벡터의 포인터 , 오른쪽 피연산벡터의 포인터);

ex D3DVECTOR3 Cross = D3DXVec3Cross(&pOut,&pv1 , &pv2);

 

기억하면 좋을 사항

 

외적은 교환법칙이 성립되지않는다 , U  * V  = - (V * B) 이다

벡터의 곱이 스칼라 이면 내적이고 벡터의 곱이 벡터이면 외적이다


반응형

'수학 (Mathematics) > 3D수학' 카테고리의 다른 글

회전 변환  (0) 2012.11.02
일차 독립, 일차 종속  (0) 2012.11.02
왼손 좌표계 vs 오른손 좌표계 의 외적  (0) 2012.11.02
directx 사원수 관련 함수 d3dx9math.h  (0) 2012.11.02
GPU 에서 노멀맵 굽기  (0) 2012.11.02
반응형




블로그 이미지

3DMP engines

3D그래픽스 물리 수학, 프로그래밍 GPU Shader 게임엔진 알고리즘 디자인패턴 matlab etc..




실제로 Direct 와 Opengl(수학좌표계) 에서의 외적 연산은 동일하다

 

연산은 동일한데 포인트는, 기본 좌표계에따라 외적의 방향이 달라진다는 것

 

 

 

 


이하 첨부내용

 

http://blog.naver.com/9992028/120020809381

 

왼손 좌표계 vs 오른손 좌표계
OpenGL은 오른손 좌표계를 쓰고,
DirectX는 왼손 좌표계를 쓴다.

사실
DirectX를 쓰면서도 오른손 좌표계를 쓰거나,
OpenGL을 쓰면서 왼손 좌표계를 사용하는 것도 가능하다.

다만 기본값이 그렇게 되어 있다는 것이고,
따라서 각각의 좌표계에 좀 더 편리하게 API가 제공되는 것일 뿐이지만 말이다.

간단하게 다음과 같이 이해하자.

일단 수학적으로는 다음과 같이 정의 된다.

기저 vector, V1, V2, V3가 있을 때.. (간단하게 x, y, z 방향이라 생각해도 된다.)
(V1 X V2) · V3 > 0 이면 오른손 좌표계
(V1 X V2) · V3 < 0 이면 왼손 좌표계이다.

정규 직교 좌표계로 한정 (세 기저 vector가 서로 직각인 경우) 지어서
기저 vector, Vx, Vy, Vz가 있을 때..
(Vx X Vy) = Vz 이면 오른손 좌표계
(Vx X Vy) = -Vz 이면 왼손 좌표계이다.

따라서 

OpenGL의 경우 (오른손 좌표계인 경우)
x, y 방향의 기저 vector을 아는 경우 z 방향의 기저 vector는 -(Vx X Vy)로 구하고,

DirectX의 경우 (왼손 좌표계인 경우)
x, y 방향의 기저 vector을 아는 경우 z 방향의 기저 vector는 (Vx X Vy)로 구하면 되겠다.
 
 
 
 
< 자료출처>  http://mobile.egloos.com/1848128

반응형

'수학 (Mathematics) > 3D수학' 카테고리의 다른 글

일차 독립, 일차 종속  (0) 2012.11.02
3D 벡터 기초 연산  (0) 2012.11.02
directx 사원수 관련 함수 d3dx9math.h  (0) 2012.11.02
GPU 에서 노멀맵 굽기  (0) 2012.11.02
표면 스케터링으로 실시간 근사  (0) 2012.11.02
반응형

d3dx9math.h 의 내용

 

//--------------------------

// Quaternion

//--------------------------

 

// inline

 

FLOAT D3DXQuaternionLength

( CONST D3DXQUATERNION *pQ );

 

// Length squared, or "norm"

FLOAT D3DXQuaternionLengthSq

( CONST D3DXQUATERNION *pQ );

 

FLOAT D3DXQuaternionDot

( CONST D3DXQUATERNION *pQ1, CONST D3DXQUATERNION *pQ2 );

 

// (0, 0, 0, 1)

D3DXQUATERNION* D3DXQuaternionIdentity

( D3DXQUATERNION *pOut );

 

BOOL D3DXQuaternionIsIdentity

( CONST D3DXQUATERNION *pQ );

 

// (-x, -y, -z, w)

D3DXQUATERNION* D3DXQuaternionConjugate

( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ );

 

 

// non-inline

#ifdef __cplusplus

extern "C" {

#endif

 

// Compute a quaternin's axis and angle of rotation. Expects unit quaternions.

void WINAPI D3DXQuaternionToAxisAngle

( CONST D3DXQUATERNION *pQ, D3DXVECTOR3 *pAxis, FLOAT *pAngle );

 

// Build a quaternion from a rotation matrix.

D3DXQUATERNION* WINAPI D3DXQuaternionRotationMatrix

( D3DXQUATERNION *pOut, CONST D3DXMATRIX *pM);

 

// Rotation about arbitrary axis.

D3DXQUATERNION* WINAPI D3DXQuaternionRotationAxis

( D3DXQUATERNION *pOut, CONST D3DXVECTOR3 *pV, FLOAT Angle );

 

// Yaw around the Y axis, a pitch around the X axis,

// and a roll around the Z axis.

D3DXQUATERNION* WINAPI D3DXQuaternionRotationYawPitchRoll

( D3DXQUATERNION *pOut, FLOAT Yaw, FLOAT Pitch, FLOAT Roll );

 

// Quaternion multiplication. The result represents the rotation Q2

// followed by the rotation Q1. (Out = Q2 * Q1)

D3DXQUATERNION* WINAPI D3DXQuaternionMultiply

( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ1,

CONST D3DXQUATERNION *pQ2 );

 

D3DXQUATERNION* WINAPI D3DXQuaternionNormalize

( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ );

 

// Conjugate and re-norm

D3DXQUATERNION* WINAPI D3DXQuaternionInverse

( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ );

 

// Expects unit quaternions.

// if q = (cos(theta), sin(theta) * v); ln(q) = (0, theta * v)

D3DXQUATERNION* WINAPI D3DXQuaternionLn

( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ );

 

// Expects pure quaternions. (w == 0) w is ignored in calculation.

// if q = (0, theta * v); exp(q) = (cos(theta), sin(theta) * v)

D3DXQUATERNION* WINAPI D3DXQuaternionExp

( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ );

// Spherical linear interpolation between Q1 (t == 0) and Q2 (t == 1).

// Expects unit quaternions.

D3DXQUATERNION* WINAPI D3DXQuaternionSlerp

( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ1,

CONST D3DXQUATERNION *pQ2, FLOAT t );

 

// Spherical quadrangle interpolation.

// Slerp(Slerp(Q1, C, t), Slerp(A, B, t), 2t(1-t))

D3DXQUATERNION* WINAPI D3DXQuaternionSquad

( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ1,

CONST D3DXQUATERNION *pA, CONST D3DXQUATERNION *pB,

CONST D3DXQUATERNION *pC, FLOAT t );

 

// Setup control points for spherical quadrangle interpolation

// from Q1 to Q2. The control points are chosen in such a way

// to ensure the continuity of tangents with adjacent segments.

void WINAPI D3DXQuaternionSquadSetup

( D3DXQUATERNION *pAOut, D3DXQUATERNION *pBOut, D3DXQUATERNION *pCOut,

CONST D3DXQUATERNION *pQ0, CONST D3DXQUATERNION *pQ1,

CONST D3DXQUATERNION *pQ2, CONST D3DXQUATERNION *pQ3 );

 

// Barycentric interpolation.

// Slerp(Slerp(Q1, Q2, f+g), Slerp(Q1, Q3, f+g), g/(f+g))

D3DXQUATERNION* WINAPI D3DXQuaternionBaryCentric

( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ1,

CONST D3DXQUATERNION *pQ2, CONST D3DXQUATERNION *pQ3,

FLOAT f, FLOAT g );

 


반응형

+ Recent posts