Skip to content

Commit e9bc2ee

Browse files
feat(rapier): fixing the demo, adding props to rigidBody, improve the demo (with custom collider and without)
1 parent 3ca458a commit e9bc2ee

2 files changed

Lines changed: 93 additions & 83 deletions

File tree

Lines changed: 86 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,106 @@
11
<script setup lang="ts">
2-
import { OrbitControls } from '@tresjs/cientos'
3-
import { TresCanvas } from '@tresjs/core'
4-
import { Physics, RigidBody } from '@tresjs/rapier'
5-
import { ACESFilmicToneMapping, SRGBColorSpace } from 'three'
6-
import { ref, shallowRef } from 'vue'
2+
import { OrbitControls } from "@tresjs/cientos";
3+
import { TresCanvas } from "@tresjs/core";
4+
import { TresLeches, useControls } from "@tresjs/leches";
5+
import { Physics, RigidBody, CuboidCollider } from "@tresjs/rapier";
6+
import { ACESFilmicToneMapping, SRGBColorSpace } from "three";
7+
import { shallowRef } from "vue";
78
89
const gl = {
9-
clearColor: '#1a1a2e',
10+
clearColor: "#1a1a2e",
1011
shadows: true,
1112
alpha: false,
1213
outputColorSpace: SRGBColorSpace,
1314
toneMapping: ACESFilmicToneMapping,
14-
}
15+
};
1516
16-
const sphereRef = shallowRef()
17-
const forceLog = ref<{ magnitude: number, time: number }[]>([])
18-
const maxEntries = 6
19-
20-
const FORCE_THRESHOLD = 10
17+
const sphereRef = shallowRef();
2118
2219
const onContactForce = (event: any) => {
23-
const magnitude = Math.round(event.totalForceMagnitude)
24-
forceLog.value.unshift({ magnitude, time: Date.now() })
25-
if (forceLog.value.length > maxEntries) {
26-
forceLog.value.pop()
27-
}
28-
}
20+
const magnitude = Math.round(event.totalForceMagnitude);
21+
console.log("jaime ~ onContactForce ~ magnitude:", magnitude);
22+
};
23+
const onContactForceCustomCollider = (event: any) => {
24+
const magnitude = Math.round(event.totalForceMagnitude);
25+
console.log("jaime ~ onContactForceCustomCollider ~ magnitude:", magnitude);
26+
};
2927
3028
const drop = () => {
31-
if (!sphereRef.value) { return }
32-
sphereRef.value.instance.setTranslation({ x: 0, y: 10, z: 0 }, true)
33-
sphereRef.value.instance.setLinvel({ x: 0, y: 0, z: 0 }, true)
34-
}
29+
if (!sphereRef.value) {
30+
return;
31+
}
32+
sphereRef.value.instance.setTranslation({ x: 0, y: 10, z: 0 }, true);
33+
sphereRef.value.instance.setLinvel({ x: 0, y: 0, z: 0 }, true);
34+
};
35+
36+
const { forceThreshold: FORCE_THRESHOLD, debug, activeContactForce } = useControls({
37+
debug: false,
38+
activeContactForce: true,
39+
forceThreshold: {
40+
label: "Force threshold",
41+
value: 10,
42+
min: 0,
43+
max: 25,
44+
step: 0.1,
45+
},
46+
acceptBtn: {
47+
label: "Drop ball",
48+
type: "button",
49+
onClick: () => {
50+
drop();
51+
},
52+
},
53+
});
3554
</script>
3655

3756
<template>
38-
<div class="relative h-full w-full">
39-
<TresCanvas v-bind="gl">
40-
<TresPerspectiveCamera :position="[0, 8, 20]" :look-at="[0, 0, 0]" />
41-
<OrbitControls />
57+
<TresLeches />
58+
<TresCanvas v-bind="gl">
59+
<TresPerspectiveCamera :position="[0, 8, 20]" :look-at="[0, 0, 0]" />
60+
<OrbitControls />
4261

43-
<TresAmbientLight :intensity="0.5" />
44-
<TresDirectionalLight :position="[5, 10, 5]" :intensity="1.5" cast-shadow />
62+
<TresAmbientLight :intensity="0.5" />
63+
<TresDirectionalLight :position="[5, 10, 5]" :intensity="1.5" cast-shadow />
4564

