[GPG 5 글 1.6] GPG5권 1.6 개선된 절두체 D3D로 포팅해보신 분?

GPG 시리즈 관련 질답, 논의 공간.

Moderator: 류광

비회원

GPG5권 1.6 개선된 절두체 D3D로 포팅해보신 분?

Post by 비회원 »

지금까지 잘 쓰던 여섯 평면 방식 절두체 대신 GPG 5권 1.6 장에 있는 개선된 절두체를 사용하려고 아래와 같이 그대로 D3D로 바꿔보았습니다.

void Frustum::SetPerspective( float FOV, float ViewAspect, float NearZ, float FarZ )
{
m_rFactor = tanf( FOV / 2.0f );
m_uFactor = m_rFactor * ViewAspect;
m_NearZ = NearZ;
m_FarZ = FarZ;
}

void Frustum::Build( D3DXVECTOR3& Eye, D3DXVECTOR3& Forward, D3DXVECTOR3& Right, D3DXVECTOR3& Up )
{
m_EyePos = Eye;
m_ForwardVector = Forward;
m_RightVector = Right;
m_UpVector = Up;
}

bool Frustum::IsSphereIn( D3DXVECTOR3& Center, float Radius )
{
D3DXVECTOR3 OP = Center - m_EyePos;
float f = D3DXVec3Dot( &OP, &m_ForwardVector );
if( f < m_NearZ - Radius || m_FarZ + Radius < f ) return false;

float r = D3DXVec3Dot( &OP, &m_RightVector );
float rLimit = m_rFactor * f;
float rTop = rLimit + Radius;
if( r < -rTop || rTop < r ) return false;

float u = D3DXVec3Dot( &OP, &m_UpVector );
float uLimit = m_uFactor * f;
float uTop = uLimit + Radius;
if( u < -uTop || uTop < u ) return false;

return true;
}

일단 SetPerspective 메서드에 카메라에서 설정한 값들 그대로 넣어주었고,
Build 메서드에는 카메라 월드 좌표 및 lookat 좌표와 외적하고 normalize해서 구한 변수들을 설정했습니다.

그런 다음 쿼드트리에 넣어서 IsSphereIn 메서드로 절두체 컬링을 해보았는데 이상하게도 시야에 빤히 보이는데 절두체에서 벗어났다고 판정해버리는 경우가 자주 생기더군요. ㅠㅠ

혹시나 해서 Radius 에 값을 넉넉하게 더해봤지만 소용이 없었습니다.

원래 쓰던 여섯 평면 방식 절두체로 해보면 잘 되는걸로 봐서 제가 잘못 만든 것 같은데, OPEN-GL을 하나도 모르는 지라 원본 소스를 봐도 알 수가 없습니다. 3D 파이프라인 변환이랑 벡터 이론을 붙잡고 봐도 문제가 뭔지 도저히 생각이 나지 않네요. 먼저 만들어 보신 분이 있으시면 한 번 봐주시면 감사하겠습니다.
nikola2
Posts: 886
Joined: 2005-07-12 01:19
Location: (주) 신규 소프트

Re: GPG5권 1.6 개선된 절두체 D3D로 포팅해보신 분?

Post by nikola2 »

비회원 wrote:
void Frustum::SetPerspective( float FOV, float ViewAspect, float NearZ, float FarZ )
{
m_rFactor = tanf( FOV / 2.0f );
m_uFactor = m_rFactor * ViewAspect;
m_NearZ = NearZ;
m_FarZ = FarZ;
}

bool Frustum::IsSphereIn( D3DXVECTOR3& Center, float Radius )
{
D3DXVECTOR3 OP = Center - m_EyePos;
float f = D3DXVec3Dot( &OP, &m_ForwardVector );
if( f < m_NearZ - Radius || m_FarZ + Radius < f ) return false;

float r = D3DXVec3Dot( &OP, &m_RightVector );
float rLimit = m_rFactor * f;
float rTop = rLimit + Radius;
if( r < -rTop || rTop < r ) return false;

float u = D3DXVec3Dot( &OP, &m_UpVector );
float uLimit = m_uFactor * f;
float uTop = uLimit + Radius;
if( u < -uTop || uTop < u ) return false;

return true;
}
5권은 거의 읽지 못했고, 인용하신 코드만 살펴봤습니다...
실수할 가능성이 있는 부분은 rFactor와 uFactor부분이네요.....

DX에서는 y축 fov와 w/h의 aspect ratio를 씁니다...
rFactor의 r은 Right이고 너비쪽방향이며, uFactor의 u는 Up이고 높이쪽 방향이니까..
코드내용의 fov는 xfov이고, aspect ratio도 h/w이네요....
(오픈지엘쪽이라 이런것일듯) 이부분에 실수가 있으시면 전환하시면 됩니다...
집사람이 국력이다...
express8
Posts: 253
Joined: 2005-05-19 13:31
Location: eppengine
Contact:

Post by express8 »

전혀 도움은 안되지만..

저랑 비슷한 고민을 하고 계시군요.

분명이 이론적으로 그려가면서 코딩을 해도

아무런 문제가 없어야 하는데 그렇질 않더군요.

저도 그래서 다시 예전으로 돌아갈까 생각중입니다. -_-;;

혹시 속시원한 원인을 알고 계시는분 없으신가요?

p.s. 분명 이론적으로는 문제가 없어야 하는데... -_-;;
차세대 멀티플랫폼 게임엔진 eppengine
(피바다 엔진3.0 )

http://www.eppengine.com
Filein
Posts: 8
Joined: 2007-11-02 16:35

Re: GPG5권 1.6 개선된 절두체 D3D로 포팅해보신 분?

Post by Filein »

Code: Select all

	m_fUFactor = tan( fFOV / 2.0f ) * 2.0f;
	m_fRFactor = m_fUFactor * fAspect;
제가 쓴 방법입니다.

위에 분이 말씀하신것처럼 fFOV는 y축의 FOV입니다. 그러니 UFactor부터 구하고 거기에

Aspect를 곱해줍니다.

여기서 질문은 왜 tan계산에 2.0f을 곱해야 되냐 입니다. 곱하지 않으면 frustum이 작게 됩니다.

전혀 이해가 되지 않습니다. 혹시, 제가 DX의 투영 행렬을 이해 못한건가 싶습니다.

이것에 대해 답변 부탁드립니다.
Post Reply