상세 컨텐츠

본문 제목

커브와 매트릭스

Maya_Plugin_Development /hCurve

by hwano 2014. 3. 26. 14:09

본문

 

두서없지만 적어놓고 나중에 정리하자.

 

어떤 오브젝트를을 curve주위로 배열할때 원래 오브젝트의 매트릭스값에다가

curve에서 뽑아낸 매트릭스 값을 곱해주는 건 알겠는데

 

paraMatrix( 0, 0 ) = normal.x;
paraMatrix( 0, 1 ) = normal.y;
paraMatrix( 0, 2 ) = normal.z;
paraMatrix( 1, 0 ) = tangent.x;
paraMatrix( 1, 1 ) = tangent.y;
paraMatrix( 1, 2 ) = tangent.z;
paraMatrix( 2, 0 ) = cross.x;
paraMatrix( 2, 1 ) = cross.y;
paraMatrix( 2, 2 ) = cross.z;
paraMatrix( 3, 0 ) = paraPosition.x;
paraMatrix( 3, 1 ) = paraPosition.y;
paraMatrix( 3, 2 ) = paraPosition.z;

 

이런식으로 매트릭스를 만들어서.

 

보통 이렇게 계산할 때 노말, 탄젠트 등을 노말라이즈하여 진행하기 때문에

저것의 의미는 이렇다.

 

profile용 circle 커브를 예를 들면

x에 노말, y에 탄젠트, z에 외적값이 들어간 거기 때문에

 

circle x축이 노말방향을 향하고 y축이 탄젠트방향을 향하고 z축이 외적방향을 향하게 된다.

 

 

0326_matrixTest.mb

 

//////////////////////////////////////////////////////////////////////////

 

위 값을 적용을 해보면

 

 

아래 그림처럼 profile curve가 뒤집어진 결과를 얻을 수 있다.

이는 path curve가 S자를 그리게 되면 곡률이 휘어지는 안쪽방향을 가리키는 normal이

양쪽으로 뒤집어 지기 때문이다.

 

때문에 이를 방지 하려면 normal을 오른쪽, 왼쪽 중 한쪽으로 정렬을 해야 한다.

오른쪽 왼쪽은 흔한 방법으로 내적을 이용하면 될테고 내적계산에 필요한 벡터하나가 필요해진다.

 

tangent와 업벡터( 여기서는 임의로 world Y를 기준으로 하자 )를 외적하면 오른쪽 혹은 왼쪽의 값이 나온다.

이를 normal과 내적을 해준 후 결과값을 가지고 음수, 양수를 기준으로 한쪽으로 정렬이 가능해진다.

 

 

 

정렬 후 모습

 

 

/////////////////////////////////////////////

 

여기까지 한 다음 커브의 S자 모양을 Y값 까지 만지게 되면

이와 같이 노말방향때문에 또 틀어지게 된다. profile curve의 모양이 world 방향 Y쪽으로 고정되어 있도록 해보자.

 

 

각 segment마다 profile curve가 tangent를 축으로 하여 임의의 로테이션으로 돌아가 있는 모양새이다.

tangent를 축으로 회전하여 노말방향이 지면과 평행이 되도록 회전하면 모두 하늘을 바라보도록 정렬이 될것이다.

 

 

////////////////////////////////////////

 

 

 

어제 관련 내용에 대해 잠깐 찾다가 위 상황에서 현재는 행렬계산으로 배치와 회전등을 하고 있다.

매트릭스 행렬은 4X4 = 16번의 항으로 계산되어야 하고 ( 위에선 매트릭스 X 매트릭스이 아닌 포인트 X 매트릭스 계산이라 훨씬 가볍긴 하지만 )

이 방식보다 사원수를 이용하면 사원수의 항은 4개 밖에 없기 때문에 훨씬 가벼운 계산을 할 수 있다는 거 같다.

주말에 이 내용을 찾아 볼 것.

 

 

 

 

///////////////////////////////////////////////////////////////////

 

 

참고한곳

http://blog.naver.com/mysticodoi?Redirect=Log&logNo=140022277518

 

쿼터니언 q = w +xi + yj + zk 에서

스칼라요소 w의 부호를 반전 시켜서 180도 회전한 쿼터니언을 얻을 수 있다.

 

단위 커터니언은 다음과 같은 속성을 지닌다.

 

w2 + x2 +y2 + z2 = 1  단위 커너니언으로 3D 공간에서 방향을 표현할 수 있다.

 

 

 

쿼터니언 화전과 동등한 회전 행렬

행렬 = [    w2 + x2 -y2 -z2            2xy - 2wz                2xz +2wy                       0

                   2xy + 2wz            w2 - x2 + y2 -z2           2yz -2wx                       0

                   2xz - 2wy               2yz + 2wx             w2 - x2 -y2 + z2                 0

                         0                           0                             0                   w2 - x2 -y2 +z2   ]

 

 

단위 커터니언 공식을 위 행렬에 적용

행렬 = [     1 - 2y2 -2z2              2xy - 2wz             2xz + 2wy                0

                 2xy + 2wz             1 - 2x2 - 2z2            2yz - 2wx                0

                 2xz - 2wy                 2yz + 2wx         1 -2x2 - 2y2                0

                       0                               0                       0                      1    ]

 

 

 

 

///////////////////////////////////////////////////////////////////

 

 

다시 위 내용으로 돌아와서

 

노말 방향이 지면과 평행이 되도록 한다는 얘기는

벡터와 평면의 각도를 찾아내서 그 각도만큼 회전하도록 하면 된다는 뜻이다.

