블로그 이미지
Every unexpected event is a path to learning for you.

카테고리

분류 전체보기 (2731)
Unity3D (814)
Programming (474)
Python (8)
TinyXML (5)
STL (13)
D3D (3)
MFC (1)
C/C++ (54)
C++/CLI (45)
C# (250)
WinForm (6)
WPF (5)
Math (10)
A.I. (1)
Win32API (11)
Algorithm (3)
Design Pattern (7)
UML (1)
MaxScript (1)
FMOD (4)
FX Studio (1)
Lua (2)
Terrain (1)
Shader (3)
boost (2)
Xml (2)
JSON (4)
Etc (11)
Monad (1)
Html5 (4)
Qt (1)
Houdini (0)
Regex (10)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (228)
협업 (57)
3DS Max (3)
Game (12)
Utility (136)
Etc (96)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (51)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday
03-29 00:00


Link : http://blog.goldface.kr/6

반응형
Posted by blueasa
, |

Ogre로 프로젝트를 하면서 가장 시간을 많이 들였던 충돌 처리 부분 입니다. 
처음에는 물리 엔진을 써보고자 Physx , bullet, OgreODE 등 많은 물리엔진을 찾아서 사용 해보려 했지만...;;
결국 Ogre로 구현을 하게 되었습니다. ;; 
게임 개발에 필요한 수학적 지식이 부족한 상황에서 검색을 하던중 directx 로 구현한 OBB 충돌 소스를 찾게 되어서 
그 소스를 이용하여 Ogre에서 구현을 해봤습니다. 

dx 소스는 GpgStudy 에서 참고 하였습니다. 
Link에 추가 해놓으테니까 참고 하시면 좋을 것 같습니다~~
그리고 이만희님의 OBB 충돌 논문(Fast Overlap Test for OBB)
을 보시면 그래도 이해더 좀더 되 실 겁니다.
첨부 파일로 올려 놓겠습니다.(올려도 되려나??)


 
-소스 코드- 

