summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/BoundingBox.cpp16
-rw-r--r--src/Entities/Entity.cpp25
2 files changed, 27 insertions, 14 deletions
diff --git a/src/BoundingBox.cpp b/src/BoundingBox.cpp
index 1356e165c..e60be3476 100644
--- a/src/BoundingBox.cpp
+++ b/src/BoundingBox.cpp
@@ -213,41 +213,45 @@ bool cBoundingBox::CalcLineIntersection(Vector3d a_Min, Vector3d a_Max, Vector3d
return true;
}
+ // Correction for floating point imprecision when calculating
+ // the coefficient to intersect a plane by slightly increasing it
+ static const auto Correction = 1.000001;
+
eBlockFace Face = BLOCK_FACE_NONE;
double Coeff = Vector3d::NO_INTERSECTION;
// Check each individual bbox face for intersection with the line, remember the one with the lowest coeff
- double c = a_Line1.LineCoeffToXYPlane(a_Line2, a_Min.z);
+ double c = a_Line1.LineCoeffToXYPlane(a_Line2, a_Min.z) * Correction;
if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c))
{
Face = (a_Line1.z > a_Line2.z) ? BLOCK_FACE_ZP : BLOCK_FACE_ZM;
Coeff = c;
}
- c = a_Line1.LineCoeffToXYPlane(a_Line2, a_Max.z);
+ c = a_Line1.LineCoeffToXYPlane(a_Line2, a_Max.z) * Correction;
if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c))
{
Face = (a_Line1.z > a_Line2.z) ? BLOCK_FACE_ZP : BLOCK_FACE_ZM;
Coeff = c;
}
- c = a_Line1.LineCoeffToXZPlane(a_Line2, a_Min.y);
+ c = a_Line1.LineCoeffToXZPlane(a_Line2, a_Min.y) * Correction;
if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c))
{
Face = (a_Line1.y > a_Line2.y) ? BLOCK_FACE_YP : BLOCK_FACE_YM;
Coeff = c;
}
- c = a_Line1.LineCoeffToXZPlane(a_Line2, a_Max.y);
+ c = a_Line1.LineCoeffToXZPlane(a_Line2, a_Max.y) * Correction;
if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c))
{
Face = (a_Line1.y > a_Line2.y) ? BLOCK_FACE_YP : BLOCK_FACE_YM;
Coeff = c;
}
- c = a_Line1.LineCoeffToYZPlane(a_Line2, a_Min.x);
+ c = a_Line1.LineCoeffToYZPlane(a_Line2, a_Min.x) * Correction;
if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c))
{
Face = (a_Line1.x > a_Line2.x) ? BLOCK_FACE_XP : BLOCK_FACE_XM;
Coeff = c;
}
- c = a_Line1.LineCoeffToYZPlane(a_Line2, a_Max.x);
+ c = a_Line1.LineCoeffToYZPlane(a_Line2, a_Max.x) * Correction;
if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c))
{
Face = (a_Line1.x > a_Line2.x) ? BLOCK_FACE_XP : BLOCK_FACE_XM;
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index 37ef925cf..1f270cff0 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -1067,9 +1067,15 @@ void cEntity::HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
// TODO: checks too much, very inefficient
for (int i = bstart.x; i <= bend.x; i++)
- for (int j = bstart.y; j <= bend.y; j++)
- for (int k = bstart.z; k <= bend.z; k++)
- Checks.emplace(Vector3i(i, j, k));
+ {
+ for (int j = bstart.y; j <= bend.y; j++)
+ {
+ for (int k = bstart.z; k <= bend.z; k++)
+ {
+ Checks.emplace(Vector3i(i, j, k));
+ }
+ }
+ }
return Checks;
}
@@ -1146,15 +1152,18 @@ void cEntity::HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
eBlockFace Face; // Face hit
cBoundingBox bb(a_BlockPos, a_BlockPos + Vector3i(1, 1, 1)); // Bounding box of the block hit
+ // First calculate line intersection
if (!bb.CalcLineIntersection(m_Start, m_End, LineCoeff, Face))
{
- // Math rounding errors have caused the calculation to miss the block completely, assume immediate hit
- LineCoeff = 0;
+ // Maths rounding errors have caused the calculation to miss the block completely
+ m_HitCoords = m_End;
+ m_HitBlockFace = BLOCK_FACE_NONE;
+ return true;
}
- m_HitCoords = m_Start + (m_End - m_Start) * LineCoeff; // Point where projectile goes into the hit block
-
- TestBoundingBoxCollisionWithEnvironment(m_HitCoords);
+ // Check bbox collision, setting final values
+ // Line tracer hit position is used as a starting point:
+ TestBoundingBoxCollisionWithEnvironment(m_Start + (m_End - m_Start) * LineCoeff);
return m_HitBlockFace != BLOCK_FACE_NONE;
}