다만 회전 축이 탄젠트로 고정이 되어야 할텐데...

 

 

 

조금 더 명확하게 판단해 보자.

 

위의 큐브의 axis로 예를 들어 살펴보자. y축이 tangent축이라고 하고 x축이 normal방향이라고 가정해보자.

그러면 y축을 축으로 회전을 하여 x축이 XZ평면과 평행이 되어야 한다.

 

하지만 회전하는 각도를 확인하려면 XZ평면과 비교를 하면 안되고 XZ평면을 y축과 평행이 되도록 회전한 후

그 평면과 x축의 각도를 찾아야 한다.  다른 말로 정리하면 큐브의 y축과 월드x축으로 만들어지는 평면과 ( 그림에 보이는 평면

큐브 x축의 각도를 찾아야 한다.   임의로 평면을 평면 P라고 칭하자.

 

 

 

//////////////////////////////////////////////////////////////////////////////////////////////////////////

 

위의 상황을 2D로 간략화 시켜보자.

위 그림에서 벡터크기와 벡터로 만들어진 점과의 거리등을 모두 구할 수 있으므로

삼각형의 아래변의 길이도 당연 구할 수 있다.

 

 

삼각형의 길이를 모두 알고 있는 상태에서 각도를 구하려면

angle은 acos(cosθ) * 180 / PI 로 구할 수 있다.

180 / PI은 라디안을 각도로 변경하기 위한 것.

 

 

 

정사영 원리에 따라 위 그림에서 S`의 크기는 Scosθ 가 된다. ( S`=Scosθ )

그러면 ccosθ = S`/S 가될 것이다.

S가 면이 아닌 그냥 직선일 때도 똑같이 적용된다.

 

따라서 정리하면

angle은 acos( 아랫변/빗변 ) * 180 / PI 이 되겠다.

 

 

 

//////////////////////////////////////////////////////////////////////////////////////////////////////////

 

아,  위의 평면P의 가정이 잘못됐다.,,,

 

 

노말 == 큐브의 x축

탄젠트 == 큐브의 y축 으로 가정하고

 

노말과 탄젠트의 외적방향( 큐브의 z축 )과 노말을 성분으로 이루어진 붉은색 평면과

월드 XZ평면이 만나는 붉은색 직선을 구한다음

붉은색 직선과 탄젠트방향( y축 )으로 만들어지는 평면P를 구해서 노말과의 각도를 구해야한다.

 

 

 

/////////////////////////////////////////////////////////////////////////////////////////////

 

두 평면  ax+by+cz+d=0 , a`x+b`y+c`z+d`=0 의 교선을 포함하는 방정식은

ax+by+cz+d+k(a`x+b`y+c`z+d`)=0 (단, k는 실수)이다.

 

 

ax+by+cz+d+k(a`x+b`y+c`z+d`)=0 는 평면P이고 이는 탄젠트 벡터를 포함하고 있으므로

tangect.x, tangect.y, tangect.z의 값을 위 식에 대입해야 해서 k를 찾아야 한다. 

 

ax+by+cz+d+k(a`x+b`y+c`z+d`)=0 을 정리하면

( a+a`k )x + ( b + b`k )y + ( c + c`k )z + ( d + d`k ) = 0이 된다.

 

따라서 각 계수들과 k값을 알아 냈으므로 평면 P의 방정식을 구할 수 있다.

 

 

 

/////////////////////////////////////////////////////////////////////////////

 

 

이렇게 하니까

위 그림의 삼각형에서 height가 1이상이 나와 버린다.

normal벡터가 현재 노말라이즈 되어 길이가 1이기 때문에 height가 1이상이 나올 수가 없다..  어디서 틀린건지 모르겠네.

 

height가 1이상이 나온다는 것은 평면의 방정식이 잘못되었다는 말 밖에 안된다.

평면이 원점을 걸친상태로 임의의 각도로 회전된 상태여야 하는데 원점에서 벗어나 버린것 같다.

 

계속 살펴봤는데 딱히 잘못된 부분을 못찾겠는데도 안된다. 그냥 다른 방법으로 평면P를 구해야 될거 같다.

 

 

///////////////////////////////////////////////////////////////////////////////////////

 

아,,  졸라 간단한 방법이 있었는데 뭐하고 있었는지...

 

 

두 평면의 노말을 외적하면 교선 방향의 벡터가 나오잖아.. 이러라고 있는 외적인데 뭔 뻘짓을 이리했나.

 

 

 

///////////////////////////////////////////////////////////////////////////////////////

 

 

 

이제 평면P와 노말방향과의 각도도 구했으니 평면P와 평행이 되도록 회전을 시켜주면 된다.

탄젠트 벡터를 축으로 하여 회전을 시켜주면 되는데 위 그림과 같이 각 사분면에 따라서 회전을

해주어야 하는 방향이 다르다.  

 

좌우를 구별할때 썼던 외각과 

위의 그림에 있는 두 평면의 교선방향의 벡터와 탄젠트와의 외각

 

이 두 외각을 이용하면 노말의 방향이 몇번째 사분면인지를 확인할 수 있고 그에 따른 회전 방향을 설정해주면 정렬이 완성된다.

 

 

 

물론 무조건 무조건 업방향을 고정시켰기 때문에

청룡열차처럼 뒤집어 지는 경우를 만들면 중간에 뒤집어 지는 부분이 생긴다.

 

 

 

 

 

 

///////////////////////////////////////////////////////////////////////////////////////////////////////

 

 

 

 

 

 

 

관련글 더보기