BOOL PlayState::centerOBB(OBBoxRenderable* OBB1, OBBoxRenderable* OBB2)
{

 //box1이 이동하는 OBB / box2는 고정되어 있는 OBB

 Vector3 obb1_center, obb2_center, T, LL; //box1,box2 의 각각 센터 좌표, 
 Real box_len, a1, a2, a3, b1, b2, b3, TL;
 Matrix4 obb1_invers_mat, obb2_rotae_mat;
 Matrix4 R ;

 //OBB 박스의 월드 좌표??
 obb1_invers_mat = OBB1->getCharMat.inverse();
 obb2_rotae_mat = OBB2->getMonMat();

 //box1 의 좌표계를 box2의 좌표계로 회전변환 행렬 R = RA-1 * RB(-1은 iverse)
 R = obb1_invers_mat * obb2_rotae_mat;

 //box의 좌표축의 normal vector x, y, z 값 (제가 이해한 내용 - 틀린 내용 일 수도 있음 ㅋ)

 Vector3 obb1_size = OBB1->getWorldBoundingBox().getSize();
 Vector3 obb2_size = OBB2->getWorldBoundingBox().getSize();

 a1 = obb1_size.x; 
 a2 = obb1_size.y ;
 a3 = obb1_size.z ;

 b1 = obb2_size.x ;
 b2 = obb2_size.y ;
 b3 = obb2_size.z ;

 obb1_center = OBB1->getWorldBoundingBox().getCenter();
 obb2_center = OBB2->getWorldBoundingBox().getCenter();


 //box1 의좌표계에서 box1 중심에서 box2의 중심으로의 이동을 나타내는 vector3
 T = Vector3(obb1_center.x - obb2_center.x, obb1_center.y - obb2_center.y, obb1_center.z - obb2_center.z);

 //0. LL = A1
 box_len = a1 + b1 * R[0][0] + b2*R[0][1] + b3*R[0][2];
 LL =Vector3(1.0f, 0.0f, 0.0f); //분할 축의 벡터 
 TL = T.absDotProduct(LL); //T 와 L의 내적의 절대값
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }
 
 //1. LL = A2
 box_len = a2 + b1 * R[1][0] + b2*R[1][1] + b3*R[1][2];
 LL = Vector3(0.0f, 1.0f, 0.0f);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //2. LL = A3
 box_len = a3 + b1 * R[2][0] + b2*R[2][1] + b3*R[2][2];
 LL = Vector3(0.0f, 0.0f, 1.0f); 
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //3. LL = RB1[R11 R21 R31]
 box_len = a1*R[0][0] + a2 * R[1][0] + a3*R[2][0] + b1;
 LL = Vector3(R[0][0], R[1][0], R[2][0]);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //4. LL = RB2[R12 R22 R32]
 box_len = a1*R[0][1] + a2 * R[1][1] + a3*R[2][1] + b2;
 LL = Vector3(R[0][1], R[1][1], R[2][1]);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //5. LL = RB3[R13 R23 R33]
 box_len = a1*R[0][2] + a2 * R[1][2] + a3*R[2][2] + b3;
 LL = Vector3(R[0][2], R[1][2], R[2][2]);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //6. LL = A1 X RB1 = [1 0 0] X [R13 R23 R33] = [ 0 -R31 R21 ]
 box_len = a2*R[2][0] + a3*R[1][0] + b2*R[0][2] + b3*R[0][1];
 LL = Vector3(0.0f,  R[2][0], R[1][0]);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //7. LL = A1 X RB2 = [1 0 0] X [R12 R22 R32] = [ 0 -R32 R22 ]
 box_len = a2*R[2][1] + a3*R[1][1] + b1*R[0][2] + b3*R[0][0];
 LL = Vector3(0.0f,  -R[2][1], R[1][1]);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //8. LL = A1 X RB3 = [1 0 0] X [R13 R23 R33] = [ 0 -R33 R23 ]
 box_len = a2*R[2][2] + a3*R[1][2] + b1*R[0][1] + b2*R[0][0];
 LL = Vector3(0.0f,  -R[2][2], R[1][2]);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //9. LL = A2 X RB1 = [0 1 0] X [R11 R21 R31] = [R31 0 -R11]
 box_len = a1*R[2][0] + a3*R[0][0] + b2*R[1][2] + b3*R[1][1];
 LL = Vector3(R[2][0], 0.0f, R[0][0]);
 TL = LL.absDotProduct(T);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //10. LL = A2 X RB2 = [0 1 0] X [R12 R22 R32] = [R32 0 -R12]
 box_len = a1*R[2][1] + a3*R[0][1] + b1*R[1][2] + b3*R[1][0];
 LL = Vector3(R[2][1], 0.0f, -R[0][1]);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //11. LL = A2 X RB3 = [0 1 0] X [R13 R23 R33] = [R33 0 -R13]
 box_len = a1*R[2][2] + a3*R[0][2] + b1*R[1][1] + b2*R[1][0];
 LL = Vector3(R[2][2], 0.0f, -R[0][2]);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
 /* cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //12. LL = A3 X RB1 = [0 0 1] X [R11 R21 R31] = [-R21 R11 0]
 box_len = a1*R[1][0] + a2*R[0][0] + b2*R[2][2] + b3*R[2][1];
 LL = Vector3(-R[1][0], R[0][0], 0.0f);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //13. LL = A3 X RB2 = [0 0 1] X [R12 R22 R32] = [-R22 R12 0]
 box_len = a1*R[1][1] + a2*R[0][1] + b1*R[2][2] + b3*R[2][0];
 LL = Vector3(-R[1][1], R[0][1], 0.0f);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //14. LL = A3 X RB3 = [0 0 1] X [R13 R23 R33] = [-R23 R13 0]
 box_len = a1*R[1][2] + a2*R[0][2] + b1*R[2][1] + b2*R[2][0];
 LL = Vector3(-R[1][2], R[0][2], 0.0f);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
 /* cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //cout << "충돌!!" << endl;
 return 1;
}

구현을 해서 실행을 시켜본 결과 충돌 검출은 잘 하는데 살짝 떨어져 있어도 충돌 체크를 하는 경우가 있는데,
이유는 저도 잘...ㅠㅠ 그래도 이렇게해서 충돌 체크를 한다는거에 감사할 따름입니다. ㅋㅋ
혹시 소스 자체에 수정 할 부분이 있다고 생각되시는 분은 가르침 부탁 드리겠습니다^^ㅋ

인증샷!!!!



 Ps. box의 Matrix를 받아 오는 함수를 사용해서 Matrix값을 받아오게 했었는데, 값이 이상 했나 보네여 ;; 충돌 처리가  정확히 되지 않았습니다. 그래서 객체의 Entity 의_getBoneMatrices.transpose()를 사용해서 Matrix값을 받아 와서 충돌처리를 했더니 정확하게 OBB의 충돌 위치에서 멈추는 것을 확인 할 수 있었습니다. 

아직 정확한 Ogre의 분석이 되지 않은 상태에서 이것 저것 해보다가 얻어 걸린 것이라서 정확하게 어떻다라는 것을 제가 말씀 드릴 수는 없을 것 같습니다. 이해해 주시길..^^;; ㅋㅋ

(소스에서 이상한점을 발견 하시거나 잘못 된 곳을 발견하시면 저에게도 살포시 알려주세요~ㅋㅋㅋ)



출처 : http://eguru.co.kr/986

반응형
Posted by blueasa
, |

미끄러짐 벡터는 충돌시 입사벡터가 입사면을 따라 미끄러지게 하기위해 수평성분만을 남긴 벡터이다.

왼쪽 그림에서, 벡터 P 가 법선벡터 n 을 가진 입사면에 충돌했을때의 슬라이딩벡터S 를 볼수 있다.

슬라이딩벡터 S 는 여러가지 방법으로 구할 수 있지만, 여기서는 이전에 설명했던
반사벡터의 과정을 이용하는 방법과, 일반적인 방법을 설명한다.
물론, 그 결과는 완전히 같다.



이전에 설명했던 반사벡터에서, 입사벡터 P  n(-P·n) 을 한번 더해주면, 입사면에 투영된 접선벡터(Tangent Vector)를 구할 수 있다고 했다.

Fig. 2 를 보면, 입사벡터의 역벡터 -P 가 n 에 투영된 n(-P·n) 을 이용하여 슬라이딩벡터 S 를 구하고 있다.

그러므로 슬라이딩벡터 S 

S = P + n(-P·n)



일반적인 방법은, 입사벡터 P  n 에 바로 투영시키는 것이다.
입사벡터 P 와 법선벡터 n 의 끼인각이 0≤ θ ≤ π/2 일때, P·n 의 값은 음수가 되므로, n 벡터의 역벡터 방향으로 투영벡터가 생성된다.

이렇게 얻어진 투영벡터 n(P·n) 을 입사벡터 P 에서 빼주면,
슬라이딩벡터 S 를 얻을수 있다.

그러므로 슬라이딩벡터 S 

S = P - n(P·n)

반응형
Posted by blueasa
, |

정반사는 입사벡터와 반사벡터의 크기가 같고, 입사각과 반사각의 크기가 같은것을 말한다.

Fig.1 을 보면 입사벡터 P 와 법선벡터 n 이 주어졌을때,
반사벡터 R 은 벡터 P 와 크기가 같고, 입사각과 반사각이
같음을 확인할 수 있다.
여기서는 P  n 만으로 반사벡터 을 구하는 방법을 알아보자.



 

 
우선, 입사 벡터 P 의 역벡터 -P  n 의 연장선상에 투영시켜
투영벡터 n(-P·n) 를 구한다.





입사 벡터 P 의 시작 위치를 원점에 위치시키고, 여기에 n(-P·n) 를 더하면, 입사면에 투영된 벡터의 위치를 구할수 있다.

Fig. 3 을 보면, 입사벡터 P  n(-P·n) 를 1번 더하면, 입사면에 투영된
위치를 구할 수 있고, 2번 더하면  반사벡터 R 을 구할 수 있음을
알수 있다.

결국, 반사벡터 R 
R = P  2n(-P·n)

반응형
Posted by blueasa
, |

좌측 그림을 보면 단위벡터 n에 대해 벡터P로부터의 투영벡터(Projection Vector) Pproj 를 구하고 있다.

이와같은 Pproj 벡터는 어떻게 구해지는가를 살펴 보기로 한다.






P
 n과의 내적은 ||P||||n||cosθ 이다.
여기서 n이 단위 벡터이기 때문에 ||n|| = 1 이므로,

P·n = ||P||cosθ

이는 P n에 투영했을때의 길이를 말하므로, 여기서 구하고자 하는 Pproj 는 단위벡터 n P·n 만큼 연장한 값이다.

그러므로 투영벡터는

Pproj = n(P·n)

가 된다.

반응형

'Programming > Math' 카테고리의 다른 글

미끄러짐 벡터 ( Sliding Vector )  (0) 2012.05.16
반사 벡터 ( Reflection Vector )  (0) 2012.05.16
동차좌표 ( 同次座標, Homogeneous coordinate )  (0) 2012.05.16
[펌] 3D공간구조 기본충돌  (0) 2011.09.08
좌표계  (0) 2010.07.01
Posted by blueasa
, |

동차좌표란?

동차좌표를 사전에서 찾아보면, '사영기하학에서 무한원점의 불편한점을 고려해서 보통의 점과 같이 취급하기 위함' 이라 적어뒀다. 외계어인가 -_-;

일단 동차란 같은 차원이란 뜻이다. 비동차(inhomogeneous, 非同次) 좌표계 에서 무한대는 ∞ 라는 기호를 이용해서 표시하는데, 다른 원소들과 달리 일반적인 수가 아니다. 이를 일반적인 수로 표현하기 위해 차수를 높여 좌표의 표현력을 늘리기 위해 등장한 개념이다.

다시 말해 현재 차원의 점을 더 높은 차원의 공간상의 직선에 사상(mapping) 시킨것이 동차 좌표이다. 2차원의 점 (1, 2)는 원점에서 출발해 (1, 2, 1)를 통과하는 모든 3차원 공간상의 좌표와 같으며, 이것이 동차좌표이다.

다음 표를 보자 

 inhomogeneous coordinate homogeneous coordinate 
 0 (0, 1) 
 -7/3 (7, -3)
 ∞ (1, 0)
 not a point (0, 0)
 (5, -7/3) (5, -7/3, 1)
 (∞, 0) (1, 0, 0)
 (0, ∞) (0, 1,0)
 (2, 3/4) (8, 3, 4)
 (-3∞, 2∞) (-3, 2, 0)
위와 같이 일반적인 수로 표현이 안되던 것이 동차좌표에서는 표현 가능하게 되었다.

좌표계에서 무한한 값인 방향을 뜻하는 벡터(vector)와 점(vertex)을 동차좌표를 이용해 구분 표시할수 있다. 마지막 요소가 0이면 벡터를, 0이 아닌 다른 값이면 점을 의미한다.


반응형

'Programming > Math' 카테고리의 다른 글

반사 벡터 ( Reflection Vector )  (0) 2012.05.16
투영 벡터 ( Projection Vector )  (0) 2012.05.16
[펌] 3D공간구조 기본충돌  (0) 2011.09.08
좌표계  (0) 2010.07.01
역행렬(Inverse Matrix)  (0) 2010.03.17
Posted by blueasa
, |

 

Plane to Plane
-> 한평면의 테두리인 4개의 직선과 평면 충돌로 검출

// 평면1과 평면2의 선분 4개와 충돌 검사를 한다.
for( int I = 0; I < LineNum; i++){
{intersect3D_SegmentPlane( Segment S2[i], Plane Pn1, Point* I ) }

//평면 2와 평면1의 선분 4개와 충돌검사를 한다. LineNum = 4
for( int I = 0; I < LineNum; i++)
{intersect3D_SegmentPlane( Segment S1[i], Plane Pn2, Point* I ) }

BOOL CheckPlane()
{
for( int I = 0; I < LineNum; i++){
if( intersect3D_SegmentPlane( Segment S2[i], Plane Pn1, Point* I ) )
return TRUE;
}
for( int I = 0; I < LineNum; i++)
{
if( ntersect3D_SegmentPlane( Segment S1[i], Plane Pn2, Point* I ) )
return TRUE;
}
}

Sphere to Sphere
-> 구의 반지름 길이로 충돌검출

float D;
|Vr| = D = sqrt(Vr.x*Vr*x + Vr.y*Vr.y + Vr.z*Vr.z)
(벡터크기는 DX에서는 D3DXVEC3Length 란 함수로 제공한다. 그 외에 벡터들간의 연산에 관련된 여러 가지 함수들이 제공되어 편하다 )
if( (r+R) > D )
{
// sphere 충돌
}


float d = (Vr.x*Vr*x + Vr.y*Vr.y + Vr.z*Vr.z)
(r+R)² > d

Sphere to Line
-> 직선의 방정식과 구의 방정식을 이용해 충돌 검출

// return 값이 -1 이 아니라면 교차한다.
float ray_sphereIntersection(sphere_t* sphere, ray_t* ray) {
//B = [xd (x0 - xc) + yd(y0 - yc) + zd(z0 - zc)]이므로
// b - 직선의 방향벡터 d 와 직선의 한점 o 에서 구의 중심 p
// 으 로 향하는 벡터의 dot product
// C = (x0 - xc)² + (y0 - yc) ² + (z0 - zc)² - rs²
// 2가아니라 제곱입니다. 제곱은 카피가 안되니 조심하세요. //…
//vsquaredist = (o.x-p.x)²+(o.y-p.y)²+(o.z-p.z)²
float b = vdot(ray->d, vsub(ray->o, sphere->p));
float c = vsquaredist(ray->o, sphere->p) - (sphere->r * sphere->r);
// d = b²-c
float d = b * b - c;

if (d < 0.0f) {
return -1.0f;
}
return -b - sqrt(d); //t 값 return
}

BOOL WINAPI D3DXSphereBoundProbe(
const D3DXVECTOR3 *pCenter, // 구의 중심점
FLOAT Radius, // 구의 반지름
const D3DXVECTOR3 *pRayPosition, //직선의 위치
const D3DXVECTOR3 *pRayDirection //직선의 방향 벡터
);

출처 : http://cafe.naver.com/opendori/17451

반응형

'Programming > Math' 카테고리의 다른 글

투영 벡터 ( Projection Vector )  (0) 2012.05.16
동차좌표 ( 同次座標, Homogeneous coordinate )  (0) 2012.05.16
좌표계  (0) 2010.07.01
역행렬(Inverse Matrix)  (0) 2010.03.17
행렬식(Determinant)  (0) 2010.03.17
Posted by blueasa
, |

좌표계

Programming/Math / 2010. 7. 1. 21:34

가볍게..

 

DirectX는 왼손 좌표계를 사용한다.

 

x축이 오른쪽을 향하고 y축은 위를 향하며, z축은 안쪽을 향합니다.

 

 

- 동차 좌표계

 

평행 이동할 때 3차원 벡터인데도 굳이 4차원(아핀 벡터)으로 벡터의 변환을 확장했다. 3차원 공간에 w성분을 더해 w = 1로 벡터를 취급했지만, 이 논리를 진전시켜서 보통 때는 4차원 벡터로 다루고, 특별한 경우에는 w성분의 값으로 벡터를 나누어(x/w, y/w, z/w, 1) 을 실제 3차원 공간 벡터로 생각하는 좌표계를 동차좌표계라고 한다. 그림으로 그리면, 원점으로 부터 뻗어나간 직선위의 모든 점을 같은 벡터라고 생각.. 단, 관측 가능한 것은 w = 1일 때의 평면에서의 교점이다.

이 방법의 장점은 (1, 1, 1, 2)과 (0.5, 0.5, 0.5, 1)을 같은 벡터로 생각하므로 3차원 벡터의 스칼라-곱을 할 경우 4차원 벡터의 w성분에 그 역수를 곱하는 것으로 끝난다.

( 다행스럽게도, 최근의 그래픽 칩은 동차 좌표계를 자동적으로 처리해준다.. 4차원 벡터를 넘겨주면 필요할 경우 자동적으로 3차원 벡터로 바꿔서 렌더링 해준다. )

 

- 원근 보정

 

서투르게 텍스처를 입히면 제대로 입혀지지 않는다..

동차 좌표계에서의 평균 조작은 w=1에 투영한 공간에서의 평균 조작과는 다르다.

두 벡터의 중점을 계산.. 원점 (0, 0, 0, 1), 또 하나는 (1, 1, 1, 1)과 (2, 2, 2, 2)..

결과는..?

3차원에서 텍스처를 입힐 때는 원래의 좌표를 (u/z, v/z, 1/z)과 같이, 동차 좌표로 확장하고 나서, 각 좌표를 선형으로 보간한 뒤, w=1 값으로 텍스처를 입히는 방법을 사용해야 올바른 결과가 나온다.

DirectX로 원근 보정을 할 경우 정점 셰이더에서 픽셀 셰이더로 값을 넘길 때 주의해야 한다.

위치 좌표나 텍스처 좌표 값은 래스터라이저에서 적절히 원근 보정되어 픽셀 셰이더 입력으로 넘겨진다. 1/z 처럼( 좌표에 관해서 선형이 아님 ) 기묘한 값을 정점 셰이더에서 픽셀 셰이더로 주고받으면, 원근 보정 처리 자체가 적절한 처리가 안 되기 때문에 픽셀 셰이더에 올바른 값이 입력되지 않는다.

따라서, 정점 셰이더에서 좌표 변환에 관한 선형 값을 얻고, 픽셀 셰이더에서 비선형 값을 계산하는 것이 정확한 렌더링 결과를 얻기 위한 요령.

 

 

-  기하 변환

 

ㅁ 로컬 좌표계

모델링 툴로 3D모델을 생성할 때 사용되는 좌표계입니다.

 

ㅁ 월드 좌표계

우리가 서 있는 대지를 기준으로 한 좌표계가 월드 좌표계

행렬의 결합 순서는 신중하게 생각해야함..

이동 행렬과 회전 행렬의 순서를 반대로 하면, 완전히 다른 장소로 이동해버린다..

 

ㅁ 뷰 좌표계

뷰 좌표계란 어디엔가 놓여있는 카메라를 월드의 중심으로 해서, 카메라가 보고 있는 방향을 z축에 맞춘 좌표계이다.

카메라의 위치를 eye, 카메라가 응시하는 방향에 위치한 점 LookAt, 지면에서 수직방향 Up이라 할 때,

 

카메라의 시선 방향 벡터

e =   LookAt - eye

     ㅡㅡㅡㅡㅡㅡㅡ

     |LookAt - eye|

 

 

카메라의 옆 방향

v = Up X e

    ㅡㅡㅡㅡ

    |Up X e|

 

카메라의 위쪽 방향

 

u = e X v

 

 

카메라가 놓여진 위치까지의 평행 이동도 필요..

카메라의 월드 좌표계에서의 위치를 c = ( Cx, Cy, Cz )라고 하면..

카메라가 놓여진 위치를 원점으로 되돌려야 하므로, 이 행렬은 벡터c에 의한 평행 이동 행렬의 역행렬이 된다. 

결과적으로 최종적인 평행 이동은 카메라가 회전한 공간에서의 평행 이동이 된다.

 

 

ㅁ 투영 좌표계( 클립 좌표계 )

 

3차원 공간에서 디스플레이로 옮기는 2차원 좌표계가 투영 좌표계이다.

실제로는 폴리곤의 앞뒤 관계를 판정하기 위해, 깊이 값도 출력.

투영 좌표계는 화면의 중심을 원점으로해서 상하 좌우에 +-1의 폭을 가지는 좌표계, 깊이는 앞이 0이고 가장 안족이 1인 범위..

 

컴퓨터에서는 무한히 멀리있는 거리는 다룰 수 없기 때문에, 시야 깊이에 범위를 마련한다. 시야의 먼 한계 값을 후방 클립면.. 시야에서 보이는 가까운 곳의 한계 값을 전방 클립면.. 이렇게 전후, 좌우, 상하로 둘러싸이는 3차원 공간 가운데에 표시되는 영역을 절두체라고 한다.

 

뷰 좌표계에서 투영 좌표계로의 변환 행렬은 투영 행렬이다..

 

 

ㅁ 화면 좌표계

 

투영 좌표계는 x축, y축이 각각 01에서 1까지의 범위. 화면 영역은 640 X 480 등의 적당한 크기를 말한다. 투영 좌표계에서 화면 좌표계로 변환하는 행렬을 스크린 행렬, 혹은 뷰포트 행렬 또는 뷰포트 스케일링 행렬이라 한다.


투영 좌표계와 화면 좌표계의 차이는 중심 좌표가 투영 좌표계에서는 한가운데에 있지만, 화면 좌표계에서는 좌측 상단에 있다고 하는 것.. 또 y축이 뒤집혀 있는 것도 큰 차이..

 

투영 좌표계와 화면 좌표계의 대응을 식으로 정리하면.. 디스플레이 해상도를 ( W, H )로 했을 때, 중심좌표는 화면 좌표계에서는 ( W/2, H/2 )위치가 된다. 또 투영 좌표계로 ( -1, 1 )인 점이 화면 좌표계에 서는 ( 0, 0)에 위치 한다. 이상의 관계로, 투영 좌표 (Px, Py)의 점은 화면 좌표계에서 다음과 같다.

 

X = W/2 ( 1 + Px )

Y = H/2 ( 1 - Py )

반응형

'Programming > Math' 카테고리의 다른 글

투영 벡터 ( Projection Vector )  (0) 2012.05.16
동차좌표 ( 同次座標, Homogeneous coordinate )  (0) 2012.05.16
[펌] 3D공간구조 기본충돌  (0) 2011.09.08
역행렬(Inverse Matrix)  (0) 2010.03.17
행렬식(Determinant)  (0) 2010.03.17
Posted by blueasa
, |
반응형

'Programming > Math' 카테고리의 다른 글

투영 벡터 ( Projection Vector )  (0) 2012.05.16
동차좌표 ( 同次座標, Homogeneous coordinate )  (0) 2012.05.16
[펌] 3D공간구조 기본충돌  (0) 2011.09.08
좌표계  (0) 2010.07.01
행렬식(Determinant)  (0) 2010.03.17
Posted by blueasa
, |
반응형

'Programming > Math' 카테고리의 다른 글

투영 벡터 ( Projection Vector )  (0) 2012.05.16
동차좌표 ( 同次座標, Homogeneous coordinate )  (0) 2012.05.16
[펌] 3D공간구조 기본충돌  (0) 2011.09.08
좌표계  (0) 2010.07.01
역행렬(Inverse Matrix)  (0) 2010.03.17
Posted by blueasa
, |