diff --git a/src/main/java/ru/windcorp/progressia/client/world/ChunkRenderModel.java b/src/main/java/ru/windcorp/progressia/client/world/ChunkRenderModel.java index 471fb92..75857b8 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/ChunkRenderModel.java +++ b/src/main/java/ru/windcorp/progressia/client/world/ChunkRenderModel.java @@ -36,8 +36,8 @@ import ru.windcorp.progressia.client.world.tile.TileRender; import ru.windcorp.progressia.client.world.tile.TileRenderNone; import ru.windcorp.progressia.client.world.tile.TileRenderStack; import ru.windcorp.progressia.common.world.ChunkData; +import ru.windcorp.progressia.common.world.rels.AxisRotations; import ru.windcorp.progressia.common.world.rels.RelFace; -import ru.windcorp.progressia.common.world.rels.RelRelation; public class ChunkRenderModel implements Renderable { @@ -61,7 +61,7 @@ public class ChunkRenderModel implements Renderable { chunk.getY() * ChunkData.BLOCKS_PER_CHUNK, chunk.getZ() * ChunkData.BLOCKS_PER_CHUNK ).translate(offset, offset, offset) - .mul(RelRelation.getResolutionMatrix4(chunk.getUp())) + .mul(AxisRotations.getResolutionMatrix4(chunk.getUp())) .translate(-offset, -offset, -offset); model.render(renderer); diff --git a/src/main/java/ru/windcorp/progressia/common/collision/AABBRotator.java b/src/main/java/ru/windcorp/progressia/common/collision/AABBRotator.java new file mode 100644 index 0000000..cbacb29 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/collision/AABBRotator.java @@ -0,0 +1,134 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package ru.windcorp.progressia.common.collision; + +import java.util.function.Supplier; + +import com.google.common.collect.ImmutableList; + +import glm.vec._3.Vec3; +import ru.windcorp.progressia.common.util.Vectors; +import ru.windcorp.progressia.common.world.rels.AbsFace; +import ru.windcorp.progressia.common.world.rels.AxisRotations; + +public class AABBRotator implements AABBoid { + + private class AABBRotatorWall implements Wall { + + private final int id; + + public AABBRotatorWall(int id) { + this.id = id; + } + + @Override + public void getOrigin(Vec3 output) { + parent.getWall(id).getOrigin(output); + AxisRotations.resolve(output, upSupplier.get(), output); + } + + @Override + public void getWidth(Vec3 output) { + parent.getWall(id).getWidth(output); + AxisRotations.resolve(output, upSupplier.get(), output); + } + + @Override + public void getHeight(Vec3 output) { + parent.getWall(id).getHeight(output); + AxisRotations.resolve(output, upSupplier.get(), output); + } + + } + + private final Supplier upSupplier; + private final Supplier hingeSupplier; + private final AABBoid parent; + + private final AABBRotatorWall[] walls = new AABBRotatorWall[AbsFace.BLOCK_FACE_COUNT]; + + { + for (int id = 0; id < walls.length; ++id) { + walls[id] = new AABBRotatorWall(id); + } + } + + public AABBRotator(Supplier upSupplier, Supplier hingeSupplier, AABBoid parent) { + this.upSupplier = upSupplier; + this.hingeSupplier = hingeSupplier; + this.parent = parent; + } + + @Override + public void setOrigin(Vec3 origin) { + Vec3 relativeOrigin = Vectors.grab3(); + Vec3 hinge = hingeSupplier.get(); + + origin.sub(hinge, relativeOrigin); + AxisRotations.relativize(relativeOrigin, upSupplier.get(), relativeOrigin); + relativeOrigin.add(hinge); + + parent.setOrigin(relativeOrigin); + + Vectors.release(relativeOrigin); + } + + @Override + public void moveOrigin(Vec3 displacement) { + parent.moveOrigin(displacement); + } + + @Override + public void getOrigin(Vec3 output) { + parent.getOrigin(output); + Vec3 hinge = hingeSupplier.get(); + + output.sub(hinge); + AxisRotations.resolve(output, upSupplier.get(), output); + output.add(hinge); + } + + @Override + public void getSize(Vec3 output) { + parent.getSize(output); + AxisRotations.resolve(output, upSupplier.get(), output); + output.abs(); + } + + @Override + public Wall getWall(int faceId) { + return walls[faceId]; + } + + public static CollisionModel rotate(Supplier upSupplier, Supplier hingeSupplier, CollisionModel parent) { + if (parent instanceof AABBoid) { + return new AABBRotator(upSupplier, hingeSupplier, (AABBoid) parent); + } else if (parent instanceof CompoundCollisionModel) { + ImmutableList.Builder models = ImmutableList.builder(); + + for (CollisionModel original : ((CompoundCollisionModel) parent).getModels()) { + models.add(rotate(upSupplier, hingeSupplier, original)); + } + + return new CompoundCollisionModel(models.build()); + } else { + throw new RuntimeException("not supported"); + } + } + +} diff --git a/src/main/java/ru/windcorp/progressia/common/world/entity/EntityData.java b/src/main/java/ru/windcorp/progressia/common/world/entity/EntityData.java index e776e6a..d54cca1 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/entity/EntityData.java +++ b/src/main/java/ru/windcorp/progressia/common/world/entity/EntityData.java @@ -26,12 +26,14 @@ import java.util.Objects; import glm.mat._3.Mat3; import glm.vec._3.Vec3; import ru.windcorp.jputil.chars.StringUtil; +import ru.windcorp.progressia.common.collision.AABBRotator; import ru.windcorp.progressia.common.collision.Collideable; import ru.windcorp.progressia.common.collision.CollisionModel; import ru.windcorp.progressia.common.state.IOContext; import ru.windcorp.progressia.common.state.StatefulObject; import ru.windcorp.progressia.common.util.Matrices; import ru.windcorp.progressia.common.world.generic.GenericEntity; +import ru.windcorp.progressia.common.world.rels.AbsFace; public class EntityData extends StatefulObject implements Collideable, GenericEntity { @@ -51,6 +53,7 @@ public class EntityData extends StatefulObject implements Collideable, GenericEn private long entityId; private CollisionModel collisionModel = null; + private CollisionModel rotatedCollisionModel = null; private double age = 0; @@ -107,11 +110,16 @@ public class EntityData extends StatefulObject implements Collideable, GenericEn @Override public CollisionModel getCollisionModel() { + return rotatedCollisionModel; + } + + public CollisionModel getOriginalCollisionModel() { return collisionModel; } public void setCollisionModel(CollisionModel collisionModel) { this.collisionModel = collisionModel; + this.rotatedCollisionModel = AABBRotator.rotate(this::getUpFace, this::getPosition, collisionModel); } @Override @@ -164,6 +172,10 @@ public class EntityData extends StatefulObject implements Collideable, GenericEn public Vec3 getUpVector() { return upVector; } + + public AbsFace getUpFace() { + return AbsFace.roundToFace(getUpVector()); + } /** * Sets this entity's up vector without updating looking at-vector. diff --git a/src/main/java/ru/windcorp/progressia/common/world/generic/GenericChunk.java b/src/main/java/ru/windcorp/progressia/common/world/generic/GenericChunk.java index 1768119..95c18be 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/generic/GenericChunk.java +++ b/src/main/java/ru/windcorp/progressia/common/world/generic/GenericChunk.java @@ -25,8 +25,8 @@ import ru.windcorp.progressia.common.util.VectorUtil; import ru.windcorp.progressia.common.util.Vectors; import ru.windcorp.progressia.common.world.Coordinates; import ru.windcorp.progressia.common.world.rels.AbsFace; +import ru.windcorp.progressia.common.world.rels.AxisRotations; import ru.windcorp.progressia.common.world.rels.BlockFace; -import ru.windcorp.progressia.common.world.rels.RelRelation; public interface GenericChunk, B extends GenericBlock, T extends GenericTile, TS extends GenericTileStack> { @@ -52,7 +52,7 @@ public interface GenericChunk, B exten output.set(relativeBlockInChunk.x, relativeBlockInChunk.y, relativeBlockInChunk.z); output.mul(2).sub(offset); - RelRelation.resolve(output, getUp(), output); + AxisRotations.resolve(output, getUp(), output); output.add(offset).div(2); diff --git a/src/main/java/ru/windcorp/progressia/common/world/rels/AxisRotations.java b/src/main/java/ru/windcorp/progressia/common/world/rels/AxisRotations.java new file mode 100644 index 0000000..2d13c19 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/world/rels/AxisRotations.java @@ -0,0 +1,193 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package ru.windcorp.progressia.common.world.rels; + +import static ru.windcorp.progressia.common.util.VectorUtil.SignedAxis.NEG_X; +import static ru.windcorp.progressia.common.util.VectorUtil.SignedAxis.NEG_Y; +import static ru.windcorp.progressia.common.util.VectorUtil.SignedAxis.NEG_Z; +import static ru.windcorp.progressia.common.util.VectorUtil.SignedAxis.POS_X; +import static ru.windcorp.progressia.common.util.VectorUtil.SignedAxis.POS_Y; +import static ru.windcorp.progressia.common.util.VectorUtil.SignedAxis.POS_Z; + +import java.util.Map; + +import glm.mat._3.Mat3; +import glm.mat._4.Mat4; +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.SignedAxis; + +public class AxisRotations { + + private static class Rotation { + private static class MyMat3i { + private final int m00, m01, m02, m10, m11, m12, m20, m21, m22; + + public MyMat3i(Mat3 integerMatrix) { + this.m00 = (int) integerMatrix.m00; + this.m01 = (int) integerMatrix.m01; + this.m02 = (int) integerMatrix.m02; + this.m10 = (int) integerMatrix.m10; + this.m11 = (int) integerMatrix.m11; + this.m12 = (int) integerMatrix.m12; + this.m20 = (int) integerMatrix.m20; + this.m21 = (int) integerMatrix.m21; + this.m22 = (int) integerMatrix.m22; + } + + public Vec3i mul(Vec3i right, Vec3i res) { + res.set( + m00 * right.x + m10 * right.y + m20 * right.z, + m01 * right.x + m11 * right.y + m21 * right.z, + m02 * right.x + m12 * right.y + m22 * right.z + ); + return res; + } + } + + private final Mat3 resolutionMatrix3 = new Mat3(); + private final Mat4 resolutionMatrix4 = new Mat4(); + private final MyMat3i resolutionMatrix3i; + + private final Mat3 relativizationMatrix3 = new Mat3(); + private final Mat4 relativizationMatrix4 = new Mat4(); + private final MyMat3i relativizationMatrix3i; + + private Rotation(SignedAxis northDestination, SignedAxis westDestination, SignedAxis upDestination) { + resolutionMatrix3.c0(computeUnitVectorAlong(northDestination)); + resolutionMatrix3.c1(computeUnitVectorAlong(westDestination)); + resolutionMatrix3.c2(computeUnitVectorAlong(upDestination)); + + resolutionMatrix3.toMat4(resolutionMatrix4); + resolutionMatrix3i = new MyMat3i(resolutionMatrix3); + + relativizationMatrix3.set(resolutionMatrix3).transpose(); + relativizationMatrix4.set(resolutionMatrix4).transpose(); + relativizationMatrix3i = new MyMat3i(relativizationMatrix3); + } + + private static Vec3 computeUnitVectorAlong(SignedAxis signedAxis) { + Vec3 result = new Vec3(0, 0, 0); + VectorUtil.set(result, signedAxis.getAxis(), signedAxis.getSign()); + return result; + } + + /** + * @return the resolutionMatrix3 + */ + public Mat3 getResolutionMatrix3() { + return resolutionMatrix3; + } + + /** + * @return the resolutionMatrix4 + */ + public Mat4 getResolutionMatrix4() { + return resolutionMatrix4; + } + + /** + * @return the relativizationMatrix3 + */ + public Mat3 getRelativizationMatrix3() { + return relativizationMatrix3; + } + + /** + * @return the relativizationMatrix4 + */ + public Mat4 getRelativizationMatrix4() { + return relativizationMatrix4; + } + + public Vec3i resolve(Vec3i output, Vec3i input) { + if (output == null) { + output = new Vec3i(); + } + resolutionMatrix3i.mul(input, output); + return output; + } + + public Vec3i relativize(Vec3i output, Vec3i input) { + if (output == null) { + output = new Vec3i(); + } + relativizationMatrix3i.mul(input, output); + return output; + } + + public Vec3 resolve(Vec3 output, Vec3 input) { + if (output == null) { + output = new Vec3(); + } + resolutionMatrix3.mul(input, output); + return output; + } + + public Vec3 relativize(Vec3 output, Vec3 input) { + if (output == null) { + output = new Vec3(); + } + relativizationMatrix3.mul(input, output); + return output; + } + } + + private final static Map TRANSFORMATIONS = AbsFace.mapToFaces( + new Rotation(POS_X, POS_Y, POS_Z), + new Rotation(POS_X, NEG_Y, NEG_Z), + new Rotation(POS_Z, NEG_Y, POS_X), + new Rotation(POS_Z, POS_Y, NEG_X), + new Rotation(POS_Z, NEG_X, NEG_Y), + new Rotation(POS_Z, POS_X, POS_Y) + ); + + public static Vec3i resolve(Vec3i relative, AbsFace up, Vec3i output) { + return TRANSFORMATIONS.get(up).resolve(output, relative); + } + + public static Vec3 resolve(Vec3 relative, AbsFace up, Vec3 output) { + return TRANSFORMATIONS.get(up).resolve(output, relative); + } + + public static Vec3i relativize(Vec3i absolute, AbsFace up, Vec3i output) { + return TRANSFORMATIONS.get(up).relativize(output, absolute); + } + + public static Vec3 relativize(Vec3 absolute, AbsFace up, Vec3 output) { + return TRANSFORMATIONS.get(up).relativize(output, absolute); + } + + public static Mat3 getResolutionMatrix3(AbsFace up) { + return TRANSFORMATIONS.get(up).getResolutionMatrix3(); + } + + public static Mat4 getResolutionMatrix4(AbsFace up) { + return TRANSFORMATIONS.get(up).getResolutionMatrix4(); + } + + public static Mat3 getRelativizationMatrix3(AbsFace up) { + return TRANSFORMATIONS.get(up).getRelativizationMatrix3(); + } + + public static Mat4 getRelativizationMatrix4(AbsFace up) { + return TRANSFORMATIONS.get(up).getRelativizationMatrix4(); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/common/world/rels/BlockFaceResolver.java b/src/main/java/ru/windcorp/progressia/common/world/rels/BlockFaceResolver.java index 3e25e1b..e1f469e 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/rels/BlockFaceResolver.java +++ b/src/main/java/ru/windcorp/progressia/common/world/rels/BlockFaceResolver.java @@ -37,7 +37,7 @@ public class BlockFaceResolver { for (AbsFace up : AbsFace.getFaces()) { for (RelFace relative : RelFace.getFaces()) { - AbsFace absolute = (AbsFace) AbsRelation.of(RelRelation.resolve(relative.getRelVector(), up, null)); + AbsFace absolute = (AbsFace) AbsRelation.of(AxisRotations.resolve(relative.getRelVector(), up, null)); RESOLUTION_TABLE[up.getId()][relative.getId()] = absolute; RELATIVIZATION_TABLE[up.getId()][absolute.getId()] = relative; diff --git a/src/main/java/ru/windcorp/progressia/common/world/rels/RelRelation.java b/src/main/java/ru/windcorp/progressia/common/world/rels/RelRelation.java index 5268a26..6eec211 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/rels/RelRelation.java +++ b/src/main/java/ru/windcorp/progressia/common/world/rels/RelRelation.java @@ -17,122 +17,15 @@ */ package ru.windcorp.progressia.common.world.rels; -import java.util.Map; - -import glm.mat._3.Mat3; -import glm.mat._4.Mat4; import glm.vec._3.Vec3; import glm.vec._3.i.Vec3i; -import ru.windcorp.progressia.common.util.VectorUtil; import ru.windcorp.progressia.common.util.Vectors; -import ru.windcorp.progressia.common.util.VectorUtil.SignedAxis; - -import static ru.windcorp.progressia.common.util.VectorUtil.SignedAxis.*; /** * Name stands for Relative Relation */ public class RelRelation extends BlockRelation { - private static class Rotation { - private final SignedAxis northDestination; - private final SignedAxis westDestination; - private final SignedAxis upDestination; - - private final Mat3 resolutionMatrix3 = new Mat3(); - private final Mat4 resolutionMatrix4 = new Mat4(); - - private final Mat3 relativizationMatrix3 = new Mat3(); - private final Mat4 relativizationMatrix4 = new Mat4(); - - private Rotation(SignedAxis northDestination, SignedAxis westDestination, SignedAxis upDestination) { - this.northDestination = northDestination; - this.westDestination = westDestination; - this.upDestination = upDestination; - - resolutionMatrix3.c0(apply(null, new Vec3(1, 0, 0))); - resolutionMatrix3.c1(apply(null, new Vec3(0, 1, 0))); - resolutionMatrix3.c2(apply(null, new Vec3(0, 0, 1))); - resolutionMatrix3.toMat4(resolutionMatrix4); - - relativizationMatrix3.set(resolutionMatrix3).transpose(); - relativizationMatrix4.set(resolutionMatrix4).transpose(); - } - - /** - * @return the resolutionMatrix3 - */ - public Mat3 getResolutionMatrix3() { - return resolutionMatrix3; - } - - /** - * @return the resolutionMatrix4 - */ - public Mat4 getResolutionMatrix4() { - return resolutionMatrix4; - } - - /** - * @return the relativizationMatrix3 - */ - public Mat3 getRelativizationMatrix3() { - return relativizationMatrix3; - } - - /** - * @return the relativizationMatrix4 - */ - public Mat4 getRelativizationMatrix4() { - return relativizationMatrix4; - } - - public Vec3i apply(Vec3i output, Vec3i input) { - if (output == null) { - output = new Vec3i(); - } - - int inX = input.x, inY = input.y, inZ = input.z; - - set(output, inX, northDestination); - set(output, inY, westDestination); - set(output, inZ, upDestination); - - return output; - } - - private static void set(Vec3i output, int value, SignedAxis axis) { - VectorUtil.set(output, axis.getAxis(), axis.isPositive() ? +value : -value); - } - - public Vec3 apply(Vec3 output, Vec3 input) { - if (output == null) { - output = new Vec3(); - } - - float inX = input.x, inY = input.y, inZ = input.z; - - set(output, inX, northDestination); - set(output, inY, westDestination); - set(output, inZ, upDestination); - - return output; - } - - private static void set(Vec3 output, float value, SignedAxis axis) { - VectorUtil.set(output, axis.getAxis(), axis.isPositive() ? +value : -value); - } - } - - private final static Map TRANSFORMATIONS = AbsFace.mapToFaces( - new Rotation(POS_X, POS_Y, POS_Z), - new Rotation(POS_X, NEG_Y, NEG_Z), - new Rotation(POS_Z, NEG_Y, POS_X), - new Rotation(POS_Z, POS_Y, NEG_X), - new Rotation(POS_Z, NEG_X, NEG_Y), - new Rotation(POS_Z, POS_X, POS_Y) - ); - private final Vec3i vector = new Vec3i(); private final Vec3 floatVector = new Vec3(); private final Vec3 normalized = new Vec3(); @@ -242,38 +135,11 @@ public class RelRelation extends BlockRelation { private AbsRelation computeResolution(AbsFace up) { Vec3i resolution = Vectors.grab3i(); - resolve(vector, up, resolution); + AxisRotations.resolve(vector, up, resolution); AbsRelation result = AbsRelation.of(resolution); Vectors.release(resolution); return result; } - - public static Vec3i resolve(Vec3i relative, AbsFace up, Vec3i output) { - if (output == null) { - output = new Vec3i(); - } - - TRANSFORMATIONS.get(up).apply(output, relative); - - return output; - } - - public static Mat3 getResolutionMatrix3(AbsFace up) { - return TRANSFORMATIONS.get(up).getResolutionMatrix3(); - } - - public static Mat4 getResolutionMatrix4(AbsFace up) { - return TRANSFORMATIONS.get(up).getResolutionMatrix4(); - } - - - public static Mat3 getRelativizationMatrix3(AbsFace up) { - return TRANSFORMATIONS.get(up).getRelativizationMatrix3(); - } - - public static Mat4 getRelativizationMatrix4(AbsFace up) { - return TRANSFORMATIONS.get(up).getRelativizationMatrix4(); - } @Override protected Vec3i getSample() { diff --git a/src/main/java/ru/windcorp/progressia/test/gen/TestPlanetGravityModel.java b/src/main/java/ru/windcorp/progressia/test/gen/TestPlanetGravityModel.java index 05d659a..f3dc35f 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/TestPlanetGravityModel.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/TestPlanetGravityModel.java @@ -43,9 +43,9 @@ public class TestPlanetGravityModel extends GravityModel { @Override protected void doGetGravity(Vec3 pos, Vec3 output) { // Change to a CS where (0;0;0) is the center of the center chunk - float px = pos.x - ChunkData.CHUNK_RADIUS; - float py = pos.y - ChunkData.CHUNK_RADIUS; - float pz = pos.z - ChunkData.CHUNK_RADIUS; + float px = pos.x - ChunkData.CHUNK_RADIUS + 0.5f; + float py = pos.y - ChunkData.CHUNK_RADIUS + 0.5f; + float pz = pos.z - ChunkData.CHUNK_RADIUS + 0.5f; // Assume weightlessness when too close to center if ((px*px + py*py + pz*pz) < INNER_RADIUS*INNER_RADIUS) {