2009년 04월 23일
[3D][DirectX] Cylinder World
Cyliner를 만드는건 간단합니다.

이것은 간단히 원통의 단계를 PI로 나누어 단위세타를 구하고, 단계마다 곱해줍니다.
그리고 이것을 높이의 양 끝에 배치해서 순서대로 넣어주면 됩니다.
렌더링엔 TRIANGE_STRIP을 사용합니다.
for(int CreateCount = 0;
CreateCount < Division;
CreateCount++) {
float Theta = 2 * D3DX_PI * CreateCount / (Division - 1);
this->m_pVertex[CreateCount * 2 ] =
CVertex(sinf(Theta) * CircleRadius, Height, cosf(Theta) * CircleRadius, UpColor);
this->m_pVertex[CreateCount * 2 + 1] =
CVertex(sinf(Theta) * CircleRadius, -Height, cosf(Theta) * CircleRadius, DownColor);
}
그리고 XZ를 평면으로 가정하고 그 위에서 Cyliner가 굴러가도록 구현했습니다.
상하좌우키로 평면위를 움직이는데, 다른 방향의 입력이 들어오면 회전합니다.
회전엔 제한을 걸었습니다. 회전을 Cyliner의 중점을 기준으로 회전하는 것이죠.
원래 회전하고자 하는 방향의 끝을 기준으로 회전인데, 코드가 매우 늘어나더군요.
게다가 시험기간이라서 간단히 회전했습니다. 덧붙여 상하<->좌우회전시 회전방향도
고정해버렸습니다. 고정을 하지 않으면 원통이 뒤집힐 수 있기때문이죠.
이동(방향에 따라 회전축이 바뀝니다. 아래소스는 한방향만 표시)
D3DXMatrixTranslation(&Trans, 0.0f, 0.0f, CylinderMovement);
D3DXMatrixRotationY(&Rot, CylinerRoll);
this->mRollCylinder.m_mtxWorldTranslation *= Trans;
this->mRollCylinder.m_mtxWorldRotation = Rot * this->mRollCylinder.m_mtxWorldRotation;
this->mRollCylinder.CalculationWorld();
회전
if(this->mBreadth== true)
this->mRollCylinder.m_mtxWorldRotation*= this->mAnimationBreadthRollMatrix;
else
this->mRollCylinder.m_mtxWorldRotation*= this->mAnimationNonBreadthRollMatrix;
굴러가는 범위제한은 두가지 방법으로 해봤습니다.
하나는 버텍스별로 월드에 배치시켜 해당범위를 체크하는 것이고,
또 다른 하나는 중점을 월드에 배치시켜 범위를 체크하는것입니다.
전자의 경우, 이동에 사용해봤고, 후자는 회전에 사용했습니다. 사실 후자가 간단하죠;;
D3DXMatrixTranslation(&Trans, MovementX, 0.0f,MovementZ);
Trans = this->mRollCylinder.m_mtxWorld* Trans;
// 필요한 버텍스마다 체크
D3DXVec3TransformCoord(&TestVec3, &TestVec3,&Trans);
// 이동 범위검사.
D3DXVECTOR3 TestVec3(0.0f, 0.0f, 0.0f);
D3DXVec3TransformCoord(&TestVec3, &TestVec3, &this->mRollCylinder.m_mtxWorld);
// 회전 범위검사
추가로 움직이는 Cylinder를 향해 총알이 발사되도록 해봤습니다.
우선 총알을 배치해야 하는데, 이것은 XZ평면 위쪽에서 일정범위 안에서
무작위로 생성되도록 해봤습니다. (New-에서 랜덤좌표를 구해넣습니다.)
그리고 이것이 움직일 수 있는 Cylinder를 행해 이동할수 있는 이동행열을 구합니다.
D3DXVECTOR3 Target(0.0f, 0.0f, 0.0f);
D3DXVec3TransformCoord(&Target, &Target, &this->mRollCylinder.m_mtxWorld);
D3DXVECTOR3 Bullet(NewX, NewY, NewZ);
D3DXVECTOR3 TargetDirection = Target - Bullet;
D3DXVec3Normalize(&TargetDirection, &TargetDirection);
D3DXMatrixTranslation(&mSpeedMatrix[Index], TargetDirection.x* Speed,
TargetDirection.y* Speed, TargetDirection.z * Speed);
그리고 이 총알을 해당방향으로 회전해야 합니다.
카메라의 역행열은 월드배치이므로 D3DXMatrixLookAtLH을 이용했습니다.
위에서 시작점과 목표점을 구했으니 이 함수에 직접 인자를 넣을수 있으니깐요.
물론 이전포스팅처럼 RIGHT, UP, LOOK벡터를 구해서 행열에 넣어도 가능합니다.
모델좌표의 Look는 Z축이고, 실제총알의 Look는 Y축이므로 X축 회전이 추가됩니다.
D3DXMATRIX NewTrans, NewRot1, NewRot2;
D3DXMatrixTranslation(&NewTrans, NewX, NewY, NewZ);
D3DXVECTOR3 Pos(NewX, NewY, NewZ);
D3DXVECTOR3 LOOK = Target;
D3DXVECTOR3 UP;
D3DXVec3Cross(&UP, &Pos, &LOOK);
D3DXMatrixLookAtLH(&NewRot1, &Pos, &LOOK,&UP);
NewRot1._41 = 0.0f; NewRot1._42= 0.0f; NewRot1._43 = 0.0f;
D3DXMatrixInverse(&NewRot1, NULL, &NewRot1);
D3DXMatrixRotationX(&NewRot2, D3DX_PI / 2);
this->mBulletCylinder[Index].m_mtxWorld = NewRot2 *NewRot1 * NewTrans;
이렇게 총알변환행열을 구했으면 카메라를 총알을 따라가게 하는 것은 쉽죠.
월드의 역변환이 카메라의 행열이 되니깐요.
D3DXMatrixInverse(&this->mView,NULL, &this->mBulletCylinder[0].m_mtxWorld);
결과


어쨌건 첫번째 과제는 이렇게 넘어가네요. 총알을 구현한 덕분에 텀프로젝트에선
탄환도 추가할수 있을듯 싶습니다. 물론 회전을 무식하게 구현한만큼 좀더 공부해서
다듬어야 겠지만요 --;
# by | 2009/04/23 12:36 | Workshop | 트랙백 | 덧글(0)




☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]