summaryrefslogtreecommitdiff
path: root/src/mesh_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesh_test.cc')
-rw-r--r--src/mesh_test.cc136
1 files changed, 136 insertions, 0 deletions
diff --git a/src/mesh_test.cc b/src/mesh_test.cc
new file mode 100644
index 0000000..fabc84f
--- /dev/null
+++ b/src/mesh_test.cc
@@ -0,0 +1,136 @@
+// Copyright 2021 Benjamin Barenblat
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+#include "src/mesh.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <stdint.h>
+
+#include <ostream>
+#include <string>
+
+#include "src/util.h"
+#include "third_party/abseil/absl/strings/substitute.h"
+
+namespace glplanet {
+namespace {
+
+using Coordinates = ::glplanet::UvSphere::Coordinates;
+using ::testing::ElementsAre;
+using ::testing::ExplainMatchResult;
+using ::testing::Field;
+using ::testing::FloatNear;
+using ::testing::UnorderedElementsAre;
+
+struct Triangle {
+ uint32_t a, b, c;
+
+ std::string DebugString() const noexcept {
+ return absl::Substitute("Triangle{$0, $1, $2}", a, b, c);
+ }
+};
+
+std::ostream& operator<<(std::ostream& out, const Triangle& t) noexcept {
+ return out << t.DebugString();
+}
+
+std::vector<Triangle> TrianglesIn(const std::vector<uint32_t>& elements) {
+ DCHECK(elements.size() % 3 == 0);
+ std::vector<Triangle> result;
+ for (int i = 0; i < elements.size(); i += 3) {
+ result.push_back(Triangle{elements[i], elements[i + 1], elements[i + 2]});
+ }
+ return result;
+}
+
+MATCHER_P5(CoordinatesAre, xv, yv, zv, uv, vv,
+ absl::Substitute("is an object whose fields (x, y, z, u, v) are "
+ "approximately ($0, $1, $2, $3, $4)",
+ xv, yv, zv, uv, vv)) {
+ return ExplainMatchResult(
+ AllOf(Field("x", &Coordinates::x, FloatNear(xv, 1e-15)),
+ Field("y", &Coordinates::y, FloatNear(yv, 1e-15)),
+ Field("z", &Coordinates::z, FloatNear(zv, 1e-15)),
+ Field("u", &Coordinates::u, FloatNear(uv, 1e-15)),
+ Field("v", &Coordinates::v, FloatNear(vv, 1e-15))),
+ arg, result_listener);
+}
+
+MATCHER_P3(TriangleIs, av, bv, cv,
+ absl::Substitute("is the triangle ($0, $1, $2)", av, bv, cv)) {
+ return arg.a == av && arg.b == bv && arg.c == cv;
+}
+
+TEST(MeshTest, SmallVertices) {
+ // This test is overconstrained. In particular, we check the returned
+ // coordinates with ElementsAre, rather than UnorderedElementsAre, and the u
+ // coordinates are exact, rather than being normalized to [0, 1]. This allows
+ // us to verify that the u coordinates increase monotonically as we travel
+ // east around the sphere, which is important to prevent discontinuities in
+ // texture mapping.
+ UvSphere s(4, 2);
+ EXPECT_THAT(s.vertices, ElementsAre(CoordinatesAre(0, 0, -1, 0, 1), //
+ CoordinatesAre(0, 0, -1, 0.25, 1), //
+ CoordinatesAre(0, 0, -1, 0.5, 1), //
+ CoordinatesAre(0, 0, -1, 0.75, 1), //
+ CoordinatesAre(0, 0, -1, 1, 1),
+
+ CoordinatesAre(-1, 0, 0, 0, 0.5), //
+ CoordinatesAre(0, -1, 0, 0.25, 0.5), //
+ CoordinatesAre(1, 0, 0, 0.5, 0.5), //
+ CoordinatesAre(0, 1, 0, 0.75, 0.5), //
+ CoordinatesAre(-1, 0, 0, 1, 0.5),
+
+ CoordinatesAre(0, 0, 1, 0, 0), //
+ CoordinatesAre(0, 0, 1, 0.25, 0), //
+ CoordinatesAre(0, 0, 1, 0.5, 0), //
+ CoordinatesAre(0, 0, 1, 0.75, 0), //
+ CoordinatesAre(0, 0, 1, 1, 0)));
+}
+
+TEST(MeshTest, SmallElements) {
+ UvSphere s(4, 2);
+ ASSERT_THAT(s.vertices, ElementsAre(CoordinatesAre(0, 0, -1, 0, 1), //
+ CoordinatesAre(0, 0, -1, 0.25, 1), //
+ CoordinatesAre(0, 0, -1, 0.5, 1), //
+ CoordinatesAre(0, 0, -1, 0.75, 1), //
+ CoordinatesAre(0, 0, -1, 1, 1),
+
+ CoordinatesAre(-1, 0, 0, 0, 0.5), //
+ CoordinatesAre(0, -1, 0, 0.25, 0.5), //
+ CoordinatesAre(1, 0, 0, 0.5, 0.5), //
+ CoordinatesAre(0, 1, 0, 0.75, 0.5), //
+ CoordinatesAre(-1, 0, 0, 1, 0.5),
+
+ CoordinatesAre(0, 0, 1, 0, 0), //
+ CoordinatesAre(0, 0, 1, 0.25, 0), //
+ CoordinatesAre(0, 0, 1, 0.5, 0), //
+ CoordinatesAre(0, 0, 1, 0.75, 0), //
+ CoordinatesAre(0, 0, 1, 1, 0)));
+ EXPECT_THAT(
+ TrianglesIn(s.elements),
+ UnorderedElementsAre(TriangleIs(0, 6, 5), TriangleIs(1, 6, 0), //
+ TriangleIs(1, 7, 6), TriangleIs(2, 7, 1), //
+ TriangleIs(2, 8, 7), TriangleIs(3, 8, 2), //
+ TriangleIs(3, 9, 8), TriangleIs(4, 9, 3),
+
+ TriangleIs(5, 11, 10), TriangleIs(6, 11, 5), //
+ TriangleIs(6, 12, 11), TriangleIs(7, 12, 6), //
+ TriangleIs(7, 13, 12), TriangleIs(8, 13, 7), //
+ TriangleIs(8, 14, 13), TriangleIs(9, 14, 8)));
+}
+
+} // namespace
+} // namespace glplanet