[3D][DirectX] Picking

과제로 작성한 피킹입니다. 상당히 예전에 작성한거죠..






LabProject.exe

클릭하면 카메라가 해당오브젝트의 뒤로 이동하게 되어, 제어할 수 있습니다.
피킹방법이야 여러 책에서 단골로 등장하니깐요.
간단히 요약해 놓자면
스크린좌표를 카메라좌표계로 변환하여 카메라에서 해당방향으로 뻗어나가는 Ray를
생성하고 이것을 필요에 따라 월드좌표계 -> 로컬좌표계로 변환시켜서 사용하게 됩니다.

DX샘플보면 오브젝트의 전체 폴리곤에 대해 피킹하는 예제를 볼 수 있습니다.

D3DX에서 제공하는 D3DXIntersectTri함수를 사용하면 쉽게 구현이 가능합니다.


아무래도 각각의 폴리곤에 대해서 검사하는건 비용문제가 클꺼라고 생각해서
오브젝트를 감싸는 바운드 박스를 계산하고 바운드박스로 피킹검사를 했습니다.

by hellz | 2009/06/27 23:12 | 트랙백 | 덧글(0)

[3D][DirectX] 물에 잠기는 알파오브젝트

드디어 한학기가 끝났습니다.
시험이다 과제때문에 한동안 포스팅이 없었네요. (정기방문보다 검색방문이 많겠지만 ;;;)
기말고사는 저번주에 끝났지만, 늦게 내는 텀이 남아서 방학(!)이  한주 더 걸렸네요.
이제 남은건 성적공개뿐이군요....



알파오브젝트는 일반적인 오브젝트를 그린 후,
알파 오브젝트끼리 카메라에서의 거리로 먼곳부터 그려줘야 합니다.

문제는 지형에 커다란 사각형으로 물을 씌울때 발생합니다.
물도 알파오브젝트인데, 다른 작은 알파오브젝트와 비교해 언제 그려줘야 할까요?




빌보드로 알파값을 가진 나무입니다.
나무를 먼저 그려주고, 물을 그려준 상태입니다.
보시다시피 빌보드의 투명부분에 물이 그려지지 않았습니다.
나무의 Z버퍼가 물보다 앞에 있기때문에 그려지지 않는것이죠.



이번엔 반대로 물을 그려주고, 나무를 그려줬습니다.
얼핏보면 제대로 그져진듯 하지만, 물에 잠긴 나무밑둥이 그려지지 않습니다.
아까와 반대로 물의 Z버퍼가 잠긴 나무앞에 있기 때문에 그려질 수 없는것이죠.
만약 물이 투명하지 않는 거라면 이정도로도 충분할 겁니다.
하지만 투명히 비추는 물에 잠긴 오브젝트를 원한다면 불충분하죠.



해결법은 나무를 2번 그리고, Z버퍼쓰기 상태를 이용하는 겁니다.
먼저 나무를 그려줍니다.
중요 포인트는 Z버퍼쓰기를 꺼주는 겁니다.
SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
이렇게하면 출력은 되지만, Z버퍼에는 반영이 되지 않죠.


다시 Z버퍼쓰기를 활성화한 후,  물을 그려줍니다.
물 위쪽에 그려진 나무가 물과 알파블렌딩되서 흐려진것을 알 수 있습니다.
당연히 물에 잠긴 밑둥은 물과 블렌딩된 상태입니다.


마지막으로 나무를 다시 그려줍니다.
물을 그릴때 Z버퍼가 변하여, 밑둥이 다시 그려지지 않고,
잠긴 효과 그대로 유지되는것을 알 수 있습니다.
물 위 가지부분은  물보다 카메라에 가까우므로, 덮어 써지는것을 알 수 있습니다.


정리하면 다음과 같습니다.
  1. Z버퍼쓰기를 끄고 알파 오브젝트를 그린다. (Z버퍼 사용[D3DRS_ZENABLE])이 아님.)
  2. Z버퍼쓰기를 다시 키고 물을 그린다.
  3. 알파 오브젝트를 다시 그린다.


