1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
inline cPlane PlaneNormalize(const Plane& p) {const float fLength = Vector3Length(p.n); return Plane(p.n / fLength, p.d / fLength);}
void FrustumCulling::ConstructFrustum(const Matrix& mView, const Matrix& mProjection)
{
Matrix mTemp(mView * mProjection);
// Linke Clippingebene
m_pClippingPlanes[0].a = -(mTemp.m14 + mTemp.m11);
m_pClippingPlanes[0].b = -(mTemp.m24 + mTemp.m21);
m_pClippingPlanes[0].c = -(mTemp.m34 + mTemp.m31);
m_pClippingPlanes[0].d = -(mTemp.m44 + mTemp.m41);
m_pClippingPlanes[0] = PlaneNormalize(m_pClippingPlanes[0]);
// Rechte Clippingebene
m_pClippingPlanes[1].a = -(mTemp.m14 - mTemp.m11);
m_pClippingPlanes[1].b = -(mTemp.m24 - mTemp.m21);
m_pClippingPlanes[1].c = -(mTemp.m34 - mTemp.m31);
m_pClippingPlanes[1].d = -(mTemp.m44 - mTemp.m41);
m_pClippingPlanes[1] = PlaneNormalize(m_pClippingPlanes[1]);
// Obere Clippingebene
m_pClippingPlanes[2].a = -(mTemp.m14 - mTemp.m12);
m_pClippingPlanes[2].b = -(mTemp.m24 - mTemp.m22);
m_pClippingPlanes[2].c = -(mTemp.m34 - mTemp.m32);
m_pClippingPlanes[2].d = -(mTemp.m44 - mTemp.m42);
m_pClippingPlanes[2] = PlaneNormalize(m_pClippingPlanes[2]);
// Untere Clippingebene
m_pClippingPlanes[3].a = -(mTemp.m14 + mTemp.m12);
m_pClippingPlanes[3].b = -(mTemp.m24 + mTemp.m22);
m_pClippingPlanes[3].c = -(mTemp.m34 + mTemp.m32);
m_pClippingPlanes[3].d = -(mTemp.m44 + mTemp.m42);
m_pClippingPlanes[3] = PlaneNormalize(m_pClippingPlanes[3]);
// Nahe Clippingebene
m_pClippingPlanes[4].a = -(mTemp.m14 + mTemp.m13);
m_pClippingPlanes[4].b = -(mTemp.m24 + mTemp.m23);
m_pClippingPlanes[4].c = -(mTemp.m34 + mTemp.m33);
m_pClippingPlanes[4].d = -(mTemp.m44 + mTemp.m43);
m_pClippingPlanes[4] = PlaneNormalize(m_pClippingPlanes[4]);
// Ferne Clippingebene
m_pClippingPlanes[5].a = -(mTemp.m14 - mTemp.m13);
m_pClippingPlanes[5].b = -(mTemp.m24 - mTemp.m23);
m_pClippingPlanes[5].c = -(mTemp.m34 - mTemp.m33);
m_pClippingPlanes[5].d = -(mTemp.m44 - mTemp.m43);
m_pClippingPlanes[5] = PlaneNormalize(m_pClippingPlanes[5]);
}
bool FrustumCulling::BoxVisible(const Vector3& vBoxMin, const Vector3& vBoxMax, const Matrix& mBoxTransformation)
{
if(!m_pClippingPlanes)
LOG_ERROR_NULL_POINTER("m_pClippingPlanes", false);
Matrix mInvBoxTransformation = MatrixInvert(mBoxTransformation);
if(ClassifyBox_Inv(vBoxMin, vBoxMax, mInvBoxTransformation, m_pClippingPlanes[0]) == 1) return false;
if(ClassifyBox_Inv(vBoxMin, vBoxMax, mInvBoxTransformation, m_pClippingPlanes[1]) == 1) return false;
if(ClassifyBox_Inv(vBoxMin, vBoxMax, mInvBoxTransformation, m_pClippingPlanes[2]) == 1) return false;
if(ClassifyBox_Inv(vBoxMin, vBoxMax, mInvBoxTransformation, m_pClippingPlanes[3]) == 1) return false;
if(ClassifyBox_Inv(vBoxMin, vBoxMax, mInvBoxTransformation, m_pClippingPlanes[4]) == 1) return false;
return ClassifyBox_Inv(vBoxMin, vBoxMax, mInvBoxTransformation, m_pClippingPlanes[5]) != 1 ? true : false;
}
NXE_API cPlane PlaneTransform(const cPlane& p, const Matrix& m)
{
const float a = p.a * m.m11 + p.b * m.m21 + p.c * m.m31;
const float b = p.a * m.m12 + p.b * m.m22 + p.c * m.m32;
const float c = p.a * m.m13 + p.b * m.m23 + p.c * m.m33;
return cPlane(a, b, c,
p.d - (a * m.m41 + b * m.m42 + c * m.m43));
}
inline float PlaneDotCoords(const Plane& p, const Vector3& v) {return p.a * v.x + p.b * v.y + p.c * v.z + p.d;}
NXE_API int32_t ClassifyBox_Inv(const Vector3& vBoxMin,
const Vector3& vBoxMax,
const Matrix& mInvBoxTransformation,
const Plane& Plane)
{
Plane NewPlane(PlaneTransform(Plane, mInvBoxTransformation));
Vector3 vNearPoint(vBoxMax);
Vector3 vFarPoint(vBoxMin);
if(NewPlane.a > 0.0f) {vNearPoint.x = vBoxMin.x; vFarPoint.x = vBoxMax.x;}
if(NewPlane.b > 0.0f) {vNearPoint.y = vBoxMin.y; vFarPoint.y = vBoxMax.y;}
if(NewPlane.c > 0.0f) {vNearPoint.z = vBoxMin.z; vFarPoint.z = vBoxMax.z;}
if(PlaneDotCoords(NewPlane, vNearPoint) > 0.0f) return 1;
if(PlaneDotCoords(NewPlane, vFarPoint) > 0.0f) return 0;
return -1;
}
|