From 0dd5e6d3da02ca3922d28624017bd92e246796e4 Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Thu, 12 Nov 2020 23:13:41 +0300 Subject: [PATCH 1/6] Increased encapsulation of AABBs and added TranslatedAABB - Interface of AABB (getOrigin(), getSize() and getWall(int)) now extracted into AABBoid interface - Same with Walls - Collection getWalls() replaced with Wall getWall(int) - Added TranslatedAABB extends AABBoid - CollisionClock replaced with direct reference to WorldData - Reorganized tmp code in LayerWorld, so as to decrease cRiNgE_ levels --- .../client/graphics/world/LayerWorld.java | 72 +++++------ .../progressia/common/collision/AABB.java | 112 ++++++++++-------- .../progressia/common/collision/AABBoid.java | 17 +++ .../common/collision/CollisionClock.java | 8 -- .../common/collision/CollisionWall.java | 55 --------- .../common/collision/TranslatedAABB.java | 105 ++++++++++++++++ .../progressia/common/collision/Wall.java | 12 ++ ...AABBCollider.java => AABBoidCollider.java} | 60 ++++++---- .../common/collision/colliders/Collider.java | 45 +++---- .../progressia/common/util/Vectors.java | 13 ++ .../progressia/common/world/WorldData.java | 14 +++ .../progressia/test/AABBRenderer.java | 35 ------ .../test/CollisionModelRenderer.java | 61 ++++++++++ .../progressia/test/TestEntityDataStatie.java | 3 +- 14 files changed, 383 insertions(+), 229 deletions(-) create mode 100644 src/main/java/ru/windcorp/progressia/common/collision/AABBoid.java delete mode 100644 src/main/java/ru/windcorp/progressia/common/collision/CollisionClock.java delete mode 100644 src/main/java/ru/windcorp/progressia/common/collision/CollisionWall.java create mode 100644 src/main/java/ru/windcorp/progressia/common/collision/TranslatedAABB.java create mode 100644 src/main/java/ru/windcorp/progressia/common/collision/Wall.java rename src/main/java/ru/windcorp/progressia/common/collision/colliders/{AABBWithAABBCollider.java => AABBoidCollider.java} (78%) delete mode 100644 src/main/java/ru/windcorp/progressia/test/AABBRenderer.java create mode 100644 src/main/java/ru/windcorp/progressia/test/CollisionModelRenderer.java 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 114e1ed..5f74963 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 @@ -36,16 +36,12 @@ 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.collision.AABB; import ru.windcorp.progressia.common.collision.Collideable; -import ru.windcorp.progressia.common.collision.CollisionClock; -import ru.windcorp.progressia.common.collision.CollisionModel; -import ru.windcorp.progressia.common.collision.CompoundCollisionModel; import ru.windcorp.progressia.common.collision.colliders.Collider; import ru.windcorp.progressia.common.util.FloatMathUtils; import ru.windcorp.progressia.common.util.Vectors; import ru.windcorp.progressia.common.world.entity.EntityData; -import ru.windcorp.progressia.test.AABBRenderer; +import ru.windcorp.progressia.test.CollisionModelRenderer; public class LayerWorld extends Layer { @@ -128,52 +124,46 @@ public class LayerWorld extends Layer { private final Collider.ColliderWorkspace tmp_colliderWorkspace = new Collider.ColliderWorkspace(); private final List tmp_collideableList = new ArrayList<>(); - private static final boolean RENDER_AABBS = true; + private static final boolean RENDER_COLLISION_MODELS = true; private void tmp_doEveryFrame() { try { - if (RENDER_AABBS) { - for (EntityData data : this.client.getWorld().getData().getEntities()) { - CollisionModel model = data.getCollisionModel(); - if (model instanceof AABB) { - AABBRenderer.renderAABB((AABB) model, helper); - } else if (model instanceof CompoundCollisionModel) { - AABBRenderer.renderAABBsInCompound((CompoundCollisionModel) model, helper); - } - } - } - - tmp_collideableList.clear(); - tmp_collideableList.addAll(this.client.getWorld().getData().getEntities()); - - Collider.performCollisions( - tmp_collideableList, - new CollisionClock() { - private float t = 0; - @Override - public float getTime() { - return t; - } - - @Override - public void advanceTime(float change) { - t += change; - } - }, - (float) GraphicsInterface.getFrameLength(), - tmp_colliderWorkspace - ); - - final float frictionCoeff = 1 - 1e-2f; + tmp_performCollisions(); for (EntityData data : this.client.getWorld().getData().getEntities()) { - data.getVelocity().mul(frictionCoeff); + tmp_applyFriction(data); + tmp_renderCollisionModel(data); } - } catch (Exception e) { + } catch (Throwable e) { + e.printStackTrace(); + System.out.println("OLEGSHA is to blame. Tell him he vry stupiDD!!"); System.exit(31337); } } + private void tmp_renderCollisionModel(EntityData entity) { + if (RENDER_COLLISION_MODELS) { + CollisionModelRenderer.renderCollisionModel(entity.getCollisionModel(), helper); + } + } + + private void tmp_performCollisions() { + tmp_collideableList.clear(); + tmp_collideableList.addAll(this.client.getWorld().getData().getEntities()); + + Collider.performCollisions( + tmp_collideableList, + this.client.getWorld().getData(), + (float) GraphicsInterface.getFrameLength(), + tmp_colliderWorkspace + ); + } + + private void tmp_applyFriction(EntityData entity) { + final float frictionCoeff = 1 - 1e-2f; + entity.getVelocity().mul(frictionCoeff); + } + @Override protected void handleInput(Input input) { if (input.isConsumed()) return; diff --git a/src/main/java/ru/windcorp/progressia/common/collision/AABB.java b/src/main/java/ru/windcorp/progressia/common/collision/AABB.java index 7188e33..9b0fd31 100644 --- a/src/main/java/ru/windcorp/progressia/common/collision/AABB.java +++ b/src/main/java/ru/windcorp/progressia/common/collision/AABB.java @@ -1,93 +1,111 @@ package ru.windcorp.progressia.common.collision; -import java.util.Collection; -import java.util.Map; - import glm.vec._3.Vec3; -import ru.windcorp.progressia.common.world.block.BlockFace; -public class AABB implements CollisionModel { +/** + * An implementation of an + * Axis-Aligned Bounding Box. + * @author javapony + */ +public class AABB implements AABBoid { + + private class AABBWallImpl implements Wall { + + private final Vec3 originOffset = new Vec3(); + private final Vec3 widthSelector = new Vec3(); + private final Vec3 heightSelector = new Vec3(); - private final Map faces = BlockFace.mapToFaces( - new CollisionWall(-0.5f, -0.5f, -0.5f, +1, 0, 0, 0, 0, +1), - new CollisionWall(+0.5f, -0.5f, -0.5f, 0, +1, 0, 0, 0, +1), - new CollisionWall(+0.5f, +0.5f, -0.5f, -1, 0, 0, 0, 0, +1), - new CollisionWall(-0.5f, +0.5f, -0.5f, 0, -1, 0, 0, 0, +1), - - new CollisionWall(-0.5f, -0.5f, +0.5f, +1, 0, 0, 0, +1, 0), - new CollisionWall(-0.5f, -0.5f, -0.5f, 0, +1, 0, +1, 0, 0) - ); + public AABBWallImpl( + float ox, float oy, float oz, + float wx, float wy, float wz, + float hx, float hy, float hz + ) { + this.originOffset.set(ox, oy, oz); + this.widthSelector.set(wx, wy, wz); + this.heightSelector.set(hx, hy, hz); + } + + @Override + public void getOrigin(Vec3 output) { + output.set(originOffset).mul(AABB.this.getSize()).add(AABB.this.getOrigin()); + } + + @Override + public void getWidth(Vec3 output) { + output.set(AABB.this.getSize()).mul(widthSelector); + } + + @Override + public void getHeight(Vec3 output) { + output.set(AABB.this.getSize()).mul(heightSelector); + } + + } + + private final Wall[] walls = new Wall[] { + new AABBWallImpl(-0.5f, -0.5f, +0.5f, +1, 0, 0, 0, +1, 0), // Top + new AABBWallImpl(-0.5f, -0.5f, -0.5f, 0, +1, 0, +1, 0, 0), // Bottom + new AABBWallImpl(+0.5f, -0.5f, -0.5f, 0, +1, 0, 0, 0, +1), // North + new AABBWallImpl(-0.5f, +0.5f, -0.5f, 0, -1, 0, 0, 0, +1), // South + new AABBWallImpl(+0.5f, +0.5f, -0.5f, -1, 0, 0, 0, 0, +1), // West + new AABBWallImpl(-0.5f, -0.5f, -0.5f, +1, 0, 0, 0, 0, +1) // East + }; private final Vec3 origin = new Vec3(); private final Vec3 size = new Vec3(); public AABB(Vec3 origin, Vec3 size) { - this.origin.set(origin); - this.size.set(size); - - for (CollisionWall wall : getFaces()) { - wall.moveOrigin(origin); - wall.getWidth().mul(size); - wall.getHeight().mul(size); - } + this(origin.x, origin.y, origin.z, size.x, size.y, size.z); } public AABB( - float ox, float oy, float oz, + float ox, float oy, float oz, float xSize, float ySize, float zSize ) { this.origin.set(ox, oy, oz); this.size.set(xSize, ySize, zSize); - - for (CollisionWall wall : getFaces()) { - wall.moveOrigin(ox, oy, oz); - wall.getWidth().mul(xSize, ySize, zSize); - wall.getHeight().mul(xSize, ySize, zSize); - } - } - - public Collection getFaces() { - return faces.values(); } public Vec3 getOrigin() { return origin; } + + @Override + public void getOrigin(Vec3 output) { + output.set(origin); + } @Override public void setOrigin(Vec3 origin) { - for (CollisionWall wall : getFaces()) { - wall.getOrigin().sub(this.origin).add(origin); - } - this.origin.set(origin); } @Override public void moveOrigin(Vec3 displacement) { - for (CollisionWall wall : getFaces()) { - wall.getOrigin().add(displacement); - } - this.origin.add(displacement); } public Vec3 getSize() { return size; } + + @Override + public void getSize(Vec3 output) { + output.set(size); + } public void setSize(Vec3 size) { setSize(size.x, size.y, size.z); } public void setSize(float xSize, float ySize, float zSize) { - for (CollisionWall wall : getFaces()) { - wall.getWidth().div(this.size).mul(xSize, ySize, zSize); - wall.getHeight().div(this.size).mul(xSize, ySize, zSize); - wall.getOrigin().sub(getOrigin()).div(this.size).mul(xSize, ySize, zSize).add(getOrigin()); - } - this.size.set(xSize, ySize, zSize); } + + @Override + public Wall getWall(int faceId) { + // No, we don't support Apple. + return walls[faceId]; + } } diff --git a/src/main/java/ru/windcorp/progressia/common/collision/AABBoid.java b/src/main/java/ru/windcorp/progressia/common/collision/AABBoid.java new file mode 100644 index 0000000..6e1d384 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/collision/AABBoid.java @@ -0,0 +1,17 @@ +package ru.windcorp.progressia.common.collision; + +import glm.vec._3.Vec3; +import ru.windcorp.progressia.common.world.block.BlockFace; + +public interface AABBoid extends CollisionModel { + + void getOrigin(Vec3 output); + void getSize(Vec3 output); + + default Wall getWall(BlockFace face) { + return getWall(face.getId()); + } + + Wall getWall(int faceId); + +} diff --git a/src/main/java/ru/windcorp/progressia/common/collision/CollisionClock.java b/src/main/java/ru/windcorp/progressia/common/collision/CollisionClock.java deleted file mode 100644 index cf42614..0000000 --- a/src/main/java/ru/windcorp/progressia/common/collision/CollisionClock.java +++ /dev/null @@ -1,8 +0,0 @@ -package ru.windcorp.progressia.common.collision; - -public interface CollisionClock { - - float getTime(); - void advanceTime(float change); - -} diff --git a/src/main/java/ru/windcorp/progressia/common/collision/CollisionWall.java b/src/main/java/ru/windcorp/progressia/common/collision/CollisionWall.java deleted file mode 100644 index 8963ffd..0000000 --- a/src/main/java/ru/windcorp/progressia/common/collision/CollisionWall.java +++ /dev/null @@ -1,55 +0,0 @@ -package ru.windcorp.progressia.common.collision; - -import glm.vec._3.Vec3; - -public class CollisionWall { - - private final Vec3 origin = new Vec3(); - private final Vec3 width = new Vec3(); - private final Vec3 height = new Vec3(); - - public CollisionWall(Vec3 origin, Vec3 width, Vec3 height) { - this.origin.set(origin); - this.width.set(width); - this.height.set(height); - } - - public CollisionWall( - float ox, float oy, float oz, - float wx, float wy, float wz, - float hx, float hy, float hz - ) { - this.origin.set(ox, oy, oz); - this.width.set(wx, wy, wz); - this.height.set(hx, hy, hz); - } - - public Vec3 getOrigin() { - return origin; - } - - public Vec3 getWidth() { - return width; - } - - public Vec3 getHeight() { - return height; - } - - public void setOrigin(Vec3 origin) { - setOrigin(origin.x, origin.y, origin.z); - } - - public void setOrigin(float x, float y, float z) { - this.origin.set(x, y, z); - } - - public void moveOrigin(Vec3 displacement) { - moveOrigin(displacement.x, displacement.y, displacement.z); - } - - public void moveOrigin(float dx, float dy, float dz) { - this.origin.add(dx, dy, dz); - } - -} diff --git a/src/main/java/ru/windcorp/progressia/common/collision/TranslatedAABB.java b/src/main/java/ru/windcorp/progressia/common/collision/TranslatedAABB.java new file mode 100644 index 0000000..a22c330 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/collision/TranslatedAABB.java @@ -0,0 +1,105 @@ +package ru.windcorp.progressia.common.collision; + +import glm.vec._3.Vec3; +import ru.windcorp.progressia.common.util.Vectors; +import ru.windcorp.progressia.common.world.block.BlockFace; + +public class TranslatedAABB implements AABBoid { + + private class TranslatedAABBWall implements Wall { + private final int id; + + public TranslatedAABBWall(int id) { + this.id = id; + } + + @Override + public void getOrigin(Vec3 output) { + parent.getWall(id).getOrigin(output); + output.add(translation); + } + + @Override + public void getWidth(Vec3 output) { + parent.getWall(id).getWidth(output); + } + + @Override + public void getHeight(Vec3 output) { + parent.getWall(id).getHeight(output); + } + } + + private AABBoid parent; + private final Vec3 translation = new Vec3(); + + private final TranslatedAABBWall[] walls = new TranslatedAABBWall[BlockFace.BLOCK_FACE_COUNT]; + + { + for (int id = 0; id < walls.length; ++id) { + walls[id] = new TranslatedAABBWall(id); + } + } + + public TranslatedAABB(AABBoid parent, float tx, float ty, float tz) { + setParent(parent); + setTranslation(tx, ty, tz); + } + + public TranslatedAABB(AABBoid parent, Vec3 translation) { + this(parent, translation.x, translation.y, translation.z); + } + + public TranslatedAABB() { + this(null, 0, 0, 0); + } + + @Override + public void setOrigin(Vec3 origin) { + Vec3 v = Vectors.grab3().set(origin).sub(translation); + parent.setOrigin(v); + Vectors.release(v); + } + + @Override + public void moveOrigin(Vec3 displacement) { + parent.moveOrigin(displacement); + } + + @Override + public void getOrigin(Vec3 output) { + parent.getOrigin(output); + output.add(translation); + } + + @Override + public void getSize(Vec3 output) { + parent.getSize(output); + } + + @Override + public Wall getWall(int faceId) { + return walls[faceId]; + } + + public AABBoid getParent() { + return parent; + } + + public void setParent(AABBoid parent) { + this.parent = parent; + } + + public Vec3 getTranslation() { + return translation; + } + + public void setTranslation(Vec3 translation) { + setTranslation(translation.x, translation.y, translation.z); + } + + public void setTranslation(float tx, float ty, float tz) { + this.translation.set(tx, ty, tz); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/common/collision/Wall.java b/src/main/java/ru/windcorp/progressia/common/collision/Wall.java new file mode 100644 index 0000000..9549f04 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/collision/Wall.java @@ -0,0 +1,12 @@ +package ru.windcorp.progressia.common.collision; + +import glm.vec._3.Vec3; + +public interface Wall { + + void getOrigin(Vec3 output); + + void getWidth(Vec3 output); + void getHeight(Vec3 output); + +} diff --git a/src/main/java/ru/windcorp/progressia/common/collision/colliders/AABBWithAABBCollider.java b/src/main/java/ru/windcorp/progressia/common/collision/colliders/AABBoidCollider.java similarity index 78% rename from src/main/java/ru/windcorp/progressia/common/collision/colliders/AABBWithAABBCollider.java rename to src/main/java/ru/windcorp/progressia/common/collision/colliders/AABBoidCollider.java index 7b961e1..f440761 100644 --- a/src/main/java/ru/windcorp/progressia/common/collision/colliders/AABBWithAABBCollider.java +++ b/src/main/java/ru/windcorp/progressia/common/collision/colliders/AABBoidCollider.java @@ -2,26 +2,25 @@ package ru.windcorp.progressia.common.collision.colliders; import glm.mat._3.Mat3; import glm.vec._3.Vec3; -import ru.windcorp.progressia.common.collision.AABB; -import ru.windcorp.progressia.common.collision.Collideable; -import ru.windcorp.progressia.common.collision.CollisionWall; +import ru.windcorp.progressia.common.collision.*; import ru.windcorp.progressia.common.collision.colliders.Collider.ColliderWorkspace; import ru.windcorp.progressia.common.collision.colliders.Collider.Collision; import ru.windcorp.progressia.common.util.Matrices; import ru.windcorp.progressia.common.util.Vectors; +import ru.windcorp.progressia.common.world.block.BlockFace; -class AABBWithAABBCollider { +class AABBoidCollider { static Collider.Collision computeModelCollision( Collideable aBody, Collideable bBody, - AABB aModel, AABB bModel, + AABBoid aModel, AABBoid bModel, float tickLength, ColliderWorkspace workspace ) { Collideable obstacleBody = bBody; Collideable colliderBody = aBody; - AABB obstacleModel = bModel; - AABB colliderModel = aModel; + AABBoid obstacleModel = bModel; + AABBoid colliderModel = aModel; Collision result = null; @@ -32,7 +31,8 @@ class AABBWithAABBCollider { computeCollisionVelocity(collisionVelocity, obstacleBody, colliderBody); // For every wall of collision space - for (CollisionWall wall : originCollisionSpace.getFaces()) { + for (int i = 0; i < BlockFace.BLOCK_FACE_COUNT; ++i) { + Wall wall = originCollisionSpace.getWall(i); Collision collision = computeWallCollision( wall, colliderModel, @@ -80,12 +80,21 @@ class AABBWithAABBCollider { Vectors.release(colliderVelocity); } - private static AABB createOriginCollisionSpace(AABB obstacle, AABB collider, AABB output) { - output.setOrigin(obstacle.getOrigin()); + private static AABB createOriginCollisionSpace(AABBoid obstacle, AABBoid collider, AABB output) { + Vec3 obstacleOrigin = Vectors.grab3(); + Vec3 obstacleSize = Vectors.grab3(); + Vec3 colliderSize = Vectors.grab3(); - Vec3 size = Vectors.grab3().set(obstacle.getSize()).add(collider.getSize()); - output.setSize(size); - Vectors.release(size); + obstacle.getOrigin(obstacleOrigin); + output.setOrigin(obstacleOrigin); + + obstacle.getSize(obstacleSize); + collider.getSize(colliderSize); + output.setSize(obstacleSize.add(colliderSize)); + + Vectors.release(obstacleOrigin); + Vectors.release(obstacleSize); + Vectors.release(colliderSize); return output; } @@ -134,27 +143,34 @@ class AABBWithAABBCollider { * If all conditions are satisfied, then the moment of impact is t0 + t. */ private static Collision computeWallCollision( - CollisionWall obstacleWall, - AABB colliderModel, + Wall obstacleWall, + AABBoid colliderModel, Vec3 collisionVelocity, float tickLength, ColliderWorkspace workspace, Collideable aBody, Collideable bBody ) { - Vec3 w = obstacleWall.getWidth(); - Vec3 h = obstacleWall.getHeight(); + Vec3 w = Vectors.grab3(); + Vec3 h = Vectors.grab3(); Vec3 v = Vectors.grab3(); Mat3 m = Matrices.grab3(); // The matrix [w h -v] Vec3 r = Vectors.grab3(); + Vec3 r_line = Vectors.grab3(); + Vec3 r_wall = Vectors.grab3(); Vec3 xyt = Vectors.grab3(); try { + obstacleWall.getWidth(w); + obstacleWall.getHeight(h); + v.set(collisionVelocity); if (isExiting(v, w, h)) { return null; } - r.set(colliderModel.getOrigin()).sub(obstacleWall.getOrigin()); + obstacleWall.getOrigin(r_wall); + colliderModel.getOrigin(r_line); + r.set(r_line).sub(r_wall); m.c0(w).c1(h).c2(v.negate()); if (Math.abs(m.det()) < 1e-6) { @@ -179,9 +195,13 @@ class AABBWithAABBCollider { return workspace.grab().set(aBody, bBody, obstacleWall, t); } finally { + Vectors.release(w); + Vectors.release(h); Vectors.release(v); - Vectors.release(r); Matrices.release(m); + Vectors.release(r); + Vectors.release(r_line); + Vectors.release(r_wall); Vectors.release(xyt); } } @@ -193,6 +213,6 @@ class AABBWithAABBCollider { return result; } - private AABBWithAABBCollider() {} + private AABBoidCollider() {} } diff --git a/src/main/java/ru/windcorp/progressia/common/collision/colliders/Collider.java b/src/main/java/ru/windcorp/progressia/common/collision/colliders/Collider.java index 74bcc2c..2e6b591 100644 --- a/src/main/java/ru/windcorp/progressia/common/collision/colliders/Collider.java +++ b/src/main/java/ru/windcorp/progressia/common/collision/colliders/Collider.java @@ -6,14 +6,10 @@ import java.util.List; import org.apache.logging.log4j.LogManager; import glm.vec._3.Vec3; -import ru.windcorp.progressia.common.collision.AABB; -import ru.windcorp.progressia.common.collision.Collideable; -import ru.windcorp.progressia.common.collision.CollisionClock; -import ru.windcorp.progressia.common.collision.CollisionModel; -import ru.windcorp.progressia.common.collision.CollisionWall; -import ru.windcorp.progressia.common.collision.CompoundCollisionModel; +import ru.windcorp.progressia.common.collision.*; import ru.windcorp.progressia.common.util.LowOverheadCache; import ru.windcorp.progressia.common.util.Vectors; +import ru.windcorp.progressia.common.world.WorldData; public class Collider { @@ -21,7 +17,7 @@ public class Collider { public static void performCollisions( List colls, - CollisionClock clock, + WorldData world, float tickLength, ColliderWorkspace workspace ) { @@ -42,7 +38,7 @@ public class Collider { if (firstCollision == null) { break; } else { - collide(firstCollision, colls, clock, tickLength, workspace); + collide(firstCollision, colls, world, tickLength, workspace); workspace.release(firstCollision); collisionCount++; @@ -50,7 +46,7 @@ public class Collider { } } - advanceTime(colls, clock, tickLength); + advanceTime(colls, world, tickLength); } private static Collision getFirstCollision( @@ -108,10 +104,10 @@ public class Collider { float tickLength, ColliderWorkspace workspace ) { - if (aModel instanceof AABB && bModel instanceof AABB) { - return AABBWithAABBCollider.computeModelCollision( + if (aModel instanceof AABBoid && bModel instanceof AABBoid) { /*replace AABB with AABBoid where makes sense, also add TranslatedAABB support in TestAABBRenderer*/ + return AABBoidCollider.computeModelCollision( aBody, bBody, - (AABB) aModel, (AABB) bModel, + (AABBoid) aModel, (AABBoid) bModel, tickLength, workspace ); @@ -144,11 +140,11 @@ public class Collider { Collision collision, Collection colls, - CollisionClock clock, + WorldData world, float tickLength, ColliderWorkspace workspace ) { - advanceTime(colls, clock, collision.time); + advanceTime(colls, world, collision.time); boolean doNotHandle = false; @@ -237,7 +233,7 @@ public class Collider { Vec3 du_a = Vectors.grab3(); Vec3 du_b = Vectors.grab3(); - n.set(collision.wall.getWidth()).cross(collision.wall.getHeight()).normalize(); + n.set(collision.wallWidth).cross(collision.wallHeight).normalize(); collision.a.getCollideableVelocity(v_a); collision.b.getCollideableVelocity(v_b); @@ -306,10 +302,10 @@ public class Collider { private static void advanceTime( Collection colls, - CollisionClock clock, + WorldData world, float step ) { - clock.advanceTime(step); + world.advanceTime(step); Vec3 tmp = Vectors.grab3(); @@ -342,7 +338,9 @@ public class Collider { static class Collision { public Collideable a; public Collideable b; - public final CollisionWall wall = new CollisionWall(0, 0, 0, 0, 0, 0, 0, 0, 0); + + public final Vec3 wallWidth = new Vec3(); + public final Vec3 wallHeight = new Vec3(); /** * Time offset from the start of the tick. @@ -350,12 +348,15 @@ public class Collider { */ public float time; - public Collision set(Collideable a, Collideable b, CollisionWall wall, float time) { + public Collision set( + Collideable a, Collideable b, + Wall wall, + float time + ) { this.a = a; this.b = b; - this.wall.getOrigin().set(wall.getOrigin()); - this.wall.getWidth().set(wall.getWidth()); - this.wall.getHeight().set(wall.getHeight()); + wall.getWidth(wallWidth); + wall.getHeight(wallHeight); this.time = time; return this; 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 489bf13..7cc3623 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/Vectors.java +++ b/src/main/java/ru/windcorp/progressia/common/util/Vectors.java @@ -30,6 +30,19 @@ import glm.vec._4.i.Vec4i; */ public class Vectors { + public static final Vec2 ZERO_2 = new Vec2 (0, 0); + public static final Vec2i ZERO_2i = new Vec2i(0, 0); + public static final Vec3 ZERO_3 = new Vec3 (0, 0, 0); + public static final Vec3i ZERO_3i = new Vec3i(0, 0, 0); + public static final Vec4 ZERO_4 = new Vec4 (0, 0, 0, 0); + public static final Vec4i ZERO_4i = new Vec4i(0, 0, 0, 0); + public static final Vec2 UNIT_2 = new Vec2 (1, 1); + public static final Vec2i UNIT_2i = new Vec2i(1, 1); + public static final Vec3 UNIT_3 = new Vec3 (1, 1, 1); + public static final Vec3i UNIT_3i = new Vec3i(1, 1, 1); + public static final Vec4 UNIT_4 = new Vec4 (1, 1, 1, 1); + public static final Vec4i UNIT_4i = new Vec4i(1, 1, 1, 1); + private static final LowOverheadCache VEC3IS = new LowOverheadCache<>(Vec3i::new); diff --git a/src/main/java/ru/windcorp/progressia/common/world/WorldData.java b/src/main/java/ru/windcorp/progressia/common/world/WorldData.java index 6440709..b403ac5 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/WorldData.java +++ b/src/main/java/ru/windcorp/progressia/common/world/WorldData.java @@ -42,6 +42,8 @@ public class WorldData { private final Collection entities = Collections.unmodifiableCollection(entitiesById.valueCollection()); + private float time = 0; + public WorldData() { final int size = 1; @@ -96,4 +98,16 @@ public class WorldData { return entities; } + public float getTime() { + return time; + } + + public void advanceTime(float change) { + this.time += change; + } + +// public CollisionModel getCollisionModelOfBlock(Vec3i blockInWorld) { +// Vec3i +// } + } diff --git a/src/main/java/ru/windcorp/progressia/test/AABBRenderer.java b/src/main/java/ru/windcorp/progressia/test/AABBRenderer.java deleted file mode 100644 index e9a6b7b..0000000 --- a/src/main/java/ru/windcorp/progressia/test/AABBRenderer.java +++ /dev/null @@ -1,35 +0,0 @@ -package ru.windcorp.progressia.test; - -import ru.windcorp.progressia.client.graphics.model.Shape; -import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper; -import ru.windcorp.progressia.client.graphics.model.Shapes; -import ru.windcorp.progressia.client.graphics.texture.Texture; -import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram; -import ru.windcorp.progressia.common.collision.AABB; -import ru.windcorp.progressia.common.collision.CollisionModel; -import ru.windcorp.progressia.common.collision.CompoundCollisionModel; - -public class AABBRenderer { - - private static final Shape CUBE = new Shapes.PppBuilder(WorldRenderProgram.getDefault(), (Texture) null).setColorMultiplier(1.0f, 0.7f, 0.2f).create(); - - public static void renderAABB(AABB aabb, ShapeRenderHelper helper) { - helper.pushTransform().translate(aabb.getOrigin()).scale(aabb.getSize()); - CUBE.render(helper); - helper.popTransform(); - } - - public static void renderAABBsInCompound( - CompoundCollisionModel model, - ShapeRenderHelper helper - ) { - for (CollisionModel part : model.getModels()) { - if (part instanceof CompoundCollisionModel) { - renderAABBsInCompound((CompoundCollisionModel) part, helper); - } else if (part instanceof AABB) { - renderAABB((AABB) part, helper); - } - } - } - -} diff --git a/src/main/java/ru/windcorp/progressia/test/CollisionModelRenderer.java b/src/main/java/ru/windcorp/progressia/test/CollisionModelRenderer.java new file mode 100644 index 0000000..15463d4 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/CollisionModelRenderer.java @@ -0,0 +1,61 @@ +package ru.windcorp.progressia.test; + +import glm.mat._4.Mat4; +import glm.vec._3.Vec3; +import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.client.graphics.model.Shape; +import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper; +import ru.windcorp.progressia.client.graphics.model.Shapes; +import ru.windcorp.progressia.client.graphics.texture.Texture; +import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram; +import ru.windcorp.progressia.common.collision.AABBoid; +import ru.windcorp.progressia.common.collision.CollisionModel; +import ru.windcorp.progressia.common.collision.CompoundCollisionModel; +import ru.windcorp.progressia.common.util.Vectors; + +public class CollisionModelRenderer { + + private static final Shape CUBE = new Shapes.PppBuilder(WorldRenderProgram.getDefault(), (Texture) null).setColorMultiplier(1.0f, 0.7f, 0.2f).create(); + private static final Shape CUBE_GRAY = new Shapes.PppBuilder(WorldRenderProgram.getDefault(), (Texture) null).setColorMultiplier(0.5f, 0.5f, 0.5f).create(); + + public static void renderCollisionModel(CollisionModel model, ShapeRenderHelper helper) { + if (model instanceof AABBoid) { + renderAABBoid((AABBoid) model, helper); + } else if (model instanceof CompoundCollisionModel) { + renderCompound((CompoundCollisionModel) model, helper); + } else { + // Ignore silently + } + } + + private static void renderAABBoid(AABBoid aabb, ShapeRenderHelper helper) { + Mat4 mat = helper.pushTransform(); + Vec3 tmp = Vectors.grab3(); + + aabb.getOrigin(tmp); + mat.translate(tmp); + aabb.getSize(tmp); + mat.scale(tmp); + + Vectors.release(tmp); + + CUBE.render(helper); + helper.popTransform(); + } + + private static void renderCompound( + CompoundCollisionModel model, + ShapeRenderHelper helper + ) { + for (CollisionModel part : model.getModels()) { + renderCollisionModel(part, helper); + } + } + + public static void renderBlock(Vec3i coords, ShapeRenderHelper helper) { + helper.pushTransform().translate(coords.x, coords.y, coords.z); + CUBE_GRAY.render(helper); + helper.popTransform(); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/TestEntityDataStatie.java b/src/main/java/ru/windcorp/progressia/test/TestEntityDataStatie.java index a58ed35..4c14053 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestEntityDataStatie.java +++ b/src/main/java/ru/windcorp/progressia/test/TestEntityDataStatie.java @@ -2,6 +2,7 @@ package ru.windcorp.progressia.test; import ru.windcorp.progressia.common.collision.AABB; import ru.windcorp.progressia.common.collision.CompoundCollisionModel; +import ru.windcorp.progressia.common.collision.TranslatedAABB; import ru.windcorp.progressia.common.state.IntStateField; import ru.windcorp.progressia.common.world.entity.EntityData; @@ -14,7 +15,7 @@ public class TestEntityDataStatie extends EntityData { super("Test", "Statie"); setCollisionModel(new CompoundCollisionModel( new AABB(0, 0, 0, 1, 1, 1 ), - new AABB(0, 0, 0.7f, 0.6f, 0.6f, 0.6f) + new TranslatedAABB(new AABB(0, 0, 0.7f, 0.6f, 0.6f, 0.6f), 0, 0, 1) )); setSizeNow(16); } From 9c894215f8f88b8e2114047a48cbb48204f2ce9d Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Fri, 13 Nov 2020 21:45:05 +0300 Subject: [PATCH 2/6] Added collisions with world --- .../client/graphics/world/LayerWorld.java | 4 +- .../progressia/common/collision/AABB.java | 2 + .../collision/CollisionPathComputer.java | 79 ++++++++++++++++ .../collision/CompoundCollisionModel.java | 6 +- .../collision/WorldCollisionHelper.java | 94 +++++++++++++++++++ .../common/collision/colliders/Collider.java | 63 +++++++++---- .../progressia/common/world/WorldData.java | 17 +++- .../common/world/block/BlockData.java | 6 ++ .../windcorp/progressia/test/TestContent.java | 8 +- .../progressia/test/TestEntityDataStatie.java | 7 +- 10 files changed, 253 insertions(+), 33 deletions(-) create mode 100644 src/main/java/ru/windcorp/progressia/common/collision/CollisionPathComputer.java create mode 100644 src/main/java/ru/windcorp/progressia/common/collision/WorldCollisionHelper.java 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 5f74963..d3ce0f4 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 @@ -124,7 +124,7 @@ public class LayerWorld extends Layer { private final Collider.ColliderWorkspace tmp_colliderWorkspace = new Collider.ColliderWorkspace(); private final List tmp_collideableList = new ArrayList<>(); - private static final boolean RENDER_COLLISION_MODELS = true; + private static final boolean RENDER_COLLISION_MODELS = false; private void tmp_doEveryFrame() { try { @@ -136,7 +136,7 @@ public class LayerWorld extends Layer { } } catch (Throwable e) { e.printStackTrace(); - System.out.println("OLEGSHA is to blame. Tell him he vry stupiDD!!"); + System.err.println("OLEGSHA is to blame. Tell him he vry stupiDD!!"); System.exit(31337); } } diff --git a/src/main/java/ru/windcorp/progressia/common/collision/AABB.java b/src/main/java/ru/windcorp/progressia/common/collision/AABB.java index 9b0fd31..e141673 100644 --- a/src/main/java/ru/windcorp/progressia/common/collision/AABB.java +++ b/src/main/java/ru/windcorp/progressia/common/collision/AABB.java @@ -42,6 +42,8 @@ public class AABB implements AABBoid { } + public static final AABB UNIT_CUBE = new AABB(0, 0, 0, 1, 1, 1); + private final Wall[] walls = new Wall[] { new AABBWallImpl(-0.5f, -0.5f, +0.5f, +1, 0, 0, 0, +1, 0), // Top new AABBWallImpl(-0.5f, -0.5f, -0.5f, 0, +1, 0, +1, 0, 0), // Bottom diff --git a/src/main/java/ru/windcorp/progressia/common/collision/CollisionPathComputer.java b/src/main/java/ru/windcorp/progressia/common/collision/CollisionPathComputer.java new file mode 100644 index 0000000..eda8e47 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/collision/CollisionPathComputer.java @@ -0,0 +1,79 @@ +package ru.windcorp.progressia.common.collision; + +import java.util.function.Consumer; + +import glm.vec._3.Vec3; +import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.common.util.Vectors; + +import static java.lang.Math.*; + +public class CollisionPathComputer { + + public static void forEveryBlockInCollisionPath( + Collideable coll, + float maxTime, + Consumer action + ) { + Vec3 displacement = Vectors.grab3(); + coll.getCollideableVelocity(displacement); + displacement.mul(maxTime); + + handleModel(coll.getCollisionModel(), displacement, action); + + Vectors.release(displacement); + } + + private static void handleModel( + CollisionModel model, + Vec3 displacement, + Consumer action + ) { + if (model instanceof CompoundCollisionModel) { + for (CollisionModel subModel : ((CompoundCollisionModel) model).getModels()) { + handleModel(subModel, displacement, action); + } + } else if (model instanceof AABBoid) { + handleAABBoid((AABBoid) model, displacement, action); + } else { + throw new RuntimeException("not supported"); + } + } + + private static void handleAABBoid(AABBoid model, Vec3 displacement, Consumer action) { + Vec3 size = Vectors.grab3(); + Vec3 origin = Vectors.grab3(); + + model.getOrigin(origin); + model.getSize(size); + + origin.mul(2).sub(size).div(2); // Subtract 0.5*size + + Vec3i pos = Vectors.grab3i(); + + for ( + pos.x = (int) floor(origin.x + min(0, size.x) + min(0, displacement.x)); + pos.x <= (int) ceil(origin.x + max(0, size.x) + max(0, displacement.x)); + pos.x += 1 + ) { + for ( + pos.y = (int) floor(origin.y + min(0, size.y) + min(0, displacement.y)); + pos.y <= (int) ceil(origin.y + max(0, size.y) + max(0, displacement.y)); + pos.y += 1 + ) { + for ( + pos.z = (int) floor(origin.z + min(0, size.z) + min(0, displacement.z)); + pos.z <= (int) ceil(origin.z + max(0, size.z) + max(0, displacement.z)); + pos.z += 1 + ) { + action.accept(pos); + } + } + } + + Vectors.release(origin); + Vectors.release(size); + Vectors.release(pos); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/common/collision/CompoundCollisionModel.java b/src/main/java/ru/windcorp/progressia/common/collision/CompoundCollisionModel.java index 2cf4572..ab5e766 100644 --- a/src/main/java/ru/windcorp/progressia/common/collision/CompoundCollisionModel.java +++ b/src/main/java/ru/windcorp/progressia/common/collision/CompoundCollisionModel.java @@ -8,9 +8,9 @@ import glm.vec._3.Vec3; public class CompoundCollisionModel implements CollisionModel { - private final Collection models; + private final Collection models; - public CompoundCollisionModel(Collection models) { + public CompoundCollisionModel(Collection models) { this.models = models; } @@ -18,7 +18,7 @@ public class CompoundCollisionModel implements CollisionModel { this(ImmutableList.copyOf(models)); } - public Collection getModels() { + public Collection getModels() { return models; } diff --git a/src/main/java/ru/windcorp/progressia/common/collision/WorldCollisionHelper.java b/src/main/java/ru/windcorp/progressia/common/collision/WorldCollisionHelper.java new file mode 100644 index 0000000..ebf2c0b --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/collision/WorldCollisionHelper.java @@ -0,0 +1,94 @@ +package ru.windcorp.progressia.common.collision; + +import java.util.ArrayList; +import java.util.Collection; + +import glm.vec._3.Vec3; +import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.common.util.LowOverheadCache; +import ru.windcorp.progressia.common.world.WorldData; + +public class WorldCollisionHelper { + + private final Collideable collideable = new Collideable() { + @Override + public boolean onCollision(Collideable other) { + return false; + } + + @Override + public void moveAsCollideable(Vec3 displacement) { + // Ignore + assert displacement.length() < 1e-3f; + } + + @Override + public CollisionModel getCollisionModel() { + return WorldCollisionHelper.this.model; + } + + @Override + public float getCollisionMass() { + return Float.POSITIVE_INFINITY; + } + + @Override + public void getCollideableVelocity(Vec3 output) { + output.set(0); + } + + @Override + public void changeVelocityOnCollision(Vec3 velocityChange) { + // Ignore + assert velocityChange.length() < 1e-3f; + } + }; + + private final Collection activeBlockModels = new ArrayList<>(); + private final CollisionModel model = new CompoundCollisionModel(activeBlockModels); + private final LowOverheadCache blockModelCache = new LowOverheadCache<>(TranslatedAABB::new); + + /** + * Changes the state of this helper's {@link #getCollideable()} so it is ready to adequately handle + * collisions with the {@code collideable} that might happen in the next {@code maxTime} seconds. + * This helper is only valid for checking collisions with the given Collideable and only within + * the given time limit. + * @param collideable the {@link Collideable} that collisions will be checked against + * @param maxTime maximum collision time + */ + public void tuneToCollideable(WorldData world, Collideable collideable, float maxTime) { + activeBlockModels.forEach(blockModelCache::release); + activeBlockModels.clear(); + CollisionPathComputer.forEveryBlockInCollisionPath( + collideable, + maxTime, + v -> addModel(world.getCollisionModelOfBlock(v), v) + ); + } + + private void addModel(CollisionModel model, Vec3i pos) { + if (model == null) { + // Ignore + } else if (model instanceof AABBoid) { + addAABBoidModel((AABBoid) model, pos); + } else if (model instanceof CompoundCollisionModel) { + for (CollisionModel subModel : ((CompoundCollisionModel) model).getModels()) { + addModel(subModel, pos); + } + } else { + throw new RuntimeException("not supported"); + } + } + + private void addAABBoidModel(AABBoid model, Vec3i pos) { + TranslatedAABB translator = blockModelCache.grab(); + translator.setParent(model); + translator.setTranslation(pos.x, pos.y, pos.z); + activeBlockModels.add(translator); + } + + public Collideable getCollideable() { + return collideable; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/common/collision/colliders/Collider.java b/src/main/java/ru/windcorp/progressia/common/collision/colliders/Collider.java index 2e6b591..8fdbc90 100644 --- a/src/main/java/ru/windcorp/progressia/common/collision/colliders/Collider.java +++ b/src/main/java/ru/windcorp/progressia/common/collision/colliders/Collider.java @@ -33,7 +33,7 @@ public class Collider { return; } - Collision firstCollision = getFirstCollision(colls, tickLength, workspace); + Collision firstCollision = getFirstCollision(colls, tickLength, world, workspace); if (firstCollision == null) { break; @@ -52,39 +52,43 @@ public class Collider { private static Collision getFirstCollision( List colls, float tickLength, + WorldData world, ColliderWorkspace workspace ) { Collision result = null; + Collideable worldColl = workspace.worldCollisionHelper.getCollideable(); // For every pair of colls for (int i = 0; i < colls.size(); ++i) { Collideable a = colls.get(i); + tuneWorldCollisionHelper(a, tickLength, world, workspace); + + result = workspace.updateLatestCollision( + result, + getCollision(a, worldColl, tickLength, workspace) + ); + for (int j = i + 1; j < colls.size(); ++j) { Collideable b = colls.get(j); - Collision collision = getCollision(a, b, tickLength, workspace); - - // Update result - if (collision != null) { - Collision second; - - if (result == null || collision.time < result.time) { - second = result; - result = collision; - } else { - second = collision; - } - - // Release Collision that is no longer used - if (second != null) workspace.release(second); - } + result = workspace.updateLatestCollision(result, collision); } } return result; } + private static void tuneWorldCollisionHelper( + Collideable coll, + float tickLength, + WorldData world, + ColliderWorkspace workspace + ) { + WorldCollisionHelper wch = workspace.worldCollisionHelper; + wch.tuneToCollideable(world, coll, tickLength); + } + static Collision getCollision( Collideable a, Collideable b, @@ -104,7 +108,7 @@ public class Collider { float tickLength, ColliderWorkspace workspace ) { - if (aModel instanceof AABBoid && bModel instanceof AABBoid) { /*replace AABB with AABBoid where makes sense, also add TranslatedAABB support in TestAABBRenderer*/ + if (aModel instanceof AABBoid && bModel instanceof AABBoid) { return AABBoidCollider.computeModelCollision( aBody, bBody, (AABBoid) aModel, (AABBoid) bModel, @@ -324,6 +328,8 @@ public class Collider { new LowOverheadCache<>(Collision::new); AABB dummyAABB = new AABB(0, 0, 0, 1, 1, 1); + + WorldCollisionHelper worldCollisionHelper = new WorldCollisionHelper(); Collision grab() { return collisionCache.grab(); @@ -333,6 +339,27 @@ public class Collider { collisionCache.release(object); } + Collision updateLatestCollision(Collision a, Collision b) { + if (a == null) { + return b; // may be null + } else if (b == null) { + return a; + } + + Collision first, second; + + if (a.time > b.time) { + first = b; + second = a; + } else { + first = a; + second = b; + } + + release(second); + return first; + } + } static class Collision { diff --git a/src/main/java/ru/windcorp/progressia/common/world/WorldData.java b/src/main/java/ru/windcorp/progressia/common/world/WorldData.java index b403ac5..6584884 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/WorldData.java +++ b/src/main/java/ru/windcorp/progressia/common/world/WorldData.java @@ -24,8 +24,10 @@ import glm.vec._3.i.Vec3i; import gnu.trove.impl.sync.TSynchronizedLongObjectMap; import gnu.trove.map.TLongObjectMap; import gnu.trove.map.hash.TLongObjectHashMap; +import ru.windcorp.progressia.common.collision.CollisionModel; import ru.windcorp.progressia.common.util.CoordinatePacker; import ru.windcorp.progressia.common.util.Vectors; +import ru.windcorp.progressia.common.world.block.BlockData; import ru.windcorp.progressia.common.world.entity.EntityData; public class WorldData { @@ -106,8 +108,17 @@ public class WorldData { this.time += change; } -// public CollisionModel getCollisionModelOfBlock(Vec3i blockInWorld) { -// Vec3i -// } + public CollisionModel getCollisionModelOfBlock(Vec3i blockInWorld) { + ChunkData chunk = getChunkByBlock(blockInWorld); + if (chunk == null) return null; + + Vec3i blockInChunk = Vectors.grab3i(); + Coordinates.convertInWorldToInChunk(blockInWorld, blockInChunk); + BlockData block = chunk.getBlock(blockInChunk); + Vectors.release(blockInChunk); + + if (block == null) return null; + return block.getCollisionModel(); + } } diff --git a/src/main/java/ru/windcorp/progressia/common/world/block/BlockData.java b/src/main/java/ru/windcorp/progressia/common/world/block/BlockData.java index 5bcbd50..e1ea62d 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/block/BlockData.java +++ b/src/main/java/ru/windcorp/progressia/common/world/block/BlockData.java @@ -17,6 +17,8 @@ *******************************************************************************/ package ru.windcorp.progressia.common.world.block; +import ru.windcorp.progressia.common.collision.AABB; +import ru.windcorp.progressia.common.collision.CollisionModel; import ru.windcorp.progressia.common.util.Namespaced; public class BlockData extends Namespaced { @@ -24,5 +26,9 @@ public class BlockData extends Namespaced { public BlockData(String namespace, String name) { super(namespace, name); } + + public CollisionModel getCollisionModel() { + return AABB.UNIT_CUBE; + } } diff --git a/src/main/java/ru/windcorp/progressia/test/TestContent.java b/src/main/java/ru/windcorp/progressia/test/TestContent.java index 3c890bc..988e4f8 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestContent.java +++ b/src/main/java/ru/windcorp/progressia/test/TestContent.java @@ -14,6 +14,7 @@ import ru.windcorp.progressia.client.world.block.*; import ru.windcorp.progressia.client.world.entity.*; import ru.windcorp.progressia.client.world.tile.*; import ru.windcorp.progressia.common.collision.AABB; +import ru.windcorp.progressia.common.collision.CollisionModel; import ru.windcorp.progressia.common.comms.controls.*; import ru.windcorp.progressia.common.state.StatefulObjectRegistry.Factory; import ru.windcorp.progressia.common.world.ChunkData; @@ -41,7 +42,12 @@ public class TestContent { } private static void registerBlocks() { - register(new BlockData("Test", "Air")); + register(new BlockData("Test", "Air") { + @Override + public CollisionModel getCollisionModel() { + return null; + } + }); register(new BlockRenderNone("Test", "Air")); register(new BlockLogic("Test", "Air")); diff --git a/src/main/java/ru/windcorp/progressia/test/TestEntityDataStatie.java b/src/main/java/ru/windcorp/progressia/test/TestEntityDataStatie.java index 4c14053..19d47c9 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestEntityDataStatie.java +++ b/src/main/java/ru/windcorp/progressia/test/TestEntityDataStatie.java @@ -1,8 +1,6 @@ package ru.windcorp.progressia.test; import ru.windcorp.progressia.common.collision.AABB; -import ru.windcorp.progressia.common.collision.CompoundCollisionModel; -import ru.windcorp.progressia.common.collision.TranslatedAABB; import ru.windcorp.progressia.common.state.IntStateField; import ru.windcorp.progressia.common.world.entity.EntityData; @@ -13,10 +11,7 @@ public class TestEntityDataStatie extends EntityData { public TestEntityDataStatie() { super("Test", "Statie"); - setCollisionModel(new CompoundCollisionModel( - new AABB(0, 0, 0, 1, 1, 1 ), - new TranslatedAABB(new AABB(0, 0, 0.7f, 0.6f, 0.6f, 0.6f), 0, 0, 1) - )); + setCollisionModel(new AABB(0, 0, 0, 1, 1, 1)); setSizeNow(16); } From 154cc0a3b830d522ef99932641325c3dab0d57a1 Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Sat, 14 Nov 2020 13:49:35 +0300 Subject: [PATCH 3/6] Added gravity and refactored player controls - Added gravity (still testing) - Two modes: realistic (9.8 m/s^2) and Minecraft (32 m/s^2) - Switch with G - Changing (0; 0; 0) rebound to H - Added walking controls - Minecraft-style - WIP - LayerTestGUI now displays dev options - Added Units --- .../progressia/client/ClientState.java | 2 +- .../client/graphics/gui/LayerTestGUI.java | 125 -------- .../client/graphics/world/Camera.java | 4 + .../client/graphics/world/LayerWorld.java | 169 ++--------- .../ru/windcorp/progressia/common/Units.java | 56 ++++ .../progressia/test/LayerTestGUI.java | 155 ++++++++++ .../windcorp/progressia/test/TestContent.java | 2 +- .../progressia/test/TestPlayerControls.java | 270 ++++++++++++++++++ 8 files changed, 516 insertions(+), 267 deletions(-) delete mode 100755 src/main/java/ru/windcorp/progressia/client/graphics/gui/LayerTestGUI.java create mode 100644 src/main/java/ru/windcorp/progressia/common/Units.java create mode 100755 src/main/java/ru/windcorp/progressia/test/LayerTestGUI.java create mode 100644 src/main/java/ru/windcorp/progressia/test/TestPlayerControls.java diff --git a/src/main/java/ru/windcorp/progressia/client/ClientState.java b/src/main/java/ru/windcorp/progressia/client/ClientState.java index 84c26a2..b812907 100644 --- a/src/main/java/ru/windcorp/progressia/client/ClientState.java +++ b/src/main/java/ru/windcorp/progressia/client/ClientState.java @@ -3,10 +3,10 @@ package ru.windcorp.progressia.client; import ru.windcorp.progressia.client.comms.localhost.LocalServerCommsChannel; import ru.windcorp.progressia.client.graphics.GUI; import ru.windcorp.progressia.client.graphics.flat.LayerTestUI; -import ru.windcorp.progressia.client.graphics.gui.LayerTestGUI; import ru.windcorp.progressia.client.graphics.world.LayerWorld; import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.server.ServerState; +import ru.windcorp.progressia.test.LayerTestGUI; public class ClientState { 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 deleted file mode 100755 index 6a74d96..0000000 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/LayerTestGUI.java +++ /dev/null @@ -1,125 +0,0 @@ -/******************************************************************************* - * Progressia - * Copyright (C) 2020 Wind Corporation - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *******************************************************************************/ -package ru.windcorp.progressia.client.graphics.gui; - -import com.google.common.eventbus.Subscribe; -import glm.vec._2.i.Vec2i; -import org.lwjgl.glfw.GLFW; -import ru.windcorp.progressia.client.graphics.Colors; -import ru.windcorp.progressia.client.graphics.flat.RenderTarget; -import ru.windcorp.progressia.client.graphics.font.Font; -import ru.windcorp.progressia.client.graphics.gui.event.HoverEvent; -import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign; -import ru.windcorp.progressia.client.graphics.gui.layout.LayoutVertical; -import ru.windcorp.progressia.client.graphics.input.KeyEvent; -import ru.windcorp.progressia.client.localization.Localizer; -import ru.windcorp.progressia.client.localization.MutableString; -import ru.windcorp.progressia.client.localization.MutableStringLocalized; - -public class LayerTestGUI extends GUILayer { - - private static class DebugComponent extends Component { - private final int color; - - public DebugComponent(String name, Vec2i size, int color) { - super(name); - this.color = color; - - setPreferredSize(size); - - addListener(new Object() { - @Subscribe - public void onHoverChanged(HoverEvent e) { - requestReassembly(); - } - }); - - addListener(KeyEvent.class, this::onClicked); - } - - private boolean onClicked(KeyEvent event) { - if (!event.isMouse()) { - return false; - } else if (event.isPress() && event.isLeftMouseButton()) { - System.out.println("You pressed a Component!"); - } - return true; - } - - @Override - protected void assembleSelf(RenderTarget target) { - target.fill(getX(), getY(), getWidth(), getHeight(), Colors.BLACK); - - target.fill( - getX() + 2, getY() + 2, - getWidth() - 4, getHeight() - 4, - isHovered() ? Colors.DEBUG_YELLOW : color - ); - } - } - - public LayerTestGUI() { - super("LayerTestGui", new LayoutAlign(1, 0.75, 5)); - - Panel panel = new Panel("Alex", new LayoutVertical(5)); - - panel.addChild(new DebugComponent("Bravo", new Vec2i(200, 100), 0x44FF44)); - - Component charlie = new DebugComponent("Charlie", null, 0x222222); - charlie.setLayout(new LayoutVertical(5)); - - //Debug - Localizer.getInstance().setLanguage("ru-RU"); - MutableString epsilon = new MutableStringLocalized("Epsilon") - .addListener(() -> ((Label)charlie.getChild(0)).update()).format(34, "thirty-four"); - // These two are swapped in code due to a bug in layouts, fixing ATM - charlie.addChild( - new Label( - "Delta", - new Font().withColor(0xCCBB44).deriveShadow().deriveBold(), - "Пре-альфа!" - ) - ); - charlie.addChild( - new Label( - "Epsilon", - new Font().withColor(0x4444BB).deriveItalic(), - () -> epsilon.get().concat("\u269b") - ) - ); - panel.addChild(charlie); - - - charlie.addListener(KeyEvent.class, e -> { - if(e.isPress() && e.getKey() == GLFW.GLFW_KEY_L) { - Localizer localizer = Localizer.getInstance(); - if (localizer.getLanguage().equals("ru-RU")) { - localizer.setLanguage("en-US"); - } else { - localizer.setLanguage("ru-RU"); - } - return true; - } return false; - }); - charlie.setFocusable(true); - charlie.takeFocus(); - - getRoot().addChild(panel); - } - -} 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 ab99777..56748f9 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 @@ -271,6 +271,10 @@ public class Camera { currentModeIndex++; } } + + public int getCurrentModeIndex() { + return currentModeIndex; + } public float getLastAnchorYaw() { return lastAnchorYaw; 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 d3ce0f4..fb7557e 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 @@ -20,41 +20,27 @@ package ru.windcorp.progressia.client.graphics.world; import java.util.ArrayList; import java.util.List; -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.ClientState; 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; -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.Units; import ru.windcorp.progressia.common.collision.Collideable; import ru.windcorp.progressia.common.collision.colliders.Collider; -import ru.windcorp.progressia.common.util.FloatMathUtils; -import ru.windcorp.progressia.common.util.Vectors; import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.test.CollisionModelRenderer; +import ru.windcorp.progressia.test.TestPlayerControls; public class LayerWorld extends Layer { - private final Mat3 angMat = new Mat3(); - - private int movementForward = 0; - private int movementRight = 0; - private int movementUp = 0; - private final WorldRenderHelper helper = new WorldRenderHelper(); private final Client client; private final InputBasedControls inputBasedControls; + private final TestPlayerControls tmp_testControls = TestPlayerControls.getInstance(); public LayerWorld(Client client) { super("World"); @@ -75,40 +61,12 @@ public class LayerWorld extends Layer { @Override protected void doRender() { - if (client.getLocalPlayer() != null) { - tmp_handleControls(); - } - Camera camera = client.getCamera(); if (camera.hasAnchor()) { renderWorld(); } } - private void tmp_handleControls() { - EntityData player = client.getLocalPlayer(); - - angMat.identity().rotateZ(player.getYaw()); - - Vec3 movement = Vectors.grab3(); - - // Horizontal and vertical max control speed - final float movementSpeed = 0.1f * 60.0f; - // (0; 1], 1 is instant change, 0 is no control authority - final float controlAuthority = 0.1f; - - movement.set(movementForward, -movementRight, 0); - if (movementForward != 0 && movementRight != 0) movement.normalize(); - angMat.mul_(movement); // bug in jglm, .mul() and mul_() are swapped - movement.z = movementUp; - movement.mul(movementSpeed); - movement.sub(player.getVelocity()); - movement.mul(controlAuthority); - player.getVelocity().add(movement); - - Vectors.release(movement); - } - private void renderWorld() { client.getCamera().apply(helper); FaceCulling.push(true); @@ -127,11 +85,16 @@ public class LayerWorld extends Layer { private static final boolean RENDER_COLLISION_MODELS = false; private void tmp_doEveryFrame() { + float tickLength = (float) GraphicsInterface.getFrameLength(); + try { - tmp_performCollisions(); + tmp_performCollisions(tickLength); + + tmp_testControls.applyPlayerControls(); for (EntityData data : this.client.getWorld().getData().getEntities()) { tmp_applyFriction(data); + tmp_applyGravity(data, tickLength); tmp_renderCollisionModel(data); } } catch (Throwable e) { @@ -147,121 +110,47 @@ public class LayerWorld extends Layer { } } - private void tmp_performCollisions() { + private void tmp_performCollisions(float tickLength) { tmp_collideableList.clear(); tmp_collideableList.addAll(this.client.getWorld().getData().getEntities()); Collider.performCollisions( tmp_collideableList, this.client.getWorld().getData(), - (float) GraphicsInterface.getFrameLength(), + tickLength, tmp_colliderWorkspace ); } private void tmp_applyFriction(EntityData entity) { - final float frictionCoeff = 1 - 1e-2f; + final float frictionCoeff = 1 - 1e-5f; entity.getVelocity().mul(frictionCoeff); } + + private void tmp_applyGravity(EntityData entity, float tickLength) { + if (ClientState.getInstance().getLocalPlayer() == entity && tmp_testControls.isFlying()) { + return; + } + + final float gravitationalAcceleration; + + if (tmp_testControls.useMinecraftGravity()) { + gravitationalAcceleration = 32f * Units.METERS_PER_SECOND_SQUARED; // plz dont sue me M$ + } else { + gravitationalAcceleration = 9.81f * Units.METERS_PER_SECOND_SQUARED; + } + entity.getVelocity().add(0, 0, -gravitationalAcceleration * tickLength); + } @Override protected void handleInput(Input input) { if (input.isConsumed()) return; - InputEvent event = input.getEvent(); - - if (event instanceof KeyEvent) { - if (onKeyEvent((KeyEvent) event)) { - input.consume(); - } - } else if (event instanceof CursorMoveEvent) { - onMouseMoved((CursorMoveEvent) event); - input.consume(); - } + tmp_testControls.handleInput(input); if (!input.isConsumed()) { inputBasedControls.handleInput(input); } } - - private boolean flag = true; - - private boolean onKeyEvent(KeyEvent event) { - if (event.isRepeat()) return false; - - int multiplier = event.isPress() ? 1 : -1; - - switch (event.getKey()) { - case GLFW.GLFW_KEY_W: - movementForward += +1 * multiplier; - break; - case GLFW.GLFW_KEY_S: - movementForward += -1 * multiplier; - break; - case GLFW.GLFW_KEY_A: - movementRight += -1 * multiplier; - break; - case GLFW.GLFW_KEY_D: - movementRight += +1 * multiplier; - break; - case GLFW.GLFW_KEY_SPACE: - movementUp += +1 * multiplier; - break; - case GLFW.GLFW_KEY_LEFT_SHIFT: - movementUp += -1 * multiplier; - break; - - case GLFW.GLFW_KEY_ESCAPE: - if (!event.isPress()) return false; - - if (flag) { - GLFW.glfwSetInputMode(GraphicsBackend.getWindowHandle(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_NORMAL); - } else { - GLFW.glfwSetInputMode(GraphicsBackend.getWindowHandle(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_DISABLED); - } - - flag = !flag; - break; - - case GLFW.GLFW_KEY_F5: - if (!event.isPress()) return false; - - if (client.getCamera().hasAnchor()) { - client.getCamera().selectNextMode(); - } - break; - - default: - return false; - } - - return true; - } - - private void onMouseMoved(CursorMoveEvent event) { - if (!flag) return; - - final float yawScale = -0.002f; - final float pitchScale = yawScale; - - EntityData player = client.getLocalPlayer(); - - 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/common/Units.java b/src/main/java/ru/windcorp/progressia/common/Units.java new file mode 100644 index 0000000..0c8348a --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/Units.java @@ -0,0 +1,56 @@ +package ru.windcorp.progressia.common; + +public class Units { + + // Base units + // We're SI. + public static final float METERS = 1; + public static final float KILOGRAMS = 1; + public static final float SECONDS = 1; + + // Length + public static final float CENTIMETERS = METERS / 100; + public static final float MILLIMETERS = METERS / 1000; + public static final float KILOMETERS = METERS * 1000; + + // Surface + public static final float SQUARE_CENTIMETERS = CENTIMETERS * CENTIMETERS; + public static final float SQUARE_METERS = METERS * METERS; + public static final float SQUARE_MILLIMETERS = MILLIMETERS * MILLIMETERS; + public static final float SQUARE_KILOMETERS = KILOMETERS * KILOMETERS; + + // Volume + public static final float CUBIC_CENTIMETERS = CENTIMETERS * CENTIMETERS * CENTIMETERS; + public static final float CUBIC_METERS = METERS * METERS * METERS; + public static final float CUBIC_MILLIMETERS = MILLIMETERS * MILLIMETERS * MILLIMETERS; + public static final float CUBIC_KILOMETERS = KILOMETERS * KILOMETERS * KILOMETERS; + + // Mass + public static final float GRAMS = KILOGRAMS / 1000; + public static final float TONNES = KILOGRAMS * 1000; + + // Density + public static final float KILOGRAMS_PER_CUBIC_METER = KILOGRAMS / CUBIC_METERS; + public static final float GRAMS_PER_CUBIC_CENTIMETER = GRAMS / CUBIC_CENTIMETERS; + + // Time + public static final float MILLISECONDS = SECONDS / 1000; + public static final float MINUTES = SECONDS * 60; + public static final float HOURS = MINUTES * 60; + public static final float DAYS = HOURS * 24; + + // Frequency + public static final float HERTZ = 1 / SECONDS; + public static final float KILOHERTZ = HERTZ * 1000; + + // Velocity + public static final float METERS_PER_SECOND = METERS / SECONDS; + public static final float KILOMETERS_PER_HOUR = KILOMETERS / HOURS; + + // Acceleration + public static final float METERS_PER_SECOND_SQUARED = METERS_PER_SECOND / SECONDS; + + // Force + public static final float NEWTONS = METERS_PER_SECOND_SQUARED * KILOGRAMS; + +} diff --git a/src/main/java/ru/windcorp/progressia/test/LayerTestGUI.java b/src/main/java/ru/windcorp/progressia/test/LayerTestGUI.java new file mode 100755 index 0000000..2ae9828 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/LayerTestGUI.java @@ -0,0 +1,155 @@ +/******************************************************************************* + * Progressia + * Copyright (C) 2020 Wind Corporation + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *******************************************************************************/ +package ru.windcorp.progressia.test; + +import java.util.ArrayList; +import java.util.Collection; + +import ru.windcorp.progressia.client.ClientState; +import ru.windcorp.progressia.client.graphics.font.Font; +import ru.windcorp.progressia.client.graphics.gui.GUILayer; +import ru.windcorp.progressia.client.graphics.gui.Label; +import ru.windcorp.progressia.client.graphics.gui.Panel; +import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign; +import ru.windcorp.progressia.client.graphics.gui.layout.LayoutVertical; + +public class LayerTestGUI extends GUILayer { + + public LayerTestGUI() { + super("LayerTestGui", new LayoutAlign(0, 1, 5)); + + Panel panel = new Panel("ControlDisplays", new LayoutVertical(5)); + + Collection