Skip to content

Commit

Permalink
feat: continuation of update @dimforge/rapier3d-compat to 0.12.0 + op…
Browse files Browse the repository at this point in the history
…timizations (#619)
  • Loading branch information
0xtito authored Feb 13, 2024
1 parent e2b361f commit 1517acb
Show file tree
Hide file tree
Showing 16 changed files with 579 additions and 131 deletions.
12 changes: 12 additions & 0 deletions .changeset/cold-apples-drop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
"@react-three/rapier": minor
---

feat: update @dimforge/rapier3d-compat to 0.12.0 (@0xtito, @isaac-mason)

- Change Physics component props to match the new rapier version's integration parameter changes.
- There aren't direct alternatives for all old parameters. See the Physics component docs for more information on the new parameters: https://pmndrs.github.io/react-three-rapier/interfaces/PhysicsProps.html
- Add `additionalSolverIterations` prop to `RigidBodyOptions`.
- See: https://pmndrs.github.io/react-three-rapier/interfaces/RigidBodyOptions.html#additionalSolverIterations
- Add `useSpringJoint`
- Add `useRopeJoint`
10 changes: 10 additions & 0 deletions .changeset/pre.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"mode": "pre",
"tag": "canary",
"initialVersions": {
"demo": "0.0.0",
"@react-three/rapier": "1.2.1",
"@react-three/rapier-addons": "3.0.3"
},
"changesets": []
}
30 changes: 16 additions & 14 deletions demo/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { Box, Environment, OrbitControls } from "@react-three/drei";
import { Canvas } from "@react-three/fiber";
import { Physics, RigidBody, useRapier } from "@react-three/rapier";
import { Physics, RigidBody } from "@react-three/rapier";
import { Perf } from "r3f-perf";
import {
createContext,
ReactNode,
StrictMode,
Suspense,
createContext,
useContext,
useState,
StrictMode,
useEffect
useState
} from "react";
import { NavLink, NavLinkProps, Route, Routes } from "react-router-dom";
import { AllCollidersExample } from "./examples/all-colliders/AllCollidersExample";
Expand All @@ -24,21 +23,23 @@ import { ComponentsExample } from "./examples/components/ComponentsExample";
import { ContactForceEventsExample } from "./examples/contact-force-events/ContactForceEventsExample";
import { CradleExample } from "./examples/cradle/CradleExample";
import { Damping } from "./examples/damping/DampingExample";
import { DynamicTypeChangeExample } from "./examples/dynamic-type-change/DynamicTypeChangeExample";
import { ImmutablePropsExample } from "./examples/immutable-props/ImmutablePropsExample";
import { InstancedMeshes } from "./examples/instanced-meshes/InstancedMeshesExample";
import { InstancedMeshesCompound } from "./examples/instances-meshes-compound/InstancedMeshesCompoundExample";
import { Joints } from "./examples/joints/JointsExample";
import { Kinematics } from "./examples/kinematics/KinematicsExample";
import { LockedTransformsExample } from "./examples/locked-transforms/LockedTransformsExample";
import { ManualStepExample } from "./examples/manual-step/ManualStepExamples";
import { MeshColliderTest } from "./examples/mesh-collider-test/MeshColliderExample";
import { SensorsExample } from "./examples/sensors/SensorsExample";
import Shapes from "./examples/plinko/ShapesExample";
import { Transforms } from "./examples/transforms/TransformsExample";
import { LockedTransformsExample } from "./examples/locked-transforms/LockedTransformsExample";
import { PerformanceExample } from "./examples/performance/PeformanceExample";
import { DynamicTypeChangeExample } from "./examples/dynamic-type-change/DynamicTypeChangeExample";
import Shapes from "./examples/plinko/ShapesExample";
import { RopeJointExample } from "./examples/rope-joint/RopeJointExample";
import { SensorsExample } from "./examples/sensors/SensorsExample";
import { SnapshotExample } from "./examples/snapshot/SnapshotExample";
import { SpringExample } from "./examples/spring/SpringExample";
import { StutteringExample } from "./examples/stuttering/StutteringExample";
import { ImmutablePropsExample } from "./examples/immutable-props/ImmutablePropsExample";
import { SnapshotExample } from './examples/snapshot/SnapshotExample';
import { Transforms } from "./examples/transforms/TransformsExample";

