TombEngine/TR5Main/Renderer/Frustum.cpp

87 lines
2.5 KiB
C++
Raw Normal View History

2020-04-13 00:36:53 +02:00
#include "Frustum.h"
DirectX::SimpleMath::Matrix inverseOrtho(const DirectX::SimpleMath::Matrix& m)
{
DirectX::SimpleMath::Matrix r;
r._11 = m._11; r._21 = m._12; r._31 = m._13; r._41 = 0;
r._12 = m._21; r._22 = m._22; r._32 = m._23; r._42 = 0;
r._13 = m._31; r._23 = m._32; r._33 = m._33; r._43 = 0;
r._14 = -(m._14 * m._11 + m._24 * m._21 + m._34 * m._31); // -dot(pos, right)
r._24 = -(m._14 * m._12 + m._24 * m._22 + m._34 * m._32); // -dot(pos, up)
r._34 = -(m._14 * m._13 + m._24 * m._23 + m._34 * m._33); // -dot(pos, dir)
r._44 = 1;
return r;
}
void Frustum::calcPlanes(const Matrix& mm)
{
Matrix m = mm.Transpose();
start = 0;
count = 5;
planes[0] = Vector4(m._41 - m._31, m._42 - m._32, m._43 - m._33, m._44 - m._34); // near
planes[1] = Vector4(m._41 - m._21, m._42 - m._22, m._43 - m._23, m._44 - m._24); // top
planes[2] = Vector4(m._41 - m._11, m._42 - m._12, m._43 - m._13, m._44 - m._14); // right
planes[3] = Vector4(m._41 + m._21, m._42 + m._22, m._43 + m._23, m._44 + m._24); // bottom
planes[4] = Vector4(m._41 + m._11, m._42 + m._12, m._43 + m._13, m._44 + m._14); // left
for (int i = 0; i < count; i++)
planes[i] *= 1.0f / DirectX::SimpleMath::Vector3(planes[i]).Length();
}
bool Frustum::isVisible(const Vector3& min, const Vector3& max) const
{
if (count < 4) return false;
for (int i = start; i < start + count; i++) {
const Vector3& n = Vector3(planes[i]);
const float d = -planes[i].w;
if (n.Dot(max) < d &&
n.Dot(min) < d &&
n.Dot(Vector3(min.x, max.y, max.z)) < d &&
n.Dot(Vector3(max.x, min.y, max.z)) < d &&
n.Dot(Vector3(min.x, min.y, max.z)) < d &&
n.Dot(Vector3(max.x, max.y, min.z)) < d &&
n.Dot(Vector3(min.x, max.y, min.z)) < d &&
n.Dot(Vector3(max.x, min.y, min.z)) < d)
return false;
}
return true;
}
bool Frustum::isVisible(const Matrix& matrix, const Vector3& min, const Vector3& max)
{
start = count;
// transform clip planes (relative)
Matrix m = inverseOrtho(matrix);
for (int i = 0; i < count; i++) {
Vector4& p = planes[i];
Vector4 o = Vector4::Transform(Vector4(p.x * (-p.w), p.y * (-p.w), p.z * (-p.w), 1.0f), m);
Vector4 n = Vector4::Transform(Vector4(p.x, p.y, p.z, 0), m);
planes[start + i] = Vector4(n.x, n.y, n.z, -Vector3(n).Dot(Vector3(o)));
}
bool visible = isVisible(min, max);
start = 0;
return visible;
}
bool Frustum::isVisible(const Vector3& center, float radius)
{
if (count < 4) return false;
for (int i = 0; i < count; i++)
if (Vector3(planes[i]).Dot(center) + planes[i].w < -radius)
return false;
return true;
}