@pmndrs/viverse 0.2.25 → 0.2.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,11 @@
1
+ import type { VRMHumanBoneName } from '@pixiv/three-vrm';
2
+ /**
3
+ * Maps standard BVH bone names to VRM humanoid bone names.
4
+ *
5
+ * Kept as a `.ts` module rather than a `.json` import on purpose: importing JSON requires
6
+ * import attributes (`with { type: 'json' }`), which survive into the published ESM build and
7
+ * break in-browser bundlers like the docs' Sandpack (Babel: "experimental syntax
8
+ * 'moduleAttributes' isn't currently enabled").
9
+ */
10
+ declare const bvhBoneMap: Record<string, VRMHumanBoneName>;
11
+ export default bvhBoneMap;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Maps standard BVH bone names to VRM humanoid bone names.
3
+ *
4
+ * Kept as a `.ts` module rather than a `.json` import on purpose: importing JSON requires
5
+ * import attributes (`with { type: 'json' }`), which survive into the published ESM build and
6
+ * break in-browser bundlers like the docs' Sandpack (Babel: "experimental syntax
7
+ * 'moduleAttributes' isn't currently enabled").
8
+ */
9
+ const bvhBoneMap = {
10
+ Hips: 'hips',
11
+ Spine: 'spine',
12
+ Spine1: 'chest',
13
+ Spine2: 'upperChest',
14
+ Neck: 'neck',
15
+ Head: 'head',
16
+ LeftShoulder: 'leftShoulder',
17
+ LeftArm: 'leftUpperArm',
18
+ LeftForeArm: 'leftLowerArm',
19
+ LeftHand: 'leftHand',
20
+ RightShoulder: 'rightShoulder',
21
+ RightArm: 'rightUpperArm',
22
+ RightForeArm: 'rightLowerArm',
23
+ RightHand: 'rightHand',
24
+ LeftUpLeg: 'leftUpperLeg',
25
+ LeftLeg: 'leftLowerLeg',
26
+ LeftFoot: 'leftFoot',
27
+ LeftToe: 'leftToes',
28
+ RightUpLeg: 'rightUpperLeg',
29
+ RightLeg: 'rightLowerLeg',
30
+ RightFoot: 'rightFoot',
31
+ RightToe: 'rightToes',
32
+ };
33
+ export default bvhBoneMap;
@@ -25,4 +25,4 @@ export declare function flattenCharacterAnimationOptions(options: Exclude<Charac
25
25
  export declare function loadCharacterAnimation(model: CharacterModel, url: string | DefaultUrl, type?: CharacterAnimationOptions['type'], removeXZMovement?: boolean, trimStartTime?: number | undefined, trimEndTime?: number | undefined, boneMap?: Record<string, VRMHumanBoneName> | undefined, scaleTime?: number | undefined, mask?: CharacterAnimationMask): Promise<AnimationClip>;
26
26
  export declare const mixamoBoneMap: Record<string, VRMHumanBoneName>;
27
27
  export declare const bvhBoneMap: Record<string, VRMHumanBoneName>;
28
- export declare const allBoneNames: string[];
28
+ export declare const allBoneNames: Array<string>;
@@ -4,10 +4,10 @@ import { BVHLoader } from 'three/examples/jsm/loaders/BVHLoader.js';
4
4
  import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js';
5
5
  import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
6
6
  import { applyAnimationBoneMap } from './bone-map.js';
7
- import _bvhBoneMap from './bvh-bone-map.json' with { type: 'json' };
7
+ import _bvhBoneMap from './bvh-bone-map.js';
8
8
  import { resolveDefaultCharacterAnimationUrl } from './default.js';
9
9
  import { applyMask } from './mask.js';
10
- import _mixamoBoneMap from './mixamo-bone-map.json' with { type: 'json' };
10
+ import _mixamoBoneMap from './mixamo-bone-map.js';
11
11
  import { scaleAnimationClipTime, trimAnimationClip } from './utils.js';
12
12
  import { vrmaLoader } from '../model/index.js';
13
13
  //helper variables for the quaternion retargeting
@@ -0,0 +1,11 @@
1
+ import type { VRMHumanBoneName } from '@pixiv/three-vrm';
2
+ /**
3
+ * Maps Mixamo bone names (`mixamorig*`) to VRM humanoid bone names.
4
+ *
5
+ * Kept as a `.ts` module rather than a `.json` import on purpose: importing JSON requires
6
+ * import attributes (`with { type: 'json' }`), which survive into the published ESM build and
7
+ * break in-browser bundlers like the docs' Sandpack (Babel: "experimental syntax
8
+ * 'moduleAttributes' isn't currently enabled").
9
+ */
10
+ declare const mixamoBoneMap: Record<string, VRMHumanBoneName>;
11
+ export default mixamoBoneMap;
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Maps Mixamo bone names (`mixamorig*`) to VRM humanoid bone names.
3
+ *
4
+ * Kept as a `.ts` module rather than a `.json` import on purpose: importing JSON requires
5
+ * import attributes (`with { type: 'json' }`), which survive into the published ESM build and
6
+ * break in-browser bundlers like the docs' Sandpack (Babel: "experimental syntax
7
+ * 'moduleAttributes' isn't currently enabled").
8
+ */
9
+ const mixamoBoneMap = {
10
+ mixamorigHips: 'hips',
11
+ mixamorigSpine: 'spine',
12
+ mixamorigSpine1: 'chest',
13
+ mixamorigSpine2: 'upperChest',
14
+ mixamorigNeck: 'neck',
15
+ mixamorigHead: 'head',
16
+ mixamorigLeftShoulder: 'leftShoulder',
17
+ mixamorigLeftArm: 'leftUpperArm',
18
+ mixamorigLeftForeArm: 'leftLowerArm',
19
+ mixamorigLeftHand: 'leftHand',
20
+ mixamorigLeftHandThumb1: 'leftThumbMetacarpal',
21
+ mixamorigLeftHandThumb2: 'leftThumbProximal',
22
+ mixamorigLeftHandThumb3: 'leftThumbDistal',
23
+ mixamorigLeftHandIndex1: 'leftIndexProximal',
24
+ mixamorigLeftHandIndex2: 'leftIndexIntermediate',
25
+ mixamorigLeftHandIndex3: 'leftIndexDistal',
26
+ mixamorigLeftHandMiddle1: 'leftMiddleProximal',
27
+ mixamorigLeftHandMiddle2: 'leftMiddleIntermediate',
28
+ mixamorigLeftHandMiddle3: 'leftMiddleDistal',
29
+ mixamorigLeftHandRing1: 'leftRingProximal',
30
+ mixamorigLeftHandRing2: 'leftRingIntermediate',
31
+ mixamorigLeftHandRing3: 'leftRingDistal',
32
+ mixamorigLeftHandPinky1: 'leftLittleProximal',
33
+ mixamorigLeftHandPinky2: 'leftLittleIntermediate',
34
+ mixamorigLeftHandPinky3: 'leftLittleDistal',
35
+ mixamorigRightShoulder: 'rightShoulder',
36
+ mixamorigRightArm: 'rightUpperArm',
37
+ mixamorigRightForeArm: 'rightLowerArm',
38
+ mixamorigRightHand: 'rightHand',
39
+ mixamorigRightHandPinky1: 'rightLittleProximal',
40
+ mixamorigRightHandPinky2: 'rightLittleIntermediate',
41
+ mixamorigRightHandPinky3: 'rightLittleDistal',
42
+ mixamorigRightHandRing1: 'rightRingProximal',
43
+ mixamorigRightHandRing2: 'rightRingIntermediate',
44
+ mixamorigRightHandRing3: 'rightRingDistal',
45
+ mixamorigRightHandMiddle1: 'rightMiddleProximal',
46
+ mixamorigRightHandMiddle2: 'rightMiddleIntermediate',
47
+ mixamorigRightHandMiddle3: 'rightMiddleDistal',
48
+ mixamorigRightHandIndex1: 'rightIndexProximal',
49
+ mixamorigRightHandIndex2: 'rightIndexIntermediate',
50
+ mixamorigRightHandIndex3: 'rightIndexDistal',
51
+ mixamorigRightHandThumb1: 'rightThumbMetacarpal',
52
+ mixamorigRightHandThumb2: 'rightThumbProximal',
53
+ mixamorigRightHandThumb3: 'rightThumbDistal',
54
+ mixamorigLeftUpLeg: 'leftUpperLeg',
55
+ mixamorigLeftLeg: 'leftLowerLeg',
56
+ mixamorigLeftFoot: 'leftFoot',
57
+ mixamorigLeftToeBase: 'leftToes',
58
+ mixamorigRightUpLeg: 'rightUpperLeg',
59
+ mixamorigRightLeg: 'rightLowerLeg',
60
+ mixamorigRightFoot: 'rightFoot',
61
+ mixamorigRightToeBase: 'rightToes',
62
+ };
63
+ export default mixamoBoneMap;
@@ -1,18 +1,23 @@
1
- import { Box3, DoubleSide, InstancedMesh, Matrix4, Mesh, Ray, Vector3, } from 'three';
2
- import { computeBoundsTree, StaticGeometryGenerator, ExtendedTriangle } from 'three-mesh-bvh';
1
+ import { Box3, BufferGeometry, DoubleSide, InstancedMesh, Matrix4, Mesh, Ray, Vector3, } from 'three';
2
+ import { mergeGeometries } from 'three/examples/jsm/utils/BufferGeometryUtils.js';
3
+ import { computeBoundsTree, ExtendedTriangle } from 'three-mesh-bvh';
3
4
  const rayHelper = new Ray();
4
5
  const farPointHelper = new Vector3();
5
6
  const boxHelper = new Box3();
6
7
  const triangleHelper = new ExtendedTriangle();
7
8
  const matrixHelper = new Matrix4();
8
9
  /**
9
- * Identifies which geometries StaticGeometryGenerator can merge together. Geometries are mergeable when they share
10
- * the same set of attributes and agree on whether they are indexed, so two geometries with an equal signature are
11
- * guaranteed not to trigger the "Make sure all geometries have the same number of attributes." error.
10
+ * Bakes a mesh's collision geometry into `matrix` space. A bvh only needs positions and (optionally) an index, so
11
+ * everything else is dropped - this keeps the merge below trivial and sidesteps three's "geometries must have the
12
+ * same attributes" restriction that a body mixing meshes with different attribute sets (e.g. gltf primitives) hits.
12
13
  */
13
- function geometryAttributeSignature(geometry) {
14
- const attributeNames = Object.keys(geometry.attributes).sort().join(',');
15
- return `${geometry.index == null ? 'non-indexed' : 'indexed'}:${attributeNames}`;
14
+ function bakeCollisionGeometry(mesh, matrix) {
15
+ const geometry = new BufferGeometry();
16
+ geometry.setAttribute('position', mesh.geometry.getAttribute('position').clone());
17
+ if (mesh.geometry.index != null) {
18
+ geometry.setIndex(mesh.geometry.index.clone());
19
+ }
20
+ return geometry.applyMatrix4(matrix);
16
21
  }
17
22
  export class BvhPhysicsWorld {
18
23
  bodies = [];
@@ -38,11 +43,15 @@ export class BvhPhysicsWorld {
38
43
  }
39
44
  computeBvhEntries(object, isStatic) {
40
45
  object.updateWorldMatrix(true, true);
46
+ //Static bodies are baked in world space; kinematic bodies are baked in the body's local space so that its
47
+ //(changing) world matrix can be applied at query time instead (see computeMatrix), hence the inverse here.
48
+ const worldToBakeSpace = isStatic ? undefined : new Matrix4().copy(object.matrixWorld).invert();
49
+ const bakeMatrix = new Matrix4();
41
50
  const result = [];
42
- //StaticGeometryGenerator merges all meshes into a single geometry and throws if they don't all expose
43
- //the same attributes ("Make sure all geometries have the same number of attributes."). Group the meshes by
44
- //their attribute signature so every merge only ever sees compatible geometries and generate one bvh per group.
45
- const meshGroups = new Map();
51
+ //A merge of collision geometries only works when they agree on being indexed, so keep indexed and
52
+ //non-indexed meshes apart and turn each group into its own bvh.
53
+ const indexedGeometries = [];
54
+ const nonIndexedGeometries = [];
46
55
  object.traverse((entry) => {
47
56
  if (entry instanceof InstancedMesh) {
48
57
  const bvh = computeBoundsTree.apply(entry.geometry);
@@ -54,30 +63,23 @@ export class BvhPhysicsWorld {
54
63
  })));
55
64
  return;
56
65
  }
57
- if (entry instanceof Mesh) {
58
- const signature = geometryAttributeSignature(entry.geometry);
59
- let group = meshGroups.get(signature);
60
- if (group == null) {
61
- meshGroups.set(signature, (group = []));
62
- }
63
- group.push(entry);
64
- }
65
- });
66
- if (meshGroups.size > 0) {
67
- const parent = object.parent;
68
- if (!isStatic) {
69
- object.parent = null;
70
- object.updateMatrixWorld(true);
66
+ if (!(entry instanceof Mesh)) {
67
+ return;
71
68
  }
72
- for (const meshes of meshGroups.values()) {
73
- const geometry = new StaticGeometryGenerator(meshes).generate();
74
- const bvh = computeBoundsTree.apply(geometry);
75
- result.push({ object, bvh, isStatic });
69
+ bakeMatrix.copy(entry.matrixWorld);
70
+ if (worldToBakeSpace != null) {
71
+ bakeMatrix.premultiply(worldToBakeSpace);
76
72
  }
77
- if (!isStatic) {
78
- object.parent = parent;
79
- object.updateMatrixWorld(true);
73
+ const geometry = bakeCollisionGeometry(entry, bakeMatrix);
74
+ (geometry.index == null ? nonIndexedGeometries : indexedGeometries).push(geometry);
75
+ });
76
+ for (const geometries of [indexedGeometries, nonIndexedGeometries]) {
77
+ if (geometries.length === 0) {
78
+ continue;
80
79
  }
80
+ const geometry = geometries.length === 1 ? geometries[0] : mergeGeometries(geometries);
81
+ const bvh = computeBoundsTree.apply(geometry);
82
+ result.push({ object, bvh, isStatic });
81
83
  }
82
84
  return result;
83
85
  }
package/package.json CHANGED
@@ -21,7 +21,7 @@
21
21
  "peerDependencies": {
22
22
  "three": "*"
23
23
  },
24
- "version": "0.2.25",
24
+ "version": "0.2.26",
25
25
  "type": "module",
26
26
  "dependencies": {
27
27
  "@pixiv/three-vrm": "^3.4.2",
@@ -1,24 +0,0 @@
1
- {
2
- "Hips": "hips",
3
- "Spine": "spine",
4
- "Spine1": "chest",
5
- "Spine2": "upperChest",
6
- "Neck": "neck",
7
- "Head": "head",
8
- "LeftShoulder": "leftShoulder",
9
- "LeftArm": "leftUpperArm",
10
- "LeftForeArm": "leftLowerArm",
11
- "LeftHand": "leftHand",
12
- "RightShoulder": "rightShoulder",
13
- "RightArm": "rightUpperArm",
14
- "RightForeArm": "rightLowerArm",
15
- "RightHand": "rightHand",
16
- "LeftUpLeg": "leftUpperLeg",
17
- "LeftLeg": "leftLowerLeg",
18
- "LeftFoot": "leftFoot",
19
- "LeftToe": "leftToes",
20
- "RightUpLeg": "rightUpperLeg",
21
- "RightLeg": "rightLowerLeg",
22
- "RightFoot": "rightFoot",
23
- "RightToe": "rightToes"
24
- }
@@ -1,54 +0,0 @@
1
- {
2
- "mixamorigHips": "hips",
3
- "mixamorigSpine": "spine",
4
- "mixamorigSpine1": "chest",
5
- "mixamorigSpine2": "upperChest",
6
- "mixamorigNeck": "neck",
7
- "mixamorigHead": "head",
8
- "mixamorigLeftShoulder": "leftShoulder",
9
- "mixamorigLeftArm": "leftUpperArm",
10
- "mixamorigLeftForeArm": "leftLowerArm",
11
- "mixamorigLeftHand": "leftHand",
12
- "mixamorigLeftHandThumb1": "leftThumbMetacarpal",
13
- "mixamorigLeftHandThumb2": "leftThumbProximal",
14
- "mixamorigLeftHandThumb3": "leftThumbDistal",
15
- "mixamorigLeftHandIndex1": "leftIndexProximal",
16
- "mixamorigLeftHandIndex2": "leftIndexIntermediate",
17
- "mixamorigLeftHandIndex3": "leftIndexDistal",
18
- "mixamorigLeftHandMiddle1": "leftMiddleProximal",
19
- "mixamorigLeftHandMiddle2": "leftMiddleIntermediate",
20
- "mixamorigLeftHandMiddle3": "leftMiddleDistal",
21
- "mixamorigLeftHandRing1": "leftRingProximal",
22
- "mixamorigLeftHandRing2": "leftRingIntermediate",
23
- "mixamorigLeftHandRing3": "leftRingDistal",
24
- "mixamorigLeftHandPinky1": "leftLittleProximal",
25
- "mixamorigLeftHandPinky2": "leftLittleIntermediate",
26
- "mixamorigLeftHandPinky3": "leftLittleDistal",
27
- "mixamorigRightShoulder": "rightShoulder",
28
- "mixamorigRightArm": "rightUpperArm",
29
- "mixamorigRightForeArm": "rightLowerArm",
30
- "mixamorigRightHand": "rightHand",
31
- "mixamorigRightHandPinky1": "rightLittleProximal",
32
- "mixamorigRightHandPinky2": "rightLittleIntermediate",
33
- "mixamorigRightHandPinky3": "rightLittleDistal",
34
- "mixamorigRightHandRing1": "rightRingProximal",
35
- "mixamorigRightHandRing2": "rightRingIntermediate",
36
- "mixamorigRightHandRing3": "rightRingDistal",
37
- "mixamorigRightHandMiddle1": "rightMiddleProximal",
38
- "mixamorigRightHandMiddle2": "rightMiddleIntermediate",
39
- "mixamorigRightHandMiddle3": "rightMiddleDistal",
40
- "mixamorigRightHandIndex1": "rightIndexProximal",
41
- "mixamorigRightHandIndex2": "rightIndexIntermediate",
42
- "mixamorigRightHandIndex3": "rightIndexDistal",
43
- "mixamorigRightHandThumb1": "rightThumbMetacarpal",
44
- "mixamorigRightHandThumb2": "rightThumbProximal",
45
- "mixamorigRightHandThumb3": "rightThumbDistal",
46
- "mixamorigLeftUpLeg": "leftUpperLeg",
47
- "mixamorigLeftLeg": "leftLowerLeg",
48
- "mixamorigLeftFoot": "leftFoot",
49
- "mixamorigLeftToeBase": "leftToes",
50
- "mixamorigRightUpLeg": "rightUpperLeg",
51
- "mixamorigRightLeg": "rightLowerLeg",
52
- "mixamorigRightFoot": "rightFoot",
53
- "mixamorigRightToeBase": "rightToes"
54
- }