CatChow0 01a9c940f0 Minor update - frustum rework
Complete overhaul of frustum culling
2025-01-12 00:59:43 +01:00

89 lines
4.5 KiB
C++
Raw Blame History

#include "frustum.h"
void Frustum::ConstructFrustum(float screenDepth, XMMATRIX projectionMatrix, XMMATRIX viewMatrix)
{
XMMATRIX matrix;
XMVECTOR planes[6];
// Calculate the minimum Z distance in the frustum.
float zMinimum = -projectionMatrix.r[3].m128_f32[2] / projectionMatrix.r[2].m128_f32[2];
float r = screenDepth / (screenDepth - zMinimum);
projectionMatrix.r[2].m128_f32[2] = r;
projectionMatrix.r[3].m128_f32[2] = -r * zMinimum;
// Create the frustum matrix from the view matrix and updated projection matrix.
matrix = XMMatrixMultiply(viewMatrix, projectionMatrix);
// Calculate near plane of frustum.
planes[0] = XMPlaneNormalize(XMVectorSet(matrix.r[0].m128_f32[3] + matrix.r[0].m128_f32[2],
matrix.r[1].m128_f32[3] + matrix.r[1].m128_f32[2],
matrix.r[2].m128_f32[3] + matrix.r[2].m128_f32[2],
matrix.r[3].m128_f32[3] + matrix.r[3].m128_f32[2]));
// Calculate far plane of frustum.
planes[1] = XMPlaneNormalize(XMVectorSet(matrix.r[0].m128_f32[3] - matrix.r[0].m128_f32[2],
matrix.r[1].m128_f32[3] - matrix.r[1].m128_f32[2],
matrix.r[2].m128_f32[3] - matrix.r[2].m128_f32[2],
matrix.r[3].m128_f32[3] - matrix.r[3].m128_f32[2]));
// Calculate left plane of frustum.
planes[2] = XMPlaneNormalize(XMVectorSet(matrix.r[0].m128_f32[3] + matrix.r[0].m128_f32[0],
matrix.r[1].m128_f32[3] + matrix.r[1].m128_f32[0],
matrix.r[2].m128_f32[3] + matrix.r[2].m128_f32[0],
matrix.r[3].m128_f32[3] + matrix.r[3].m128_f32[0]));
// Calculate right plane of frustum.
planes[3] = XMPlaneNormalize(XMVectorSet(matrix.r[0].m128_f32[3] - matrix.r[0].m128_f32[0],
matrix.r[1].m128_f32[3] - matrix.r[1].m128_f32[0],
matrix.r[2].m128_f32[3] - matrix.r[2].m128_f32[0],
matrix.r[3].m128_f32[3] - matrix.r[3].m128_f32[0]));
// Calculate top plane of frustum.
planes[4] = XMPlaneNormalize(XMVectorSet(matrix.r[0].m128_f32[3] - matrix.r[0].m128_f32[1],
matrix.r[1].m128_f32[3] - matrix.r[1].m128_f32[1],
matrix.r[2].m128_f32[3] - matrix.r[2].m128_f32[1],
matrix.r[3].m128_f32[3] - matrix.r[3].m128_f32[1]));
// Calculate bottom plane of frustum.
planes[5] = XMPlaneNormalize(XMVectorSet(matrix.r[0].m128_f32[3] + matrix.r[0].m128_f32[1],
matrix.r[1].m128_f32[3] + matrix.r[1].m128_f32[1],
matrix.r[2].m128_f32[3] + matrix.r[2].m128_f32[1],
matrix.r[3].m128_f32[3] + matrix.r[3].m128_f32[1]));
for (int i = 0; i < 6; i++)
{
m_planes[i] = planes[i];
}
}
bool Frustum::CheckCube(float xCenter, float yCenter, float zCenter, float radius, float tolerance)
{
// V<>rifiez chaque plan du frustum pour voir si le cube est <20> l'int<6E>rieur
for (int i = 0; i < 6; i++)
{
XMVECTOR plane = m_planes[i];
if (XMVectorGetX(plane) * (xCenter - radius) + XMVectorGetY(plane) * (yCenter - radius) + XMVectorGetZ(plane) * (zCenter - radius) + XMVectorGetW(plane) > -tolerance)
continue;
if (XMVectorGetX(plane) * (xCenter + radius) + XMVectorGetY(plane) * (yCenter - radius) + XMVectorGetZ(plane) * (zCenter - radius) + XMVectorGetW(plane) > -tolerance)
continue;
if (XMVectorGetX(plane) * (xCenter - radius) + XMVectorGetY(plane) * (yCenter + radius) + XMVectorGetZ(plane) * (zCenter - radius) + XMVectorGetW(plane) > -tolerance)
continue;
if (XMVectorGetX(plane) * (xCenter + radius) + XMVectorGetY(plane) * (yCenter + radius) + XMVectorGetZ(plane) * (zCenter - radius) + XMVectorGetW(plane) > -tolerance)
continue;
if (XMVectorGetX(plane) * (xCenter - radius) + XMVectorGetY(plane) * (yCenter - radius) + XMVectorGetZ(plane) * (zCenter + radius) + XMVectorGetW(plane) > -tolerance)
continue;
if (XMVectorGetX(plane) * (xCenter + radius) + XMVectorGetY(plane) * (yCenter - radius) + XMVectorGetZ(plane) * (zCenter + radius) + XMVectorGetW(plane) > -tolerance)
continue;
if (XMVectorGetX(plane) * (xCenter - radius) + XMVectorGetY(plane) * (yCenter + radius) + XMVectorGetZ(plane) * (zCenter + radius) + XMVectorGetW(plane) > -tolerance)
continue;
if (XMVectorGetX(plane) * (xCenter + radius) + XMVectorGetY(plane) * (yCenter + radius) + XMVectorGetZ(plane) * (zCenter + radius) + XMVectorGetW(plane) > -tolerance)
continue;
// Si le cube est en dehors de l'un des plans, il n'est pas dans le frustum
return false;
}
// Si le cube est <20> l'int<6E>rieur de tous les plans, il est dans le frustum
return true;
}