이걸 생각해내기 전에는 요상하게 작성해봤었죠.
Z버퍼쓰기를 끄고, 물을 그리고, Z버퍼쓰기 키고 오브젝트를 그리고 알파블렌딩을
D3DBLENDOP_MIN로 지정한뒤 물을 다시 출력했었습니다.
이렇게하면 오브젝트의 알파부분과 물과 약간의 색차가 존재합니다.
그래도 멀리서 보면, 어느정도 그럴듯 했었죠;;;;

원래 과제에 덤으로 넣은 물효과인데, 그냥 초안대로 작성해서 빨리 내버렸습니다.
근데 제출한 다음날에 이방법이 떠올랐다죠 orz...
다행히 기말 실기시험에서 이 소스를 사용해서, 기말고사는 수정된 버전으로 제출~




by hellz | 2009/06/26 23:51 | Programming | 트랙백 | 덧글(0)

[3D][DirectX] Solar System

과제로 나온 태양계입니다. 과제한지는 꽤 됐는데, 그다지 시간여유가 없었습니다 --;


우선 태양계를 살펴보면 항성인 태양. 지구같은 행성. 달과 같은 위성이 있습니다.
지구는 태양주위를 공전하며, 달은 지구 주위를 공전하죠.
또한 자신조차도 스스로 공전을 합니다.

즉, 혹성은 부모주위를 공전하며, 자전을 하죠.
이것을 정리하여 항성과 행성과 위성을 나타내는 혹성클레스를 정의합니다.
혹성안에는 공전과 자전을 위한 자료. 그리고 자식들의 리스트를 가지고 있습니다.
그리고 혹성의 움직임, 그리기등의 작업은 부모를 통해 자식에게 전해지게 됩니다.

그리기 코드는 다음과 같습니다.

bool CPlanet::Draw(LPDIRECT3DDEVICE9 pD3DDevice, D3DXMATRIXMotherTranslation) {

             pD3DDevice->SetTransform(D3DTS_WORLD,

 &(SelfRotation* MotherRotation * MotherTranslation));

             this->m_pMesh->Render(pD3DDevice);

 

             for(int Count = 0;Count < Child.size(); Count++)

Child[Count]->Draw(pD3DDevice, this->MotherRotation * MotherTranslation);   

return true;

}

부모의 위치좌표를 넘겨 받습니다.

그리고 자전회전 * 공전회전 * 부모위치을 차례로 곱해서 혹성의 위치를 구합니다.

자신을 그리면 자전을 제외한 위치행열을 자식에게 전달합니다.


이렇게하면 모든 혹성을 루프를 통해 일괄적으로 넣을수도 있죠.




실행파일 (LabProject.exe)

숫자키 1~8을 누르면 각 행성으로 카메라가 이동되며
9번은 상단카메라. 0번은 위에서 비스듬하게 내려다 보는 카메라입니다.
구는 버텍스와 인덱스를 실린더 공식을 이용해서 직접 만들어 주었는데,
회전을 명확히 보기 위해 색상에 노이즈를 넣어봤습니다.


원래는 구 코드도 올릴까 했는데, 이건 나중에 시간되면 올리죠 --;
일단 다음과제 올리는건 건너뛰고(제공된 소스를 활용한 수준이라)
다음에 올릴건 피킹이 되겠군요.. 일단 구현은 완료된 상태...

by hellz | 2009/05/25 00:16 | Workshop | 트랙백 | 덧글(0)

[BUY] 이어폰 & 헤드폰 구입(UBQ-ES303/CS-C510H)

그동안 잘 쓰던 ubq-es103입니다. 저렴한 거격에도 좋은 성능을 보여주죠.
두번여의 단선에도 불구하고 직접 선을 교환하며 잘 썼죠.
근데 오른쪽 은색 플라스틱이 없어져 버렸습니다. 저음이 엄청 퍼지더군요;;
일단 임시로 테이프로 막아줬지만, 좌우 벨런스도 어긋나있더군요..




그래서 새로운 리시버를 장만했습니다.
ubq-es303입니다. 하이엔드에 필적한다나 어쩐다나.. 아무튼 평 좋은 넘이죠.

SE버전도 있는듯 한데, 이건 중음 높인다고 덕트만 막아놨다더군요.
그래서 303으로 구입.. 중음 부족한거 같으면 덕트 막으면 되니깐요..


