From abe5d3185f25a119d3e863f5734aaeefa57cfdd8 Mon Sep 17 00:00:00 2001 From: Ykkrosh Date: Fri, 12 Feb 2010 12:01:46 +0000 Subject: [PATCH] Fix crash when constructing buildings off the edge of the map This was SVN commit r7320. --- source/graphics/Terrain.cpp | 4 +- source/graphics/tests/test_Terrain.h | 59 ++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/source/graphics/Terrain.cpp b/source/graphics/Terrain.cpp index 54999f3247..2c556d2f81 100644 --- a/source/graphics/Terrain.cpp +++ b/source/graphics/Terrain.cpp @@ -505,11 +505,11 @@ float CTerrain::FlattenArea(float x0, float x1, float z0, float z1) for (ssize_t z=tz0;z<=tz1;z++) { for (ssize_t x=tx0;x<=tx1;x++) { m_Heightmap[z*m_MapSize + x]=avgY; - CPatch* patch=GetPatch(x/PATCH_SIZE,z/PATCH_SIZE); // can't fail (x,z were clamped) - patch->SetDirty(RENDERDATA_UPDATE_VERTICES); } } + MakeDirty(tx0, tz0, tx1, tz1, RENDERDATA_UPDATE_VERTICES); + return avgY*HEIGHT_SCALE; } diff --git a/source/graphics/tests/test_Terrain.h b/source/graphics/tests/test_Terrain.h index 7d1a922e44..eaf74e3b2a 100644 --- a/source/graphics/tests/test_Terrain.h +++ b/source/graphics/tests/test_Terrain.h @@ -19,6 +19,7 @@ #include "graphics/Terrain.h" +#include "graphics/Patch.h" #include "graphics/RenderableObject.h" #include "maths/FixedVector3D.h" @@ -30,6 +31,11 @@ class TestTerrain : public CxxTest::TestSuite terrain.MakeDirty(RENDERDATA_UPDATE_VERTICES); } + u16 GetVertex(CTerrain& terrain, ssize_t i, ssize_t j) + { + return terrain.GetHeightMap()[j*terrain.GetVerticesPerSide() + i]; + } + void Set45Slope(CTerrain& terrain) { SetVertex(terrain, 0, 0, 100); @@ -95,4 +101,57 @@ public: TS_ASSERT_EQUALS(vec.Y.ToFloat(), 1.f); TS_ASSERT_EQUALS(vec.Z.ToFloat(), 0.f); } + + void test_FlattenArea() + { + CTerrain terrain; + terrain.Initialize(4, NULL); + size_t m = terrain.GetVerticesPerSide() - 1; + SetVertex(terrain, 0, 0, 25600); + SetVertex(terrain, 2, 3, 25600); + SetVertex(terrain, m, m, 25600); + + terrain.FlattenArea(-1000, 1000, -1000, 1000); + + // (25600*3) / (65*65) = 18 + TS_ASSERT_EQUALS(GetVertex(terrain, 0, 0), 18); + TS_ASSERT_EQUALS(GetVertex(terrain, 4, 5), 18); + TS_ASSERT_EQUALS(GetVertex(terrain, m, m), 18); + } + + void test_FlattenArea_dirty() + { + CTerrain terrain; + terrain.Initialize(4, NULL); + + for (ssize_t pj = 0; pj < terrain.GetPatchesPerSide(); ++pj) + for (ssize_t pi = 0; pi < terrain.GetPatchesPerSide(); ++pi) + terrain.GetPatch(pi, pj)->SetRenderData(new CRenderData()); + +#define EXPECT_DIRTY(which, pi, pj) TS_ASSERT_EQUALS((bool)(terrain.GetPatch(pi, pj)->GetRenderData()->m_UpdateFlags & RENDERDATA_UPDATE_VERTICES), which) + + EXPECT_DIRTY(false, 0, 0); + EXPECT_DIRTY(false, 1, 0); + EXPECT_DIRTY(false, 2, 0); + EXPECT_DIRTY(false, 0, 1); + EXPECT_DIRTY(false, 1, 1); + EXPECT_DIRTY(false, 2, 1); + EXPECT_DIRTY(false, 0, 2); + EXPECT_DIRTY(false, 1, 2); + EXPECT_DIRTY(false, 2, 2); + + terrain.FlattenArea(PATCH_SIZE*CELL_SIZE, 2*PATCH_SIZE*CELL_SIZE, PATCH_SIZE*CELL_SIZE+1, 2*PATCH_SIZE*CELL_SIZE-1); + + EXPECT_DIRTY(true, 0, 0); + EXPECT_DIRTY(true, 1, 0); + EXPECT_DIRTY(true, 2, 0); + EXPECT_DIRTY(true, 0, 1); + EXPECT_DIRTY(true, 1, 1); + EXPECT_DIRTY(true, 2, 1); + EXPECT_DIRTY(true, 0, 2); + EXPECT_DIRTY(true, 1, 2); + EXPECT_DIRTY(true, 2, 2); + // This is dirtying more than strictly necessary, but that's okay + } + };