139 lines
5.0 KiB
C++
139 lines
5.0 KiB
C++
#include "procgen/Procgen.h"
|
|
#include "procgen/SpatialData.h"
|
|
|
|
#include <zeroerr.hpp>
|
|
|
|
#include <cmath>
|
|
|
|
using namespace eve::procgen;
|
|
|
|
TEST_CASE("procgen.spatialData.volumeComposition") {
|
|
const SpatialData world = SpatialData::box(0.f, 0.f, 0.f, 10.f, 4.f, 10.f);
|
|
const SpatialData hole = SpatialData::sphere(5.f, 2.f, 5.f, 2.f);
|
|
const SpatialData buildable = SpatialData::subtract(world, hole);
|
|
|
|
CHECK_EQ(world.getKind(), std::string("volume.box"));
|
|
CHECK(world.contains(1.f, 1.f, 1.f));
|
|
CHECK(!world.contains(11.f, 1.f, 1.f));
|
|
CHECK(!buildable.contains(5.f, 2.f, 5.f));
|
|
CHECK(buildable.contains(1.f, 1.f, 1.f));
|
|
CHECK(buildable.hasBounds());
|
|
CHECK_EQ(buildable.getMaxX(), 10.f);
|
|
|
|
const SpatialData overlap = SpatialData::intersect(
|
|
world, SpatialData::box(8.f, -2.f, 8.f, 12.f, 8.f, 12.f));
|
|
CHECK(overlap.contains(9.f, 2.f, 9.f));
|
|
CHECK(!overlap.contains(7.f, 2.f, 9.f));
|
|
CHECK_EQ(overlap.getMinX(), 8.f);
|
|
CHECK_EQ(overlap.getMaxZ(), 10.f);
|
|
}
|
|
|
|
TEST_CASE("procgen.spatialData.splineAndDeterministicSampling") {
|
|
PointSet control;
|
|
control.add(0.f, 0.f, 0.f);
|
|
control.add(10.f, 0.f, 0.f);
|
|
const SpatialData road = SpatialData::spline(control, 1.f);
|
|
CHECK(road.contains(5.f, 0.5f, 0.f));
|
|
CHECK(!road.contains(5.f, 2.f, 0.f));
|
|
|
|
const SpatialData volume = SpatialData::box(0.f, 0.f, 0.f, 4.f, 2.f, 4.f);
|
|
const PointSet first = volume.sample(2.f, 42, 0.f);
|
|
const PointSet second = volume.sample(2.f, 42, 0.f);
|
|
CHECK_EQ(first.getCount(), 18);
|
|
CHECK_EQ(first.getCount(), second.getCount());
|
|
for (int i = 0; i < first.getCount(); ++i) {
|
|
CHECK_EQ(first.getX(i), second.getX(i));
|
|
CHECK_EQ(first.getY(i), second.getY(i));
|
|
CHECK_EQ(first.getZ(i), second.getZ(i));
|
|
CHECK_EQ(first.getPointSeed(i), second.getPointSeed(i));
|
|
}
|
|
}
|
|
|
|
TEST_CASE("procgen.spatialData.scriptFacingApiFiltersPoints") {
|
|
Procgen proc;
|
|
SpatialData* include = proc.boxVolume(0.f, -1.f, 0.f, 5.f, 1.f, 5.f);
|
|
SpatialData* exclude = proc.sphereVolume(2.f, 0.f, 2.f, 1.f);
|
|
REQUIRE(bool(include));
|
|
REQUIRE(bool(exclude));
|
|
SpatialData* domain = proc.differenceSpatial(include, exclude);
|
|
REQUIRE(bool(domain));
|
|
|
|
PointSet input;
|
|
input.add(1.f, 0.f, 1.f);
|
|
input.add(2.f, 0.f, 2.f);
|
|
input.add(9.f, 0.f, 9.f);
|
|
PointSet* accepted = proc.filterSpatial(&input, domain, false);
|
|
PointSet* rejected = proc.filterSpatial(&input, domain, true);
|
|
REQUIRE(bool(accepted));
|
|
REQUIRE(bool(rejected));
|
|
CHECK_EQ(accepted->getCount(), 1);
|
|
CHECK_EQ(rejected->getCount(), 2);
|
|
|
|
delete rejected;
|
|
delete accepted;
|
|
delete domain;
|
|
delete exclude;
|
|
delete include;
|
|
}
|
|
|
|
TEST_CASE("procgen.spatialData.heightfieldSamplesAndProjectsSurface") {
|
|
Heightmap map(3, 3);
|
|
for (int z = 0; z < 3; ++z)
|
|
for (int x = 0; x < 3; ++x) map.setHeight(x, z, float(x + z));
|
|
|
|
const SpatialData surface = SpatialData::heightfield(map, 10.f, 20.f, 2.f, 3.f);
|
|
CHECK_EQ(surface.getKind(), std::string("surface.heightfield"));
|
|
CHECK_EQ(surface.getMinX(), 10.f);
|
|
CHECK_EQ(surface.getMaxZ(), 24.f);
|
|
CHECK(surface.contains(12.f, 6.f, 22.f));
|
|
|
|
const PointSet samples = surface.sample(2.f, 91, 0.f);
|
|
CHECK_EQ(samples.getCount(), 9);
|
|
CHECK_EQ(samples.getX(0), 10.f);
|
|
CHECK_EQ(samples.getZ(0), 20.f);
|
|
CHECK_EQ(samples.getY(4), 6.f);
|
|
CHECK(samples.getNormalY(4) > 0.f);
|
|
CHECK(samples.getNormalX(4) < 0.f);
|
|
|
|
PointSet source;
|
|
source.add(14.f, -100.f, 24.f);
|
|
const PointSet projected = surface.project(source);
|
|
CHECK_EQ(projected.getY(0), 12.f);
|
|
}
|
|
|
|
TEST_CASE("procgen.pointOperations.matchCorePcgNodes") {
|
|
PointSet first;
|
|
const int a = first.add(1.f, 0.f, 0.f);
|
|
first.setDensity(a, 1.f);
|
|
first.setFloatAttribute(a, "age", 12.f);
|
|
first.setStringAttribute(a, "biome", "forest");
|
|
|
|
PointSet second;
|
|
const int b = second.add(0.f, 0.f, 2.f);
|
|
second.setDensity(b, 0.f);
|
|
second.setFloatAttribute(b, "age", 2.f);
|
|
second.setStringAttribute(b, "biome", "desert");
|
|
|
|
const PointSet merged = mergePointSets(first, second);
|
|
CHECK_EQ(merged.getCount(), 2);
|
|
const PointSet transformed =
|
|
transformPointSet(merged, 10.f, 3.f, 20.f, 90.f, 2.f, 1.f, 2.f);
|
|
CHECK(std::abs(transformed.getX(0) - 10.f) < 0.0001f);
|
|
CHECK(std::abs(transformed.getZ(0) - 22.f) < 0.0001f);
|
|
CHECK_EQ(transformed.getY(0), 3.f);
|
|
CHECK_EQ(transformed.getYaw(0), 90.f);
|
|
CHECK_EQ(transformed.getScaleX(0), 2.f);
|
|
|
|
const PointSet mature = filterPointFloatAttribute(merged, "age", 10.f, 20.f, false);
|
|
const PointSet forest = filterPointStringAttribute(merged, "biome", "forest", false);
|
|
CHECK_EQ(mature.getCount(), 1);
|
|
CHECK_EQ(forest.getCount(), 1);
|
|
CHECK_EQ(forest.getStringAttribute(0, "biome", ""), std::string("forest"));
|
|
|
|
const PointSet culledA = densityCullPoints(merged, 123, 1.f);
|
|
const PointSet culledB = densityCullPoints(merged, 123, 1.f);
|
|
CHECK_EQ(culledA.getCount(), 1);
|
|
CHECK_EQ(culledA.getCount(), culledB.getCount());
|
|
CHECK_EQ(culledA.getPointSeed(0), culledB.getPointSeed(0));
|
|
}
|