408 lines
19 KiB
C++
408 lines
19 KiB
C++
#include <cmath>
|
|
#include <simplesquirrel/simplesquirrel.hpp>
|
|
#include "procgen/heightmap/Heightmap.h"
|
|
#include "procgen/heightmap/TerrainDerivedMap.h"
|
|
#include "procgen/heightmap/TerrainStampScript.h"
|
|
#include "zeroerr/unittest.h"
|
|
|
|
using namespace eve::procgen;
|
|
|
|
TEST_CASE("procgen.derivedMap.aspectSourceConventions") {
|
|
Heightmap plane(5, 5), output(5, 5);
|
|
for (int y = 0; y < 5; ++y)
|
|
for (int x = 0; x < 5; ++x) plane.setHeight(x, y, float(x) / 4.F);
|
|
REQUIRE(generateTerrainHeightmapAspect(output, plane, TerrainHeightmapAspect::Aspect).ok());
|
|
CHECK(std::abs(output.height(2, 2) - 0.75F) < 0.000001F);
|
|
REQUIRE(generateTerrainHeightmapAspect(output, plane, TerrainHeightmapAspect::Northerness).ok());
|
|
CHECK(std::abs(output.height(2, 2) - 0.5F) < 0.000001F);
|
|
REQUIRE(generateTerrainHeightmapAspect(output, plane, TerrainHeightmapAspect::Easterness).ok());
|
|
CHECK(std::abs(output.height(2, 2)) < 0.000001F);
|
|
|
|
Heightmap flat(3, 3);
|
|
flat.data().assign(9, 0.2F);
|
|
REQUIRE(generateTerrainHeightmapAspect(flat, flat, TerrainHeightmapAspect::Aspect).ok());
|
|
CHECK(flat.height(1, 1) == 0.5F);
|
|
}
|
|
|
|
TEST_CASE("procgen.derivedMap.curvatureModesAndAtomicFailure") {
|
|
Heightmap bowl(5, 5), average(5, 5), horizontal(5, 5), vertical(5, 5);
|
|
for (int y = 0; y < 5; ++y)
|
|
for (int x = 0; x < 5; ++x) {
|
|
const float dx = float(x - 2), dy = float(y - 2);
|
|
bowl.setHeight(x, y, 0.02F * (dx * dx + 2.F * dy * dy));
|
|
}
|
|
REQUIRE(generateTerrainHeightmapCurvature(horizontal, bowl, TerrainHeightmapCurvature::Horizontal).ok());
|
|
REQUIRE(generateTerrainHeightmapCurvature(vertical, bowl, TerrainHeightmapCurvature::Vertical).ok());
|
|
REQUIRE(generateTerrainHeightmapCurvature(average, bowl, TerrainHeightmapCurvature::Average).ok());
|
|
CHECK(std::abs(average.height(3, 2) - (horizontal.height(3, 2) + vertical.height(3, 2)) * 0.5F) < 0.000001F);
|
|
CHECK(horizontal.height(3, 2) != vertical.height(3, 2));
|
|
const auto before = average.data();
|
|
CHECK(!generateTerrainHeightmapCurvature(average, bowl, static_cast<TerrainHeightmapCurvature>(9)).ok());
|
|
CHECK(average.data() == before);
|
|
Heightmap wrong(2, 2);
|
|
CHECK(!generateTerrainHeightmapAspect(wrong, bowl, TerrainHeightmapAspect::Aspect).ok());
|
|
}
|
|
|
|
TEST_CASE("procgen.derivedMap.scriptBinding") {
|
|
Heightmap source(3, 3), curvature(3, 3), aspect(3, 3), filtered(3, 3);
|
|
source.data() = {0.F, 0.1F, 0.2F, 0.F, 0.1F, 0.2F, 0.F, 0.1F, 0.2F};
|
|
ssq::VM vm(1024);
|
|
auto table = vm.addTable("eve");
|
|
exposeHeightmap(table);
|
|
vm.addFunc("derivedSource", [&]() { return &source; });
|
|
vm.addFunc("derivedCurvature", [&]() { return &curvature; });
|
|
vm.addFunc("derivedAspect", [&]() { return &aspect; });
|
|
vm.addFunc("derivedFiltered", [&]() { return &filtered; });
|
|
vm.run(vm.compileSource(R"(
|
|
assert(eve.generateTerrainHeightmapCurvature(derivedCurvature(),derivedSource(),0).ok);
|
|
assert(eve.generateTerrainHeightmapAspect(derivedAspect(),derivedSource(),2).ok);
|
|
assert(!eve.generateTerrainHeightmapAspect(derivedAspect(),derivedSource(),9).ok);
|
|
assert(eve.filterTerrainHeightmapNeighborhood(derivedFiltered(),derivedSource(),1,0).ok);
|
|
assert(!eve.filterTerrainHeightmapNeighborhood(derivedFiltered(),derivedSource(),1,9).ok);
|
|
)"));
|
|
}
|
|
|
|
TEST_CASE("procgen.neighborhood.exactInPlaceTraversal") {
|
|
Heightmap grow(2, 2), shrink(2, 2), output(2, 2);
|
|
grow.data() = {0.F, 1.F, 0.F, 0.F};
|
|
auto result = filterTerrainHeightmapNeighborhood(output, grow, 1, TerrainHeightmapNeighborhood::GrowEdges);
|
|
REQUIRE(result.ok());
|
|
const std::vector<float> expectedGrow{0.5F, 1.F, 0.5F, 0.5F};
|
|
CHECK(output.data() == expectedGrow);
|
|
|
|
shrink.data() = {0.F, 1.F, 1.F, 1.F};
|
|
result = filterTerrainHeightmapNeighborhood(output, shrink, 1, TerrainHeightmapNeighborhood::ShrinkEdges);
|
|
REQUIRE(result.ok());
|
|
const std::vector<float> expectedShrink{0.F, 0.5F, 0.5F, 0.5F};
|
|
CHECK(output.data() == expectedShrink);
|
|
|
|
Heightmap spike(3, 3);
|
|
spike.data() = {0.F, 0.F, 0.F, 0.F, 1.F, 0.F, 0.F, 0.F, 0.F};
|
|
REQUIRE(filterTerrainHeightmapNeighborhood(spike, spike, 1, TerrainHeightmapNeighborhood::DeNoise).ok());
|
|
CHECK(spike.height(1, 1) == 0.F);
|
|
}
|
|
|
|
TEST_CASE("procgen.neighborhood.invalidInputIsAtomic") {
|
|
Heightmap source(3, 3), target(3, 3);
|
|
source.data().assign(9, 0.25F);
|
|
target.data().assign(9, 0.75F);
|
|
const auto before = target.data();
|
|
CHECK(!filterTerrainHeightmapNeighborhood(target, source, 0, TerrainHeightmapNeighborhood::DeNoise).ok());
|
|
CHECK(target.data() == before);
|
|
CHECK(!filterTerrainHeightmapNeighborhood(target, source, 1, static_cast<TerrainHeightmapNeighborhood>(7)).ok());
|
|
CHECK(target.data() == before);
|
|
}
|
|
|
|
TEST_CASE("procgen.heightmapFilter.sourceOrderAndRadiusQuirk") {
|
|
Heightmap source(2, 2), output(2, 2);
|
|
source.data() = {0.F, 1.F, 0.F, 0.F};
|
|
REQUIRE(smoothTerrainHeightmap(output, source, 1).ok());
|
|
const std::vector<float> expected{0.25F, 0.5625F, 0.0625F, 0.15625F};
|
|
CHECK(output.data() == expected);
|
|
|
|
Heightmap wide(11, 12), radiusOutput(11, 12);
|
|
wide.data().assign(132, 1.F);
|
|
REQUIRE(smoothTerrainHeightmapRadius(radiusOutput, wide, 0).ok());
|
|
CHECK(radiusOutput.height(5, 5) == 1.F);
|
|
CHECK(std::abs(radiusOutput.height(5, 6) - 1.F) < 0.00001F);
|
|
}
|
|
|
|
TEST_CASE("procgen.heightmapFilter.convolveAndScriptBinding") {
|
|
Heightmap source(3, 3), output(3, 3), kernel(3, 3);
|
|
source.data() = {0.F, 0.F, 0.F, 0.F, 1.F, 0.F, 0.F, 0.F, 0.F};
|
|
kernel.data().assign(9, 1.F);
|
|
REQUIRE(convolveTerrainHeightmap(output, source, kernel).ok());
|
|
CHECK(std::abs(output.height(1, 1) - 1.F / 9.F) < 0.000001F);
|
|
CHECK(output.height(0, 0) == 0.F);
|
|
|
|
ssq::VM vm(1024);
|
|
auto table = vm.addTable("eve");
|
|
exposeHeightmap(table);
|
|
vm.addFunc("filterSource", [&]() { return &source; });
|
|
vm.addFunc("filterOutput", [&]() { return &output; });
|
|
vm.addFunc("filterKernel", [&]() { return &kernel; });
|
|
vm.run(vm.compileSource(R"(
|
|
assert(eve.smoothTerrainHeightmap(filterOutput(),filterSource(),1).ok);
|
|
assert(eve.smoothTerrainHeightmapRadius(filterOutput(),filterSource(),5).ok);
|
|
assert(eve.convolveTerrainHeightmap(filterOutput(),filterSource(),filterKernel()).ok);
|
|
)"));
|
|
}
|
|
|
|
TEST_CASE("procgen.heightmapSlope.exactPlaneAndEdges") {
|
|
Heightmap plane(3, 3), slope(3, 3);
|
|
for (int y = 0; y < 3; ++y)
|
|
for (int x = 0; x < 3; ++x) plane.setHeight(x, y, float(x) * 0.5F);
|
|
REQUIRE(generateTerrainHeightmapSlope(slope, plane).ok());
|
|
CHECK(std::abs(slope.height(1, 1) - float(0.5 / std::sqrt(1.25))) < 0.000001F);
|
|
CHECK(slope.height(0, 1) < slope.height(1, 1));
|
|
CHECK(slope.height(2, 1) < slope.height(1, 1));
|
|
}
|
|
|
|
TEST_CASE("procgen.heightmapSlope.quantizeAndBindings") {
|
|
Heightmap source(2, 2), output(2, 2);
|
|
source.data() = {0.125F, 0.375F, 0.625F, 0.875F};
|
|
REQUIRE(quantizeTerrainHeightmap(output, source, 0.25F).ok());
|
|
const std::vector<float> expected{0.F, 0.5F, 0.5F, 1.F};
|
|
CHECK(output.data() == expected);
|
|
const auto before = output.data();
|
|
CHECK(!quantizeTerrainHeightmap(output, source, 0.F).ok());
|
|
CHECK(output.data() == before);
|
|
|
|
ssq::VM vm(1024);
|
|
auto table = vm.addTable("eve");
|
|
exposeHeightmap(table);
|
|
vm.addFunc("slopeSource", [&]() { return &source; });
|
|
vm.addFunc("slopeOutput", [&]() { return &output; });
|
|
vm.run(vm.compileSource(R"(
|
|
assert(eve.generateTerrainHeightmapSlope(slopeOutput(),slopeSource()).ok);
|
|
assert(eve.quantizeTerrainHeightmap(slopeOutput(),slopeSource(),0.25).ok);
|
|
assert(!eve.quantizeTerrainHeightmap(slopeOutput(),slopeSource(),0.0).ok);
|
|
)"));
|
|
}
|
|
|
|
TEST_CASE("procgen.heightmapArithmetic.scalarAndClamp") {
|
|
Heightmap source(2, 1), output(2, 1);
|
|
source.data() = {0.25F, 0.75F};
|
|
REQUIRE(applyTerrainHeightmapScalarArithmetic(output, source, 0.5F, TerrainHeightmapArithmetic::Add, false, 0.F,
|
|
0.F).ok());
|
|
const std::vector<float> expectedAdd{0.75F, 1.25F};
|
|
CHECK(output.data() == expectedAdd);
|
|
REQUIRE(applyTerrainHeightmapScalarArithmetic(output, source, 2.F, TerrainHeightmapArithmetic::Multiply, true,
|
|
0.2F, 1.F).ok());
|
|
const std::vector<float> expectedMultiply{0.5F, 1.F};
|
|
CHECK(output.data() == expectedMultiply);
|
|
const auto before = output.data();
|
|
CHECK(!applyTerrainHeightmapScalarArithmetic(output, source, 0.F, TerrainHeightmapArithmetic::Divide, false,
|
|
0.F, 1.F).ok());
|
|
CHECK(output.data() == before);
|
|
}
|
|
|
|
TEST_CASE("procgen.heightmapArithmetic.resampleLerpAndBindings") {
|
|
Heightmap source(4, 1), operand(2, 1), mask(2, 1), output(4, 1);
|
|
source.data().assign(4, 1.F);
|
|
operand.data() = {0.F, 1.F};
|
|
mask.data() = {-1.F, 2.F};
|
|
REQUIRE(applyTerrainHeightmapRasterArithmetic(output, source, operand, TerrainHeightmapArithmetic::Subtract,
|
|
false, 0.F, 0.F).ok());
|
|
const std::vector<float> expectedSubtract{1.F, 0.5F, 0.F, 0.F};
|
|
CHECK(output.data() == expectedSubtract);
|
|
REQUIRE(lerpTerrainHeightmap(output, source, operand, mask).ok());
|
|
const std::vector<float> expectedLerp{1.F, 0.75F, 1.F, 1.F};
|
|
CHECK(output.data() == expectedLerp);
|
|
|
|
ssq::VM vm(1024);
|
|
auto table = vm.addTable("eve");
|
|
exposeHeightmap(table);
|
|
vm.addFunc("arithmeticSource", [&]() { return &source; });
|
|
vm.addFunc("arithmeticOperand", [&]() { return &operand; });
|
|
vm.addFunc("arithmeticMask", [&]() { return &mask; });
|
|
vm.addFunc("arithmeticOutput", [&]() { return &output; });
|
|
vm.run(vm.compileSource(R"(
|
|
assert(eve.applyTerrainHeightmapScalarArithmetic(arithmeticOutput(),arithmeticSource(),0.5,0,true,0.0,1.0).ok);
|
|
assert(eve.applyTerrainHeightmapRasterArithmetic(arithmeticOutput(),arithmeticSource(),arithmeticOperand(),2,false,0.0,1.0).ok);
|
|
assert(eve.lerpTerrainHeightmap(arithmeticOutput(),arithmeticSource(),arithmeticOperand(),arithmeticMask()).ok);
|
|
)"));
|
|
}
|
|
|
|
TEST_CASE("procgen.heightmapTransform.sourceFormulasAndAtomicFailure") {
|
|
Heightmap source(3, 1), output(3, 1);
|
|
source.data() = {0.25F, 0.5F, 0.75F};
|
|
REQUIRE(transformTerrainHeightmap(output, source, TerrainHeightmapTransform::Invert, 0.F).ok());
|
|
const std::vector<float> inverted{0.75F, 0.5F, 0.25F};
|
|
CHECK(output.data() == inverted);
|
|
REQUIRE(transformTerrainHeightmap(output, source, TerrainHeightmapTransform::Normalise, 0.F).ok());
|
|
const std::vector<float> normalized{0.F, 0.5F, 1.F};
|
|
CHECK(output.data() == normalized);
|
|
REQUIRE(transformTerrainHeightmap(output, source, TerrainHeightmapTransform::Power, 2.F).ok());
|
|
CHECK(output.height(0, 0) == 0.0625F);
|
|
REQUIRE(transformTerrainHeightmap(output, source, TerrainHeightmapTransform::Contrast, 2.F).ok());
|
|
const std::vector<float> contrasted{0.F, 0.5F, 1.F};
|
|
CHECK(output.data() == contrasted);
|
|
const auto before = output.data();
|
|
CHECK(!transformTerrainHeightmap(output, source, static_cast<TerrainHeightmapTransform>(8), 1.F).ok());
|
|
CHECK(output.data() == before);
|
|
|
|
ssq::VM vm(1024);
|
|
auto table = vm.addTable("eve");
|
|
exposeHeightmap(table);
|
|
vm.addFunc("transformSource", [&]() { return &source; });
|
|
vm.addFunc("transformOutput", [&]() { return &output; });
|
|
vm.run(vm.compileSource(R"(
|
|
assert(eve.transformTerrainHeightmap(transformOutput(),transformSource(),1,0.0).ok);
|
|
assert(eve.transformTerrainHeightmap(transformOutput(),transformSource(),3,2.0).ok);
|
|
)"));
|
|
}
|
|
|
|
TEST_CASE("procgen.heightmapCopy.conditionalAndResampled") {
|
|
Heightmap target(4, 1), source(2, 1);
|
|
target.data() = {0.25F, 0.25F, 0.75F, 0.75F};
|
|
source.data() = {0.F, 1.F};
|
|
REQUIRE(copyTerrainHeightmap(target, source, TerrainHeightmapCopy::IfLess).ok());
|
|
const std::vector<float> expectedLess{0.F, 0.25F, 0.75F, 0.75F};
|
|
CHECK(target.data() == expectedLess);
|
|
REQUIRE(copyTerrainHeightmap(target, source, TerrainHeightmapCopy::IfGreater).ok());
|
|
const std::vector<float> expectedGreater{0.F, 0.5F, 1.F, 1.F};
|
|
CHECK(target.data() == expectedGreater);
|
|
}
|
|
|
|
TEST_CASE("procgen.heightmapCopy.clampAtomicAndBindings") {
|
|
Heightmap source(2, 1), target(3, 1);
|
|
source.data() = {-1.F, 2.F};
|
|
REQUIRE(copyTerrainHeightmapClamped(target, source, 0.2F, 0.8F).ok());
|
|
const std::vector<float> expected{0.2F, 0.8F, 0.8F};
|
|
CHECK(target.data() == expected);
|
|
const auto before = target.data();
|
|
CHECK(!copyTerrainHeightmap(target, source, static_cast<TerrainHeightmapCopy>(9)).ok());
|
|
CHECK(target.data() == before);
|
|
|
|
ssq::VM vm(1024);
|
|
auto table = vm.addTable("eve");
|
|
exposeHeightmap(table);
|
|
vm.addFunc("copySource", [&]() { return &source; });
|
|
vm.addFunc("copyTarget", [&]() { return ⌖ });
|
|
vm.run(vm.compileSource(R"(
|
|
assert(eve.copyTerrainHeightmap(copyTarget(),copySource(),0).ok);
|
|
assert(eve.copyTerrainHeightmapClamped(copyTarget(),copySource(),0.0,1.0).ok);
|
|
assert(!eve.copyTerrainHeightmap(copyTarget(),copySource(),9).ok);
|
|
)"));
|
|
}
|
|
|
|
TEST_CASE("procgen.heightmapFlip.rectangularAliasAndBinding") {
|
|
Heightmap source(3, 2), output(1, 1);
|
|
source.data() = {1.F, 2.F, 3.F, 4.F, 5.F, 6.F};
|
|
REQUIRE(flipTerrainHeightmap(output, source).ok());
|
|
CHECK(output.getWidth() == 2);
|
|
CHECK(output.getHeight() == 3);
|
|
const std::vector<float> expected{1.F, 4.F, 2.F, 5.F, 3.F, 6.F};
|
|
CHECK(output.data() == expected);
|
|
REQUIRE(flipTerrainHeightmap(source, source).ok());
|
|
CHECK(source.getWidth() == 2);
|
|
CHECK(source.getHeight() == 3);
|
|
CHECK(source.data() == expected);
|
|
|
|
ssq::VM vm(1024);
|
|
auto table = vm.addTable("eve");
|
|
exposeHeightmap(table);
|
|
vm.addFunc("flipSource", [&]() { return &source; });
|
|
vm.addFunc("flipOutput", [&]() { return &output; });
|
|
vm.run(vm.compileSource(R"(
|
|
assert(eve.flipTerrainHeightmap(flipOutput(),flipSource()).ok);
|
|
assert(flipOutput().getWidth()==3 && flipOutput().getHeight()==2);
|
|
)"));
|
|
}
|
|
|
|
TEST_CASE("procgen.heightmapMeasure.sourceOrderAndBaseLevel") {
|
|
Heightmap source(3, 3);
|
|
source.data() = {-2.F, -1.F, -3.F, -4.F, 10.F, -5.F, -6.F, -7.F, -8.F};
|
|
auto minimum = measureTerrainHeightmap(source, TerrainHeightmapMeasure::Minimum);
|
|
auto maximum = measureTerrainHeightmap(source, TerrainHeightmapMeasure::Maximum);
|
|
auto sum = measureTerrainHeightmap(source, TerrainHeightmapMeasure::Sum);
|
|
auto average = measureTerrainHeightmap(source, TerrainHeightmapMeasure::Average);
|
|
auto base = measureTerrainHeightmap(source, TerrainHeightmapMeasure::BaseLevel);
|
|
REQUIRE(minimum.ok());
|
|
REQUIRE(maximum.ok());
|
|
REQUIRE(sum.ok());
|
|
REQUIRE(average.ok());
|
|
REQUIRE(base.ok());
|
|
CHECK(minimum.value() == -8.0);
|
|
CHECK(maximum.value() == 10.0);
|
|
CHECK(sum.value() == -26.0);
|
|
CHECK(std::abs(average.value() + 26.0 / 9.0) < 0.000001);
|
|
CHECK(base.value() == 0.0);
|
|
|
|
ssq::VM vm(1024);
|
|
auto table = vm.addTable("eve");
|
|
exposeHeightmap(table);
|
|
vm.addFunc("measureSource", [&]() { return &source; });
|
|
vm.run(vm.compileSource(R"(
|
|
assert(eve.measureTerrainHeightmap(measureSource(),0).value==-8.0);
|
|
assert(eve.measureTerrainHeightmap(measureSource(),1).value==10.0);
|
|
assert(eve.measureTerrainHeightmap(measureSource(),4).value==0.0);
|
|
assert(!eve.measureTerrainHeightmap(measureSource(),9).ok);
|
|
)"));
|
|
}
|
|
|
|
TEST_CASE("procgen.heightmapTerraceQuantize.curvesBoundariesAndBinding") {
|
|
Heightmap source(5, 1), output(5, 1), starts(2, 1), curves(3, 2);
|
|
source.data() = {0.F, 0.25F, 0.5F, 0.75F, 1.F};
|
|
starts.data() = {0.F, 0.5F};
|
|
curves.data() = {0.F, 0.F, 1.F, 0.F, 1.F, 1.F};
|
|
REQUIRE(quantizeTerrainHeightmapTerraces(output, source, starts, curves).ok());
|
|
const std::vector<float> expected{0.F, 0.F, 0.5F, 0.75F, 1.F};
|
|
CHECK(output.data() == expected);
|
|
starts.data() = {0.1F, 0.5F};
|
|
const auto before = output.data();
|
|
CHECK(!quantizeTerrainHeightmapTerraces(output, source, starts, curves).ok());
|
|
CHECK(output.data() == before);
|
|
starts.data() = {0.F, 0.5F};
|
|
|
|
ssq::VM vm(1024);
|
|
auto table = vm.addTable("eve");
|
|
exposeHeightmap(table);
|
|
vm.addFunc("terraceSource", [&]() { return &source; });
|
|
vm.addFunc("terraceOutput", [&]() { return &output; });
|
|
vm.addFunc("terraceStarts", [&]() { return &starts; });
|
|
vm.addFunc("terraceCurves", [&]() { return &curves; });
|
|
vm.run(vm.compileSource(R"(
|
|
assert(eve.quantizeTerrainHeightmapTerraces(terraceOutput(),terraceSource(),terraceStarts(),terraceCurves()).ok);
|
|
)"));
|
|
}
|
|
|
|
TEST_CASE("procgen.heightmapSlopeQuery.threeSourceFormulasAndBinding") {
|
|
Heightmap source(3, 3);
|
|
for (int y = 0; y < 3; ++y)
|
|
for (int x = 0; x < 3; ++x) source.setHeight(x, y, float(x + 2 * y) * 0.1F);
|
|
auto forward = measureTerrainHeightmapSlope(source, 1.F, 1.F, TerrainHeightmapSlopeQuery::GridForward);
|
|
auto central = measureTerrainHeightmapSlope(source, 0.5F, 0.5F, TerrainHeightmapSlopeQuery::NormalizedCentral);
|
|
auto average = measureTerrainHeightmapSlope(source, 0.5F, 0.5F, TerrainHeightmapSlopeQuery::NormalizedAverage);
|
|
REQUIRE(forward.ok());
|
|
REQUIRE(central.ok());
|
|
REQUIRE(average.ok());
|
|
CHECK(std::abs(forward.value() - std::sqrt(0.05)) < 0.000001);
|
|
CHECK(central.value() == 90.0);
|
|
CHECK(std::abs(average.value() - 60.0) < 0.00001);
|
|
CHECK(!measureTerrainHeightmapSlope(source, 2.F, 2.F, TerrainHeightmapSlopeQuery::GridForward).ok());
|
|
|
|
ssq::VM vm(1024);
|
|
auto table = vm.addTable("eve");
|
|
exposeHeightmap(table);
|
|
vm.addFunc("slopeQuerySource", [&]() { return &source; });
|
|
vm.run(vm.compileSource(R"(
|
|
assert(eve.measureTerrainHeightmapSlope(slopeQuerySource(),1.0,1.0,0).ok);
|
|
assert(eve.measureTerrainHeightmapSlope(slopeQuerySource(),0.5,0.5,2).ok);
|
|
assert(!eve.measureTerrainHeightmapSlope(slopeQuerySource(),2.0,2.0,0).ok);
|
|
)"));
|
|
}
|
|
|
|
TEST_CASE("procgen.heightmapWrite.safeFillRowsColumnsReset") {
|
|
Heightmap target(3, 2), row(2, 1), column(3, 1);
|
|
REQUIRE(fillTerrainHeightmap(target, 2.F).ok());
|
|
CHECK(target.height(1, 1) == 1.F);
|
|
REQUIRE(setTerrainHeightmapSafe(target, -4, 8, 0.25F).ok());
|
|
CHECK(target.height(0, 1) == 0.25F);
|
|
row.data() = {0.1F, 0.2F};
|
|
column.data() = {0.3F, 0.4F, 0.5F};
|
|
REQUIRE(setTerrainHeightmapRow(target, 1, row).ok());
|
|
REQUIRE(setTerrainHeightmapColumn(target, 0, column).ok());
|
|
const std::vector<float> expected{0.3F, 0.4F, 0.5F, 0.25F, 0.2F, 1.F};
|
|
CHECK(target.data() == expected);
|
|
const auto before = target.data();
|
|
CHECK(!setTerrainHeightmapRow(target, 3, row).ok());
|
|
CHECK(target.data() == before);
|
|
|
|
ssq::VM vm(1024);
|
|
auto table = vm.addTable("eve");
|
|
exposeHeightmap(table);
|
|
vm.addFunc("writeTarget", [&]() { return ⌖ });
|
|
vm.addFunc("writeRow", [&]() { return &row; });
|
|
vm.addFunc("writeColumn", [&]() { return &column; });
|
|
vm.run(vm.compileSource(R"(
|
|
assert(eve.fillTerrainHeightmap(writeTarget(),0.5).ok);
|
|
assert(eve.setTerrainHeightmapSafe(writeTarget(),-1,9,0.2).ok);
|
|
assert(eve.setTerrainHeightmapRow(writeTarget(),1,writeRow()).ok);
|
|
assert(eve.setTerrainHeightmapColumn(writeTarget(),0,writeColumn()).ok);
|
|
assert(eve.resetTerrainHeightmap(writeTarget()).ok);
|
|
assert(writeTarget().getWidth()==0 && writeTarget().getHeight()==0);
|
|
)"));
|
|
}
|