Skip to content

Commit 9736e55

Browse files
committed
Do some housekeeping on the Rapier pipeline (lots of breaking changes)
1 parent 9f7d823 commit 9736e55

51 files changed

Lines changed: 2747 additions & 2250 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

common/src/main/java/dev/ryanhcode/sable/api/SubLevelAssemblyHelper.java

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,32 @@ public static ServerSubLevel assembleBlocks(final ServerLevel level, final Block
7070
final ServerSubLevelContainer container = SubLevelContainer.getContainer(level);
7171
assert container != null;
7272

73+
final SubLevelPhysicsSystem physicsSystem = container.physicsSystem();
7374
final SubLevel containingSubLevel = Sable.HELPER.getContaining(level, anchor);
7475
final Pose3d pose = new Pose3d();
7576

7677
pose.position().set(anchor.getX() + 0.5, anchor.getY() + 0.5, anchor.getZ() + 0.5);
78+
79+
final Vector3d containingAngularVelocity = new Vector3d();
80+
final Vector3d containingLinearVelocity = new Vector3d();
81+
final Pose3d containingPose;
82+
7783
if (containingSubLevel != null) {
78-
final Pose3d containingPose = containingSubLevel.logicalPose();
84+
if (containingSubLevel.isRemoved()) {
85+
throw new RuntimeException("Sub-level assembly attempted inside plot of already removed sub-level");
86+
}
87+
88+
containingPose = new Pose3d(containingSubLevel.logicalPose());
89+
7990
containingPose.transformPosition(pose.position());
8091
pose.orientation().set(containingPose.orientation());
92+
93+
final RigidBodyHandle containingHandle = physicsSystem.getPhysicsHandle((ServerSubLevel) containingSubLevel);
94+
95+
containingHandle.getLinearVelocity(containingLinearVelocity);
96+
containingHandle.getAngularVelocity(containingAngularVelocity);
97+
} else {
98+
containingPose = null;
8199
}
82100

83101
final ServerSubLevel subLevel = (ServerSubLevel) container.allocateNewSubLevel(pose);
@@ -104,11 +122,10 @@ public static ServerSubLevel assembleBlocks(final ServerLevel level, final Block
104122

105123
subLevel.logicalPose().position().set(subLevelCenter.x, subLevelCenter.y, subLevelCenter.z);
106124

107-
final SubLevelPhysicsSystem physicsSystem = container.physicsSystem();
108125
final PhysicsPipeline pipeline = physicsSystem.getPipeline();
109126

110127
if (containingSubLevel != null) {
111-
kickFromContainingSubLevel(level, physicsSystem, pipeline, subLevel, containingSubLevel);
128+
kickFromContainingSubLevel(pipeline, subLevel, containingLinearVelocity, containingAngularVelocity, containingPose, !containingSubLevel.isRemoved() ? containingSubLevel : null);
112129
}
113130

114131
pipeline.teleport(subLevel, subLevel.logicalPose().position(), subLevel.logicalPose().orientation());
@@ -125,18 +142,35 @@ public static void kickFromContainingSubLevel(final ServerLevel level,
125142
final PhysicsPipeline pipeline,
126143
final ServerSubLevel subLevel,
127144
final SubLevel containingSubLevel) {
128-
final Pose3d originalPose = new Pose3d(subLevel.logicalPose());
129145

130-
final Vector3d velocity = Sable.HELPER.getVelocity(level, subLevel.logicalPose().position(), new Vector3d());
131146
final RigidBodyHandle containingHandle = physicsSystem.getPhysicsHandle((ServerSubLevel) containingSubLevel);
132-
pipeline.addLinearAndAngularVelocity(subLevel, velocity, containingHandle.getAngularVelocity());
147+
final Vector3d linearVelocity = containingHandle.getLinearVelocity(new Vector3d());
148+
final Vector3d angularVelocity = containingHandle.getAngularVelocity(new Vector3d());
149+
final Pose3d containingPose = containingSubLevel.logicalPose();
150+
151+
kickFromContainingSubLevel(pipeline, subLevel, linearVelocity, angularVelocity, containingPose, containingSubLevel);
152+
}
153+
154+
@ApiStatus.Internal
155+
private static void kickFromContainingSubLevel(final PhysicsPipeline pipeline,
156+
final ServerSubLevel subLevel,
157+
final Vector3d containingLinearVelocity,
158+
final Vector3d containingAngularVelocity,
159+
final Pose3d containingPose,
160+
@Nullable final SubLevel containingSubLevel) {
161+
final Pose3d originalPose = new Pose3d(subLevel.logicalPose());
162+
133163

134164
// re-transform after center of mass is fixed
135165
// we don't need to set the orientation again as it couldn't have changed
136-
final Pose3d containingPose = containingSubLevel.logicalPose();
137166
containingPose.transformPosition(subLevel.logicalPose().position());
138167

139-
subLevel.setSplitFrom((ServerSubLevel) containingSubLevel, originalPose);
168+
final Vector3d localPos = subLevel.logicalPose().position().sub(containingPose.position(), new Vector3d());
169+
pipeline.addLinearAndAngularVelocity(subLevel, containingAngularVelocity.cross(localPos, localPos).add(containingLinearVelocity), containingAngularVelocity);
170+
171+
if (containingSubLevel != null) {
172+
subLevel.setSplitFrom((ServerSubLevel) containingSubLevel, originalPose);
173+
}
140174
}
141175

142176
/**

common/src/main/java/dev/ryanhcode/sable/api/physics/PhysicsPipeline.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import net.minecraft.world.level.block.state.BlockState;
1717
import net.minecraft.world.level.chunk.LevelChunkSection;
1818
import org.jetbrains.annotations.ApiStatus;
19+
import org.jetbrains.annotations.Contract;
1920
import org.jetbrains.annotations.NotNull;
2021
import org.jetbrains.annotations.Nullable;
2122
import org.joml.Quaterniondc;
@@ -216,11 +217,13 @@ default Vector3d getAngularVelocity(final PhysicsPipelineBody body, final Vector
216217
/**
217218
* Adds a constraint to the engine, returning its handle
218219
*
219-
* @param sublevelA the first sub-level to constrain, or null to constrain the second sub-level to the world
220-
* @param sublevelB the second sub-level to constrain, or null to constrain the first sub-level to the world
220+
* @param bodyA the first body to constrain, or null to constrain the second body to the world
221+
* @param bodyB the second body to constrain, or null to constrain the first body to the world
221222
* @param configuration the configuration of the constraint
222223
*/
223-
default <T extends PhysicsConstraintHandle> T addConstraint(@Nullable final ServerSubLevel sublevelA, @Nullable final ServerSubLevel sublevelB, final PhysicsConstraintConfiguration<T> configuration) {
224+
@Nullable
225+
@Contract("null, null, _ -> fail")
226+
default <T extends PhysicsConstraintHandle> T addConstraint(@Nullable final PhysicsPipelineBody bodyA, @Nullable final PhysicsPipelineBody bodyB, @NotNull final PhysicsConstraintConfiguration<T> configuration) {
224227
throw new UnsupportedOperationException("Not implemented");
225228
}
226229

common/src/main/java/dev/ryanhcode/sable/api/physics/callback/BlockSubLevelCollisionCallback.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import dev.ryanhcode.sable.companion.math.JOMLConversion;
44
import net.minecraft.core.BlockPos;
55
import org.jetbrains.annotations.ApiStatus;
6+
import org.jetbrains.annotations.Nullable;
67
import org.joml.Vector3d;
78
import org.joml.Vector3dc;
89

@@ -18,18 +19,30 @@ public interface BlockSubLevelCollisionCallback {
1819
default double[] onCollision(final int x,
1920
final int y,
2021
final int z,
22+
final int otherX,
23+
final int otherY,
24+
final int otherZ,
2125
final double x1,
2226
final double y1,
2327
final double z1,
24-
final double impactVelocity) {
25-
final CollisionResult result = this.sable$onCollision(new BlockPos(x, y, z), new Vector3d(x1, y1, z1), impactVelocity);
28+
final double impactVelocity,
29+
final boolean hasOtherBlock) {
30+
final CollisionResult result = this.sable$onCollision(new BlockPos(x, y, z), hasOtherBlock ? new BlockPos(otherX, otherY, otherZ) : null, new Vector3d(x1, y1, z1), impactVelocity);
2631
final Vector3dc motion = result.tangentMotion;
2732

2833
// TODO: this is stupid and moronic to pass through the removal as a double lmao, let's not do that in the future
2934
return new double[]{motion.x(), motion.y(), motion.z(), result.removeCollision ? 1.0 : 0.0};
3035
}
3136

32-
CollisionResult sable$onCollision(BlockPos blockPos, Vector3d pos, double impactVelocity);
37+
/**
38+
* Called when a collision occurs between two blocks
39+
* @param hitBlockPos the block that was hit (the block this callback is on)
40+
* @param otherHitBlockPos the other block that was hit (if the other body is a sub-level)
41+
* @param impactPosition the impact position, in the plot of the sub-level that was hit (or in global coordinates if a sub-level does not contain the block)
42+
* @param impactVelocity the velocity of the impact along the normal
43+
* @return the result of the collision callback
44+
*/
45+
CollisionResult sable$onCollision(BlockPos hitBlockPos, @Nullable BlockPos otherHitBlockPos, Vector3d impactPosition, double impactVelocity);
3346

3447
record CollisionResult(Vector3dc tangentMotion, boolean removeCollision) {
3548
public static final CollisionResult NONE = new CollisionResult(JOMLConversion.ZERO, false);

common/src/main/java/dev/ryanhcode/sable/api/physics/constraint/fixed/FixedConstraintConfiguration.java renamed to common/src/main/java/dev/ryanhcode/sable/api/physics/constraint/FixedConstraintConfiguration.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
package dev.ryanhcode.sable.api.physics.constraint.fixed;
1+
package dev.ryanhcode.sable.api.physics.constraint;
22

3-
import dev.ryanhcode.sable.api.physics.constraint.PhysicsConstraintConfiguration;
3+
import dev.ryanhcode.sable.api.physics.PhysicsPipelineBody;
4+
import dev.ryanhcode.sable.api.sublevel.ServerSubLevelContainer;
45
import org.joml.Quaterniondc;
56
import org.joml.Vector3dc;
67

@@ -13,4 +14,9 @@
1314
*/
1415
public record FixedConstraintConfiguration(Vector3dc pos1, Vector3dc pos2, Quaterniondc orientation) implements PhysicsConstraintConfiguration<FixedConstraintHandle> {
1516

17+
@Override
18+
public void validate(final ServerSubLevelContainer container, final PhysicsPipelineBody bodyA, final PhysicsPipelineBody bodyB) {
19+
PhysicsConstraintConfiguration.validateAnchors(container, bodyA, bodyB, this.pos1, this.pos2);
20+
}
21+
1622
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package dev.ryanhcode.sable.api.physics.constraint;
2+
3+
/**
4+
* A fixed constraint between two bodies
5+
*/
6+
public non-sealed interface FixedConstraintHandle extends PhysicsConstraintHandle {
7+
8+
}

common/src/main/java/dev/ryanhcode/sable/api/physics/constraint/free/FreeConstraintConfiguration.java renamed to common/src/main/java/dev/ryanhcode/sable/api/physics/constraint/FreeConstraintConfiguration.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
package dev.ryanhcode.sable.api.physics.constraint.free;
1+
package dev.ryanhcode.sable.api.physics.constraint;
22

3-
import dev.ryanhcode.sable.api.physics.constraint.PhysicsConstraintConfiguration;
3+
import dev.ryanhcode.sable.api.physics.PhysicsPipelineBody;
4+
import dev.ryanhcode.sable.api.sublevel.ServerSubLevelContainer;
45
import org.joml.Quaterniondc;
56
import org.joml.Vector3dc;
67

@@ -13,4 +14,9 @@
1314
*/
1415
public record FreeConstraintConfiguration(Vector3dc pos1, Vector3dc pos2, Quaterniondc orientation) implements PhysicsConstraintConfiguration<FreeConstraintHandle> {
1516

17+
@Override
18+
public void validate(final ServerSubLevelContainer container, final PhysicsPipelineBody bodyA, final PhysicsPipelineBody bodyB) {
19+
PhysicsConstraintConfiguration.validateAnchors(container, bodyA, bodyB, this.pos1, this.pos2);
20+
}
21+
1622
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package dev.ryanhcode.sable.api.physics.constraint;
2+
3+
/**
4+
* A free constraint between two bodies
5+
*/
6+
public non-sealed interface FreeConstraintHandle extends PhysicsConstraintHandle {
7+
8+
}

common/src/main/java/dev/ryanhcode/sable/api/physics/constraint/generic/GenericConstraintConfiguration.java renamed to common/src/main/java/dev/ryanhcode/sable/api/physics/constraint/GenericConstraintConfiguration.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
package dev.ryanhcode.sable.api.physics.constraint.generic;
1+
package dev.ryanhcode.sable.api.physics.constraint;
22

3-
import dev.ryanhcode.sable.api.physics.constraint.ConstraintJointAxis;
4-
import dev.ryanhcode.sable.api.physics.constraint.PhysicsConstraintConfiguration;
3+
import dev.ryanhcode.sable.api.physics.PhysicsPipelineBody;
4+
import dev.ryanhcode.sable.api.sublevel.ServerSubLevelContainer;
55
import org.joml.Quaterniondc;
66
import org.joml.Vector3dc;
77

@@ -29,4 +29,10 @@ public record GenericConstraintConfiguration(
2929
public GenericConstraintConfiguration(final Vector3dc pos1, final Vector3dc pos2, final Quaterniondc orientation1, final Quaterniondc orientation2) {
3030
this(pos1, pos2, orientation1, orientation2, EnumSet.noneOf(ConstraintJointAxis.class));
3131
}
32+
33+
@Override
34+
public void validate(final ServerSubLevelContainer container, final PhysicsPipelineBody bodyA, final PhysicsPipelineBody bodyB) {
35+
PhysicsConstraintConfiguration.validateAnchors(container, bodyA, bodyB, this.pos1, this.pos2);
36+
}
37+
3238
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package dev.ryanhcode.sable.api.physics.constraint;
2+
3+
import org.joml.Quaterniondc;
4+
import org.joml.Vector3dc;
5+
6+
/**
7+
* A generic constraint between two bodies.
8+
*
9+
* @since 1.1.0
10+
*/
11+
public non-sealed interface GenericConstraintHandle extends PhysicsConstraintHandle {
12+
13+
/**
14+
* Sets the local frame on the first body.
15+
*
16+
* @param localPosition the local anchor position
17+
* @param localOrientation the local frame orientation
18+
*/
19+
void setFrame1(Vector3dc localPosition, Quaterniondc localOrientation);
20+
21+
/**
22+
* Sets the local frame on the second body.
23+
*
24+
* @param localPosition the local anchor position
25+
* @param localOrientation the local frame orientation
26+
*/
27+
void setFrame2(Vector3dc localPosition, Quaterniondc localOrientation);
28+
29+
/**
30+
* Adds / sets a limit on this joint
31+
*
32+
* @param axis The axis on which the limit should be placed
33+
* @param min The minimum limit on the constraint axis
34+
* @param max The maximum limit on the constraint axis
35+
*/
36+
void setLimit(ConstraintJointAxis axis, double min, double max);
37+
38+
/**
39+
* Locks the given constraint axes on this joint
40+
*
41+
* @param axes The axes to lock
42+
*/
43+
void lockAxes(ConstraintJointAxis... axes);
44+
}
Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,47 @@
11
package dev.ryanhcode.sable.api.physics.constraint;
22

3+
import dev.ryanhcode.sable.api.physics.PhysicsPipelineBody;
4+
import dev.ryanhcode.sable.api.sublevel.ServerSubLevelContainer;
5+
import dev.ryanhcode.sable.sublevel.ServerSubLevel;
6+
import org.joml.Vector3dc;
7+
38
/**
49
* A configuration for a physics constraint.
510
* @param <T> the type of constraint handle this configuration produces
611
*/
7-
public interface PhysicsConstraintConfiguration<T extends PhysicsConstraintHandle> {
12+
public sealed interface PhysicsConstraintConfiguration<T extends PhysicsConstraintHandle> permits FixedConstraintConfiguration, FreeConstraintConfiguration, GenericConstraintConfiguration, RotaryConstraintConfiguration {
13+
14+
static void validateAnchors(final ServerSubLevelContainer container, final PhysicsPipelineBody bodyA, final PhysicsPipelineBody bodyB, final Vector3dc pos1, final Vector3dc pos2) {
15+
if (bodyA instanceof final ServerSubLevel subLevel) {
16+
if (!subLevel.getPlot().contains(pos1)) {
17+
throw new IllegalArgumentException("pos1 does not fall within the plot of the first sub-level in block-coordinates! Double check your coordinate spaces.");
18+
}
19+
} else {
20+
if (container.inBounds(pos1)) {
21+
throw new IllegalArgumentException("the first body of this constraint is not a sub-level, but the first position is in the plotgrid! Double check your coordinate spaces.");
22+
}
23+
}
24+
25+
if (bodyB instanceof final ServerSubLevel subLevel) {
26+
if (!subLevel.getPlot().contains(pos2)) {
27+
throw new IllegalArgumentException("pos2 does not fall within the plot of the second sub-level in block-coordinates! Double check your coordinate spaces.");
28+
}
29+
} else {
30+
if (container.inBounds(pos2)) {
31+
throw new IllegalArgumentException("the second body of this constraint is not a sub-level, but the second position is in the plotgrid! Double check your coordinate spaces.");
32+
}
33+
}
34+
}
35+
36+
/**
37+
* Validates that this constraint can be added
38+
*
39+
* @param container the sub-level container the constraint is being applied in
40+
* @param bodyA the first body the constraint is being applied to
41+
* @param bodyB the first second the constraint is being applied to
42+
*/
43+
default void validate(final ServerSubLevelContainer container, final PhysicsPipelineBody bodyA, final PhysicsPipelineBody bodyB) {
44+
45+
}
846

947
}

0 commit comments

Comments
 (0)