Skip to content

Commit

Permalink
feat(core): implement all the supported Joints
Browse files Browse the repository at this point in the history
  • Loading branch information
Neosoulink committed Nov 19, 2024
1 parent 1094cec commit 27e0abc
Show file tree
Hide file tree
Showing 7 changed files with 297 additions and 95 deletions.
5 changes: 4 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,8 @@
"cSpell.words": [
"cientos",
"tresjs"
]
],
"[typescript]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
}
}
5 changes: 2 additions & 3 deletions playground/src/pages/basics/JointsDemo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { OrbitControls } from '@tresjs/cientos'
import { TresCanvas } from '@tresjs/core'
// eslint-disable-next-line ts/ban-ts-comment
// @ts-ignore
import { type ExposedRigidBody, Joint, Physics, RigidBody } from '@tresjs/rapier'
import { type ExposedRigidBody, Physics, RigidBody, SphericalJoint } from '@tresjs/rapier'
import { ACESFilmicToneMapping, Quaternion, SRGBColorSpace } from 'three'
import { shallowRef } from 'vue'
import type { ShallowRef } from 'vue'
Expand Down Expand Up @@ -52,10 +52,9 @@ setInterval(() => {
</TresMesh>
</RigidBody>

<Joint
<SphericalJoint
v-for="(ref, i) in bodyRefs"
:key="i"
type="spherical"
:bodies="[ref.value?.[0]?.instance, bodyRefs[i - 1]?.value?.[0]?.instance]"
:params="[
[-1.1, 0, 0],
Expand Down
89 changes: 0 additions & 89 deletions src/components/Joint.vue

This file was deleted.

2 changes: 1 addition & 1 deletion src/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export * from './colliders'
export { default as InstancedRigidBody } from './InstancedRigidBody.vue'
export { default as Joint } from './Joint.vue'
export * from './joints'
export { default as Physics } from './Physics.vue'
export { default as RigidBody } from './RigidBody.vue'
185 changes: 185 additions & 0 deletions src/components/joints/BaseJoint.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
<script lang="ts" setup>
import { type ImpulseJoint, type JointAxesMask, type JointData, Quaternion, Vector3 } from '@dimforge/rapier3d-compat'
import { onUnmounted, shallowRef, watch } from 'vue'
import { useRapier } from '../../composables'
import type { JointProps, QuaternionArray, VectorArray } from '../../types'
const {
type = 'fixed',
bodies,
params = [
[0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0],
[0, 0, 0, 0],
],
wakeUpOnChanges = true,
} = defineProps<JointProps>()
const { world, rapier } = useRapier()
const joins = shallowRef<ImpulseJoint>()
watch(() => bodies, (bodies) => {
if (
joins.value
|| !(bodies?.[0] instanceof rapier.RigidBody)
|| !(bodies?.[1] instanceof rapier.RigidBody)
|| !Array.isArray(params)
) {
return
}
let jointParams: JointData | undefined
let hasParamsError = false
if (
type === 'fixed'
&& params.length >= 4
&& (Array.isArray(params[0]) && params[0].length >= 3)
&& (Array.isArray(params[1]) && params[1].length >= 4)
&& (Array.isArray(params[2]) && params[2].length >= 3)
&& (Array.isArray(params[3]) && params[3].length >= 4)
) {
jointParams = rapier.JointData.fixed(
new Vector3(...params[0] as VectorArray),
new Quaternion(...params[1] as QuaternionArray),
new Vector3(...params[2] as VectorArray),
new Quaternion(...params[3] as QuaternionArray),
)
}
else if (type === 'fixed') {
hasParamsError = true
}
if (
type === 'generic'
&& params.length >= 3
&& (Array.isArray(params[0]) && params[0].length >= 3)
&& (Array.isArray(params[1]) && params[1].length >= 3)
&& (Array.isArray(params[2]) && params[2].length >= 3)
&& typeof params[3] === 'number'
) {
jointParams = rapier.JointData.generic(
new Vector3(...params[0] as VectorArray),
new Vector3(...params[1] as VectorArray),
new Vector3(...params[2] as VectorArray),
params[3] as JointAxesMask,
)
}
else if (type === 'generic') {
hasParamsError = true
}
if (
type === 'prismatic'
&& params.length >= 4
&& (Array.isArray(params[0]) && params[0].length >= 3)
&& (Array.isArray(params[1]) && params[1].length >= 3)
&& (Array.isArray(params[2]) && params[2].length >= 3)
) {
jointParams = rapier.JointData.prismatic(
new Vector3(...params[0] as VectorArray),
new Vector3(...params[1] as VectorArray),
new Vector3(...params[1] as VectorArray),
)
}
else if (type === 'prismatic') {
hasParamsError = true
}
if (
type === 'revolute'
&& params.length >= 3
&& (Array.isArray(params[0]) && params[0].length >= 3)
&& (Array.isArray(params[1]) && params[1].length >= 3)
&& (Array.isArray(params[2]) && params[2].length >= 3)
) {
jointParams = rapier.JointData.revolute(
new Vector3(...params[0] as VectorArray),
new Vector3(...params[1] as VectorArray),
new Vector3(...params[2] as VectorArray),
)
}
else if (type === 'revolute') {
hasParamsError = true
}
if (
type === 'rope'
&& params.length >= 3
&& typeof params[0] === 'number'
&& (Array.isArray(params[1]) && params[1].length >= 3)
&& (Array.isArray(params[2]) && params[2].length >= 4)
) {
jointParams = rapier.JointData.rope(
params[0],
new Vector3(...params[1] as VectorArray),
new Quaternion(...params[2] as QuaternionArray),
)
}
else if (type === 'rope') {
hasParamsError = true
}
if (
type === 'spherical'
&& params.length >= 2
&& (Array.isArray(params[0]) && params[0].length >= 3)
&& (Array.isArray(params[1]) && params[1].length >= 3)
) {
jointParams = rapier.JointData.spherical(
new Vector3(...params[0] as VectorArray),
new Vector3(...params[1] as VectorArray),
)
}
else if (type === 'spherical') {
hasParamsError = true
}
if (
type === 'spring'
&& params.length >= 5
&& typeof params[0] === 'number'
&& typeof params[1] === 'number'
&& typeof params[2] === 'number'
&& (Array.isArray(params[3]) && params[3].length >= 3)
&& (Array.isArray(params[4]) && params[4].length >= 3)
) {
jointParams = rapier.JointData.spring(
params[0],
params[1],
params[2],
new Vector3(...params[3] as VectorArray),
new Vector3(...params[4] as VectorArray),
)
}
else if (type === 'spring') {
hasParamsError = true
}
if (hasParamsError) {
throw new Error(`Invalid "${type}" joint parameters`)
}
if (!jointParams) {
throw new Error(`Unsupported joint type. If you think this is a bug or the "${type}" type should be implemented, please open an issue.`)
}
joins.value = world.createImpulseJoint(jointParams, bodies[0], bodies[1], wakeUpOnChanges)
})
onUnmounted(() => {
if (joins.value) {
world.removeImpulseJoint(joins.value, wakeUpOnChanges)
}
})
defineExpose({
joins,
})
</script>

<template>
<slot v-once></slot>
</template>
Loading

0 comments on commit 27e0abc

Please sign in to comment.