From 6fbc524e653dd672669d4adde55dcaf89149689b Mon Sep 17 00:00:00 2001 From: Ykkrosh Date: Sat, 12 Dec 2009 17:52:38 +0000 Subject: [PATCH] # Terrain-related bug fixes Fix several off-by-one errors Reorder some loops to be theoretically more efficient Other minor cleanups This was SVN commit r7221. --- source/graphics/Terrain.cpp | 58 ++++++++++++++++++++----------------- source/graphics/Terrain.h | 8 ----- 2 files changed, 31 insertions(+), 35 deletions(-) diff --git a/source/graphics/Terrain.cpp b/source/graphics/Terrain.cpp index 2548e14916..2af06dc08c 100644 --- a/source/graphics/Terrain.cpp +++ b/source/graphics/Terrain.cpp @@ -218,22 +218,23 @@ CMiniPatch* CTerrain::GetTile(ssize_t i, ssize_t j) const float CTerrain::GetVertexGroundLevel(ssize_t i, ssize_t j) const { - i = ClampCoordToMap(i); - j = ClampCoordToMap(j); + i = clamp(i, (ssize_t)0, m_MapSize-1); + j = clamp(j, (ssize_t)0, m_MapSize-1); return HEIGHT_SCALE * m_Heightmap[j*m_MapSize + i]; } float CTerrain::GetSlope(float x, float z) const { - const ssize_t xi = ClampCoordToMap((ssize_t)floor(x/CELL_SIZE)); - const ssize_t zi = ClampCoordToMap((ssize_t)floor(z/CELL_SIZE)); + // Clamp to size-2 so we can use the tiles (xi,zi)-(xi+1,zi+1) + const ssize_t xi = clamp((ssize_t)floor(x/CELL_SIZE), (ssize_t)0, m_MapSize-2); + const ssize_t zi = clamp((ssize_t)floor(z/CELL_SIZE), (ssize_t)0, m_MapSize-2); float h00 = m_Heightmap[zi*m_MapSize + xi]; - float h01 = m_Heightmap[zi*m_MapSize + xi + m_MapSize]; - float h10 = m_Heightmap[zi*m_MapSize + xi + 1]; - float h11 = m_Heightmap[zi*m_MapSize + xi + m_MapSize + 1]; + float h01 = m_Heightmap[(zi+1)*m_MapSize + xi]; + float h10 = m_Heightmap[zi*m_MapSize + (xi+1)]; + float h11 = m_Heightmap[(zi+1)*m_MapSize + (xi+1)]; - //Difference of highest point from lowest point + // Difference of highest point from lowest point return std::max(std::max(h00, h01), std::max(h10, h11)) - std::min(std::min(h00, h01), std::min(h10, h11)); } @@ -261,15 +262,18 @@ CVector2D CTerrain::GetSlopeAngleFace( CEntity* entity ) const float CTerrain::GetExactGroundLevel(float x, float z) const { - const ssize_t xi = ClampCoordToMap((ssize_t)floor(x/CELL_SIZE)); - const ssize_t zi = ClampCoordToMap((ssize_t)floor(z/CELL_SIZE)); + // Clamp to size-2 so we can use the tiles (xi,zi)-(xi+1,zi+1) + const ssize_t xi = clamp((ssize_t)floor(x/CELL_SIZE), (ssize_t)0, m_MapSize-2); + const ssize_t zi = clamp((ssize_t)floor(z/CELL_SIZE), (ssize_t)0, m_MapSize-2); + const float xf = clamp(x/CELL_SIZE-xi, 0.0f, 1.0f); const float zf = clamp(z/CELL_SIZE-zi, 0.0f, 1.0f); float h00 = m_Heightmap[zi*m_MapSize + xi]; - float h01 = m_Heightmap[zi*m_MapSize + xi + m_MapSize]; - float h10 = m_Heightmap[zi*m_MapSize + xi + 1]; - float h11 = m_Heightmap[zi*m_MapSize + xi + m_MapSize + 1]; + float h01 = m_Heightmap[(zi+1)*m_MapSize + xi]; + float h10 = m_Heightmap[zi*m_MapSize + (xi+1)]; + float h11 = m_Heightmap[(zi+1)*m_MapSize + (xi+1)]; + // Linearly interpolate return (HEIGHT_SCALE * ( (1 - zf) * ((1 - xf) * h00 + xf * h10) + zf * ((1 - xf) * h01 + xf * h11))); @@ -298,13 +302,13 @@ void CTerrain::Resize(ssize_t size) if (size>m_MapSizePatches) { // new map is bigger than old one - zero the heightmap so we don't get uninitialised // height data along the expanded edges - memset(newHeightmap,0,newMapSize*newMapSize); + memset(newHeightmap,0,newMapSize*newMapSize*sizeof(u16)); } // now copy over rows of data u16* src=m_Heightmap; u16* dst=newHeightmap; - ssize_t copysize=newMapSize>m_MapSize ? m_MapSize : newMapSize; + ssize_t copysize=std::min(newMapSize, m_MapSize); for (ssize_t j=0;jSetDirty(RENDERDATA_UPDATE_VERTICES); @@ -453,10 +457,10 @@ float CTerrain::FlattenArea(float x0, float x1, float z0, float z1) void CTerrain::MakeDirty(ssize_t i0, ssize_t j0, ssize_t i1, ssize_t j1, int dirtyFlags) { // flag vertex data as dirty for affected patches, and rebuild bounds of these patches - ssize_t pi0 = clamp((i0/PATCH_SIZE)-1, ssize_t(0), m_MapSizePatches-1); - ssize_t pi1 = clamp((i1/PATCH_SIZE)+1, ssize_t(0), m_MapSizePatches-1); - ssize_t pj0 = clamp((j0/PATCH_SIZE)-1, ssize_t(0), m_MapSizePatches-1); - ssize_t pj1 = clamp((j1/PATCH_SIZE)+1, ssize_t(0), m_MapSizePatches-1); + ssize_t pi0 = clamp((i0/PATCH_SIZE)-1, (ssize_t)0, m_MapSizePatches); + ssize_t pi1 = clamp((i1/PATCH_SIZE)+1, (ssize_t)0, m_MapSizePatches); + ssize_t pj0 = clamp((j0/PATCH_SIZE)-1, (ssize_t)0, m_MapSizePatches); + ssize_t pj1 = clamp((j1/PATCH_SIZE)+1, (ssize_t)0, m_MapSizePatches); for (ssize_t j = pj0; j < pj1; j++) { for (ssize_t i = pi0; i < pi1; i++) { CPatch* patch = GetPatch(i,j); // can't fail (i,j were clamped) diff --git a/source/graphics/Terrain.h b/source/graphics/Terrain.h index 54c08e9bfe..d8b2c399ea 100644 --- a/source/graphics/Terrain.h +++ b/source/graphics/Terrain.h @@ -24,7 +24,6 @@ #include "maths/Vector3D.h" #include "graphics/SColor.h" -#include "maths/MathUtil.h" // clamp #include "lib/sysdep/cpu.h" class HEntity; @@ -76,13 +75,6 @@ public: bool IsPassable(const CVector2D& tileSpaceLoc, HEntity entity) const; - ssize_t ClampCoordToMap(ssize_t index) const - { - // GetSlope wants to access the next index, - // hence clamp to size-2 - return clamp(index, ssize_t(0), m_MapSize-2); - } - float GetVertexGroundLevel(ssize_t i, ssize_t j) const; float GetExactGroundLevel(float x, float z) const; float GetExactGroundLevel(const CVector2D& v) const;