summaryrefslogtreecommitdiff
path: root/test/test-terrain.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/test-terrain.cpp')
-rw-r--r--test/test-terrain.cpp172
1 files changed, 172 insertions, 0 deletions
diff --git a/test/test-terrain.cpp b/test/test-terrain.cpp
new file mode 100644
index 0000000..53eebfb
--- /dev/null
+++ b/test/test-terrain.cpp
@@ -0,0 +1,172 @@
+#define BOOST_TEST_MODULE terrain
+#include "testHelpers.h"
+#include <boost/test/data/test_case.hpp>
+#include <boost/test/unit_test.hpp>
+#include <stream_support.h>
+
+#include <game/terrain2.h>
+
+class TestTerrainMesh : public TerrainMesh {
+public:
+ TestTerrainMesh() : TerrainMesh {FIXTURESDIR "height/SD19.asc"} { }
+};
+
+constexpr size_t ncols = 200, nrows = 200, xllcorner = 310000, yllcorner = 490000, cellsize = 50;
+
+BOOST_FIXTURE_TEST_SUITE(ttm, TestTerrainMesh);
+
+BOOST_AUTO_TEST_CASE(loadSuccess)
+{
+ BOOST_CHECK_EQUAL(ncols * nrows, n_vertices());
+ BOOST_CHECK_EQUAL(2 * (ncols - 1) * (nrows - 1), n_faces());
+}
+
+BOOST_AUTO_TEST_CASE(normalsAllPointUp)
+{
+ BOOST_CHECK(std::all_of(faces_begin(), faces_end(), [this](auto && vh) {
+ return normal(vh).z > 0;
+ }));
+ BOOST_CHECK(std::all_of(vertices_begin(), vertices_end(), [this](auto && vh) {
+ return normal(vh).z > 0;
+ }));
+}
+
+BOOST_AUTO_TEST_CASE(trianglesContainsPoints)
+{
+ const auto face = face_handle(0);
+ auto vertices = cfv_iter(face);
+
+ BOOST_TEST_CONTEXT(point(*vertices++) << point(*vertices++) << point(*vertices++)) {
+ BOOST_CHECK(triangleContainsPoint(glm::vec2 {xllcorner, yllcorner}, face));
+ BOOST_CHECK(triangleContainsPoint(glm::vec2 {xllcorner + cellsize, yllcorner + cellsize}, face));
+ BOOST_CHECK(triangleContainsPoint(glm::vec2 {xllcorner, yllcorner + cellsize}, face));
+ BOOST_CHECK(triangleContainsPoint(glm::vec2 {xllcorner + 1, yllcorner + 1}, face));
+ BOOST_CHECK(triangleContainsPoint(glm::vec2 {xllcorner + 1, yllcorner + 2}, face));
+ BOOST_CHECK(!triangleContainsPoint(glm::vec2 {xllcorner + 3, yllcorner + 2}, face));
+ BOOST_CHECK(!triangleContainsPoint(glm::vec2 {xllcorner + cellsize, yllcorner}, face));
+ }
+}
+
+BOOST_AUTO_TEST_CASE(locatePointFace)
+{
+ const PointFace pf {{310002, 490003}};
+ BOOST_CHECK(!pf.isLocated());
+ BOOST_CHECK(pf.face(this).is_valid());
+ BOOST_CHECK_EQUAL(pf.face(this).idx(), 0);
+}
+
+BOOST_AUTO_TEST_CASE(preLocatePointFace)
+{
+ const PointFace pf {{310002, 490003}, this};
+ BOOST_CHECK(pf.isLocated());
+ BOOST_CHECK_EQUAL(pf.face(this).idx(), 0);
+}
+
+BOOST_AUTO_TEST_SUITE_END();
+
+using FindPointData = std::tuple<glm::vec2, int>;
+
+static const TestTerrainMesh fixedTerrtain;
+
+// No boundary cases as these can produce different valid results depending on starting point
+BOOST_DATA_TEST_CASE(findPointOnTerrain,
+ boost::unit_test::data::make<FindPointData>({
+ {{0, 0}, -1}, {{xllcorner, 0}, -1}, {{0, yllcorner}, -1}, {{xllcorner + 1, yllcorner + 2}, 0},
+ {{xllcorner + (cellsize * (nrows - 1)) - 2, yllcorner + (cellsize * (ncols - 1)) - 1}, 79200},
+ {{315555, 495556}, 44400}, // perf test target
+ })
+ * boost::unit_test::data::make<int>(
+ {0, 1, 2, 3, 4, 5, 6, 10, 100, 150, 200, 1000, 1234, 17439, 79201, 79200, 79199}),
+ p, fh, start)
+{
+ BOOST_CHECK_EQUAL(fh, fixedTerrtain.findPoint(p, TerrainMesh::FaceHandle(start)).idx());
+}
+
+using FindPositionData = std::tuple<glm::vec2, float>;
+
+BOOST_DATA_TEST_CASE(findPositionAt,
+ boost::unit_test::data::make<FindPositionData>({
+ // corners
+ {{310000, 490000}, 32.8F},
+ {{310050, 490050}, 33.0F},
+ {{310000, 490050}, 32.7F},
+ {{310050, 490000}, 33.2F},
+ {{310750, 490150}, 58.4F},
+ // midpoints
+ {{310025, 490025}, 32.9F},
+ {{310025, 490050}, 32.85F},
+ {{310000, 490025}, 32.75F},
+ // other
+ {{310751, 490152}, 58.326F},
+ }),
+ p, h)
+{
+ BOOST_CHECK_CLOSE_VEC(fixedTerrtain.positionAt(p), p ^ h);
+}
+
+using FindRayIntersectData = std::tuple<glm::vec3, glm::vec3, glm::vec3>;
+
+BOOST_DATA_TEST_CASE(findRayIntersect,
+ boost::unit_test::data::make<FindRayIntersectData>({
+ {{310000, 490000, 50}, {1, 1, -2}, {310008.59, 490008.59, 32.834301}},
+ {{310000, 490000, 50}, {1, 1, -1}, {310017.12, 490017.12, 32.868526}},
+ }),
+ p, d, i)
+{
+ BOOST_CHECK_CLOSE_VEC(fixedTerrtain.intersectRay({p, d}).value(), i);
+}
+
+using WalkTerrainData = std::tuple<glm::vec2, glm::vec2, std::vector<int>>;
+
+BOOST_DATA_TEST_CASE(walkTerrain,
+ boost::unit_test::data::make<WalkTerrainData>({
+ {{310002, 490003}, {310002, 490003}, {0}},
+ {{310003, 490002}, {310003, 490002}, {1}},
+ {{310002, 490003}, {310003, 490002}, {0, 1}},
+ {{310003, 490002}, {310002, 490003}, {1, 0}},
+ {{310002, 490003}, {310202, 490003}, {0, 1, 2, 3, 4, 5, 6, 7, 8}},
+ {{310202, 490003}, {310002, 490003}, {8, 7, 6, 5, 4, 3, 2, 1, 0}},
+ {{310002, 490003}, {310002, 490203}, {0, 399, 398, 797, 796, 1195, 1194, 1593, 1592}},
+ }),
+ from, to, visits)
+{
+ std::vector<int> visited;
+ BOOST_CHECK_NO_THROW(fixedTerrtain.walk(from, to, [&visited](auto fh) {
+ visited.emplace_back(fh.idx());
+ }));
+ BOOST_CHECK_EQUAL_COLLECTIONS(visited.begin(), visited.end(), visits.begin(), visits.end());
+}
+
+BOOST_DATA_TEST_CASE(walkTerrainSetsFromFace,
+ boost::unit_test::data::make<WalkTerrainData>({
+ {{310002, 490003}, {310002, 490003}, {0}},
+ {{310003, 490002}, {310003, 490002}, {1}},
+ {{310002, 490003}, {310003, 490002}, {0, 1}},
+ {{310003, 490002}, {310002, 490003}, {1, 0}},
+ }),
+ from, to, visits)
+{
+ TerrainMesh::PointFace pf {from};
+ BOOST_CHECK_NO_THROW(fixedTerrtain.walk(pf, to, [](auto) {}));
+ BOOST_CHECK_EQUAL(pf.face(&fixedTerrtain).idx(), visits.front());
+}
+
+BOOST_DATA_TEST_CASE(walkTerrainUntil,
+ boost::unit_test::data::make<WalkTerrainData>({
+ {{310002, 490003}, {310002, 490003}, {0}},
+ {{310003, 490002}, {310003, 490002}, {1}},
+ {{310002, 490003}, {310003, 490002}, {0, 1}},
+ {{310003, 490002}, {310002, 490003}, {1, 0}},
+ {{310002, 490003}, {310202, 490003}, {0, 1, 2, 3, 4}},
+ {{310202, 490003}, {310002, 490003}, {8, 7, 6, 5, 4}},
+ {{310002, 490003}, {310002, 490203}, {0, 399, 398, 797, 796}},
+ }),
+ from, to, visits)
+{
+ std::vector<int> visited;
+ BOOST_CHECK_NO_THROW(fixedTerrtain.walkUntil(from, to, [&visited](auto fh) {
+ visited.emplace_back(fh.idx());
+ return visited.size() >= 5;
+ }));
+ BOOST_CHECK_EQUAL_COLLECTIONS(visited.begin(), visited.end(), visits.begin(), visits.end());
+}