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
This commit is contained in:
parent
dc74a419c9
commit
9dc3154874
@ -0,0 +1,8 @@
|
||||
package ru.windcorp.jputil.functions;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface FloatSupplier {
|
||||
|
||||
float getAsFloat();
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
}
|
||||
@ -127,4 +136,8 @@ public class TestContent {
|
||||
TileLogicRegistry.getInstance().register(x);
|
||||
}
|
||||
|
||||
private static void register(EntityLogic x) {
|
||||
EntityLogicRegistry.getInstance().register(x);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<Face> 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
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -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<BlockFace, Texture> 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,
|
||||
|
@ -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<BlockFace, Texture> 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<BlockFace, Texture> getCuboidTextures(
|
||||
int x, int y,
|
||||
int size
|
||||
) {
|
||||
return getCuboidTextures(x, y, size, size, size);
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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<ChunkData, ChunkRender> chunks = new HashMap<>();
|
||||
private final Map<EntityData, Renderable> entityModels =
|
||||
Collections.synchronizedMap(new WeakHashMap<>());
|
||||
|
||||
public WorldRender(WorldData data) {
|
||||
this.data = data;
|
||||
@ -62,4 +69,16 @@ public class WorldRender {
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
@ -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<EntityRender> {
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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<EntityData> 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<EntityData> getEntities() {
|
||||
return entities;
|
||||
}
|
||||
|
||||
private static void checkLocalCoordinates(Vec3i posInChunk) {
|
||||
if (!isInBounds(posInChunk)) {
|
||||
throw new IllegalArgumentException(
|
||||
@ -280,6 +294,10 @@ public class ChunkData {
|
||||
});
|
||||
}
|
||||
|
||||
public void forEachEntity(Consumer<EntityData> action) {
|
||||
getEntities().forEach(action);
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return position.x;
|
||||
}
|
||||
|
@ -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 <E> ImmutableMap<BlockFace, E> mapToFaces(
|
||||
E top, E bottom,
|
||||
E north, E south,
|
||||
E east, E west
|
||||
) {
|
||||
return ImmutableMap.<BlockFace, E>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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package ru.windcorp.progressia.common.world.entity;
|
||||
|
||||
import ru.windcorp.progressia.common.util.NamespacedRegistry;
|
||||
|
||||
public class EntityDataRegistry extends NamespacedRegistry<EntityData> {
|
||||
|
||||
private static final EntityDataRegistry INSTANCE = new EntityDataRegistry();
|
||||
|
||||
public static EntityDataRegistry getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package ru.windcorp.progressia.server.world.entity;
|
||||
|
||||
import ru.windcorp.progressia.common.util.NamespacedRegistry;
|
||||
|
||||
public class EntityLogicRegistry extends NamespacedRegistry<EntityLogic> {
|
||||
|
||||
private static final EntityLogicRegistry INSTANCE =
|
||||
new EntityLogicRegistry();
|
||||
|
||||
public static EntityLogicRegistry getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
}
|
BIN
src/main/resources/assets/textures/entities/javapony.png
Normal file
BIN
src/main/resources/assets/textures/entities/javapony.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
Reference in New Issue
Block a user