Seit ein paar Stunden sitze ich jetzt schon am Frustum Culling für mein Spiel. Eigentlich kein Problem, hatte ich gedacht, da ich einfach alten Code wiederverwenden konnte.
Zwar musste ich von D3DX auf DirectXMath umstellen, und außerdem will die neue Engine die Matrizen transponiert haben, aber das sollte ja alles kein Problem sein, oder?
Nun, anscheinend schon. Ich weiß nicht genau was falsch läuft, ich habe aber die Frustum Planes unter Verdacht. Ich bin mir nämlich immer noch ziemlich unsicher wann ich welche Matrix transponieren muss und in welcher reihen folge diese dann zusammen multipliziert werden müssen um zum richtigen Ergebnis zu kommen.
Hier ist mein alter, funktionierender, Code:
Code: Alles auswählen
void WCamera::BuildFrustumPlanes()
{
D3DXMATRIX viewProjection;
D3DXMatrixMultiply( &viewProjection, ViewMatrix, ProjMatrix );
// Left plane
FrustumPlanes[0].a = viewProjection._14 + viewProjection._11;
FrustumPlanes[0].b = viewProjection._24 + viewProjection._21;
FrustumPlanes[0].c = viewProjection._34 + viewProjection._31;
FrustumPlanes[0].d = viewProjection._44 + viewProjection._41;
// Right plane
FrustumPlanes[1].a = viewProjection._14 - viewProjection._11;
FrustumPlanes[1].b = viewProjection._24 - viewProjection._21;
FrustumPlanes[1].c = viewProjection._34 - viewProjection._31;
FrustumPlanes[1].d = viewProjection._44 - viewProjection._41;
// Top plane
FrustumPlanes[2].a = viewProjection._14 - viewProjection._12;
FrustumPlanes[2].b = viewProjection._24 - viewProjection._22;
FrustumPlanes[2].c = viewProjection._34 - viewProjection._32;
FrustumPlanes[2].d = viewProjection._44 - viewProjection._42;
// Bottom plane
FrustumPlanes[3].a = viewProjection._14 + viewProjection._12;
FrustumPlanes[3].b = viewProjection._24 + viewProjection._22;
FrustumPlanes[3].c = viewProjection._34 + viewProjection._32;
FrustumPlanes[3].d = viewProjection._44 + viewProjection._42;
// Near plane
FrustumPlanes[4].a = viewProjection._13;
FrustumPlanes[4].b = viewProjection._23;
FrustumPlanes[4].c = viewProjection._33;
FrustumPlanes[4].d = viewProjection._43;
// Far plane
FrustumPlanes[5].a = viewProjection._14 - viewProjection._13;
FrustumPlanes[5].b = viewProjection._24 - viewProjection._23;
FrustumPlanes[5].c = viewProjection._34 - viewProjection._33;
FrustumPlanes[5].d = viewProjection._44 - viewProjection._43;
// Normalize planes
for ( int i = 0; i < 6; i++ )
{
D3DXPlaneNormalize( &FrustumPlanes[i], &FrustumPlanes[i] );
}
}
Code: Alles auswählen
void BaseCamera::BuildFrustumPlanes(const XMFLOAT4X4& proj)
{
XMMATRIX mViewMatrix = XMLoadFloat4x4( &ViewMatrix );
XMMATRIX mProjMatrix = XMLoadFloat4x4( &proj );
XMMATRIX mViewProjection = XMMatrixTranspose( XMMatrixMultiply(mProjMatrix, mViewMatrix) );
XMFLOAT4X4 viewProjection; XMStoreFloat4x4(&viewProjection, mViewProjection);
// Left plane
FrustumPlanes[0].x = viewProjection._14 + viewProjection._11;
FrustumPlanes[0].y = viewProjection._24 + viewProjection._21;
FrustumPlanes[0].z = viewProjection._34 + viewProjection._31;
FrustumPlanes[0].w = viewProjection._44 + viewProjection._41;
// Right plane
FrustumPlanes[1].x = viewProjection._14 - viewProjection._11;
FrustumPlanes[1].y = viewProjection._24 - viewProjection._21;
FrustumPlanes[1].z = viewProjection._34 - viewProjection._31;
FrustumPlanes[1].w = viewProjection._44 - viewProjection._41;
// Top plane
FrustumPlanes[2].x = viewProjection._14 - viewProjection._12;
FrustumPlanes[2].y = viewProjection._24 - viewProjection._22;
FrustumPlanes[2].z = viewProjection._34 - viewProjection._32;
FrustumPlanes[2].w = viewProjection._44 - viewProjection._42;
// Bottom plane
FrustumPlanes[3].x = viewProjection._14 + viewProjection._12;
FrustumPlanes[3].y = viewProjection._24 + viewProjection._22;
FrustumPlanes[3].z = viewProjection._34 + viewProjection._32;
FrustumPlanes[3].w = viewProjection._44 + viewProjection._42;
// Near plane
FrustumPlanes[4].x = viewProjection._13;
FrustumPlanes[4].y = viewProjection._23;
FrustumPlanes[4].z = viewProjection._33;
FrustumPlanes[4].w = viewProjection._43;
// Far plane
FrustumPlanes[5].x = viewProjection._14 - viewProjection._13;
FrustumPlanes[5].y = viewProjection._24 - viewProjection._23;
FrustumPlanes[5].z = viewProjection._34 - viewProjection._33;
FrustumPlanes[5].w = viewProjection._44 - viewProjection._43;
// Normalize planes
for ( int i = 0; i < 6; i++ )
{
XMStoreFloat4( &FrustumPlanes[i], XMPlaneNormalize( XMLoadFloat4(&FrustumPlanes[i]) ));
}
}
Hier ist noch die Funktion, welche überprüft ob ein Objekt im Frustum liegt:
Code: Alles auswählen
/** Checks if the component is visible from our POV */
bool WorldObject::CheckVisibility(const XMFLOAT4* frustumPlanes)
{
float rad = GetObjectRadius();
if(rad > 0.0001f) // Only cull things with a radius
{
XMFLOAT3 mid = GetTrueObjectMid();
// Frustum Culling with Caching
if(FrustumCullPlaneCache != -1 )
{
if ( XMVectorGetX( XMPlaneDotCoord( XMLoadFloat4( &frustumPlanes[FrustumCullPlaneCache]), XMLoadFloat3(&mid) ) ) + rad < 0 )
{
// Outside the frustum, reject it. No need to alter the cache!
return false;
}
}
for(int i=0; i < 6; i++)
{
if ( XMVectorGetX( XMPlaneDotCoord( XMLoadFloat4( &frustumPlanes[i]), XMLoadFloat3(&mid) ) ) + rad < 0 )
{
// Outside the frustum, reject it and set cache!
FrustumCullPlaneCache = i;
return false;
}
}
// Wasn't frustumculled, reset cache
FrustumCullPlaneCache = -1;
}
return true;
}