Blocks looked at are now highlighted

This commit is contained in:
OLEGSHA 2020-11-16 18:02:41 +03:00
parent b987412670
commit b51b3a4d80
11 changed files with 475 additions and 21 deletions

View File

@ -3,6 +3,7 @@ package ru.windcorp.progressia.client;
import ru.windcorp.progressia.client.comms.DefaultClientCommsListener; import ru.windcorp.progressia.client.comms.DefaultClientCommsListener;
import ru.windcorp.progressia.client.comms.ServerCommsChannel; import ru.windcorp.progressia.client.comms.ServerCommsChannel;
import ru.windcorp.progressia.client.graphics.world.Camera; import ru.windcorp.progressia.client.graphics.world.Camera;
import ru.windcorp.progressia.client.graphics.world.LocalPlayer;
import ru.windcorp.progressia.client.world.WorldRender; import ru.windcorp.progressia.client.world.WorldRender;
import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.WorldData;
import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.common.world.entity.EntityData;
@ -10,7 +11,7 @@ import ru.windcorp.progressia.common.world.entity.EntityData;
public class Client { public class Client {
private final WorldRender world; private final WorldRender world;
private EntityData localPlayer; private LocalPlayer localPlayer;
private final Camera camera = new Camera((float) Math.toRadians(70)); private final Camera camera = new Camera((float) Math.toRadians(70));
@ -27,12 +28,12 @@ public class Client {
return world; return world;
} }
public EntityData getLocalPlayer() { public LocalPlayer getLocalPlayer() {
return localPlayer; return localPlayer;
} }
public void setLocalPlayer(EntityData localPlayer) { public void setLocalPlayer(EntityData localPlayer) {
this.localPlayer = localPlayer; this.localPlayer = new LocalPlayer(localPlayer);
} }
public Camera getCamera() { public Camera getCamera() {

View File

@ -20,6 +20,7 @@ package ru.windcorp.progressia.client.graphics.world;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.client.Client; import ru.windcorp.progressia.client.Client;
import ru.windcorp.progressia.client.ClientState; import ru.windcorp.progressia.client.ClientState;
import ru.windcorp.progressia.client.comms.controls.InputBasedControls; import ru.windcorp.progressia.client.comms.controls.InputBasedControls;
@ -65,6 +66,10 @@ public class LayerWorld extends Layer {
if (camera.hasAnchor()) { if (camera.hasAnchor()) {
renderWorld(); renderWorld();
} }
if (client.getLocalPlayer() != null) {
client.getLocalPlayer().update(client.getWorld());
}
} }
private void renderWorld() { private void renderWorld() {
@ -89,6 +94,7 @@ public class LayerWorld extends Layer {
try { try {
tmp_performCollisions(tickLength); tmp_performCollisions(tickLength);
tmp_drawSelectionBox();
tmp_testControls.applyPlayerControls(); tmp_testControls.applyPlayerControls();
@ -122,13 +128,25 @@ public class LayerWorld extends Layer {
); );
} }
private void tmp_drawSelectionBox() {
LocalPlayer player = client.getLocalPlayer();
if (player == null) return;
Vec3i lookingAt = player.getLookingAt();
if (lookingAt == null) return;
helper.pushTransform().translate(lookingAt.x, lookingAt.y, lookingAt.z).scale(1.1f);
CollisionModelRenderer.renderCollisionModel(client.getWorld().getData().getCollisionModelOfBlock(lookingAt), helper);
helper.popTransform();
}
private void tmp_applyFriction(EntityData entity) { private void tmp_applyFriction(EntityData entity) {
final float frictionCoeff = 1 - 1e-5f; final float frictionCoeff = 1 - 1e-5f;
entity.getVelocity().mul(frictionCoeff); entity.getVelocity().mul(frictionCoeff);
} }
private void tmp_applyGravity(EntityData entity, float tickLength) { private void tmp_applyGravity(EntityData entity, float tickLength) {
if (ClientState.getInstance().getLocalPlayer() == entity && tmp_testControls.isFlying()) { if (ClientState.getInstance().getLocalPlayer().getEntity() == entity && tmp_testControls.isFlying()) {
return; return;
} }

View File

@ -0,0 +1,64 @@
package ru.windcorp.progressia.client.graphics.world;
import glm.vec._3.Vec3;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.client.world.WorldRender;
import ru.windcorp.progressia.client.world.entity.EntityRenderable;
import ru.windcorp.progressia.common.util.Vectors;
import ru.windcorp.progressia.common.world.BlockRay;
import ru.windcorp.progressia.common.world.Player;
import ru.windcorp.progressia.common.world.entity.EntityData;
public class LocalPlayer extends Player {
private Vec3i lookingAt = new Vec3i();
private boolean isLookingAtBlock = false;
private BlockRay lookingAtRay = new BlockRay();
public LocalPlayer(EntityData entity) {
super(entity);
}
public Vec3i getLookingAt() {
return isLookingAtBlock ? lookingAt : null;
}
public void update(WorldRender world) {
updateLookingAt(world);
}
private void updateLookingAt(WorldRender world) {
Vec3 direction = Vectors.grab3();
Vec3 start = Vectors.grab3();
BlockRay ray = lookingAtRay;
EntityData player = getEntity();
player.getLookingAtVector(direction);
world.getEntityRenderable(player).getViewPoint(start);
start.add(player.getPosition());
isLookingAtBlock = false;
for (ray.start(start, direction); ray.getDistance() < 6; ray.next()) {
Vec3i blockInWorld = ray.current();
if (world.getData().getCollisionModelOfBlock(blockInWorld) != null) {
isLookingAtBlock = true;
lookingAt.set(blockInWorld.x, blockInWorld.y, blockInWorld.z);
break;
}
}
ray.end();
Vectors.release(direction);
Vectors.release(start);
}
public EntityRenderable getRenderable(WorldRender world) {
return world.getEntityRenderable(getEntity());
}
}

View File

@ -3,12 +3,22 @@ package ru.windcorp.progressia.common.util;
import java.util.function.Consumer; import java.util.function.Consumer;
import glm.mat._4.Mat4; import glm.mat._4.Mat4;
import glm.vec._2.Vec2;
import glm.vec._2.d.Vec2d;
import glm.vec._2.i.Vec2i;
import glm.vec._3.Vec3; import glm.vec._3.Vec3;
import glm.vec._3.d.Vec3d;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import glm.vec._4.Vec4; import glm.vec._4.Vec4;
import glm.vec._4.d.Vec4d;
import glm.vec._4.i.Vec4i;
public class VectorUtil { public class VectorUtil {
public static enum Axis {
X, Y, Z, W;
}
public static void forEachVectorInCuboid( public static void forEachVectorInCuboid(
int x0, int y0, int z0, int x0, int y0, int z0,
int x1, int y1, int z1, int x1, int y1, int z1,
@ -47,6 +57,204 @@ public class VectorUtil {
inOut.set(vec4.x, vec4.y, vec4.z); inOut.set(vec4.x, vec4.y, vec4.z);
} }
public static Vec3 linearCombination(
Vec3 va, float ka,
Vec3 vb, float kb,
Vec3 output
) {
output.set(
va.x * ka + vb.x * kb,
va.y * ka + vb.y * kb,
va.z * ka + vb.z * kb
);
return output;
}
public static Vec3 linearCombination(
Vec3 va, float ka,
Vec3 vb, float kb,
Vec3 vc, float kc,
Vec3 output
) {
output.set(
va.x * ka + vb.x * kb + vc.x * kc,
va.y * ka + vb.y * kb + vc.y * kc,
va.z * ka + vb.z * kb + vc.z * kc
);
return output;
}
public static float get(Vec2 v, Axis a) {
switch (a) {
case X: return v.x;
case Y: return v.y;
default: throw new IllegalArgumentException("Vec2 does not have axis " + a);
}
}
public static Vec2 set(Vec2 v, Axis a, float value) {
switch (a) {
case X: v.x = value; break;
case Y: v.y = value; break;
default: throw new IllegalArgumentException("Vec2 does not have axis " + a);
}
return v;
}
public static int get(Vec2i v, Axis a) {
switch (a) {
case X: return v.x;
case Y: return v.y;
default: throw new IllegalArgumentException("Vec2i does not have axis " + a);
}
}
public static Vec2i set(Vec2i v, Axis a, int value) {
switch (a) {
case X: v.x = value; break;
case Y: v.y = value; break;
default: throw new IllegalArgumentException("Vec2i does not have axis " + a);
}
return v;
}
public static double get(Vec2d v, Axis a) {
switch (a) {
case X: return v.x;
case Y: return v.y;
default: throw new IllegalArgumentException("Vec2d does not have axis " + a);
}
}
public static Vec2d set(Vec2d v, Axis a, double value) {
switch (a) {
case X: v.x = value; break;
case Y: v.y = value; break;
default: throw new IllegalArgumentException("Vec2d does not have axis " + a);
}
return v;
}
public static float get(Vec3 v, Axis a) {
switch (a) {
case X: return v.x;
case Y: return v.y;
case Z: return v.z;
default: throw new IllegalArgumentException("Vec3 does not have axis " + a);
}
}
public static Vec3 set(Vec3 v, Axis a, float value) {
switch (a) {
case X: v.x = value; break;
case Y: v.y = value; break;
case Z: v.z = value; break;
default: throw new IllegalArgumentException("Vec3 does not have axis " + a);
}
return v;
}
public static int get(Vec3i v, Axis a) {
switch (a) {
case X: return v.x;
case Y: return v.y;
case Z: return v.z;
default: throw new IllegalArgumentException("Vec3i does not have axis " + a);
}
}
public static Vec3i set(Vec3i v, Axis a, int value) {
switch (a) {
case X: v.x = value; break;
case Y: v.y = value; break;
case Z: v.z = value; break;
default: throw new IllegalArgumentException("Vec3i does not have axis " + a);
}
return v;
}
public static double get(Vec3d v, Axis a) {
switch (a) {
case X: return v.x;
case Y: return v.y;
case Z: return v.z;
default: throw new IllegalArgumentException("Vec3d does not have axis " + a);
}
}
public static Vec3d set(Vec3d v, Axis a, double value) {
switch (a) {
case X: v.x = value; break;
case Y: v.y = value; break;
case Z: v.z = value; break;
default: throw new IllegalArgumentException("Vec3d does not have axis " + a);
}
return v;
}
public static float get(Vec4 v, Axis a) {
switch (a) {
case X: return v.x;
case Y: return v.y;
case Z: return v.z;
case W: return v.w;
default: throw new IllegalArgumentException("Vec4 does not have axis " + a);
}
}
public static Vec4 set(Vec4 v, Axis a, float value) {
switch (a) {
case X: v.x = value; break;
case Y: v.y = value; break;
case Z: v.z = value; break;
case W: v.w = value; break;
default: throw new IllegalArgumentException("Vec4 does not have axis " + a);
}
return v;
}
public static int get(Vec4i v, Axis a) {
switch (a) {
case X: return v.x;
case Y: return v.y;
case Z: return v.z;
case W: return v.w;
default: throw new IllegalArgumentException("Vec4i does not have axis " + a);
}
}
public static Vec4i set(Vec4i v, Axis a, int value) {
switch (a) {
case X: v.x = value; break;
case Y: v.y = value; break;
case Z: v.z = value; break;
case W: v.w = value; break;
default: throw new IllegalArgumentException("Vec4i does not have axis " + a);
}
return v;
}
public static double get(Vec4d v, Axis a) {
switch (a) {
case X: return v.x;
case Y: return v.y;
case Z: return v.z;
case W: return v.w;
default: throw new IllegalArgumentException("Vec4d does not have axis " + a);
}
}
public static Vec4d set(Vec4d v, Axis a, double value) {
switch (a) {
case X: v.x = value; break;
case Y: v.y = value; break;
case Z: v.z = value; break;
case W: v.w = value; break;
default: throw new IllegalArgumentException("Vec4d does not have axis " + a);
}
return v;
}
private VectorUtil() {} private VectorUtil() {}
} }

View File

@ -0,0 +1,123 @@
package ru.windcorp.progressia.common.world;
import glm.vec._3.Vec3;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.util.VectorUtil;
import ru.windcorp.progressia.common.util.VectorUtil.Axis;
import static java.lang.Math.*;
public class BlockRay {
private final Vec3 position = new Vec3();
private final Vec3 direction = new Vec3();
private float distance;
private final Vec3i block = new Vec3i();
private boolean isValid = false;
public void start(Vec3 position, Vec3 direction) {
if (!direction.any()) {
throw new IllegalArgumentException("Direction is a zero vector");
}
isValid = true;
this.position.set(position).sub(0.5f); // Make sure lattice points are block vertices, not centers
this.direction.set(direction).normalize();
this.block.set(toBlock(position.x), toBlock(position.y), toBlock(position.z));
this.distance = 0;
}
public void end() {
isValid = false;
}
public Vec3i next() {
checkState();
float tx = distanceToEdge(position.x, direction.x);
float ty = distanceToEdge(position.y, direction.y);
float tz = distanceToEdge(position.z, direction.z);
float tMin;
Axis axis;
if (tx < ty && tx < tz) {
tMin = tx;
axis = Axis.X;
} else if (ty < tx && ty < tz) {
tMin = ty;
axis = Axis.Y;
} else {
tMin = tz;
axis = Axis.Z;
}
// block.(axis) += signum(direction.(axis))
VectorUtil.set(block, axis, VectorUtil.get(block, axis) + (int) signum(VectorUtil.get(direction, axis)));
// position += direction * tMin
VectorUtil.linearCombination(position, 1, direction, tMin, position); // position += direction * tMin
distance += tMin;
// position.(axis) = round(position.(axis))
VectorUtil.set(position, axis, round(VectorUtil.get(position, axis)));
return block;
}
public Vec3i current() {
checkState();
return block;
}
private static float distanceToEdge(float c, float dir) {
if (dir == 0) return Float.POSITIVE_INFINITY;
float edge;
if (dir > 0) {
edge = strictCeil(c);
} else {
edge = strictFloor(c);
}
return (edge - c) / dir;
}
public float getDistance() {
checkState();
return distance;
}
private void checkState() {
if (!isValid) {
throw new IllegalStateException("BlockRay not started");
}
}
private static int toBlock(float c) {
return (int) round(c);
}
/**
* Returns a smallest integer <i>a</i> such that <i>a</i> > <i>c</i>.
* @param c the number to compute strict ceiling of
* @return the strict ceiling of <i>c</i>
*/
private static float strictCeil(float c) {
return (float) (floor(c) + 1);
}
/**
* Returns a largest integer <i>a</i> such that <i>a</i> < <i>c</i>.
* @param c the number to compute strict ceiling of
* @return the strict ceiling of <i>c</i>
*/
private static float strictFloor(float c) {
return (float) (ceil(c) - 1);
}
}

View File

@ -133,14 +133,6 @@ public class ChunkData {
} }
if (!getPosition().any()) { if (!getPosition().any()) {
// EntityData javapony = EntityDataRegistry.getInstance().create("Test:Javapony");
// javapony.setEntityId(0x42);
// javapony.setPosition(new Vec3(-6, -6, 20));
// javapony.setDirection(new Vec2(
// (float) Math.toRadians(40), (float) Math.toRadians(45)
// ));
// getEntities().add(javapony);
EntityData player = EntityDataRegistry.getInstance().create("Test:Player"); EntityData player = EntityDataRegistry.getInstance().create("Test:Player");
player.setEntityId(0x42); player.setEntityId(0x42);
player.setPosition(new Vec3(-6, -6, 20)); player.setPosition(new Vec3(-6, -6, 20));

View File

@ -0,0 +1,17 @@
package ru.windcorp.progressia.common.world;
import ru.windcorp.progressia.common.world.entity.EntityData;
public class Player {
private EntityData entity;
public Player(EntityData entity) {
this.entity = entity;
}
public EntityData getEntity() {
return entity;
}
}

View File

@ -119,5 +119,15 @@ public class EntityData extends StatefulObject implements Collideable {
public void changeVelocityOnCollision(Vec3 velocityChange) { public void changeVelocityOnCollision(Vec3 velocityChange) {
getVelocity().add(velocityChange); getVelocity().add(velocityChange);
} }
public Vec3 getLookingAtVector(Vec3 output) {
output.set(
Math.cos(getPitch()) * Math.cos(getYaw()),
Math.cos(getPitch()) * Math.sin(getYaw()),
-Math.sin(getPitch())
);
return output;
}
} }

View File

@ -53,7 +53,7 @@ public class CollisionModelRenderer {
} }
public static void renderBlock(Vec3i coords, ShapeRenderHelper helper) { public static void renderBlock(Vec3i coords, ShapeRenderHelper helper) {
helper.pushTransform().translate(coords.x, coords.y, coords.z); helper.pushTransform().translate(coords.x, coords.y, coords.z).scale(0.25f);
CUBE_GRAY.render(helper); CUBE_GRAY.render(helper);
helper.popTransform(); helper.popTransform();
} }

View File

@ -87,10 +87,6 @@ public class TestContent {
} }
private static void registerEntities() { private static void registerEntities() {
// registerEntityData("Test", "Javapony", e -> e.setCollisionModel(new AABB(0, 0, -0.05f, 0.75f, 0.75f, 1.2f)));
// register(new TestEntityRenderJavapony());
// register(new EntityLogic("Test", "Javapony"));
float scale = 1.8f / 8; float scale = 1.8f / 8;
registerEntityData("Test", "Player", e -> e.setCollisionModel(new AABB(0, 0, 4*scale, 0.75f, 0.75f, 1.8f))); registerEntityData("Test", "Player", e -> e.setCollisionModel(new AABB(0, 0, 4*scale, 0.75f, 0.75f, 1.8f)));
register(new TestEntityRenderHuman()); register(new TestEntityRenderHuman());
@ -121,6 +117,26 @@ public class TestContent {
server.getAdHocChanger().setBlock(z000, block); server.getAdHocChanger().setBlock(z000, block);
} }
}); });
// ControlDataRegistry.getInstance().register(new ControlData("Test", "BreakBlock"));
// ControlTriggerRegistry.getInstance().register(new ControlTriggerOnKeyPress("Test", "BreakBlock", new KeyMatcher(GLFW.GLFW_KEY_ENTER, new int[0], 0)::matches));
// ControlLogicRegistry.getInstance().register(new ControlLogic("Test", "BreakBlock") {
// @Override
// public void apply(Server server, PacketControl packet, Client client) {
// Vec3i z000 = new Vec3i(0, 0, 0);
//
// ChunkData data = server.getWorld().getChunk(z000).getData();
//
// BlockData block;
// if (data.getBlock(z000).getId().equals("Test:Stone")) {
// block = BlockDataRegistry.getInstance().get("Test:Glass");
// } else {
// block = BlockDataRegistry.getInstance().get("Test:Stone");
// }
//
// server.getAdHocChanger().setBlock(z000, block);
// }
// });
} }
private static void register(BlockData x) { private static void register(BlockData x) {

View File

@ -13,6 +13,7 @@ import ru.windcorp.progressia.client.graphics.input.CursorMoveEvent;
import ru.windcorp.progressia.client.graphics.input.InputEvent; import ru.windcorp.progressia.client.graphics.input.InputEvent;
import ru.windcorp.progressia.client.graphics.input.KeyEvent; import ru.windcorp.progressia.client.graphics.input.KeyEvent;
import ru.windcorp.progressia.client.graphics.input.bus.Input; import ru.windcorp.progressia.client.graphics.input.bus.Input;
import ru.windcorp.progressia.client.graphics.world.LocalPlayer;
import ru.windcorp.progressia.common.Units; import ru.windcorp.progressia.common.Units;
import ru.windcorp.progressia.common.util.FloatMathUtils; import ru.windcorp.progressia.common.util.FloatMathUtils;
import ru.windcorp.progressia.common.util.Matrices; import ru.windcorp.progressia.common.util.Matrices;
@ -65,7 +66,7 @@ public class TestPlayerControls {
return; return;
} }
EntityData player = getPlayer(); EntityData player = getEntity();
Mat3 angMat = Matrices.grab3(); Mat3 angMat = Matrices.grab3();
angMat.identity().rotateZ(player.getYaw()); angMat.identity().rotateZ(player.getYaw());
@ -185,7 +186,7 @@ public class TestPlayerControls {
} }
private void jump() { private void jump() {
getPlayer().getVelocity().add(0, 0, JUMP_VELOCITY * (useMinecraftGravity ? 2 : 1)); getEntity().getVelocity().add(0, 0, JUMP_VELOCITY * (useMinecraftGravity ? 2 : 1));
} }
private void handleShift(int multiplier) { private void handleShift(int multiplier) {
@ -223,7 +224,7 @@ public class TestPlayerControls {
final float yawScale = -0.002f; final float yawScale = -0.002f;
final float pitchScale = yawScale; final float pitchScale = yawScale;
EntityData player = getPlayer(); EntityData player = getEntity();
normalizeAngles(player.getDirection().add( normalizeAngles(player.getDirection().add(
(float) (event.getChangeX() * yawScale), (float) (event.getChangeX() * yawScale),
@ -241,7 +242,11 @@ public class TestPlayerControls {
); );
} }
private EntityData getPlayer() { private EntityData getEntity() {
return getPlayer().getEntity();
}
private LocalPlayer getPlayer() {
return ClientState.getInstance().getLocalPlayer(); return ClientState.getInstance().getLocalPlayer();
} }