Added surface features. Tree generation is currently broken!

- Added SurfaceFeature
  - Used to generate chunk features
- Added SurfaceTopLayerFeature
  - A superclass for features that are only concerned with editing the
surface
- Added grass, temporary bushes and temporary trees
  - Bushes and trees do not generate properly due to bugs
  - Added Test:TemporaryLeaves
- Added SurfaceWorld (a GenericWritableWorld wrapper)
- Added some unit tests for rotation utilities
- Fixed a whole lot of bugs
This commit is contained in:
OLEGSHA 2021-07-07 17:37:08 +03:00
parent 6fb7e7fc04
commit e47fb3c4bd
Signed by: OLEGSHA
GPG Key ID: E57A4B08D64AFF7A
19 changed files with 587 additions and 97 deletions

View File

@ -56,6 +56,7 @@ public interface ChunkSet extends Iterable<Vec3i> {
default boolean contains(int x, int y, int z) {
Vec3i v = Vectors.grab3i();
v.set(x, y, z);
boolean result = contains(v);
Vectors.release(v);
return result;
@ -63,6 +64,7 @@ public interface ChunkSet extends Iterable<Vec3i> {
default boolean add(int x, int y, int z) {
Vec3i v = Vectors.grab3i();
v.set(x, y, z);
boolean result = add(v);
Vectors.release(v);
return result;
@ -70,6 +72,7 @@ public interface ChunkSet extends Iterable<Vec3i> {
default boolean remove(int x, int y, int z) {
Vec3i v = Vectors.grab3i();
v.set(x, y, z);
boolean result = remove(v);
Vectors.release(v);
return result;

View File

@ -106,7 +106,11 @@ public interface GenericChunk<
boolean hasTiles(Vec3i blockInChunk, BlockFace face);
default Vec3i resolve(Vec3i relativeCoords, Vec3i output) {
return GenericChunks.resolve(relativeCoords, output, getUp());
return GenericChunks.resolve(relativeCoords, getUp(), output);
}
default Vec3i relativize(Vec3i absoluteCoords, Vec3i output) {
return GenericChunks.relativize(absoluteCoords, getUp(), output);
}
default B getBlockRel(Vec3i relativeBlockInChunk) {

View File

@ -29,7 +29,7 @@ import ru.windcorp.progressia.common.world.rels.AxisRotations;
public class GenericChunks {
public static Vec3i resolve(Vec3i relativeCoords, Vec3i output, AbsFace up) {
public static Vec3i resolve(Vec3i relativeCoords, AbsFace up, Vec3i output) {
if (output == null) {
output = new Vec3i();
}
@ -46,6 +46,23 @@ public class GenericChunks {
return output;
}
public static Vec3i relativize(Vec3i absoluteCoords, AbsFace up, Vec3i output) {
if (output == null) {
output = new Vec3i();
}
final int offset = GenericChunk.BLOCKS_PER_CHUNK - 1;
output.set(absoluteCoords.x, absoluteCoords.y, absoluteCoords.z);
output.mul(2).sub(offset);
AxisRotations.relativize(output, up, output);
output.add(offset).div(2);
return output;
}
private static int getBorderHits(Vec3i blockInChunk) {
int hits = 0;

View File

@ -18,28 +18,49 @@
package ru.windcorp.progressia.test;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.ChunkData;
import ru.windcorp.progressia.common.util.VectorUtil;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
import ru.windcorp.progressia.test.gen.surface.SurfaceFeature;
import ru.windcorp.progressia.common.world.rels.RelFace;
import ru.windcorp.progressia.server.world.block.BlockLogicRegistry;
import ru.windcorp.progressia.test.gen.surface.SurfaceTopLayerFeature;
import ru.windcorp.progressia.test.gen.surface.SurfaceWorld;
public class TestBushFeature extends SurfaceFeature {
public class TestBushFeature extends SurfaceTopLayerFeature {
public TestBushFeature(String id) {
super(id);
}
@Override
public void process(SurfaceWorld world, Request request) {
BlockData block = BlockDataRegistry.getInstance().get("Test:Log");
Vec3i location = new Vec3i(request.getRandom().nextInt(ChunkData.BLOCKS_PER_CHUNK), request.getRandom().nextInt(ChunkData.BLOCKS_PER_CHUNK), request.getRandom().nextInt(ChunkData.BLOCKS_PER_CHUNK)).add(request.getMin());
if (world.getBlockSfc(location) == BlockDataRegistry.getInstance().get("Test:Air")) {
world.setBlockSfc(location, block, false);
private void tryToSetLeaves(SurfaceWorld world, Vec3i posSfc, BlockData leaves) {
if (world.getBlockSfc(posSfc).getId().equals("Test:Air")) {
world.setBlockSfc(posSfc, leaves, false);
}
}
@Override
protected void processTopBlock(SurfaceWorld world, Request request, Vec3i topBlock) {
if (request.getRandom().nextInt(10*10) > 0) return;
Vec3i center = topBlock.add_(0, 0, 1);
BlockData log = BlockDataRegistry.getInstance().get("Test:Log");
BlockData leaves = BlockDataRegistry.getInstance().get("Test:TemporaryLeaves");
world.setBlockSfc(center, log, false);
VectorUtil.iterateCuboidAround(center.x, center.y, center.z, 3, 3, 3, p -> {
tryToSetLeaves(world, p, leaves);
});
VectorUtil.iterateCuboidAround(center.x, center.y, center.z, 5, 5, 1, p -> {
tryToSetLeaves(world, p, leaves);
});
}
@Override
protected boolean isSolid(SurfaceWorld world, Vec3i surfaceBlockInWorld) {
return BlockLogicRegistry.getInstance().get(world.getBlockSfc(surfaceBlockInWorld).getId()).isSolid(RelFace.UP);
}
}

View File

@ -93,8 +93,6 @@ public class TestChunkCodec extends ChunkCodec {
ChunkData chunk = new ChunkData(position, world);
assert chunk.getUp() == ru.windcorp.progressia.server.ServerState.getInstance().getWorld().getData().getChunk(position).getUp();
readBlocks(input, blockPalette, chunk);
readTiles(input, tilePalette, chunk);

View File

@ -140,6 +140,9 @@ public class TestContent {
)
);
register(new BlockLogic("Test:Log"));
register(new BlockData("Test:TemporaryLeaves"));
register(new BlockRenderTransparentCube("Test:TemporaryLeaves", getBlockTexture("TemporaryLeaves")));
register(new TestBlockLogicGlass("Test:TemporaryLeaves")); // Sic, using Glass logic for leaves because Test
register(new BlockData("Test:WoodenPlank"));
register(new BlockRenderOpaqueCube("Test:WoodenPlank", getBlockTexture("WoodenPlank")));

View File

@ -0,0 +1,68 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.test;
import java.util.Set;
import com.google.common.collect.ImmutableSet;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.rels.RelFace;
import ru.windcorp.progressia.common.world.tile.TileData;
import ru.windcorp.progressia.common.world.tile.TileDataRegistry;
import ru.windcorp.progressia.server.world.block.BlockLogicRegistry;
import ru.windcorp.progressia.test.gen.surface.SurfaceTopLayerFeature;
import ru.windcorp.progressia.test.gen.surface.SurfaceWorld;
public class TestGrassFeature extends SurfaceTopLayerFeature {
private static final Set<String> WHITELIST = ImmutableSet.of(
"Test:Dirt",
"Test:Stone",
"Test:GraniteMonolith",
"Test:GraniteCracked",
"Test:GraniteGravel"
);
public TestGrassFeature(String id) {
super(id);
}
@Override
protected void processTopBlock(SurfaceWorld world, Request request, Vec3i topBlock) {
if (!WHITELIST.contains(world.getBlockSfc(topBlock).getId())) {
return;
}
TileData grass = TileDataRegistry.getInstance().get("Test:Grass");
for (RelFace face : RelFace.getFaces()) {
if (face == RelFace.DOWN) continue;
if (BlockLogicRegistry.getInstance().get(world.getBlockSfc(topBlock.add_(face.getRelVector())).getId()).isTransparent()) {
world.getTilesSfc(topBlock, face).addFarthest(grass);
}
}
}
@Override
protected boolean isSolid(SurfaceWorld world, Vec3i surfaceBlockInWorld) {
return BlockLogicRegistry.getInstance().get(world.getBlockSfc(surfaceBlockInWorld).getId()).isSolid(RelFace.UP);
}
}

View File

@ -0,0 +1,103 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.test;
import java.util.function.Consumer;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.util.VectorUtil;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
import ru.windcorp.progressia.common.world.rels.RelFace;
import ru.windcorp.progressia.server.world.block.BlockLogicRegistry;
import ru.windcorp.progressia.test.gen.surface.SurfaceTopLayerFeature;
import ru.windcorp.progressia.test.gen.surface.SurfaceWorld;
public class TestTreeFeature extends SurfaceTopLayerFeature {
public TestTreeFeature(String id) {
super(id);
}
private void tryToSetLeaves(SurfaceWorld world, Vec3i posSfc, BlockData leaves) {
if (world.getBlockSfc(posSfc).getId().equals("Test:Air")) {
world.setBlockSfc(posSfc, leaves, false);
}
}
private void iterateSpheroid(Vec3i center, double horDiameter, double vertDiameter, Consumer<Vec3i> action) {
VectorUtil.iterateCuboidAround(
center.x, center.y, center.z,
(int) Math.ceil(horDiameter) / 2 * 2 + 5,
(int) Math.ceil(horDiameter) / 2 * 2 + 5,
(int) Math.ceil(vertDiameter) / 2 * 2 + 5,
pos -> {
double sx = (pos.x - center.x) / horDiameter;
double sy = (pos.y - center.y) / horDiameter;
double sz = (pos.z - center.z) / vertDiameter;
if (sx*sx + sy*sy + sz*sz <= 1) {
action.accept(pos);
}
}
);
}
@Override
protected void processTopBlock(SurfaceWorld world, Request request, Vec3i topBlock) {
if (request.getRandom().nextInt(20*20) > 0) return;
Vec3i start = topBlock.add_(0, 0, 1);
BlockData log = BlockDataRegistry.getInstance().get("Test:Log");
BlockData leaves = BlockDataRegistry.getInstance().get("Test:TemporaryLeaves");
Vec3i center = start.add_(0);
int height = request.getRandom().nextInt(3) + 5;
for (; center.z < start.z + height; ++center.z) {
world.setBlockSfc(center, log, false);
}
double branchHorDistance = 0;
do {
double branchSize = 0.5 + 1 * request.getRandom().nextDouble();
double branchHorAngle = 2 * Math.PI * request.getRandom().nextDouble();
int branchVertOffset = -2 + request.getRandom().nextInt(3);
Vec3i branchCenter = center.add_(
(int) (Math.sin(branchHorAngle) * branchHorDistance),
(int) (Math.cos(branchHorAngle) * branchHorDistance),
branchVertOffset
);
iterateSpheroid(branchCenter, 1.75 * branchSize, 2.5 * branchSize, p -> {
tryToSetLeaves(world, p, leaves);
});
branchHorDistance = 1 + 2 * request.getRandom().nextDouble();
} while (request.getRandom().nextInt(8) > 1);
}
@Override
protected boolean isSolid(SurfaceWorld world, Vec3i surfaceBlockInWorld) {
return BlockLogicRegistry.getInstance().get(world.getBlockSfc(surfaceBlockInWorld).getId()).isSolid(RelFace.UP);
}
}

View File

@ -26,6 +26,8 @@ import ru.windcorp.progressia.common.util.VectorUtil;
import ru.windcorp.progressia.common.world.ChunkData;
import ru.windcorp.progressia.common.world.rels.AbsFace;
import ru.windcorp.progressia.test.TestBushFeature;
import ru.windcorp.progressia.test.TestGrassFeature;
import ru.windcorp.progressia.test.TestTreeFeature;
import ru.windcorp.progressia.test.gen.surface.Surface;
import ru.windcorp.progressia.test.gen.surface.SurfaceFeature;
import ru.windcorp.progressia.test.gen.surface.SurfaceFeatureGenerator;
@ -41,6 +43,8 @@ public class PlanetFeatureGenerator {
Collection<SurfaceFeature> features = new ArrayList<>();
features.add(new TestBushFeature("Test:BushFeature"));
features.add(new TestTreeFeature("Test:TreeFeature"));
features.add(new TestGrassFeature("Test:GrassFeature"));
int seaLevel = (int) parent.getPlanet().getRadius();
this.surfaceGenerators = AbsFace.mapToFaces(face -> new SurfaceFeatureGenerator(
@ -59,6 +63,8 @@ public class PlanetFeatureGenerator {
} else {
generateBorderFeatures(chunk);
}
chunk.setGenerationHint(true);
}
private boolean isOrdinaryChunk(Vec3i chunkPos) {
@ -72,7 +78,6 @@ public class PlanetFeatureGenerator {
private void generateBorderFeatures(ChunkData chunk) {
// Do nothing
chunk.setGenerationHint(true);
}
}

View File

@ -70,6 +70,8 @@ class PlanetTerrainGenerator {
generateBorderTerrain(chunk);
}
chunk.setGenerationHint(false);
return chunk;
}

View File

@ -72,7 +72,7 @@ public class TestPlanetGenerator extends AbstractWorldGenerator<Boolean> {
@Override
protected boolean checkIsChunkReady(Boolean hint) {
return hint == Boolean.TRUE; // Avoid NPE
return Boolean.TRUE.equals(hint); // Avoid NPE
}
@Override
@ -91,7 +91,6 @@ public class TestPlanetGenerator extends AbstractWorldGenerator<Boolean> {
ChunkData chunk = getWorldData().getChunk(chunkPos);
if (chunk == null) {
getServer().getLoadManager().getChunkManager().loadChunk(chunkPos);
chunk = getWorldData().getChunk(chunkPos);
}

View File

@ -27,36 +27,44 @@ import ru.windcorp.progressia.common.util.Vectors;
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import ru.windcorp.progressia.common.world.ChunkData;
import ru.windcorp.progressia.common.world.generic.GenericChunks;
import ru.windcorp.progressia.common.world.rels.AxisRotations;
public abstract class SurfaceFeature extends Namespaced {
public static class Request {
private final SurfaceWorld world;
private final ChunkData chunk;
private final Vec3i minSfc = new Vec3i();
private final Vec3i maxSfc = new Vec3i();
private final Random random;
public Request(ChunkData chunk, Random random) {
public Request(SurfaceWorld world, ChunkData chunk, Random random) {
this.world = world;
this.chunk = chunk;
this.random = random;
Vec3i absMin = chunk.getMinBIW(null);
Vec3i absMax = chunk.getMaxBIW(null);
Vec3i tmpMin = chunk.getMinBIW(null);
Vec3i tmpMax = chunk.getMaxBIW(null);
AxisRotations.relativize(absMin, chunk.getUp(), absMin);
AxisRotations.relativize(absMax, chunk.getUp(), absMax);
GenericChunks.relativize(tmpMin, chunk.getUp(), tmpMin);
GenericChunks.relativize(tmpMax, chunk.getUp(), tmpMax);
Glm.min(absMin, absMax, minSfc);
Glm.max(absMin, absMax, maxSfc);
Glm.min(tmpMin, tmpMax, minSfc);
Glm.max(tmpMin, tmpMax, maxSfc);
minSfc.z -= world.getSurface().getSeaLevel();
maxSfc.z -= world.getSurface().getSeaLevel();
}
public ChunkData getChunk() {
return chunk;
}
public SurfaceWorld getWorld() {
return world;
}
public Random getRandom() {
return random;
}
@ -93,56 +101,6 @@ public abstract class SurfaceFeature extends Namespaced {
return maxSfc;
}
public boolean contains(Vec3i surfaceBlockInWorld) {
Vec3i bic = Vectors.grab3i();
bic.set(surfaceBlockInWorld.x, surfaceBlockInWorld.y, surfaceBlockInWorld.z);
bic.sub(minSfc);
boolean result = GenericChunks.containsBiC(bic);
Vectors.release(bic);
return result;
}
public void forEach(Consumer<? super Vec3i> action) {
VectorUtil.iterateCuboid(
minSfc.x,
minSfc.y,
minSfc.z,
maxSfc.x + 1,
maxSfc.y + 1,
maxSfc.z + 1,
action
);
}
/**
* Provided vectors have z set to {@link #getMinZ()}.
*/
public void forEachOnFloor(Consumer<? super Vec3i> action) {
forEachOnLayer(action, getMinZ());
}
/**
* Provided vectors have z set to {@link #getMaxZ()}.
*/
public void forEachOnCeiling(Consumer<? super Vec3i> action) {
forEachOnLayer(action, getMaxZ());
}
/**
* Provided vectors have z set to layer.
*/
public void forEachOnLayer(Consumer<? super Vec3i> action, int layer) {
VectorUtil.iterateCuboid(
minSfc.x,
minSfc.y,
layer,
maxSfc.x + 1,
maxSfc.y + 1,
layer + 1,
action
);
}
}
public SurfaceFeature(String id) {
@ -151,4 +109,58 @@ public abstract class SurfaceFeature extends Namespaced {
public abstract void process(SurfaceWorld world, Request request);
/*
* Utility methods
*/
public boolean contains(Request request, Vec3i surfaceBlockInWorld) {
Vec3i bic = Vectors.grab3i();
bic.set(surfaceBlockInWorld.x, surfaceBlockInWorld.y, surfaceBlockInWorld.z);
bic.sub(request.minSfc);
boolean result = GenericChunks.containsBiC(bic);
Vectors.release(bic);
return result;
}
public void forEach(Request request, Consumer<? super Vec3i> action) {
VectorUtil.iterateCuboid(
request.minSfc.x,
request.minSfc.y,
request.minSfc.z,
request.maxSfc.x + 1,
request.maxSfc.y + 1,
request.maxSfc.z + 1,
action
);
}
/**
* Provided vectors have z set to {@link #getMinZ()}.
*/
public void forEachOnFloor(Request request, Consumer<? super Vec3i> action) {
forEachOnLayer(request, action, request.getMinZ());
}
/**
* Provided vectors have z set to {@link #getMaxZ()}.
*/
public void forEachOnCeiling(Request request, Consumer<? super Vec3i> action) {
forEachOnLayer(request, action, request.getMaxZ());
}
/**
* Provided vectors have z set to layer.
*/
public void forEachOnLayer(Request request, Consumer<? super Vec3i> action, int layer) {
VectorUtil.iterateCuboid(
request.minSfc.x,
request.minSfc.y,
layer,
request.maxSfc.x + 1,
request.maxSfc.y + 1,
layer + 1,
action
);
}
}

View File

@ -46,7 +46,7 @@ public class SurfaceFeatureGenerator {
SurfaceWorld world = new SurfaceWorld(surface, chunk.getWorld());
Random random = new Random(CoordinatePacker.pack3IntsIntoLong(chunk.getPosition()) /* ^ seed*/);
SurfaceFeature.Request request = new SurfaceFeature.Request(chunk, random);
SurfaceFeature.Request request = new SurfaceFeature.Request(world, chunk, random);
for (SurfaceFeature feature : features) {
feature.process(world, request);

View File

@ -0,0 +1,58 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.test.gen.surface;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.util.Vectors;
public abstract class SurfaceTopLayerFeature extends SurfaceFeature {
public SurfaceTopLayerFeature(String id) {
super(id);
}
protected abstract void processTopBlock(SurfaceWorld world, Request request, Vec3i topBlock);
protected abstract boolean isSolid(SurfaceWorld world, Vec3i surfaceBlockInWorld);
@Override
public void process(SurfaceWorld world, Request request) {
Vec3i cursor = Vectors.grab3i();
forEachOnLayer(request, pos -> {
cursor.set(pos.x, pos.y, pos.z);
if (!isSolid(world, cursor)) {
return;
}
for (cursor.z += 1; cursor.z <= request.getMaxZ() + 1; ++cursor.z) {
if (!isSolid(world, cursor)) {
cursor.z -= 1;
processTopBlock(world, request, cursor);
return;
}
}
}, request.getMinZ());
Vectors.release(cursor);
}
}

View File

@ -31,7 +31,8 @@ import ru.windcorp.progressia.common.world.tile.TileData;
import ru.windcorp.progressia.common.world.tile.TileDataReference;
import ru.windcorp.progressia.common.world.tile.TileDataStack;
public class SurfaceWorld implements GenericWritableWorld<BlockData, TileData, TileDataStack, TileDataReference, ChunkData, EntityData> {
public class SurfaceWorld
implements GenericWritableWorld<BlockData, TileData, TileDataStack, TileDataReference, ChunkData, EntityData> {
private final Surface surface;
private final GenericWritableWorld<BlockData, TileData, TileDataStack, TileDataReference, ChunkData, EntityData> parent;
@ -99,13 +100,26 @@ public class SurfaceWorld implements GenericWritableWorld<BlockData, TileData, T
public Vec3i resolve(Vec3i surfacePosition, Vec3i output) {
if (output == null) {
output = new Vec3i();
output = new Vec3i();
}
output.set(surfacePosition.x, surfacePosition.y, surfacePosition.z);
output.z -= getSurface().getSeaLevel();
output.z += getSurface().getSeaLevel();
GenericChunks.resolve(surfacePosition, output, getSurface().getUp());
GenericChunks.resolve(output, getSurface().getUp(), output);
return output;
}
public Vec3i relativize(Vec3i absolutePosition, Vec3i output) {
if (output == null) {
output = new Vec3i();
}
output.set(absolutePosition.x, absolutePosition.y, absolutePosition.z);
GenericChunks.relativize(output, getSurface().getUp(), output);
output.z -= getSurface().getSeaLevel();
return output;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 705 B

View File

@ -0,0 +1,83 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.common.world.generic;
import static org.junit.Assert.fail;
import static ru.windcorp.progressia.common.world.generic.GenericChunks.*;
import java.util.Random;
import org.junit.Test;
import glm.Glm;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.rels.AbsFace;
public class GenericChunkRotationsTest {
private static void assertVecEquals(String message, AbsFace up, Vec3i a, Vec3i b) {
if (a == b) {
return;
}
if (Glm.equals(a, b)) {
return;
}
fail(String.format("%s. x = (%4d; %4d; %4d), got (%4d; %4d; %4d) (up = %s)", message, a.x, a.y, a.z, b.x, b.y, b.z, up));
}
private void check(int x, int y, int z) {
for (AbsFace up : AbsFace.getFaces()) {
Vec3i veci = new Vec3i(x, y, z);
assertVecEquals("Vec3i, x != resolve(relativize(x))", up, veci, resolve(relativize(veci, up, null), up, null));
assertVecEquals("Vec3i, x != relativize(resolve(x))", up, veci, relativize(resolve(veci, up, null), up, null));
}
}
@Test
public void specialCases() {
for (int x = -1; x <= 1; ++x) {
for (int y = -1; y <= 1; ++y) {
for (int z = -1; z <= 1; ++z) {
check(x, y, z);
}
}
}
}
@Test
public void randomValues() {
final int iterations = 2 << 16;
final long seed = 0;
Random random = new Random(seed);
for (int i = 0; i < iterations; ++i) {
check(random.nextInt(200) - 100, random.nextInt(200) - 100, random.nextInt(200) - 100);
}
}
}

View File

@ -0,0 +1,100 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.common.world.rels;
import static org.junit.Assert.fail;
import static ru.windcorp.progressia.common.world.rels.AxisRotations.*;
import java.util.Random;
import org.junit.Test;
import glm.Glm;
import glm.vec._3.Vec3;
import glm.vec._3.i.Vec3i;
public class AxisRotationsTest {
private static void assertVecEquals(String message, AbsFace up, Vec3i a, Vec3i b) {
if (a == b) {
return;
}
if (Glm.equals(a, b)) {
return;
}
fail(String.format("%s. x = (%4d; %4d; %4d), got (%4d; %4d; %4d) (up = %s)", message, a.x, a.y, a.z, b.x, b.y, b.z, up));
}
private static void assertVecEquals(String message, AbsFace up, Vec3 a, Vec3 b) {
if (a == b) {
return;
}
if (b.sub_(a).length() <= 1e-3) {
return;
}
fail(String.format("%s. x = (%4f; %4f; %4f), got (%4f; %4f; %4f), d = %f (up = %s)", message, a.x, a.y, a.z, b.x, b.y, b.z, b.sub_(a).length(), up));
}
private void check(int x, int y, int z) {
for (AbsFace up : AbsFace.getFaces()) {
Vec3i veci = new Vec3i(x, y, z);
assertVecEquals("Vec3i, x != resolve(relativize(x))", up, veci, resolve(relativize(veci, up, null), up, null));
assertVecEquals("Vec3i, x != relativize(resolve(x))", up, veci, relativize(resolve(veci, up, null), up, null));
Vec3 vecf = new Vec3(x, y, z);
assertVecEquals("Vec3, x != resolve(relativize(x))", up, vecf, resolve(relativize(vecf, up, null), up, null));
assertVecEquals("Vec3, x != relativize(resolve(x))", up, vecf, relativize(resolve(vecf, up, null), up, null));
}
}
@Test
public void specialCases() {
for (int x = -1; x <= 1; ++x) {
for (int y = -1; y <= 1; ++y) {
for (int z = -1; z <= 1; ++z) {
check(x, y, z);
}
}
}
}
@Test
public void randomValues() {
final int iterations = 2 << 16;
final long seed = 0;
Random random = new Random(seed);
for (int i = 0; i < iterations; ++i) {
check(random.nextInt(200) - 100, random.nextInt(200) - 100, random.nextInt(200) - 100);
}
}
}