처음엔 커널형으로 해볼까 했으나, 귀에 안 좋으니 각하...
게다가 가끔 산보하면서 음악들이니 커널은 위험하겠죠...


그래서 헤드폰도 하나 장만했습니다
크렉신의 CS-C510H입니다.
마지막엔 HP600하고 고민했지만, 벨런스는 좋다고 하니깐요.
솔직히 환율만 이렇지 않았어도 SJ5샀을텐데 말이죠 orz...




이어폰은 걸어다닐때 쓰고
헤드폰은 차 안이나 학교에 짱 박혀 있을때 쓸 계획입니다.
겨울엔 보온도 되고 말이죠..

물론 집에선 스피커입니다 ;;


현제 계속 돌리면서 푸는 중입니다.
에이징까지 거창한건 아니고, 처음샀을땐 좀 딱딱하니깐 말이죠...
나중에 사용기나 올릴까 하네요...





by hellz | 2009/05/13 14:39 | Talk | 트랙백 | 덧글(0)

[3D] 사각형의 충돌체크

사각형 충돌을 위한 사각형에는 두가지 종류가 있습니다.

AABB  : 슬라이드 49 좌표축을 기준으로 만든 박스 Axis Aligned Bounding Box
OBB    : 모델의 좌표축을 기준으로 만든 박스 Oriented Bounding Box


AABB로만 이루어진 사각형끼리의 체크는 간단합니다.
단순히 사각형의 점이 다른 사각형 내부에 있는지만 검사하는것으로 만족하죠.
간단한 윈도우 프로그래밍때 하던 RECT와 POINT간의 체크와 아주 유사합니다.


문제는 한쪽이 OBB일때 발생하죠.
그림과 같이 한쪽이 기울어진 사각형일때, 단순히 점이 사각형 안에 들어가는지로는
제대로 체크가 할수 없습니다. 분명히 4점 모두 들어가지 않지만 이건 충동이 일어났죠.



이럴때 충돌체크는 면과 점과의 거리를 사용하면 구할수 있습니다.
파란 사각형의 각각의 변에 대하여 평면의 방정식을 4개 만듭니다. (2D에선 변이 면)
그리고 빨간색 사각형의 각각의 점에 대해서 각 평면과의 거리를 측정합니다.
만약 하나라도 평면과의 거리가 0보다 크면 두 사각형은 충돌하지 않는것입니다.

1번 평면의 경우, 법선이 X축으로 감소하며 Y축으로 증가하고 있습니다.
이 경우 가장 먼저 만나는 점은 X축으로 가장 크며, Y축으로 가장 작은 점이 됩니다.
이에 해당하는 점은 D가 되겠죠.

중요한건 체크할 모든 점이 이 방정식을 만족하는게 아니라는겁니다.
2번평면의 경우 A,B,C,D모두가 해당평면의 뒤에 있기때문에 문제가 안됩니다만,
4번평면의 경우 만족하는 점은 B뿐입니다.  이렇게 각 평면에 유효점을 구해서 처리합니다.

AABB의 경우는 쉽게 체크해야 할 점을 특정할수 있으니 빠르게 충돌처리를 할수 있습니다.
만약 둘다 OBB일 경우라면 점을 제공하는 사각형의 모든 점중 하나라도 법선내에 포함되면
해당 평면에 대해서는 체크에 성공했다고 하는것이 좋겠죠.
(OBB경우 두 벡터로 바운딩박스를 구현할수 없는데다, 회전도 있기때문에 1:1비교를 예상)


평면을 이용한 사각형 충돌체크는 절두체컬링에서도 쓰이고 있습니다. (AABB로)

3D에서의 오브젝트끼리의 충돌은 모텔축에서만 AABB를 구축해서 사용하면 월드축에서
OBB과 동일한 효과를 가지므로 각 평면만 모델축으로 가져와서 충돌체크하는게
좋지 않을까 싶네요. (아직 구현전이라;;)





by hellz | 2009/05/03 20:26 | Programming | 트랙백 | 덧글(0)

◀ 이전 페이지          다음 페이지 ▶