diff --git a/playground/package.json b/playground/package.json index 7476bf9..b7882a7 100644 --- a/playground/package.json +++ b/playground/package.json @@ -9,6 +9,7 @@ "preview": "vite preview" }, "dependencies": { + "@tresjs/cientos": "^3.6.0", "vue": "^3.3.4", "vue-router": "^4.2.5" }, diff --git a/playground/src/App.vue b/playground/src/App.vue index 6e26943..aa58c60 100644 --- a/playground/src/App.vue +++ b/playground/src/App.vue @@ -4,14 +4,14 @@ import { useRoute } from 'vue-router' const route = useRoute() function setBodyClass(routeName: string) { - document.title = `Rapier Playground - ${routeName}` - document.body.className = routeName + document.title = `Rapier Playground - ${routeName}` + document.body.className = routeName } watch([route], () => setBodyClass(route.name?.toString() ?? '')) diff --git a/playground/src/pages/basics/BasicsDemo.vue b/playground/src/pages/basics/BasicsDemo.vue deleted file mode 100644 index 762314e..0000000 --- a/playground/src/pages/basics/BasicsDemo.vue +++ /dev/null @@ -1 +0,0 @@ - diff --git a/playground/src/pages/basics/RigidBodyDemo.vue b/playground/src/pages/basics/RigidBodyDemo.vue new file mode 100644 index 0000000..18ffb82 --- /dev/null +++ b/playground/src/pages/basics/RigidBodyDemo.vue @@ -0,0 +1,56 @@ + + + diff --git a/playground/src/pages/index.vue b/playground/src/pages/index.vue index d027fb3..7eeae97 100644 --- a/playground/src/pages/index.vue +++ b/playground/src/pages/index.vue @@ -5,55 +5,59 @@ const sections = [{ icon: '📦', title: 'Basics', routes: basicsRoutes }] diff --git a/playground/src/router/routes/basics.ts b/playground/src/router/routes/basics.ts index 5aa7cb3..c69605c 100644 --- a/playground/src/router/routes/basics.ts +++ b/playground/src/router/routes/basics.ts @@ -1,7 +1,7 @@ export const basicsRoutes = [ { - path: '/basics/basic-setup', - name: 'Basic Setup', - component: () => import('../../pages/basics/BasicsDemo.vue'), + path: '/basics/rigid-body', + name: 'Rigid Body', + component: () => import('../../pages/basics/RigidBodyDemo.vue'), }, ] diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2b34336..a7bd8de 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -81,6 +81,9 @@ importers: playground: dependencies: + '@tresjs/cientos': + specifier: ^3.6.0 + version: 3.6.0(@tresjs/core@3.5.0)(three@0.158.0)(tweakpane@4.0.1)(vue@3.3.8) vue: specifier: ^3.3.4 version: 3.3.8(typescript@5.2.2) @@ -957,6 +960,30 @@ packages: resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} dev: true + /@tresjs/cientos@3.6.0(@tresjs/core@3.5.0)(three@0.158.0)(tweakpane@4.0.1)(vue@3.3.8): + resolution: {integrity: sha512-VM6LamAFlcKufbrtbYN71ncuAw2JPVfKUC6Ey9+scq05qvHdQM8fU0WoppNZEtmIL7m2aUqroOZRnr9LXyZPCg==} + peerDependencies: + '@tresjs/core': '>=3.2' + three: '>=0.133' + tweakpane: '>=3.0.0' + vue: '>=3.3' + dependencies: + '@tresjs/core': 3.5.0(three@0.158.0)(vue@3.3.8) + '@vueuse/core': 10.5.0(vue@3.3.8) + camera-controls: 2.7.3(three@0.158.0) + stats-gl: 1.0.7 + stats.js: 0.17.0 + three: 0.158.0 + three-custom-shader-material: 5.4.0(three@0.158.0) + three-stdlib: 2.28.5(three@0.158.0) + tweakpane: 4.0.1 + vue: 3.3.8(typescript@5.2.2) + transitivePeerDependencies: + - '@react-three/fiber' + - '@vue/composition-api' + - react + dev: false + /@tresjs/core@3.5.0(three@0.158.0)(vue@3.3.8): resolution: {integrity: sha512-kh9QoLMWfkO2V4lytdJTARhfpC+Hf8JH/aTLsqYOirhHla4tTahQn5lHVrFwgkYjES/Qwr+UX84U2J6CQHBT3g==} peerDependencies: @@ -1039,6 +1066,10 @@ packages: resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} dev: true + /@types/draco3d@1.4.8: + resolution: {integrity: sha512-hdA2gODc+1X5gG+buH8gMRnQdRTa3vep8+PyGFK9xDQmbdudobP//yXLK+C/SnjGLWHiER2QL+xWjq7qkFuivA==} + dev: false + /@types/estree@1.0.5: resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} dev: true @@ -1086,6 +1117,10 @@ packages: resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} dev: true + /@types/offscreencanvas@2019.7.3: + resolution: {integrity: sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A==} + dev: false + /@types/semver@7.5.4: resolution: {integrity: sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==} dev: true @@ -1112,7 +1147,6 @@ packages: /@types/webxr@0.5.7: resolution: {integrity: sha512-Rcgs5c2eNFnHp53YOjgtKfl/zWX1Y+uFGUwlSXrWcZWu3yhANRezmph4MninmqybUYT6g9ZE0aQ9QIdPkLR3Kg==} - dev: true /@typescript-eslint/eslint-plugin@6.10.0(@typescript-eslint/parser@6.10.0)(eslint@8.53.0)(typescript@5.2.2): resolution: {integrity: sha512-uoLj4g2OTL8rfUQVx2AFO1hp/zja1wABJq77P6IclQs6I/m9GLrm7jCdgzZkvWdDCQf1uEvoa8s8CupsgWQgVg==} @@ -2069,6 +2103,14 @@ packages: engines: {node: '>=14.16'} dev: true + /camera-controls@2.7.3(three@0.158.0): + resolution: {integrity: sha512-L4mxjBd3u8qiOLozdWrH2P8ZybSsDXBF7iyNyqNEFJhPUkovmuARWR8JTc1B/qlclOIg6FvZZA/0uAZMMim0mw==} + peerDependencies: + three: '>=0.126.1' + dependencies: + three: 0.158.0 + dev: false + /chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -2384,6 +2426,10 @@ packages: meow: 12.1.1 dev: true + /core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + dev: false + /cosmiconfig@8.3.6(typescript@5.2.2): resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} engines: {node: '>=14'} @@ -2626,6 +2672,10 @@ packages: is-obj: 2.0.0 dev: true + /draco3d@1.5.6: + resolution: {integrity: sha512-+3NaRjWktb5r61ZFoDejlykPEFKT5N/LkbXsaddlw6xNSXBanUYpFc2AXXpbJDilPHazcSreU/DpQIaxfX0NfQ==} + dev: false + /dts@0.1.1: resolution: {integrity: sha512-A8yu9cMgPtCg2xlxwYvukVCjKGUNKzkHUNSMDmTNz4ixlpyIMQ72Uz28W5Au+2i87NokUFFTXYTiHCb+RdAnVw==} dev: true @@ -3251,7 +3301,6 @@ packages: /fflate@0.6.10: resolution: {integrity: sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==} - dev: true /figures@5.0.0: resolution: {integrity: sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==} @@ -3531,6 +3580,20 @@ packages: unicorn-magic: 0.1.0 dev: true + /glsl-token-functions@1.0.1: + resolution: {integrity: sha512-EigGhp1g+aUVeUNY7H1o5tL/bnwIB3/FcRREPr2E7Du+/UDXN24hDkaZ3e4aWHDjHr9lJ6YHXMISkwhUYg9UOg==} + dev: false + + /glsl-token-string@1.0.1: + resolution: {integrity: sha512-1mtQ47Uxd47wrovl+T6RshKGkRRCYWhnELmkEcUAPALWGTFe2XZpH3r45XAwL2B6v+l0KNsCnoaZCSnhzKEksg==} + dev: false + + /glsl-tokenizer@2.1.5: + resolution: {integrity: sha512-XSZEJ/i4dmz3Pmbnpsy3cKh7cotvFlBiZnDOwnj/05EwNp2XrhQ4XKJxT7/pDt4kp4YcpRSKz8eTV7S+mwV6MA==} + dependencies: + through2: 0.6.5 + dev: false + /gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: @@ -3767,7 +3830,6 @@ packages: /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: true /ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} @@ -4104,6 +4166,10 @@ packages: is-docker: 2.2.1 dev: true + /isarray@0.0.1: + resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} + dev: false + /isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} dev: true @@ -4615,6 +4681,11 @@ packages: boolbase: 1.0.0 dev: true + /object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + dev: false + /object-inspect@1.13.1: resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} dev: true @@ -4980,6 +5051,10 @@ packages: picocolors: 1.0.0 source-map-js: 1.0.2 + /potpack@1.0.2: + resolution: {integrity: sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==} + dev: false + /preact@10.18.2: resolution: {integrity: sha512-X/K43vocUHDg0XhWVmTTMbec4LT/iBMh+csCEqJk+pJqegaXsvjdqN80ZZ3L+93azWCnWCZ+WGwYb8SplxeNjA==} dev: true @@ -5103,6 +5178,15 @@ packages: type-fest: 4.6.0 dev: true + /readable-stream@1.0.34: + resolution: {integrity: sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==} + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 0.0.1 + string_decoder: 0.10.31 + dev: false + /readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} @@ -5513,6 +5597,14 @@ packages: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} dev: true + /stats-gl@1.0.7: + resolution: {integrity: sha512-vZI82CjefSxLC1bjw36z28v0+QE9rJKymGlXtfWu+ipW70ZEAwa4EbO4LxluAfLfpqiaAS04NzpYBRLDeAwYWQ==} + dev: false + + /stats.js@0.17.0: + resolution: {integrity: sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw==} + dev: false + /stdin-discarder@0.1.0: resolution: {integrity: sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -5584,6 +5676,10 @@ packages: es-abstract: 1.22.3 dev: true + /string_decoder@0.10.31: + resolution: {integrity: sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==} + dev: false + /string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} dependencies: @@ -5674,10 +5770,50 @@ packages: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} dev: true + /three-custom-shader-material@5.4.0(three@0.158.0): + resolution: {integrity: sha512-Yn1lFlKOk3Vul3npEGAmbbFUZ5S2+yjPgM2XqJEZEYRSUUH2vk+WVYrtTB6Bcq15wa7hLUXAKoctAvbRmBmbYA==} + peerDependencies: + '@react-three/fiber': '>=8.0' + react: '>=18.0' + three: '>=0.154' + peerDependenciesMeta: + '@react-three/fiber': + optional: true + react: + optional: true + dependencies: + glsl-token-functions: 1.0.1 + glsl-token-string: 1.0.1 + glsl-tokenizer: 2.1.5 + object-hash: 3.0.0 + three: 0.158.0 + dev: false + + /three-stdlib@2.28.5(three@0.158.0): + resolution: {integrity: sha512-JdLMhkpT+1ZWeQPyKQNW1zqUwISI2hsUljS6u3vB9lp5EvwsayaAzGnbVeR35895udOF+zxcTiQY3psk+qqlxg==} + peerDependencies: + three: '>=0.128.0' + dependencies: + '@types/draco3d': 1.4.8 + '@types/offscreencanvas': 2019.7.3 + '@types/webxr': 0.5.7 + draco3d: 1.5.6 + fflate: 0.6.10 + potpack: 1.0.2 + three: 0.158.0 + dev: false + /three@0.158.0: resolution: {integrity: sha512-TALj4EOpdDPF1henk2Q+s17K61uEAAWQ7TJB68nr7FKxqwyDr3msOt5IWdbGm4TaWKjrtWS8DJJWe9JnvsWOhQ==} dev: false + /through2@0.6.5: + resolution: {integrity: sha512-RkK/CCESdTKQZHdmKICijdKKsCRVHs5KsLZ6pACAmF/1GPUQhonHSXWNERctxEp7RmvjdNbZTL5z9V7nSCXKcg==} + dependencies: + readable-stream: 1.0.34 + xtend: 4.0.2 + dev: false + /through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} dev: true @@ -5732,6 +5868,10 @@ packages: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} dev: true + /tweakpane@4.0.1: + resolution: {integrity: sha512-1JmmGbF4h2zuFbpN1XfIWcV0kLbBUgSXpR1QtW19vJFx44asnCrufRSvd69OItOFMEWgbVtoiWM2uDPUEUKcMQ==} + dev: false + /type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -6391,6 +6531,11 @@ packages: engines: {node: '>=12'} dev: true + /xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + dev: false + /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} dev: true diff --git a/src/composables/useRapier.ts b/src/composables/useRapier.ts index e69de29..4d75020 100644 --- a/src/composables/useRapier.ts +++ b/src/composables/useRapier.ts @@ -0,0 +1,76 @@ +import type { World } from '@dimforge/rapier3d-compat' +import type Rapier from '@dimforge/rapier3d-compat' +import { inject, provide } from 'vue' + +const GRAVITY = { x: 0, y: -9.81, z: 0 } +export interface RapierContext { + /** + * The Rapier physics world + */ + world: World + setWorld: (world: World) => void + /** + * Direct access to the Rapier instance + */ + rapier: typeof Rapier + /** + * Step the physics world one step + * + * @param deltaTime The delta time to step the world with + * + * @example + * ``` + * step(1/60) + * ``` + */ + step: (deltaTime: number) => void + /** + * If the physics simulation is paused + */ + isPaused: boolean + /** + * Is debug mode enabled + */ + isDebug: boolean +} + +export async function useRapierContextProvider() { + const toProvide = { + world: null as World | null, + setWorld: (world: World) => { + toProvide.world = world + }, + rapier: null as typeof Rapier | null, + step: (deltaTime: number) => { + if (toProvide.world) { + toProvide.world.step(deltaTime) + } + }, + isPaused: false, + isDebug: false, + } + + provide('useRapier', toProvide) + + toProvide.rapier = await import('@dimforge/rapier3d-compat') + await toProvide.rapier.init() + + /* + Initialize the world with gravity and timestep. + */ + toProvide.world = new toProvide.rapier.World(GRAVITY) + + return toProvide +} + +export function useRapierContext(): RapierContext { + const context = inject>('useRapier') + + if (!context) { + throw new Error('useRapierContext must be used together with useRapierContextProvider') + } + + return context as RapierContext +} + +export const useRapier = useRapierContext \ No newline at end of file diff --git a/src/core/Debug.vue b/src/core/Debug.vue new file mode 100644 index 0000000..51bbcbe --- /dev/null +++ b/src/core/Debug.vue @@ -0,0 +1,37 @@ + + + \ No newline at end of file diff --git a/src/core/Physics.vue b/src/core/Physics.vue index c080008..b546446 100644 --- a/src/core/Physics.vue +++ b/src/core/Physics.vue @@ -1,6 +1,31 @@ \ No newline at end of file + + + diff --git a/src/core/RigidBody.vue b/src/core/RigidBody.vue index c080008..b46267e 100644 --- a/src/core/RigidBody.vue +++ b/src/core/RigidBody.vue @@ -1,6 +1,104 @@ \ No newline at end of file + + + + diff --git a/src/core/index.ts b/src/core/index.ts new file mode 100644 index 0000000..ee68270 --- /dev/null +++ b/src/core/index.ts @@ -0,0 +1,7 @@ +import Physics from './Physics.vue' +import RigidBody from './RigidBody.vue' + +export { + Physics, + RigidBody +} diff --git a/src/core/inyectionKeys.ts b/src/core/injectionKeys.ts similarity index 98% rename from src/core/inyectionKeys.ts rename to src/core/injectionKeys.ts index ca2d0ce..5f681a4 100644 --- a/src/core/inyectionKeys.ts +++ b/src/core/injectionKeys.ts @@ -1,6 +1,7 @@ import type { InjectionKey, ShallowRef } from 'vue' export interface RapierContext { - + } + export const rapierInjectionKey: InjectionKey> = Symbol() diff --git a/src/index.ts b/src/index.ts index 4e86691..46d458a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1 @@ -import Physics from './core/Physics.vue' -import RigidBody from './core/RigidBody.vue' \ No newline at end of file +export * from './core'