119 lines
4.7 KiB
C++
119 lines
4.7 KiB
C++
#include "procgen/IncrementalBuild.h"
|
|
#include "procgen/Semantic.h"
|
|
#include "zeroerr/assert.h"
|
|
#include "zeroerr/unittest.h"
|
|
|
|
using namespace eve::procgen;
|
|
|
|
namespace {
|
|
|
|
bool containsChange(const IncrementalBuildDelta& delta, int x, int z, bool removed) {
|
|
for (int index = 0; index < delta.getCount(); ++index)
|
|
if (delta.getClusterX(index) == x && delta.getClusterZ(index) == z && delta.isRemoved(index) == removed)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
TEST_CASE("procgen.incrementalBuild.rebuildsOnlyDirtyClustersAndEmitsRemovals") {
|
|
Grid2D grid;
|
|
grid.resize(8, 2);
|
|
grid.setCell(1, 0, int(Semantic::Floor));
|
|
grid.setCell(5, 0, int(Semantic::Floor));
|
|
PointSet points;
|
|
const int leftPoint = points.add(1.5f, 0.f, 0.5f);
|
|
const int rightPoint = points.add(5.5f, 0.f, 0.5f);
|
|
|
|
ObjectBuildLayer objects;
|
|
REQUIRE(objects.addAsset("props/crate", 1.f).ok());
|
|
BuildLayerStack stack;
|
|
REQUIRE(stack.addTileLayer("floor", true, 1.f, 0.f, "floor").ok());
|
|
REQUIRE(stack.addObjectLayer("props", true, objects).ok());
|
|
IncrementalBuildExecutor incremental;
|
|
auto first = incremental.update(stack, grid, points, 4, 1.f);
|
|
REQUIRE(first.ok());
|
|
CHECK_EQ(first.value().getCount(), 2);
|
|
CHECK_EQ(incremental.getCachedClusterCount(), 2);
|
|
CHECK(containsChange(first.value(), 0, 0, false));
|
|
CHECK(containsChange(first.value(), 1, 0, false));
|
|
CHECK(incremental.getCachedArtifacts(0, 0).ok());
|
|
|
|
auto unchanged = incremental.update(stack, grid, points, 4, 1.f);
|
|
REQUIRE(unchanged.ok());
|
|
CHECK_EQ(unchanged.value().getCount(), 0);
|
|
|
|
grid.setDetail(1, 0, 7);
|
|
auto interior = incremental.update(stack, grid, points, 4, 1.f);
|
|
REQUIRE(interior.ok());
|
|
CHECK_EQ(interior.value().getCount(), 1);
|
|
CHECK(containsChange(interior.value(), 0, 0, false));
|
|
|
|
grid.setCell(3, 0, int(Semantic::Floor));
|
|
auto boundary = incremental.update(stack, grid, points, 4, 1.f);
|
|
REQUIRE(boundary.ok());
|
|
CHECK_EQ(boundary.value().getCount(), 2);
|
|
CHECK(containsChange(boundary.value(), 0, 0, false));
|
|
CHECK(containsChange(boundary.value(), 1, 0, false));
|
|
|
|
points.setPosition(rightPoint, 6.5f, 0.f, 0.5f);
|
|
auto pointEdit = incremental.update(stack, grid, points, 4, 1.f);
|
|
REQUIRE(pointEdit.ok());
|
|
CHECK_EQ(pointEdit.value().getCount(), 1);
|
|
CHECK(containsChange(pointEdit.value(), 1, 0, false));
|
|
|
|
grid.setCell(1, 0, int(Semantic::Empty));
|
|
grid.setCell(3, 0, int(Semantic::Empty));
|
|
points.setPosition(leftPoint, 5.75f, 0.f, 0.5f);
|
|
auto removed = incremental.update(stack, grid, points, 4, 1.f);
|
|
REQUIRE(removed.ok());
|
|
CHECK(containsChange(removed.value(), 0, 0, true));
|
|
CHECK_EQ(incremental.getCachedClusterCount(), 1);
|
|
CHECK(!incremental.getCachedArtifacts(0, 0).ok());
|
|
}
|
|
|
|
TEST_CASE("procgen.incrementalBuild.partitionsGlobalMeshAndPreservesCacheOnFailure") {
|
|
Grid2D grid;
|
|
grid.resize(8, 1);
|
|
for (int x = 0; x < 8; ++x) grid.setCell(x, 0, int(Semantic::Floor));
|
|
PointSet points;
|
|
points.add(1.f, 0.f, 0.f);
|
|
|
|
ObjectBuildLayer objects;
|
|
REQUIRE(objects.addAsset("props/crate", 1.f).ok());
|
|
BuildLayerStack stack;
|
|
REQUIRE(stack.addTileLayer("floor", true, 1.f, 0.f, "floor").ok());
|
|
REQUIRE(stack.addObjectLayer("props", true, objects).ok());
|
|
IncrementalBuildExecutor incremental;
|
|
auto delta = incremental.update(stack, grid, points, 4, 1.f);
|
|
REQUIRE(delta.ok());
|
|
REQUIRE_EQ(delta.value().getCount(), 2);
|
|
auto leftArtifacts = incremental.getCachedArtifacts(0, 0);
|
|
auto rightArtifacts = incremental.getCachedArtifacts(1, 0);
|
|
REQUIRE(leftArtifacts.ok());
|
|
REQUIRE(rightArtifacts.ok());
|
|
auto leftMesh = leftArtifacts.value().getMesh(0);
|
|
auto rightMesh = rightArtifacts.value().getMesh(0);
|
|
REQUIRE(leftMesh.ok());
|
|
REQUIRE(rightMesh.ok());
|
|
auto full = stack.execute(grid, points);
|
|
REQUIRE(full.ok());
|
|
auto fullMesh = full.value().getMesh(0);
|
|
REQUIRE(fullMesh.ok());
|
|
CHECK_EQ(leftMesh.value().getIndexCount() + rightMesh.value().getIndexCount(), fullMesh.value().getIndexCount());
|
|
CHECK(leftMesh.value().getPositionX(0) < 4.f);
|
|
CHECK(rightMesh.value().getPositionX(0) >= 4.f);
|
|
|
|
ObjectBuildLayer oriented;
|
|
REQUIRE(oriented.addAsset("props/oriented", 1.f).ok());
|
|
REQUIRE(oriented.setOrientation(1.f, 0.f, false).ok());
|
|
BuildLayerStack failingStack;
|
|
REQUIRE(failingStack.addObjectLayer("oriented", true, oriented).ok());
|
|
auto failed = incremental.update(failingStack, grid, points, 4, 1.f);
|
|
CHECK(!failed.ok());
|
|
CHECK_EQ(incremental.getCachedClusterCount(), 2);
|
|
CHECK(incremental.getCachedArtifacts(0, 0).ok());
|
|
CHECK(!incremental.update(stack, grid, points, 0, 1.f).ok());
|
|
CHECK(!incremental.update(stack, grid, points, 4, 0.f).ok());
|
|
}
|