const demoContext = createContext<{
setDebug?(f: boolean): void;
Expand Down Expand Up @@ -116,7 +117,9 @@ const routes: Record<string, ReactNode> = {
"dynamic-type-changes": <DynamicTypeChangeExample />,
stuttering: <StutteringExample />,
"immutable-props": <ImmutablePropsExample />,
snapshot: <SnapshotExample />
snapshot: <SnapshotExample />,
spring: <SpringExample />,
"rope-joint": <RopeJointExample />
};

export const App = () => {
Expand Down Expand Up @@ -149,7 +152,6 @@ export const App = () => {
interpolate={interpolate}
debug={debug}
timeStep={1 / 60}
// erp={0.2}
>
<directionalLight
castShadow
Expand Down
9 changes: 1 addition & 8 deletions demo/src/examples/cradle/CradleExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ import {
RapierRigidBody,
RigidBody,
RigidBodyOptions,
useRapier,
useSphericalJoint
} from "@react-three/rapier";
import { useEffect, useRef } from "react";
import { useRef } from "react";
import { Demo } from "../../App";

const Rod = (props: RigidBodyOptions) => {
Expand All @@ -20,12 +19,6 @@ const Rod = (props: RigidBodyOptions) => {
[0, 0, 0]
]);

const { world } = useRapier();

useEffect(() => {
world.maxStabilizationIterations = 10;
}, []);

return (
<group>
<RigidBody ref={anchor} {...props} />
Expand Down
120 changes: 120 additions & 0 deletions demo/src/examples/rope-joint/RopeJointExample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { Sphere, Box } from "@react-three/drei";
import {
BallCollider,
RapierRigidBody,
RigidBody,
RigidBodyOptions,
useRopeJoint
} from "@react-three/rapier";
import { useRef } from "react";
import { Demo } from "../../App";
import { Vector3 } from "@react-three/fiber";

const WALL_COLORS = ["#50514F", "#CBD4C2", "#FFFCFF", "#247BA0", "#C3B299"];

interface BoxRigidBodyProps extends RigidBodyOptions {
color: string;
}

interface BoxWallProps extends RigidBodyOptions {
height: number;
width: number;
}

interface RopeJointProps {
anchorPosition: Vector3;
ballPosition: Vector3;
ropeLength: number;
}

const Floor = (props: RigidBodyOptions) => {
return (
<RigidBody type="fixed" colliders="cuboid" position={[0, -1, 0]} {...props}>
<Box args={[20, 1, 20]}>
<meshStandardMaterial color="white" />
</Box>
</RigidBody>
);
};

const BoxRigidBody = (props: BoxRigidBodyProps) => {
return (
<RigidBody {...props}>
<Box castShadow receiveShadow>
<meshStandardMaterial color={props.color} />
</Box>
</RigidBody>
);
};

const BoxWall = ({ height, width, ...props }: BoxWallProps) => {
const wall = [];

for (let i = 0; i < height; i++) {
for (let j = 0; j < width; j++) {
const position: [number, number, number] = [j, i, 0];
wall.push(
<BoxRigidBody
key={`${i}-${j}`}
{...props}
density={2}
color={WALL_COLORS[i % 5]}
position={position}
/>
);
}
}

return (
<group name="wall" rotation-y={-0.7853982} position={[-1.8, 0, -1.8]}>
{wall.map((box, i) => box)}
</group>
);
};

const RopeJoint = ({
anchorPosition,
ballPosition,
ropeLength
}: RopeJointProps) => {
const anchor = useRef<RapierRigidBody>(null);
const ball = useRef<RapierRigidBody>(null);

useRopeJoint(anchor, ball, [[0, 0, 0], [0, 0, 0], ropeLength]);

return (
<group>
{/* Anchor */}
<RigidBody ref={anchor} position={anchorPosition} />

{/* Wrecking Ball */}
<RigidBody
position={ballPosition}
ref={ball}
restitution={1.2}
density={30}
colliders={false}
>
<Sphere args={[2]} receiveShadow castShadow>
<meshStandardMaterial metalness={1} roughness={0.3} />
</Sphere>

<BallCollider args={[2]} />
</RigidBody>
</group>
);
};

export const RopeJointExample: Demo = () => {
return (
<group position={[0, 0, 0]} scale={3}>
<Floor />
<BoxWall height={10} width={6} />
<RopeJoint
ropeLength={35}
anchorPosition={[0, 15, 0]}
ballPosition={[-8, 15, 8]}
/>
</group>
);
};
113 changes: 113 additions & 0 deletions demo/src/examples/spring/SpringExample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { Box, Sphere } from "@react-three/drei";
import {
BallCollider,
RapierRigidBody,
RigidBody,
RigidBodyOptions,
useSpringJoint
} from "@react-three/rapier";
import { forwardRef, useMemo, useRef } from "react";
import { Demo } from "../../App";
import { useForwardedRef } from "@react-three/rapier/src/hooks/use-forwarded-ref";
import { vectorArrayToVector3 } from "@react-three/rapier/src/utils/utils";

const COLORS_ARR = ["#335C67", "#FFF3B0", "#E09F3E", "#9E2A2B", "#540B0E"];

interface BallSpringProps extends RigidBodyOptions {
jointNum: number;
total: number;
}

interface BoxRigidBodyProps extends RigidBodyOptions {
color: string;
}

const BoxRigidBody = ({ color, ...props }: BoxRigidBodyProps) => {
return (
<RigidBody {...props} ccd canSleep={false}>
<Box castShadow receiveShadow>
<meshStandardMaterial color={color} />
</Box>
</RigidBody>
);
};

const BallSpring = forwardRef<RapierRigidBody, BallSpringProps>(
(props, floorRef) => {
const floor = useForwardedRef(floorRef);
const ball = useRef<RapierRigidBody>(null);

const stiffness = 1.0e3;
const criticalDamping = 2.0 * Math.sqrt(stiffness * (props.mass ?? 1));
const dampingRatio = props.jointNum / (props.total / 2);
const damping = dampingRatio * criticalDamping;

const ballPos = props.position as THREE.Vector3;

if (!ballPos) {
throw new Error("BallSpring requires a position prop");
}

useSpringJoint(ball, floor, [
[0, 0, 0],
[ballPos.x, ballPos.y - 3, ballPos.z],
0,
stiffness,
damping
]);

return (
<RigidBody
key={`spring-${props.jointNum}`}
{...props}
ref={ball}
ccd
name={`spring-${props.jointNum}`}
position={ballPos}
colliders={false}
canSleep={false}
>
<Sphere args={[0.5]} castShadow receiveShadow>
<meshStandardMaterial color="#E09F3E" />
</Sphere>
<BallCollider args={[0.5]} />
</RigidBody>
);
}
);

export const SpringExample: Demo = () => {
const floor = useRef<RapierRigidBody>(null);

const vectorArr = useMemo(() => {
return Array.from({ length: 30 }).map((_, i) => {
return vectorArrayToVector3([-20 + 1.5 * (i + 1), 7.5, -30]);
});
}, []);

return (
<>
<RigidBody ref={floor} position={[0, 0, 0]} type="fixed" />

{vectorArr.map((_, i) => (
<group key={`box-ball-${i}`}>
<BallSpring
key={`ball-${i}`}
ref={floor}
position={vectorArr[i]}
mass={1}
jointNum={i}
total={30}
/>
<BoxRigidBody
key={`box-${i}`}
color={COLORS_ARR[i % 5]}
position={[vectorArr[i].x, vectorArr[i].y + 3, vectorArr[i].z]}
colliders="cuboid"
density={100}
/>
</group>
))}
</>
);
};
2 changes: 1 addition & 1 deletion packages/react-three-rapier/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"three": ">=0.139.0"
},
"dependencies": {
"@dimforge/rapier3d-compat": "0.11.2",
"@dimforge/rapier3d-compat": "0.12.0",
"three-stdlib": "2.23.9",
"use-asset": "1.0.4"
},
Expand Down
Loading

0 comments on commit 1517acb

Please sign in to comment.