Skip to content

Commit

Permalink
Fix/instanced rigid bodies not applying options (#104)
Browse files Browse the repository at this point in the history
* fix(InstancedRigidBodies): pass options and events

* chore: changeset
  • Loading branch information
wiledal authored Sep 29, 2022
1 parent 2292dda commit 36328f7
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 29 deletions.
5 changes: 5 additions & 0 deletions .changeset/giant-beans-end.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@react-three/rapier": patch
---

Fix InstancedRigidBodies not passing options to colliders
7 changes: 4 additions & 3 deletions demo/src/cluster/ClusterExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
CuboidCollider,
InstancedRigidBodies,
InstancedRigidBodyApi,
useRapier,
useRapier
} from "@react-three/rapier";
import { createRef, useEffect, useRef } from "react";
import { Demo } from "../App";
Expand All @@ -19,7 +19,7 @@ export const Cluster: Demo = () => {

useFrame(() => {
if (!isPaused) {
api.current!.forEach((body) => {
api.current!.forEach(body => {
const p = body.translation();
p.normalize().multiplyScalar(-0.01);
body.applyImpulse(p);
Expand All @@ -34,9 +34,10 @@ export const Cluster: Demo = () => {
positions={Array.from({ length: BALLS }, (_, i) => [
Math.floor(i / 30) * 1,
(i % 30) * 0.5,
0,
0
])}
colliders={"ball"}
linearDamping={1}
>
<instancedMesh args={[undefined, undefined, BALLS]} castShadow>
<sphereBufferGeometry args={[0.2]} />
Expand Down
30 changes: 24 additions & 6 deletions packages/react-three-rapier/src/InstancedRigidBodies.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ import { vector3ToQuaternion, vectorArrayToVector3 } from "./utils";
import {
createRigidBodyState,
rigidBodyDescFromOptions,
setRigidBodyOptions
setRigidBodyOptions,
useRigidBodyEvents,
useUpdateRigidBodyOptions
} from "./utils-rigidbody";

export interface InstancedRigidBodiesProps
Expand All @@ -52,13 +54,18 @@ export const InstancedRigidBodies = forwardRef<
InstancedRigidBodyApi,
InstancedRigidBodiesProps
>((props: InstancedRigidBodiesProps, ref) => {
const { world, rigidBodyStates, physicsOptions } = useRapier();
const {
world,
rigidBodyStates,
physicsOptions,
rigidBodyEvents
} = useRapier();
const object = useRef<Object3D>(null);
const { positions, rotations, children, ...options } = props;

const instancesRef = useRef<
{ rigidBody: RapierRigidBody; api: RigidBodyApi }[]
>();
>([]);
const instancesRefGetter = useRef(() => {
if (!instancesRef.current) {
instancesRef.current = [];
Expand Down Expand Up @@ -115,9 +122,8 @@ export const InstancedRigidBodies = forwardRef<
_object3d.position.set(x, y, z);
_object3d.rotation.set(rx, ry, rz);
_object3d.applyMatrix4(invertedWorld);
mesh.setMatrixAt(index, _object3d.matrix);

// Set initial transforms based on world transforms
// will be replaced by the setRigidBodyOption below
rigidBody.setTranslation(_object3d.position, false);
rigidBody.setRotation(_object3d.quaternion, false);

Expand All @@ -136,7 +142,7 @@ export const InstancedRigidBodies = forwardRef<
world.removeRigidBody(rb.rigidBody);
rigidBodyStates.delete(rb.rigidBody.handle);
});
instancesRef.current = undefined;
instancesRef.current = [];
};
}, []);

Expand All @@ -149,6 +155,18 @@ export const InstancedRigidBodies = forwardRef<
);

useImperativeHandle(ref, () => api);
useUpdateRigidBodyOptions(
{ current: instancesRef.current.map(({ rigidBody }) => rigidBody) },
mergedOptions,
rigidBodyStates,
false
);
useRigidBodyEvents(
{ current: instancesRef.current.map(({ rigidBody }) => rigidBody) },
mergedOptions,
rigidBodyEvents,
false
);

return (
<RigidBodyContext.Provider
Expand Down
69 changes: 49 additions & 20 deletions packages/react-three-rapier/src/utils-rigidbody.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ const mutableRigidBodyOptionKeys = Object.keys(mutableRigidBodyOptions);
export const setRigidBodyOptions = (
rigidBody: RigidBody,
options: RigidBodyProps,
states: RigidBodyStateMap
states: RigidBodyStateMap,
updateTranslations: boolean = true
) => {
if (!rigidBody) {
return;
Expand All @@ -108,14 +109,16 @@ export const setRigidBodyOptions = (
const state = states.get(rigidBody.handle);

if (state) {
state.object.updateWorldMatrix(true, false);
if (updateTranslations) {
state.object.updateWorldMatrix(true, false);

_matrix4
.copy(state.object.matrixWorld)
.decompose(_position, _rotation, _scale);
_matrix4
.copy(state.object.matrixWorld)
.decompose(_position, _rotation, _scale);

rigidBody.setTranslation(_position, false);
rigidBody.setRotation(_rotation, false);
rigidBody.setTranslation(_position, false);
rigidBody.setRotation(_rotation, false);
}

mutableRigidBodyOptionKeys.forEach(key => {
if (key in options) {
Expand All @@ -129,17 +132,29 @@ export const setRigidBodyOptions = (
};

export const useUpdateRigidBodyOptions = (
rigidBodyRef: MutableRefObject<RigidBody | undefined>,
rigidBodyRef: MutableRefObject<RigidBody | RigidBody[] | undefined>,
props: RigidBodyProps,
states: RigidBodyStateMap
states: RigidBodyStateMap,
updateTranslations: boolean = true
) => {
useEffect(() => {
setRigidBodyOptions(rigidBodyRef.current!, props, states);
if ("length" in rigidBodyRef.current!) {
(rigidBodyRef.current as RigidBody[]).forEach(rigidBody => {
setRigidBodyOptions(rigidBody, props, states, updateTranslations);
});
} else {
setRigidBodyOptions(
rigidBodyRef.current!,
props,
states,
updateTranslations
);
}
}, [props]);
};

export const useRigidBodyEvents = (
rigidBodyRef: MutableRefObject<RigidBody | undefined>,
rigidBodyRef: MutableRefObject<RigidBody | RigidBody[] | undefined>,
props: RigidBodyProps,
events: EventMap
) => {
Expand All @@ -152,18 +167,32 @@ export const useRigidBodyEvents = (
onIntersectionExit
} = props;

const eventHandlers = {
onWake,
onSleep,
onCollisionEnter,
onCollisionExit,
onIntersectionEnter,
onIntersectionExit
};

useEffect(() => {
events.set(rigidBodyRef.current!.handle, {
onWake,
onSleep,
onCollisionEnter,
onCollisionExit,
onIntersectionEnter,
onIntersectionExit
});
if ("length" in rigidBodyRef.current!) {
(rigidBodyRef.current as RigidBody[]).forEach(rigidBody => {
events.set(rigidBody.handle, eventHandlers);
});
} else {
events.set(rigidBodyRef.current!.handle, eventHandlers);
}

return () => {
events.delete(rigidBodyRef.current!.handle);
if ("length" in rigidBodyRef.current!) {
(rigidBodyRef.current as RigidBody[]).forEach(rigidBody => {
events.delete(rigidBody.handle);
});
} else {
events.delete(rigidBodyRef.current!.handle);
}
};
}, [onWake, onSleep, onCollisionEnter, onCollisionExit]);
};

1 comment on commit 36328f7

@vercel
Copy link

@vercel vercel bot commented on 36328f7 Sep 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

react-three-rapier – ./

react-three-rapier-pmndrs.vercel.app
react-three-rapier-git-main-pmndrs.vercel.app
react-three-rapier.pmnd.rs

Please sign in to comment.