46-
<Suspense>
47-
<Physics>
48-
<!-- Falling sphere with contact force events enabled -->
49-
<RigidBody
50-
ref="sphereRef"
51-
active-contact-force
52-
:contact-force-event-threshold="FORCE_THRESHOLD"
53-
@contact-force="onContactForce"
54-
>
55-
<TresMesh :position="[0, 10, 0]" cast-shadow>
56-
<TresSphereGeometry :args="[1, 32, 32]" />
57-
<TresMeshStandardMaterial color="#e94560" />
58-
</TresMesh>
59-
</RigidBody>
60-
61-
<!-- Fixed floor -->
62-
<RigidBody type="fixed">
63-
<TresMesh receive-shadow>
64-
<TresBoxGeometry :args="[20, 0.5, 20]" />
65-
<TresMeshStandardMaterial color="#16213e" />
66-
</TresMesh>
67-
</RigidBody>
68-
</Physics>
69-
</Suspense>
70-
</TresCanvas>
65+
<Suspense>
66+
<Physics :debug>
67+
<!-- Falling sphere with contact force events enabled -->
68+
<RigidBody
69+
ref="sphereRef"
70+
:active-contact-force="activeContactForce"
71+
:contact-force-event-threshold="FORCE_THRESHOLD"
72+
@contact-force="onContactForce"
73+
collider="ball"
74+
>
75+
<
76+
<TresMesh :position="[0, 10, 0]" cast-shadow>
77+
<TresSphereGeometry :args="[1, 32, 32]" />
78+
<TresMeshStandardMaterial color="#e94560" />
79+
</TresMesh>
80+
</RigidBody>
7181

72-
<!-- HUD overlay -->
73-
<div class="absolute top-4 left-4 right-4 flex flex-col gap-3 pointer-events-none">
74-
<div class="bg-black/70 text-white rounded-lg p-4 text-sm font-mono max-w-xs">
75-
<p class="text-gray-400 mb-1 text-xs uppercase tracking-wide">Contact Force Events</p>
76-
<p class="text-gray-500 text-xs mb-3">
77-
Threshold: {{ FORCE_THRESHOLD }}
78-
</p>
79-
<div v-if="forceLog.length === 0" class="text-gray-500 italic text-xs">
80-
No events yet — drop the sphere!
81-
</div>
82-
<ul class="space-y-1">
83-
<li
84-
v-for="(entry, i) in forceLog"
85-
:key="entry.time"
86-
class="flex justify-between"
87-
:style="{ opacity: 1 - i * 0.14 }"
88-
>
89-
<span class="text-red-400">contact-force</span>
90-
<span class="text-yellow-300">{{ entry.magnitude }} N</span>
91-
</li>
92-
</ul>
93-
</div>
82+
<RigidBody :collider="false">
83+
<CuboidCollider
84+
:active-contact-force="activeContactForce"
85+
:contact-force-event-threshold="FORCE_THRESHOLD"
86+
@contact-force="onContactForceCustomCollider"
87+
:args="[1, 1, 1]"
88+
:position="[0, 10, 0]"
89+
/>
90+
<TresMesh :position="[0, 10, 0]" cast-shadow>
91+
<TresSphereGeometry :args="[1, 32, 32]" />
92+
<TresMeshStandardMaterial color="#e94560" />
93+
</TresMesh>
94+
</RigidBody>
9495

95-
<button
96-
class="pointer-events-auto bg-red-500 hover:bg-red-600 text-white font-bold py-2 px-4 rounded-lg w-fit text-sm"
97-
@click="drop"
98-
>
99-
Drop sphere
100-
</button>
101-
</div>
102-
</div>
96+
<!-- Fixed floor -->
97+
<RigidBody type="fixed">
98+
<TresMesh receive-shadow>
99+
<TresBoxGeometry :args="[20, 0.5, 20]" />
100+
<TresMeshStandardMaterial color="#16213e" />
101+
</TresMesh>
102+
</RigidBody>
103+
</Physics>
104+
</Suspense>
105+
</TresCanvas>
103106
</template>

‎packages/rapier/src/components/RigidBody.vue‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ const props = withDefaults(defineProps<Partial<RigidBodyProps>>(), {
4141
enabledTranslations: () => [true, true, true],
4242
4343
// Auto-generated colliders props
44+
activeContactForce: false,
45+
contactForceEventThreshold: 0,
4446
friction: 0.5,
4547
mass: 1,
4648
restitution: 0,
@@ -137,6 +139,9 @@ watch(() => props.activeCollision, value => setAutoColliderProp('activeCollision
137139
watch(() => props.activeCollisionTypes, value => setAutoColliderProp('activeCollisionTypes', value))
138140
watch(() => props.collisionGroups, value => setAutoColliderProp('collisionGroups', value))
139141
watch(() => props.sensor, value => setAutoColliderProp('sensor', value))
142+
watch(() => props.activeContactForce, value => setAutoColliderProp('activeContactForce', value))
143+
watch(() => props.contactForceEventThreshold, value => setAutoColliderProp('contactForceEventThreshold', value))
144+
140145
141146
watch([() => props.lockTranslations, instance], ([_lockTranslations, _]) => {
142147
if (!instance.value) { return }
@@ -195,6 +200,8 @@ onUnmounted(() => {
195200
:activeCollisionTypes="_props.activeCollisionTypes"
196201
:collisionGroups="_props.collisionGroups"
197202
:sensor="_props.sensor"
203+
:activeContactForce="_props.activeContactForce"
204+
:contactForceEventThreshold="_props.contactForceEventThreshold"
198205
/>
199206
<slot></slot>
200207
</TresGroup>

0 commit comments

Comments
 (0)