diff --git a/.github/workflows/inspect.yml b/.github/workflows/inspect.yml index 05d9ae8d3..8795bcdc8 100644 --- a/.github/workflows/inspect.yml +++ b/.github/workflows/inspect.yml @@ -7,7 +7,7 @@ defaults: shell: bash jobs: - fetch: + build: runs-on: ubuntu-latest steps: - name: Checkout @@ -27,26 +27,6 @@ jobs: ${{ runner.os }}-yarn- - name: Fetch Deps run: yarn install --frozen-lockfile - - build: - runs-on: ubuntu-latest - needs: fetch - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Setup Node - uses: actions/setup-node@v4 - with: - node-version-file: './.node-version' - - name: Cache Deps - uses: actions/cache@v4 - with: - path: | - node_modules - packages/*/node_modules - key: ${{ runner.os }}-yarn-${{ hashFiles( 'yarn.lock' ) }} - restore-keys: | - ${{ runner.os }}-yarn- - name: Build run: yarn build - name: Upload Builds @@ -76,6 +56,8 @@ jobs: key: ${{ runner.os }}-yarn-${{ hashFiles( 'yarn.lock' ) }} restore-keys: | ${{ runner.os }}-yarn- + - name: Fetch Deps + run: yarn install --frozen-lockfile - name: Download Builds uses: actions/download-artifact@v3 with: @@ -103,6 +85,8 @@ jobs: key: ${{ runner.os }}-yarn-${{ hashFiles( 'yarn.lock' ) }} restore-keys: | ${{ runner.os }}-yarn- + - name: Fetch Deps + run: yarn install --frozen-lockfile - name: Download Builds uses: actions/download-artifact@v3 with: @@ -130,6 +114,8 @@ jobs: key: ${{ runner.os }}-yarn-${{ hashFiles( 'yarn.lock' ) }} restore-keys: | ${{ runner.os }}-yarn- + - name: Fetch Deps + run: yarn install --frozen-lockfile - name: Download Builds uses: actions/download-artifact@v3 with: @@ -166,6 +152,8 @@ jobs: key: ${{ runner.os }}-yarn-${{ hashFiles( 'yarn.lock' ) }} restore-keys: | ${{ runner.os }}-yarn- + - name: Fetch Deps + run: yarn install --frozen-lockfile - name: Download Builds uses: actions/download-artifact@v3 with: diff --git a/packages/three-vrm-springbone/examples/index.html b/packages/three-vrm-springbone/examples/index.html index 55940cb23..b8f46d101 100644 --- a/packages/three-vrm-springbone/examples/index.html +++ b/packages/three-vrm-springbone/examples/index.html @@ -22,7 +22,15 @@

examples of @pixiv/three-vrm-s

collider.html
- An example with a node collider + An example with a collider +

+

+ inside-collider.html
+ An example with an inside collider +

+

+ plane-collider.html
+ An example with a plane collider

loader-plugin.html
diff --git a/packages/three-vrm-springbone/examples/inside-collider.html b/packages/three-vrm-springbone/examples/inside-collider.html new file mode 100644 index 000000000..5d47d4dca --- /dev/null +++ b/packages/three-vrm-springbone/examples/inside-collider.html @@ -0,0 +1,166 @@ + + + + + + three-vrm-springbone example - inside-collider + + + + + + + + + + diff --git a/packages/three-vrm-springbone/examples/loader-plugin.html b/packages/three-vrm-springbone/examples/loader-plugin.html index 45aef1431..70c5001b8 100644 --- a/packages/three-vrm-springbone/examples/loader-plugin.html +++ b/packages/three-vrm-springbone/examples/loader-plugin.html @@ -34,6 +34,7 @@ import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; import { VRMSpringBoneLoaderPlugin } from "@pixiv/three-vrm-springbone"; + import GUI from 'three/addons/libs/lil-gui.module.min.js'; // renderer const renderer = new THREE.WebGLRenderer(); @@ -43,7 +44,7 @@ // camera const camera = new THREE.PerspectiveCamera( 30.0, window.innerWidth / window.innerHeight, 0.1, 20.0 ); - camera.position.set( 0.0, 1.0, 5.0 ); + camera.position.set( 0.0, 1.0, 10.0 ); // camera controls const controls = new OrbitControls( camera, renderer.domElement ); @@ -54,6 +55,9 @@ // scene const scene = new THREE.Scene(); + const helperRoot = new THREE.Group(); + scene.add( helperRoot ); + // light const light = new THREE.DirectionalLight( 0xffffff, Math.PI ); light.position.set( 1.0, 1.0, 1.0 ).normalize(); @@ -61,14 +65,13 @@ // gltf and vrm let currentGltf = null; - let currentSpringBoneManager = null; const loader = new GLTFLoader(); const loaderPluginOptions = { - jointHelperRoot: scene, - colliderHelperRoot: scene, + jointHelperRoot: helperRoot, + colliderHelperRoot: helperRoot, }; @@ -80,6 +83,13 @@ function load( url ) { + if ( currentGltf != null ) { + + scene.remove( currentGltf.scene ); + helperRoot.clear(); + + } + loader.crossOrigin = 'anonymous'; loader.load( @@ -92,7 +102,7 @@ currentGltf = gltf; - const springBoneManager = gltf.vrmSpringBoneManager; + clock.start(); }, @@ -104,7 +114,7 @@ } - load( './models/cubes.gltf' ); + load( './models/sphere-collider.gltf' ); // helpers const gridHelper = new THREE.GridHelper( 10, 10 ); @@ -146,6 +156,29 @@ animate(); + // gui + const gui = new GUI(); + + const params = { + + model: 'sphere-collider.gltf', + + }; + + const availableModels = [ + + 'sphere-collider.gltf', + 'inside-collider.gltf', + 'plane-collider.gltf', + + ]; + + gui.add( params, 'model', availableModels ).onChange( ( value ) => { + + load( `./models/${ value }` ); + + } ); + // dnd handler window.addEventListener( 'dragover', function ( event ) { @@ -160,16 +193,16 @@ // read given file then convert it to blob url const files = event.dataTransfer.files; if ( ! files ) { - + return; - + } const file = files[ 0 ]; if ( ! file ) { - + return; - + } const blob = new Blob( [ file ], { type: "application/octet-stream" } ); diff --git a/packages/three-vrm-springbone/examples/models/cube_mesh.bin b/packages/three-vrm-springbone/examples/models/cube_mesh.bin deleted file mode 100644 index 3f26e918e..000000000 Binary files a/packages/three-vrm-springbone/examples/models/cube_mesh.bin and /dev/null differ diff --git a/packages/three-vrm-springbone/examples/models/inside-collider.gltf b/packages/three-vrm-springbone/examples/models/inside-collider.gltf new file mode 100644 index 000000000..b2e3b0510 --- /dev/null +++ b/packages/three-vrm-springbone/examples/models/inside-collider.gltf @@ -0,0 +1,368 @@ +{ + "asset": { + "generator": "Handwritten", + "version": "2.0" + }, + "buffers": [ + { + "uri": "sphere_mesh.bin", + "byteLength": 2496 + } + ], + "bufferViews": [ + { + "name": "Sphere Position", + "buffer": 0, + "byteOffset": 0, + "byteLength": 756, + "target": 34962 + }, + { + "name": "Sphere Normal", + "buffer": 0, + "byteOffset": 756, + "byteLength": 756, + "target": 34962 + }, + { + "name": "Sphere UV", + "buffer": 0, + "byteOffset": 1512, + "byteLength": 504, + "target": 34962 + }, + { + "name": "Sphere Indices", + "buffer": 0, + "byteOffset": 2016, + "byteLength": 480, + "target": 34963 + } + ], + "accessors": [ + { + "name": "Sphere Position", + "bufferView": 0, + "type": "VEC3", + "componentType": 5126, + "count": 63, + "max": [ + 0.9510578513145447, + 1, + 0.9999999403953552 + ], + "min": [ + -0.9510578513145447, + -1, + -0.9999999403953552 + ] + }, + { + "name": "Sphere Normal", + "bufferView": 1, + "type": "VEC3", + "componentType": 5126, + "count": 63 + }, + { + "name": "Sphere UV", + "bufferView": 2, + "type": "VEC2", + "componentType": 5126, + "count": 63 + }, + { + "name": "Sphere Indices", + "bufferView": 3, + "type": "SCALAR", + "componentType": 5123, + "count": 240 + } + ], + "materials": [ + { + "name": "Sphere Material Yellow", + "pbrMetallicRoughness": { + "baseColorFactor": [ 1, 1, 0.7, 1 ], + "metallicFactor": 0, + "roughnessFactor": 0.5 + }, + "alphaMode": "OPAQUE", + "doubleSided": false + }, + { + "name": "Sphere Material Pink", + "pbrMetallicRoughness": { + "baseColorFactor": [ 1, 0.7, 1, 0.5 ], + "metallicFactor": 0, + "roughnessFactor": 0.5 + }, + "alphaMode": "BLEND", + "doubleSided": false + } + ], + "meshes": [ + { + "name": "Sphere Yellow", + "primitives": [ + { + "mode": 4, + "indices": 3, + "attributes": { + "POSITION": 0, + "NORMAL": 1, + "TEXCOORD_0": 2 + }, + "material": 0 + } + ] + }, + { + "name": "Sphere Pink", + "primitives": [ + { + "mode": 4, + "indices": 3, + "attributes": { + "POSITION": 0, + "NORMAL": 1, + "TEXCOORD_0": 2 + }, + "material": 1 + } + ] + } + ], + "nodes": [ + { + "name": "Spring A", + "children": [ + 1 + ], + "translation": [ + 0, + 2, + 0 + ], + "rotation": [ + 0, + 0, + 0, + 1 + ], + "scale": [ + 0.25, + 0.25, + 0.25 + ], + "mesh": 0, + "extras": {} + }, + { + "name": "Spring B", + "children": [ + 2 + ], + "translation": [ + 0, + -2, + 0 + ], + "rotation": [ + 0, + 0, + 0, + 1 + ], + "scale": [ + 1, + 1, + 1 + ], + "mesh": 0, + "extras": {} + }, + { + "name": "Spring C", + "children": [ + 3 + ], + "translation": [ + 0, + -2, + 0 + ], + "rotation": [ + 0, + 0, + 0, + 1 + ], + "scale": [ + 1, + 1, + 1 + ], + "mesh": 0, + "extras": {} + }, + { + "name": "Spring D", + "children": [ + 4 + ], + "translation": [ + 0, + -2, + 0 + ], + "rotation": [ + 0, + 0, + 0, + 1 + ], + "scale": [ + 1, + 1, + 1 + ], + "mesh": 0, + "extras": {} + }, + { + "name": "Spring E", + "translation": [ + 0, + -2, + 0 + ], + "rotation": [ + 0, + 0, + 0, + 1 + ], + "scale": [ + 1, + 1, + 1 + ], + "mesh": 0, + "extras": {} + }, + { + "name": "Collider", + "translation": [ + 0, + 1, + 0 + ], + "rotation": [ + 0, + 0, + 0, + 1 + ], + "scale": [ + 1.35, + 1.35, + 1.35 + ], + "mesh": 1, + "extras": {} + } + ], + "scene": 0, + "scenes": [ + { + "nodes": [ + 0, + 5 + ] + } + ], + "extensionsUsed": [ + "VRMC_springBone", + "VRMC_springBone_extended_collider" + ], + "extensions": { + "VRMC_springBone": { + "specVersion": "1.0", + "colliders": [ + { + "node": 5, + "shape": { + "sphere": { + "offset": [ + 10000.0, + 0.0, + 0.0 + ], + "radius": 0.0 + } + }, + "extensions": { + "VRMC_springBone_extended_collider": { + "specVersion": "1.0-draft", + "shape": { + "sphere": { + "radius": 1.25, + "inside": true + } + } + } + } + } + ], + "colliderGroups": [ + { + "colliders": [ 0 ] + } + ], + "springs": [ + { + "joints": [ + { + "node": 0, + "hitRadius": 0.25, + "stiffness": 1.0, + "gravityPower": 0.0, + "gravityDir": [ 0.0, -1.0, 0.0 ], + "dragForce": 0.4 + }, + { + "node": 1, + "hitRadius": 0.25, + "stiffness": 1.0, + "gravityPower": 0.0, + "gravityDir": [ 0.0, -1.0, 0.0 ], + "dragForce": 0.4 + }, + { + "node": 2, + "hitRadius": 0.25, + "stiffness": 1.0, + "gravityPower": 0.0, + "gravityDir": [ 0.0, -1.0, 0.0 ], + "dragForce": 0.4 + }, + { + "node": 3, + "hitRadius": 0.25, + "stiffness": 1.0, + "gravityPower": 0.0, + "gravityDir": [ 0.0, -1.0, 0.0 ], + "dragForce": 0.4 + }, + { + "node": 4 + } + ], + "colliderGroups": [ 0 ] + } + ] + } + }, + "extras": {} +} diff --git a/packages/three-vrm-springbone/examples/models/plane-collider.gltf b/packages/three-vrm-springbone/examples/models/plane-collider.gltf new file mode 100644 index 000000000..41c536472 --- /dev/null +++ b/packages/three-vrm-springbone/examples/models/plane-collider.gltf @@ -0,0 +1,441 @@ +{ + "asset": { + "generator": "Handwritten", + "version": "2.0" + }, + "buffers": [ + { + "uri": "sphere_mesh.bin", + "byteLength": 2496 + }, + { + "uri": "plane_mesh.bin", + "byteLength": 140 + } + ], + "bufferViews": [ + { + "name": "Sphere Position", + "buffer": 0, + "byteOffset": 0, + "byteLength": 756, + "target": 34962 + }, + { + "name": "Sphere Normal", + "buffer": 0, + "byteOffset": 756, + "byteLength": 756, + "target": 34962 + }, + { + "name": "Sphere UV", + "buffer": 0, + "byteOffset": 1512, + "byteLength": 504, + "target": 34962 + }, + { + "name": "Sphere Indices", + "buffer": 0, + "byteOffset": 2016, + "byteLength": 480, + "target": 34963 + }, + { + "name": "Plane Position", + "buffer": 1, + "byteOffset": 0, + "byteLength": 48, + "target": 34962 + }, + { + "name": "Plane Normal", + "buffer": 1, + "byteOffset": 48, + "byteLength": 48, + "target": 34962 + }, + { + "name": "Plane UV", + "buffer": 1, + "byteOffset": 96, + "byteLength": 32, + "target": 34962 + }, + { + "name": "Plane Indices", + "buffer": 1, + "byteOffset": 128, + "byteLength": 12, + "target": 34963 + } + ], + "accessors": [ + { + "name": "Sphere Position", + "bufferView": 0, + "type": "VEC3", + "componentType": 5126, + "count": 63, + "max": [ + 0.9510578513145447, + 1, + 0.9999999403953552 + ], + "min": [ + -0.9510578513145447, + -1, + -0.9999999403953552 + ] + }, + { + "name": "Sphere Normal", + "bufferView": 1, + "type": "VEC3", + "componentType": 5126, + "count": 63 + }, + { + "name": "Sphere UV", + "bufferView": 2, + "type": "VEC2", + "componentType": 5126, + "count": 63 + }, + { + "name": "Sphere Indices", + "bufferView": 3, + "type": "SCALAR", + "componentType": 5123, + "count": 240 + }, + { + "name": "Plane Position", + "bufferView": 4, + "type": "VEC3", + "componentType": 5126, + "count": 4, + "max":[ + 0.9999999403953552, + 1, + 0 + ], + "min":[ + -0.9999999403953552, + -1, + 0 + ] + }, + { + "name": "Plane Normal", + "bufferView": 5, + "type": "VEC3", + "componentType": 5126, + "count": 4 + }, + { + "name": "Plane UV", + "bufferView": 6, + "type": "VEC2", + "componentType": 5126, + "count": 4 + }, + { + "name": "Plane Indices", + "bufferView": 7, + "type": "SCALAR", + "componentType": 5123, + "count": 6 + } + ], + "materials": [ + { + "name": "Sphere Material Yellow", + "pbrMetallicRoughness": { + "baseColorFactor": [ 1, 1, 0.7, 1 ], + "metallicFactor": 0, + "roughnessFactor": 0.5 + }, + "alphaMode": "OPAQUE", + "doubleSided": false + }, + { + "name": "Plane Material Pink", + "pbrMetallicRoughness": { + "baseColorFactor": [ 1, 0.7, 1, 1 ], + "metallicFactor": 0, + "roughnessFactor": 0.5 + }, + "alphaMode": "OPAQUE", + "doubleSided": true + } + ], + "meshes": [ + { + "name": "Cube", + "primitives": [ + { + "mode": 4, + "indices": 3, + "attributes": { + "POSITION": 0, + "NORMAL": 1, + "TEXCOORD_0": 2 + }, + "material": 0 + } + ] + }, + { + "name": "Plane Pink", + "primitives": [ + { + "mode": 4, + "indices": 7, + "attributes": { + "POSITION": 4, + "NORMAL": 5, + "TEXCOORD_0": 6 + }, + "material": 1 + } + ] + } + ], + "nodes": [ + { + "name": "Spring A", + "children": [ + 1 + ], + "translation": [ + 0, + 2, + 0 + ], + "rotation": [ + 0, + 0, + 0, + 1 + ], + "scale": [ + 0.25, + 0.25, + 0.25 + ], + "mesh": 0, + "extras": {} + }, + { + "name": "Spring B", + "children": [ + 2 + ], + "translation": [ + 0, + -2, + 0 + ], + "rotation": [ + 0, + 0, + 0, + 1 + ], + "scale": [ + 1, + 1, + 1 + ], + "mesh": 0, + "extras": {} + }, + { + "name": "Spring C", + "children": [ + 3 + ], + "translation": [ + 0, + -2, + 0 + ], + "rotation": [ + 0, + 0, + 0, + 1 + ], + "scale": [ + 1, + 1, + 1 + ], + "mesh": 0, + "extras": {} + }, + { + "name": "Spring D", + "children": [ + 4 + ], + "translation": [ + 0, + -2, + 0 + ], + "rotation": [ + 0, + 0, + 0, + 1 + ], + "scale": [ + 1, + 1, + 1 + ], + "mesh": 0, + "extras": {} + }, + { + "name": "Spring E", + "translation": [ + 0, + -2, + 0 + ], + "rotation": [ + 0, + 0, + 0, + 1 + ], + "scale": [ + 1, + 1, + 1 + ], + "mesh": 0, + "extras": {} + }, + { + "name": "Collider", + "translation": [ + -0.25, + 1, + 0 + ], + "rotation": [ + 0, + 0.70710678118, + 0, + 0.70710678118 + ], + "scale": [ + 1, + 1, + 1 + ], + "mesh": 1, + "extras": {} + } + ], + "scene": 0, + "scenes": [ + { + "nodes": [ + 0, + 5 + ] + } + ], + "extensionsUsed": [ + "VRMC_springBone", + "VRMC_springBone_extended_collider" + ], + "extensions": { + "VRMC_springBone": { + "specVersion": "1.0", + "colliders": [ + { + "node": 5, + "shape": { + "sphere": { + "offset": [ + -10000.0, + 0.0, + 0.0 + ], + "radius": 10000.0 + } + }, + "extensions": { + "VRMC_springBone_extended_collider": { + "specVersion": "1.0-draft", + "shape": { + "plane": { + "normal": [ + 0.0, + 0.0, + 1.0 + ] + } + } + } + } + } + ], + "colliderGroups": [ + { + "colliders": [ 0 ] + } + ], + "springs": [ + { + "joints": [ + { + "node": 0, + "hitRadius": 0.25, + "stiffness": 1.0, + "gravityPower": 0.0, + "gravityDir": [ 0.0, -1.0, 0.0 ], + "dragForce": 0.4 + }, + { + "node": 1, + "hitRadius": 0.25, + "stiffness": 1.0, + "gravityPower": 0.0, + "gravityDir": [ 0.0, -1.0, 0.0 ], + "dragForce": 0.4 + }, + { + "node": 2, + "hitRadius": 0.25, + "stiffness": 1.0, + "gravityPower": 0.0, + "gravityDir": [ 0.0, -1.0, 0.0 ], + "dragForce": 0.4 + }, + { + "node": 3, + "hitRadius": 0.25, + "stiffness": 1.0, + "gravityPower": 0.0, + "gravityDir": [ 0.0, -1.0, 0.0 ], + "dragForce": 0.4 + }, + { + "node": 4 + } + ], + "colliderGroups": [ 0 ] + } + ] + } + }, + "extras": {} +} diff --git a/packages/three-vrm-springbone/examples/models/plane_mesh.bin b/packages/three-vrm-springbone/examples/models/plane_mesh.bin new file mode 100644 index 000000000..859ce947f Binary files /dev/null and b/packages/three-vrm-springbone/examples/models/plane_mesh.bin differ diff --git a/packages/three-vrm-springbone/examples/models/cubes.gltf b/packages/three-vrm-springbone/examples/models/sphere-collider.gltf similarity index 68% rename from packages/three-vrm-springbone/examples/models/cubes.gltf rename to packages/three-vrm-springbone/examples/models/sphere-collider.gltf index eb352b13d..b864452f1 100644 --- a/packages/three-vrm-springbone/examples/models/cubes.gltf +++ b/packages/three-vrm-springbone/examples/models/sphere-collider.gltf @@ -5,93 +5,95 @@ }, "buffers": [ { - "uri": "cube_mesh.bin", - "byteLength": 912 + "uri": "sphere_mesh.bin", + "byteLength": 2496 } ], "bufferViews": [ { - "name": "Cube Position", + "name": "Sphere Position", "buffer": 0, "byteOffset": 0, - "byteLength": 288, + "byteLength": 756, "target": 34962 }, { - "name": "Cube Normal", + "name": "Sphere Normal", "buffer": 0, - "byteOffset": 288, - "byteLength": 288, + "byteOffset": 756, + "byteLength": 756, "target": 34962 }, { - "name": "Cube UV", + "name": "Sphere UV", "buffer": 0, - "byteOffset": 576, - "byteLength": 192, + "byteOffset": 1512, + "byteLength": 504, "target": 34962 }, { - "name": "Cube Indices", + "name": "Sphere Indices", "buffer": 0, - "byteOffset": 768, - "byteLength": 144, + "byteOffset": 2016, + "byteLength": 480, "target": 34963 } ], "accessors": [ { - "name": "Cube Position", + "name": "Sphere Position", "bufferView": 0, - "byteOffset": 0, "type": "VEC3", "componentType": 5126, - "count": 24, + "count": 63, "max": [ - 0.5, - 0.5, - 0.5 + 0.9510578513145447, + 1, + 0.9999999403953552 ], "min": [ - -0.5, - -0.5, - -0.5 - ], - "normalized": false + -0.9510578513145447, + -1, + -0.9999999403953552 + ] }, { - "name": "Cube Normal", + "name": "Sphere Normal", "bufferView": 1, - "byteOffset": 0, "type": "VEC3", "componentType": 5126, - "count": 24, - "normalized": false + "count": 63 }, { - "name": "Cube UV", + "name": "Sphere UV", "bufferView": 2, - "byteOffset": 0, "type": "VEC2", "componentType": 5126, - "count": 24, - "normalized": false + "count": 63 }, { - "name": "Cube Indices", + "name": "Sphere Indices", "bufferView": 3, - "byteOffset": 0, "type": "SCALAR", - "componentType": 5125, - "count": 36, - "normalized": false + "componentType": 5123, + "count": 240 } ], "materials": [ { - "name": "Cube Material", + "name": "Sphere Material Yellow", + "pbrMetallicRoughness": { + "baseColorFactor": [ 1, 1, 0.7, 1 ], + "metallicFactor": 0, + "roughnessFactor": 0.5 + }, + "alphaMode": "OPAQUE", + "doubleSided": false + }, + { + "name": "Sphere Material Pink", "pbrMetallicRoughness": { - "baseColorFactor": [ 1, 1, 1, 1 ], + "baseColorFactor": [ 1, 0.7, 1, 1 ], "metallicFactor": 0, "roughnessFactor": 0.5 }, @@ -101,7 +103,7 @@ ], "meshes": [ { - "name": "Cube", + "name": "Sphere Yellow", "primitives": [ { "mode": 4, @@ -114,11 +116,26 @@ "material": 0 } ] + }, + { + "name": "Sphere Pink", + "primitives": [ + { + "mode": 4, + "indices": 3, + "attributes": { + "POSITION": 0, + "NORMAL": 1, + "TEXCOORD_0": 2 + }, + "material": 1 + } + ] } ], "nodes": [ { - "name": "CubeA", + "name": "Spring A", "children": [ 1 ], @@ -134,21 +151,21 @@ 1 ], "scale": [ - 0.5, - 0.5, - 0.5 + 0.25, + 0.25, + 0.25 ], "mesh": 0, "extras": {} }, { - "name": "CubeB", + "name": "Spring B", "children": [ 2 ], "translation": [ 0, - -1, + -2, 0 ], "rotation": [ @@ -166,13 +183,13 @@ "extras": {} }, { - "name": "CubeC", + "name": "Spring C", "children": [ 3 ], "translation": [ 0, - -1, + -2, 0 ], "rotation": [ @@ -190,13 +207,13 @@ "extras": {} }, { - "name": "CubeD", + "name": "Spring D", "children": [ 4 ], "translation": [ 0, - -1, + -2, 0 ], "rotation": [ @@ -214,10 +231,10 @@ "extras": {} }, { - "name": "CubeE", + "name": "Spring E", "translation": [ 0, - -1, + -2, 0 ], "rotation": [ @@ -237,7 +254,7 @@ { "name": "Collider", "translation": [ - 0.5, + 0.75, 1, 0 ], @@ -248,10 +265,11 @@ 1 ], "scale": [ - 1, - 1, - 1 + 0.5, + 0.5, + 0.5 ], + "mesh": 1, "extras": {} } ], @@ -293,9 +311,17 @@ "springs": [ { "joints": [ + { + "node": 0, + "hitRadius": 0.25, + "stiffness": 1.0, + "gravityPower": 0.0, + "gravityDir": [ 0.0, -1.0, 0.0 ], + "dragForce": 0.4 + }, { "node": 1, - "hitRadius": 0.02, + "hitRadius": 0.25, "stiffness": 1.0, "gravityPower": 0.0, "gravityDir": [ 0.0, -1.0, 0.0 ], @@ -303,7 +329,7 @@ }, { "node": 2, - "hitRadius": 0.02, + "hitRadius": 0.25, "stiffness": 1.0, "gravityPower": 0.0, "gravityDir": [ 0.0, -1.0, 0.0 ], @@ -311,7 +337,7 @@ }, { "node": 3, - "hitRadius": 0.02, + "hitRadius": 0.25, "stiffness": 1.0, "gravityPower": 0.0, "gravityDir": [ 0.0, -1.0, 0.0 ], diff --git a/packages/three-vrm-springbone/examples/models/sphere_mesh.bin b/packages/three-vrm-springbone/examples/models/sphere_mesh.bin new file mode 100644 index 000000000..4ff55c723 Binary files /dev/null and b/packages/three-vrm-springbone/examples/models/sphere_mesh.bin differ diff --git a/packages/three-vrm-springbone/examples/plane-collider.html b/packages/three-vrm-springbone/examples/plane-collider.html new file mode 100644 index 000000000..99e87f668 --- /dev/null +++ b/packages/three-vrm-springbone/examples/plane-collider.html @@ -0,0 +1,164 @@ + + + + + + three-vrm-springbone example - plane-collider + + + + + + + + + + diff --git a/packages/three-vrm-springbone/package.json b/packages/three-vrm-springbone/package.json index 5a1d3acbf..8d0813f7d 100644 --- a/packages/three-vrm-springbone/package.json +++ b/packages/three-vrm-springbone/package.json @@ -52,7 +52,8 @@ }, "dependencies": { "@pixiv/types-vrm-0.0": "3.0.0", - "@pixiv/types-vrmc-springbone-1.0": "3.0.0" + "@pixiv/types-vrmc-springbone-1.0": "3.0.0", + "@pixiv/types-vrmc-springbone-extended-collider-1.0": "3.0.0" }, "devDependencies": { "@types/three": "^0.167.0", diff --git a/packages/three-vrm-springbone/src/VRMSpringBoneColliderShapeCapsule.ts b/packages/three-vrm-springbone/src/VRMSpringBoneColliderShapeCapsule.ts index 8135e11cb..1d6aa51a0 100644 --- a/packages/three-vrm-springbone/src/VRMSpringBoneColliderShapeCapsule.ts +++ b/packages/three-vrm-springbone/src/VRMSpringBoneColliderShapeCapsule.ts @@ -10,26 +10,32 @@ export class VRMSpringBoneColliderShapeCapsule extends VRMSpringBoneColliderShap } /** - * The offset of the head from the origin. + * The offset of the capsule head from the origin in local space. */ public offset: THREE.Vector3; /** - * The offset of the tail from the origin. + * The offset of the capsule tail from the origin in local space. */ public tail: THREE.Vector3; /** - * The radius. + * The radius of the capsule. */ public radius: number; - public constructor(params?: { radius?: number; offset?: THREE.Vector3; tail?: THREE.Vector3 }) { + /** + * If true, the collider prevents spring bones from going outside of the capsule instead. + */ + public inside: boolean; + + public constructor(params?: { radius?: number; offset?: THREE.Vector3; tail?: THREE.Vector3; inside?: boolean }) { super(); this.offset = params?.offset ?? new THREE.Vector3(0.0, 0.0, 0.0); this.tail = params?.tail ?? new THREE.Vector3(0.0, 0.0, 0.0); this.radius = params?.radius ?? 0.0; + this.inside = params?.inside ?? false; } public calculateCollision( @@ -58,9 +64,15 @@ export class VRMSpringBoneColliderShapeCapsule extends VRMSpringBoneColliderShap target.sub(_v3B); // from the shaft point to object } - const radius = objectRadius + this.radius; - const distance = target.length() - radius; - target.normalize(); + const distance = this.inside + ? this.radius - objectRadius - target.length() + : target.length() - objectRadius - this.radius; + + target.normalize(); // convert the delta to the direction + if (this.inside) { + target.negate(); // if inside, reverse the direction + } + return distance; } } diff --git a/packages/three-vrm-springbone/src/VRMSpringBoneColliderShapePlane.ts b/packages/three-vrm-springbone/src/VRMSpringBoneColliderShapePlane.ts new file mode 100644 index 000000000..087d1fd26 --- /dev/null +++ b/packages/three-vrm-springbone/src/VRMSpringBoneColliderShapePlane.ts @@ -0,0 +1,46 @@ +import * as THREE from 'three'; +import { VRMSpringBoneColliderShape } from './VRMSpringBoneColliderShape'; + +const _v3A = new THREE.Vector3(); +const _mat3A = new THREE.Matrix3(); + +export class VRMSpringBoneColliderShapePlane extends VRMSpringBoneColliderShape { + public get type(): 'plane' { + return 'plane'; + } + + /** + * The offset of the plane from the origin in local space. + */ + public offset: THREE.Vector3; + + /** + * The normal of the plane in local space. Must be normalized. + */ + public normal: THREE.Vector3; + + public constructor(params?: { offset?: THREE.Vector3; normal?: THREE.Vector3 }) { + super(); + + this.offset = params?.offset ?? new THREE.Vector3(0.0, 0.0, 0.0); + this.normal = params?.normal ?? new THREE.Vector3(0.0, 0.0, 1.0); + } + + public calculateCollision( + colliderMatrix: THREE.Matrix4, + objectPosition: THREE.Vector3, + objectRadius: number, + target: THREE.Vector3, + ): number { + target.copy(this.offset).applyMatrix4(colliderMatrix); // transformed offset + target.negate().add(objectPosition); // a vector from collider center to object position + + _mat3A.getNormalMatrix(colliderMatrix); // convert the collider matrix to the normal matrix + _v3A.copy(this.normal).applyNormalMatrix(_mat3A).normalize(); // transformed normal + const distance = target.dot(_v3A) - objectRadius; + + target.copy(_v3A); // convert the delta to the direction + + return distance; + } +} diff --git a/packages/three-vrm-springbone/src/VRMSpringBoneColliderShapeSphere.ts b/packages/three-vrm-springbone/src/VRMSpringBoneColliderShapeSphere.ts index b54d20778..95aac74d1 100644 --- a/packages/three-vrm-springbone/src/VRMSpringBoneColliderShapeSphere.ts +++ b/packages/three-vrm-springbone/src/VRMSpringBoneColliderShapeSphere.ts @@ -7,7 +7,7 @@ export class VRMSpringBoneColliderShapeSphere extends VRMSpringBoneColliderShape } /** - * The offset from the origin. + * The offset of the sphere from the origin in local space. */ public offset: THREE.Vector3; @@ -16,11 +16,17 @@ export class VRMSpringBoneColliderShapeSphere extends VRMSpringBoneColliderShape */ public radius: number; - public constructor(params?: { radius?: number; offset?: THREE.Vector3 }) { + /** + * If true, the collider prevents spring bones from going outside of the sphere instead. + */ + public inside: boolean; + + public constructor(params?: { radius?: number; offset?: THREE.Vector3; inside?: boolean }) { super(); this.offset = params?.offset ?? new THREE.Vector3(0.0, 0.0, 0.0); this.radius = params?.radius ?? 0.0; + this.inside = params?.inside ?? false; } public calculateCollision( @@ -31,9 +37,16 @@ export class VRMSpringBoneColliderShapeSphere extends VRMSpringBoneColliderShape ): number { target.copy(this.offset).applyMatrix4(colliderMatrix); // transformed offset target.negate().add(objectPosition); // a vector from collider center to object position - const radius = objectRadius + this.radius; - const distance = target.length() - radius; - target.normalize(); + + const distance = this.inside + ? this.radius - objectRadius - target.length() + : target.length() - objectRadius - this.radius; + + target.normalize(); // convert the delta to the direction + if (this.inside) { + target.negate(); // if inside, reverse the direction + } + return distance; } } diff --git a/packages/three-vrm-springbone/src/VRMSpringBoneLoaderPlugin.ts b/packages/three-vrm-springbone/src/VRMSpringBoneLoaderPlugin.ts index 1e2c3eaca..121915fc4 100644 --- a/packages/three-vrm-springbone/src/VRMSpringBoneLoaderPlugin.ts +++ b/packages/three-vrm-springbone/src/VRMSpringBoneLoaderPlugin.ts @@ -1,5 +1,6 @@ import type * as V0VRM from '@pixiv/types-vrm-0.0'; import type * as V1SpringBoneSchema from '@pixiv/types-vrmc-springbone-1.0'; +import type * as SpringBoneExtendedColliderSchema from '@pixiv/types-vrmc-springbone-extended-collider-1.0'; import * as THREE from 'three'; import type { GLTF, GLTFLoaderPlugin, GLTFParser } from 'three/examples/jsm/loaders/GLTFLoader.js'; import { VRMSpringBoneColliderHelper, VRMSpringBoneJointHelper } from './helpers'; @@ -12,12 +13,20 @@ import type { VRMSpringBoneLoaderPluginOptions } from './VRMSpringBoneLoaderPlug import { VRMSpringBoneManager } from './VRMSpringBoneManager'; import type { VRMSpringBoneJointSettings } from './VRMSpringBoneJointSettings'; import { GLTF as GLTFSchema } from '@gltf-transform/core'; +import { VRMSpringBoneColliderShapePlane } from './VRMSpringBoneColliderShapePlane'; + +const EXTENSION_NAME_EXTENDED_COLLIDER = 'VRMC_springBone_extended_collider'; /** * Possible spec versions it recognizes. */ const POSSIBLE_SPEC_VERSIONS = new Set(['1.0', '1.0-beta']); +/** + * Possible spec versions of `VRMC_springBone_extended_collider` it recognizes. + */ +const POSSIBLE_SPEC_VERSIONS_EXTENDED_COLLIDERS = new Set(['1.0-draft']); + export class VRMSpringBoneLoaderPlugin implements GLTFLoaderPlugin { public static readonly EXTENSION_NAME = 'VRMC_springBone'; @@ -35,6 +44,13 @@ export class VRMSpringBoneLoaderPlugin implements GLTFLoaderPlugin { */ public colliderHelperRoot?: THREE.Object3D; + /** + * If true, load colliders defined in `VRMC_springBone_extended_collider`. + * Set to `false` to disable loading extended colliders and use the fallback behavior. + * `true` by default. + */ + public useExtendedColliders: boolean; + public readonly parser: GLTFParser; public get name(): string { @@ -46,6 +62,7 @@ export class VRMSpringBoneLoaderPlugin implements GLTFLoaderPlugin { this.jointHelperRoot = options?.jointHelperRoot; this.colliderHelperRoot = options?.colliderHelperRoot; + this.useExtendedColliders = options?.useExtendedColliders ?? true; } public async afterRoot(gltf: GLTF): Promise { @@ -104,16 +121,53 @@ export class VRMSpringBoneLoaderPlugin implements GLTFLoaderPlugin { const node = threeNodes[schemaCollider.node!]; const schemaShape = schemaCollider.shape!; + // TODO: separate into several functions + + const schemaExCollider: SpringBoneExtendedColliderSchema.VRMCSpringBoneExtendedCollider | undefined = + schemaCollider.extensions?.[EXTENSION_NAME_EXTENDED_COLLIDER]; + + if (this.useExtendedColliders && schemaExCollider != null) { + const specVersionExCollider = schemaExCollider.specVersion; + if (!POSSIBLE_SPEC_VERSIONS_EXTENDED_COLLIDERS.has(specVersionExCollider)) { + console.warn( + `VRMSpringBoneLoaderPlugin: Unknown ${EXTENSION_NAME_EXTENDED_COLLIDER} specVersion "${specVersionExCollider}". Fallbacking to the ${VRMSpringBoneLoaderPlugin.EXTENSION_NAME} definition`, + ); + } else { + const schemaExShape = schemaExCollider.shape!; + if (schemaExShape.sphere) { + return this._importSphereCollider(node, { + offset: new THREE.Vector3().fromArray(schemaExShape.sphere.offset ?? [0.0, 0.0, 0.0]), + radius: schemaExShape.sphere.radius ?? 0.0, + inside: schemaExShape.sphere.inside ?? false, + }); + } else if (schemaExShape.capsule) { + return this._importCapsuleCollider(node, { + offset: new THREE.Vector3().fromArray(schemaExShape.capsule.offset ?? [0.0, 0.0, 0.0]), + radius: schemaExShape.capsule.radius ?? 0.0, + tail: new THREE.Vector3().fromArray(schemaExShape.capsule.tail ?? [0.0, 0.0, 0.0]), + inside: schemaExShape.capsule.inside ?? false, + }); + } else if (schemaExShape.plane) { + return this._importPlaneCollider(node, { + offset: new THREE.Vector3().fromArray(schemaExShape.plane.offset ?? [0.0, 0.0, 0.0]), + normal: new THREE.Vector3().fromArray(schemaExShape.plane.normal ?? [0.0, 0.0, 1.0]), + }); + } + } + } + if (schemaShape.sphere) { return this._importSphereCollider(node, { offset: new THREE.Vector3().fromArray(schemaShape.sphere.offset ?? [0.0, 0.0, 0.0]), radius: schemaShape.sphere.radius ?? 0.0, + inside: false, }); } else if (schemaShape.capsule) { return this._importCapsuleCollider(node, { offset: new THREE.Vector3().fromArray(schemaShape.capsule.offset ?? [0.0, 0.0, 0.0]), radius: schemaShape.capsule.radius ?? 0.0, tail: new THREE.Vector3().fromArray(schemaShape.capsule.tail ?? [0.0, 0.0, 0.0]), + inside: false, }); } @@ -240,6 +294,7 @@ export class VRMSpringBoneLoaderPlugin implements GLTFLoaderPlugin { return this._importSphereCollider(node, { offset, radius: schemaCollider.radius ?? 0.0, + inside: false, }); }); @@ -335,11 +390,10 @@ export class VRMSpringBoneLoaderPlugin implements GLTFLoaderPlugin { params: { offset: THREE.Vector3; radius: number; + inside: boolean; }, ): VRMSpringBoneCollider { - const { offset, radius } = params; - - const shape = new VRMSpringBoneColliderShapeSphere({ offset, radius }); + const shape = new VRMSpringBoneColliderShapeSphere(params); const collider = new VRMSpringBoneCollider(shape); @@ -360,11 +414,32 @@ export class VRMSpringBoneLoaderPlugin implements GLTFLoaderPlugin { offset: THREE.Vector3; radius: number; tail: THREE.Vector3; + inside: boolean; }, ): VRMSpringBoneCollider { - const { offset, radius, tail } = params; + const shape = new VRMSpringBoneColliderShapeCapsule(params); + + const collider = new VRMSpringBoneCollider(shape); + + destination.add(collider); + + if (this.colliderHelperRoot) { + const helper = new VRMSpringBoneColliderHelper(collider); + this.colliderHelperRoot.add(helper); + helper.renderOrder = this.colliderHelperRoot.renderOrder; + } - const shape = new VRMSpringBoneColliderShapeCapsule({ offset, radius, tail }); + return collider; + } + + private _importPlaneCollider( + destination: THREE.Object3D, + params: { + offset: THREE.Vector3; + normal: THREE.Vector3; + }, + ): VRMSpringBoneCollider { + const shape = new VRMSpringBoneColliderShapePlane(params); const collider = new VRMSpringBoneCollider(shape); diff --git a/packages/three-vrm-springbone/src/VRMSpringBoneLoaderPluginOptions.ts b/packages/three-vrm-springbone/src/VRMSpringBoneLoaderPluginOptions.ts index a5fe05972..be91436b0 100644 --- a/packages/three-vrm-springbone/src/VRMSpringBoneLoaderPluginOptions.ts +++ b/packages/three-vrm-springbone/src/VRMSpringBoneLoaderPluginOptions.ts @@ -14,4 +14,11 @@ export interface VRMSpringBoneLoaderPluginOptions { * If `renderOrder` is set to the root, helpers will copy the same `renderOrder` . */ colliderHelperRoot?: THREE.Object3D; + + /** + * If true, load colliders defined in `VRMC_springBone_extended_collider`. + * Set to `false` to disable loading extended colliders and use the fallback behavior. + * `true` by default. + */ + useExtendedColliders?: boolean; } diff --git a/packages/three-vrm-springbone/src/helpers/VRMSpringBoneColliderHelper.ts b/packages/three-vrm-springbone/src/helpers/VRMSpringBoneColliderHelper.ts index b44f90cbe..c7182c067 100644 --- a/packages/three-vrm-springbone/src/helpers/VRMSpringBoneColliderHelper.ts +++ b/packages/three-vrm-springbone/src/helpers/VRMSpringBoneColliderHelper.ts @@ -1,9 +1,11 @@ import * as THREE from 'three'; import { VRMSpringBoneCollider } from '../VRMSpringBoneCollider'; import { VRMSpringBoneColliderShapeCapsule } from '../VRMSpringBoneColliderShapeCapsule'; +import { VRMSpringBoneColliderShapePlane } from '../VRMSpringBoneColliderShapePlane'; import { VRMSpringBoneColliderShapeSphere } from '../VRMSpringBoneColliderShapeSphere'; import { ColliderShapeBufferGeometry } from './utils/ColliderShapeBufferGeometry'; import { ColliderShapeCapsuleBufferGeometry } from './utils/ColliderShapeCapsuleBufferGeometry'; +import { ColliderShapePlaneBufferGeometry } from './utils/ColliderShapePlaneBufferGeometry'; import { ColliderShapeSphereBufferGeometry } from './utils/ColliderShapeSphereBufferGeometry'; const _v3A = new THREE.Vector3(); @@ -23,6 +25,8 @@ export class VRMSpringBoneColliderHelper extends THREE.Group { this._geometry = new ColliderShapeSphereBufferGeometry(this.collider.shape); } else if (this.collider.shape instanceof VRMSpringBoneColliderShapeCapsule) { this._geometry = new ColliderShapeCapsuleBufferGeometry(this.collider.shape); + } else if (this.collider.shape instanceof VRMSpringBoneColliderShapePlane) { + this._geometry = new ColliderShapePlaneBufferGeometry(this.collider.shape); } else { throw new Error('VRMSpringBoneColliderHelper: Unknown collider shape type detected'); } diff --git a/packages/three-vrm-springbone/src/helpers/utils/ColliderShapePlaneBufferGeometry.ts b/packages/three-vrm-springbone/src/helpers/utils/ColliderShapePlaneBufferGeometry.ts new file mode 100644 index 000000000..98f52eab8 --- /dev/null +++ b/packages/three-vrm-springbone/src/helpers/utils/ColliderShapePlaneBufferGeometry.ts @@ -0,0 +1,70 @@ +import * as THREE from 'three'; +import { VRMSpringBoneColliderShapePlane } from '../../VRMSpringBoneColliderShapePlane'; +import { ColliderShapeBufferGeometry } from './ColliderShapeBufferGeometry'; + +export class ColliderShapePlaneBufferGeometry extends THREE.BufferGeometry implements ColliderShapeBufferGeometry { + public worldScale = 1.0; + + private readonly _attrPos: THREE.BufferAttribute; + private readonly _attrIndex: THREE.BufferAttribute; + private readonly _shape: VRMSpringBoneColliderShapePlane; + private readonly _currentOffset = new THREE.Vector3(); + private readonly _currentNormal = new THREE.Vector3(); + + public constructor(shape: VRMSpringBoneColliderShapePlane) { + super(); + + this._shape = shape; + + this._attrPos = new THREE.BufferAttribute(new Float32Array(6 * 3), 3); + this.setAttribute('position', this._attrPos); + + this._attrIndex = new THREE.BufferAttribute(new Uint16Array(10), 1); + this.setIndex(this._attrIndex); + + this._buildIndex(); + this.update(); + } + + public update(): void { + let shouldUpdateGeometry = false; + + if (!this._currentOffset.equals(this._shape.offset)) { + this._currentOffset.copy(this._shape.offset); + shouldUpdateGeometry = true; + } + + if (!this._currentNormal.equals(this._shape.normal)) { + this._currentNormal.copy(this._shape.normal); + shouldUpdateGeometry = true; + } + + if (shouldUpdateGeometry) { + this._buildPosition(); + } + } + + private _buildPosition(): void { + this._attrPos.setXYZ(0, -0.5, -0.5, 0); + this._attrPos.setXYZ(1, 0.5, -0.5, 0); + this._attrPos.setXYZ(2, 0.5, 0.5, 0); + this._attrPos.setXYZ(3, -0.5, 0.5, 0); + this._attrPos.setXYZ(4, 0, 0, 0); + this._attrPos.setXYZ(5, 0, 0, 0.25); + + this.translate(this._currentOffset.x, this._currentOffset.y, this._currentOffset.z); + this.lookAt(this._currentNormal); + + this._attrPos.needsUpdate = true; + } + + private _buildIndex(): void { + this._attrIndex.setXY(0, 0, 1); + this._attrIndex.setXY(2, 1, 2); + this._attrIndex.setXY(4, 2, 3); + this._attrIndex.setXY(6, 3, 0); + this._attrIndex.setXY(8, 4, 5); + + this._attrIndex.needsUpdate = true; + } +} diff --git a/packages/three-vrm-springbone/src/index.ts b/packages/three-vrm-springbone/src/index.ts index 62b73923d..d1535d009 100644 --- a/packages/three-vrm-springbone/src/index.ts +++ b/packages/three-vrm-springbone/src/index.ts @@ -3,6 +3,7 @@ export * from './VRMSpringBoneCollider'; export * from './VRMSpringBoneColliderGroup'; export * from './VRMSpringBoneColliderShape'; export * from './VRMSpringBoneColliderShapeCapsule'; +export * from './VRMSpringBoneColliderShapePlane'; export * from './VRMSpringBoneColliderShapeSphere'; export * from './VRMSpringBoneJoint'; export * from './VRMSpringBoneLoaderPlugin'; diff --git a/packages/types-vrmc-springbone-extended-collider-1.0/.gitignore b/packages/types-vrmc-springbone-extended-collider-1.0/.gitignore new file mode 100644 index 000000000..1509aadd3 --- /dev/null +++ b/packages/types-vrmc-springbone-extended-collider-1.0/.gitignore @@ -0,0 +1 @@ +!types \ No newline at end of file diff --git a/packages/types-vrmc-springbone-extended-collider-1.0/README.md b/packages/types-vrmc-springbone-extended-collider-1.0/README.md new file mode 100644 index 000000000..52705919e --- /dev/null +++ b/packages/types-vrmc-springbone-extended-collider-1.0/README.md @@ -0,0 +1,13 @@ +# @pixiv/types-vrmc-springbone-extended-collider-1.0 + +Type definitions of VRMC_springBone_extended_collider 1.0 schema. + +https://github.com/vrm-c/vrm-specification/tree/master/specification/VRMC_springBone_extended_collider-1.0 + +There should not be any implementation in this package. Just type definitions of the schema. + +The extension root is named `VRMCSpringBoneExtendedCollider` . + +[GitHub Repository](https://github.com/pixiv/three-vrm/tree/dev/packages/types-vrmc-springbone-extended-collider-1.0) + +[Documentation](https://pixiv.github.io/three-vrm/packages/types-vrmc-springbone-extended-collider-1.0/docs) diff --git a/packages/types-vrmc-springbone-extended-collider-1.0/package.json b/packages/types-vrmc-springbone-extended-collider-1.0/package.json new file mode 100644 index 000000000..b625735d4 --- /dev/null +++ b/packages/types-vrmc-springbone-extended-collider-1.0/package.json @@ -0,0 +1,32 @@ +{ + "name": "@pixiv/types-vrmc-springbone-extended-collider-1.0", + "version": "3.0.0", + "description": "Type definitions of VRMC_springBone_extended_collider 1.0 schema", + "license": "MIT", + "author": "pixiv", + "files": [ + "/types/", + "LICENSE" + ], + "main": "", + "types": "types/index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/pixiv/three-vrm.git", + "directory": "packages/types-vrmc-springbone-extended-collider-1.0" + }, + "scripts": { + "version": "yarn all", + "all": "yarn lint && yarn clean && yarn docs", + "clean": "rimraf docs/", + "docs": "typedoc --entryPoints ./types/index.d.ts --out docs", + "lint": "eslint \"types/**/*.{ts,tsx}\" && prettier \"types/**/*.{ts,tsx}\" --check", + "lint-fix": "eslint \"types/**/*.{ts,tsx}\" --fix && prettier \"types/**/*.{ts,tsx}\" --write" + }, + "lint-staged": { + "./types/**/*.{ts,tsx}": [ + "eslint --fix", + "prettier --write" + ] + } +} diff --git a/packages/types-vrmc-springbone-extended-collider-1.0/tsconfig.json b/packages/types-vrmc-springbone-extended-collider-1.0/tsconfig.json new file mode 100644 index 000000000..15b9f2152 --- /dev/null +++ b/packages/types-vrmc-springbone-extended-collider-1.0/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../../tsconfig.json", + "include": [ + "./types" + ] +} diff --git a/packages/types-vrmc-springbone-extended-collider-1.0/types/SpringBoneExtendedColliderShape.d.ts b/packages/types-vrmc-springbone-extended-collider-1.0/types/SpringBoneExtendedColliderShape.d.ts new file mode 100644 index 000000000..6d8f11397 --- /dev/null +++ b/packages/types-vrmc-springbone-extended-collider-1.0/types/SpringBoneExtendedColliderShape.d.ts @@ -0,0 +1,15 @@ +import type { SpringBoneExtendedColliderShapeCapsule } from './SpringBoneExtendedColliderShapeCapsule'; +import type { SpringBoneExtendedColliderShapePlane } from './SpringBoneExtendedColliderShapePlane'; +import type { SpringBoneExtendedColliderShapeSphere } from './SpringBoneExtendedColliderShapeSphere'; + +/** + * The shape of the collider. One of sphere, capsule, or plane is defined. + */ +export interface SpringBoneExtendedColliderShape { + sphere?: SpringBoneExtendedColliderShapeSphere; + capsule?: SpringBoneExtendedColliderShapeCapsule; + plane?: SpringBoneExtendedColliderShapePlane; + + extensions?: { [name: string]: any }; + extras?: any; +} diff --git a/packages/types-vrmc-springbone-extended-collider-1.0/types/SpringBoneExtendedColliderShapeCapsule.d.ts b/packages/types-vrmc-springbone-extended-collider-1.0/types/SpringBoneExtendedColliderShapeCapsule.d.ts new file mode 100644 index 000000000..017026612 --- /dev/null +++ b/packages/types-vrmc-springbone-extended-collider-1.0/types/SpringBoneExtendedColliderShapeCapsule.d.ts @@ -0,0 +1,21 @@ +export interface SpringBoneExtendedColliderShapeCapsule { + /** + * The offset of the capsule head from the origin in local space. + */ + offset?: [number, number, number]; + + /** + * The radius of the capsule. + */ + radius?: number; + + /** + * The offset of the capsule tail from the origin in local space. + */ + tail?: [number, number, number]; + + /** + * If true, the collider prevents spring bones from going outside of the capsule instead. + */ + inside?: boolean; +} diff --git a/packages/types-vrmc-springbone-extended-collider-1.0/types/SpringBoneExtendedColliderShapePlane.d.ts b/packages/types-vrmc-springbone-extended-collider-1.0/types/SpringBoneExtendedColliderShapePlane.d.ts new file mode 100644 index 000000000..c42d2cb34 --- /dev/null +++ b/packages/types-vrmc-springbone-extended-collider-1.0/types/SpringBoneExtendedColliderShapePlane.d.ts @@ -0,0 +1,11 @@ +export interface SpringBoneExtendedColliderShapePlane { + /** + * The offset of the plane from the origin in local space. + */ + offset?: [number, number, number]; + + /** + * The normal of the plane in local space. Must be normalized. + */ + normal?: [number, number, number]; +} diff --git a/packages/types-vrmc-springbone-extended-collider-1.0/types/SpringBoneExtendedColliderShapeSphere.d.ts b/packages/types-vrmc-springbone-extended-collider-1.0/types/SpringBoneExtendedColliderShapeSphere.d.ts new file mode 100644 index 000000000..66b413698 --- /dev/null +++ b/packages/types-vrmc-springbone-extended-collider-1.0/types/SpringBoneExtendedColliderShapeSphere.d.ts @@ -0,0 +1,16 @@ +export interface SpringBoneExtendedColliderShapeSphere { + /** + * The offset of the sphere from the origin in local space. + */ + offset?: [number, number, number]; + + /** + * The radius of the sphere. + */ + radius?: number; + + /** + * If true, the collider prevents spring bones from going outside of the sphere instead. + */ + inside?: boolean; +} diff --git a/packages/types-vrmc-springbone-extended-collider-1.0/types/VRMCSpringBoneExtendedCollider.d.ts b/packages/types-vrmc-springbone-extended-collider-1.0/types/VRMCSpringBoneExtendedCollider.d.ts new file mode 100644 index 000000000..db0d26e9e --- /dev/null +++ b/packages/types-vrmc-springbone-extended-collider-1.0/types/VRMCSpringBoneExtendedCollider.d.ts @@ -0,0 +1,19 @@ +import type { SpringBoneExtendedColliderShape } from './SpringBoneExtendedColliderShape'; + +/** + * An extended collider for VRMC_springBone. + */ +export interface VRMCSpringBoneExtendedCollider { + /** + * Specification version of VRMC_springBone_extended_collider. + */ + specVersion: '1.0-draft'; + + /** + * The shape of the collider. + */ + shape?: SpringBoneExtendedColliderShape; + + extensions?: { [name: string]: any }; + extras?: any; +} diff --git a/packages/types-vrmc-springbone-extended-collider-1.0/types/index.d.ts b/packages/types-vrmc-springbone-extended-collider-1.0/types/index.d.ts new file mode 100644 index 000000000..0442459e7 --- /dev/null +++ b/packages/types-vrmc-springbone-extended-collider-1.0/types/index.d.ts @@ -0,0 +1,5 @@ +export type { SpringBoneExtendedColliderShape } from './SpringBoneExtendedColliderShape'; +export type { SpringBoneExtendedColliderShapeCapsule } from './SpringBoneExtendedColliderShapeCapsule'; +export type { SpringBoneExtendedColliderShapeSphere } from './SpringBoneExtendedColliderShapeSphere'; +export type { SpringBoneExtendedColliderShapePlane } from './SpringBoneExtendedColliderShapePlane'; +export type { VRMCSpringBoneExtendedCollider } from './VRMCSpringBoneExtendedCollider';