From 0d003a2d2a8807983f23372dd15eabd403cd4b1c Mon Sep 17 00:00:00 2001 From: Woazboat Date: Wed, 29 Apr 2015 00:14:42 +0200 Subject: [PATCH 1/6] Changed Tracer::m_NormalTable to static array Was previously instantiated for every trace --- src/Tracer.cpp | 27 ++++++++++++++++++++------- src/Tracer.h | 4 +++- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/Tracer.cpp b/src/Tracer.cpp index e604f4a5b..bd5fcebc5 100644 --- a/src/Tracer.cpp +++ b/src/Tracer.cpp @@ -13,16 +13,29 @@ +const std::array& cTracer::m_NormalTable(void) +{ + static std::array* table = + new std::array + { + { + Vector3f(-1, 0, 0), // 1: -x + Vector3f( 0, 0, -1), // 2: -z + Vector3f( 1, 0, 0), // 3: +x + Vector3f( 0, 0, 1), // 4: +z + Vector3f( 0, 1, 0), // 5: +y + Vector3f( 0, -1, 0) // 6: -y + } + }; + + return *table; +}; + + cTracer::cTracer(cWorld * a_World): m_World(a_World) { - m_NormalTable[0].Set(-1, 0, 0); - m_NormalTable[1].Set( 0, 0, -1); - m_NormalTable[2].Set( 1, 0, 0); - m_NormalTable[3].Set( 0, 0, 1); - m_NormalTable[4].Set( 0, 1, 0); - m_NormalTable[5].Set( 0, -1, 0); } @@ -241,7 +254,7 @@ bool cTracer::Trace(const Vector3f & a_Start, const Vector3f & a_Direction, int int Normal = GetHitNormal(a_Start, End, pos); if (Normal > 0) { - HitNormal = m_NormalTable[Normal-1]; + HitNormal = m_NormalTable()[Normal - 1]; } return true; } diff --git a/src/Tracer.h b/src/Tracer.h index ec87d449e..cf54fa66c 100644 --- a/src/Tracer.h +++ b/src/Tracer.h @@ -3,6 +3,8 @@ #include "Vector3.h" +#include + @@ -64,7 +66,7 @@ private: float SigNum( float a_Num); cWorld* m_World; - Vector3f m_NormalTable[6]; + static const std::array & m_NormalTable(void); Vector3f dir; Vector3f tDelta; From c74bfc35d61022c1d1e660935601d461b39b8b88 Mon Sep 17 00:00:00 2001 From: Woazboat Date: Tue, 28 Apr 2015 02:47:36 +0200 Subject: [PATCH 2/6] Check for zero length vector in Trace Added hasNonZeroLength member function to Vector3 --- src/Tracer.cpp | 14 ++++++++++---- src/Vector3.h | 5 +++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/Tracer.cpp b/src/Tracer.cpp index bd5fcebc5..38968bc61 100644 --- a/src/Tracer.cpp +++ b/src/Tracer.cpp @@ -69,6 +69,9 @@ float cTracer::SigNum(float a_Num) void cTracer::SetValues(const Vector3f & a_Start, const Vector3f & a_Direction) { + // Since this method should only be called by Trace, zero length vectors should already have been taken care of + ASSERT(a_Direction.HasNonZeroLength()); + // calculate the direction of the ray (linear algebra) dir = a_Direction; @@ -78,10 +81,8 @@ void cTracer::SetValues(const Vector3f & a_Start, const Vector3f & a_Direction) step.z = (int) SigNum(dir.z); // normalize the direction vector - if (dir.SqrLength() > 0.f) - { - dir.Normalize(); - } + dir.Normalize(); + // how far we must move in the ray direction before // we encounter a new voxel in x-direction @@ -151,6 +152,11 @@ void cTracer::SetValues(const Vector3f & a_Start, const Vector3f & a_Direction) bool cTracer::Trace(const Vector3f & a_Start, const Vector3f & a_Direction, int a_Distance, bool a_LineOfSight) { + if (!a_Direction.HasNonZeroLength()) + { + return false; + } + if ((a_Start.y < 0) || (a_Start.y >= cChunkDef::Height)) { LOGD("%s: Start Y is outside the world (%.2f), not tracing.", __FUNCTION__, a_Start.y); diff --git a/src/Vector3.h b/src/Vector3.h index 36f277ba4..a42003aae 100644 --- a/src/Vector3.h +++ b/src/Vector3.h @@ -78,6 +78,11 @@ public: ); } + inline bool HasNonZeroLength(void) const + { + return ((x != 0) || (y != 0) || (z != 0)); + } + inline double Length(void) const { return sqrt(static_cast(x * x + y * y + z * z)); From 8a50918d2a58a84111567d73949fe67b9424c660 Mon Sep 17 00:00:00 2001 From: Woazboat Date: Tue, 28 Apr 2015 02:51:21 +0200 Subject: [PATCH 3/6] Tracer::signum function now returns int convert c style casts to c++ static casts Changed fabs() to std::abs() --- src/SetChunkData.cpp | 2 +- src/Tracer.cpp | 49 +++++++++++++++++++++++--------------------- src/Tracer.h | 3 ++- 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/src/SetChunkData.cpp b/src/SetChunkData.cpp index e5afd96ed..7549b0dbf 100644 --- a/src/SetChunkData.cpp +++ b/src/SetChunkData.cpp @@ -103,7 +103,7 @@ void cSetChunkData::CalculateHeightMap(void) int index = cChunkDef::MakeIndexNoCheck(x, y, z); if (m_BlockTypes[index] != E_BLOCK_AIR) { - m_HeightMap[x + z * cChunkDef::Width] = (HEIGHTTYPE)y; + m_HeightMap[x + z * cChunkDef::Width] = static_cast(y); break; } } // for y diff --git a/src/Tracer.cpp b/src/Tracer.cpp index 38968bc61..b6b0fd634 100644 --- a/src/Tracer.cpp +++ b/src/Tracer.cpp @@ -12,6 +12,8 @@ +const float FLOAT_EPSILON = 0.0001f; // TODO: Stash this in some header where it can be reused + const std::array& cTracer::m_NormalTable(void) { @@ -50,7 +52,7 @@ cTracer::~cTracer() -float cTracer::SigNum(float a_Num) +int cTracer::SigNum(float a_Num) { if (a_Num < 0.f) { @@ -76,9 +78,10 @@ void cTracer::SetValues(const Vector3f & a_Start, const Vector3f & a_Direction) dir = a_Direction; // decide which direction to start walking in - step.x = (int) SigNum(dir.x); - step.y = (int) SigNum(dir.y); - step.z = (int) SigNum(dir.z); + step.x = SigNum(dir.x); + step.y = SigNum(dir.y); + step.z = SigNum(dir.z); + // normalize the direction vector dir.Normalize(); @@ -89,7 +92,7 @@ void cTracer::SetValues(const Vector3f & a_Start, const Vector3f & a_Direction) // same but y-direction if (dir.x != 0.f) { - tDelta.x = 1 / fabs(dir.x); + tDelta.x = 1 / std::abs(dir.x); } else { @@ -97,7 +100,7 @@ void cTracer::SetValues(const Vector3f & a_Start, const Vector3f & a_Direction) } if (dir.y != 0.f) { - tDelta.y = 1 / fabs(dir.y); + tDelta.y = 1 / std::abs(dir.y); } else { @@ -105,44 +108,45 @@ void cTracer::SetValues(const Vector3f & a_Start, const Vector3f & a_Direction) } if (dir.z != 0.f) { - tDelta.z = 1 / fabs(dir.z); + tDelta.z = 1 / std::abs(dir.z); } else { tDelta.z = 0; } + // start voxel coordinates - pos.x = (int)floorf(a_Start.x); - pos.y = (int)floorf(a_Start.y); - pos.z = (int)floorf(a_Start.z); + pos.x = static_cast(floorf(a_Start.x)); + pos.y = static_cast(floorf(a_Start.y)); + pos.z = static_cast(floorf(a_Start.z)); // calculate distance to first intersection in the voxel we start from if (dir.x < 0) { - tMax.x = ((float)pos.x - a_Start.x) / dir.x; + tMax.x = (static_cast(pos.x) - a_Start.x) / dir.x; } else { - tMax.x = (((float)pos.x + 1) - a_Start.x) / dir.x; + tMax.x = (static_cast(pos.x + 1) - a_Start.x) / dir.x; // TODO: Possible division by zero } if (dir.y < 0) { - tMax.y = ((float)pos.y - a_Start.y) / dir.y; + tMax.y = (static_cast(pos.y) - a_Start.y) / dir.y; } else { - tMax.y = (((float)pos.y + 1) - a_Start.y) / dir.y; + tMax.y = (static_cast(pos.y + 1) - a_Start.y) / dir.y; // TODO: Possible division by zero } if (dir.z < 0) { - tMax.z = ((float)pos.z - a_Start.z) / dir.z; + tMax.z = (static_cast(pos.z) - a_Start.z) / dir.z; } else { - tMax.z = (((float)pos.z + 1) - a_Start.z) / dir.z; + tMax.z = (static_cast(pos.z + 1) - a_Start.z) / dir.z; // TODO: Possible division by zero } } @@ -165,18 +169,18 @@ bool cTracer::Trace(const Vector3f & a_Start, const Vector3f & a_Direction, int SetValues(a_Start, a_Direction); - Vector3f End = a_Start + (dir * (float)a_Distance); + Vector3f End = a_Start + (dir * static_cast(a_Distance)); if (End.y < 0) { - float dist = -a_Start.y / dir.y; + float dist = -a_Start.y / dir.y; // No division by 0 possible End = a_Start + (dir * dist); } // end voxel coordinates - end1.x = (int)floorf(End.x); - end1.y = (int)floorf(End.y); - end1.z = (int)floorf(End.z); + end1.x = static_cast(floorf(End.x)); + end1.y = static_cast(floorf(End.y)); + end1.z = static_cast(floorf(End.z)); // check if first is occupied if (pos.Equals(end1)) @@ -314,8 +318,7 @@ int cTracer::intersect3D_SegmentPlane(const Vector3f & a_Origin, const Vector3f float D = a_PlaneNormal.Dot(u); // dot(Pn.n, u); float N = -(a_PlaneNormal.Dot(w)); // -dot(a_Plane.n, w); - const float EPSILON = 0.0001f; - if (fabs(D) < EPSILON) + if (std::abs(D) < FLOAT_EPSILON) { // segment is parallel to plane if (N == 0.0) diff --git a/src/Tracer.h b/src/Tracer.h index cf54fa66c..31531719f 100644 --- a/src/Tracer.h +++ b/src/Tracer.h @@ -63,7 +63,8 @@ private: /// Return 1 through 6 for the following block faces, repectively: -x, -z, x, z, y, -y int GetHitNormal( const Vector3f & start, const Vector3f & end, const Vector3i & a_BlockPos); - float SigNum( float a_Num); + /// Signum function + int SigNum( float a_Num); cWorld* m_World; static const std::array & m_NormalTable(void); From 689fe6041c746d608330700160d3a71fb182be0b Mon Sep 17 00:00:00 2001 From: Woazboat Date: Tue, 28 Apr 2015 02:54:45 +0200 Subject: [PATCH 4/6] Changed Vector3 Equals function to avoid using memcmp --- src/Vector3.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Vector3.h b/src/Vector3.h index a42003aae..6164721da 100644 --- a/src/Vector3.h +++ b/src/Vector3.h @@ -126,11 +126,7 @@ public: { // Perform a bitwise comparison of the contents - we want to know whether this object is exactly equal // To perform EPS-based comparison, use the EqualsEps() function - return ( - (memcmp(&x, &a_Rhs.x, sizeof(x)) == 0) && - (memcmp(&y, &a_Rhs.y, sizeof(y)) == 0) && - (memcmp(&z, &a_Rhs.z, sizeof(z)) == 0) - ); + return !((x != a_Rhs.x) || (y != a_Rhs.y) || (z != a_Rhs.z)); } inline bool EqualsEps(const Vector3 & a_Rhs, T a_Eps) const From ed404bc2f6488a59da280697ad6c3a8ffcbab0fd Mon Sep 17 00:00:00 2001 From: Woazboat Date: Tue, 5 May 2015 22:21:07 +0200 Subject: [PATCH 5/6] Ignoring Clang warnings for strict float comparison in Vector::Equals() --- src/Vector3.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Vector3.h b/src/Vector3.h index 6164721da..d454fda06 100644 --- a/src/Vector3.h +++ b/src/Vector3.h @@ -124,9 +124,19 @@ public: inline bool Equals(const Vector3 & a_Rhs) const { - // Perform a bitwise comparison of the contents - we want to know whether this object is exactly equal + // Perform a strict comparison of the contents - we want to know whether this object is exactly equal // To perform EPS-based comparison, use the EqualsEps() function + +#ifndef __GNUC__ +#pragma clang diagnostics push +#pragma clang diagnostics ignored "-Wfloat-equal" +#endif + return !((x != a_Rhs.x) || (y != a_Rhs.y) || (z != a_Rhs.z)); + +#ifndef __GNUC__ +#pragma clang diagnostics pop +#endif } inline bool EqualsEps(const Vector3 & a_Rhs, T a_Eps) const From eb84ffe5a6eb4a79b91e58c263bf222496ad5afb Mon Sep 17 00:00:00 2001 From: Woazboat Date: Wed, 6 May 2015 01:53:28 +0200 Subject: [PATCH 6/6] Added float comparison warning overrides to Vector3::hasNonZeroLength --- src/Vector3.h | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/Vector3.h b/src/Vector3.h index d454fda06..f116c07f6 100644 --- a/src/Vector3.h +++ b/src/Vector3.h @@ -80,7 +80,16 @@ public: inline bool HasNonZeroLength(void) const { + #ifndef __GNUC__ + #pragma clang diagnostics push + #pragma clang diagnostics ignored "-Wfloat-equal" + #endif + return ((x != 0) || (y != 0) || (z != 0)); + + #ifndef __GNUC__ + #pragma clang diagnostics pop + #endif } inline double Length(void) const @@ -127,16 +136,16 @@ public: // Perform a strict comparison of the contents - we want to know whether this object is exactly equal // To perform EPS-based comparison, use the EqualsEps() function -#ifndef __GNUC__ -#pragma clang diagnostics push -#pragma clang diagnostics ignored "-Wfloat-equal" -#endif + #ifndef __GNUC__ + #pragma clang diagnostics push + #pragma clang diagnostics ignored "-Wfloat-equal" + #endif return !((x != a_Rhs.x) || (y != a_Rhs.y) || (z != a_Rhs.z)); -#ifndef __GNUC__ -#pragma clang diagnostics pop -#endif + #ifndef __GNUC__ + #pragma clang diagnostics pop + #endif } inline bool EqualsEps(const Vector3 & a_Rhs, T a_Eps) const