From 068f229a453fe82c38f2e6a2e7004eb4fe655a0c Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Mon, 31 Aug 2020 20:39:35 +0300 Subject: [PATCH 1/6] Added TileLogic --- .../progressia/client/TestContent.java | 12 +- .../client/world/tile/TileLocation.java | 22 +++ .../progressia/common/world/ChunkData.java | 30 ++++ .../progressia/server/world/ChunkLogic.java | 95 +++++++++++-- .../server/world/MutableBlockTickContext.java | 54 +------ .../server/world/MutableChunkTickContext.java | 66 +++++++++ .../server/world/MutableTileTickContext.java | 65 +++++++++ .../progressia/server/world/TickContext.java | 3 + .../progressia/server/world/Ticker.java | 37 +++-- .../block/ForwardingBlockTickContext.java | 21 ++- .../{Tickable.java => TickableBlock.java} | 2 +- .../{Updatable.java => UpdatableBlock.java} | 2 +- .../world/tile/ForwardingTileTickContext.java | 132 ++++++++++++++++++ .../server/world/tile/TickableTile.java | 17 +++ .../server/world/tile/TileLogic.java | 28 ++++ .../server/world/tile/TileLogicRegistry.java | 13 ++ .../server/world/tile/TileTickContext.java | 71 ++++++++++ .../server/world/tile/UpdatableTile.java | 9 ++ 18 files changed, 601 insertions(+), 78 deletions(-) create mode 100644 src/main/java/ru/windcorp/progressia/client/world/tile/TileLocation.java create mode 100644 src/main/java/ru/windcorp/progressia/server/world/MutableChunkTickContext.java create mode 100644 src/main/java/ru/windcorp/progressia/server/world/MutableTileTickContext.java rename src/main/java/ru/windcorp/progressia/server/world/block/{Tickable.java => TickableBlock.java} (87%) rename src/main/java/ru/windcorp/progressia/server/world/block/{Updatable.java => UpdatableBlock.java} (79%) create mode 100644 src/main/java/ru/windcorp/progressia/server/world/tile/ForwardingTileTickContext.java create mode 100644 src/main/java/ru/windcorp/progressia/server/world/tile/TickableTile.java create mode 100644 src/main/java/ru/windcorp/progressia/server/world/tile/TileLogic.java create mode 100644 src/main/java/ru/windcorp/progressia/server/world/tile/TileLogicRegistry.java create mode 100644 src/main/java/ru/windcorp/progressia/server/world/tile/TileTickContext.java create mode 100644 src/main/java/ru/windcorp/progressia/server/world/tile/UpdatableTile.java diff --git a/src/main/java/ru/windcorp/progressia/client/TestContent.java b/src/main/java/ru/windcorp/progressia/client/TestContent.java index b866d76..3a93f54 100644 --- a/src/main/java/ru/windcorp/progressia/client/TestContent.java +++ b/src/main/java/ru/windcorp/progressia/client/TestContent.java @@ -26,6 +26,8 @@ import ru.windcorp.progressia.server.comms.Client; import ru.windcorp.progressia.server.comms.controls.ControlLogic; import ru.windcorp.progressia.server.comms.controls.ControlLogicRegistry; import ru.windcorp.progressia.server.world.block.*; +import ru.windcorp.progressia.server.world.tile.TileLogic; +import ru.windcorp.progressia.server.world.tile.TileLogicRegistry; public class TestContent { @@ -64,15 +66,19 @@ public class TestContent { private static void registerTiles() { register(new TileData("Test", "Grass")); register(new TileRenderGrass("Test", "Grass", getTileTexture("grass_top"), getTileTexture("grass_side"))); + register(new TileLogic("Test", "Grass")); register(new TileData("Test", "Stones")); register(new TileRenderSimple("Test", "Stones", getTileTexture("stones"))); + register(new TileLogic("Test", "Stones")); register(new TileData("Test", "YellowFlowers")); register(new TileRenderSimple("Test", "YellowFlowers", getTileTexture("yellow_flowers"))); + register(new TileLogic("Test", "YellowFlowers")); register(new TileData("Test", "Sand")); register(new TileRenderSimple("Test", "Sand", getTileTexture("sand"))); + register(new TileLogic("Test", "Sand")); } private static void regsiterControls() { @@ -117,8 +123,8 @@ public class TestContent { BlockLogicRegistry.getInstance().register(x); } -// private static void register(TileRender x) { -// TileLogicRegistry.getInstance().register(x); -// } + private static void register(TileLogic x) { + TileLogicRegistry.getInstance().register(x); + } } diff --git a/src/main/java/ru/windcorp/progressia/client/world/tile/TileLocation.java b/src/main/java/ru/windcorp/progressia/client/world/tile/TileLocation.java new file mode 100644 index 0000000..9590454 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/world/tile/TileLocation.java @@ -0,0 +1,22 @@ +package ru.windcorp.progressia.client.world.tile; + +import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.common.world.block.BlockFace; + +public class TileLocation { + + public final Vec3i pos = new Vec3i(); + public BlockFace face; + public int layer; + + public TileLocation() { + // Do nothing + } + + public TileLocation(TileLocation src) { + this.pos.set(src.pos.x, src.pos.y, src.pos.z); + this.face = src.face; + this.layer = src.layer; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/common/world/ChunkData.java b/src/main/java/ru/windcorp/progressia/common/world/ChunkData.java index 64033a6..f1f2bb8 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/ChunkData.java +++ b/src/main/java/ru/windcorp/progressia/common/world/ChunkData.java @@ -21,11 +21,13 @@ import static ru.windcorp.progressia.common.world.block.BlockFace.*; import java.util.ArrayList; import java.util.List; +import java.util.function.BiConsumer; import java.util.function.Consumer; import com.google.common.collect.Lists; import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.client.world.tile.TileLocation; import ru.windcorp.progressia.common.util.SizeLimitedList; import ru.windcorp.progressia.common.util.VectorUtil; import ru.windcorp.progressia.common.util.Vectors; @@ -249,6 +251,34 @@ public class ChunkData { action ); } + + /** + * Iterates over all tiles in this chunk. Tiles are referenced using their + * primary block (so that the face is + * {@linkplain BlockFace#isPrimary() primary}). + * + * @param action the action to perform. {@code TileLocation} refers to each + * tile using its primary block + */ + public void forEachTile(BiConsumer action) { + TileLocation loc = new TileLocation(); + + forEachBlock(blockInChunk -> { + loc.pos.set(blockInChunk.x, blockInChunk.y, blockInChunk.z); + + for (BlockFace face : BlockFace.getPrimaryFaces()) { + List list = getTilesOrNull(blockInChunk, face); + if (list == null) continue; + + loc.face = face; + + for (loc.layer = 0; loc.layer < list.size(); ++loc.layer) { + TileData tile = list.get(loc.layer); + action.accept(loc, tile); + } + } + }); + } public int getX() { return position.x; diff --git a/src/main/java/ru/windcorp/progressia/server/world/ChunkLogic.java b/src/main/java/ru/windcorp/progressia/server/world/ChunkLogic.java index 9b489a4..6ba1087 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/ChunkLogic.java +++ b/src/main/java/ru/windcorp/progressia/server/world/ChunkLogic.java @@ -2,43 +2,82 @@ package ru.windcorp.progressia.server.world; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; import java.util.function.BiConsumer; +import com.google.common.collect.Lists; + import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.client.world.tile.TileLocation; import ru.windcorp.progressia.common.world.ChunkData; +import ru.windcorp.progressia.common.world.block.BlockFace; +import ru.windcorp.progressia.common.world.tile.TileData; import ru.windcorp.progressia.server.world.block.BlockLogic; import ru.windcorp.progressia.server.world.block.BlockLogicRegistry; -import ru.windcorp.progressia.server.world.block.Tickable; +import ru.windcorp.progressia.server.world.block.TickableBlock; +import ru.windcorp.progressia.server.world.tile.TickableTile; +import ru.windcorp.progressia.server.world.tile.TileLogic; +import ru.windcorp.progressia.server.world.tile.TileLogicRegistry; public class ChunkLogic { private final WorldLogic world; private final ChunkData data; - private final Collection ticking = new ArrayList<>(); + private final Collection tickingBlocks = new ArrayList<>(); + private final Collection tickingTiles = new ArrayList<>(); + + private final Map, List> tileLogicLists = + Collections.synchronizedMap(new WeakHashMap<>()); public ChunkLogic(WorldLogic world, ChunkData data) { this.world = world; this.data = data; - generateTickList(); + generateTickLists(); } - private void generateTickList() { + private void generateTickLists() { MutableBlockTickContext blockTickContext = new MutableBlockTickContext(); + MutableTileTickContext tileTickContext = + new MutableTileTickContext(); + blockTickContext.setWorld(getWorld()); blockTickContext.setChunk(this); + tileTickContext.setWorld(getWorld()); + tileTickContext.setChunk(this); + data.forEachBlock(blockInChunk -> { BlockLogic block = getBlock(blockInChunk); - if (block instanceof Tickable) { + if (block instanceof TickableBlock) { blockTickContext.setCoordsInChunk(blockInChunk); - if (((Tickable) block).doesTickRegularly(blockTickContext)) { - ticking.add(new Vec3i(blockInChunk)); + if (((TickableBlock) block) + .doesTickRegularly(blockTickContext) + ) { + tickingBlocks.add(new Vec3i(blockInChunk)); + } + } + }); + + data.forEachTile((loc, tileData) -> { + TileLogic tile = + TileLogicRegistry.getInstance().get(tileData.getId()); + + if (tile instanceof TickableTile) { + tileTickContext.setCoordsInChunk(loc.pos); + tileTickContext.setFace(loc.face); + tileTickContext.setLayer(loc.layer); + + if (((TickableTile) tile).doesTickRegularly(tileTickContext)) { + tickingTiles.add(new TileLocation(loc)); } } }); @@ -53,19 +92,57 @@ public class ChunkLogic { } public boolean hasTickingBlocks() { - return ticking.isEmpty(); + return !tickingBlocks.isEmpty(); + } + + public boolean hasTickingTiles() { + return !tickingTiles.isEmpty(); } public void forEachTickingBlock(BiConsumer action) { - ticking.forEach(blockInChunk -> { + tickingBlocks.forEach(blockInChunk -> { action.accept(blockInChunk, getBlock(blockInChunk)); }); } + public void forEachTickingTile(BiConsumer action) { + tickingTiles.forEach(location -> { + action.accept( + location, + getTilesOrNull(location.pos, location.face) + .get(location.layer) + ); + }); + } + public BlockLogic getBlock(Vec3i blockInChunk) { return BlockLogicRegistry.getInstance().get( getData().getBlock(blockInChunk).getId() ); } + + public List getTiles(Vec3i blockInChunk, BlockFace face) { + return wrapTileList(getData().getTiles(blockInChunk, face)); + } + + public List getTilesOrNull(Vec3i blockInChunk, BlockFace face) { + List tiles = getData().getTilesOrNull(blockInChunk, face); + if (tiles == null) return null; + return wrapTileList(tiles); + } + + private List wrapTileList(List tileDataList) { + return tileLogicLists.computeIfAbsent( + tileDataList, + ChunkLogic::createWrapper + ); + } + + private static List createWrapper(List tileDataList) { + return Lists.transform( + tileDataList, + data -> TileLogicRegistry.getInstance().get(data.getId()) + ); + } } diff --git a/src/main/java/ru/windcorp/progressia/server/world/MutableBlockTickContext.java b/src/main/java/ru/windcorp/progressia/server/world/MutableBlockTickContext.java index 0b03a5c..b23731a 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/MutableBlockTickContext.java +++ b/src/main/java/ru/windcorp/progressia/server/world/MutableBlockTickContext.java @@ -3,57 +3,15 @@ package ru.windcorp.progressia.server.world; import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.util.Vectors; import ru.windcorp.progressia.common.world.Coordinates; -import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.world.block.BlockTickContext; -public class MutableBlockTickContext implements BlockTickContext { - - private double tickLength; - - private Server server; - private WorldLogic world; - - private ChunkLogic chunk; +public class MutableBlockTickContext +extends MutableChunkTickContext +implements BlockTickContext { private final Vec3i blockInWorld = new Vec3i(); private final Vec3i blockInChunk = new Vec3i(); - public double getTickLength() { - return tickLength; - } - - public void setTickLength(double tickLength) { - this.tickLength = tickLength; - } - - @Override - public Server getServer() { - return server; - } - - public void setServer(Server server) { - this.server = server; - setWorld(server.getWorld()); - } - - @Override - public WorldLogic getWorld() { - return world; - } - - public void setWorld(WorldLogic world) { - this.world = world; - } - - @Override - public ChunkLogic getChunk() { - return chunk; - } - - public void setChunk(ChunkLogic chunk) { - this.chunk = chunk; - } - @Override public Vec3i getCoords() { return this.blockInWorld; @@ -82,10 +40,4 @@ public class MutableBlockTickContext implements BlockTickContext { ); } - @Override - public void requestBlockTick(Vec3i blockInWorld) { - // TODO implement - throw new UnsupportedOperationException("Not yet implemented"); - } - } diff --git a/src/main/java/ru/windcorp/progressia/server/world/MutableChunkTickContext.java b/src/main/java/ru/windcorp/progressia/server/world/MutableChunkTickContext.java new file mode 100644 index 0000000..775cc1e --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/server/world/MutableChunkTickContext.java @@ -0,0 +1,66 @@ +package ru.windcorp.progressia.server.world; + +import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.common.world.block.BlockFace; +import ru.windcorp.progressia.server.Server; + +public class MutableChunkTickContext implements ChunkTickContext { + + private double tickLength; + private Server server; + private WorldLogic world; + private ChunkLogic chunk; + + public MutableChunkTickContext() { + super(); + } + + public double getTickLength() { + return tickLength; + } + + public void setTickLength(double tickLength) { + this.tickLength = tickLength; + } + + @Override + public Server getServer() { + return server; + } + + public void setServer(Server server) { + this.server = server; + setWorld(server.getWorld()); + } + + @Override + public WorldLogic getWorld() { + return world; + } + + public void setWorld(WorldLogic world) { + this.world = world; + } + + @Override + public ChunkLogic getChunk() { + return chunk; + } + + public void setChunk(ChunkLogic chunk) { + this.chunk = chunk; + } + + @Override + public void requestBlockTick(Vec3i blockInWorld) { + // TODO implement + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public void requestTileTick(Vec3i blockInWorld, BlockFace face, int layer) { + // TODO implement + throw new UnsupportedOperationException("Not yet implemented"); + } + +} \ No newline at end of file diff --git a/src/main/java/ru/windcorp/progressia/server/world/MutableTileTickContext.java b/src/main/java/ru/windcorp/progressia/server/world/MutableTileTickContext.java new file mode 100644 index 0000000..6770834 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/server/world/MutableTileTickContext.java @@ -0,0 +1,65 @@ +package ru.windcorp.progressia.server.world; + +import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.common.util.Vectors; +import ru.windcorp.progressia.common.world.Coordinates; +import ru.windcorp.progressia.common.world.block.BlockFace; +import ru.windcorp.progressia.server.world.tile.TileTickContext; + +public class MutableTileTickContext +extends MutableChunkTickContext +implements TileTickContext { + + private final Vec3i blockInWorld = new Vec3i(); + private final Vec3i blockInChunk = new Vec3i(); + + private BlockFace face; + private int layer; + + @Override + public Vec3i getCoords() { + return this.blockInWorld; + } + + @Override + public Vec3i getChunkCoords() { + return this.blockInChunk; + } + + public void setCoordsInWorld(Vec3i coords) { + getCoords().set(coords.x, coords.y, coords.z); + Coordinates.convertInWorldToInChunk(getCoords(), getChunkCoords()); + + Vec3i chunk = Vectors.grab3i(); + Coordinates.convertInWorldToChunk(coords, chunk); + setChunk(getWorld().getChunk(chunk)); + Vectors.release(chunk); + } + + public void setCoordsInChunk(Vec3i coords) { + getChunkCoords().set(coords.x, coords.y, coords.z); + Coordinates.getInWorld( + getChunkData().getPosition(), getChunkCoords(), + getCoords() + ); + } + + @Override + public BlockFace getFace() { + return face; + } + + public void setFace(BlockFace face) { + this.face = face; + } + + @Override + public int getLayer() { + return layer; + } + + public void setLayer(int layer) { + this.layer = layer; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/server/world/TickContext.java b/src/main/java/ru/windcorp/progressia/server/world/TickContext.java index d572fec..73d43e0 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/TickContext.java +++ b/src/main/java/ru/windcorp/progressia/server/world/TickContext.java @@ -2,6 +2,7 @@ package ru.windcorp.progressia.server.world; import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.world.WorldData; +import ru.windcorp.progressia.common.world.block.BlockFace; import ru.windcorp.progressia.server.Server; public interface TickContext { @@ -19,5 +20,7 @@ public interface TickContext { } void requestBlockTick(Vec3i blockInWorld); + + void requestTileTick(Vec3i blockInWorld, BlockFace face, int layer); } diff --git a/src/main/java/ru/windcorp/progressia/server/world/Ticker.java b/src/main/java/ru/windcorp/progressia/server/world/Ticker.java index 975ddcb..ec4b4e5 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/Ticker.java +++ b/src/main/java/ru/windcorp/progressia/server/world/Ticker.java @@ -1,7 +1,8 @@ package ru.windcorp.progressia.server.world; import ru.windcorp.progressia.server.Server; -import ru.windcorp.progressia.server.world.block.Tickable; +import ru.windcorp.progressia.server.world.block.TickableBlock; +import ru.windcorp.progressia.server.world.tile.TickableTile; public class Ticker implements Runnable { @@ -11,6 +12,9 @@ public class Ticker implements Runnable { private final MutableBlockTickContext blockTickContext = new MutableBlockTickContext(); + private final MutableTileTickContext tileTickContext = + new MutableTileTickContext(); + private final Server server; public Ticker(Server server) { @@ -26,30 +30,41 @@ public class Ticker implements Runnable { } private void tickChunk(ChunkLogic chunk) { - MutableBlockTickContext context = this.blockTickContext; + MutableBlockTickContext blockContext = this.blockTickContext; + MutableTileTickContext tileContext = this.tileTickContext; - context.setServer(server); - context.setChunk(chunk); + blockContext.setServer(server); + tileContext.setServer(server); - tickRegularBlocks(chunk, context); - tickRandomBlocks(chunk, context); + tickRegularTickers(chunk, blockContext, tileContext); + tickRandomBlocks(chunk, blockContext, tileContext); flushChanges(chunk); } - private void tickRegularBlocks( + private void tickRegularTickers( ChunkLogic chunk, - MutableBlockTickContext context + MutableBlockTickContext blockContext, + MutableTileTickContext tileContext ) { chunk.forEachTickingBlock((blockInChunk, block) -> { - context.setCoordsInChunk(blockInChunk); - ((Tickable) block).tick(context, tracker); + blockContext.setCoordsInChunk(blockInChunk); + ((TickableBlock) block).tick(blockContext, tracker); + }); + + chunk.forEachTickingTile((locInChunk, tile) -> { + tileContext.setCoordsInChunk(locInChunk.pos); + tileContext.setFace(locInChunk.face); + tileContext.setLayer(locInChunk.layer); + + ((TickableTile) tile).tick(tileContext, tracker); }); } private void tickRandomBlocks( ChunkLogic chunk, - MutableBlockTickContext context + MutableBlockTickContext blockContext, + MutableTileTickContext tileContext ) { // TODO implement } diff --git a/src/main/java/ru/windcorp/progressia/server/world/block/ForwardingBlockTickContext.java b/src/main/java/ru/windcorp/progressia/server/world/block/ForwardingBlockTickContext.java index 49bb42c..03be3be 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/block/ForwardingBlockTickContext.java +++ b/src/main/java/ru/windcorp/progressia/server/world/block/ForwardingBlockTickContext.java @@ -4,11 +4,12 @@ import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.block.BlockData; +import ru.windcorp.progressia.common.world.block.BlockFace; import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.world.ChunkLogic; import ru.windcorp.progressia.server.world.WorldLogic; -public class ForwardingBlockTickContext { +public class ForwardingBlockTickContext implements BlockTickContext { private BlockTickContext parent; @@ -24,46 +25,62 @@ public class ForwardingBlockTickContext { this.parent = parent; } + @Override public ChunkLogic getChunk() { return parent.getChunk(); } - + + @Override public ChunkData getChunkData() { return parent.getChunkData(); } + @Override public double getTickLength() { return parent.getTickLength(); } + @Override public Server getServer() { return parent.getServer(); } + @Override public Vec3i getCoords() { return parent.getCoords(); } + @Override public WorldLogic getWorld() { return parent.getWorld(); } + @Override public WorldData getWorldData() { return parent.getWorldData(); } + @Override public Vec3i getChunkCoords() { return parent.getChunkCoords(); } + @Override public void requestBlockTick(Vec3i blockInWorld) { parent.requestBlockTick(blockInWorld); } + @Override + public void requestTileTick(Vec3i blockInWorld, BlockFace face, int layer) { + parent.requestTileTick(blockInWorld, face, layer); + } + + @Override public BlockLogic getBlock() { return parent.getBlock(); } + @Override public BlockData getBlockData() { return parent.getBlockData(); } diff --git a/src/main/java/ru/windcorp/progressia/server/world/block/Tickable.java b/src/main/java/ru/windcorp/progressia/server/world/block/TickableBlock.java similarity index 87% rename from src/main/java/ru/windcorp/progressia/server/world/block/Tickable.java rename to src/main/java/ru/windcorp/progressia/server/world/block/TickableBlock.java index cb12d80..4bdfceb 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/block/Tickable.java +++ b/src/main/java/ru/windcorp/progressia/server/world/block/TickableBlock.java @@ -2,7 +2,7 @@ package ru.windcorp.progressia.server.world.block; import ru.windcorp.progressia.server.world.Changer; -public interface Tickable { +public interface TickableBlock { void tick(BlockTickContext context, Changer changer); diff --git a/src/main/java/ru/windcorp/progressia/server/world/block/Updatable.java b/src/main/java/ru/windcorp/progressia/server/world/block/UpdatableBlock.java similarity index 79% rename from src/main/java/ru/windcorp/progressia/server/world/block/Updatable.java rename to src/main/java/ru/windcorp/progressia/server/world/block/UpdatableBlock.java index ab13886..b76f6da 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/block/Updatable.java +++ b/src/main/java/ru/windcorp/progressia/server/world/block/UpdatableBlock.java @@ -2,7 +2,7 @@ package ru.windcorp.progressia.server.world.block; import ru.windcorp.progressia.server.world.Changer; -public interface Updatable { +public interface UpdatableBlock { void update(BlockTickContext context, Changer changer); diff --git a/src/main/java/ru/windcorp/progressia/server/world/tile/ForwardingTileTickContext.java b/src/main/java/ru/windcorp/progressia/server/world/tile/ForwardingTileTickContext.java new file mode 100644 index 0000000..0f2c29e --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/server/world/tile/ForwardingTileTickContext.java @@ -0,0 +1,132 @@ +package ru.windcorp.progressia.server.world.tile; + +import java.util.List; + +import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.common.world.ChunkData; +import ru.windcorp.progressia.common.world.WorldData; +import ru.windcorp.progressia.common.world.block.BlockData; +import ru.windcorp.progressia.common.world.block.BlockFace; +import ru.windcorp.progressia.common.world.tile.TileData; +import ru.windcorp.progressia.server.Server; +import ru.windcorp.progressia.server.world.ChunkLogic; +import ru.windcorp.progressia.server.world.WorldLogic; +import ru.windcorp.progressia.server.world.block.BlockLogic; + +public class ForwardingTileTickContext implements TileTickContext { + + private TileTickContext parent; + + public ForwardingTileTickContext(TileTickContext parent) { + this.parent = parent; + } + + public TileTickContext getParent() { + return parent; + } + + public void setParent(TileTickContext parent) { + this.parent = parent; + } + + @Override + public ChunkLogic getChunk() { + return parent.getChunk(); + } + + @Override + public ChunkData getChunkData() { + return parent.getChunkData(); + } + + @Override + public double getTickLength() { + return parent.getTickLength(); + } + + @Override + public Server getServer() { + return parent.getServer(); + } + + @Override + public WorldLogic getWorld() { + return parent.getWorld(); + } + + @Override + public WorldData getWorldData() { + return parent.getWorldData(); + } + + @Override + public void requestBlockTick(Vec3i blockInWorld) { + parent.requestBlockTick(blockInWorld); + } + + @Override + public void requestTileTick(Vec3i blockInWorld, BlockFace face, int layer) { + parent.requestTileTick(blockInWorld, face, layer); + } + + @Override + public Vec3i getCoords() { + return parent.getCoords(); + } + + @Override + public Vec3i getChunkCoords() { + return parent.getChunkCoords(); + } + + @Override + public BlockFace getFace() { + return parent.getFace(); + } + + @Override + public int getLayer() { + return parent.getLayer(); + } + + @Override + public TileLogic getTile() { + return parent.getTile(); + } + + @Override + public TileData getTileData() { + return parent.getTileData(); + } + + @Override + public List getTiles() { + return parent.getTiles(); + } + + @Override + public List getTilesOrNull() { + return parent.getTilesOrNull(); + } + + @Override + public List getTileDataList() { + return parent.getTileDataList(); + } + + @Override + public List getTileDataListOrNull() { + return parent.getTileDataListOrNull(); + } + + @Override + public BlockLogic getBlock() { + return parent.getBlock(); + } + + @Override + public BlockData getBlockData() { + return parent.getBlockData(); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/server/world/tile/TickableTile.java b/src/main/java/ru/windcorp/progressia/server/world/tile/TickableTile.java new file mode 100644 index 0000000..d078ba0 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/server/world/tile/TickableTile.java @@ -0,0 +1,17 @@ +package ru.windcorp.progressia.server.world.tile; + +import ru.windcorp.progressia.server.world.Changer; + +public interface TickableTile { + + void tick(TileTickContext context, Changer changer); + + default boolean doesTickRegularly(TileTickContext context) { + return false; + } + + default boolean doesTickRandomly(TileTickContext context) { + return false; + } + +} \ No newline at end of file diff --git a/src/main/java/ru/windcorp/progressia/server/world/tile/TileLogic.java b/src/main/java/ru/windcorp/progressia/server/world/tile/TileLogic.java new file mode 100644 index 0000000..f530c26 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/server/world/tile/TileLogic.java @@ -0,0 +1,28 @@ +package ru.windcorp.progressia.server.world.tile; + +import ru.windcorp.progressia.common.util.Namespaced; +import ru.windcorp.progressia.common.world.block.BlockFace; + +public class TileLogic extends Namespaced { + + public TileLogic(String namespace, String name) { + super(namespace, name); + } + + public boolean canOccupyFace(TileTickContext context) { + return canOccupyFace(context.getFace()); + } + + public boolean canOccupyFace(BlockFace face) { + return true; + } + + public boolean isSolid(TileTickContext context) { + return isSolid(); + } + + public boolean isSolid() { + return false; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/server/world/tile/TileLogicRegistry.java b/src/main/java/ru/windcorp/progressia/server/world/tile/TileLogicRegistry.java new file mode 100644 index 0000000..a5b522b --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/server/world/tile/TileLogicRegistry.java @@ -0,0 +1,13 @@ +package ru.windcorp.progressia.server.world.tile; + +import ru.windcorp.progressia.common.util.NamespacedRegistry; + +public class TileLogicRegistry extends NamespacedRegistry { + + private static final TileLogicRegistry INSTANCE = new TileLogicRegistry(); + + public static TileLogicRegistry getInstance() { + return INSTANCE; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/server/world/tile/TileTickContext.java b/src/main/java/ru/windcorp/progressia/server/world/tile/TileTickContext.java new file mode 100644 index 0000000..0b80b5f --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/server/world/tile/TileTickContext.java @@ -0,0 +1,71 @@ +package ru.windcorp.progressia.server.world.tile; + +import java.util.List; + +import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.common.world.block.BlockData; +import ru.windcorp.progressia.common.world.block.BlockFace; +import ru.windcorp.progressia.common.world.tile.TileData; +import ru.windcorp.progressia.server.world.ChunkTickContext; +import ru.windcorp.progressia.server.world.block.BlockLogic; + +public interface TileTickContext extends ChunkTickContext { + + /** + * Returns the current world coordinates. + * @return the world coordinates of the tile being ticked + */ + Vec3i getCoords(); + + /** + * Returns the current chunk coordinates. + * @return the chunk coordinates of the tile being ticked + */ + Vec3i getChunkCoords(); + + /** + * Returns the current block face. This face is always + * {@linkplain BlockFace#isPrimary() primary}. + * @return the block face that the tile being ticked occupies + */ + BlockFace getFace(); + + /** + * Returns the current layer. + * @return the layer that the tile being ticked occupies in the tile stack + */ + int getLayer(); + + default TileLogic getTile() { + return getTiles().get(getLayer()); + } + + default TileData getTileData() { + return getTileDataList().get(getLayer()); + } + + default List getTiles() { + return getChunk().getTiles(getChunkCoords(), getFace()); + } + + default List getTilesOrNull() { + return getChunk().getTilesOrNull(getChunkCoords(), getFace()); + } + + default List getTileDataList() { + return getChunkData().getTiles(getChunkCoords(), getFace()); + } + + default List getTileDataListOrNull() { + return getChunkData().getTilesOrNull(getChunkCoords(), getFace()); + } + + default BlockLogic getBlock() { + return getChunk().getBlock(getChunkCoords()); + } + + default BlockData getBlockData() { + return getChunkData().getBlock(getChunkCoords()); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/server/world/tile/UpdatableTile.java b/src/main/java/ru/windcorp/progressia/server/world/tile/UpdatableTile.java new file mode 100644 index 0000000..00613f0 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/server/world/tile/UpdatableTile.java @@ -0,0 +1,9 @@ +package ru.windcorp.progressia.server.world.tile; + +import ru.windcorp.progressia.server.world.Changer; + +public interface UpdatableTile { + + void update(TileTickContext context, Changer changer); + +} From aa3cb630fbef2a5bb8f77c0952813529ea4fdee1 Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Wed, 2 Sep 2020 09:15:54 +0300 Subject: [PATCH 2/6] Fixed LayoutVertical --- .../client/graphics/gui/LayerTestGUI.java | 14 +++++++------- .../client/graphics/gui/layout/LayoutVertical.java | 8 +++----- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/LayerTestGUI.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/LayerTestGUI.java index d8d364e..6a74d96 100755 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/LayerTestGUI.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/LayerTestGUI.java @@ -81,7 +81,7 @@ public class LayerTestGUI extends GUILayer { panel.addChild(new DebugComponent("Bravo", new Vec2i(200, 100), 0x44FF44)); Component charlie = new DebugComponent("Charlie", null, 0x222222); - charlie.setLayout(new LayoutVertical()); + charlie.setLayout(new LayoutVertical(5)); //Debug Localizer.getInstance().setLanguage("ru-RU"); @@ -90,16 +90,16 @@ public class LayerTestGUI extends GUILayer { // These two are swapped in code due to a bug in layouts, fixing ATM charlie.addChild( new Label( - "Epsilon", - new Font().withColor(0x4444BB).deriveItalic(), - () -> epsilon.get().concat("\u269b") + "Delta", + new Font().withColor(0xCCBB44).deriveShadow().deriveBold(), + "Пре-альфа!" ) ); charlie.addChild( new Label( - "Delta", - new Font().withColor(0xCCBB44).deriveShadow().deriveBold(), - "Пре-альфа!" + "Epsilon", + new Font().withColor(0x4444BB).deriveItalic(), + () -> epsilon.get().concat("\u269b") ) ); panel.addChild(charlie); diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutVertical.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutVertical.java index 3ceea63..83e331f 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutVertical.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutVertical.java @@ -43,16 +43,14 @@ public class LayoutVertical implements Layout { @Override public void layout(Component c) { int x = c.getX() + margin, - y = c.getY() + margin; - - int height; + y = c.getY() + c.getHeight(); synchronized (c.getChildren()) { for (Component child : c.getChildren()) { - height = child.getPreferredSize().y; + int height = child.getPreferredSize().y; + y -= gap + height; child.setBounds(x, y, c.getWidth() - 2 * margin, height); - y += gap + height; } } From dc74a419c9f2e122e69a4c5983074b2a39703f6d Mon Sep 17 00:00:00 2001 From: serega404 Date: Thu, 3 Sep 2020 23:40:28 +0300 Subject: [PATCH 3/6] Added logger --- .gitignore | 1 + README.md | 1 + build.gradle | 10 ++++-- pictures/jetbrains_ide.png | Bin 0 -> 15952 bytes .../client/ProgressiaClientMain.java | 6 ++++ src/main/resources/log4j2.xml | 34 ++++++++++++++++++ 6 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 pictures/jetbrains_ide.png create mode 100644 src/main/resources/log4j2.xml diff --git a/.gitignore b/.gitignore index 9edc0b1..0d32c6c 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ bin # Ignore MacOS **/.DS_Store .idea/ +run/ diff --git a/README.md b/README.md index 3c60656..a5b54ce 100644 --- a/README.md +++ b/README.md @@ -43,3 +43,4 @@ plugins { * Trove4j * java-graphics/glm - GLM ported to Java. _Maven Central contains an outdated version, a custom repository used instead_ * Apache Commons Math (_not currently used_) +* log4j diff --git a/build.gradle b/build.gradle index 4a47ffe..618a35b 100644 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,11 @@ dependencies { implementation 'ru.windcorp.fork.io.github.java-graphics:glm:1.0.1' - testImplementation 'junit:junit:4.12' + // log4j + compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.13.3' + compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.13.3' + + testImplementation 'junit:junit:4.12' } /* @@ -70,4 +74,6 @@ dependencies { runtimeOnly "org.lwjgl:lwjgl-par::$lwjglNatives" runtimeOnly "org.lwjgl:lwjgl-stb::$lwjglNatives" if (lwjglNatives == "natives-macos") runtimeOnly "org.lwjgl:lwjgl-vulkan::$lwjglNatives" -} \ No newline at end of file +} + +// LWJGL END \ No newline at end of file diff --git a/pictures/jetbrains_ide.png b/pictures/jetbrains_ide.png new file mode 100644 index 0000000000000000000000000000000000000000..75706e6ca085631e41ba375b6696eda5c1bbd060 GIT binary patch literal 15952 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 + + + %d{yyyy-MM-dd'T'HH:mm:ss.SSSZ} %p %m%n + logs + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 9dc315487457d3c48e607eabede73ef074de205b Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Fri, 4 Sep 2020 21:54:55 +0300 Subject: [PATCH 4/6] Added entities - Added EntityData, EntityRender and EntityLogic - Added QuadripedModel - Added ComplexTexture to simplify syntax when working with complex models - Added the most adorable creature in the universe (as a test feature) - Camera is now 3rd person (temporary) - Direction can now be switched with F5 --- .../jputil/functions/FloatSupplier.java | 8 + .../ru/windcorp/progressia/client/Client.java | 10 + .../progressia/client/ClientState.java | 5 + .../progressia/client/TestContent.java | 43 ++- .../client/TestEntityRenderJavapony.java | 325 ++++++++++++++++++ .../client/graphics/model/Shapes.java | 22 ++ .../graphics/texture/ComplexTexture.java | 66 ++++ .../client/graphics/world/Camera.java | 6 + .../client/graphics/world/LayerWorld.java | 14 + .../progressia/client/world/ChunkRender.java | 6 + .../progressia/client/world/WorldRender.java | 19 + .../client/world/entity/EntityRender.java | 15 + .../world/entity/EntityRenderRegistry.java | 35 ++ .../client/world/entity/QuadripedModel.java | 195 +++++++++++ .../progressia/common/world/ChunkData.java | 18 + .../common/world/block/BlockFace.java | 16 + .../common/world/entity/EntityData.java | 62 ++++ .../world/entity/EntityDataRegistry.java | 13 + .../server/world/entity/EntityLogic.java | 11 + .../world/entity/EntityLogicRegistry.java | 14 + .../assets/textures/entities/javapony.png | Bin 0 -> 3347 bytes 21 files changed, 888 insertions(+), 15 deletions(-) create mode 100644 src/main/java/ru/windcorp/jputil/functions/FloatSupplier.java create mode 100644 src/main/java/ru/windcorp/progressia/client/TestEntityRenderJavapony.java create mode 100644 src/main/java/ru/windcorp/progressia/client/graphics/texture/ComplexTexture.java create mode 100644 src/main/java/ru/windcorp/progressia/client/world/entity/EntityRender.java create mode 100644 src/main/java/ru/windcorp/progressia/client/world/entity/EntityRenderRegistry.java create mode 100644 src/main/java/ru/windcorp/progressia/client/world/entity/QuadripedModel.java create mode 100644 src/main/java/ru/windcorp/progressia/common/world/entity/EntityData.java create mode 100644 src/main/java/ru/windcorp/progressia/common/world/entity/EntityDataRegistry.java create mode 100644 src/main/java/ru/windcorp/progressia/server/world/entity/EntityLogic.java create mode 100644 src/main/java/ru/windcorp/progressia/server/world/entity/EntityLogicRegistry.java create mode 100644 src/main/resources/assets/textures/entities/javapony.png diff --git a/src/main/java/ru/windcorp/jputil/functions/FloatSupplier.java b/src/main/java/ru/windcorp/jputil/functions/FloatSupplier.java new file mode 100644 index 0000000..060b06a --- /dev/null +++ b/src/main/java/ru/windcorp/jputil/functions/FloatSupplier.java @@ -0,0 +1,8 @@ +package ru.windcorp.jputil.functions; + +@FunctionalInterface +public interface FloatSupplier { + + float getAsFloat(); + +} diff --git a/src/main/java/ru/windcorp/progressia/client/Client.java b/src/main/java/ru/windcorp/progressia/client/Client.java index b257e58..5115cc5 100644 --- a/src/main/java/ru/windcorp/progressia/client/Client.java +++ b/src/main/java/ru/windcorp/progressia/client/Client.java @@ -6,10 +6,12 @@ import ru.windcorp.progressia.client.comms.ServerCommsChannel; import ru.windcorp.progressia.client.graphics.world.Camera; import ru.windcorp.progressia.client.world.WorldRender; import ru.windcorp.progressia.common.world.WorldData; +import ru.windcorp.progressia.common.world.entity.EntityData; public class Client { private final WorldRender world; + private EntityData localPlayer; private final Camera camera = new Camera( new Vec3(-6, -6, 20), @@ -30,6 +32,14 @@ public class Client { return world; } + public EntityData getLocalPlayer() { + return localPlayer; + } + + public void setLocalPlayer(EntityData localPlayer) { + this.localPlayer = localPlayer; + } + public Camera getCamera() { return camera; } diff --git a/src/main/java/ru/windcorp/progressia/client/ClientState.java b/src/main/java/ru/windcorp/progressia/client/ClientState.java index 1a3eb73..eab5cfc 100644 --- a/src/main/java/ru/windcorp/progressia/client/ClientState.java +++ b/src/main/java/ru/windcorp/progressia/client/ClientState.java @@ -1,5 +1,6 @@ package ru.windcorp.progressia.client; +import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.client.comms.localhost.LocalServerCommsChannel; import ru.windcorp.progressia.client.graphics.GUI; import ru.windcorp.progressia.client.graphics.flat.LayerTestUI; @@ -27,6 +28,10 @@ public class ClientState { ServerState.getInstance() )); + client.setLocalPlayer( + world.getChunk(new Vec3i(0, 0, 0)).getEntities().get(0) + ); + setInstance(client); GUI.addBottomLayer(new LayerWorld(client)); diff --git a/src/main/java/ru/windcorp/progressia/client/TestContent.java b/src/main/java/ru/windcorp/progressia/client/TestContent.java index 3a93f54..d49b081 100644 --- a/src/main/java/ru/windcorp/progressia/client/TestContent.java +++ b/src/main/java/ru/windcorp/progressia/client/TestContent.java @@ -6,28 +6,22 @@ import static ru.windcorp.progressia.client.world.tile.TileRenderRegistry.getTil import org.lwjgl.glfw.GLFW; import glm.vec._3.i.Vec3i; -import ru.windcorp.progressia.client.comms.controls.ControlTriggerOnKeyPress; -import ru.windcorp.progressia.client.comms.controls.ControlTriggerRegistry; +import ru.windcorp.progressia.client.comms.controls.*; import ru.windcorp.progressia.client.graphics.input.KeyMatcher; import ru.windcorp.progressia.client.world.block.*; -import ru.windcorp.progressia.client.world.tile.TileRender; -import ru.windcorp.progressia.client.world.tile.TileRenderGrass; -import ru.windcorp.progressia.client.world.tile.TileRenderRegistry; -import ru.windcorp.progressia.client.world.tile.TileRenderSimple; -import ru.windcorp.progressia.common.comms.controls.ControlData; -import ru.windcorp.progressia.common.comms.controls.ControlDataRegistry; -import ru.windcorp.progressia.common.comms.controls.PacketControl; +import ru.windcorp.progressia.client.world.entity.*; +import ru.windcorp.progressia.client.world.tile.*; +import ru.windcorp.progressia.common.comms.controls.*; import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.block.*; -import ru.windcorp.progressia.common.world.tile.TileData; -import ru.windcorp.progressia.common.world.tile.TileDataRegistry; +import ru.windcorp.progressia.common.world.entity.*; +import ru.windcorp.progressia.common.world.tile.*; import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.comms.Client; -import ru.windcorp.progressia.server.comms.controls.ControlLogic; -import ru.windcorp.progressia.server.comms.controls.ControlLogicRegistry; +import ru.windcorp.progressia.server.comms.controls.*; import ru.windcorp.progressia.server.world.block.*; -import ru.windcorp.progressia.server.world.tile.TileLogic; -import ru.windcorp.progressia.server.world.tile.TileLogicRegistry; +import ru.windcorp.progressia.server.world.entity.*; +import ru.windcorp.progressia.server.world.tile.*; public class TestContent { @@ -39,6 +33,7 @@ public class TestContent { private static void registerWorldContent() { registerBlocks(); registerTiles(); + registerEntities(); } private static void registerBlocks() { @@ -81,6 +76,12 @@ public class TestContent { register(new TileLogic("Test", "Sand")); } + private static void registerEntities() { + register(new EntityData("Test", "Javapony")); + register(new TestEntityRenderJavapony()); + register(new EntityLogic("Test", "Javapony")); + } + private static void regsiterControls() { ControlDataRegistry.getInstance().register(new ControlData("Test", "Switch000")); ControlTriggerRegistry.getInstance().register(new ControlTriggerOnKeyPress("Test", "Switch000", new KeyMatcher(GLFW.GLFW_KEY_G, new int[0], 0)::matches)); @@ -111,6 +112,10 @@ public class TestContent { TileDataRegistry.getInstance().register(x); } + private static void register(EntityData x) { + EntityDataRegistry.getInstance().register(x); + } + private static void register(BlockRender x) { BlockRenderRegistry.getInstance().register(x); } @@ -119,6 +124,10 @@ public class TestContent { TileRenderRegistry.getInstance().register(x); } + private static void register(EntityRender x) { + EntityRenderRegistry.getInstance().register(x); + } + private static void register(BlockLogic x) { BlockLogicRegistry.getInstance().register(x); } @@ -126,5 +135,9 @@ public class TestContent { private static void register(TileLogic x) { TileLogicRegistry.getInstance().register(x); } + + private static void register(EntityLogic x) { + EntityLogicRegistry.getInstance().register(x); + } } diff --git a/src/main/java/ru/windcorp/progressia/client/TestEntityRenderJavapony.java b/src/main/java/ru/windcorp/progressia/client/TestEntityRenderJavapony.java new file mode 100644 index 0000000..14ccabf --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/TestEntityRenderJavapony.java @@ -0,0 +1,325 @@ +package ru.windcorp.progressia.client; + +import java.util.ArrayList; +import java.util.List; + +import glm.vec._3.Vec3; +import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface; +import ru.windcorp.progressia.client.graphics.backend.Usage; +import ru.windcorp.progressia.client.graphics.model.Face; +import ru.windcorp.progressia.client.graphics.model.Faces; +import ru.windcorp.progressia.client.graphics.model.LambdaModel; +import ru.windcorp.progressia.client.graphics.model.Renderable; +import ru.windcorp.progressia.client.graphics.model.Shape; +import ru.windcorp.progressia.client.graphics.model.Shapes.PppBuilder; +import ru.windcorp.progressia.client.graphics.model.StaticModel; +import ru.windcorp.progressia.client.graphics.texture.ComplexTexture; +import ru.windcorp.progressia.client.graphics.texture.Texture; +import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram; +import ru.windcorp.progressia.client.world.entity.EntityRender; +import ru.windcorp.progressia.client.world.entity.EntityRenderRegistry; +import ru.windcorp.progressia.client.world.entity.QuadripedModel; +import ru.windcorp.progressia.common.world.block.BlockFace; +import ru.windcorp.progressia.common.world.entity.EntityData; + +public class TestEntityRenderJavapony extends EntityRender { + + private final Renderable body; + private final Renderable head; + private final Renderable foreLeg; + private final Renderable hindLeg; + + public TestEntityRenderJavapony() { + super("Test", "Javapony"); + + ComplexTexture texture = new ComplexTexture( + EntityRenderRegistry.getEntityTexture("javapony"), + 256, 128 + ); + + this.body = createBody(texture); + this.head = createHead(texture); + this.foreLeg = createForeLeg(texture); + this.hindLeg = createHindLeg(texture); + } + + private static Renderable createBody(ComplexTexture texture) { + LambdaModel.Builder b = LambdaModel.lambdaBuilder(); + + b.addStaticPart(createMainBody(texture)); + + Texture tailStartTexture = texture.get(128, 96, 8, 32); + + b.addStaticPart( + new PppBuilder( + WorldRenderProgram.getDefault(), + BlockFace.mapToFaces( + tailStartTexture, tailStartTexture, + tailStartTexture, tailStartTexture, + tailStartTexture, tailStartTexture + ) + ) + .setOrigin(-60, -4, 14) + .setDepth(32, 0, -16).setWidth(8).setHeight(8) + .create() + ); + + Texture neckTexture = texture.get(0, 48, 16, 16); + + b.addStaticPart( + new PppBuilder( + WorldRenderProgram.getDefault(), + BlockFace.mapToFaces( + neckTexture, neckTexture, neckTexture, + neckTexture, neckTexture, neckTexture + ) + ) + .setOrigin(0, -8, 8) + .setWidth(16).setDepth(16).setHeight(4, 0, 16) + .create() + ); + + b.addDynamicPart( + createTail(texture), + m -> m + .translate(-60, 0, 24) + .rotateX(0.05f * Math.sin(GraphicsInterface.getTime())) + .rotateY(0.05f * Math.sin(Math.PI / 3 * GraphicsInterface.getTime())) + ); + + return new LambdaModel(b); + } + + private static Renderable createMainBody(ComplexTexture texture) { + WorldRenderProgram program = WorldRenderProgram.getDefault(); + List faces = new ArrayList<>(); + + final Vec3 color = new Vec3(1, 1, 1); + + // F BODY + faces.add(Faces.createRectangle( + program, texture.get(80, 16, 32, 32), color, + new Vec3(+16, -16, -16), + new Vec3(0, +32, 0), new Vec3(0, 0, +32), + false + )); + + // NECK BASE + faces.add(Faces.createRectangle( + program, texture.get(80, 48, 32, 16), color, + new Vec3(+16, -16, +16), + new Vec3(0, +32, 0), new Vec3(-16, 0, 0), + false + )); + + // T BODY (BACK) + faces.add(Faces.createRectangle( + program, texture.get(128, 0, 32, 48), color, + new Vec3(0, -16, +16), + new Vec3(0, +32, 0), new Vec3(-48, 0, 0), + false + )); + + // BOTTOM B (upper) + faces.add(Faces.createRectangle( + program, texture.get(144, 48, 32, 16), color, + new Vec3(-48, -16, 0), + new Vec3(0, 32, 0), new Vec3(0, 0, 16), + true + )); + + // BOTTOM B (lower) + faces.add(Faces.createRectangle( + program, texture.get(144, 48, 32, 16), color, + new Vec3(-48, -16, -16), + new Vec3(0, 32, 0), new Vec3(0, 0, 16), + true + )); + + // BOTTOM B (stomach) + faces.add(Faces.createRectangle( + program, texture.get(144, 48, 32, 16), color, + new Vec3(-48, -16, -16), + new Vec3(0, 32, 0), new Vec3(16, 0, 0), + false + )); + + // STOMACH + faces.add(Faces.createRectangle( + program, texture.get(224, 96, 32, 32), color, + new Vec3(-32, -16, -16), + new Vec3(0, 32, 0), new Vec3(32, 0, 0), + false + )); + + // BOTTOM F + faces.add(Faces.createRectangle( + program, texture.get(112, 48, 32, 16), color, + new Vec3(+16, -16, -16), + new Vec3(0, 32, 0), new Vec3(-16, 0, 0), + true + )); + + // BODY L + faces.add(Faces.createRectangle( + program, texture.get(112, 16, 16, 32), color, + new Vec3(+16, +16, -16), + new Vec3(-16, 0, 0), new Vec3(0, 0, +32), + false + )); + + // BODY SIDES (left) + faces.add(Faces.createRectangle( + program, texture.get(96, 96, 32, 32), color, + new Vec3(0, +16, -16), + new Vec3(-32, 0, 0), new Vec3(0, 0, +32), + false + )); + + // QT MARK (left) + faces.add(Faces.createRectangle( + program, texture.get(16, 96, 16, 32), color, + new Vec3(-32, +16, -16), + new Vec3(-16, 0, 0), new Vec3(0, 0, +32), + false + )); + + // BODY R + faces.add(Faces.createRectangle( + program, texture.get(64, 16, 16, 32), color, + new Vec3(0, -16, -16), + new Vec3(+16, 0, 0), new Vec3(0, 0, +32), + false + )); + + // BODY SIDES (right) + faces.add(Faces.createRectangle( + program, texture.get(96, 96, 32, 32), color, + new Vec3(0, -16, -16), + new Vec3(-32, 0, 0), new Vec3(0, 0, +32), + true + )); + + // QT MARK (right) + faces.add(Faces.createRectangle( + program, texture.get(16, 96, 16, 32), color, + new Vec3(-32, -16, -16), + new Vec3(-16, 0, 0), new Vec3(0, 0, +32), + true + )); + + return new Shape( + Usage.STATIC, program, + faces.toArray(new Face[faces.size()]) + ); + } + + private static Renderable createHead(ComplexTexture texture) { + WorldRenderProgram program = WorldRenderProgram.getDefault(); + StaticModel.Builder b = StaticModel.builder(); + + // Head + b.addPart(new PppBuilder( + program, texture.getCuboidTextures(0, 64, 32) + ).setOrigin(-16, -16, 0).setSize(32).create()); + + final float hairOffset = 1f; + + // Hair + b.addPart( + new PppBuilder( + program, texture.getCuboidTextures(128, 64, 32) + ) + .setOrigin(-16 - hairOffset, -16 - hairOffset, -hairOffset) + .setSize(32 + 2*hairOffset) + .create() + ); + + // Right ear + b.addPart(new PppBuilder( + program, texture.getCuboidTextures(48, 128-80, 8) + ).setOrigin(-16 + 3, -16, 32).setSize(8).create()); + + // Left ear + b.addPart(new PppBuilder( + program, texture.getCuboidTextures(48, 128-80, 8) + ).setOrigin(-16 + 3, 16 - 8, 32).setSize(8).create()); + + // Muzzle + b.addPart(new PppBuilder( + program, BlockFace.mapToFaces( + texture.get(32, 64, 0, 0), + texture.get(32, 64, 0, 0), + texture.get(32 + 8, 64, 16, 8), + texture.get(32, 64, 0, 0), + texture.get(32, 64, 0, 0), + texture.get(32, 64, 0, 0) + ) + ).setOrigin(16, -8, 0).setSize(16, 4, 8).create()); + + // Nose + b.addPart(new PppBuilder( + program, BlockFace.mapToFaces( + texture.get(32, 64, 0, 0), + texture.get(32, 64, 0, 0), + texture.get(32 + 12, 64 + 8, 8, 4), + texture.get(32, 64, 0, 0), + texture.get(32, 64, 0, 0), + texture.get(32, 64, 0, 0) + ) + ).setOrigin(16, -4, 8).setSize(8, 4, 4).create()); + + return new StaticModel(b); + } + + private static Renderable createForeLeg(ComplexTexture texture) { + return new PppBuilder( + WorldRenderProgram.getDefault(), + texture.getCuboidTextures(160, 0, 16, 48, 16) + ).setOrigin(-8, -8, -48).setSize(16, 16, 48).create(); + } + + private static Renderable createHindLeg(ComplexTexture texture) { + return new PppBuilder( + WorldRenderProgram.getDefault(), + texture.getCuboidTextures(0, 0, 16, 48, 16) + ).setOrigin(-8, -8, -48).setSize(16, 16, 48).create(); + } + + private static Renderable createTail(ComplexTexture texture) { + WorldRenderProgram program = WorldRenderProgram.getDefault(); + StaticModel.Builder b = StaticModel.builder(); + + // Main tail + b.addPart(new PppBuilder( + program, BlockFace.mapToFaces( + texture.get(128, 96, 16, 16), + texture.get(128, 96, 16, 16), + texture.get(128, 96, 16, 32), + texture.get(128, 96, 16, 32), + texture.get(144, 96, 16, 32), + texture.get(144, 96, 16, 32) + ) + ).setOrigin(-8, -8, -32).setSize(16, 16, 32).create()); + + return new StaticModel(b); + } + + @Override + public Renderable createRenderable(EntityData entity) { + return new QuadripedModel( + entity, + + new QuadripedModel.Body(body), + new QuadripedModel.Head( + head, new Vec3(16, 0, 20), 60, 45 + ), + new QuadripedModel.Leg(foreLeg, new Vec3( 6, +8.1f, -16), 0.0f), + new QuadripedModel.Leg(foreLeg, new Vec3( 6, -8.1f, -16), 2.5f), + new QuadripedModel.Leg(hindLeg, new Vec3(-36, +8.2f, -16), 2.5f), + new QuadripedModel.Leg(hindLeg, new Vec3(-36, -8.2f, -16), 0.0f), + 1 / 96f + ); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/Shapes.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/Shapes.java index fabc468..90624ec 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/model/Shapes.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/Shapes.java @@ -17,10 +17,13 @@ *******************************************************************************/ package ru.windcorp.progressia.client.graphics.model; +import java.util.Map; + import glm.vec._3.Vec3; import ru.windcorp.progressia.client.graphics.backend.Usage; import ru.windcorp.progressia.client.graphics.texture.Texture; import ru.windcorp.progressia.common.util.Vectors; +import ru.windcorp.progressia.common.world.block.BlockFace; public class Shapes { @@ -149,6 +152,21 @@ public class Shapes { this.westTexture = west; } + public PppBuilder( + ShapeRenderProgram program, + Map textureMap + ) { + this( + program, + textureMap.get(BlockFace.TOP), + textureMap.get(BlockFace.BOTTOM), + textureMap.get(BlockFace.NORTH), + textureMap.get(BlockFace.SOUTH), + textureMap.get(BlockFace.EAST), + textureMap.get(BlockFace.WEST) + ); + } + public PppBuilder(ShapeRenderProgram program, Texture texture) { this(program, texture, texture, texture, texture, texture, texture); } @@ -222,6 +240,10 @@ public class Shapes { return this.setWidth(x).setDepth(y).setHeight(z); } + public PppBuilder setSize(float size) { + return this.setSize(size, size, size); + } + public Shape create() { return createParallelepiped( program, diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/texture/ComplexTexture.java b/src/main/java/ru/windcorp/progressia/client/graphics/texture/ComplexTexture.java new file mode 100644 index 0000000..d8f4c18 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/graphics/texture/ComplexTexture.java @@ -0,0 +1,66 @@ +package ru.windcorp.progressia.client.graphics.texture; + +import java.util.Map; + +import glm.vec._2.Vec2; +import ru.windcorp.progressia.common.world.block.BlockFace; + +public class ComplexTexture { + + private final TexturePrimitive primitive; + + private final float assumedWidth; + private final float assumedHeight; + + public ComplexTexture( + TexturePrimitive primitive, + int abstractWidth, int abstractHeight + ) { + this.primitive = primitive; + + this.assumedWidth = abstractWidth + * primitive.getWidth() / (float) primitive.getBufferWidth(); + + this.assumedHeight = abstractHeight + * primitive.getHeight() / (float) primitive.getBufferHeight(); + } + + public Texture get(int x, int y, int width, int height) { + return new SimpleTexture(new Sprite( + primitive, + new Vec2(x / assumedWidth, y / assumedHeight), + new Vec2(width / assumedWidth, height / assumedHeight) + )); + } + + public Map getCuboidTextures( + int x, int y, + int width, int height, int depth + ) { + return BlockFace.mapToFaces( + get( + x + depth + width, y + height + depth, + -width, -depth + ), + get( + x + depth + width + width, y + height + depth, + -width, -depth + ), + get(x + depth, y, width, height), + get( + x + depth + width + depth, y, + width, height + ), + get(x, y, depth, height), + get(x + depth + width, y, depth, height) + ); + } + + public Map getCuboidTextures( + int x, int y, + int size + ) { + return getCuboidTextures(x, y, size, size, size); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/Camera.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/Camera.java index 3eb8745..23af1e4 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/world/Camera.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/Camera.java @@ -33,6 +33,8 @@ public class Camera { private float fieldOfView; + public boolean tmp_mode = false; + public Camera(Vec3 position, float pitch, float yaw, float fieldOfView) { teleport(position); setPitch(pitch); @@ -46,6 +48,10 @@ public class Camera { applyPerspective(helper); rotateCoordinateSystem(helper); + // TODO debug + helper.pushViewTransform().translate(3.5f, 0, -0.5f); + if (tmp_mode) helper.pushViewTransform().rotateZ(PI); + applyDirection(helper); applyPosition(helper); } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java index 6f18b0e..30e4c4f 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java @@ -66,7 +66,15 @@ public class LayerWorld extends Layer { @Override protected void doRender() { + client.getLocalPlayer().setPosition(client.getCamera().getPosition()); + client.getLocalPlayer().setVelocity(velocity); + client.getLocalPlayer().getDirection().set( + -client.getCamera().getYaw(), + -client.getCamera().getPitch() + ); + client.getCamera().apply(helper); + renderWorld(); helper.reset(); @@ -156,6 +164,12 @@ public class LayerWorld extends Layer { flag = !flag; break; + case GLFW.GLFW_KEY_F5: + if (!event.isPress()) return false; + + client.getCamera().tmp_mode = !client.getCamera().tmp_mode; + break; + default: return false; } diff --git a/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java b/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java index 3bead82..badcfb7 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java +++ b/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java @@ -92,6 +92,12 @@ public class ChunkRender { model.render(renderer); renderer.popTransform(); + + getData().forEachEntity(entityData -> { + renderer.pushTransform().translate(entityData.getPosition()); + getWorld().getEntityRenderable(entityData).render(renderer); + renderer.popTransform(); + }); } private void buildModel() { diff --git a/src/main/java/ru/windcorp/progressia/client/world/WorldRender.java b/src/main/java/ru/windcorp/progressia/client/world/WorldRender.java index 249dd91..68b5e22 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/WorldRender.java +++ b/src/main/java/ru/windcorp/progressia/client/world/WorldRender.java @@ -18,19 +18,26 @@ package ru.windcorp.progressia.client.world; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.WeakHashMap; import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.client.graphics.model.Renderable; import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper; +import ru.windcorp.progressia.client.world.entity.EntityRenderRegistry; import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.WorldData; +import ru.windcorp.progressia.common.world.entity.EntityData; public class WorldRender { private final WorldData data; private final Map chunks = new HashMap<>(); + private final Map entityModels = + Collections.synchronizedMap(new WeakHashMap<>()); public WorldRender(WorldData data) { this.data = data; @@ -61,5 +68,17 @@ public class WorldRender { chunk.render(renderer); } } + + public Renderable getEntityRenderable(EntityData entity) { + return entityModels.computeIfAbsent( + entity, + WorldRender::createEntityRenderable + ); + } + + private static Renderable createEntityRenderable(EntityData entity) { + return EntityRenderRegistry.getInstance().get(entity.getId()) + .createRenderable(entity); + } } diff --git a/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRender.java b/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRender.java new file mode 100644 index 0000000..98e1f10 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRender.java @@ -0,0 +1,15 @@ +package ru.windcorp.progressia.client.world.entity; + +import ru.windcorp.progressia.client.graphics.model.Renderable; +import ru.windcorp.progressia.common.util.Namespaced; +import ru.windcorp.progressia.common.world.entity.EntityData; + +public abstract class EntityRender extends Namespaced { + + public EntityRender(String namespace, String name) { + super(namespace, name); + } + + public abstract Renderable createRenderable(EntityData entity); + +} diff --git a/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRenderRegistry.java b/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRenderRegistry.java new file mode 100644 index 0000000..e79cebe --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRenderRegistry.java @@ -0,0 +1,35 @@ +package ru.windcorp.progressia.client.world.entity; + +import java.io.IOException; + +import ru.windcorp.progressia.client.graphics.texture.TextureLoader; +import ru.windcorp.progressia.client.graphics.texture.TexturePrimitive; +import ru.windcorp.progressia.client.graphics.texture.TextureSettings; +import ru.windcorp.progressia.common.resource.ResourceManager; +import ru.windcorp.progressia.common.util.NamespacedRegistry; + +public class EntityRenderRegistry extends NamespacedRegistry { + + private static final EntityRenderRegistry INSTANCE = + new EntityRenderRegistry(); + + public static EntityRenderRegistry getInstance() { + return INSTANCE; + } + + public static TexturePrimitive getEntityTexture(String name) { + try { + return new TexturePrimitive( + TextureLoader.loadPixels( + ResourceManager.getTextureResource( + "entities/" + name + ), + new TextureSettings(false) + ).getData() + ); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/src/main/java/ru/windcorp/progressia/client/world/entity/QuadripedModel.java b/src/main/java/ru/windcorp/progressia/client/world/entity/QuadripedModel.java new file mode 100644 index 0000000..14e01e9 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/world/entity/QuadripedModel.java @@ -0,0 +1,195 @@ +package ru.windcorp.progressia.client.world.entity; + +import static java.lang.Math.*; + +import glm.Glm; +import glm.mat._4.Mat4; +import glm.vec._3.Vec3; +import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface; +import ru.windcorp.progressia.client.graphics.model.Renderable; +import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper; +import ru.windcorp.progressia.common.util.Vectors; +import ru.windcorp.progressia.common.world.entity.EntityData; + +public class QuadripedModel implements Renderable { + + private static abstract class BodyPart { + private final Renderable renderable; + private final Vec3 translation = new Vec3(); + + public BodyPart(Renderable renderable, Vec3 joint) { + this.renderable = renderable; + if (joint != null) { +// joint.negate(this.translation); + this.translation.set(joint); + } + } + + + protected void render( + ShapeRenderHelper renderer, QuadripedModel model + ) { + renderer.pushTransform().translate(translation); + applyTransform(renderer.pushTransform(), model); + renderable.render(renderer); + renderer.popTransform(); + renderer.popTransform(); + } + + protected abstract void applyTransform(Mat4 mat, QuadripedModel model); + } + + public static class Body extends BodyPart { + public Body(Renderable renderable) { + super(renderable, null); + } + + @Override + protected void applyTransform(Mat4 mat, QuadripedModel model) { + // Do nothing + } + } + + public static class Head extends BodyPart { + private final float maxYaw; + private final float maxPitch; + + public Head( + Renderable renderable, Vec3 joint, + double maxYawDegrees, double maxPitchDegrees + ) { + super(renderable, joint); + this.maxYaw = (float) toRadians(maxYawDegrees); + this.maxPitch = (float) toRadians(maxPitchDegrees); + } + + @Override + protected void applyTransform(Mat4 mat, QuadripedModel model) { + mat.rotateZ(model.headYaw).rotateY(model.headPitch); + } + } + + public static class Leg extends BodyPart { + private final float animationOffset; + + public Leg( + Renderable renderable, Vec3 joint, + float animationOffset + ) { + super(renderable, joint); + this.animationOffset = animationOffset; + } + + @Override + protected void applyTransform(Mat4 mat, QuadripedModel model) { + mat.rotateY(sin(model.walkingFrequency * model.walkingAnimationParameter + animationOffset) * model.walkingSwing * model.velocityCoeff); + } + } + + private final EntityData entity; + + private final Body body; + private final Head head; + private final Leg leftForeLeg, rightForeLeg; + private final Leg leftHindLeg, rightHindLeg; + + private final float scale; + + private float walkingAnimationParameter = 0; + private float velocityCoeff = 0; + private float velocity = 0; + + private float walkingFrequency = 0.15f; + private float walkingSwing = (float) toRadians(30); + + private float bodyYaw = Float.NaN; + private float headYaw; + private float headPitch; + + public QuadripedModel( + EntityData entity, + + Body body, Head head, + Leg leftForeLeg, Leg rightForeLeg, + Leg leftHindLeg, Leg rightHindLeg, + + float scale + ) { + this.entity = entity; + + this.body = body; + this.head = head; + this.leftForeLeg = leftForeLeg; + this.rightForeLeg = rightForeLeg; + this.leftHindLeg = leftHindLeg; + this.rightHindLeg = rightHindLeg; + + this.scale = scale; + } + + @Override + public void render(ShapeRenderHelper renderer) { + evaluateAngles(); + accountForVelocity(); + + renderer.pushTransform().scale(scale).rotateZ(bodyYaw); + body.render(renderer, this); + + head.render(renderer, this); + + leftForeLeg.render(renderer, this); + rightForeLeg.render(renderer, this); + leftHindLeg.render(renderer, this); + rightHindLeg.render(renderer, this); + renderer.popTransform(); + } + + private void evaluateAngles() { + float globalYaw = normalizeAngle(entity.getYaw()); + + if (Float.isNaN(bodyYaw)) { + bodyYaw = globalYaw; + headYaw = 0; + } else { + headYaw = normalizeAngle(globalYaw - bodyYaw); + + if (headYaw > +head.maxYaw) { + bodyYaw += headYaw - +head.maxYaw; + headYaw = +head.maxYaw; + } else if (headYaw < -head.maxYaw) { + bodyYaw += headYaw - -head.maxYaw; + headYaw = -head.maxYaw; + } + } + + bodyYaw = normalizeAngle(bodyYaw); + + headPitch = Glm.clamp( + entity.getPitch(), + -head.maxPitch, head.maxPitch + ); + } + + private void accountForVelocity() { + // TODO switch to world time + Vec3 horizontal = Vectors.grab3(); + horizontal.set(entity.getVelocity()); + horizontal.z = 0; + + velocity = (float) (horizontal.length()); + velocityCoeff = -1 / (velocity * 1000 + 1) + 1; + walkingAnimationParameter += velocity * GraphicsInterface.getFrameLength() * 1000; + + bodyYaw += velocityCoeff * normalizeAngle( + (float) (atan2(horizontal.y, horizontal.x) - bodyYaw) + ) * min(1, GraphicsInterface.getFrameLength() * 10); + Vectors.release(horizontal); + } + + private static float normalizeAngle(float x) { + final float half = (float) (PI); + final float full = (float) (2 * PI); + return ((x + half) % full + full) % full - half; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/common/world/ChunkData.java b/src/main/java/ru/windcorp/progressia/common/world/ChunkData.java index f1f2bb8..b67032d 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/ChunkData.java +++ b/src/main/java/ru/windcorp/progressia/common/world/ChunkData.java @@ -20,12 +20,14 @@ package ru.windcorp.progressia.common.world; import static ru.windcorp.progressia.common.world.block.BlockFace.*; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.function.BiConsumer; import java.util.function.Consumer; import com.google.common.collect.Lists; +import glm.vec._3.Vec3; import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.client.world.tile.TileLocation; import ru.windcorp.progressia.common.util.SizeLimitedList; @@ -34,6 +36,7 @@ import ru.windcorp.progressia.common.util.Vectors; import ru.windcorp.progressia.common.world.block.BlockData; import ru.windcorp.progressia.common.world.block.BlockDataRegistry; import ru.windcorp.progressia.common.world.block.BlockFace; +import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.common.world.tile.TileData; import ru.windcorp.progressia.common.world.tile.TileDataRegistry; @@ -55,6 +58,9 @@ public class ChunkData { BLOCK_FACE_COUNT ]; + private final List entities = + Collections.synchronizedList(new ArrayList<>()); + public ChunkData(int x, int y, int z, WorldData world) { this.position.set(x, y, z); this.world = world; @@ -123,6 +129,10 @@ public class ChunkData { } } } + + EntityData javapony = new EntityData("Test", "Javapony"); + javapony.setPosition(new Vec3(8, 12, 16.2f)); + getEntities().add(javapony); } public BlockData getBlock(Vec3i posInChunk) { @@ -216,6 +226,10 @@ public class ChunkData { face.getId(); } + public List getEntities() { + return entities; + } + private static void checkLocalCoordinates(Vec3i posInChunk) { if (!isInBounds(posInChunk)) { throw new IllegalArgumentException( @@ -279,6 +293,10 @@ public class ChunkData { } }); } + + public void forEachEntity(Consumer action) { + getEntities().forEach(action); + } public int getX() { return position.x; diff --git a/src/main/java/ru/windcorp/progressia/common/world/block/BlockFace.java b/src/main/java/ru/windcorp/progressia/common/world/block/BlockFace.java index b9ed2cc..f33f8d7 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/block/BlockFace.java +++ b/src/main/java/ru/windcorp/progressia/common/world/block/BlockFace.java @@ -18,6 +18,7 @@ package ru.windcorp.progressia.common.world.block; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import glm.vec._3.i.Vec3i; @@ -58,6 +59,21 @@ public final class BlockFace extends BlockRelation { b.counterFace = a; } + public static ImmutableMap mapToFaces( + E top, E bottom, + E north, E south, + E east, E west + ) { + return ImmutableMap.builderWithExpectedSize(6) + .put(TOP, top) + .put(BOTTOM, bottom) + .put(NORTH, north) + .put(SOUTH, south) + .put(EAST, east) + .put(WEST, west) + .build(); + } + private static int nextId = 0; private final int id; diff --git a/src/main/java/ru/windcorp/progressia/common/world/entity/EntityData.java b/src/main/java/ru/windcorp/progressia/common/world/entity/EntityData.java new file mode 100644 index 0000000..1748104 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/world/entity/EntityData.java @@ -0,0 +1,62 @@ +package ru.windcorp.progressia.common.world.entity; + +import java.util.UUID; + +import glm.vec._2.Vec2; +import glm.vec._3.Vec3; +import ru.windcorp.progressia.common.util.Namespaced; + +public class EntityData extends Namespaced { + + private final Vec3 position = new Vec3(); + private final Vec3 velocity = new Vec3(); + + private final Vec2 direction = new Vec2(); + + private UUID uuid; + + public EntityData(String namespace, String name) { + super(namespace, name); + } + + public Vec3 getPosition() { + return position; + } + + public void setPosition(Vec3 position) { + this.position.set(position); + } + + public Vec3 getVelocity() { + return velocity; + } + + public void setVelocity(Vec3 velocity) { + this.velocity.set(velocity); + } + + public Vec2 getDirection() { + return direction; + } + + public void setDirection(Vec2 direction) { + this.direction.set(direction.x, direction.y); + } + + public float getYaw() { + return getDirection().x; + } + + public float getPitch() { + return getDirection().y; + } + + public UUID getUUID() { + return uuid; + } + + public void setUUID(UUID uuid) { + this.uuid = uuid; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/common/world/entity/EntityDataRegistry.java b/src/main/java/ru/windcorp/progressia/common/world/entity/EntityDataRegistry.java new file mode 100644 index 0000000..8457541 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/world/entity/EntityDataRegistry.java @@ -0,0 +1,13 @@ +package ru.windcorp.progressia.common.world.entity; + +import ru.windcorp.progressia.common.util.NamespacedRegistry; + +public class EntityDataRegistry extends NamespacedRegistry { + + private static final EntityDataRegistry INSTANCE = new EntityDataRegistry(); + + public static EntityDataRegistry getInstance() { + return INSTANCE; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/server/world/entity/EntityLogic.java b/src/main/java/ru/windcorp/progressia/server/world/entity/EntityLogic.java new file mode 100644 index 0000000..c3c09e6 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/server/world/entity/EntityLogic.java @@ -0,0 +1,11 @@ +package ru.windcorp.progressia.server.world.entity; + +import ru.windcorp.progressia.common.util.Namespaced; + +public class EntityLogic extends Namespaced { + + public EntityLogic(String namespace, String name) { + super(namespace, name); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/server/world/entity/EntityLogicRegistry.java b/src/main/java/ru/windcorp/progressia/server/world/entity/EntityLogicRegistry.java new file mode 100644 index 0000000..21e37f9 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/server/world/entity/EntityLogicRegistry.java @@ -0,0 +1,14 @@ +package ru.windcorp.progressia.server.world.entity; + +import ru.windcorp.progressia.common.util.NamespacedRegistry; + +public class EntityLogicRegistry extends NamespacedRegistry { + + private static final EntityLogicRegistry INSTANCE = + new EntityLogicRegistry(); + + public static EntityLogicRegistry getInstance() { + return INSTANCE; + } + +} diff --git a/src/main/resources/assets/textures/entities/javapony.png b/src/main/resources/assets/textures/entities/javapony.png new file mode 100644 index 0000000000000000000000000000000000000000..59ac59ce0e7f3f3a1a05978eda0dc2d90f1d984a GIT binary patch literal 3347 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 Date: Sat, 5 Sep 2020 23:26:54 +0300 Subject: [PATCH 5/6] Added face culling state stack and disabled face culling for entities --- .../client/TestEntityRenderJavapony.java | 66 ++++++++++++------- .../client/graphics/backend/FaceCulling.java | 27 ++++++++ .../graphics/backend/GraphicsBackend.java | 14 ++++ .../graphics/backend/LWJGLInitializer.java | 1 - .../graphics/flat/AssembledFlatLayer.java | 5 ++ .../graphics/flat/FlatRenderProgram.java | 4 -- .../client/graphics/model/Shapes.java | 28 +++++--- .../client/graphics/world/LayerWorld.java | 3 + .../progressia/client/world/ChunkRender.java | 6 -- .../progressia/client/world/WorldRender.java | 17 +++++ .../client/world/entity/QuadripedModel.java | 24 +++++-- 11 files changed, 146 insertions(+), 49 deletions(-) create mode 100644 src/main/java/ru/windcorp/progressia/client/graphics/backend/FaceCulling.java diff --git a/src/main/java/ru/windcorp/progressia/client/TestEntityRenderJavapony.java b/src/main/java/ru/windcorp/progressia/client/TestEntityRenderJavapony.java index 14ccabf..1dbf6ec 100644 --- a/src/main/java/ru/windcorp/progressia/client/TestEntityRenderJavapony.java +++ b/src/main/java/ru/windcorp/progressia/client/TestEntityRenderJavapony.java @@ -26,8 +26,10 @@ public class TestEntityRenderJavapony extends EntityRender { private final Renderable body; private final Renderable head; - private final Renderable foreLeg; - private final Renderable hindLeg; + private final Renderable leftForeLeg; + private final Renderable leftHindLeg; + private final Renderable rightForeLeg; + private final Renderable rightHindLeg; public TestEntityRenderJavapony() { super("Test", "Javapony"); @@ -39,8 +41,10 @@ public class TestEntityRenderJavapony extends EntityRender { this.body = createBody(texture); this.head = createHead(texture); - this.foreLeg = createForeLeg(texture); - this.hindLeg = createHindLeg(texture); + this.leftForeLeg = createLeg(texture, 160, 0, true); + this.rightForeLeg = createLeg(texture, 160, 0, false); + this.leftHindLeg = createLeg(texture, 0, 0, true); + this.rightHindLeg = createLeg(texture, 0, 0, false); } private static Renderable createBody(ComplexTexture texture) { @@ -75,7 +79,7 @@ public class TestEntityRenderJavapony extends EntityRender { ) ) .setOrigin(0, -8, 8) - .setWidth(16).setDepth(16).setHeight(4, 0, 16) + .setWidth(16).setDepth(16).setHeight(2, 0, 16) .create() ); @@ -243,7 +247,7 @@ public class TestEntityRenderJavapony extends EntityRender { // Left ear b.addPart(new PppBuilder( program, texture.getCuboidTextures(48, 128-80, 8) - ).setOrigin(-16 + 3, 16 - 8, 32).setSize(8).create()); + ).setOrigin(-16 + 3, +16, 32).setSize(8, -8, 8).flip().create()); // Muzzle b.addPart(new PppBuilder( @@ -255,7 +259,7 @@ public class TestEntityRenderJavapony extends EntityRender { texture.get(32, 64, 0, 0), texture.get(32, 64, 0, 0) ) - ).setOrigin(16, -8, 0).setSize(16, 4, 8).create()); + ).setOrigin(16, -8, 0).setSize(4, 16, 8).create()); // Nose b.addPart(new PppBuilder( @@ -267,23 +271,26 @@ public class TestEntityRenderJavapony extends EntityRender { texture.get(32, 64, 0, 0), texture.get(32, 64, 0, 0) ) - ).setOrigin(16, -4, 8).setSize(8, 4, 4).create()); + ).setOrigin(16, -4, 8).setSize(4, 8, 4).create()); return new StaticModel(b); } - - private static Renderable createForeLeg(ComplexTexture texture) { - return new PppBuilder( + + private static Renderable createLeg( + ComplexTexture texture, + int textureX, int textureY, + boolean isLeft + ) { + PppBuilder b = new PppBuilder( WorldRenderProgram.getDefault(), - texture.getCuboidTextures(160, 0, 16, 48, 16) - ).setOrigin(-8, -8, -48).setSize(16, 16, 48).create(); - } - - private static Renderable createHindLeg(ComplexTexture texture) { - return new PppBuilder( - WorldRenderProgram.getDefault(), - texture.getCuboidTextures(0, 0, 16, 48, 16) - ).setOrigin(-8, -8, -48).setSize(16, 16, 48).create(); + texture.getCuboidTextures(textureX, textureY, 16, 48, 16) + ) + .setOrigin(-8, isLeft ? +8 : -8, -48) + .setSize(16, isLeft ? -16 : +16, 48); + + if (isLeft) b.flip(); + + return b.create(); } private static Renderable createTail(ComplexTexture texture) { @@ -312,12 +319,21 @@ public class TestEntityRenderJavapony extends EntityRender { new QuadripedModel.Body(body), new QuadripedModel.Head( - head, new Vec3(16, 0, 20), 60, 45 + head, new Vec3(12, 0, 20), 60, 45 ), - new QuadripedModel.Leg(foreLeg, new Vec3( 6, +8.1f, -16), 0.0f), - new QuadripedModel.Leg(foreLeg, new Vec3( 6, -8.1f, -16), 2.5f), - new QuadripedModel.Leg(hindLeg, new Vec3(-36, +8.2f, -16), 2.5f), - new QuadripedModel.Leg(hindLeg, new Vec3(-36, -8.2f, -16), 0.0f), + new QuadripedModel.Leg( + leftForeLeg, new Vec3( 6, +8.1f, -16), 0.0f + ), + new QuadripedModel.Leg( + rightForeLeg, new Vec3( 6, -8.1f, -16), 2.5f + ), + new QuadripedModel.Leg( + leftHindLeg, new Vec3(-36, +8.2f, -16), 2.5f + ), + new QuadripedModel.Leg( + rightHindLeg, new Vec3(-36, -8.2f, -16), 0.0f + ), + 1 / 96f ); } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/FaceCulling.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/FaceCulling.java new file mode 100644 index 0000000..f289876 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/FaceCulling.java @@ -0,0 +1,27 @@ +package ru.windcorp.progressia.client.graphics.backend; + +import java.util.ArrayDeque; +import java.util.Deque; + +public class FaceCulling { + + private static final Deque STACK = new ArrayDeque<>(); + + public static void push(boolean useFaceCulling) { + GraphicsBackend.setFaceCulling(useFaceCulling); + STACK.push(Boolean.valueOf(useFaceCulling)); + } + + public static void pop() { + STACK.pop(); + + if (STACK.isEmpty()) { + GraphicsBackend.setFaceCulling(false); + } else { + GraphicsBackend.setFaceCulling(STACK.getFirst()); + } + } + + private FaceCulling() {} + +} diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/GraphicsBackend.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/GraphicsBackend.java index ba19d31..cc1df99 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/GraphicsBackend.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/GraphicsBackend.java @@ -35,6 +35,8 @@ public class GraphicsBackend { private static long framesRendered = 0; private static double frameStart = Double.NaN; + private static boolean faceCullingEnabled = false; + private GraphicsBackend() {} public static void initialize() { @@ -109,5 +111,17 @@ public class GraphicsBackend { public static void startNextLayer() { glClear(GL_DEPTH_BUFFER_BIT); } + + public static void setFaceCulling(boolean useFaceCulling) { + if (useFaceCulling == faceCullingEnabled) return; + + if (useFaceCulling) { + glEnable(GL_CULL_FACE); + } else { + glDisable(GL_CULL_FACE); + } + + faceCullingEnabled = useFaceCulling; + } } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/LWJGLInitializer.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/LWJGLInitializer.java index ea14292..17e36f6 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/LWJGLInitializer.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/LWJGLInitializer.java @@ -81,7 +81,6 @@ class LWJGLInitializer { private static void initializeOpenGL() { GL.createCapabilities(); glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/flat/AssembledFlatLayer.java b/src/main/java/ru/windcorp/progressia/client/graphics/flat/AssembledFlatLayer.java index 0980e01..f53aab0 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/flat/AssembledFlatLayer.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/flat/AssembledFlatLayer.java @@ -18,6 +18,7 @@ package ru.windcorp.progressia.client.graphics.flat; import ru.windcorp.progressia.client.graphics.Layer; +import ru.windcorp.progressia.client.graphics.backend.FaceCulling; public abstract class AssembledFlatLayer extends Layer { @@ -48,11 +49,15 @@ public abstract class AssembledFlatLayer extends Layer { @Override protected void doRender() { + FaceCulling.push(false); + for (RenderTarget.Clip clip : clips) { clip.render(helper); } helper.reset(); + + FaceCulling.pop(); } } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatRenderProgram.java b/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatRenderProgram.java index 9828518..846013f 100755 --- a/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatRenderProgram.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatRenderProgram.java @@ -17,8 +17,6 @@ *******************************************************************************/ package ru.windcorp.progressia.client.graphics.flat; -import static org.lwjgl.opengl.GL11.*; - import java.nio.FloatBuffer; import com.google.common.collect.ObjectArrays; @@ -81,9 +79,7 @@ public class FlatRenderProgram extends ShapeRenderProgram { @Override public void render(ShapeRenderHelper helper, Shape shape) { - glDisable(GL_CULL_FACE); super.render(helper, shape); - glEnable(GL_CULL_FACE); } @Override diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/Shapes.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/Shapes.java index 90624ec..224ff11 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/model/Shapes.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/Shapes.java @@ -43,7 +43,9 @@ public class Shapes { Texture northTexture, Texture southTexture, Texture eastTexture, - Texture westTexture + Texture westTexture, + + boolean flip ) { Vec3 faceOrigin = Vectors.grab3(); @@ -55,7 +57,7 @@ public class Shapes { faceOrigin.set(origin).add(height).add(width), faceWidth.set(width).negate(), depth, - false + flip ); Face bottom = Faces.createRectangle( @@ -64,7 +66,7 @@ public class Shapes { origin, width, depth, - false + flip ); Face north = Faces.createRectangle( @@ -73,7 +75,7 @@ public class Shapes { faceOrigin.set(origin).add(depth), width, height, - false + flip ); Face south = Faces.createRectangle( @@ -82,7 +84,7 @@ public class Shapes { faceOrigin.set(origin).add(width), faceWidth.set(width).negate(), height, - false + flip ); Face east = Faces.createRectangle( @@ -91,7 +93,7 @@ public class Shapes { origin, depth, height, - false + flip ); Face west = Faces.createRectangle( @@ -100,7 +102,7 @@ public class Shapes { faceOrigin.set(origin).add(width).add(depth), faceWidth.set(depth).negate(), height, - false + flip ); Shape result = new Shape( @@ -134,6 +136,8 @@ public class Shapes { private final Texture eastTexture; private final Texture westTexture; + private boolean flip = false; + public PppBuilder( ShapeRenderProgram program, Texture top, @@ -237,13 +241,18 @@ public class Shapes { } public PppBuilder setSize(float x, float y, float z) { - return this.setWidth(x).setDepth(y).setHeight(z); + return this.setDepth(x).setWidth(y).setHeight(z); } public PppBuilder setSize(float size) { return this.setSize(size, size, size); } + public PppBuilder flip() { + this.flip = true; + return this; + } + public Shape create() { return createParallelepiped( program, @@ -255,7 +264,8 @@ public class Shapes { northTexture, southTexture, eastTexture, - westTexture + westTexture, + flip ); } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java index 30e4c4f..6aa5a87 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java @@ -24,6 +24,7 @@ import glm.vec._3.Vec3; import ru.windcorp.progressia.client.Client; import ru.windcorp.progressia.client.comms.controls.InputBasedControls; import ru.windcorp.progressia.client.graphics.Layer; +import ru.windcorp.progressia.client.graphics.backend.FaceCulling; import ru.windcorp.progressia.client.graphics.backend.GraphicsBackend; import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface; import ru.windcorp.progressia.client.graphics.input.CursorMoveEvent; @@ -102,7 +103,9 @@ public class LayerWorld extends Layer { } private void renderWorld() { + FaceCulling.push(true); this.client.getWorld().render(helper); + FaceCulling.pop(); } @Override diff --git a/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java b/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java index badcfb7..3bead82 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java +++ b/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java @@ -92,12 +92,6 @@ public class ChunkRender { model.render(renderer); renderer.popTransform(); - - getData().forEachEntity(entityData -> { - renderer.pushTransform().translate(entityData.getPosition()); - getWorld().getEntityRenderable(entityData).render(renderer); - renderer.popTransform(); - }); } private void buildModel() { diff --git a/src/main/java/ru/windcorp/progressia/client/world/WorldRender.java b/src/main/java/ru/windcorp/progressia/client/world/WorldRender.java index 68b5e22..26dd653 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/WorldRender.java +++ b/src/main/java/ru/windcorp/progressia/client/world/WorldRender.java @@ -24,6 +24,7 @@ import java.util.Map; import java.util.WeakHashMap; import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.client.graphics.backend.FaceCulling; import ru.windcorp.progressia.client.graphics.model.Renderable; import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper; import ru.windcorp.progressia.client.world.entity.EntityRenderRegistry; @@ -67,8 +68,24 @@ public class WorldRender { for (ChunkRender chunk : getChunks()) { chunk.render(renderer); } + + renderEntities(renderer); } + private void renderEntities(ShapeRenderHelper renderer) { + FaceCulling.push(false); + + for (ChunkRender chunk : getChunks()) { + chunk.getData().forEachEntity(entity -> { + renderer.pushTransform().translate(entity.getPosition()); + getEntityRenderable(entity).render(renderer); + renderer.popTransform(); + }); + } + + FaceCulling.pop(); + } + public Renderable getEntityRenderable(EntityData entity) { return entityModels.computeIfAbsent( entity, diff --git a/src/main/java/ru/windcorp/progressia/client/world/entity/QuadripedModel.java b/src/main/java/ru/windcorp/progressia/client/world/entity/QuadripedModel.java index 14e01e9..5b55665 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/entity/QuadripedModel.java +++ b/src/main/java/ru/windcorp/progressia/client/world/entity/QuadripedModel.java @@ -99,6 +99,11 @@ public class QuadripedModel implements Renderable { private float velocityCoeff = 0; private float velocity = 0; + /** + * Controls how quickly velocityCoeff approaches 1 + */ + private float velocityCutoff = 10; + private float walkingFrequency = 0.15f; private float walkingSwing = (float) toRadians(30); @@ -129,8 +134,8 @@ public class QuadripedModel implements Renderable { @Override public void render(ShapeRenderHelper renderer) { - evaluateAngles(); accountForVelocity(); + evaluateAngles(); renderer.pushTransform().scale(scale).rotateZ(bodyYaw); body.render(renderer, this); @@ -171,13 +176,15 @@ public class QuadripedModel implements Renderable { } private void accountForVelocity() { - // TODO switch to world time Vec3 horizontal = Vectors.grab3(); horizontal.set(entity.getVelocity()); horizontal.z = 0; - velocity = (float) (horizontal.length()); - velocityCoeff = -1 / (velocity * 1000 + 1) + 1; + velocity = horizontal.length(); + + evaluateVelocityCoeff(); + + // TODO switch to world time walkingAnimationParameter += velocity * GraphicsInterface.getFrameLength() * 1000; bodyYaw += velocityCoeff * normalizeAngle( @@ -186,6 +193,15 @@ public class QuadripedModel implements Renderable { Vectors.release(horizontal); } + private void evaluateVelocityCoeff() { + if (velocity * velocityCutoff > 1) { + velocityCoeff = 1; + } else { + velocityCoeff = velocity * velocityCutoff; + velocityCoeff *= velocityCoeff; + } + } + private static float normalizeAngle(float x) { final float half = (float) (PI); final float full = (float) (2 * PI); From ccc9d8f3a7d4c7fb39a252793dad3745832ffbb1 Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Mon, 7 Sep 2020 10:16:52 +0300 Subject: [PATCH 6/6] Refactored Camera to use anchors - Camera now uses anchor objects to obtain position and direction - Replaceable at runtime - Anchor supplies info about camera modes (switch with F5) - Only Entity anchor implemented ATM - Added PacketSetLocalPlayer - EntityRenders now produce EntityRenderable - Holds reference to EntityData - Has getViewPoint() to use with camera anchors - Added Matrices (like Vectors) - Added FloatMathUtils for all those pesky math functions that are only implemented for double. Curse you double! --- .../ru/windcorp/progressia/client/Client.java | 7 +- .../progressia/client/ClientState.java | 12 +- .../client/TestEntityRenderJavapony.java | 5 +- .../comms/DefaultClientCommsListener.java | 38 ++++ .../localhost/LocalServerCommsChannel.java | 7 +- .../client/graphics/flat/LayerTestUI.java | 15 +- .../client/graphics/world/Camera.java | 170 ++++++++++++------ .../client/graphics/world/EntityAnchor.java | 67 +++++++ .../client/graphics/world/LayerWorld.java | 61 +++++-- .../progressia/client/world/WorldRender.java | 8 +- .../client/world/entity/EntityRender.java | 3 +- .../client/world/entity/EntityRenderable.java | 23 +++ .../client/world/entity/QuadripedModel.java | 63 +++++-- .../comms/packets/PacketSetLocalPlayer.java | 18 ++ .../common/util/FloatMathUtils.java | 19 ++ .../progressia/common/util/Matrices.java | 65 +++++++ .../progressia/common/util/Vectors.java | 2 + .../progressia/common/world/ChunkData.java | 8 +- .../server/comms/ClientManager.java | 7 + 19 files changed, 484 insertions(+), 114 deletions(-) create mode 100644 src/main/java/ru/windcorp/progressia/client/graphics/world/EntityAnchor.java create mode 100644 src/main/java/ru/windcorp/progressia/client/world/entity/EntityRenderable.java create mode 100644 src/main/java/ru/windcorp/progressia/common/comms/packets/PacketSetLocalPlayer.java create mode 100644 src/main/java/ru/windcorp/progressia/common/util/FloatMathUtils.java create mode 100644 src/main/java/ru/windcorp/progressia/common/util/Matrices.java diff --git a/src/main/java/ru/windcorp/progressia/client/Client.java b/src/main/java/ru/windcorp/progressia/client/Client.java index 5115cc5..de6fa54 100644 --- a/src/main/java/ru/windcorp/progressia/client/Client.java +++ b/src/main/java/ru/windcorp/progressia/client/Client.java @@ -1,6 +1,5 @@ package ru.windcorp.progressia.client; -import glm.vec._3.Vec3; import ru.windcorp.progressia.client.comms.DefaultClientCommsListener; import ru.windcorp.progressia.client.comms.ServerCommsChannel; import ru.windcorp.progressia.client.graphics.world.Camera; @@ -13,11 +12,7 @@ public class Client { private final WorldRender world; private EntityData localPlayer; - private final Camera camera = new Camera( - new Vec3(-6, -6, 20), - (float) Math.toRadians(-40), (float) Math.toRadians(-45), - (float) Math.toRadians(70) - ); + private final Camera camera = new Camera((float) Math.toRadians(70)); private final ServerCommsChannel comms; diff --git a/src/main/java/ru/windcorp/progressia/client/ClientState.java b/src/main/java/ru/windcorp/progressia/client/ClientState.java index eab5cfc..84c26a2 100644 --- a/src/main/java/ru/windcorp/progressia/client/ClientState.java +++ b/src/main/java/ru/windcorp/progressia/client/ClientState.java @@ -1,6 +1,5 @@ package ru.windcorp.progressia.client; -import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.client.comms.localhost.LocalServerCommsChannel; import ru.windcorp.progressia.client.graphics.GUI; import ru.windcorp.progressia.client.graphics.flat.LayerTestUI; @@ -24,14 +23,15 @@ public class ClientState { public static void connectToLocalServer() { WorldData world = new WorldData(); - Client client = new Client(world, new LocalServerCommsChannel( - ServerState.getInstance() - )); - client.setLocalPlayer( - world.getChunk(new Vec3i(0, 0, 0)).getEntities().get(0) + LocalServerCommsChannel channel = new LocalServerCommsChannel( + ServerState.getInstance() ); + Client client = new Client(world, channel); + + channel.connect(); + setInstance(client); GUI.addBottomLayer(new LayerWorld(client)); diff --git a/src/main/java/ru/windcorp/progressia/client/TestEntityRenderJavapony.java b/src/main/java/ru/windcorp/progressia/client/TestEntityRenderJavapony.java index 1dbf6ec..b1e8a92 100644 --- a/src/main/java/ru/windcorp/progressia/client/TestEntityRenderJavapony.java +++ b/src/main/java/ru/windcorp/progressia/client/TestEntityRenderJavapony.java @@ -18,6 +18,7 @@ import ru.windcorp.progressia.client.graphics.texture.Texture; import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram; import ru.windcorp.progressia.client.world.entity.EntityRender; import ru.windcorp.progressia.client.world.entity.EntityRenderRegistry; +import ru.windcorp.progressia.client.world.entity.EntityRenderable; import ru.windcorp.progressia.client.world.entity.QuadripedModel; import ru.windcorp.progressia.common.world.block.BlockFace; import ru.windcorp.progressia.common.world.entity.EntityData; @@ -313,13 +314,13 @@ public class TestEntityRenderJavapony extends EntityRender { } @Override - public Renderable createRenderable(EntityData entity) { + public EntityRenderable createRenderable(EntityData entity) { return new QuadripedModel( entity, new QuadripedModel.Body(body), new QuadripedModel.Head( - head, new Vec3(12, 0, 20), 60, 45 + head, new Vec3(12, 0, 20), 60, 45, new Vec3(16, 0, 20) ), new QuadripedModel.Leg( leftForeLeg, new Vec3( 6, +8.1f, -16), 0.0f diff --git a/src/main/java/ru/windcorp/progressia/client/comms/DefaultClientCommsListener.java b/src/main/java/ru/windcorp/progressia/client/comms/DefaultClientCommsListener.java index 134bfb1..299c50a 100644 --- a/src/main/java/ru/windcorp/progressia/client/comms/DefaultClientCommsListener.java +++ b/src/main/java/ru/windcorp/progressia/client/comms/DefaultClientCommsListener.java @@ -1,12 +1,18 @@ package ru.windcorp.progressia.client.comms; import java.io.IOException; +import java.util.Collection; +import java.util.UUID; import ru.windcorp.progressia.client.Client; +import ru.windcorp.progressia.client.graphics.world.EntityAnchor; import ru.windcorp.progressia.client.world.ChunkRender; import ru.windcorp.progressia.common.comms.CommsListener; import ru.windcorp.progressia.common.comms.packets.Packet; +import ru.windcorp.progressia.common.comms.packets.PacketSetLocalPlayer; import ru.windcorp.progressia.common.comms.packets.PacketWorldChange; +import ru.windcorp.progressia.common.world.ChunkData; +import ru.windcorp.progressia.common.world.entity.EntityData; public class DefaultClientCommsListener implements CommsListener { @@ -24,9 +30,41 @@ public class DefaultClientCommsListener implements CommsListener { ); tmp_reassembleWorld(); + } else if (packet instanceof PacketSetLocalPlayer) { + setLocalPlayer((PacketSetLocalPlayer) packet); } } + private void setLocalPlayer(PacketSetLocalPlayer packet) { + UUID uuid = packet.getLocalPlayerEntityUUID(); + + Collection chunks = + getClient().getWorld().getData().getChunks(); + + EntityData entity = null; + + synchronized (chunks) { + chunkLoop: + for (ChunkData chunk : chunks) { + for (EntityData anEntity : chunk.getEntities()) { + if (anEntity.getUUID().equals(uuid)) { + entity = anEntity; + break chunkLoop; + } + } + } + } + + if (entity == null) { + throw new RuntimeException(""); + } + + getClient().setLocalPlayer(entity); + getClient().getCamera().setAnchor(new EntityAnchor( + getClient().getWorld().getEntityRenderable(entity) + )); + } + private void tmp_reassembleWorld() { getClient().getWorld().getChunks().forEach(ChunkRender::markForUpdate); } diff --git a/src/main/java/ru/windcorp/progressia/client/comms/localhost/LocalServerCommsChannel.java b/src/main/java/ru/windcorp/progressia/client/comms/localhost/LocalServerCommsChannel.java index 478f6f4..8c7b6d7 100644 --- a/src/main/java/ru/windcorp/progressia/client/comms/localhost/LocalServerCommsChannel.java +++ b/src/main/java/ru/windcorp/progressia/client/comms/localhost/LocalServerCommsChannel.java @@ -6,10 +6,15 @@ import ru.windcorp.progressia.server.Server; public class LocalServerCommsChannel extends ServerCommsChannel { - private final LocalClient localClient; + private LocalClient localClient; + private final Server server; public LocalServerCommsChannel(Server server) { super(Role.GAME, Role.CHAT); + this.server = server; + } + + public void connect() { setState(State.CONNECTED); this.localClient = new LocalClient( diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/flat/LayerTestUI.java b/src/main/java/ru/windcorp/progressia/client/graphics/flat/LayerTestUI.java index cf2cb90..f5da33e 100755 --- a/src/main/java/ru/windcorp/progressia/client/graphics/flat/LayerTestUI.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/flat/LayerTestUI.java @@ -30,6 +30,7 @@ import ru.windcorp.progressia.client.graphics.input.bus.Input; import ru.windcorp.progressia.client.graphics.model.LambdaModel; import ru.windcorp.progressia.client.graphics.texture.SimpleTextures; import ru.windcorp.progressia.client.graphics.texture.Texture; +import ru.windcorp.progressia.client.graphics.world.Camera; public class LayerTestUI extends AssembledFlatLayer { @@ -73,7 +74,10 @@ public class LayerTestUI extends AssembledFlatLayer { target.addCustomRenderer(new LambdaModel(LambdaModel.lambdaBuilder() .addDynamicPart( target.createRectagle(0, 0, texSize, texSize, 0xFFFFFF, compassFg), - mat -> mat.translate(texSize/2, texSize/2, 0).rotateZ(ClientState.getInstance().getCamera().getYaw()).translate(-texSize/2, -texSize/2, 0) + mat -> + mat.translate(texSize/2, texSize/2, 0) + .rotateZ(getCompassRotation()) + .translate(-texSize/2, -texSize/2, 0) ) )); target.popTransform(); @@ -81,6 +85,15 @@ public class LayerTestUI extends AssembledFlatLayer { drawCross(target); } + private double getCompassRotation() { + Camera.Anchor anchor = + ClientState.getInstance().getCamera().getAnchor(); + + if (anchor == null) return 0; + + return -anchor.getCameraYaw(); + } + private void drawCross(RenderTarget target) { int cx = getWidth() / 2; int cy = getHeight() / 2; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/Camera.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/Camera.java index 23af1e4..7e8a59d 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/world/Camera.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/Camera.java @@ -19,26 +19,62 @@ package ru.windcorp.progressia.client.graphics.world; import static java.lang.Math.*; +import java.util.Collection; +import java.util.function.Consumer; + import glm.Glm; import glm.mat._4.Mat4; import glm.vec._3.Vec3; import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface; +import ru.windcorp.progressia.client.graphics.world.Camera.Anchor.Mode; +import ru.windcorp.progressia.common.util.Vectors; public class Camera { - private final Vec3 position = new Vec3(); + public static interface Anchor { + + /** + * Offset is applied after the rotation. + */ + public static interface Mode { + void getCameraOffset(Vec3 output); + void applyCameraRotation(Mat4 output); + + public static Mode of( + Consumer offsetGetter, + Consumer rotator + ) { + return new Mode() { + @Override + public void getCameraOffset(Vec3 output) { + offsetGetter.accept(output); + } + + @Override + public void applyCameraRotation(Mat4 output) { + rotator.accept(output); + } + }; + } + } + + void getCameraPosition(Vec3 output); + void getCameraVelocity(Vec3 output); + float getCameraYaw(); + float getCameraPitch(); + + Collection getCameraModes(); + + } - private float pitch; - private float yaw; + private Anchor anchor; + + private Anchor.Mode[] modes; + private int currentModeIndex; private float fieldOfView; - public boolean tmp_mode = false; - - public Camera(Vec3 position, float pitch, float yaw, float fieldOfView) { - teleport(position); - setPitch(pitch); - setYaw(yaw); + public Camera(float fieldOfView) { setFieldOfView(fieldOfView); } @@ -48,10 +84,7 @@ public class Camera { applyPerspective(helper); rotateCoordinateSystem(helper); - // TODO debug - helper.pushViewTransform().translate(3.5f, 0, -0.5f); - if (tmp_mode) helper.pushViewTransform().rotateZ(PI); - + applyMode(helper); applyDirection(helper); applyPosition(helper); } @@ -70,14 +103,38 @@ public class Camera { private void rotateCoordinateSystem(WorldRenderHelper helper) { helper.pushViewTransform().rotateX(-PI / 2).rotateZ(PI / 2); } + + private void applyMode(WorldRenderHelper helper) { + Mode mode = getMode(); + + Mat4 matrix = helper.pushViewTransform(); + + Vec3 offset = Vectors.grab3(); + mode.getCameraOffset(offset); + + offset.negate(); + matrix.translate(offset); + + Vectors.release(offset); + + mode.applyCameraRotation(matrix); + } private void applyDirection(WorldRenderHelper helper) { - helper.pushViewTransform().rotateY(pitch).rotateZ(yaw); + helper.pushViewTransform() + .rotateY(-anchor.getCameraPitch()) + .rotateZ(-anchor.getCameraYaw()); } private void applyPosition(WorldRenderHelper helper) { - helper.pushViewTransform().translate(position.negate()); - position.negate(); + Vec3 v = Vectors.grab3(); + + anchor.getCameraPosition(v); + v.negate(); + + helper.pushViewTransform().translate(v); + + Vectors.release(v); } private float computeFovY() { @@ -93,45 +150,6 @@ public class Camera { )); } } - - public Vec3 getPosition() { - return position; - } - - public void teleport(Vec3 pos) { - position.set(pos); - } - - public void move(Vec3 pos) { - position.add(pos); - } - - public float getPitch() { - return pitch; - } - - public void setPitch(float pitch) { - final float maxPitch = (float) (Math.PI / 2); - this.pitch = Glm.clamp(pitch, -maxPitch, +maxPitch); - } - - public float getYaw() { - return yaw; - } - - public void setYaw(float yaw) { - this.yaw = Glm.mod(yaw, 2 * (float) PI); - } - - public void setDirection(float pitch, float yaw) { - setPitch(pitch); - setYaw(yaw); - } - - public void turn(float pitchChange, float yawChange) { - setPitch(getPitch() + pitchChange); - setYaw(getYaw() + yawChange); - } public float getFieldOfView() { return fieldOfView; @@ -140,5 +158,47 @@ public class Camera { public void setFieldOfView(float fieldOfView) { this.fieldOfView = fieldOfView; } + + public Anchor getAnchor() { + return anchor; + } + + public boolean hasAnchor() { + return anchor != null; + } + + public void setAnchor(Anchor anchor) { + if (anchor == null) { + this.anchor = null; + this.modes = null; + return; + } + + Collection modesCollection = anchor.getCameraModes(); + + if (modesCollection.isEmpty()) { + throw new IllegalArgumentException( + "Anchor " + anchor + " returned no camera modes," + + " at least one required" + ); + } + + this.anchor = anchor; + + this.modes = modesCollection.toArray(new Mode[modesCollection.size()]); + this.currentModeIndex = 0; + } + + public Anchor.Mode getMode() { + return modes[currentModeIndex]; + } + + public void selectNextMode() { + if (currentModeIndex == modes.length - 1) { + currentModeIndex = 0; + } else { + currentModeIndex++; + } + } } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/EntityAnchor.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/EntityAnchor.java new file mode 100644 index 0000000..86f859f --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/EntityAnchor.java @@ -0,0 +1,67 @@ +package ru.windcorp.progressia.client.graphics.world; + +import java.util.Collection; + +import com.google.common.collect.ImmutableList; + +import glm.vec._3.Vec3; +import ru.windcorp.progressia.client.graphics.world.Camera.Anchor; +import ru.windcorp.progressia.client.world.entity.EntityRenderable; +import ru.windcorp.progressia.common.world.entity.EntityData; + +public class EntityAnchor implements Anchor { + + private final EntityData entity; + private final EntityRenderable model; + + private final Collection modes; + + public EntityAnchor(EntityRenderable model) { + this.entity = model.getData(); + this.model = model; + + this.modes = ImmutableList.of( + // From viewpoint / first person + Mode.of(v -> v.set(0), m -> {}), + + // Third person, looking forward + Mode.of( + v -> v.set(-3.5f, +0.5f, 0), + m -> {} + ), + + // Third person, looking back + Mode.of( + v -> v.set(-3.5f, 0, 0), + m -> m.rotateZ((float) Math.PI) + ) + ); + } + + @Override + public void getCameraPosition(Vec3 output) { + model.getViewPoint(output); + output.add(entity.getPosition()); + } + + @Override + public void getCameraVelocity(Vec3 output) { + output.set(entity.getVelocity()); + } + + @Override + public float getCameraYaw() { + return entity.getYaw(); + } + + @Override + public float getCameraPitch() { + return entity.getPitch(); + } + + @Override + public Collection getCameraModes() { + return modes; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java index 6aa5a87..2cc11b0 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java @@ -19,7 +19,9 @@ package ru.windcorp.progressia.client.graphics.world; import org.lwjgl.glfw.GLFW; +import glm.Glm; import glm.mat._3.Mat3; +import glm.vec._2.Vec2; import glm.vec._3.Vec3; import ru.windcorp.progressia.client.Client; import ru.windcorp.progressia.client.comms.controls.InputBasedControls; @@ -31,7 +33,9 @@ import ru.windcorp.progressia.client.graphics.input.CursorMoveEvent; import ru.windcorp.progressia.client.graphics.input.InputEvent; import ru.windcorp.progressia.client.graphics.input.KeyEvent; import ru.windcorp.progressia.client.graphics.input.bus.Input; +import ru.windcorp.progressia.common.util.FloatMathUtils; import ru.windcorp.progressia.common.util.Vectors; +import ru.windcorp.progressia.common.world.entity.EntityData; public class LayerWorld extends Layer { @@ -67,19 +71,20 @@ public class LayerWorld extends Layer { @Override protected void doRender() { - client.getLocalPlayer().setPosition(client.getCamera().getPosition()); - client.getLocalPlayer().setVelocity(velocity); - client.getLocalPlayer().getDirection().set( - -client.getCamera().getYaw(), - -client.getCamera().getPitch() - ); + if (client.getLocalPlayer() != null) { + tmp_handleControls(); + } - client.getCamera().apply(helper); + Camera camera = client.getCamera(); + if (camera.hasAnchor()) { + renderWorld(); + } + } + + private void tmp_handleControls() { + EntityData player = client.getLocalPlayer(); - renderWorld(); - helper.reset(); - - angMat.set().rotateZ(-client.getCamera().getYaw()); + angMat.set().rotateZ(player.getYaw()); Vec3 movement = Vectors.grab3(); @@ -97,15 +102,21 @@ public class LayerWorld extends Layer { Vec3 velCopy = Vectors.grab3().set(velocity); velCopy.mul((float) (GraphicsInterface.getFrameLength() * 60)); - client.getCamera().move(velCopy); + + player.getPosition().add(velCopy); + player.getVelocity().set(velocity); Vectors.release(velCopy); } private void renderWorld() { + client.getCamera().apply(helper); FaceCulling.push(true); + this.client.getWorld().render(helper); + FaceCulling.pop(); + helper.reset(); } @Override @@ -170,7 +181,9 @@ public class LayerWorld extends Layer { case GLFW.GLFW_KEY_F5: if (!event.isPress()) return false; - client.getCamera().tmp_mode = !client.getCamera().tmp_mode; + if (client.getCamera().hasAnchor()) { + client.getCamera().selectNextMode(); + } break; default: @@ -183,12 +196,26 @@ public class LayerWorld extends Layer { private void onMouseMoved(CursorMoveEvent event) { if (!flag) return; - final float yawScale = 0.002f; + final float yawScale = -0.002f; final float pitchScale = yawScale; + + EntityData player = client.getLocalPlayer(); - client.getCamera().turn( - (float) (event.getChangeY() * pitchScale), - (float) (event.getChangeX() * yawScale) + if (player != null) { + normalizeAngles(player.getDirection().add( + (float) (event.getChangeX() * yawScale), + (float) (event.getChangeY() * pitchScale) + )); + } + } + + private void normalizeAngles(Vec2 dir) { + // Normalize yaw + dir.x = FloatMathUtils.normalizeAngle(dir.x); + + // Clamp pitch + dir.y = Glm.clamp( + dir.y, -FloatMathUtils.PI_F/2, +FloatMathUtils.PI_F/2 ); } diff --git a/src/main/java/ru/windcorp/progressia/client/world/WorldRender.java b/src/main/java/ru/windcorp/progressia/client/world/WorldRender.java index 26dd653..fc219f4 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/WorldRender.java +++ b/src/main/java/ru/windcorp/progressia/client/world/WorldRender.java @@ -25,9 +25,9 @@ import java.util.WeakHashMap; import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.client.graphics.backend.FaceCulling; -import ru.windcorp.progressia.client.graphics.model.Renderable; import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper; import ru.windcorp.progressia.client.world.entity.EntityRenderRegistry; +import ru.windcorp.progressia.client.world.entity.EntityRenderable; import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.entity.EntityData; @@ -37,7 +37,7 @@ public class WorldRender { private final WorldData data; private final Map chunks = new HashMap<>(); - private final Map entityModels = + private final Map entityModels = Collections.synchronizedMap(new WeakHashMap<>()); public WorldRender(WorldData data) { @@ -86,14 +86,14 @@ public class WorldRender { FaceCulling.pop(); } - public Renderable getEntityRenderable(EntityData entity) { + public EntityRenderable getEntityRenderable(EntityData entity) { return entityModels.computeIfAbsent( entity, WorldRender::createEntityRenderable ); } - private static Renderable createEntityRenderable(EntityData entity) { + private static EntityRenderable createEntityRenderable(EntityData entity) { return EntityRenderRegistry.getInstance().get(entity.getId()) .createRenderable(entity); } diff --git a/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRender.java b/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRender.java index 98e1f10..32c9be1 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRender.java +++ b/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRender.java @@ -1,6 +1,5 @@ package ru.windcorp.progressia.client.world.entity; -import ru.windcorp.progressia.client.graphics.model.Renderable; import ru.windcorp.progressia.common.util.Namespaced; import ru.windcorp.progressia.common.world.entity.EntityData; @@ -10,6 +9,6 @@ public abstract class EntityRender extends Namespaced { super(namespace, name); } - public abstract Renderable createRenderable(EntityData entity); + public abstract EntityRenderable createRenderable(EntityData entity); } diff --git a/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRenderable.java b/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRenderable.java new file mode 100644 index 0000000..e7e8466 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRenderable.java @@ -0,0 +1,23 @@ +package ru.windcorp.progressia.client.world.entity; + +import glm.vec._3.Vec3; +import ru.windcorp.progressia.client.graphics.model.Renderable; +import ru.windcorp.progressia.common.world.entity.EntityData; + +public abstract class EntityRenderable implements Renderable { + + private final EntityData data; + + public EntityRenderable(EntityData data) { + this.data = data; + } + + public EntityData getData() { + return data; + } + + public void getViewPoint(Vec3 output) { + output.set(0, 0, 0); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/client/world/entity/QuadripedModel.java b/src/main/java/ru/windcorp/progressia/client/world/entity/QuadripedModel.java index 5b55665..a7bdc97 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/entity/QuadripedModel.java +++ b/src/main/java/ru/windcorp/progressia/client/world/entity/QuadripedModel.java @@ -1,17 +1,20 @@ package ru.windcorp.progressia.client.world.entity; import static java.lang.Math.*; +import static ru.windcorp.progressia.common.util.FloatMathUtils.*; import glm.Glm; import glm.mat._4.Mat4; import glm.vec._3.Vec3; +import glm.vec._4.Vec4; import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface; import ru.windcorp.progressia.client.graphics.model.Renderable; import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper; +import ru.windcorp.progressia.common.util.Matrices; import ru.windcorp.progressia.common.util.Vectors; import ru.windcorp.progressia.common.world.entity.EntityData; -public class QuadripedModel implements Renderable { +public class QuadripedModel extends EntityRenderable { private static abstract class BodyPart { private final Renderable renderable; @@ -20,7 +23,6 @@ public class QuadripedModel implements Renderable { public BodyPart(Renderable renderable, Vec3 joint) { this.renderable = renderable; if (joint != null) { -// joint.negate(this.translation); this.translation.set(joint); } } @@ -37,6 +39,10 @@ public class QuadripedModel implements Renderable { } protected abstract void applyTransform(Mat4 mat, QuadripedModel model); + + public Vec3 getTranslation() { + return translation; + } } public static class Body extends BodyPart { @@ -54,19 +60,27 @@ public class QuadripedModel implements Renderable { private final float maxYaw; private final float maxPitch; + private final Vec3 viewPoint; + public Head( Renderable renderable, Vec3 joint, - double maxYawDegrees, double maxPitchDegrees + double maxYawDegrees, double maxPitchDegrees, + Vec3 viewPoint ) { super(renderable, joint); this.maxYaw = (float) toRadians(maxYawDegrees); this.maxPitch = (float) toRadians(maxPitchDegrees); + this.viewPoint = viewPoint; } @Override protected void applyTransform(Mat4 mat, QuadripedModel model) { mat.rotateZ(model.headYaw).rotateY(model.headPitch); } + + public Vec3 getViewPoint() { + return viewPoint; + } } public static class Leg extends BodyPart { @@ -86,8 +100,6 @@ public class QuadripedModel implements Renderable { } } - private final EntityData entity; - private final Body body; private final Head head; private final Leg leftForeLeg, rightForeLeg; @@ -120,7 +132,7 @@ public class QuadripedModel implements Renderable { float scale ) { - this.entity = entity; + super(entity); this.body = body; this.head = head; @@ -134,23 +146,21 @@ public class QuadripedModel implements Renderable { @Override public void render(ShapeRenderHelper renderer) { - accountForVelocity(); - evaluateAngles(); - renderer.pushTransform().scale(scale).rotateZ(bodyYaw); body.render(renderer, this); - head.render(renderer, this); - leftForeLeg.render(renderer, this); rightForeLeg.render(renderer, this); leftHindLeg.render(renderer, this); rightHindLeg.render(renderer, this); renderer.popTransform(); + + accountForVelocity(); + evaluateAngles(); } private void evaluateAngles() { - float globalYaw = normalizeAngle(entity.getYaw()); + float globalYaw = normalizeAngle(getData().getYaw()); if (Float.isNaN(bodyYaw)) { bodyYaw = globalYaw; @@ -170,14 +180,14 @@ public class QuadripedModel implements Renderable { bodyYaw = normalizeAngle(bodyYaw); headPitch = Glm.clamp( - entity.getPitch(), + getData().getPitch(), -head.maxPitch, head.maxPitch ); } private void accountForVelocity() { Vec3 horizontal = Vectors.grab3(); - horizontal.set(entity.getVelocity()); + horizontal.set(getData().getVelocity()); horizontal.z = 0; velocity = horizontal.length(); @@ -201,11 +211,26 @@ public class QuadripedModel implements Renderable { velocityCoeff *= velocityCoeff; } } - - private static float normalizeAngle(float x) { - final float half = (float) (PI); - final float full = (float) (2 * PI); - return ((x + half) % full + full) % full - half; + + @Override + public void getViewPoint(Vec3 output) { + Mat4 m = Matrices.grab4(); + Vec4 v = Vectors.grab4(); + + m.identity() + .scale(scale) + .rotateZ(bodyYaw) + .translate(head.getTranslation()) + .rotateZ(headYaw) + .rotateY(headPitch); + + v.set(head.getViewPoint(), 1); + m.mul(v); + + output.set(v.x, v.y, v.z); + + Vectors.release(v); + Matrices.release(m); } } diff --git a/src/main/java/ru/windcorp/progressia/common/comms/packets/PacketSetLocalPlayer.java b/src/main/java/ru/windcorp/progressia/common/comms/packets/PacketSetLocalPlayer.java new file mode 100644 index 0000000..f20843a --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/comms/packets/PacketSetLocalPlayer.java @@ -0,0 +1,18 @@ +package ru.windcorp.progressia.common.comms.packets; + +import java.util.UUID; + +public class PacketSetLocalPlayer extends Packet { + + private final UUID localPlayerEntityUUID; + + public PacketSetLocalPlayer(UUID uuid) { + super("Core", "SetLocalPlayer"); + this.localPlayerEntityUUID = uuid; + } + + public UUID getLocalPlayerEntityUUID() { + return localPlayerEntityUUID; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/common/util/FloatMathUtils.java b/src/main/java/ru/windcorp/progressia/common/util/FloatMathUtils.java new file mode 100644 index 0000000..bdf3dec --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/util/FloatMathUtils.java @@ -0,0 +1,19 @@ +package ru.windcorp.progressia.common.util; + +import org.apache.commons.math3.util.FastMath; + +public class FloatMathUtils { + + public static final float PI_F = (float) Math.PI; + + public static float floor(float x) { + return (float) FastMath.floor(x); + } + + public static float normalizeAngle(float a) { + return a - 2*PI_F * floor((a + PI_F) / (2*PI_F)); + } + + private FloatMathUtils() {} + +} diff --git a/src/main/java/ru/windcorp/progressia/common/util/Matrices.java b/src/main/java/ru/windcorp/progressia/common/util/Matrices.java new file mode 100644 index 0000000..bc60c22 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/util/Matrices.java @@ -0,0 +1,65 @@ +package ru.windcorp.progressia.common.util; + +import glm.mat._3.Mat3; +import glm.mat._4.Mat4; +import glm.mat._4.d.Mat4d; + +/** + * A set of caches for GLM matrix objects. Use this instead of allocating new + * matrices when the objects are effectively local. + *

+ * All {@code grab}bed objects must be {@code release}d as soon as possible. + * Ideally, user code should be: + *

+ * Mat4 myMatrix = Vectors.grab4();
+ * try {
+ *     // use myMatrix
+ * } finally {
+ *     Matrices.release(myMatrix);
+ * }
+ * 
+ * Provided objects may be reused after {@code release} has been invoked; + * do not store them. + *

+ * This class is thread- and recursion-safe. + * + * @see Vectors + */ +public class Matrices { + + private static final LowOverheadCache MAT3S = + new LowOverheadCache<>(Mat3::new); + + public static Mat3 grab3() { + return MAT3S.grab(); + } + + public static void release(Mat3 m) { + MAT3S.release(m); + } + + private static final LowOverheadCache MAT4S = + new LowOverheadCache<>(Mat4::new); + + public static Mat4 grab4() { + return MAT4S.grab(); + } + + public static void release(Mat4 m) { + MAT4S.release(m); + } + + private static final LowOverheadCache MAT4DS = + new LowOverheadCache<>(Mat4d::new); + + public static Mat4d grab4d() { + return MAT4DS.grab(); + } + + public static void release(Mat4d m) { + MAT4DS.release(m); + } + + private Matrices() {} + +} diff --git a/src/main/java/ru/windcorp/progressia/common/util/Vectors.java b/src/main/java/ru/windcorp/progressia/common/util/Vectors.java index 2468707..489bf13 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/Vectors.java +++ b/src/main/java/ru/windcorp/progressia/common/util/Vectors.java @@ -25,6 +25,8 @@ import glm.vec._4.i.Vec4i; * do not store them. *

* This class is thread- and recursion-safe. + * + * @see Matrices */ public class Vectors { diff --git a/src/main/java/ru/windcorp/progressia/common/world/ChunkData.java b/src/main/java/ru/windcorp/progressia/common/world/ChunkData.java index b67032d..681b779 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/ChunkData.java +++ b/src/main/java/ru/windcorp/progressia/common/world/ChunkData.java @@ -22,11 +22,13 @@ import static ru.windcorp.progressia.common.world.block.BlockFace.*; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.UUID; import java.util.function.BiConsumer; import java.util.function.Consumer; import com.google.common.collect.Lists; +import glm.vec._2.Vec2; import glm.vec._3.Vec3; import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.client.world.tile.TileLocation; @@ -131,7 +133,11 @@ public class ChunkData { } EntityData javapony = new EntityData("Test", "Javapony"); - javapony.setPosition(new Vec3(8, 12, 16.2f)); + javapony.setUUID(UUID.nameUUIDFromBytes(new byte[] {42})); + javapony.setPosition(new Vec3(-6, -6, 20)); + javapony.setDirection(new Vec2( + (float) Math.toRadians(40), (float) Math.toRadians(45) + )); getEntities().add(javapony); } diff --git a/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java b/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java index cfff2b0..6f9381b 100644 --- a/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java +++ b/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java @@ -4,12 +4,14 @@ import java.util.Collection; import java.util.Collections; import java.util.concurrent.atomic.AtomicInteger; +import glm.vec._3.i.Vec3i; import gnu.trove.TCollections; import gnu.trove.map.TIntObjectMap; import gnu.trove.map.hash.TIntObjectHashMap; import ru.windcorp.progressia.common.comms.CommsChannel.Role; import ru.windcorp.progressia.common.comms.CommsChannel.State; import ru.windcorp.progressia.common.comms.packets.Packet; +import ru.windcorp.progressia.common.comms.packets.PacketSetLocalPlayer; import ru.windcorp.progressia.server.Server; public class ClientManager { @@ -36,6 +38,11 @@ public class ClientManager { clientsById.put(client.getId(), client); client.addListener(new DefaultServerCommsListener(this, client)); + + client.sendPacket(new PacketSetLocalPlayer( + server.getWorld().getData().getChunk(new Vec3i(0, 0, 0)) + .getEntities().get(0).getUUID() + )); } public void disconnectClient(Client client) {