2024-04-04 09:02:33 +02:00

297 lines
8.3 KiB
C++

#include "frustumclass.h"
FrustumClass::FrustumClass()
{
}
FrustumClass::FrustumClass(const FrustumClass& other)
{
}
FrustumClass::~FrustumClass()
{
}
void FrustumClass::ConstructFrustum(XMMATRIX viewMatrix, XMMATRIX projectionMatrix, float screenDepth)
{
XMMATRIX finalMatrix;
XMFLOAT4X4 projMatrix, matrix;
float zMinimum, r, t;
// Load the projection matrix into a XMFLOAT4X4 structure.
XMStoreFloat4x4(&projMatrix, projectionMatrix);
// Calculate the minimum Z distance in the frustum.
zMinimum = -projMatrix._43 / projMatrix._33;
r = screenDepth / (screenDepth - zMinimum);
projMatrix._33 = r;
projMatrix._43 = -r * zMinimum;
// Load the updated XMFLOAT4X4 back into the original projection matrix.
projectionMatrix = XMLoadFloat4x4(&projMatrix);
// Create the frustum matrix from the view matrix and updated projection matrix.
finalMatrix = XMMatrixMultiply(viewMatrix, projectionMatrix);
// Load the final matrix into a XMFLOAT4X4 structure.
XMStoreFloat4x4(&matrix, finalMatrix);
// Get the near plane of the frustum.
m_planes[0].x = matrix._13;
m_planes[0].y = matrix._23;
m_planes[0].z = matrix._33;
m_planes[0].w = matrix._43;
// Normalize it.
t = (float)sqrt((m_planes[0].x * m_planes[0].x) + (m_planes[0].y * m_planes[0].y) + (m_planes[0].z * m_planes[0].z));
m_planes[0].x /= t;
m_planes[0].y /= t;
m_planes[0].z /= t;
m_planes[0].w /= t;
// Calculate the far plane of frustum.
m_planes[1].x = matrix._14 - matrix._13;
m_planes[1].y = matrix._24 - matrix._23;
m_planes[1].z = matrix._34 - matrix._33;
m_planes[1].w = matrix._44 - matrix._43;
// Normalize it.
t = (float)sqrt((m_planes[1].x * m_planes[1].x) + (m_planes[1].y * m_planes[1].y) + (m_planes[1].z * m_planes[1].z));
m_planes[1].x /= t;
m_planes[1].y /= t;
m_planes[1].z /= t;
m_planes[1].w /= t;
// Calculate the left plane of frustum.
m_planes[2].x = matrix._14 + matrix._11;
m_planes[2].y = matrix._24 + matrix._21;
m_planes[2].z = matrix._34 + matrix._31;
m_planes[2].w = matrix._44 + matrix._41;
// Normalize it.
t = (float)sqrt((m_planes[2].x * m_planes[2].x) + (m_planes[2].y * m_planes[2].y) + (m_planes[2].z * m_planes[2].z));
m_planes[2].x /= t;
m_planes[2].y /= t;
m_planes[2].z /= t;
m_planes[2].w /= t;
// Calculate the right plane of frustum.
m_planes[3].x = matrix._14 - matrix._11;
m_planes[3].y = matrix._24 - matrix._21;
m_planes[3].z = matrix._34 - matrix._31;
m_planes[3].w = matrix._44 - matrix._41;
// Normalize it.
t = (float)sqrt((m_planes[3].x * m_planes[3].x) + (m_planes[3].y * m_planes[3].y) + (m_planes[3].z * m_planes[3].z));
m_planes[3].x /= t;
m_planes[3].y /= t;
m_planes[3].z /= t;
m_planes[3].w /= t;
// Calculate the top plane of frustum.
m_planes[4].x = matrix._14 - matrix._12;
m_planes[4].y = matrix._24 - matrix._22;
m_planes[4].z = matrix._34 - matrix._32;
m_planes[4].w = matrix._44 - matrix._42;
// Normalize it.
t = (float)sqrt((m_planes[4].x * m_planes[4].x) + (m_planes[4].y * m_planes[4].y) + (m_planes[4].z * m_planes[4].z));
m_planes[4].x /= t;
m_planes[4].y /= t;
m_planes[4].z /= t;
m_planes[4].w /= t;
// Calculate the bottom plane of frustum.
m_planes[5].x = matrix._14 + matrix._12;
m_planes[5].y = matrix._24 + matrix._22;
m_planes[5].z = matrix._34 + matrix._32;
m_planes[5].w = matrix._44 + matrix._42;
// Normalize it.
t = (float)sqrt((m_planes[5].x * m_planes[5].x) + (m_planes[5].y * m_planes[5].y) + (m_planes[5].z * m_planes[5].z));
m_planes[5].x /= t;
m_planes[5].y /= t;
m_planes[5].z /= t;
m_planes[5].w /= t;
return;
}
bool FrustumClass::CheckPoint(float x, float y, float z)
{
int i;
// Check if the point is inside all six planes of the view frustum.
for (i = 0; i < 6; i++)
{
if (((m_planes[i].x * x) + (m_planes[i].y * y) + (m_planes[i].z * z) + m_planes[i].w) < 0.0f)
{
return false;
}
}
return true;
}
bool FrustumClass::CheckCube(float xCenter, float yCenter, float zCenter, float radius)
{
int i;
// Check if any one point of the cube is in the view frustum.
for (i = 0; i < 6; i++)
{
if (m_planes[i].x * (xCenter - radius) +
m_planes[i].y * (yCenter - radius) +
m_planes[i].z * (zCenter - radius) + m_planes[i].w >= 0.0f)
{
continue;
}
if (m_planes[i].x * (xCenter + radius) +
m_planes[i].y * (yCenter - radius) +
m_planes[i].z * (zCenter - radius) + m_planes[i].w >= 0.0f)
{
continue;
}
if (m_planes[i].x * (xCenter - radius) +
m_planes[i].y * (yCenter + radius) +
m_planes[i].z * (zCenter - radius) + m_planes[i].w >= 0.0f)
{
continue;
}
if (m_planes[i].x * (xCenter + radius) +
m_planes[i].y * (yCenter + radius) +
m_planes[i].z * (zCenter - radius) + m_planes[i].w >= 0.0f)
{
continue;
}
if (m_planes[i].x * (xCenter - radius) +
m_planes[i].y * (yCenter - radius) +
m_planes[i].z * (zCenter + radius) + m_planes[i].w >= 0.0f)
{
continue;
}
if (m_planes[i].x * (xCenter + radius) +
m_planes[i].y * (yCenter - radius) +
m_planes[i].z * (zCenter + radius) + m_planes[i].w >= 0.0f)
{
continue;
}
if (m_planes[i].x * (xCenter - radius) +
m_planes[i].y * (yCenter + radius) +
m_planes[i].z * (zCenter + radius) + m_planes[i].w >= 0.0f)
{
continue;
}
if (m_planes[i].x * (xCenter + radius) +
m_planes[i].y * (yCenter + radius) +
m_planes[i].z * (zCenter + radius) + m_planes[i].w >= 0.0f)
{
continue;
}
return false;
}
return true;
}
bool FrustumClass::CheckSphere(float xCenter, float yCenter, float zCenter, float radius)
{
int i;
// Check if the radius of the sphere is inside the view frustum.
for (i = 0; i < 6; i++)
{
if (((m_planes[i].x * xCenter) + (m_planes[i].y * yCenter) + (m_planes[i].z * zCenter) + m_planes[i].w) < -radius)
{
return false;
}
}
return true;
}
bool FrustumClass::CheckRectangle(float xCenter, float yCenter, float zCenter, float xSize, float ySize, float zSize)
{
int i;
// Check if any of the 6 planes of the rectangle are inside the view frustum.
for (i = 0; i < 6; i++)
{
if (m_planes[i].x * (xCenter - xSize) +
m_planes[i].y * (yCenter - ySize) +
m_planes[i].z * (zCenter - zSize) + m_planes[i].w >= 0.0f)
{
continue;
}
if (m_planes[i].x * (xCenter + xSize) +
m_planes[i].y * (yCenter - ySize) +
m_planes[i].z * (zCenter - zSize) + m_planes[i].w >= 0.0f)
{
continue;
}
if (m_planes[i].x * (xCenter - xSize) +
m_planes[i].y * (yCenter + ySize) +
m_planes[i].z * (zCenter - zSize) + m_planes[i].w >= 0.0f)
{
continue;
}
if (m_planes[i].x * (xCenter - xSize) +
m_planes[i].y * (yCenter - ySize) +
m_planes[i].z * (zCenter + zSize) + m_planes[i].w >= 0.0f)
{
continue;
}
if (m_planes[i].x * (xCenter + xSize) +
m_planes[i].y * (yCenter + ySize) +
m_planes[i].z * (zCenter - zSize) + m_planes[i].w >= 0.0f)
{
continue;
}
if (m_planes[i].x * (xCenter + xSize) +
m_planes[i].y * (yCenter - ySize) +
m_planes[i].z * (zCenter + zSize) + m_planes[i].w >= 0.0f)
{
continue;
}
if (m_planes[i].x * (xCenter - xSize) +
m_planes[i].y * (yCenter + ySize) +
m_planes[i].z * (zCenter + zSize) + m_planes[i].w >= 0.0f)
{
continue;
}
if (m_planes[i].x * (xCenter + xSize) +
m_planes[i].y * (yCenter + ySize) +
m_planes[i].z * (zCenter + zSize) + m_planes[i].w >= 0.0f)
{
continue;
}
return false;
}
return true;
}