diff --git a/src/test/java/testjoltjni/app/samples/SmokeTestAll.java b/src/test/java/testjoltjni/app/samples/SmokeTestAll.java index 4364df92..f4bf8d98 100644 --- a/src/test/java/testjoltjni/app/samples/SmokeTestAll.java +++ b/src/test/java/testjoltjni/app/samples/SmokeTestAll.java @@ -46,6 +46,11 @@ final public class SmokeTestAll { * renderer shared by all test objects */ private static DebugRenderer renderer; + /** + * how many physics steps to simulate for each invocation of + * {@code smokeTest()} + */ + private static int numSteps = 1; /** * count invocations of {@code smokeTest()} */ @@ -152,9 +157,16 @@ public static void main(String... arguments) { smokeTest(new EmptyShapeTest()); smokeTest(new HeightFieldShapeTest()); smokeTest(new MeshShapeTest()); + smokeTest(new MeshShapeUserDataTest()); smokeTest(new MutableCompoundShapeTest()); + smokeTest(new OffsetCenterOfMassShapeTest()); smokeTest(new PlaneShapeTest()); smokeTest(new RotatedTranslatedShapeTest()); + smokeTest(new SphereShapeTest()); + smokeTest(new StaticCompoundShapeTest()); + smokeTest(new TaperedCapsuleShapeTest()); + smokeTest(new TaperedCylinderShapeTest()); + smokeTest(new TriangleShapeTest()); // softbody package: smokeTest(new SoftBodyPressureTest()); @@ -194,18 +206,20 @@ static private void smokeTest(Test test) { PhysicsSystem physicsSystem = newPhysicsSystem(10_240); test.SetPhysicsSystem(physicsSystem); - // Initialize and single-step the test: test.Initialize(); - PreUpdateParams params = new PreUpdateParams(); - params.mDeltaTime = 0.02f; - test.PrePhysicsUpdate(params); + // Single-step the physics numSteps times: + for (int i = 0; i < numSteps; ++i) { + PreUpdateParams params = new PreUpdateParams(); + params.mDeltaTime = 0.02f; + test.PrePhysicsUpdate(params); - int collisionSteps = 1; - physicsSystem.update( - params.mDeltaTime, collisionSteps, tempAllocator, jobSystem); + int collisionSteps = 1; + physicsSystem.update(params.mDeltaTime, collisionSteps, + tempAllocator, jobSystem); - test.PostPhysicsUpdate(params.mDeltaTime); + test.PostPhysicsUpdate(params.mDeltaTime); + } test.Cleanup(); System.gc(); diff --git a/src/test/java/testjoltjni/app/samples/shapes/MeshShapeUserDataTest.java b/src/test/java/testjoltjni/app/samples/shapes/MeshShapeUserDataTest.java new file mode 100644 index 00000000..67a0cab6 --- /dev/null +++ b/src/test/java/testjoltjni/app/samples/shapes/MeshShapeUserDataTest.java @@ -0,0 +1,115 @@ +/* +Copyright (c) 2024 Stephen Gold + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ +package testjoltjni.app.samples.shapes; +import com.github.stephengold.joltjni.*; +import com.github.stephengold.joltjni.enumerate.*; +import com.github.stephengold.joltjni.readonly.*; +import com.github.stephengold.joltjni.std.*; +import java.util.*; +import testjoltjni.app.samples.*; +import static com.github.stephengold.joltjni.Jolt.*; +import static com.github.stephengold.joltjni.operator.Op.*; +import static com.github.stephengold.joltjni.std.Std.*; +/** + * A line-for-line Java translation of the Jolt Physics mesh-shape user-data test. + *

+ * Compare with the original by Jorrit Rouwe at + * https://github.com/jrouwe/JoltPhysics/blob/master/Samples/Tests/Shapes/MeshShapeUserDataTest.cpp + */ +public class MeshShapeUserDataTest extends Test{ + +@SuppressWarnings("unchecked") +public void Initialize() +{ + DefaultRandomEngine random=new DefaultRandomEngine(); + + // Create regular grid of triangles + int user_data = 0; + List[] triangles={new ArrayList<>(),new ArrayList<>()}; + for (int x = -10; x < 10; ++x) + for (int z = -10; z < 10; ++z) + { + float x1 = 10.0f * x; + float z1 = 10.0f * z; + float x2 = x1 + 10.0f; + float z2 = z1 + 10.0f; + + Float3 v1 =new Float3(x1, 0, z1); + Float3 v2 =new Float3(x2, 0, z1); + Float3 v3 =new Float3(x1, 0, z2); + Float3 v4 =new Float3(x2, 0, z2); + + triangles[random.nextInt() & 1].add(new Triangle(v1, v3, v4, 0, user_data++)); + triangles[random.nextInt() & 1].add(new Triangle(v1, v4, v2, 0, user_data++)); + } + + // Create a compound with 2 meshes + StaticCompoundShapeSettings compound_settings=new StaticCompoundShapeSettings(); + compound_settings.setEmbedded(); + for (List t : triangles) + { + // Shuffle the triangles + shuffle(t, random); + + // Create mesh + MeshShapeSettings mesh_settings=new MeshShapeSettings(t); + mesh_settings.setPerTriangleUserData ( true); + compound_settings.addShape(Vec3.sZero(), Quat.sIdentity(), mesh_settings.create().get()); + } + + // Create body + mBodyInterface.createAndAddBody(new BodyCreationSettings(compound_settings, RVec3.sZero(), Quat.sRotation(Vec3.sAxisX(), 0.25f * JPH_PI), EMotionType.Static, Layers.NON_MOVING), EActivation.DontActivate); + + // 1 body with zero friction + BodyCreationSettings bcs=new BodyCreationSettings(new BoxShape(Vec3.sReplicate(2.0f)),new RVec3(0, 55.0f, -50.0f), Quat.sRotation(Vec3.sAxisX(), 0.25f * JPH_PI), EMotionType.Dynamic, Layers.MOVING); + bcs.setFriction ( 0.0f); + bcs.setEnhancedInternalEdgeRemoval ( true); // Needed because the 2 meshes have a lot of active edges + mBodyInterface.createAndAddBody(bcs, EActivation.Activate); +} + +public void PrePhysicsUpdate(PreUpdateParams inParams) +{ + // Cast a ray + RayCastResult hit=new RayCastResult(); + RRayCast ray=new RRayCast(inParams.mCameraState.mPos, star(inParams.mCameraState.mForward , 100.0f)); + mPhysicsSystem.getNarrowPhaseQuery().castRay(ray, hit); + + // Get body (if there was a hit) + BodyLockRead lock=new BodyLockRead(mPhysicsSystem.getBodyLockInterface(), hit.getBodyId()); + if (lock.succeededAndIsInBroadPhase()) + { + // Get the leaf shape (mesh shape in this case) + SubShapeId remainder=new SubShapeId(); + ConstShape shape = lock.getBody().getShape().getLeafShape(hit.getSubShapeId2(), remainder); + if (shape.getType() == EShapeType.Mesh) + { + // Get user data from the triangle that was hit + int user_data = ((MeshShape)shape).getTriangleUserData(remainder); + + // Draw it on screen + RVec3 hit_pos = ray.getPointOnRay(hit.getFraction()); + mDebugRenderer.drawText3D(hit_pos, String.format("UserData: %d", user_data)); + } + } + lock.releaseLock(); +} +} diff --git a/src/test/java/testjoltjni/app/samples/shapes/OffsetCenterOfMassShapeTest.java b/src/test/java/testjoltjni/app/samples/shapes/OffsetCenterOfMassShapeTest.java new file mode 100644 index 00000000..978e22ed --- /dev/null +++ b/src/test/java/testjoltjni/app/samples/shapes/OffsetCenterOfMassShapeTest.java @@ -0,0 +1,74 @@ +/* +Copyright (c) 2024 Stephen Gold + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ +package testjoltjni.app.samples.shapes; +import com.github.stephengold.joltjni.*; +import com.github.stephengold.joltjni.enumerate.*; +import testjoltjni.app.samples.*; +/** + * A line-for-line Java translation of the Jolt Physics offset center-of-mass shape test. + *

+ * Compare with the original by Jorrit Rouwe at + * https://github.com/jrouwe/JoltPhysics/blob/master/Samples/Tests/Shapes/OffsetCenterOfMassShapeTest.cpp + */ +public class OffsetCenterOfMassShapeTest extends Test{ + +public void Initialize() +{ + // Floor + Body floor = CreateFloor(); + floor.setFriction(1.0f); + + ShapeSettings sphere = new SphereShapeSettings(1.0f); + OffsetCenterOfMassShapeSettings left = new OffsetCenterOfMassShapeSettings(new Vec3(-1, 0, 0), sphere); + OffsetCenterOfMassShapeSettings right = new OffsetCenterOfMassShapeSettings(new Vec3(1, 0, 0), sphere); + + // Sphere with center of mass moved to the left side + Body body_left = mBodyInterface.createBody(new BodyCreationSettings(left,new RVec3(-5, 5, 0), Quat.sIdentity(), EMotionType.Dynamic, Layers.MOVING)); + body_left.setFriction(1.0f); + mBodyInterface.addBody(body_left.getId(), EActivation.Activate); + + // Sphere with center of mass centered + Body body_center = mBodyInterface.createBody(new BodyCreationSettings(sphere,new RVec3(0, 5, 0), Quat.sIdentity(), EMotionType.Dynamic, Layers.MOVING)); + body_center.setFriction(1.0f); + mBodyInterface.addBody(body_center.getId(), EActivation.Activate); + + // Sphere with center of mass moved to the right side + Body body_right = mBodyInterface.createBody(new BodyCreationSettings(right,new RVec3(5, 5, 0), Quat.sIdentity(), EMotionType.Dynamic, Layers.MOVING)); + body_right.setFriction(1.0f); + mBodyInterface.addBody(body_right.getId(), EActivation.Activate); + + // Create body and apply a large angular impulse so see that it spins around the COM + BodyCreationSettings bcs=new BodyCreationSettings(new OffsetCenterOfMassShapeSettings(new Vec3(-3, 0, 0), new SphereShapeSettings(1.0f)),new RVec3(-5, 5, 10), Quat.sIdentity(), EMotionType.Dynamic, Layers.MOVING); + bcs.setGravityFactor ( 0.0f); + bcs.setLinearDamping ( 0.0f); + bcs.setAngularDamping ( 0.0f); + Body body_rotating1 = mBodyInterface.createBody(bcs); + mBodyInterface.addBody(body_rotating1.getId(), EActivation.Activate); + body_rotating1.addAngularImpulse(new Vec3(0, 1.0e6f, 0)); + + // Create the same body but this time apply a torque + bcs.setPosition (new RVec3(5, 5, 10)); + Body body_rotating2 = mBodyInterface.createBody(bcs); + mBodyInterface.addBody(body_rotating2.getId(), EActivation.Activate); + body_rotating2.addTorque(new Vec3(0, 1.0e6f * 60.0f, 0)); // Assuming physics sim is at 60Hz here, otherwise the bodies won't rotate with the same speed +} +} \ No newline at end of file diff --git a/src/test/java/testjoltjni/app/samples/shapes/SphereShapeTest.java b/src/test/java/testjoltjni/app/samples/shapes/SphereShapeTest.java new file mode 100644 index 00000000..03578417 --- /dev/null +++ b/src/test/java/testjoltjni/app/samples/shapes/SphereShapeTest.java @@ -0,0 +1,51 @@ +/* +Copyright (c) 2024 Stephen Gold + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ +package testjoltjni.app.samples.shapes; +import com.github.stephengold.joltjni.*; +import com.github.stephengold.joltjni.enumerate.*; +import testjoltjni.app.samples.*; +import static com.github.stephengold.joltjni.Jolt.*; +/** + * A line-for-line Java translation of the Jolt Physics sphere-shape test. + *

+ * Compare with the original by Jorrit Rouwe at + * https://github.com/jrouwe/JoltPhysics/blob/master/Samples/Tests/Shapes/SphereShapeTest.cpp + */ +public class SphereShapeTest extends Test{ + +public void Initialize() +{ + // Floor + CreateFloor(); + + // Create different sized spheres + mBodyInterface.createAndAddBody(new BodyCreationSettings(new SphereShape(1.0f),new RVec3(0, 10, 0), Quat.sIdentity(), EMotionType.Dynamic, Layers.MOVING), EActivation.Activate); + + mBodyInterface.createAndAddBody(new BodyCreationSettings(new SphereShape(2.0f),new RVec3(0, 10, 10), Quat.sIdentity(), EMotionType.Dynamic, Layers.MOVING), EActivation.Activate); + + mBodyInterface.createAndAddBody(new BodyCreationSettings(new SphereShape(0.5f),new RVec3(0, 10, 20), Quat.sIdentity(), EMotionType.Dynamic, Layers.MOVING), EActivation.Activate); + + // Tower of spheres + for (int i = 0; i < 10; ++i) + mBodyInterface.createAndAddBody(new BodyCreationSettings(new SphereShape(0.5f),new RVec3(10, 10 + 1.5f * i, 0), Quat.sRotation(Vec3.sAxisZ(), 0.25f * JPH_PI), EMotionType.Dynamic, Layers.MOVING), EActivation.Activate); +} +} diff --git a/src/test/java/testjoltjni/app/samples/shapes/StaticCompoundShapeTest.java b/src/test/java/testjoltjni/app/samples/shapes/StaticCompoundShapeTest.java new file mode 100644 index 00000000..9f80f305 --- /dev/null +++ b/src/test/java/testjoltjni/app/samples/shapes/StaticCompoundShapeTest.java @@ -0,0 +1,79 @@ +/* +Copyright (c) 2024 Stephen Gold + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ +package testjoltjni.app.samples.shapes; +import com.github.stephengold.joltjni.*; +import com.github.stephengold.joltjni.enumerate.*; +import com.github.stephengold.joltjni.std.*; +import java.nio.*; +import testjoltjni.app.samples.*; +import static com.github.stephengold.joltjni.Jolt.*; +import static com.github.stephengold.joltjni.operator.Op.*; +/** + * A line-for-line Java translation of the Jolt Physics static compound-shape test. + *

+ * Compare with the original by Jorrit Rouwe at + * https://github.com/stephengold/JoltPhysics/blob/master/Samples/Tests/Shapes/StaticCompoundShapeTest.cpp + */ +public class StaticCompoundShapeTest extends Test{ + +public void Initialize() +{ + // Floor + CreateFloor(); + + // Simple compound + StaticCompoundShapeSettings compound_shape1 = new StaticCompoundShapeSettings(); + compound_shape1.addShape(Vec3.sZero(), Quat.sIdentity(), new CapsuleShape(5, 1)); + compound_shape1.addShape(new Vec3(0, -5, 0), Quat.sIdentity(), new SphereShape(2)); + compound_shape1.addShape(new Vec3(0, 5, 0), Quat.sIdentity(), new SphereShape(2)); + + // Compound with sub compound and rotation + StaticCompoundShapeSettings sub_compound = new StaticCompoundShapeSettings(); + sub_compound.addShape(new Vec3(0, 1.5f, 0), Quat.sRotation(Vec3.sAxisZ(), 0.5f * JPH_PI), new BoxShape(new Vec3(1.5f, 0.25f, 0.2f))); + sub_compound.addShape(new Vec3(1.5f, 0, 0), Quat.sRotation(Vec3.sAxisZ(), 0.5f * JPH_PI), new CylinderShape(1.5f, 0.2f)); + sub_compound.addShape(new Vec3(0, 0, 1.5f), Quat.sRotation(Vec3.sAxisX(), 0.5f * JPH_PI), new TaperedCapsuleShapeSettings(1.5f, 0.25f, 0.2f)); + + StaticCompoundShapeSettings compound_shape2 = new StaticCompoundShapeSettings(); + compound_shape2.addShape(new Vec3(0, 0, 0), star(Quat.sRotation(Vec3.sAxisX(), -0.25f * JPH_PI) , Quat.sRotation(Vec3.sAxisZ(), 0.25f * JPH_PI)), sub_compound); + compound_shape2.addShape(new Vec3(0, -0.1f, 0), star(Quat.sRotation(Vec3.sAxisX(), 0.25f * JPH_PI) , Quat.sRotation(Vec3.sAxisZ(), -0.75f * JPH_PI)), sub_compound); + + // Compound with large amount of sub shapes + StaticCompoundShapeSettings compound_shape3 = new StaticCompoundShapeSettings(); + for (int y = -2; y <= 2; ++y) + for (int x = -2; x <= 2; ++x) + for (int z = -2; z <= 2; ++z) + compound_shape3.addShape(new Vec3(0.5f * x, 0.5f * y, 0.5f * z), star(Quat.sRotation(Vec3.sAxisX(), -0.25f * JPH_PI) , Quat.sRotation(Vec3.sAxisZ(), 0.25f * JPH_PI)), new BoxShape(Vec3.sReplicate(0.5f))); + + StaticCompoundShapeSettings shapes[] = { compound_shape1, compound_shape2, compound_shape3 }; + + for (int i = 0; i < 10; ++i) + for (int j = 0; j < 3; ++j) + { + Quat rotation; + if ((i & 1) == 0) + rotation = Quat.sRotation(Vec3.sAxisX(), 0.5f * JPH_PI); + else + rotation = Quat.sRotation(Vec3.sAxisZ(), 0.5f * JPH_PI); + mBodyInterface.createAndAddBody(new BodyCreationSettings(shapes[j],new RVec3(0, 10.0f + 4.0f * i, j * 20.0f), rotation, EMotionType.Dynamic, Layers.MOVING), EActivation.Activate); + } +} +} diff --git a/src/test/java/testjoltjni/app/samples/shapes/TaperedCapsuleShapeTest.java b/src/test/java/testjoltjni/app/samples/shapes/TaperedCapsuleShapeTest.java new file mode 100644 index 00000000..3f3a5de0 --- /dev/null +++ b/src/test/java/testjoltjni/app/samples/shapes/TaperedCapsuleShapeTest.java @@ -0,0 +1,75 @@ +/* +Copyright (c) 2024 Stephen Gold + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ +package testjoltjni.app.samples.shapes; +import com.github.stephengold.joltjni.*; +import com.github.stephengold.joltjni.enumerate.*; +import testjoltjni.app.samples.*; +import static com.github.stephengold.joltjni.Jolt.*; +/** + * A line-for-line Java translation of the Jolt Physics tapered-capsule shape test. + *

+ * Compare with the original by Jorrit Rouwe at + * https://github.com/jrouwe/JoltPhysics/blob/master/Samples/Tests/Shapes/TaperedCapsuleShapeTest.cpp + */ +public class TaperedCapsuleShapeTest extends Test{ + +public void Initialize() +{ + // Floor + CreateFloor(); + + ShapeSettingsRef big_taperedcapsule = new TaperedCapsuleShapeSettings(2.0f, 1.0f, 3.0f).toRef(); + ShapeSettingsRef big_taperedcapsule2 = new TaperedCapsuleShapeSettings(2.0f, 3.0f, 1.0f).toRef(); + + // Tapered capsule on outer sphere + mBodyInterface.createAndAddBody(new BodyCreationSettings(big_taperedcapsule,new RVec3(0, 10, 0), Quat.sIdentity(), EMotionType.Dynamic, Layers.MOVING), EActivation.Activate); + + // Tapered capsule on other outer sphere + mBodyInterface.createAndAddBody(new BodyCreationSettings(big_taperedcapsule2,new RVec3(10, 10, 0), Quat.sIdentity(), EMotionType.Dynamic, Layers.MOVING), EActivation.Activate); + + // Tapered capsule on side + mBodyInterface.createAndAddBody(new BodyCreationSettings(big_taperedcapsule,new RVec3(20, 10, 0), Quat.sRotation(Vec3.sAxisX(), 0.5f * JPH_PI), EMotionType.Dynamic, Layers.MOVING), EActivation.Activate); + + ShapeSettingsRef long_taperedcapsule = new TaperedCapsuleShapeSettings(5, 0.5f, 1.0f).toRef(); + + // Tower of tapered capsules + for (int i = 0; i < 10; ++i) + { + for (int j = 0; j < 2; ++j) + { + RVec3 position; + Quat rotation; + if ((i & 1)!=0) + { + position =new RVec3(-4.0f + 8.0f * j, 2.0f + 3.0f * i, -20.0f); + rotation = Quat.sRotation(Vec3.sAxisX(), 0.5f * JPH_PI + (j & 1) * JPH_PI); + } + else + { + position =new RVec3(0, 2.0f + 3.0f * i, -20.0f - 4.0f + 8.0f * j); + rotation = Quat.sRotation(Vec3.sAxisZ(), 0.5f * JPH_PI + (j & 1) * JPH_PI); + } + mBodyInterface.createAndAddBody(new BodyCreationSettings(long_taperedcapsule, position, rotation, EMotionType.Dynamic, Layers.MOVING), EActivation.Activate); + } + } +} +} \ No newline at end of file diff --git a/src/test/java/testjoltjni/app/samples/shapes/TaperedCylinderShapeTest.java b/src/test/java/testjoltjni/app/samples/shapes/TaperedCylinderShapeTest.java new file mode 100644 index 00000000..976cad8e --- /dev/null +++ b/src/test/java/testjoltjni/app/samples/shapes/TaperedCylinderShapeTest.java @@ -0,0 +1,87 @@ +/* +Copyright (c) 2024 Stephen Gold + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ +package testjoltjni.app.samples.shapes; +import com.github.stephengold.joltjni.*; +import com.github.stephengold.joltjni.enumerate.*; +import testjoltjni.app.samples.*; +import static com.github.stephengold.joltjni.Jolt.*; +/** + * A line-for-line Java translation of the Jolt Physics tapered-cylinder shape test. + *

+ * Compare with the original by Jorrit Rouwe at + * https://github.com/jrouwe/JoltPhysics/blob/master/Samples/Tests/Shapes/TaperedCylinderShapeTest.cpp + */ +public class TaperedCylinderShapeTest extends Test{ + +public void Initialize() +{ + // Floor + CreateFloor(); + + ShapeSettingsRef big_taperedcylinder = new TaperedCylinderShapeSettings(2.0f, 1.0f, 3.0f).toRef(); + ShapeSettingsRef big_taperedcylinder2 = new TaperedCylinderShapeSettings(2.0f, 3.0f, 1.0f).toRef(); + + // Tapered cylinder on large radius + mBodyInterface.createAndAddBody(new BodyCreationSettings(big_taperedcylinder,new RVec3(0, 10, 0), Quat.sIdentity(), EMotionType.Dynamic, Layers.MOVING), EActivation.Activate); + + // Tapered cylinder on small radius + mBodyInterface.createAndAddBody(new BodyCreationSettings(big_taperedcylinder2,new RVec3(10, 10, 0), Quat.sIdentity(), EMotionType.Dynamic, Layers.MOVING), EActivation.Activate); + + // Tapered cylinder on side + mBodyInterface.createAndAddBody(new BodyCreationSettings(big_taperedcylinder,new RVec3(20, 10, 0), Quat.sRotation(Vec3.sAxisX(), 0.5f * JPH_PI), EMotionType.Dynamic, Layers.MOVING), EActivation.Activate); + + ShapeSettingsRef big_cone = new TaperedCylinderShapeSettings(2.0f, 0.0f, 3.0f, 0.0f).toRef(); + ShapeSettingsRef big_cone2 = new TaperedCylinderShapeSettings(2.0f, 3.0f, 0.0f, 0.0f).toRef(); + + // Cone on large radius + mBodyInterface.createAndAddBody(new BodyCreationSettings(big_cone,new RVec3(0, 10, 10), Quat.sIdentity(), EMotionType.Dynamic, Layers.MOVING), EActivation.Activate); + + // Cone on small radius + mBodyInterface.createAndAddBody(new BodyCreationSettings(big_cone2,new RVec3(10, 10, 10), Quat.sIdentity(), EMotionType.Dynamic, Layers.MOVING), EActivation.Activate); + + // Cone on side + mBodyInterface.createAndAddBody(new BodyCreationSettings(big_cone,new RVec3(20, 10, 10), Quat.sRotation(Vec3.sAxisX(), 0.5f * JPH_PI), EMotionType.Dynamic, Layers.MOVING), EActivation.Activate); + + ShapeSettingsRef long_taperedcylinder = new TaperedCylinderShapeSettings(5, 0.5f, 1.0f).toRef(); + + // Tower of tapered cylinders + for (int i = 0; i < 10; ++i) + { + for (int j = 0; j < 2; ++j) + { + RVec3 position; + Quat rotation; + if ((i & 1)!=0) + { + position =new RVec3(-4.0f + 8.0f * j, 2.0f + 3.0f * i, -20.0f); + rotation = Quat.sRotation(Vec3.sAxisX(), 0.5f * JPH_PI + (j & 1) * JPH_PI); + } + else + { + position =new RVec3(0, 2.0f + 3.0f * i, -20.0f - 4.0f + 8.0f * j); + rotation = Quat.sRotation(Vec3.sAxisZ(), 0.5f * JPH_PI + (j & 1) * JPH_PI); + } + mBodyInterface.createAndAddBody(new BodyCreationSettings(long_taperedcylinder, position, rotation, EMotionType.Dynamic, Layers.MOVING), EActivation.Activate); + } + } +} +} \ No newline at end of file diff --git a/src/test/java/testjoltjni/app/samples/shapes/TriangleShapeTest.java b/src/test/java/testjoltjni/app/samples/shapes/TriangleShapeTest.java new file mode 100644 index 00000000..7011ee3c --- /dev/null +++ b/src/test/java/testjoltjni/app/samples/shapes/TriangleShapeTest.java @@ -0,0 +1,44 @@ +/* +Copyright (c) 2024 Stephen Gold + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ +package testjoltjni.app.samples.shapes; +import com.github.stephengold.joltjni.*; +import com.github.stephengold.joltjni.enumerate.*; +import testjoltjni.app.samples.*; +/** + * A line-for-line Java translation of the Jolt Physics triangle-shape test. + *

+ * Compare with the original by Jorrit Rouwe at + * https://github.com/jrouwe/JoltPhysics/blob/master/Samples/Tests/Shapes/TriangleShapeTest.cpp + */ +public class TriangleShapeTest extends Test{ + +public void Initialize() +{ + // Single triangle + TriangleShape triangle_shape = new TriangleShape(new Vec3(-10, -1, 0),new Vec3(0, 1, 10),new Vec3(10, -2, -10), 0.01f); + mBodyInterface.createAndAddBody(new BodyCreationSettings(triangle_shape, RVec3.sZero(), Quat.sIdentity(), EMotionType.Static, Layers.NON_MOVING), EActivation.DontActivate); + + // Create a box above the triangle + BoxShape box_shape = new BoxShape(new Vec3(0.2f, 0.2f, 0.4f), 0.01f); + mBodyInterface.createAndAddBody(new BodyCreationSettings(box_shape,new RVec3(0, 5, 0), Quat.sIdentity(), EMotionType.Dynamic, Layers.MOVING), EActivation.Activate); +} +}