@pixiv/three-vrm-core 1.0.0-beta.10 → 1.0.0-beta.11

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.
Files changed (58) hide show
  1. package/lib/three-vrm-core.js +2549 -2549
  2. package/lib/three-vrm-core.module.js +2549 -2549
  3. package/package.json +4 -4
  4. package/types/VRMCore.d.ts +58 -58
  5. package/types/VRMCoreLoaderPlugin.d.ts +18 -18
  6. package/types/VRMCoreLoaderPluginOptions.d.ts +18 -18
  7. package/types/VRMCoreParameters.d.ts +16 -16
  8. package/types/expressions/VRMExpression.d.ts +64 -64
  9. package/types/expressions/VRMExpressionBind.d.ts +11 -11
  10. package/types/expressions/VRMExpressionLoaderPlugin.d.ts +23 -23
  11. package/types/expressions/VRMExpressionManager.d.ts +124 -124
  12. package/types/expressions/VRMExpressionMaterialColorBind.d.ts +42 -42
  13. package/types/expressions/VRMExpressionMaterialColorType.d.ts +8 -8
  14. package/types/expressions/VRMExpressionMorphTargetBind.d.ts +35 -35
  15. package/types/expressions/VRMExpressionOverrideType.d.ts +6 -6
  16. package/types/expressions/VRMExpressionPresetName.d.ts +21 -21
  17. package/types/expressions/VRMExpressionTextureTransformBind.d.ts +40 -40
  18. package/types/expressions/index.d.ts +10 -10
  19. package/types/firstPerson/VRMFirstPerson.d.ts +84 -84
  20. package/types/firstPerson/VRMFirstPersonLoaderPlugin.d.ts +20 -20
  21. package/types/firstPerson/VRMFirstPersonMeshAnnotation.d.ts +5 -5
  22. package/types/firstPerson/VRMFirstPersonMeshAnnotationType.d.ts +7 -7
  23. package/types/firstPerson/index.d.ts +4 -4
  24. package/types/humanoid/VRMHumanBone.d.ts +10 -10
  25. package/types/humanoid/VRMHumanBoneName.d.ts +58 -58
  26. package/types/humanoid/VRMHumanBones.d.ts +11 -11
  27. package/types/humanoid/VRMHumanoid.d.ts +73 -73
  28. package/types/humanoid/VRMHumanoidLoaderPlugin.d.ts +24 -24
  29. package/types/humanoid/VRMPose.d.ts +24 -24
  30. package/types/humanoid/VRMPoseTransform.d.ts +15 -15
  31. package/types/humanoid/VRMRequiredHumanBoneName.d.ts +18 -18
  32. package/types/humanoid/index.d.ts +8 -8
  33. package/types/index.d.ts +9 -9
  34. package/types/lookAt/VRMLookAt.d.ts +104 -104
  35. package/types/lookAt/VRMLookAtApplier.d.ts +12 -12
  36. package/types/lookAt/VRMLookAtBoneApplier.d.ts +50 -50
  37. package/types/lookAt/VRMLookAtExpressionApplier.d.ts +51 -51
  38. package/types/lookAt/VRMLookAtLoaderPlugin.d.ts +30 -30
  39. package/types/lookAt/VRMLookAtLoaderPluginOptions.d.ts +8 -8
  40. package/types/lookAt/VRMLookAtRangeMap.d.ts +23 -23
  41. package/types/lookAt/VRMLookAtTypeName.d.ts +8 -8
  42. package/types/lookAt/helpers/VRMLookAtHelper.d.ts +11 -11
  43. package/types/lookAt/helpers/index.d.ts +1 -1
  44. package/types/lookAt/helpers/utils/FanBufferGeometry.d.ts +13 -13
  45. package/types/lookAt/helpers/utils/LineAndSphereBufferGeometry.d.ts +13 -13
  46. package/types/lookAt/index.d.ts +8 -8
  47. package/types/meta/VRM0Meta.d.ts +62 -62
  48. package/types/meta/VRM1Meta.d.ts +86 -86
  49. package/types/meta/VRMMeta.d.ts +6 -6
  50. package/types/meta/VRMMetaLoaderPlugin.d.ts +32 -32
  51. package/types/meta/VRMMetaLoaderPluginOptions.d.ts +22 -22
  52. package/types/meta/index.d.ts +5 -5
  53. package/types/utils/getWorldQuaternionLite.d.ts +8 -8
  54. package/types/utils/gltfExtractPrimitivesFromNode.d.ts +21 -21
  55. package/types/utils/gltfGetAssociatedMaterialIndex.d.ts +10 -10
  56. package/types/utils/quatInvertCompat.d.ts +8 -8
  57. package/types/utils/resolveURL.d.ts +4 -4
  58. package/types/utils/saturate.d.ts +6 -6
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @pixiv/three-vrm-core v1.0.0-beta.10
2
+ * @pixiv/three-vrm-core v1.0.0-beta.11
3
3
  * The implementation of core features of VRM, for @pixiv/three-vrm
4
4
  *
5
5
  * Copyright (c) 2020-2021 pixiv Inc.
@@ -34,104 +34,104 @@
34
34
 
35
35
  var THREE__namespace = /*#__PURE__*/_interopNamespace(THREE);
36
36
 
37
- // animationMixer の監視対象は、Scene の中に入っている必要がある。
38
- // そのため、表示オブジェクトではないけれど、Object3D を継承して Scene に投入できるようにする。
39
- class VRMExpression extends THREE__namespace.Object3D {
40
- constructor(expressionName) {
41
- super();
42
- /**
43
- * The current weight of the expression.
44
- */
45
- this.weight = 0.0;
46
- /**
47
- * Interpret non-zero values as 1.
48
- */
49
- this.isBinary = false;
50
- /**
51
- * Specify how the expression overrides blink expressions.
52
- */
53
- this.overrideBlink = 'none';
54
- /**
55
- * Specify how the expression overrides lookAt expressions.
56
- */
57
- this.overrideLookAt = 'none';
58
- /**
59
- * Specify how the expression overrides mouth expressions.
60
- */
61
- this.overrideMouth = 'none';
62
- this._binds = [];
63
- this.name = `VRMExpression_${expressionName}`;
64
- this.expressionName = expressionName;
65
- // traverse 時の救済手段として Object3D ではないことを明示しておく
66
- this.type = 'VRMExpression';
67
- // 表示目的のオブジェクトではないので、負荷軽減のために visible を false にしておく。
68
- // これにより、このインスタンスに対する毎フレームの matrix 自動計算を省略できる。
69
- this.visible = false;
70
- }
71
- /**
72
- * A value represents how much it should override blink expressions.
73
- * `0.0` == no override at all, `1.0` == completely block the expressions.
74
- */
75
- get overrideBlinkAmount() {
76
- if (this.overrideBlink === 'block') {
77
- return 0.0 < this.weight ? 1.0 : 0.0;
78
- }
79
- else if (this.overrideBlink === 'blend') {
80
- return this.weight;
81
- }
82
- else {
83
- return 0.0;
84
- }
85
- }
86
- /**
87
- * A value represents how much it should override lookAt expressions.
88
- * `0.0` == no override at all, `1.0` == completely block the expressions.
89
- */
90
- get overrideLookAtAmount() {
91
- if (this.overrideLookAt === 'block') {
92
- return 0.0 < this.weight ? 1.0 : 0.0;
93
- }
94
- else if (this.overrideLookAt === 'blend') {
95
- return this.weight;
96
- }
97
- else {
98
- return 0.0;
99
- }
100
- }
101
- /**
102
- * A value represents how much it should override mouth expressions.
103
- * `0.0` == no override at all, `1.0` == completely block the expressions.
104
- */
105
- get overrideMouthAmount() {
106
- if (this.overrideMouth === 'block') {
107
- return 0.0 < this.weight ? 1.0 : 0.0;
108
- }
109
- else if (this.overrideMouth === 'blend') {
110
- return this.weight;
111
- }
112
- else {
113
- return 0.0;
114
- }
115
- }
116
- addBind(bind) {
117
- this._binds.push(bind);
118
- }
119
- /**
120
- * Apply weight to every assigned blend shapes.
121
- * Should be called every frame.
122
- */
123
- applyWeight(options) {
124
- var _a;
125
- let actualWeight = this.isBinary ? (this.weight === 0.0 ? 0.0 : 1.0) : this.weight;
126
- actualWeight *= (_a = options === null || options === void 0 ? void 0 : options.multiplier) !== null && _a !== void 0 ? _a : 1.0;
127
- this._binds.forEach((bind) => bind.applyWeight(actualWeight));
128
- }
129
- /**
130
- * Clear previously assigned blend shapes.
131
- */
132
- clearAppliedWeight() {
133
- this._binds.forEach((bind) => bind.clearAppliedWeight());
134
- }
37
+ // animationMixer の監視対象は、Scene の中に入っている必要がある。
38
+ // そのため、表示オブジェクトではないけれど、Object3D を継承して Scene に投入できるようにする。
39
+ class VRMExpression extends THREE__namespace.Object3D {
40
+ constructor(expressionName) {
41
+ super();
42
+ /**
43
+ * The current weight of the expression.
44
+ */
45
+ this.weight = 0.0;
46
+ /**
47
+ * Interpret non-zero values as 1.
48
+ */
49
+ this.isBinary = false;
50
+ /**
51
+ * Specify how the expression overrides blink expressions.
52
+ */
53
+ this.overrideBlink = 'none';
54
+ /**
55
+ * Specify how the expression overrides lookAt expressions.
56
+ */
57
+ this.overrideLookAt = 'none';
58
+ /**
59
+ * Specify how the expression overrides mouth expressions.
60
+ */
61
+ this.overrideMouth = 'none';
62
+ this._binds = [];
63
+ this.name = `VRMExpression_${expressionName}`;
64
+ this.expressionName = expressionName;
65
+ // traverse 時の救済手段として Object3D ではないことを明示しておく
66
+ this.type = 'VRMExpression';
67
+ // 表示目的のオブジェクトではないので、負荷軽減のために visible を false にしておく。
68
+ // これにより、このインスタンスに対する毎フレームの matrix 自動計算を省略できる。
69
+ this.visible = false;
70
+ }
71
+ /**
72
+ * A value represents how much it should override blink expressions.
73
+ * `0.0` == no override at all, `1.0` == completely block the expressions.
74
+ */
75
+ get overrideBlinkAmount() {
76
+ if (this.overrideBlink === 'block') {
77
+ return 0.0 < this.weight ? 1.0 : 0.0;
78
+ }
79
+ else if (this.overrideBlink === 'blend') {
80
+ return this.weight;
81
+ }
82
+ else {
83
+ return 0.0;
84
+ }
85
+ }
86
+ /**
87
+ * A value represents how much it should override lookAt expressions.
88
+ * `0.0` == no override at all, `1.0` == completely block the expressions.
89
+ */
90
+ get overrideLookAtAmount() {
91
+ if (this.overrideLookAt === 'block') {
92
+ return 0.0 < this.weight ? 1.0 : 0.0;
93
+ }
94
+ else if (this.overrideLookAt === 'blend') {
95
+ return this.weight;
96
+ }
97
+ else {
98
+ return 0.0;
99
+ }
100
+ }
101
+ /**
102
+ * A value represents how much it should override mouth expressions.
103
+ * `0.0` == no override at all, `1.0` == completely block the expressions.
104
+ */
105
+ get overrideMouthAmount() {
106
+ if (this.overrideMouth === 'block') {
107
+ return 0.0 < this.weight ? 1.0 : 0.0;
108
+ }
109
+ else if (this.overrideMouth === 'blend') {
110
+ return this.weight;
111
+ }
112
+ else {
113
+ return 0.0;
114
+ }
115
+ }
116
+ addBind(bind) {
117
+ this._binds.push(bind);
118
+ }
119
+ /**
120
+ * Apply weight to every assigned blend shapes.
121
+ * Should be called every frame.
122
+ */
123
+ applyWeight(options) {
124
+ var _a;
125
+ let actualWeight = this.isBinary ? (this.weight === 0.0 ? 0.0 : 1.0) : this.weight;
126
+ actualWeight *= (_a = options === null || options === void 0 ? void 0 : options.multiplier) !== null && _a !== void 0 ? _a : 1.0;
127
+ this._binds.forEach((bind) => bind.applyWeight(actualWeight));
128
+ }
129
+ /**
130
+ * Clear previously assigned blend shapes.
131
+ */
132
+ clearAppliedWeight() {
133
+ this._binds.forEach((bind) => bind.clearAppliedWeight());
134
+ }
135
135
  }
136
136
 
137
137
  /*! *****************************************************************************
@@ -159,2520 +159,2520 @@
159
159
  });
160
160
  }
161
161
 
162
- function extractPrimitivesInternal(gltf, nodeIndex, node) {
163
- var _a, _b;
164
- const json = gltf.parser.json;
165
- /**
166
- * Let's list up every possible patterns that parsed gltf nodes with a mesh can have,,,
167
- *
168
- * "*" indicates that those meshes should be listed up using this function
169
- *
170
- * ### A node with a (mesh, a signle primitive)
171
- *
172
- * - `THREE.Mesh`: The only primitive of the mesh *
173
- *
174
- * ### A node with a (mesh, multiple primitives)
175
- *
176
- * - `THREE.Group`: The root of the mesh
177
- * - `THREE.Mesh`: A primitive of the mesh *
178
- * - `THREE.Mesh`: A primitive of the mesh (2) *
179
- *
180
- * ### A node with a (mesh, multiple primitives) AND (a child with a mesh, a single primitive)
181
- *
182
- * - `THREE.Group`: The root of the mesh
183
- * - `THREE.Mesh`: A primitive of the mesh *
184
- * - `THREE.Mesh`: A primitive of the mesh (2) *
185
- * - `THREE.Mesh`: A primitive of a MESH OF THE CHILD
186
- *
187
- * ### A node with a (mesh, multiple primitives) AND (a child with a mesh, multiple primitives)
188
- *
189
- * - `THREE.Group`: The root of the mesh
190
- * - `THREE.Mesh`: A primitive of the mesh *
191
- * - `THREE.Mesh`: A primitive of the mesh (2) *
192
- * - `THREE.Group`: The root of a MESH OF THE CHILD
193
- * - `THREE.Mesh`: A primitive of the mesh of the child
194
- * - `THREE.Mesh`: A primitive of the mesh of the child (2)
195
- *
196
- * ### A node with a (mesh, multiple primitives) BUT the node is a bone
197
- *
198
- * - `THREE.Bone`: The root of the node, as a bone
199
- * - `THREE.Group`: The root of the mesh
200
- * - `THREE.Mesh`: A primitive of the mesh *
201
- * - `THREE.Mesh`: A primitive of the mesh (2) *
202
- *
203
- * ### A node with a (mesh, multiple primitives) AND (a child with a mesh, multiple primitives) BUT the node is a bone
204
- *
205
- * - `THREE.Bone`: The root of the node, as a bone
206
- * - `THREE.Group`: The root of the mesh
207
- * - `THREE.Mesh`: A primitive of the mesh *
208
- * - `THREE.Mesh`: A primitive of the mesh (2) *
209
- * - `THREE.Group`: The root of a MESH OF THE CHILD
210
- * - `THREE.Mesh`: A primitive of the mesh of the child
211
- * - `THREE.Mesh`: A primitive of the mesh of the child (2)
212
- *
213
- * ...I will take a strategy that traverses the root of the node and take first (primitiveCount) meshes.
214
- */
215
- // Make sure that the node has a mesh
216
- const schemaNode = (_a = json.nodes) === null || _a === void 0 ? void 0 : _a[nodeIndex];
217
- if (schemaNode == null) {
218
- console.warn(`extractPrimitivesInternal: Attempt to use nodes[${nodeIndex}] of glTF but the node doesn't exist`);
219
- return null;
220
- }
221
- const meshIndex = schemaNode.mesh;
222
- if (meshIndex == null) {
223
- return null;
224
- }
225
- // How many primitives the mesh has?
226
- const schemaMesh = (_b = json.meshes) === null || _b === void 0 ? void 0 : _b[meshIndex];
227
- if (schemaMesh == null) {
228
- console.warn(`extractPrimitivesInternal: Attempt to use meshes[${meshIndex}] of glTF but the mesh doesn't exist`);
229
- return null;
230
- }
231
- const primitiveCount = schemaMesh.primitives.length;
232
- // Traverse the node and take first (primitiveCount) meshes
233
- const primitives = [];
234
- node.traverse((object) => {
235
- if (primitives.length < primitiveCount) {
236
- if (object.isMesh) {
237
- primitives.push(object);
238
- }
239
- }
240
- });
241
- return primitives;
242
- }
243
- /**
244
- * Extract primitives ( `THREE.Mesh[]` ) of a node from a loaded GLTF.
245
- * The main purpose of this function is to distinguish primitives and children from a node that has both meshes and children.
246
- *
247
- * It utilizes the behavior that GLTFLoader adds mesh primitives to the node object ( `THREE.Group` ) first then adds its children.
248
- *
249
- * @param gltf A GLTF object taken from GLTFLoader
250
- * @param nodeIndex The index of the node
251
- */
252
- function gltfExtractPrimitivesFromNode(gltf, nodeIndex) {
253
- return __awaiter(this, void 0, void 0, function* () {
254
- const node = yield gltf.parser.getDependency('node', nodeIndex);
255
- return extractPrimitivesInternal(gltf, nodeIndex, node);
256
- });
257
- }
258
- /**
259
- * Extract primitives ( `THREE.Mesh[]` ) of nodes from a loaded GLTF.
260
- * See {@link gltfExtractPrimitivesFromNode} for more details.
261
- *
262
- * It returns a map from node index to extraction result.
263
- * If a node does not have a mesh, the entry for the node will not be put in the returning map.
264
- *
265
- * @param gltf A GLTF object taken from GLTFLoader
266
- */
267
- function gltfExtractPrimitivesFromNodes(gltf) {
268
- return __awaiter(this, void 0, void 0, function* () {
269
- const nodes = yield gltf.parser.getDependencies('node');
270
- const map = new Map();
271
- nodes.forEach((node, index) => {
272
- const result = extractPrimitivesInternal(gltf, index, node);
273
- if (result != null) {
274
- map.set(index, result);
275
- }
276
- });
277
- return map;
278
- });
162
+ function extractPrimitivesInternal(gltf, nodeIndex, node) {
163
+ var _a, _b;
164
+ const json = gltf.parser.json;
165
+ /**
166
+ * Let's list up every possible patterns that parsed gltf nodes with a mesh can have,,,
167
+ *
168
+ * "*" indicates that those meshes should be listed up using this function
169
+ *
170
+ * ### A node with a (mesh, a signle primitive)
171
+ *
172
+ * - `THREE.Mesh`: The only primitive of the mesh *
173
+ *
174
+ * ### A node with a (mesh, multiple primitives)
175
+ *
176
+ * - `THREE.Group`: The root of the mesh
177
+ * - `THREE.Mesh`: A primitive of the mesh *
178
+ * - `THREE.Mesh`: A primitive of the mesh (2) *
179
+ *
180
+ * ### A node with a (mesh, multiple primitives) AND (a child with a mesh, a single primitive)
181
+ *
182
+ * - `THREE.Group`: The root of the mesh
183
+ * - `THREE.Mesh`: A primitive of the mesh *
184
+ * - `THREE.Mesh`: A primitive of the mesh (2) *
185
+ * - `THREE.Mesh`: A primitive of a MESH OF THE CHILD
186
+ *
187
+ * ### A node with a (mesh, multiple primitives) AND (a child with a mesh, multiple primitives)
188
+ *
189
+ * - `THREE.Group`: The root of the mesh
190
+ * - `THREE.Mesh`: A primitive of the mesh *
191
+ * - `THREE.Mesh`: A primitive of the mesh (2) *
192
+ * - `THREE.Group`: The root of a MESH OF THE CHILD
193
+ * - `THREE.Mesh`: A primitive of the mesh of the child
194
+ * - `THREE.Mesh`: A primitive of the mesh of the child (2)
195
+ *
196
+ * ### A node with a (mesh, multiple primitives) BUT the node is a bone
197
+ *
198
+ * - `THREE.Bone`: The root of the node, as a bone
199
+ * - `THREE.Group`: The root of the mesh
200
+ * - `THREE.Mesh`: A primitive of the mesh *
201
+ * - `THREE.Mesh`: A primitive of the mesh (2) *
202
+ *
203
+ * ### A node with a (mesh, multiple primitives) AND (a child with a mesh, multiple primitives) BUT the node is a bone
204
+ *
205
+ * - `THREE.Bone`: The root of the node, as a bone
206
+ * - `THREE.Group`: The root of the mesh
207
+ * - `THREE.Mesh`: A primitive of the mesh *
208
+ * - `THREE.Mesh`: A primitive of the mesh (2) *
209
+ * - `THREE.Group`: The root of a MESH OF THE CHILD
210
+ * - `THREE.Mesh`: A primitive of the mesh of the child
211
+ * - `THREE.Mesh`: A primitive of the mesh of the child (2)
212
+ *
213
+ * ...I will take a strategy that traverses the root of the node and take first (primitiveCount) meshes.
214
+ */
215
+ // Make sure that the node has a mesh
216
+ const schemaNode = (_a = json.nodes) === null || _a === void 0 ? void 0 : _a[nodeIndex];
217
+ if (schemaNode == null) {
218
+ console.warn(`extractPrimitivesInternal: Attempt to use nodes[${nodeIndex}] of glTF but the node doesn't exist`);
219
+ return null;
220
+ }
221
+ const meshIndex = schemaNode.mesh;
222
+ if (meshIndex == null) {
223
+ return null;
224
+ }
225
+ // How many primitives the mesh has?
226
+ const schemaMesh = (_b = json.meshes) === null || _b === void 0 ? void 0 : _b[meshIndex];
227
+ if (schemaMesh == null) {
228
+ console.warn(`extractPrimitivesInternal: Attempt to use meshes[${meshIndex}] of glTF but the mesh doesn't exist`);
229
+ return null;
230
+ }
231
+ const primitiveCount = schemaMesh.primitives.length;
232
+ // Traverse the node and take first (primitiveCount) meshes
233
+ const primitives = [];
234
+ node.traverse((object) => {
235
+ if (primitives.length < primitiveCount) {
236
+ if (object.isMesh) {
237
+ primitives.push(object);
238
+ }
239
+ }
240
+ });
241
+ return primitives;
242
+ }
243
+ /**
244
+ * Extract primitives ( `THREE.Mesh[]` ) of a node from a loaded GLTF.
245
+ * The main purpose of this function is to distinguish primitives and children from a node that has both meshes and children.
246
+ *
247
+ * It utilizes the behavior that GLTFLoader adds mesh primitives to the node object ( `THREE.Group` ) first then adds its children.
248
+ *
249
+ * @param gltf A GLTF object taken from GLTFLoader
250
+ * @param nodeIndex The index of the node
251
+ */
252
+ function gltfExtractPrimitivesFromNode(gltf, nodeIndex) {
253
+ return __awaiter(this, void 0, void 0, function* () {
254
+ const node = yield gltf.parser.getDependency('node', nodeIndex);
255
+ return extractPrimitivesInternal(gltf, nodeIndex, node);
256
+ });
257
+ }
258
+ /**
259
+ * Extract primitives ( `THREE.Mesh[]` ) of nodes from a loaded GLTF.
260
+ * See {@link gltfExtractPrimitivesFromNode} for more details.
261
+ *
262
+ * It returns a map from node index to extraction result.
263
+ * If a node does not have a mesh, the entry for the node will not be put in the returning map.
264
+ *
265
+ * @param gltf A GLTF object taken from GLTFLoader
266
+ */
267
+ function gltfExtractPrimitivesFromNodes(gltf) {
268
+ return __awaiter(this, void 0, void 0, function* () {
269
+ const nodes = yield gltf.parser.getDependencies('node');
270
+ const map = new Map();
271
+ nodes.forEach((node, index) => {
272
+ const result = extractPrimitivesInternal(gltf, index, node);
273
+ if (result != null) {
274
+ map.set(index, result);
275
+ }
276
+ });
277
+ return map;
278
+ });
279
279
  }
280
280
 
281
- /**
282
- * Get a material definition index of glTF from associated material.
283
- * It's basically a comat code between Three.js r133 or above and previous versions.
284
- * @param parser GLTFParser
285
- * @param material A material of gltf
286
- * @returns Material definition index of glTF
287
- */
288
- function gltfGetAssociatedMaterialIndex(parser, material) {
289
- var _a, _b;
290
- const threeRevision = parseInt(THREE__namespace.REVISION, 10);
291
- let index = null;
292
- if (threeRevision >= 133) {
293
- index = (_b = (_a = parser.associations.get(material)) === null || _a === void 0 ? void 0 : _a.materials) !== null && _b !== void 0 ? _b : null;
294
- }
295
- else {
296
- const associations = parser.associations;
297
- const reference = associations.get(material);
298
- if ((reference === null || reference === void 0 ? void 0 : reference.type) === 'materials') {
299
- index = reference.index;
300
- }
301
- }
302
- return index;
281
+ /**
282
+ * Get a material definition index of glTF from associated material.
283
+ * It's basically a comat code between Three.js r133 or above and previous versions.
284
+ * @param parser GLTFParser
285
+ * @param material A material of gltf
286
+ * @returns Material definition index of glTF
287
+ */
288
+ function gltfGetAssociatedMaterialIndex(parser, material) {
289
+ var _a, _b;
290
+ const threeRevision = parseInt(THREE__namespace.REVISION, 10);
291
+ let index = null;
292
+ if (threeRevision >= 133) {
293
+ index = (_b = (_a = parser.associations.get(material)) === null || _a === void 0 ? void 0 : _a.materials) !== null && _b !== void 0 ? _b : null;
294
+ }
295
+ else {
296
+ const associations = parser.associations;
297
+ const reference = associations.get(material);
298
+ if ((reference === null || reference === void 0 ? void 0 : reference.type) === 'materials') {
299
+ index = reference.index;
300
+ }
301
+ }
302
+ return index;
303
303
  }
304
304
 
305
- /* eslint-disable @typescript-eslint/naming-convention */
306
- const VRMExpressionPresetName = {
307
- Aa: 'aa',
308
- Ih: 'ih',
309
- Ou: 'ou',
310
- Ee: 'ee',
311
- Oh: 'oh',
312
- Blink: 'blink',
313
- Happy: 'happy',
314
- Angry: 'angry',
315
- Sad: 'sad',
316
- Relaxed: 'relaxed',
317
- LookUp: 'lookUp',
318
- Surprised: 'surprised',
319
- LookDown: 'lookDown',
320
- LookLeft: 'lookLeft',
321
- LookRight: 'lookRight',
322
- BlinkLeft: 'blinkLeft',
323
- BlinkRight: 'blinkRight',
324
- Neutral: 'neutral',
305
+ /* eslint-disable @typescript-eslint/naming-convention */
306
+ const VRMExpressionPresetName = {
307
+ Aa: 'aa',
308
+ Ih: 'ih',
309
+ Ou: 'ou',
310
+ Ee: 'ee',
311
+ Oh: 'oh',
312
+ Blink: 'blink',
313
+ Happy: 'happy',
314
+ Angry: 'angry',
315
+ Sad: 'sad',
316
+ Relaxed: 'relaxed',
317
+ LookUp: 'lookUp',
318
+ Surprised: 'surprised',
319
+ LookDown: 'lookDown',
320
+ LookLeft: 'lookLeft',
321
+ LookRight: 'lookRight',
322
+ BlinkLeft: 'blinkLeft',
323
+ BlinkRight: 'blinkRight',
324
+ Neutral: 'neutral',
325
325
  };
326
326
 
327
- /**
328
- * Clamp the input value within [0.0 - 1.0].
329
- *
330
- * @param value The input value
331
- */
332
- function saturate(value) {
333
- return Math.max(Math.min(value, 1.0), 0.0);
327
+ /**
328
+ * Clamp the input value within [0.0 - 1.0].
329
+ *
330
+ * @param value The input value
331
+ */
332
+ function saturate(value) {
333
+ return Math.max(Math.min(value, 1.0), 0.0);
334
334
  }
335
335
 
336
- class VRMExpressionManager {
337
- /**
338
- * Create a new {@link VRMExpressionManager}.
339
- */
340
- constructor() {
341
- /**
342
- * A set of name or preset name of expressions that will be overridden by {@link VRMExpression.overrideBlink}.
343
- */
344
- this.blinkExpressionNames = ['blink', 'blinkLeft', 'blinkRight'];
345
- /**
346
- * A set of name or preset name of expressions that will be overridden by {@link VRMExpression.overrideLookAt}.
347
- */
348
- this.lookAtExpressionNames = ['lookLeft', 'lookRight', 'lookUp', 'lookDown'];
349
- /**
350
- * A set of name or preset name of expressions that will be overridden by {@link VRMExpression.overrideMouth}.
351
- */
352
- this.mouthExpressionNames = ['aa', 'ee', 'ih', 'oh', 'ou'];
353
- /**
354
- * A set of {@link VRMExpression}.
355
- * When you want to register expressions, use {@link registerExpression}
356
- */
357
- this._expressions = [];
358
- /**
359
- * A map from name to expression.
360
- */
361
- this._expressionMap = {};
362
- // do nothing
363
- }
364
- get expressions() {
365
- return this._expressions.concat();
366
- }
367
- get expressionMap() {
368
- return Object.assign({}, this._expressionMap);
369
- }
370
- /**
371
- * A map from name to expression, but excluding custom expressions.
372
- */
373
- get presetExpressionMap() {
374
- const result = {};
375
- const presetNameSet = new Set(Object.values(VRMExpressionPresetName));
376
- Object.entries(this._expressionMap).forEach(([name, expression]) => {
377
- if (presetNameSet.has(name)) {
378
- result[name] = expression;
379
- }
380
- });
381
- return result;
382
- }
383
- /**
384
- * A map from name to expression, but excluding preset expressions.
385
- */
386
- get customExpressionMap() {
387
- const result = {};
388
- const presetNameSet = new Set(Object.values(VRMExpressionPresetName));
389
- Object.entries(this._expressionMap).forEach(([name, expression]) => {
390
- if (!presetNameSet.has(name)) {
391
- result[name] = expression;
392
- }
393
- });
394
- return result;
395
- }
396
- /**
397
- * Copy the given {@link VRMExpressionManager} into this one.
398
- * @param source The {@link VRMExpressionManager} you want to copy
399
- * @returns this
400
- */
401
- copy(source) {
402
- // first unregister all the expression it has
403
- const expressions = this._expressions.concat();
404
- expressions.forEach((expression) => {
405
- this.unregisterExpression(expression);
406
- });
407
- // then register all the expression of the source
408
- source._expressions.forEach((expression) => {
409
- this.registerExpression(expression);
410
- });
411
- // copy remaining members
412
- this.blinkExpressionNames = source.blinkExpressionNames.concat();
413
- this.lookAtExpressionNames = source.lookAtExpressionNames.concat();
414
- this.mouthExpressionNames = source.mouthExpressionNames.concat();
415
- return this;
416
- }
417
- /**
418
- * Returns a clone of this {@link VRMExpressionManager}.
419
- * @returns Copied {@link VRMExpressionManager}
420
- */
421
- clone() {
422
- return new VRMExpressionManager().copy(this);
423
- }
424
- /**
425
- * Return a registered expression.
426
- * If it cannot find an expression, it will return `null` instead.
427
- *
428
- * @param name Name or preset name of the expression
429
- */
430
- getExpression(name) {
431
- var _a;
432
- return (_a = this._expressionMap[name]) !== null && _a !== void 0 ? _a : null;
433
- }
434
- /**
435
- * Register an expression.
436
- *
437
- * @param expression {@link VRMExpression} that describes the expression
438
- */
439
- registerExpression(expression) {
440
- this._expressions.push(expression);
441
- this._expressionMap[expression.expressionName] = expression;
442
- }
443
- /**
444
- * Unregister an expression.
445
- *
446
- * @param expression The expression you want to unregister
447
- */
448
- unregisterExpression(expression) {
449
- const index = this._expressions.indexOf(expression);
450
- if (index === -1) {
451
- console.warn('VRMExpressionManager: The specified expressions is not registered');
452
- }
453
- this._expressions.splice(index, 1);
454
- delete this._expressionMap[expression.expressionName];
455
- }
456
- /**
457
- * Get the current weight of the specified expression.
458
- * If it doesn't have an expression of given name, it will return `null` instead.
459
- *
460
- * @param name Name of the expression
461
- */
462
- getValue(name) {
463
- var _a;
464
- const expression = this.getExpression(name);
465
- return (_a = expression === null || expression === void 0 ? void 0 : expression.weight) !== null && _a !== void 0 ? _a : null;
466
- }
467
- /**
468
- * Set a weight to the specified expression.
469
- *
470
- * @param name Name of the expression
471
- * @param weight Weight
472
- */
473
- setValue(name, weight) {
474
- const expression = this.getExpression(name);
475
- if (expression) {
476
- expression.weight = saturate(weight);
477
- }
478
- }
479
- /**
480
- * Get a track name of specified expression.
481
- * This track name is needed to manipulate its expression via keyframe animations.
482
- *
483
- * @example Manipulate an expression using keyframe animation
484
- * ```js
485
- * const trackName = vrm.expressionManager.getExpressionTrackName( 'blink' );
486
- * const track = new THREE.NumberKeyframeTrack(
487
- * name,
488
- * [ 0.0, 0.5, 1.0 ], // times
489
- * [ 0.0, 1.0, 0.0 ] // values
490
- * );
491
- *
492
- * const clip = new THREE.AnimationClip(
493
- * 'blink', // name
494
- * 1.0, // duration
495
- * [ track ] // tracks
496
- * );
497
- *
498
- * const mixer = new THREE.AnimationMixer( vrm.scene );
499
- * const action = mixer.clipAction( clip );
500
- * action.play();
501
- * ```
502
- *
503
- * @param name Name of the expression
504
- */
505
- getExpressionTrackName(name) {
506
- const expression = this.getExpression(name);
507
- return expression ? `${expression.name}.weight` : null;
508
- }
509
- /**
510
- * Update every expressions.
511
- */
512
- update() {
513
- // see how much we should override certain expressions
514
- const weightMultipliers = this._calculateWeightMultipliers();
515
- // reset expression binds first
516
- this._expressions.forEach((expression) => {
517
- expression.clearAppliedWeight();
518
- });
519
- // then apply binds
520
- this._expressions.forEach((expression) => {
521
- let multiplier = 1.0;
522
- const name = expression.expressionName;
523
- if (this.blinkExpressionNames.indexOf(name) !== -1) {
524
- multiplier *= weightMultipliers.blink;
525
- }
526
- if (this.lookAtExpressionNames.indexOf(name) !== -1) {
527
- multiplier *= weightMultipliers.lookAt;
528
- }
529
- if (this.mouthExpressionNames.indexOf(name) !== -1) {
530
- multiplier *= weightMultipliers.mouth;
531
- }
532
- expression.applyWeight({ multiplier });
533
- });
534
- }
535
- /**
536
- * Calculate sum of override amounts to see how much we should multiply weights of certain expressions.
537
- */
538
- _calculateWeightMultipliers() {
539
- let blink = 1.0;
540
- let lookAt = 1.0;
541
- let mouth = 1.0;
542
- this._expressions.forEach((expression) => {
543
- blink -= expression.overrideBlinkAmount;
544
- lookAt -= expression.overrideLookAtAmount;
545
- mouth -= expression.overrideMouthAmount;
546
- });
547
- blink = Math.max(0.0, blink);
548
- lookAt = Math.max(0.0, lookAt);
549
- mouth = Math.max(0.0, mouth);
550
- return { blink, lookAt, mouth };
551
- }
336
+ class VRMExpressionManager {
337
+ /**
338
+ * Create a new {@link VRMExpressionManager}.
339
+ */
340
+ constructor() {
341
+ /**
342
+ * A set of name or preset name of expressions that will be overridden by {@link VRMExpression.overrideBlink}.
343
+ */
344
+ this.blinkExpressionNames = ['blink', 'blinkLeft', 'blinkRight'];
345
+ /**
346
+ * A set of name or preset name of expressions that will be overridden by {@link VRMExpression.overrideLookAt}.
347
+ */
348
+ this.lookAtExpressionNames = ['lookLeft', 'lookRight', 'lookUp', 'lookDown'];
349
+ /**
350
+ * A set of name or preset name of expressions that will be overridden by {@link VRMExpression.overrideMouth}.
351
+ */
352
+ this.mouthExpressionNames = ['aa', 'ee', 'ih', 'oh', 'ou'];
353
+ /**
354
+ * A set of {@link VRMExpression}.
355
+ * When you want to register expressions, use {@link registerExpression}
356
+ */
357
+ this._expressions = [];
358
+ /**
359
+ * A map from name to expression.
360
+ */
361
+ this._expressionMap = {};
362
+ // do nothing
363
+ }
364
+ get expressions() {
365
+ return this._expressions.concat();
366
+ }
367
+ get expressionMap() {
368
+ return Object.assign({}, this._expressionMap);
369
+ }
370
+ /**
371
+ * A map from name to expression, but excluding custom expressions.
372
+ */
373
+ get presetExpressionMap() {
374
+ const result = {};
375
+ const presetNameSet = new Set(Object.values(VRMExpressionPresetName));
376
+ Object.entries(this._expressionMap).forEach(([name, expression]) => {
377
+ if (presetNameSet.has(name)) {
378
+ result[name] = expression;
379
+ }
380
+ });
381
+ return result;
382
+ }
383
+ /**
384
+ * A map from name to expression, but excluding preset expressions.
385
+ */
386
+ get customExpressionMap() {
387
+ const result = {};
388
+ const presetNameSet = new Set(Object.values(VRMExpressionPresetName));
389
+ Object.entries(this._expressionMap).forEach(([name, expression]) => {
390
+ if (!presetNameSet.has(name)) {
391
+ result[name] = expression;
392
+ }
393
+ });
394
+ return result;
395
+ }
396
+ /**
397
+ * Copy the given {@link VRMExpressionManager} into this one.
398
+ * @param source The {@link VRMExpressionManager} you want to copy
399
+ * @returns this
400
+ */
401
+ copy(source) {
402
+ // first unregister all the expression it has
403
+ const expressions = this._expressions.concat();
404
+ expressions.forEach((expression) => {
405
+ this.unregisterExpression(expression);
406
+ });
407
+ // then register all the expression of the source
408
+ source._expressions.forEach((expression) => {
409
+ this.registerExpression(expression);
410
+ });
411
+ // copy remaining members
412
+ this.blinkExpressionNames = source.blinkExpressionNames.concat();
413
+ this.lookAtExpressionNames = source.lookAtExpressionNames.concat();
414
+ this.mouthExpressionNames = source.mouthExpressionNames.concat();
415
+ return this;
416
+ }
417
+ /**
418
+ * Returns a clone of this {@link VRMExpressionManager}.
419
+ * @returns Copied {@link VRMExpressionManager}
420
+ */
421
+ clone() {
422
+ return new VRMExpressionManager().copy(this);
423
+ }
424
+ /**
425
+ * Return a registered expression.
426
+ * If it cannot find an expression, it will return `null` instead.
427
+ *
428
+ * @param name Name or preset name of the expression
429
+ */
430
+ getExpression(name) {
431
+ var _a;
432
+ return (_a = this._expressionMap[name]) !== null && _a !== void 0 ? _a : null;
433
+ }
434
+ /**
435
+ * Register an expression.
436
+ *
437
+ * @param expression {@link VRMExpression} that describes the expression
438
+ */
439
+ registerExpression(expression) {
440
+ this._expressions.push(expression);
441
+ this._expressionMap[expression.expressionName] = expression;
442
+ }
443
+ /**
444
+ * Unregister an expression.
445
+ *
446
+ * @param expression The expression you want to unregister
447
+ */
448
+ unregisterExpression(expression) {
449
+ const index = this._expressions.indexOf(expression);
450
+ if (index === -1) {
451
+ console.warn('VRMExpressionManager: The specified expressions is not registered');
452
+ }
453
+ this._expressions.splice(index, 1);
454
+ delete this._expressionMap[expression.expressionName];
455
+ }
456
+ /**
457
+ * Get the current weight of the specified expression.
458
+ * If it doesn't have an expression of given name, it will return `null` instead.
459
+ *
460
+ * @param name Name of the expression
461
+ */
462
+ getValue(name) {
463
+ var _a;
464
+ const expression = this.getExpression(name);
465
+ return (_a = expression === null || expression === void 0 ? void 0 : expression.weight) !== null && _a !== void 0 ? _a : null;
466
+ }
467
+ /**
468
+ * Set a weight to the specified expression.
469
+ *
470
+ * @param name Name of the expression
471
+ * @param weight Weight
472
+ */
473
+ setValue(name, weight) {
474
+ const expression = this.getExpression(name);
475
+ if (expression) {
476
+ expression.weight = saturate(weight);
477
+ }
478
+ }
479
+ /**
480
+ * Get a track name of specified expression.
481
+ * This track name is needed to manipulate its expression via keyframe animations.
482
+ *
483
+ * @example Manipulate an expression using keyframe animation
484
+ * ```js
485
+ * const trackName = vrm.expressionManager.getExpressionTrackName( 'blink' );
486
+ * const track = new THREE.NumberKeyframeTrack(
487
+ * name,
488
+ * [ 0.0, 0.5, 1.0 ], // times
489
+ * [ 0.0, 1.0, 0.0 ] // values
490
+ * );
491
+ *
492
+ * const clip = new THREE.AnimationClip(
493
+ * 'blink', // name
494
+ * 1.0, // duration
495
+ * [ track ] // tracks
496
+ * );
497
+ *
498
+ * const mixer = new THREE.AnimationMixer( vrm.scene );
499
+ * const action = mixer.clipAction( clip );
500
+ * action.play();
501
+ * ```
502
+ *
503
+ * @param name Name of the expression
504
+ */
505
+ getExpressionTrackName(name) {
506
+ const expression = this.getExpression(name);
507
+ return expression ? `${expression.name}.weight` : null;
508
+ }
509
+ /**
510
+ * Update every expressions.
511
+ */
512
+ update() {
513
+ // see how much we should override certain expressions
514
+ const weightMultipliers = this._calculateWeightMultipliers();
515
+ // reset expression binds first
516
+ this._expressions.forEach((expression) => {
517
+ expression.clearAppliedWeight();
518
+ });
519
+ // then apply binds
520
+ this._expressions.forEach((expression) => {
521
+ let multiplier = 1.0;
522
+ const name = expression.expressionName;
523
+ if (this.blinkExpressionNames.indexOf(name) !== -1) {
524
+ multiplier *= weightMultipliers.blink;
525
+ }
526
+ if (this.lookAtExpressionNames.indexOf(name) !== -1) {
527
+ multiplier *= weightMultipliers.lookAt;
528
+ }
529
+ if (this.mouthExpressionNames.indexOf(name) !== -1) {
530
+ multiplier *= weightMultipliers.mouth;
531
+ }
532
+ expression.applyWeight({ multiplier });
533
+ });
534
+ }
535
+ /**
536
+ * Calculate sum of override amounts to see how much we should multiply weights of certain expressions.
537
+ */
538
+ _calculateWeightMultipliers() {
539
+ let blink = 1.0;
540
+ let lookAt = 1.0;
541
+ let mouth = 1.0;
542
+ this._expressions.forEach((expression) => {
543
+ blink -= expression.overrideBlinkAmount;
544
+ lookAt -= expression.overrideLookAtAmount;
545
+ mouth -= expression.overrideMouthAmount;
546
+ });
547
+ blink = Math.max(0.0, blink);
548
+ lookAt = Math.max(0.0, lookAt);
549
+ mouth = Math.max(0.0, mouth);
550
+ return { blink, lookAt, mouth };
551
+ }
552
552
  }
553
553
 
554
- const _color = new THREE__namespace.Color();
555
- /**
556
- * A bind of expression influences to a material color.
557
- */
558
- class VRMExpressionMaterialColorBind {
559
- constructor({ material, type, targetValue, }) {
560
- var _a, _b, _c;
561
- this.material = material;
562
- this.type = type;
563
- this.targetValue = targetValue;
564
- // init property name
565
- const propertyNameMap = (_a = Object.entries(VRMExpressionMaterialColorBind._propertyNameMapMap).find(([distinguisher]) => {
566
- return material[distinguisher] === true;
567
- })) === null || _a === void 0 ? void 0 : _a[1];
568
- const propertyName = (_b = propertyNameMap === null || propertyNameMap === void 0 ? void 0 : propertyNameMap[type]) !== null && _b !== void 0 ? _b : null;
569
- if (propertyName == null) {
570
- console.warn(`Tried to add a material color bind to the material ${(_c = material.name) !== null && _c !== void 0 ? _c : '(no name)'}, the type ${type} but the material or the type is not supported.`);
571
- this._state = null;
572
- }
573
- else {
574
- const target = material[propertyName];
575
- const initialValue = target.clone();
576
- const deltaValue = this.targetValue.clone().sub(initialValue);
577
- this._state = {
578
- propertyName,
579
- initialValue,
580
- deltaValue,
581
- };
582
- }
583
- }
584
- applyWeight(weight) {
585
- if (this._state == null) {
586
- // warning is already emitted in constructor
587
- return;
588
- }
589
- const { propertyName, deltaValue } = this._state;
590
- const target = this.material[propertyName];
591
- if (target === undefined) {
592
- return;
593
- } // TODO: we should kick this at `addMaterialValue`
594
- target.add(_color.copy(deltaValue).multiplyScalar(weight));
595
- if (typeof this.material.shouldApplyUniforms === 'boolean') {
596
- this.material.shouldApplyUniforms = true;
597
- }
598
- }
599
- clearAppliedWeight() {
600
- if (this._state == null) {
601
- // warning is already emitted in constructor
602
- return;
603
- }
604
- const { propertyName, initialValue } = this._state;
605
- const target = this.material[propertyName];
606
- if (target === undefined) {
607
- return;
608
- } // TODO: we should kick this at `addMaterialValue`
609
- target.copy(initialValue);
610
- if (typeof this.material.shouldApplyUniforms === 'boolean') {
611
- this.material.shouldApplyUniforms = true;
612
- }
613
- }
614
- }
615
- VRMExpressionMaterialColorBind._propertyNameMapMap = {
616
- isMeshStandardMaterial: {
617
- color: 'color',
618
- emissionColor: 'emissive',
619
- },
620
- isMeshBasicMaterial: {
621
- color: 'color',
622
- },
623
- isMToonMaterial: {
624
- color: 'color',
625
- emissionColor: 'emissive',
626
- outlineColor: 'outlineFactor',
627
- rimColor: 'rimFactor',
628
- shadeColor: 'shadeFactor',
629
- },
554
+ const _color = new THREE__namespace.Color();
555
+ /**
556
+ * A bind of expression influences to a material color.
557
+ */
558
+ class VRMExpressionMaterialColorBind {
559
+ constructor({ material, type, targetValue, }) {
560
+ var _a, _b, _c;
561
+ this.material = material;
562
+ this.type = type;
563
+ this.targetValue = targetValue;
564
+ // init property name
565
+ const propertyNameMap = (_a = Object.entries(VRMExpressionMaterialColorBind._propertyNameMapMap).find(([distinguisher]) => {
566
+ return material[distinguisher] === true;
567
+ })) === null || _a === void 0 ? void 0 : _a[1];
568
+ const propertyName = (_b = propertyNameMap === null || propertyNameMap === void 0 ? void 0 : propertyNameMap[type]) !== null && _b !== void 0 ? _b : null;
569
+ if (propertyName == null) {
570
+ console.warn(`Tried to add a material color bind to the material ${(_c = material.name) !== null && _c !== void 0 ? _c : '(no name)'}, the type ${type} but the material or the type is not supported.`);
571
+ this._state = null;
572
+ }
573
+ else {
574
+ const target = material[propertyName];
575
+ const initialValue = target.clone();
576
+ const deltaValue = this.targetValue.clone().sub(initialValue);
577
+ this._state = {
578
+ propertyName,
579
+ initialValue,
580
+ deltaValue,
581
+ };
582
+ }
583
+ }
584
+ applyWeight(weight) {
585
+ if (this._state == null) {
586
+ // warning is already emitted in constructor
587
+ return;
588
+ }
589
+ const { propertyName, deltaValue } = this._state;
590
+ const target = this.material[propertyName];
591
+ if (target === undefined) {
592
+ return;
593
+ } // TODO: we should kick this at `addMaterialValue`
594
+ target.add(_color.copy(deltaValue).multiplyScalar(weight));
595
+ if (typeof this.material.shouldApplyUniforms === 'boolean') {
596
+ this.material.shouldApplyUniforms = true;
597
+ }
598
+ }
599
+ clearAppliedWeight() {
600
+ if (this._state == null) {
601
+ // warning is already emitted in constructor
602
+ return;
603
+ }
604
+ const { propertyName, initialValue } = this._state;
605
+ const target = this.material[propertyName];
606
+ if (target === undefined) {
607
+ return;
608
+ } // TODO: we should kick this at `addMaterialValue`
609
+ target.copy(initialValue);
610
+ if (typeof this.material.shouldApplyUniforms === 'boolean') {
611
+ this.material.shouldApplyUniforms = true;
612
+ }
613
+ }
614
+ }
615
+ VRMExpressionMaterialColorBind._propertyNameMapMap = {
616
+ isMeshStandardMaterial: {
617
+ color: 'color',
618
+ emissionColor: 'emissive',
619
+ },
620
+ isMeshBasicMaterial: {
621
+ color: 'color',
622
+ },
623
+ isMToonMaterial: {
624
+ color: 'color',
625
+ emissionColor: 'emissive',
626
+ outlineColor: 'outlineFactor',
627
+ rimColor: 'rimFactor',
628
+ shadeColor: 'shadeFactor',
629
+ },
630
630
  };
631
631
 
632
- /**
633
- * A bind of {@link VRMExpression} influences to morph targets.
634
- */
635
- class VRMExpressionMorphTargetBind {
636
- constructor({ primitives, index, weight, }) {
637
- this.primitives = primitives;
638
- this.index = index;
639
- this.weight = weight;
640
- }
641
- applyWeight(weight) {
642
- this.primitives.forEach((mesh) => {
643
- var _a;
644
- if (((_a = mesh.morphTargetInfluences) === null || _a === void 0 ? void 0 : _a[this.index]) != null) {
645
- mesh.morphTargetInfluences[this.index] += this.weight * weight;
646
- }
647
- });
648
- }
649
- clearAppliedWeight() {
650
- this.primitives.forEach((mesh) => {
651
- var _a;
652
- if (((_a = mesh.morphTargetInfluences) === null || _a === void 0 ? void 0 : _a[this.index]) != null) {
653
- mesh.morphTargetInfluences[this.index] = 0.0;
654
- }
655
- });
656
- }
632
+ /**
633
+ * A bind of {@link VRMExpression} influences to morph targets.
634
+ */
635
+ class VRMExpressionMorphTargetBind {
636
+ constructor({ primitives, index, weight, }) {
637
+ this.primitives = primitives;
638
+ this.index = index;
639
+ this.weight = weight;
640
+ }
641
+ applyWeight(weight) {
642
+ this.primitives.forEach((mesh) => {
643
+ var _a;
644
+ if (((_a = mesh.morphTargetInfluences) === null || _a === void 0 ? void 0 : _a[this.index]) != null) {
645
+ mesh.morphTargetInfluences[this.index] += this.weight * weight;
646
+ }
647
+ });
648
+ }
649
+ clearAppliedWeight() {
650
+ this.primitives.forEach((mesh) => {
651
+ var _a;
652
+ if (((_a = mesh.morphTargetInfluences) === null || _a === void 0 ? void 0 : _a[this.index]) != null) {
653
+ mesh.morphTargetInfluences[this.index] = 0.0;
654
+ }
655
+ });
656
+ }
657
657
  }
658
658
 
659
- const _v2 = new THREE__namespace.Vector2();
660
- /**
661
- * A bind of expression influences to texture transforms.
662
- */
663
- class VRMExpressionTextureTransformBind {
664
- constructor({ material, scale, offset, }) {
665
- var _a, _b;
666
- this.material = material;
667
- this.scale = scale;
668
- this.offset = offset;
669
- const propertyNames = (_a = Object.entries(VRMExpressionTextureTransformBind._propertyNamesMap).find(([distinguisher]) => {
670
- return material[distinguisher] === true;
671
- })) === null || _a === void 0 ? void 0 : _a[1];
672
- if (propertyNames == null) {
673
- console.warn(`Tried to add a texture transform bind to the material ${(_b = material.name) !== null && _b !== void 0 ? _b : '(no name)'} but the material is not supported.`);
674
- this._properties = [];
675
- }
676
- else {
677
- this._properties = [];
678
- propertyNames.forEach((propertyName) => {
679
- var _a;
680
- const texture = (_a = material[propertyName]) === null || _a === void 0 ? void 0 : _a.clone();
681
- if (!texture) {
682
- return null;
683
- }
684
- material[propertyName] = texture; // because the texture is cloned
685
- const initialOffset = texture.offset.clone();
686
- const initialScale = texture.repeat.clone();
687
- const deltaOffset = offset.clone().sub(initialOffset);
688
- const deltaScale = scale.clone().sub(initialScale);
689
- this._properties.push({
690
- name: propertyName,
691
- initialOffset,
692
- deltaOffset,
693
- initialScale,
694
- deltaScale,
695
- });
696
- });
697
- }
698
- }
699
- applyWeight(weight) {
700
- this._properties.forEach((property) => {
701
- const target = this.material[property.name];
702
- if (target === undefined) {
703
- return;
704
- } // TODO: we should kick this at `addMaterialValue`
705
- target.offset.add(_v2.copy(property.deltaOffset).multiplyScalar(weight));
706
- target.repeat.add(_v2.copy(property.deltaScale).multiplyScalar(weight));
707
- target.needsUpdate = true;
708
- });
709
- }
710
- clearAppliedWeight() {
711
- this._properties.forEach((property) => {
712
- const target = this.material[property.name];
713
- if (target === undefined) {
714
- return;
715
- } // TODO: we should kick this at `addMaterialValue`
716
- target.offset.copy(property.initialOffset);
717
- target.repeat.copy(property.initialScale);
718
- target.needsUpdate = true;
719
- });
720
- }
721
- }
722
- VRMExpressionTextureTransformBind._propertyNamesMap = {
723
- isMeshStandardMaterial: [
724
- 'map',
725
- 'emissiveMap',
726
- 'bumpMap',
727
- 'normalMap',
728
- 'displacementMap',
729
- 'roughnessMap',
730
- 'metalnessMap',
731
- 'alphaMap',
732
- ],
733
- isMeshBasicMaterial: ['map', 'specularMap', 'alphaMap'],
734
- isMToonMaterial: [
735
- 'map',
736
- 'normalMap',
737
- 'emissiveMap',
738
- 'shadeMultiplyTexture',
739
- 'rimMultiplyTexture',
740
- 'outlineWidthMultiplyTexture',
741
- 'uvAnimationMaskTexture',
742
- ],
659
+ const _v2 = new THREE__namespace.Vector2();
660
+ /**
661
+ * A bind of expression influences to texture transforms.
662
+ */
663
+ class VRMExpressionTextureTransformBind {
664
+ constructor({ material, scale, offset, }) {
665
+ var _a, _b;
666
+ this.material = material;
667
+ this.scale = scale;
668
+ this.offset = offset;
669
+ const propertyNames = (_a = Object.entries(VRMExpressionTextureTransformBind._propertyNamesMap).find(([distinguisher]) => {
670
+ return material[distinguisher] === true;
671
+ })) === null || _a === void 0 ? void 0 : _a[1];
672
+ if (propertyNames == null) {
673
+ console.warn(`Tried to add a texture transform bind to the material ${(_b = material.name) !== null && _b !== void 0 ? _b : '(no name)'} but the material is not supported.`);
674
+ this._properties = [];
675
+ }
676
+ else {
677
+ this._properties = [];
678
+ propertyNames.forEach((propertyName) => {
679
+ var _a;
680
+ const texture = (_a = material[propertyName]) === null || _a === void 0 ? void 0 : _a.clone();
681
+ if (!texture) {
682
+ return null;
683
+ }
684
+ material[propertyName] = texture; // because the texture is cloned
685
+ const initialOffset = texture.offset.clone();
686
+ const initialScale = texture.repeat.clone();
687
+ const deltaOffset = offset.clone().sub(initialOffset);
688
+ const deltaScale = scale.clone().sub(initialScale);
689
+ this._properties.push({
690
+ name: propertyName,
691
+ initialOffset,
692
+ deltaOffset,
693
+ initialScale,
694
+ deltaScale,
695
+ });
696
+ });
697
+ }
698
+ }
699
+ applyWeight(weight) {
700
+ this._properties.forEach((property) => {
701
+ const target = this.material[property.name];
702
+ if (target === undefined) {
703
+ return;
704
+ } // TODO: we should kick this at `addMaterialValue`
705
+ target.offset.add(_v2.copy(property.deltaOffset).multiplyScalar(weight));
706
+ target.repeat.add(_v2.copy(property.deltaScale).multiplyScalar(weight));
707
+ target.needsUpdate = true;
708
+ });
709
+ }
710
+ clearAppliedWeight() {
711
+ this._properties.forEach((property) => {
712
+ const target = this.material[property.name];
713
+ if (target === undefined) {
714
+ return;
715
+ } // TODO: we should kick this at `addMaterialValue`
716
+ target.offset.copy(property.initialOffset);
717
+ target.repeat.copy(property.initialScale);
718
+ target.needsUpdate = true;
719
+ });
720
+ }
721
+ }
722
+ VRMExpressionTextureTransformBind._propertyNamesMap = {
723
+ isMeshStandardMaterial: [
724
+ 'map',
725
+ 'emissiveMap',
726
+ 'bumpMap',
727
+ 'normalMap',
728
+ 'displacementMap',
729
+ 'roughnessMap',
730
+ 'metalnessMap',
731
+ 'alphaMap',
732
+ ],
733
+ isMeshBasicMaterial: ['map', 'specularMap', 'alphaMap'],
734
+ isMToonMaterial: [
735
+ 'map',
736
+ 'normalMap',
737
+ 'emissiveMap',
738
+ 'shadeMultiplyTexture',
739
+ 'rimMultiplyTexture',
740
+ 'outlineWidthMultiplyTexture',
741
+ 'uvAnimationMaskTexture',
742
+ ],
743
743
  };
744
744
 
745
- /**
746
- * A plugin of GLTFLoader that imports a {@link VRMExpressionManager} from a VRM extension of a GLTF.
747
- */
748
- class VRMExpressionLoaderPlugin {
749
- constructor(parser) {
750
- this.parser = parser;
751
- }
752
- get name() {
753
- // We should use the extension name instead but we have multiple plugins for an extension...
754
- return 'VRMExpressionLoaderPlugin';
755
- }
756
- afterRoot(gltf) {
757
- return __awaiter(this, void 0, void 0, function* () {
758
- gltf.userData.vrmExpressionManager = yield this._import(gltf);
759
- });
760
- }
761
- /**
762
- * Import a {@link VRMExpressionManager} from a VRM.
763
- *
764
- * @param gltf A parsed result of GLTF taken from GLTFLoader
765
- */
766
- _import(gltf) {
767
- return __awaiter(this, void 0, void 0, function* () {
768
- const v1Result = yield this._v1Import(gltf);
769
- if (v1Result) {
770
- return v1Result;
771
- }
772
- const v0Result = yield this._v0Import(gltf);
773
- if (v0Result) {
774
- return v0Result;
775
- }
776
- return null;
777
- });
778
- }
779
- _v1Import(gltf) {
780
- var _a, _b;
781
- return __awaiter(this, void 0, void 0, function* () {
782
- const json = this.parser.json;
783
- // early abort if it doesn't use vrm
784
- const isVRMUsed = ((_a = json.extensionsUsed) === null || _a === void 0 ? void 0 : _a.indexOf('VRMC_vrm')) !== -1;
785
- if (!isVRMUsed) {
786
- return null;
787
- }
788
- const extension = (_b = json.extensions) === null || _b === void 0 ? void 0 : _b['VRMC_vrm'];
789
- if (!extension) {
790
- return null;
791
- }
792
- const specVersion = extension.specVersion;
793
- if (specVersion !== '1.0-beta') {
794
- return null;
795
- }
796
- const schemaExpressions = extension.expressions;
797
- if (!schemaExpressions) {
798
- return null;
799
- }
800
- // list expressions
801
- const presetNameSet = new Set(Object.values(VRMExpressionPresetName));
802
- const nameSchemaExpressionMap = new Map();
803
- if (schemaExpressions.preset != null) {
804
- Object.entries(schemaExpressions.preset).forEach(([name, schemaExpression]) => {
805
- if (schemaExpression == null) {
806
- return;
807
- } // typescript
808
- if (!presetNameSet.has(name)) {
809
- console.warn(`VRMExpressionLoaderPlugin: Unknown preset name "${name}" detected. Ignoring the expression`);
810
- return;
811
- }
812
- nameSchemaExpressionMap.set(name, schemaExpression);
813
- });
814
- }
815
- if (schemaExpressions.custom != null) {
816
- Object.entries(schemaExpressions.custom).forEach(([name, schemaExpression]) => {
817
- if (presetNameSet.has(name)) {
818
- console.warn(`VRMExpressionLoaderPlugin: Custom expression cannot have preset name "${name}". Ignoring the expression`);
819
- return;
820
- }
821
- nameSchemaExpressionMap.set(name, schemaExpression);
822
- });
823
- }
824
- // prepare manager
825
- const manager = new VRMExpressionManager();
826
- // load expressions
827
- yield Promise.all(Array.from(nameSchemaExpressionMap.entries()).map(([name, schemaExpression]) => __awaiter(this, void 0, void 0, function* () {
828
- var _c, _d, _e, _f, _g, _h, _j;
829
- const expression = new VRMExpression(name);
830
- gltf.scene.add(expression);
831
- expression.isBinary = (_c = schemaExpression.isBinary) !== null && _c !== void 0 ? _c : false;
832
- expression.overrideBlink = (_d = schemaExpression.overrideBlink) !== null && _d !== void 0 ? _d : 'none';
833
- expression.overrideLookAt = (_e = schemaExpression.overrideLookAt) !== null && _e !== void 0 ? _e : 'none';
834
- expression.overrideMouth = (_f = schemaExpression.overrideMouth) !== null && _f !== void 0 ? _f : 'none';
835
- (_g = schemaExpression.morphTargetBinds) === null || _g === void 0 ? void 0 : _g.forEach((bind) => __awaiter(this, void 0, void 0, function* () {
836
- var _k;
837
- if (bind.node === undefined || bind.index === undefined) {
838
- return;
839
- }
840
- const primitives = (yield gltfExtractPrimitivesFromNode(gltf, bind.node));
841
- const morphTargetIndex = bind.index;
842
- // check if the mesh has the target morph target
843
- if (!primitives.every((primitive) => Array.isArray(primitive.morphTargetInfluences) &&
844
- morphTargetIndex < primitive.morphTargetInfluences.length)) {
845
- console.warn(`VRMExpressionLoaderPlugin: ${schemaExpression.name} attempts to index morph #${morphTargetIndex} but not found.`);
846
- return;
847
- }
848
- expression.addBind(new VRMExpressionMorphTargetBind({
849
- primitives,
850
- index: morphTargetIndex,
851
- weight: (_k = bind.weight) !== null && _k !== void 0 ? _k : 1.0,
852
- }));
853
- }));
854
- if (schemaExpression.materialColorBinds || schemaExpression.textureTransformBinds) {
855
- // list up every material in `gltf.scene`
856
- const gltfMaterials = [];
857
- gltf.scene.traverse((object) => {
858
- const material = object.material;
859
- if (material) {
860
- gltfMaterials.push(material);
861
- }
862
- });
863
- (_h = schemaExpression.materialColorBinds) === null || _h === void 0 ? void 0 : _h.forEach((bind) => __awaiter(this, void 0, void 0, function* () {
864
- const materials = gltfMaterials.filter((material) => {
865
- const materialIndex = gltfGetAssociatedMaterialIndex(this.parser, material);
866
- return bind.material === materialIndex;
867
- });
868
- materials.forEach((material) => {
869
- expression.addBind(new VRMExpressionMaterialColorBind({
870
- material,
871
- type: bind.type,
872
- targetValue: new THREE__namespace.Color().fromArray(bind.targetValue),
873
- }));
874
- });
875
- }));
876
- (_j = schemaExpression.textureTransformBinds) === null || _j === void 0 ? void 0 : _j.forEach((bind) => __awaiter(this, void 0, void 0, function* () {
877
- const materials = gltfMaterials.filter((material) => {
878
- const materialIndex = gltfGetAssociatedMaterialIndex(this.parser, material);
879
- return bind.material === materialIndex;
880
- });
881
- materials.forEach((material) => {
882
- var _a, _b;
883
- expression.addBind(new VRMExpressionTextureTransformBind({
884
- material,
885
- offset: new THREE__namespace.Vector2().fromArray((_a = bind.offset) !== null && _a !== void 0 ? _a : [0.0, 0.0]),
886
- scale: new THREE__namespace.Vector2().fromArray((_b = bind.scale) !== null && _b !== void 0 ? _b : [1.0, 1.0]),
887
- }));
888
- });
889
- }));
890
- }
891
- manager.registerExpression(expression);
892
- })));
893
- return manager;
894
- });
895
- }
896
- _v0Import(gltf) {
897
- var _a;
898
- return __awaiter(this, void 0, void 0, function* () {
899
- const json = this.parser.json;
900
- // early abort if it doesn't use vrm
901
- const vrmExt = (_a = json.extensions) === null || _a === void 0 ? void 0 : _a.VRM;
902
- if (!vrmExt) {
903
- return null;
904
- }
905
- const schemaBlendShape = vrmExt.blendShapeMaster;
906
- if (!schemaBlendShape) {
907
- return null;
908
- }
909
- const manager = new VRMExpressionManager();
910
- const schemaBlendShapeGroups = schemaBlendShape.blendShapeGroups;
911
- if (!schemaBlendShapeGroups) {
912
- return manager;
913
- }
914
- const blendShapeNameSet = new Set();
915
- yield Promise.all(schemaBlendShapeGroups.map((schemaGroup) => __awaiter(this, void 0, void 0, function* () {
916
- var _b;
917
- const v0PresetName = schemaGroup.presetName;
918
- const v1PresetName = (v0PresetName != null && VRMExpressionLoaderPlugin.v0v1PresetNameMap[v0PresetName]) || null;
919
- const name = v1PresetName !== null && v1PresetName !== void 0 ? v1PresetName : schemaGroup.name;
920
- if (name == null) {
921
- console.warn('VRMExpressionLoaderPlugin: One of custom expressions has no name. Ignoring the expression');
922
- return;
923
- }
924
- // duplication check
925
- if (blendShapeNameSet.has(name)) {
926
- console.warn(`VRMExpressionLoaderPlugin: An expression preset ${v0PresetName} has duplicated entries. Ignoring the expression`);
927
- return;
928
- }
929
- blendShapeNameSet.add(name);
930
- const expression = new VRMExpression(name);
931
- gltf.scene.add(expression);
932
- expression.isBinary = (_b = schemaGroup.isBinary) !== null && _b !== void 0 ? _b : false;
933
- // v0 doesn't have ignore properties
934
- if (schemaGroup.binds) {
935
- schemaGroup.binds.forEach((bind) => __awaiter(this, void 0, void 0, function* () {
936
- var _c;
937
- if (bind.mesh === undefined || bind.index === undefined) {
938
- return;
939
- }
940
- const nodesUsingMesh = [];
941
- (_c = json.nodes) === null || _c === void 0 ? void 0 : _c.forEach((node, i) => {
942
- if (node.mesh === bind.mesh) {
943
- nodesUsingMesh.push(i);
944
- }
945
- });
946
- const morphTargetIndex = bind.index;
947
- yield Promise.all(nodesUsingMesh.map((nodeIndex) => __awaiter(this, void 0, void 0, function* () {
948
- var _d;
949
- const primitives = (yield gltfExtractPrimitivesFromNode(gltf, nodeIndex));
950
- // check if the mesh has the target morph target
951
- if (!primitives.every((primitive) => Array.isArray(primitive.morphTargetInfluences) &&
952
- morphTargetIndex < primitive.morphTargetInfluences.length)) {
953
- console.warn(`VRMExpressionLoaderPlugin: ${schemaGroup.name} attempts to index ${morphTargetIndex}th morph but not found.`);
954
- return;
955
- }
956
- expression.addBind(new VRMExpressionMorphTargetBind({
957
- primitives,
958
- index: morphTargetIndex,
959
- weight: 0.01 * ((_d = bind.weight) !== null && _d !== void 0 ? _d : 100),
960
- }));
961
- })));
962
- }));
963
- }
964
- const materialValues = schemaGroup.materialValues;
965
- if (materialValues && materialValues.length !== 0) {
966
- console.warn('Material binds of VRM 0.0 are not supported. Setup the model in VRM 1.0 and try again');
967
- }
968
- manager.registerExpression(expression);
969
- })));
970
- return manager;
971
- });
972
- }
973
- }
974
- VRMExpressionLoaderPlugin.v0v1PresetNameMap = {
975
- a: 'aa',
976
- e: 'ee',
977
- i: 'ih',
978
- o: 'oh',
979
- u: 'ou',
980
- blink: 'blink',
981
- joy: 'happy',
982
- angry: 'angry',
983
- sorrow: 'sad',
984
- fun: 'relaxed',
985
- lookup: 'lookUp',
986
- lookdown: 'lookDown',
987
- lookleft: 'lookLeft',
988
- lookright: 'lookRight',
989
- // eslint-disable-next-line @typescript-eslint/naming-convention
990
- blink_l: 'blinkLeft',
991
- // eslint-disable-next-line @typescript-eslint/naming-convention
992
- blink_r: 'blinkRight',
993
- neutral: 'neutral',
745
+ /**
746
+ * A plugin of GLTFLoader that imports a {@link VRMExpressionManager} from a VRM extension of a GLTF.
747
+ */
748
+ class VRMExpressionLoaderPlugin {
749
+ constructor(parser) {
750
+ this.parser = parser;
751
+ }
752
+ get name() {
753
+ // We should use the extension name instead but we have multiple plugins for an extension...
754
+ return 'VRMExpressionLoaderPlugin';
755
+ }
756
+ afterRoot(gltf) {
757
+ return __awaiter(this, void 0, void 0, function* () {
758
+ gltf.userData.vrmExpressionManager = yield this._import(gltf);
759
+ });
760
+ }
761
+ /**
762
+ * Import a {@link VRMExpressionManager} from a VRM.
763
+ *
764
+ * @param gltf A parsed result of GLTF taken from GLTFLoader
765
+ */
766
+ _import(gltf) {
767
+ return __awaiter(this, void 0, void 0, function* () {
768
+ const v1Result = yield this._v1Import(gltf);
769
+ if (v1Result) {
770
+ return v1Result;
771
+ }
772
+ const v0Result = yield this._v0Import(gltf);
773
+ if (v0Result) {
774
+ return v0Result;
775
+ }
776
+ return null;
777
+ });
778
+ }
779
+ _v1Import(gltf) {
780
+ var _a, _b;
781
+ return __awaiter(this, void 0, void 0, function* () {
782
+ const json = this.parser.json;
783
+ // early abort if it doesn't use vrm
784
+ const isVRMUsed = ((_a = json.extensionsUsed) === null || _a === void 0 ? void 0 : _a.indexOf('VRMC_vrm')) !== -1;
785
+ if (!isVRMUsed) {
786
+ return null;
787
+ }
788
+ const extension = (_b = json.extensions) === null || _b === void 0 ? void 0 : _b['VRMC_vrm'];
789
+ if (!extension) {
790
+ return null;
791
+ }
792
+ const specVersion = extension.specVersion;
793
+ if (specVersion !== '1.0-beta') {
794
+ return null;
795
+ }
796
+ const schemaExpressions = extension.expressions;
797
+ if (!schemaExpressions) {
798
+ return null;
799
+ }
800
+ // list expressions
801
+ const presetNameSet = new Set(Object.values(VRMExpressionPresetName));
802
+ const nameSchemaExpressionMap = new Map();
803
+ if (schemaExpressions.preset != null) {
804
+ Object.entries(schemaExpressions.preset).forEach(([name, schemaExpression]) => {
805
+ if (schemaExpression == null) {
806
+ return;
807
+ } // typescript
808
+ if (!presetNameSet.has(name)) {
809
+ console.warn(`VRMExpressionLoaderPlugin: Unknown preset name "${name}" detected. Ignoring the expression`);
810
+ return;
811
+ }
812
+ nameSchemaExpressionMap.set(name, schemaExpression);
813
+ });
814
+ }
815
+ if (schemaExpressions.custom != null) {
816
+ Object.entries(schemaExpressions.custom).forEach(([name, schemaExpression]) => {
817
+ if (presetNameSet.has(name)) {
818
+ console.warn(`VRMExpressionLoaderPlugin: Custom expression cannot have preset name "${name}". Ignoring the expression`);
819
+ return;
820
+ }
821
+ nameSchemaExpressionMap.set(name, schemaExpression);
822
+ });
823
+ }
824
+ // prepare manager
825
+ const manager = new VRMExpressionManager();
826
+ // load expressions
827
+ yield Promise.all(Array.from(nameSchemaExpressionMap.entries()).map(([name, schemaExpression]) => __awaiter(this, void 0, void 0, function* () {
828
+ var _c, _d, _e, _f, _g, _h, _j;
829
+ const expression = new VRMExpression(name);
830
+ gltf.scene.add(expression);
831
+ expression.isBinary = (_c = schemaExpression.isBinary) !== null && _c !== void 0 ? _c : false;
832
+ expression.overrideBlink = (_d = schemaExpression.overrideBlink) !== null && _d !== void 0 ? _d : 'none';
833
+ expression.overrideLookAt = (_e = schemaExpression.overrideLookAt) !== null && _e !== void 0 ? _e : 'none';
834
+ expression.overrideMouth = (_f = schemaExpression.overrideMouth) !== null && _f !== void 0 ? _f : 'none';
835
+ (_g = schemaExpression.morphTargetBinds) === null || _g === void 0 ? void 0 : _g.forEach((bind) => __awaiter(this, void 0, void 0, function* () {
836
+ var _k;
837
+ if (bind.node === undefined || bind.index === undefined) {
838
+ return;
839
+ }
840
+ const primitives = (yield gltfExtractPrimitivesFromNode(gltf, bind.node));
841
+ const morphTargetIndex = bind.index;
842
+ // check if the mesh has the target morph target
843
+ if (!primitives.every((primitive) => Array.isArray(primitive.morphTargetInfluences) &&
844
+ morphTargetIndex < primitive.morphTargetInfluences.length)) {
845
+ console.warn(`VRMExpressionLoaderPlugin: ${schemaExpression.name} attempts to index morph #${morphTargetIndex} but not found.`);
846
+ return;
847
+ }
848
+ expression.addBind(new VRMExpressionMorphTargetBind({
849
+ primitives,
850
+ index: morphTargetIndex,
851
+ weight: (_k = bind.weight) !== null && _k !== void 0 ? _k : 1.0,
852
+ }));
853
+ }));
854
+ if (schemaExpression.materialColorBinds || schemaExpression.textureTransformBinds) {
855
+ // list up every material in `gltf.scene`
856
+ const gltfMaterials = [];
857
+ gltf.scene.traverse((object) => {
858
+ const material = object.material;
859
+ if (material) {
860
+ gltfMaterials.push(material);
861
+ }
862
+ });
863
+ (_h = schemaExpression.materialColorBinds) === null || _h === void 0 ? void 0 : _h.forEach((bind) => __awaiter(this, void 0, void 0, function* () {
864
+ const materials = gltfMaterials.filter((material) => {
865
+ const materialIndex = gltfGetAssociatedMaterialIndex(this.parser, material);
866
+ return bind.material === materialIndex;
867
+ });
868
+ materials.forEach((material) => {
869
+ expression.addBind(new VRMExpressionMaterialColorBind({
870
+ material,
871
+ type: bind.type,
872
+ targetValue: new THREE__namespace.Color().fromArray(bind.targetValue),
873
+ }));
874
+ });
875
+ }));
876
+ (_j = schemaExpression.textureTransformBinds) === null || _j === void 0 ? void 0 : _j.forEach((bind) => __awaiter(this, void 0, void 0, function* () {
877
+ const materials = gltfMaterials.filter((material) => {
878
+ const materialIndex = gltfGetAssociatedMaterialIndex(this.parser, material);
879
+ return bind.material === materialIndex;
880
+ });
881
+ materials.forEach((material) => {
882
+ var _a, _b;
883
+ expression.addBind(new VRMExpressionTextureTransformBind({
884
+ material,
885
+ offset: new THREE__namespace.Vector2().fromArray((_a = bind.offset) !== null && _a !== void 0 ? _a : [0.0, 0.0]),
886
+ scale: new THREE__namespace.Vector2().fromArray((_b = bind.scale) !== null && _b !== void 0 ? _b : [1.0, 1.0]),
887
+ }));
888
+ });
889
+ }));
890
+ }
891
+ manager.registerExpression(expression);
892
+ })));
893
+ return manager;
894
+ });
895
+ }
896
+ _v0Import(gltf) {
897
+ var _a;
898
+ return __awaiter(this, void 0, void 0, function* () {
899
+ const json = this.parser.json;
900
+ // early abort if it doesn't use vrm
901
+ const vrmExt = (_a = json.extensions) === null || _a === void 0 ? void 0 : _a.VRM;
902
+ if (!vrmExt) {
903
+ return null;
904
+ }
905
+ const schemaBlendShape = vrmExt.blendShapeMaster;
906
+ if (!schemaBlendShape) {
907
+ return null;
908
+ }
909
+ const manager = new VRMExpressionManager();
910
+ const schemaBlendShapeGroups = schemaBlendShape.blendShapeGroups;
911
+ if (!schemaBlendShapeGroups) {
912
+ return manager;
913
+ }
914
+ const blendShapeNameSet = new Set();
915
+ yield Promise.all(schemaBlendShapeGroups.map((schemaGroup) => __awaiter(this, void 0, void 0, function* () {
916
+ var _b;
917
+ const v0PresetName = schemaGroup.presetName;
918
+ const v1PresetName = (v0PresetName != null && VRMExpressionLoaderPlugin.v0v1PresetNameMap[v0PresetName]) || null;
919
+ const name = v1PresetName !== null && v1PresetName !== void 0 ? v1PresetName : schemaGroup.name;
920
+ if (name == null) {
921
+ console.warn('VRMExpressionLoaderPlugin: One of custom expressions has no name. Ignoring the expression');
922
+ return;
923
+ }
924
+ // duplication check
925
+ if (blendShapeNameSet.has(name)) {
926
+ console.warn(`VRMExpressionLoaderPlugin: An expression preset ${v0PresetName} has duplicated entries. Ignoring the expression`);
927
+ return;
928
+ }
929
+ blendShapeNameSet.add(name);
930
+ const expression = new VRMExpression(name);
931
+ gltf.scene.add(expression);
932
+ expression.isBinary = (_b = schemaGroup.isBinary) !== null && _b !== void 0 ? _b : false;
933
+ // v0 doesn't have ignore properties
934
+ if (schemaGroup.binds) {
935
+ schemaGroup.binds.forEach((bind) => __awaiter(this, void 0, void 0, function* () {
936
+ var _c;
937
+ if (bind.mesh === undefined || bind.index === undefined) {
938
+ return;
939
+ }
940
+ const nodesUsingMesh = [];
941
+ (_c = json.nodes) === null || _c === void 0 ? void 0 : _c.forEach((node, i) => {
942
+ if (node.mesh === bind.mesh) {
943
+ nodesUsingMesh.push(i);
944
+ }
945
+ });
946
+ const morphTargetIndex = bind.index;
947
+ yield Promise.all(nodesUsingMesh.map((nodeIndex) => __awaiter(this, void 0, void 0, function* () {
948
+ var _d;
949
+ const primitives = (yield gltfExtractPrimitivesFromNode(gltf, nodeIndex));
950
+ // check if the mesh has the target morph target
951
+ if (!primitives.every((primitive) => Array.isArray(primitive.morphTargetInfluences) &&
952
+ morphTargetIndex < primitive.morphTargetInfluences.length)) {
953
+ console.warn(`VRMExpressionLoaderPlugin: ${schemaGroup.name} attempts to index ${morphTargetIndex}th morph but not found.`);
954
+ return;
955
+ }
956
+ expression.addBind(new VRMExpressionMorphTargetBind({
957
+ primitives,
958
+ index: morphTargetIndex,
959
+ weight: 0.01 * ((_d = bind.weight) !== null && _d !== void 0 ? _d : 100),
960
+ }));
961
+ })));
962
+ }));
963
+ }
964
+ const materialValues = schemaGroup.materialValues;
965
+ if (materialValues && materialValues.length !== 0) {
966
+ console.warn('Material binds of VRM 0.0 are not supported. Setup the model in VRM 1.0 and try again');
967
+ }
968
+ manager.registerExpression(expression);
969
+ })));
970
+ return manager;
971
+ });
972
+ }
973
+ }
974
+ VRMExpressionLoaderPlugin.v0v1PresetNameMap = {
975
+ a: 'aa',
976
+ e: 'ee',
977
+ i: 'ih',
978
+ o: 'oh',
979
+ u: 'ou',
980
+ blink: 'blink',
981
+ joy: 'happy',
982
+ angry: 'angry',
983
+ sorrow: 'sad',
984
+ fun: 'relaxed',
985
+ lookup: 'lookUp',
986
+ lookdown: 'lookDown',
987
+ lookleft: 'lookLeft',
988
+ lookright: 'lookRight',
989
+ // eslint-disable-next-line @typescript-eslint/naming-convention
990
+ blink_l: 'blinkLeft',
991
+ // eslint-disable-next-line @typescript-eslint/naming-convention
992
+ blink_r: 'blinkRight',
993
+ neutral: 'neutral',
994
994
  };
995
995
 
996
- /* eslint-disable @typescript-eslint/naming-convention */
997
- const VRMExpressionMaterialColorType = {
998
- Color: 'color',
999
- EmissionColor: 'emissionColor',
1000
- ShadeColor: 'shadeColor',
1001
- RimColor: 'rimColor',
1002
- OutlineColor: 'outlineColor',
996
+ /* eslint-disable @typescript-eslint/naming-convention */
997
+ const VRMExpressionMaterialColorType = {
998
+ Color: 'color',
999
+ EmissionColor: 'emissionColor',
1000
+ ShadeColor: 'shadeColor',
1001
+ RimColor: 'rimColor',
1002
+ OutlineColor: 'outlineColor',
1003
1003
  };
1004
1004
 
1005
- /* eslint-disable @typescript-eslint/naming-convention */
1006
- const VRMExpressionOverrideType = {
1007
- None: 'none',
1008
- Block: 'block',
1009
- Blend: 'blend',
1005
+ /* eslint-disable @typescript-eslint/naming-convention */
1006
+ const VRMExpressionOverrideType = {
1007
+ None: 'none',
1008
+ Block: 'block',
1009
+ Blend: 'blend',
1010
1010
  };
1011
1011
 
1012
- class VRMFirstPerson {
1013
- /**
1014
- * Create a new VRMFirstPerson object.
1015
- *
1016
- * @param humanoid A {@link VRMHumanoid}
1017
- * @param meshAnnotations A renderer settings. See the description of [[RendererFirstPersonFlags]] for more info
1018
- */
1019
- constructor(humanoid, meshAnnotations) {
1020
- this._firstPersonOnlyLayer = VRMFirstPerson.DEFAULT_FIRSTPERSON_ONLY_LAYER;
1021
- this._thirdPersonOnlyLayer = VRMFirstPerson.DEFAULT_THIRDPERSON_ONLY_LAYER;
1022
- this._initializedLayers = false;
1023
- this.humanoid = humanoid;
1024
- this.meshAnnotations = meshAnnotations;
1025
- }
1026
- /**
1027
- * Copy the given {@link VRMFirstPerson} into this one.
1028
- * {@link humanoid} must be same as the source one.
1029
- * @param source The {@link VRMFirstPerson} you want to copy
1030
- * @returns this
1031
- */
1032
- copy(source) {
1033
- if (this.humanoid !== source.humanoid) {
1034
- throw new Error('VRMFirstPerson: humanoid must be same in order to copy');
1035
- }
1036
- this.meshAnnotations = source.meshAnnotations.map((annotation) => ({
1037
- meshes: annotation.meshes.concat(),
1038
- type: annotation.type,
1039
- }));
1040
- return this;
1041
- }
1042
- /**
1043
- * Returns a clone of this {@link VRMFirstPerson}.
1044
- * @returns Copied {@link VRMFirstPerson}
1045
- */
1046
- clone() {
1047
- return new VRMFirstPerson(this.humanoid, this.meshAnnotations).copy(this);
1048
- }
1049
- /**
1050
- * A camera layer represents `FirstPersonOnly` layer.
1051
- * Note that **you must call {@link setup} first before you use the layer feature** or it does not work properly.
1052
- *
1053
- * The value is {@link DEFAULT_FIRSTPERSON_ONLY_LAYER} by default but you can change the layer by specifying via {@link setup} if you prefer.
1054
- *
1055
- * @see https://vrm.dev/en/univrm/api/univrm_use_firstperson/
1056
- * @see https://threejs.org/docs/#api/en/core/Layers
1057
- */
1058
- get firstPersonOnlyLayer() {
1059
- return this._firstPersonOnlyLayer;
1060
- }
1061
- /**
1062
- * A camera layer represents `ThirdPersonOnly` layer.
1063
- * Note that **you must call {@link setup} first before you use the layer feature** or it does not work properly.
1064
- *
1065
- * The value is {@link DEFAULT_THIRDPERSON_ONLY_LAYER} by default but you can change the layer by specifying via {@link setup} if you prefer.
1066
- *
1067
- * @see https://vrm.dev/en/univrm/api/univrm_use_firstperson/
1068
- * @see https://threejs.org/docs/#api/en/core/Layers
1069
- */
1070
- get thirdPersonOnlyLayer() {
1071
- return this._thirdPersonOnlyLayer;
1072
- }
1073
- /**
1074
- * In this method, it assigns layers for every meshes based on mesh annotations.
1075
- * You must call this method first before you use the layer feature.
1076
- *
1077
- * This is an equivalent of [VRMFirstPerson.Setup](https://github.com/vrm-c/UniVRM/blob/73a5bd8fcddaa2a7a8735099a97e63c9db3e5ea0/Assets/VRM/Runtime/FirstPerson/VRMFirstPerson.cs#L295-L299) of the UniVRM.
1078
- *
1079
- * The `cameraLayer` parameter specifies which layer will be assigned for `FirstPersonOnly` / `ThirdPersonOnly`.
1080
- * In UniVRM, we specified those by naming each desired layer as `FIRSTPERSON_ONLY_LAYER` / `THIRDPERSON_ONLY_LAYER`
1081
- * but we are going to specify these layers at here since we are unable to name layers in Three.js.
1082
- *
1083
- * @param cameraLayer Specify which layer will be for `FirstPersonOnly` / `ThirdPersonOnly`.
1084
- */
1085
- setup({ firstPersonOnlyLayer = VRMFirstPerson.DEFAULT_FIRSTPERSON_ONLY_LAYER, thirdPersonOnlyLayer = VRMFirstPerson.DEFAULT_THIRDPERSON_ONLY_LAYER, } = {}) {
1086
- if (this._initializedLayers) {
1087
- return;
1088
- }
1089
- this._firstPersonOnlyLayer = firstPersonOnlyLayer;
1090
- this._thirdPersonOnlyLayer = thirdPersonOnlyLayer;
1091
- this.meshAnnotations.forEach((item) => {
1092
- item.meshes.forEach((mesh) => {
1093
- if (item.type === 'firstPersonOnly') {
1094
- mesh.layers.set(this._firstPersonOnlyLayer);
1095
- mesh.traverse((child) => child.layers.set(this._firstPersonOnlyLayer));
1096
- }
1097
- else if (item.type === 'thirdPersonOnly') {
1098
- mesh.layers.set(this._thirdPersonOnlyLayer);
1099
- mesh.traverse((child) => child.layers.set(this._thirdPersonOnlyLayer));
1100
- }
1101
- else if (item.type === 'auto') {
1102
- this._createHeadlessModel(mesh);
1103
- }
1104
- });
1105
- });
1106
- this._initializedLayers = true;
1107
- }
1108
- _excludeTriangles(triangles, bws, skinIndex, exclude) {
1109
- let count = 0;
1110
- if (bws != null && bws.length > 0) {
1111
- for (let i = 0; i < triangles.length; i += 3) {
1112
- const a = triangles[i];
1113
- const b = triangles[i + 1];
1114
- const c = triangles[i + 2];
1115
- const bw0 = bws[a];
1116
- const skin0 = skinIndex[a];
1117
- if (bw0[0] > 0 && exclude.includes(skin0[0]))
1118
- continue;
1119
- if (bw0[1] > 0 && exclude.includes(skin0[1]))
1120
- continue;
1121
- if (bw0[2] > 0 && exclude.includes(skin0[2]))
1122
- continue;
1123
- if (bw0[3] > 0 && exclude.includes(skin0[3]))
1124
- continue;
1125
- const bw1 = bws[b];
1126
- const skin1 = skinIndex[b];
1127
- if (bw1[0] > 0 && exclude.includes(skin1[0]))
1128
- continue;
1129
- if (bw1[1] > 0 && exclude.includes(skin1[1]))
1130
- continue;
1131
- if (bw1[2] > 0 && exclude.includes(skin1[2]))
1132
- continue;
1133
- if (bw1[3] > 0 && exclude.includes(skin1[3]))
1134
- continue;
1135
- const bw2 = bws[c];
1136
- const skin2 = skinIndex[c];
1137
- if (bw2[0] > 0 && exclude.includes(skin2[0]))
1138
- continue;
1139
- if (bw2[1] > 0 && exclude.includes(skin2[1]))
1140
- continue;
1141
- if (bw2[2] > 0 && exclude.includes(skin2[2]))
1142
- continue;
1143
- if (bw2[3] > 0 && exclude.includes(skin2[3]))
1144
- continue;
1145
- triangles[count++] = a;
1146
- triangles[count++] = b;
1147
- triangles[count++] = c;
1148
- }
1149
- }
1150
- return count;
1151
- }
1152
- _createErasedMesh(src, erasingBonesIndex) {
1153
- const dst = new THREE__namespace.SkinnedMesh(src.geometry.clone(), src.material);
1154
- dst.name = `${src.name}(erase)`;
1155
- dst.frustumCulled = src.frustumCulled;
1156
- dst.layers.set(this._firstPersonOnlyLayer);
1157
- const geometry = dst.geometry;
1158
- const skinIndexAttr = geometry.getAttribute('skinIndex').array;
1159
- const skinIndex = [];
1160
- for (let i = 0; i < skinIndexAttr.length; i += 4) {
1161
- skinIndex.push([skinIndexAttr[i], skinIndexAttr[i + 1], skinIndexAttr[i + 2], skinIndexAttr[i + 3]]);
1162
- }
1163
- const skinWeightAttr = geometry.getAttribute('skinWeight').array;
1164
- const skinWeight = [];
1165
- for (let i = 0; i < skinWeightAttr.length; i += 4) {
1166
- skinWeight.push([skinWeightAttr[i], skinWeightAttr[i + 1], skinWeightAttr[i + 2], skinWeightAttr[i + 3]]);
1167
- }
1168
- const index = geometry.getIndex();
1169
- if (!index) {
1170
- throw new Error("The geometry doesn't have an index buffer");
1171
- }
1172
- const oldTriangles = Array.from(index.array);
1173
- const count = this._excludeTriangles(oldTriangles, skinWeight, skinIndex, erasingBonesIndex);
1174
- const newTriangle = [];
1175
- for (let i = 0; i < count; i++) {
1176
- newTriangle[i] = oldTriangles[i];
1177
- }
1178
- geometry.setIndex(newTriangle);
1179
- // mtoon material includes onBeforeRender. this is unsupported at SkinnedMesh#clone
1180
- if (src.onBeforeRender) {
1181
- dst.onBeforeRender = src.onBeforeRender;
1182
- }
1183
- dst.bind(new THREE__namespace.Skeleton(src.skeleton.bones, src.skeleton.boneInverses), new THREE__namespace.Matrix4());
1184
- return dst;
1185
- }
1186
- _createHeadlessModelForSkinnedMesh(parent, mesh) {
1187
- const eraseBoneIndexes = [];
1188
- mesh.skeleton.bones.forEach((bone, index) => {
1189
- if (this._isEraseTarget(bone))
1190
- eraseBoneIndexes.push(index);
1191
- });
1192
- // Unlike UniVRM we don't copy mesh if no invisible bone was found
1193
- if (!eraseBoneIndexes.length) {
1194
- mesh.layers.enable(this._thirdPersonOnlyLayer);
1195
- mesh.layers.enable(this._firstPersonOnlyLayer);
1196
- return;
1197
- }
1198
- mesh.layers.set(this._thirdPersonOnlyLayer);
1199
- const newMesh = this._createErasedMesh(mesh, eraseBoneIndexes);
1200
- parent.add(newMesh);
1201
- }
1202
- _createHeadlessModel(node) {
1203
- if (node.type === 'Group') {
1204
- node.layers.set(this._thirdPersonOnlyLayer);
1205
- if (this._isEraseTarget(node)) {
1206
- node.traverse((child) => child.layers.set(this._thirdPersonOnlyLayer));
1207
- }
1208
- else {
1209
- const parent = new THREE__namespace.Group();
1210
- parent.name = `_headless_${node.name}`;
1211
- parent.layers.set(this._firstPersonOnlyLayer);
1212
- node.parent.add(parent);
1213
- node.children
1214
- .filter((child) => child.type === 'SkinnedMesh')
1215
- .forEach((child) => {
1216
- const skinnedMesh = child;
1217
- this._createHeadlessModelForSkinnedMesh(parent, skinnedMesh);
1218
- });
1219
- }
1220
- }
1221
- else if (node.type === 'SkinnedMesh') {
1222
- const skinnedMesh = node;
1223
- this._createHeadlessModelForSkinnedMesh(node.parent, skinnedMesh);
1224
- }
1225
- else {
1226
- if (this._isEraseTarget(node)) {
1227
- node.layers.set(this._thirdPersonOnlyLayer);
1228
- node.traverse((child) => child.layers.set(this._thirdPersonOnlyLayer));
1229
- }
1230
- }
1231
- }
1232
- _isEraseTarget(bone) {
1233
- if (bone === this.humanoid.getBoneNode('head')) {
1234
- return true;
1235
- }
1236
- else if (!bone.parent) {
1237
- return false;
1238
- }
1239
- else {
1240
- return this._isEraseTarget(bone.parent);
1241
- }
1242
- }
1243
- }
1244
- /**
1245
- * A default camera layer for `FirstPersonOnly` layer.
1246
- *
1247
- * @see [[getFirstPersonOnlyLayer]]
1248
- */
1249
- VRMFirstPerson.DEFAULT_FIRSTPERSON_ONLY_LAYER = 9;
1250
- /**
1251
- * A default camera layer for `ThirdPersonOnly` layer.
1252
- *
1253
- * @see [[getThirdPersonOnlyLayer]]
1254
- */
1012
+ class VRMFirstPerson {
1013
+ /**
1014
+ * Create a new VRMFirstPerson object.
1015
+ *
1016
+ * @param humanoid A {@link VRMHumanoid}
1017
+ * @param meshAnnotations A renderer settings. See the description of [[RendererFirstPersonFlags]] for more info
1018
+ */
1019
+ constructor(humanoid, meshAnnotations) {
1020
+ this._firstPersonOnlyLayer = VRMFirstPerson.DEFAULT_FIRSTPERSON_ONLY_LAYER;
1021
+ this._thirdPersonOnlyLayer = VRMFirstPerson.DEFAULT_THIRDPERSON_ONLY_LAYER;
1022
+ this._initializedLayers = false;
1023
+ this.humanoid = humanoid;
1024
+ this.meshAnnotations = meshAnnotations;
1025
+ }
1026
+ /**
1027
+ * Copy the given {@link VRMFirstPerson} into this one.
1028
+ * {@link humanoid} must be same as the source one.
1029
+ * @param source The {@link VRMFirstPerson} you want to copy
1030
+ * @returns this
1031
+ */
1032
+ copy(source) {
1033
+ if (this.humanoid !== source.humanoid) {
1034
+ throw new Error('VRMFirstPerson: humanoid must be same in order to copy');
1035
+ }
1036
+ this.meshAnnotations = source.meshAnnotations.map((annotation) => ({
1037
+ meshes: annotation.meshes.concat(),
1038
+ type: annotation.type,
1039
+ }));
1040
+ return this;
1041
+ }
1042
+ /**
1043
+ * Returns a clone of this {@link VRMFirstPerson}.
1044
+ * @returns Copied {@link VRMFirstPerson}
1045
+ */
1046
+ clone() {
1047
+ return new VRMFirstPerson(this.humanoid, this.meshAnnotations).copy(this);
1048
+ }
1049
+ /**
1050
+ * A camera layer represents `FirstPersonOnly` layer.
1051
+ * Note that **you must call {@link setup} first before you use the layer feature** or it does not work properly.
1052
+ *
1053
+ * The value is {@link DEFAULT_FIRSTPERSON_ONLY_LAYER} by default but you can change the layer by specifying via {@link setup} if you prefer.
1054
+ *
1055
+ * @see https://vrm.dev/en/univrm/api/univrm_use_firstperson/
1056
+ * @see https://threejs.org/docs/#api/en/core/Layers
1057
+ */
1058
+ get firstPersonOnlyLayer() {
1059
+ return this._firstPersonOnlyLayer;
1060
+ }
1061
+ /**
1062
+ * A camera layer represents `ThirdPersonOnly` layer.
1063
+ * Note that **you must call {@link setup} first before you use the layer feature** or it does not work properly.
1064
+ *
1065
+ * The value is {@link DEFAULT_THIRDPERSON_ONLY_LAYER} by default but you can change the layer by specifying via {@link setup} if you prefer.
1066
+ *
1067
+ * @see https://vrm.dev/en/univrm/api/univrm_use_firstperson/
1068
+ * @see https://threejs.org/docs/#api/en/core/Layers
1069
+ */
1070
+ get thirdPersonOnlyLayer() {
1071
+ return this._thirdPersonOnlyLayer;
1072
+ }
1073
+ /**
1074
+ * In this method, it assigns layers for every meshes based on mesh annotations.
1075
+ * You must call this method first before you use the layer feature.
1076
+ *
1077
+ * This is an equivalent of [VRMFirstPerson.Setup](https://github.com/vrm-c/UniVRM/blob/73a5bd8fcddaa2a7a8735099a97e63c9db3e5ea0/Assets/VRM/Runtime/FirstPerson/VRMFirstPerson.cs#L295-L299) of the UniVRM.
1078
+ *
1079
+ * The `cameraLayer` parameter specifies which layer will be assigned for `FirstPersonOnly` / `ThirdPersonOnly`.
1080
+ * In UniVRM, we specified those by naming each desired layer as `FIRSTPERSON_ONLY_LAYER` / `THIRDPERSON_ONLY_LAYER`
1081
+ * but we are going to specify these layers at here since we are unable to name layers in Three.js.
1082
+ *
1083
+ * @param cameraLayer Specify which layer will be for `FirstPersonOnly` / `ThirdPersonOnly`.
1084
+ */
1085
+ setup({ firstPersonOnlyLayer = VRMFirstPerson.DEFAULT_FIRSTPERSON_ONLY_LAYER, thirdPersonOnlyLayer = VRMFirstPerson.DEFAULT_THIRDPERSON_ONLY_LAYER, } = {}) {
1086
+ if (this._initializedLayers) {
1087
+ return;
1088
+ }
1089
+ this._firstPersonOnlyLayer = firstPersonOnlyLayer;
1090
+ this._thirdPersonOnlyLayer = thirdPersonOnlyLayer;
1091
+ this.meshAnnotations.forEach((item) => {
1092
+ item.meshes.forEach((mesh) => {
1093
+ if (item.type === 'firstPersonOnly') {
1094
+ mesh.layers.set(this._firstPersonOnlyLayer);
1095
+ mesh.traverse((child) => child.layers.set(this._firstPersonOnlyLayer));
1096
+ }
1097
+ else if (item.type === 'thirdPersonOnly') {
1098
+ mesh.layers.set(this._thirdPersonOnlyLayer);
1099
+ mesh.traverse((child) => child.layers.set(this._thirdPersonOnlyLayer));
1100
+ }
1101
+ else if (item.type === 'auto') {
1102
+ this._createHeadlessModel(mesh);
1103
+ }
1104
+ });
1105
+ });
1106
+ this._initializedLayers = true;
1107
+ }
1108
+ _excludeTriangles(triangles, bws, skinIndex, exclude) {
1109
+ let count = 0;
1110
+ if (bws != null && bws.length > 0) {
1111
+ for (let i = 0; i < triangles.length; i += 3) {
1112
+ const a = triangles[i];
1113
+ const b = triangles[i + 1];
1114
+ const c = triangles[i + 2];
1115
+ const bw0 = bws[a];
1116
+ const skin0 = skinIndex[a];
1117
+ if (bw0[0] > 0 && exclude.includes(skin0[0]))
1118
+ continue;
1119
+ if (bw0[1] > 0 && exclude.includes(skin0[1]))
1120
+ continue;
1121
+ if (bw0[2] > 0 && exclude.includes(skin0[2]))
1122
+ continue;
1123
+ if (bw0[3] > 0 && exclude.includes(skin0[3]))
1124
+ continue;
1125
+ const bw1 = bws[b];
1126
+ const skin1 = skinIndex[b];
1127
+ if (bw1[0] > 0 && exclude.includes(skin1[0]))
1128
+ continue;
1129
+ if (bw1[1] > 0 && exclude.includes(skin1[1]))
1130
+ continue;
1131
+ if (bw1[2] > 0 && exclude.includes(skin1[2]))
1132
+ continue;
1133
+ if (bw1[3] > 0 && exclude.includes(skin1[3]))
1134
+ continue;
1135
+ const bw2 = bws[c];
1136
+ const skin2 = skinIndex[c];
1137
+ if (bw2[0] > 0 && exclude.includes(skin2[0]))
1138
+ continue;
1139
+ if (bw2[1] > 0 && exclude.includes(skin2[1]))
1140
+ continue;
1141
+ if (bw2[2] > 0 && exclude.includes(skin2[2]))
1142
+ continue;
1143
+ if (bw2[3] > 0 && exclude.includes(skin2[3]))
1144
+ continue;
1145
+ triangles[count++] = a;
1146
+ triangles[count++] = b;
1147
+ triangles[count++] = c;
1148
+ }
1149
+ }
1150
+ return count;
1151
+ }
1152
+ _createErasedMesh(src, erasingBonesIndex) {
1153
+ const dst = new THREE__namespace.SkinnedMesh(src.geometry.clone(), src.material);
1154
+ dst.name = `${src.name}(erase)`;
1155
+ dst.frustumCulled = src.frustumCulled;
1156
+ dst.layers.set(this._firstPersonOnlyLayer);
1157
+ const geometry = dst.geometry;
1158
+ const skinIndexAttr = geometry.getAttribute('skinIndex').array;
1159
+ const skinIndex = [];
1160
+ for (let i = 0; i < skinIndexAttr.length; i += 4) {
1161
+ skinIndex.push([skinIndexAttr[i], skinIndexAttr[i + 1], skinIndexAttr[i + 2], skinIndexAttr[i + 3]]);
1162
+ }
1163
+ const skinWeightAttr = geometry.getAttribute('skinWeight').array;
1164
+ const skinWeight = [];
1165
+ for (let i = 0; i < skinWeightAttr.length; i += 4) {
1166
+ skinWeight.push([skinWeightAttr[i], skinWeightAttr[i + 1], skinWeightAttr[i + 2], skinWeightAttr[i + 3]]);
1167
+ }
1168
+ const index = geometry.getIndex();
1169
+ if (!index) {
1170
+ throw new Error("The geometry doesn't have an index buffer");
1171
+ }
1172
+ const oldTriangles = Array.from(index.array);
1173
+ const count = this._excludeTriangles(oldTriangles, skinWeight, skinIndex, erasingBonesIndex);
1174
+ const newTriangle = [];
1175
+ for (let i = 0; i < count; i++) {
1176
+ newTriangle[i] = oldTriangles[i];
1177
+ }
1178
+ geometry.setIndex(newTriangle);
1179
+ // mtoon material includes onBeforeRender. this is unsupported at SkinnedMesh#clone
1180
+ if (src.onBeforeRender) {
1181
+ dst.onBeforeRender = src.onBeforeRender;
1182
+ }
1183
+ dst.bind(new THREE__namespace.Skeleton(src.skeleton.bones, src.skeleton.boneInverses), new THREE__namespace.Matrix4());
1184
+ return dst;
1185
+ }
1186
+ _createHeadlessModelForSkinnedMesh(parent, mesh) {
1187
+ const eraseBoneIndexes = [];
1188
+ mesh.skeleton.bones.forEach((bone, index) => {
1189
+ if (this._isEraseTarget(bone))
1190
+ eraseBoneIndexes.push(index);
1191
+ });
1192
+ // Unlike UniVRM we don't copy mesh if no invisible bone was found
1193
+ if (!eraseBoneIndexes.length) {
1194
+ mesh.layers.enable(this._thirdPersonOnlyLayer);
1195
+ mesh.layers.enable(this._firstPersonOnlyLayer);
1196
+ return;
1197
+ }
1198
+ mesh.layers.set(this._thirdPersonOnlyLayer);
1199
+ const newMesh = this._createErasedMesh(mesh, eraseBoneIndexes);
1200
+ parent.add(newMesh);
1201
+ }
1202
+ _createHeadlessModel(node) {
1203
+ if (node.type === 'Group') {
1204
+ node.layers.set(this._thirdPersonOnlyLayer);
1205
+ if (this._isEraseTarget(node)) {
1206
+ node.traverse((child) => child.layers.set(this._thirdPersonOnlyLayer));
1207
+ }
1208
+ else {
1209
+ const parent = new THREE__namespace.Group();
1210
+ parent.name = `_headless_${node.name}`;
1211
+ parent.layers.set(this._firstPersonOnlyLayer);
1212
+ node.parent.add(parent);
1213
+ node.children
1214
+ .filter((child) => child.type === 'SkinnedMesh')
1215
+ .forEach((child) => {
1216
+ const skinnedMesh = child;
1217
+ this._createHeadlessModelForSkinnedMesh(parent, skinnedMesh);
1218
+ });
1219
+ }
1220
+ }
1221
+ else if (node.type === 'SkinnedMesh') {
1222
+ const skinnedMesh = node;
1223
+ this._createHeadlessModelForSkinnedMesh(node.parent, skinnedMesh);
1224
+ }
1225
+ else {
1226
+ if (this._isEraseTarget(node)) {
1227
+ node.layers.set(this._thirdPersonOnlyLayer);
1228
+ node.traverse((child) => child.layers.set(this._thirdPersonOnlyLayer));
1229
+ }
1230
+ }
1231
+ }
1232
+ _isEraseTarget(bone) {
1233
+ if (bone === this.humanoid.getBoneNode('head')) {
1234
+ return true;
1235
+ }
1236
+ else if (!bone.parent) {
1237
+ return false;
1238
+ }
1239
+ else {
1240
+ return this._isEraseTarget(bone.parent);
1241
+ }
1242
+ }
1243
+ }
1244
+ /**
1245
+ * A default camera layer for `FirstPersonOnly` layer.
1246
+ *
1247
+ * @see [[getFirstPersonOnlyLayer]]
1248
+ */
1249
+ VRMFirstPerson.DEFAULT_FIRSTPERSON_ONLY_LAYER = 9;
1250
+ /**
1251
+ * A default camera layer for `ThirdPersonOnly` layer.
1252
+ *
1253
+ * @see [[getThirdPersonOnlyLayer]]
1254
+ */
1255
1255
  VRMFirstPerson.DEFAULT_THIRDPERSON_ONLY_LAYER = 10;
1256
1256
 
1257
- /**
1258
- * A plugin of GLTFLoader that imports a {@link VRMFirstPerson} from a VRM extension of a GLTF.
1259
- */
1260
- class VRMFirstPersonLoaderPlugin {
1261
- constructor(parser) {
1262
- this.parser = parser;
1263
- }
1264
- get name() {
1265
- // We should use the extension name instead but we have multiple plugins for an extension...
1266
- return 'VRMFirstPersonLoaderPlugin';
1267
- }
1268
- afterRoot(gltf) {
1269
- return __awaiter(this, void 0, void 0, function* () {
1270
- const vrmHumanoid = gltf.userData.vrmHumanoid;
1271
- // explicitly distinguish null and undefined
1272
- // since vrmHumanoid might be null as a result
1273
- if (vrmHumanoid === null) {
1274
- return;
1275
- }
1276
- else if (vrmHumanoid === undefined) {
1277
- throw new Error('VRMFirstPersonLoaderPlugin: vrmHumanoid is undefined. VRMHumanoidLoaderPlugin have to be used first');
1278
- }
1279
- gltf.userData.vrmFirstPerson = yield this._import(gltf, vrmHumanoid);
1280
- });
1281
- }
1282
- /**
1283
- * Import a {@link VRMFirstPerson} from a VRM.
1284
- *
1285
- * @param gltf A parsed result of GLTF taken from GLTFLoader
1286
- * @param humanoid A {@link VRMHumanoid} instance that represents the VRM
1287
- */
1288
- _import(gltf, humanoid) {
1289
- return __awaiter(this, void 0, void 0, function* () {
1290
- if (humanoid == null) {
1291
- return null;
1292
- }
1293
- const v1Result = yield this._v1Import(gltf, humanoid);
1294
- if (v1Result) {
1295
- return v1Result;
1296
- }
1297
- const v0Result = yield this._v0Import(gltf, humanoid);
1298
- if (v0Result) {
1299
- return v0Result;
1300
- }
1301
- return null;
1302
- });
1303
- }
1304
- _v1Import(gltf, humanoid) {
1305
- var _a, _b;
1306
- return __awaiter(this, void 0, void 0, function* () {
1307
- const json = this.parser.json;
1308
- // early abort if it doesn't use vrm
1309
- const isVRMUsed = ((_a = json.extensionsUsed) === null || _a === void 0 ? void 0 : _a.indexOf('VRMC_vrm')) !== -1;
1310
- if (!isVRMUsed) {
1311
- return null;
1312
- }
1313
- const extension = (_b = json.extensions) === null || _b === void 0 ? void 0 : _b['VRMC_vrm'];
1314
- if (!extension) {
1315
- return null;
1316
- }
1317
- const specVersion = extension.specVersion;
1318
- if (specVersion !== '1.0-beta') {
1319
- return null;
1320
- }
1321
- const schemaFirstPerson = extension.firstPerson;
1322
- if (!schemaFirstPerson) {
1323
- return null;
1324
- }
1325
- const meshAnnotations = [];
1326
- const nodePrimitivesMap = yield gltfExtractPrimitivesFromNodes(gltf);
1327
- Array.from(nodePrimitivesMap.entries()).forEach(([nodeIndex, primitives]) => {
1328
- var _a;
1329
- const annotation = schemaFirstPerson.meshAnnotations
1330
- ? schemaFirstPerson.meshAnnotations.find((a) => a.node === nodeIndex)
1331
- : undefined;
1332
- meshAnnotations.push({
1333
- meshes: primitives,
1334
- type: (_a = annotation === null || annotation === void 0 ? void 0 : annotation.type) !== null && _a !== void 0 ? _a : 'both',
1335
- });
1336
- });
1337
- return new VRMFirstPerson(humanoid, meshAnnotations);
1338
- });
1339
- }
1340
- _v0Import(gltf, humanoid) {
1341
- var _a;
1342
- return __awaiter(this, void 0, void 0, function* () {
1343
- const json = this.parser.json;
1344
- const vrmExt = (_a = json.extensions) === null || _a === void 0 ? void 0 : _a.VRM;
1345
- if (!vrmExt) {
1346
- return null;
1347
- }
1348
- const schemaFirstPerson = vrmExt.firstPerson;
1349
- if (!schemaFirstPerson) {
1350
- return null;
1351
- }
1352
- const meshAnnotations = [];
1353
- const nodePrimitivesMap = yield gltfExtractPrimitivesFromNodes(gltf);
1354
- Array.from(nodePrimitivesMap.entries()).forEach(([nodeIndex, primitives]) => {
1355
- const schemaNode = json.nodes[nodeIndex];
1356
- const flag = schemaFirstPerson.meshAnnotations
1357
- ? schemaFirstPerson.meshAnnotations.find((a) => a.mesh === schemaNode.mesh)
1358
- : undefined;
1359
- meshAnnotations.push({
1360
- meshes: primitives,
1361
- type: this._convertV0FlagToV1Type(flag === null || flag === void 0 ? void 0 : flag.firstPersonFlag),
1362
- });
1363
- });
1364
- return new VRMFirstPerson(humanoid, meshAnnotations);
1365
- });
1366
- }
1367
- _convertV0FlagToV1Type(flag) {
1368
- if (flag === 'FirstPersonOnly') {
1369
- return 'firstPersonOnly';
1370
- }
1371
- else if (flag === 'ThirdPersonOnly') {
1372
- return 'thirdPersonOnly';
1373
- }
1374
- else if (flag === 'Auto') {
1375
- return 'auto';
1376
- }
1377
- else {
1378
- return 'both';
1379
- }
1380
- }
1257
+ /**
1258
+ * A plugin of GLTFLoader that imports a {@link VRMFirstPerson} from a VRM extension of a GLTF.
1259
+ */
1260
+ class VRMFirstPersonLoaderPlugin {
1261
+ constructor(parser) {
1262
+ this.parser = parser;
1263
+ }
1264
+ get name() {
1265
+ // We should use the extension name instead but we have multiple plugins for an extension...
1266
+ return 'VRMFirstPersonLoaderPlugin';
1267
+ }
1268
+ afterRoot(gltf) {
1269
+ return __awaiter(this, void 0, void 0, function* () {
1270
+ const vrmHumanoid = gltf.userData.vrmHumanoid;
1271
+ // explicitly distinguish null and undefined
1272
+ // since vrmHumanoid might be null as a result
1273
+ if (vrmHumanoid === null) {
1274
+ return;
1275
+ }
1276
+ else if (vrmHumanoid === undefined) {
1277
+ throw new Error('VRMFirstPersonLoaderPlugin: vrmHumanoid is undefined. VRMHumanoidLoaderPlugin have to be used first');
1278
+ }
1279
+ gltf.userData.vrmFirstPerson = yield this._import(gltf, vrmHumanoid);
1280
+ });
1281
+ }
1282
+ /**
1283
+ * Import a {@link VRMFirstPerson} from a VRM.
1284
+ *
1285
+ * @param gltf A parsed result of GLTF taken from GLTFLoader
1286
+ * @param humanoid A {@link VRMHumanoid} instance that represents the VRM
1287
+ */
1288
+ _import(gltf, humanoid) {
1289
+ return __awaiter(this, void 0, void 0, function* () {
1290
+ if (humanoid == null) {
1291
+ return null;
1292
+ }
1293
+ const v1Result = yield this._v1Import(gltf, humanoid);
1294
+ if (v1Result) {
1295
+ return v1Result;
1296
+ }
1297
+ const v0Result = yield this._v0Import(gltf, humanoid);
1298
+ if (v0Result) {
1299
+ return v0Result;
1300
+ }
1301
+ return null;
1302
+ });
1303
+ }
1304
+ _v1Import(gltf, humanoid) {
1305
+ var _a, _b;
1306
+ return __awaiter(this, void 0, void 0, function* () {
1307
+ const json = this.parser.json;
1308
+ // early abort if it doesn't use vrm
1309
+ const isVRMUsed = ((_a = json.extensionsUsed) === null || _a === void 0 ? void 0 : _a.indexOf('VRMC_vrm')) !== -1;
1310
+ if (!isVRMUsed) {
1311
+ return null;
1312
+ }
1313
+ const extension = (_b = json.extensions) === null || _b === void 0 ? void 0 : _b['VRMC_vrm'];
1314
+ if (!extension) {
1315
+ return null;
1316
+ }
1317
+ const specVersion = extension.specVersion;
1318
+ if (specVersion !== '1.0-beta') {
1319
+ return null;
1320
+ }
1321
+ const schemaFirstPerson = extension.firstPerson;
1322
+ if (!schemaFirstPerson) {
1323
+ return null;
1324
+ }
1325
+ const meshAnnotations = [];
1326
+ const nodePrimitivesMap = yield gltfExtractPrimitivesFromNodes(gltf);
1327
+ Array.from(nodePrimitivesMap.entries()).forEach(([nodeIndex, primitives]) => {
1328
+ var _a;
1329
+ const annotation = schemaFirstPerson.meshAnnotations
1330
+ ? schemaFirstPerson.meshAnnotations.find((a) => a.node === nodeIndex)
1331
+ : undefined;
1332
+ meshAnnotations.push({
1333
+ meshes: primitives,
1334
+ type: (_a = annotation === null || annotation === void 0 ? void 0 : annotation.type) !== null && _a !== void 0 ? _a : 'both',
1335
+ });
1336
+ });
1337
+ return new VRMFirstPerson(humanoid, meshAnnotations);
1338
+ });
1339
+ }
1340
+ _v0Import(gltf, humanoid) {
1341
+ var _a;
1342
+ return __awaiter(this, void 0, void 0, function* () {
1343
+ const json = this.parser.json;
1344
+ const vrmExt = (_a = json.extensions) === null || _a === void 0 ? void 0 : _a.VRM;
1345
+ if (!vrmExt) {
1346
+ return null;
1347
+ }
1348
+ const schemaFirstPerson = vrmExt.firstPerson;
1349
+ if (!schemaFirstPerson) {
1350
+ return null;
1351
+ }
1352
+ const meshAnnotations = [];
1353
+ const nodePrimitivesMap = yield gltfExtractPrimitivesFromNodes(gltf);
1354
+ Array.from(nodePrimitivesMap.entries()).forEach(([nodeIndex, primitives]) => {
1355
+ const schemaNode = json.nodes[nodeIndex];
1356
+ const flag = schemaFirstPerson.meshAnnotations
1357
+ ? schemaFirstPerson.meshAnnotations.find((a) => a.mesh === schemaNode.mesh)
1358
+ : undefined;
1359
+ meshAnnotations.push({
1360
+ meshes: primitives,
1361
+ type: this._convertV0FlagToV1Type(flag === null || flag === void 0 ? void 0 : flag.firstPersonFlag),
1362
+ });
1363
+ });
1364
+ return new VRMFirstPerson(humanoid, meshAnnotations);
1365
+ });
1366
+ }
1367
+ _convertV0FlagToV1Type(flag) {
1368
+ if (flag === 'FirstPersonOnly') {
1369
+ return 'firstPersonOnly';
1370
+ }
1371
+ else if (flag === 'ThirdPersonOnly') {
1372
+ return 'thirdPersonOnly';
1373
+ }
1374
+ else if (flag === 'Auto') {
1375
+ return 'auto';
1376
+ }
1377
+ else {
1378
+ return 'both';
1379
+ }
1380
+ }
1381
1381
  }
1382
1382
 
1383
- /* eslint-disable @typescript-eslint/naming-convention */
1384
- const VRMFirstPersonMeshAnnotationType = {
1385
- Auto: 'auto',
1386
- Both: 'both',
1387
- ThirdPersonOnly: 'thirdPersonOnly',
1388
- FirstPersonOnly: 'firstPersonOnly',
1383
+ /* eslint-disable @typescript-eslint/naming-convention */
1384
+ const VRMFirstPersonMeshAnnotationType = {
1385
+ Auto: 'auto',
1386
+ Both: 'both',
1387
+ ThirdPersonOnly: 'thirdPersonOnly',
1388
+ FirstPersonOnly: 'firstPersonOnly',
1389
1389
  };
1390
1390
 
1391
- /* eslint-disable @typescript-eslint/naming-convention */
1392
- const VRMHumanBoneName = {
1393
- Hips: 'hips',
1394
- Spine: 'spine',
1395
- Chest: 'chest',
1396
- UpperChest: 'upperChest',
1397
- Neck: 'neck',
1398
- Head: 'head',
1399
- LeftEye: 'leftEye',
1400
- RightEye: 'rightEye',
1401
- Jaw: 'jaw',
1402
- LeftUpperLeg: 'leftUpperLeg',
1403
- LeftLowerLeg: 'leftLowerLeg',
1404
- LeftFoot: 'leftFoot',
1405
- LeftToes: 'leftToes',
1406
- RightUpperLeg: 'rightUpperLeg',
1407
- RightLowerLeg: 'rightLowerLeg',
1408
- RightFoot: 'rightFoot',
1409
- RightToes: 'rightToes',
1410
- LeftShoulder: 'leftShoulder',
1411
- LeftUpperArm: 'leftUpperArm',
1412
- LeftLowerArm: 'leftLowerArm',
1413
- LeftHand: 'leftHand',
1414
- RightShoulder: 'rightShoulder',
1415
- RightUpperArm: 'rightUpperArm',
1416
- RightLowerArm: 'rightLowerArm',
1417
- RightHand: 'rightHand',
1418
- LeftThumbProximal: 'leftThumbProximal',
1419
- LeftThumbIntermediate: 'leftThumbIntermediate',
1420
- LeftThumbDistal: 'leftThumbDistal',
1421
- LeftIndexProximal: 'leftIndexProximal',
1422
- LeftIndexIntermediate: 'leftIndexIntermediate',
1423
- LeftIndexDistal: 'leftIndexDistal',
1424
- LeftMiddleProximal: 'leftMiddleProximal',
1425
- LeftMiddleIntermediate: 'leftMiddleIntermediate',
1426
- LeftMiddleDistal: 'leftMiddleDistal',
1427
- LeftRingProximal: 'leftRingProximal',
1428
- LeftRingIntermediate: 'leftRingIntermediate',
1429
- LeftRingDistal: 'leftRingDistal',
1430
- LeftLittleProximal: 'leftLittleProximal',
1431
- LeftLittleIntermediate: 'leftLittleIntermediate',
1432
- LeftLittleDistal: 'leftLittleDistal',
1433
- RightThumbProximal: 'rightThumbProximal',
1434
- RightThumbIntermediate: 'rightThumbIntermediate',
1435
- RightThumbDistal: 'rightThumbDistal',
1436
- RightIndexProximal: 'rightIndexProximal',
1437
- RightIndexIntermediate: 'rightIndexIntermediate',
1438
- RightIndexDistal: 'rightIndexDistal',
1439
- RightMiddleProximal: 'rightMiddleProximal',
1440
- RightMiddleIntermediate: 'rightMiddleIntermediate',
1441
- RightMiddleDistal: 'rightMiddleDistal',
1442
- RightRingProximal: 'rightRingProximal',
1443
- RightRingIntermediate: 'rightRingIntermediate',
1444
- RightRingDistal: 'rightRingDistal',
1445
- RightLittleProximal: 'rightLittleProximal',
1446
- RightLittleIntermediate: 'rightLittleIntermediate',
1447
- RightLittleDistal: 'rightLittleDistal',
1391
+ /* eslint-disable @typescript-eslint/naming-convention */
1392
+ const VRMHumanBoneName = {
1393
+ Hips: 'hips',
1394
+ Spine: 'spine',
1395
+ Chest: 'chest',
1396
+ UpperChest: 'upperChest',
1397
+ Neck: 'neck',
1398
+ Head: 'head',
1399
+ LeftEye: 'leftEye',
1400
+ RightEye: 'rightEye',
1401
+ Jaw: 'jaw',
1402
+ LeftUpperLeg: 'leftUpperLeg',
1403
+ LeftLowerLeg: 'leftLowerLeg',
1404
+ LeftFoot: 'leftFoot',
1405
+ LeftToes: 'leftToes',
1406
+ RightUpperLeg: 'rightUpperLeg',
1407
+ RightLowerLeg: 'rightLowerLeg',
1408
+ RightFoot: 'rightFoot',
1409
+ RightToes: 'rightToes',
1410
+ LeftShoulder: 'leftShoulder',
1411
+ LeftUpperArm: 'leftUpperArm',
1412
+ LeftLowerArm: 'leftLowerArm',
1413
+ LeftHand: 'leftHand',
1414
+ RightShoulder: 'rightShoulder',
1415
+ RightUpperArm: 'rightUpperArm',
1416
+ RightLowerArm: 'rightLowerArm',
1417
+ RightHand: 'rightHand',
1418
+ LeftThumbProximal: 'leftThumbProximal',
1419
+ LeftThumbIntermediate: 'leftThumbIntermediate',
1420
+ LeftThumbDistal: 'leftThumbDistal',
1421
+ LeftIndexProximal: 'leftIndexProximal',
1422
+ LeftIndexIntermediate: 'leftIndexIntermediate',
1423
+ LeftIndexDistal: 'leftIndexDistal',
1424
+ LeftMiddleProximal: 'leftMiddleProximal',
1425
+ LeftMiddleIntermediate: 'leftMiddleIntermediate',
1426
+ LeftMiddleDistal: 'leftMiddleDistal',
1427
+ LeftRingProximal: 'leftRingProximal',
1428
+ LeftRingIntermediate: 'leftRingIntermediate',
1429
+ LeftRingDistal: 'leftRingDistal',
1430
+ LeftLittleProximal: 'leftLittleProximal',
1431
+ LeftLittleIntermediate: 'leftLittleIntermediate',
1432
+ LeftLittleDistal: 'leftLittleDistal',
1433
+ RightThumbProximal: 'rightThumbProximal',
1434
+ RightThumbIntermediate: 'rightThumbIntermediate',
1435
+ RightThumbDistal: 'rightThumbDistal',
1436
+ RightIndexProximal: 'rightIndexProximal',
1437
+ RightIndexIntermediate: 'rightIndexIntermediate',
1438
+ RightIndexDistal: 'rightIndexDistal',
1439
+ RightMiddleProximal: 'rightMiddleProximal',
1440
+ RightMiddleIntermediate: 'rightMiddleIntermediate',
1441
+ RightMiddleDistal: 'rightMiddleDistal',
1442
+ RightRingProximal: 'rightRingProximal',
1443
+ RightRingIntermediate: 'rightRingIntermediate',
1444
+ RightRingDistal: 'rightRingDistal',
1445
+ RightLittleProximal: 'rightLittleProximal',
1446
+ RightLittleIntermediate: 'rightLittleIntermediate',
1447
+ RightLittleDistal: 'rightLittleDistal',
1448
1448
  };
1449
1449
 
1450
- /**
1451
- * A compat function for `Quaternion.invert()` / `Quaternion.inverse()`.
1452
- * `Quaternion.invert()` is introduced in r123 and `Quaternion.inverse()` emits a warning.
1453
- * We are going to use this compat for a while.
1454
- * @param target A target quaternion
1455
- */
1456
- function quatInvertCompat(target) {
1457
- if (target.invert) {
1458
- target.invert();
1459
- }
1460
- else {
1461
- target.inverse();
1462
- }
1463
- return target;
1450
+ /**
1451
+ * A compat function for `Quaternion.invert()` / `Quaternion.inverse()`.
1452
+ * `Quaternion.invert()` is introduced in r123 and `Quaternion.inverse()` emits a warning.
1453
+ * We are going to use this compat for a while.
1454
+ * @param target A target quaternion
1455
+ */
1456
+ function quatInvertCompat(target) {
1457
+ if (target.invert) {
1458
+ target.invert();
1459
+ }
1460
+ else {
1461
+ target.inverse();
1462
+ }
1463
+ return target;
1464
1464
  }
1465
1465
 
1466
- const _v3A$2 = new THREE__namespace.Vector3();
1467
- const _quatA$2 = new THREE__namespace.Quaternion();
1468
- /**
1469
- * A class represents a humanoid of a VRM.
1470
- */
1471
- class VRMHumanoid {
1472
- /**
1473
- * Create a new {@link VRMHumanoid}.
1474
- * @param boneArray A {@link VRMHumanBones} contains all the bones of the new humanoid
1475
- */
1476
- constructor(humanBones) {
1477
- this.humanBones = humanBones;
1478
- this.restPose = this.getAbsolutePose();
1479
- }
1480
- /**
1481
- * Copy the given {@link VRMHumanoid} into this one.
1482
- * @param source The {@link VRMHumanoid} you want to copy
1483
- * @returns this
1484
- */
1485
- copy(source) {
1486
- this.humanBones = source.humanBones;
1487
- this.restPose = source.restPose;
1488
- return this;
1489
- }
1490
- /**
1491
- * Returns a clone of this {@link VRMHumanoid}.
1492
- * @returns Copied {@link VRMHumanoid}
1493
- */
1494
- clone() {
1495
- return new VRMHumanoid(this.humanBones).copy(this);
1496
- }
1497
- /**
1498
- * Return the current absolute pose of this humanoid as a {@link VRMPose}.
1499
- * Note that the output result will contain initial state of the VRM and not compatible between different models.
1500
- * You might want to use {@link getPose} instead.
1501
- */
1502
- getAbsolutePose() {
1503
- const pose = {};
1504
- Object.keys(this.humanBones).forEach((vrmBoneNameString) => {
1505
- const vrmBoneName = vrmBoneNameString;
1506
- const node = this.getBoneNode(vrmBoneName);
1507
- // Ignore when there are no bone on the VRMHumanoid
1508
- if (!node) {
1509
- return;
1510
- }
1511
- // Get the position / rotation from the node
1512
- _v3A$2.copy(node.position);
1513
- _quatA$2.copy(node.quaternion);
1514
- // Convert to raw arrays
1515
- pose[vrmBoneName] = {
1516
- position: _v3A$2.toArray(),
1517
- rotation: _quatA$2.toArray(),
1518
- };
1519
- });
1520
- return pose;
1521
- }
1522
- /**
1523
- * Return the current pose of this humanoid as a {@link VRMPose}.
1524
- *
1525
- * Each transform is a local transform relative from rest pose (T-pose).
1526
- */
1527
- getPose() {
1528
- const pose = {};
1529
- Object.keys(this.humanBones).forEach((boneNameString) => {
1530
- const boneName = boneNameString;
1531
- const node = this.getBoneNode(boneName);
1532
- // Ignore when there are no bone on the VRMHumanoid
1533
- if (!node) {
1534
- return;
1535
- }
1536
- // Take a diff from restPose
1537
- _v3A$2.set(0, 0, 0);
1538
- _quatA$2.identity();
1539
- const restState = this.restPose[boneName];
1540
- if (restState === null || restState === void 0 ? void 0 : restState.position) {
1541
- _v3A$2.fromArray(restState.position).negate();
1542
- }
1543
- if (restState === null || restState === void 0 ? void 0 : restState.rotation) {
1544
- quatInvertCompat(_quatA$2.fromArray(restState.rotation));
1545
- }
1546
- // Get the position / rotation from the node
1547
- _v3A$2.add(node.position);
1548
- _quatA$2.premultiply(node.quaternion);
1549
- // Convert to raw arrays
1550
- pose[boneName] = {
1551
- position: _v3A$2.toArray(),
1552
- rotation: _quatA$2.toArray(),
1553
- };
1554
- });
1555
- return pose;
1556
- }
1557
- /**
1558
- * Let the humanoid do a specified pose.
1559
- *
1560
- * Each transform have to be a local transform relative from rest pose (T-pose).
1561
- * You can pass what you got from {@link getPose}.
1562
- *
1563
- * @param poseObject A [[VRMPose]] that represents a single pose
1564
- */
1565
- setPose(poseObject) {
1566
- Object.entries(poseObject).forEach(([boneNameString, state]) => {
1567
- const boneName = boneNameString;
1568
- const node = this.getBoneNode(boneName);
1569
- // Ignore when there are no bone that is defined in the pose on the VRMHumanoid
1570
- if (!node) {
1571
- return;
1572
- }
1573
- const restState = this.restPose[boneName];
1574
- if (!restState) {
1575
- // It's very unlikely. Possibly a bug
1576
- return;
1577
- }
1578
- // Apply the state to the actual bone
1579
- if (state === null || state === void 0 ? void 0 : state.position) {
1580
- node.position.fromArray(state.position);
1581
- if (restState.position) {
1582
- node.position.add(_v3A$2.fromArray(restState.position));
1583
- }
1584
- }
1585
- if (state === null || state === void 0 ? void 0 : state.rotation) {
1586
- node.quaternion.fromArray(state.rotation);
1587
- if (restState.rotation) {
1588
- node.quaternion.multiply(_quatA$2.fromArray(restState.rotation));
1589
- }
1590
- }
1591
- });
1592
- }
1593
- /**
1594
- * Reset the humanoid to its rest pose.
1595
- */
1596
- resetPose() {
1597
- Object.entries(this.restPose).forEach(([boneName, rest]) => {
1598
- const node = this.getBoneNode(boneName);
1599
- if (!node) {
1600
- return;
1601
- }
1602
- if (rest === null || rest === void 0 ? void 0 : rest.position) {
1603
- node.position.fromArray(rest.position);
1604
- }
1605
- if (rest === null || rest === void 0 ? void 0 : rest.rotation) {
1606
- node.quaternion.fromArray(rest.rotation);
1607
- }
1608
- });
1609
- }
1610
- /**
1611
- * Return a bone bound to a specified {@link VRMHumanBoneName}, as a {@link VRMHumanBone}.
1612
- *
1613
- * @param name Name of the bone you want
1614
- */
1615
- getBone(name) {
1616
- var _a;
1617
- return (_a = this.humanBones[name]) !== null && _a !== void 0 ? _a : undefined;
1618
- }
1619
- /**
1620
- * Return a bone bound to a specified {@link VRMHumanBoneName}, as a `THREE.Object3D`.
1621
- *
1622
- * @param name Name of the bone you want
1623
- */
1624
- getBoneNode(name) {
1625
- var _a, _b;
1626
- return (_b = (_a = this.humanBones[name]) === null || _a === void 0 ? void 0 : _a.node) !== null && _b !== void 0 ? _b : null;
1627
- }
1466
+ const _v3A$2 = new THREE__namespace.Vector3();
1467
+ const _quatA$2 = new THREE__namespace.Quaternion();
1468
+ /**
1469
+ * A class represents a humanoid of a VRM.
1470
+ */
1471
+ class VRMHumanoid {
1472
+ /**
1473
+ * Create a new {@link VRMHumanoid}.
1474
+ * @param boneArray A {@link VRMHumanBones} contains all the bones of the new humanoid
1475
+ */
1476
+ constructor(humanBones) {
1477
+ this.humanBones = humanBones;
1478
+ this.restPose = this.getAbsolutePose();
1479
+ }
1480
+ /**
1481
+ * Copy the given {@link VRMHumanoid} into this one.
1482
+ * @param source The {@link VRMHumanoid} you want to copy
1483
+ * @returns this
1484
+ */
1485
+ copy(source) {
1486
+ this.humanBones = source.humanBones;
1487
+ this.restPose = source.restPose;
1488
+ return this;
1489
+ }
1490
+ /**
1491
+ * Returns a clone of this {@link VRMHumanoid}.
1492
+ * @returns Copied {@link VRMHumanoid}
1493
+ */
1494
+ clone() {
1495
+ return new VRMHumanoid(this.humanBones).copy(this);
1496
+ }
1497
+ /**
1498
+ * Return the current absolute pose of this humanoid as a {@link VRMPose}.
1499
+ * Note that the output result will contain initial state of the VRM and not compatible between different models.
1500
+ * You might want to use {@link getPose} instead.
1501
+ */
1502
+ getAbsolutePose() {
1503
+ const pose = {};
1504
+ Object.keys(this.humanBones).forEach((vrmBoneNameString) => {
1505
+ const vrmBoneName = vrmBoneNameString;
1506
+ const node = this.getBoneNode(vrmBoneName);
1507
+ // Ignore when there are no bone on the VRMHumanoid
1508
+ if (!node) {
1509
+ return;
1510
+ }
1511
+ // Get the position / rotation from the node
1512
+ _v3A$2.copy(node.position);
1513
+ _quatA$2.copy(node.quaternion);
1514
+ // Convert to raw arrays
1515
+ pose[vrmBoneName] = {
1516
+ position: _v3A$2.toArray(),
1517
+ rotation: _quatA$2.toArray(),
1518
+ };
1519
+ });
1520
+ return pose;
1521
+ }
1522
+ /**
1523
+ * Return the current pose of this humanoid as a {@link VRMPose}.
1524
+ *
1525
+ * Each transform is a local transform relative from rest pose (T-pose).
1526
+ */
1527
+ getPose() {
1528
+ const pose = {};
1529
+ Object.keys(this.humanBones).forEach((boneNameString) => {
1530
+ const boneName = boneNameString;
1531
+ const node = this.getBoneNode(boneName);
1532
+ // Ignore when there are no bone on the VRMHumanoid
1533
+ if (!node) {
1534
+ return;
1535
+ }
1536
+ // Take a diff from restPose
1537
+ _v3A$2.set(0, 0, 0);
1538
+ _quatA$2.identity();
1539
+ const restState = this.restPose[boneName];
1540
+ if (restState === null || restState === void 0 ? void 0 : restState.position) {
1541
+ _v3A$2.fromArray(restState.position).negate();
1542
+ }
1543
+ if (restState === null || restState === void 0 ? void 0 : restState.rotation) {
1544
+ quatInvertCompat(_quatA$2.fromArray(restState.rotation));
1545
+ }
1546
+ // Get the position / rotation from the node
1547
+ _v3A$2.add(node.position);
1548
+ _quatA$2.premultiply(node.quaternion);
1549
+ // Convert to raw arrays
1550
+ pose[boneName] = {
1551
+ position: _v3A$2.toArray(),
1552
+ rotation: _quatA$2.toArray(),
1553
+ };
1554
+ });
1555
+ return pose;
1556
+ }
1557
+ /**
1558
+ * Let the humanoid do a specified pose.
1559
+ *
1560
+ * Each transform have to be a local transform relative from rest pose (T-pose).
1561
+ * You can pass what you got from {@link getPose}.
1562
+ *
1563
+ * @param poseObject A [[VRMPose]] that represents a single pose
1564
+ */
1565
+ setPose(poseObject) {
1566
+ Object.entries(poseObject).forEach(([boneNameString, state]) => {
1567
+ const boneName = boneNameString;
1568
+ const node = this.getBoneNode(boneName);
1569
+ // Ignore when there are no bone that is defined in the pose on the VRMHumanoid
1570
+ if (!node) {
1571
+ return;
1572
+ }
1573
+ const restState = this.restPose[boneName];
1574
+ if (!restState) {
1575
+ // It's very unlikely. Possibly a bug
1576
+ return;
1577
+ }
1578
+ // Apply the state to the actual bone
1579
+ if (state === null || state === void 0 ? void 0 : state.position) {
1580
+ node.position.fromArray(state.position);
1581
+ if (restState.position) {
1582
+ node.position.add(_v3A$2.fromArray(restState.position));
1583
+ }
1584
+ }
1585
+ if (state === null || state === void 0 ? void 0 : state.rotation) {
1586
+ node.quaternion.fromArray(state.rotation);
1587
+ if (restState.rotation) {
1588
+ node.quaternion.multiply(_quatA$2.fromArray(restState.rotation));
1589
+ }
1590
+ }
1591
+ });
1592
+ }
1593
+ /**
1594
+ * Reset the humanoid to its rest pose.
1595
+ */
1596
+ resetPose() {
1597
+ Object.entries(this.restPose).forEach(([boneName, rest]) => {
1598
+ const node = this.getBoneNode(boneName);
1599
+ if (!node) {
1600
+ return;
1601
+ }
1602
+ if (rest === null || rest === void 0 ? void 0 : rest.position) {
1603
+ node.position.fromArray(rest.position);
1604
+ }
1605
+ if (rest === null || rest === void 0 ? void 0 : rest.rotation) {
1606
+ node.quaternion.fromArray(rest.rotation);
1607
+ }
1608
+ });
1609
+ }
1610
+ /**
1611
+ * Return a bone bound to a specified {@link VRMHumanBoneName}, as a {@link VRMHumanBone}.
1612
+ *
1613
+ * @param name Name of the bone you want
1614
+ */
1615
+ getBone(name) {
1616
+ var _a;
1617
+ return (_a = this.humanBones[name]) !== null && _a !== void 0 ? _a : undefined;
1618
+ }
1619
+ /**
1620
+ * Return a bone bound to a specified {@link VRMHumanBoneName}, as a `THREE.Object3D`.
1621
+ *
1622
+ * @param name Name of the bone you want
1623
+ */
1624
+ getBoneNode(name) {
1625
+ var _a, _b;
1626
+ return (_b = (_a = this.humanBones[name]) === null || _a === void 0 ? void 0 : _a.node) !== null && _b !== void 0 ? _b : null;
1627
+ }
1628
1628
  }
1629
1629
 
1630
- /* eslint-disable @typescript-eslint/naming-convention */
1631
- const VRMRequiredHumanBoneName = {
1632
- Hips: 'hips',
1633
- Spine: 'spine',
1634
- Head: 'head',
1635
- LeftUpperLeg: 'leftUpperLeg',
1636
- LeftLowerLeg: 'leftLowerLeg',
1637
- LeftFoot: 'leftFoot',
1638
- RightUpperLeg: 'rightUpperLeg',
1639
- RightLowerLeg: 'rightLowerLeg',
1640
- RightFoot: 'rightFoot',
1641
- LeftUpperArm: 'leftUpperArm',
1642
- LeftLowerArm: 'leftLowerArm',
1643
- LeftHand: 'leftHand',
1644
- RightUpperArm: 'rightUpperArm',
1645
- RightLowerArm: 'rightLowerArm',
1646
- RightHand: 'rightHand',
1630
+ /* eslint-disable @typescript-eslint/naming-convention */
1631
+ const VRMRequiredHumanBoneName = {
1632
+ Hips: 'hips',
1633
+ Spine: 'spine',
1634
+ Head: 'head',
1635
+ LeftUpperLeg: 'leftUpperLeg',
1636
+ LeftLowerLeg: 'leftLowerLeg',
1637
+ LeftFoot: 'leftFoot',
1638
+ RightUpperLeg: 'rightUpperLeg',
1639
+ RightLowerLeg: 'rightLowerLeg',
1640
+ RightFoot: 'rightFoot',
1641
+ LeftUpperArm: 'leftUpperArm',
1642
+ LeftLowerArm: 'leftLowerArm',
1643
+ LeftHand: 'leftHand',
1644
+ RightUpperArm: 'rightUpperArm',
1645
+ RightLowerArm: 'rightLowerArm',
1646
+ RightHand: 'rightHand',
1647
1647
  };
1648
1648
 
1649
- /**
1650
- * A plugin of GLTFLoader that imports a {@link VRMHumanoid} from a VRM extension of a GLTF.
1651
- */
1652
- class VRMHumanoidLoaderPlugin {
1653
- constructor(parser) {
1654
- this.parser = parser;
1655
- }
1656
- get name() {
1657
- // We should use the extension name instead but we have multiple plugins for an extension...
1658
- return 'VRMHumanoidLoaderPlugin';
1659
- }
1660
- afterRoot(gltf) {
1661
- return __awaiter(this, void 0, void 0, function* () {
1662
- gltf.userData.vrmHumanoid = yield this._import(gltf);
1663
- });
1664
- }
1665
- /**
1666
- * Import a {@link VRMHumanoid} from a VRM.
1667
- *
1668
- * @param gltf A parsed result of GLTF taken from GLTFLoader
1669
- */
1670
- _import(gltf) {
1671
- return __awaiter(this, void 0, void 0, function* () {
1672
- const v1Result = yield this._v1Import(gltf);
1673
- if (v1Result) {
1674
- return v1Result;
1675
- }
1676
- const v0Result = yield this._v0Import(gltf);
1677
- if (v0Result) {
1678
- return v0Result;
1679
- }
1680
- return null;
1681
- });
1682
- }
1683
- _v1Import(gltf) {
1684
- var _a, _b;
1685
- return __awaiter(this, void 0, void 0, function* () {
1686
- const json = this.parser.json;
1687
- // early abort if it doesn't use vrm
1688
- const isVRMUsed = ((_a = json.extensionsUsed) === null || _a === void 0 ? void 0 : _a.indexOf('VRMC_vrm')) !== -1;
1689
- if (!isVRMUsed) {
1690
- return null;
1691
- }
1692
- const extension = (_b = json.extensions) === null || _b === void 0 ? void 0 : _b['VRMC_vrm'];
1693
- if (!extension) {
1694
- return null;
1695
- }
1696
- const specVersion = extension.specVersion;
1697
- if (specVersion !== '1.0-beta') {
1698
- return null;
1699
- }
1700
- const schemaHumanoid = extension.humanoid;
1701
- if (!schemaHumanoid) {
1702
- return null;
1703
- }
1704
- const humanBones = {};
1705
- if (schemaHumanoid.humanBones != null) {
1706
- yield Promise.all(Object.entries(schemaHumanoid.humanBones).map(([boneNameString, schemaHumanBone]) => __awaiter(this, void 0, void 0, function* () {
1707
- const boneName = boneNameString;
1708
- const index = schemaHumanBone.node;
1709
- const node = yield this.parser.getDependency('node', index);
1710
- // if the specified node does not exist, emit a warning
1711
- if (node == null) {
1712
- console.warn(`A glTF node bound to the humanoid bone ${boneName} (index = ${index}) does not exist`);
1713
- return;
1714
- }
1715
- // set to the `humanBones`
1716
- humanBones[boneName] = { node };
1717
- })));
1718
- }
1719
- return new VRMHumanoid(this._ensureRequiredBonesExist(humanBones));
1720
- });
1721
- }
1722
- _v0Import(gltf) {
1723
- var _a;
1724
- return __awaiter(this, void 0, void 0, function* () {
1725
- const json = this.parser.json;
1726
- const vrmExt = (_a = json.extensions) === null || _a === void 0 ? void 0 : _a.VRM;
1727
- if (!vrmExt) {
1728
- return null;
1729
- }
1730
- const schemaHumanoid = vrmExt.humanoid;
1731
- if (!schemaHumanoid) {
1732
- return null;
1733
- }
1734
- const humanBones = {};
1735
- if (schemaHumanoid.humanBones != null) {
1736
- yield Promise.all(schemaHumanoid.humanBones.map((bone) => __awaiter(this, void 0, void 0, function* () {
1737
- const boneName = bone.bone;
1738
- const index = bone.node;
1739
- if (boneName == null || index == null) {
1740
- return;
1741
- }
1742
- const node = yield this.parser.getDependency('node', index);
1743
- // if the specified node does not exist, emit a warning
1744
- if (node == null) {
1745
- console.warn(`A glTF node bound to the humanoid bone ${boneName} (index = ${index}) does not exist`);
1746
- return;
1747
- }
1748
- // v0 VRMs might have a multiple nodes attached to a single bone...
1749
- // so if there already is an entry in the `humanBones`, show a warning and ignore it
1750
- if (humanBones[boneName] != null) {
1751
- console.warn(`Multiple bone entries for ${boneName} detected (index = ${index}), ignoring duplicated entries.`);
1752
- return;
1753
- }
1754
- // set to the `humanBones`
1755
- humanBones[boneName] = { node };
1756
- })));
1757
- }
1758
- return new VRMHumanoid(this._ensureRequiredBonesExist(humanBones));
1759
- });
1760
- }
1761
- /**
1762
- * Ensure required bones exist in given human bones.
1763
- * @param humanBones Human bones
1764
- * @returns Human bones, no longer partial!
1765
- */
1766
- _ensureRequiredBonesExist(humanBones) {
1767
- // ensure required bones exist
1768
- const missingRequiredBones = Object.values(VRMRequiredHumanBoneName).filter((requiredBoneName) => humanBones[requiredBoneName] == null);
1769
- // throw an error if there are missing bones
1770
- if (missingRequiredBones.length > 0) {
1771
- throw new Error(`VRMHumanoidLoaderPlugin: These humanoid bones are required but not exist: ${missingRequiredBones.join(', ')}`);
1772
- }
1773
- return humanBones;
1774
- }
1649
+ /**
1650
+ * A plugin of GLTFLoader that imports a {@link VRMHumanoid} from a VRM extension of a GLTF.
1651
+ */
1652
+ class VRMHumanoidLoaderPlugin {
1653
+ constructor(parser) {
1654
+ this.parser = parser;
1655
+ }
1656
+ get name() {
1657
+ // We should use the extension name instead but we have multiple plugins for an extension...
1658
+ return 'VRMHumanoidLoaderPlugin';
1659
+ }
1660
+ afterRoot(gltf) {
1661
+ return __awaiter(this, void 0, void 0, function* () {
1662
+ gltf.userData.vrmHumanoid = yield this._import(gltf);
1663
+ });
1664
+ }
1665
+ /**
1666
+ * Import a {@link VRMHumanoid} from a VRM.
1667
+ *
1668
+ * @param gltf A parsed result of GLTF taken from GLTFLoader
1669
+ */
1670
+ _import(gltf) {
1671
+ return __awaiter(this, void 0, void 0, function* () {
1672
+ const v1Result = yield this._v1Import(gltf);
1673
+ if (v1Result) {
1674
+ return v1Result;
1675
+ }
1676
+ const v0Result = yield this._v0Import(gltf);
1677
+ if (v0Result) {
1678
+ return v0Result;
1679
+ }
1680
+ return null;
1681
+ });
1682
+ }
1683
+ _v1Import(gltf) {
1684
+ var _a, _b;
1685
+ return __awaiter(this, void 0, void 0, function* () {
1686
+ const json = this.parser.json;
1687
+ // early abort if it doesn't use vrm
1688
+ const isVRMUsed = ((_a = json.extensionsUsed) === null || _a === void 0 ? void 0 : _a.indexOf('VRMC_vrm')) !== -1;
1689
+ if (!isVRMUsed) {
1690
+ return null;
1691
+ }
1692
+ const extension = (_b = json.extensions) === null || _b === void 0 ? void 0 : _b['VRMC_vrm'];
1693
+ if (!extension) {
1694
+ return null;
1695
+ }
1696
+ const specVersion = extension.specVersion;
1697
+ if (specVersion !== '1.0-beta') {
1698
+ return null;
1699
+ }
1700
+ const schemaHumanoid = extension.humanoid;
1701
+ if (!schemaHumanoid) {
1702
+ return null;
1703
+ }
1704
+ const humanBones = {};
1705
+ if (schemaHumanoid.humanBones != null) {
1706
+ yield Promise.all(Object.entries(schemaHumanoid.humanBones).map(([boneNameString, schemaHumanBone]) => __awaiter(this, void 0, void 0, function* () {
1707
+ const boneName = boneNameString;
1708
+ const index = schemaHumanBone.node;
1709
+ const node = yield this.parser.getDependency('node', index);
1710
+ // if the specified node does not exist, emit a warning
1711
+ if (node == null) {
1712
+ console.warn(`A glTF node bound to the humanoid bone ${boneName} (index = ${index}) does not exist`);
1713
+ return;
1714
+ }
1715
+ // set to the `humanBones`
1716
+ humanBones[boneName] = { node };
1717
+ })));
1718
+ }
1719
+ return new VRMHumanoid(this._ensureRequiredBonesExist(humanBones));
1720
+ });
1721
+ }
1722
+ _v0Import(gltf) {
1723
+ var _a;
1724
+ return __awaiter(this, void 0, void 0, function* () {
1725
+ const json = this.parser.json;
1726
+ const vrmExt = (_a = json.extensions) === null || _a === void 0 ? void 0 : _a.VRM;
1727
+ if (!vrmExt) {
1728
+ return null;
1729
+ }
1730
+ const schemaHumanoid = vrmExt.humanoid;
1731
+ if (!schemaHumanoid) {
1732
+ return null;
1733
+ }
1734
+ const humanBones = {};
1735
+ if (schemaHumanoid.humanBones != null) {
1736
+ yield Promise.all(schemaHumanoid.humanBones.map((bone) => __awaiter(this, void 0, void 0, function* () {
1737
+ const boneName = bone.bone;
1738
+ const index = bone.node;
1739
+ if (boneName == null || index == null) {
1740
+ return;
1741
+ }
1742
+ const node = yield this.parser.getDependency('node', index);
1743
+ // if the specified node does not exist, emit a warning
1744
+ if (node == null) {
1745
+ console.warn(`A glTF node bound to the humanoid bone ${boneName} (index = ${index}) does not exist`);
1746
+ return;
1747
+ }
1748
+ // v0 VRMs might have a multiple nodes attached to a single bone...
1749
+ // so if there already is an entry in the `humanBones`, show a warning and ignore it
1750
+ if (humanBones[boneName] != null) {
1751
+ console.warn(`Multiple bone entries for ${boneName} detected (index = ${index}), ignoring duplicated entries.`);
1752
+ return;
1753
+ }
1754
+ // set to the `humanBones`
1755
+ humanBones[boneName] = { node };
1756
+ })));
1757
+ }
1758
+ return new VRMHumanoid(this._ensureRequiredBonesExist(humanBones));
1759
+ });
1760
+ }
1761
+ /**
1762
+ * Ensure required bones exist in given human bones.
1763
+ * @param humanBones Human bones
1764
+ * @returns Human bones, no longer partial!
1765
+ */
1766
+ _ensureRequiredBonesExist(humanBones) {
1767
+ // ensure required bones exist
1768
+ const missingRequiredBones = Object.values(VRMRequiredHumanBoneName).filter((requiredBoneName) => humanBones[requiredBoneName] == null);
1769
+ // throw an error if there are missing bones
1770
+ if (missingRequiredBones.length > 0) {
1771
+ throw new Error(`VRMHumanoidLoaderPlugin: These humanoid bones are required but not exist: ${missingRequiredBones.join(', ')}`);
1772
+ }
1773
+ return humanBones;
1774
+ }
1775
1775
  }
1776
1776
 
1777
- class FanBufferGeometry extends THREE__namespace.BufferGeometry {
1778
- constructor() {
1779
- super();
1780
- this._currentTheta = 0;
1781
- this._currentRadius = 0;
1782
- this.theta = 0.0;
1783
- this.radius = 0.0;
1784
- this._currentTheta = 0.0;
1785
- this._currentRadius = 0.0;
1786
- this._attrPos = new THREE__namespace.BufferAttribute(new Float32Array(65 * 3), 3);
1787
- this.setAttribute('position', this._attrPos);
1788
- this._attrIndex = new THREE__namespace.BufferAttribute(new Uint16Array(3 * 63), 1);
1789
- this.setIndex(this._attrIndex);
1790
- this._buildIndex();
1791
- this.update();
1792
- }
1793
- update() {
1794
- let shouldUpdateGeometry = false;
1795
- if (this._currentTheta !== this.theta) {
1796
- this._currentTheta = this.theta;
1797
- shouldUpdateGeometry = true;
1798
- }
1799
- if (this._currentRadius !== this.radius) {
1800
- this._currentRadius = this.radius;
1801
- shouldUpdateGeometry = true;
1802
- }
1803
- if (shouldUpdateGeometry) {
1804
- this._buildPosition();
1805
- }
1806
- }
1807
- _buildPosition() {
1808
- this._attrPos.setXYZ(0, 0.0, 0.0, 0.0);
1809
- for (let i = 0; i < 64; i++) {
1810
- const t = (i / 63.0) * this._currentTheta;
1811
- this._attrPos.setXYZ(i + 1, this._currentRadius * Math.sin(t), 0.0, this._currentRadius * Math.cos(t));
1812
- }
1813
- this._attrPos.needsUpdate = true;
1814
- }
1815
- _buildIndex() {
1816
- for (let i = 0; i < 63; i++) {
1817
- this._attrIndex.setXYZ(i * 3, 0, i + 1, i + 2);
1818
- }
1819
- this._attrIndex.needsUpdate = true;
1820
- }
1777
+ class FanBufferGeometry extends THREE__namespace.BufferGeometry {
1778
+ constructor() {
1779
+ super();
1780
+ this._currentTheta = 0;
1781
+ this._currentRadius = 0;
1782
+ this.theta = 0.0;
1783
+ this.radius = 0.0;
1784
+ this._currentTheta = 0.0;
1785
+ this._currentRadius = 0.0;
1786
+ this._attrPos = new THREE__namespace.BufferAttribute(new Float32Array(65 * 3), 3);
1787
+ this.setAttribute('position', this._attrPos);
1788
+ this._attrIndex = new THREE__namespace.BufferAttribute(new Uint16Array(3 * 63), 1);
1789
+ this.setIndex(this._attrIndex);
1790
+ this._buildIndex();
1791
+ this.update();
1792
+ }
1793
+ update() {
1794
+ let shouldUpdateGeometry = false;
1795
+ if (this._currentTheta !== this.theta) {
1796
+ this._currentTheta = this.theta;
1797
+ shouldUpdateGeometry = true;
1798
+ }
1799
+ if (this._currentRadius !== this.radius) {
1800
+ this._currentRadius = this.radius;
1801
+ shouldUpdateGeometry = true;
1802
+ }
1803
+ if (shouldUpdateGeometry) {
1804
+ this._buildPosition();
1805
+ }
1806
+ }
1807
+ _buildPosition() {
1808
+ this._attrPos.setXYZ(0, 0.0, 0.0, 0.0);
1809
+ for (let i = 0; i < 64; i++) {
1810
+ const t = (i / 63.0) * this._currentTheta;
1811
+ this._attrPos.setXYZ(i + 1, this._currentRadius * Math.sin(t), 0.0, this._currentRadius * Math.cos(t));
1812
+ }
1813
+ this._attrPos.needsUpdate = true;
1814
+ }
1815
+ _buildIndex() {
1816
+ for (let i = 0; i < 63; i++) {
1817
+ this._attrIndex.setXYZ(i * 3, 0, i + 1, i + 2);
1818
+ }
1819
+ this._attrIndex.needsUpdate = true;
1820
+ }
1821
1821
  }
1822
1822
 
1823
- class LineAndSphereBufferGeometry extends THREE__namespace.BufferGeometry {
1824
- constructor() {
1825
- super();
1826
- this.radius = 0.0;
1827
- this._currentRadius = 0.0;
1828
- this.tail = new THREE__namespace.Vector3();
1829
- this._currentTail = new THREE__namespace.Vector3();
1830
- this._attrPos = new THREE__namespace.BufferAttribute(new Float32Array(294), 3);
1831
- this.setAttribute('position', this._attrPos);
1832
- this._attrIndex = new THREE__namespace.BufferAttribute(new Uint16Array(194), 1);
1833
- this.setIndex(this._attrIndex);
1834
- this._buildIndex();
1835
- this.update();
1836
- }
1837
- update() {
1838
- let shouldUpdateGeometry = false;
1839
- if (this._currentRadius !== this.radius) {
1840
- this._currentRadius = this.radius;
1841
- shouldUpdateGeometry = true;
1842
- }
1843
- if (!this._currentTail.equals(this.tail)) {
1844
- this._currentTail.copy(this.tail);
1845
- shouldUpdateGeometry = true;
1846
- }
1847
- if (shouldUpdateGeometry) {
1848
- this._buildPosition();
1849
- }
1850
- }
1851
- _buildPosition() {
1852
- for (let i = 0; i < 32; i++) {
1853
- const t = (i / 16.0) * Math.PI;
1854
- this._attrPos.setXYZ(i, Math.cos(t), Math.sin(t), 0.0);
1855
- this._attrPos.setXYZ(32 + i, 0.0, Math.cos(t), Math.sin(t));
1856
- this._attrPos.setXYZ(64 + i, Math.sin(t), 0.0, Math.cos(t));
1857
- }
1858
- this.scale(this._currentRadius, this._currentRadius, this._currentRadius);
1859
- this.translate(this._currentTail.x, this._currentTail.y, this._currentTail.z);
1860
- this._attrPos.setXYZ(96, 0, 0, 0);
1861
- this._attrPos.setXYZ(97, this._currentTail.x, this._currentTail.y, this._currentTail.z);
1862
- this._attrPos.needsUpdate = true;
1863
- }
1864
- _buildIndex() {
1865
- for (let i = 0; i < 32; i++) {
1866
- const i1 = (i + 1) % 32;
1867
- this._attrIndex.setXY(i * 2, i, i1);
1868
- this._attrIndex.setXY(64 + i * 2, 32 + i, 32 + i1);
1869
- this._attrIndex.setXY(128 + i * 2, 64 + i, 64 + i1);
1870
- }
1871
- this._attrIndex.setXY(192, 96, 97);
1872
- this._attrIndex.needsUpdate = true;
1873
- }
1823
+ class LineAndSphereBufferGeometry extends THREE__namespace.BufferGeometry {
1824
+ constructor() {
1825
+ super();
1826
+ this.radius = 0.0;
1827
+ this._currentRadius = 0.0;
1828
+ this.tail = new THREE__namespace.Vector3();
1829
+ this._currentTail = new THREE__namespace.Vector3();
1830
+ this._attrPos = new THREE__namespace.BufferAttribute(new Float32Array(294), 3);
1831
+ this.setAttribute('position', this._attrPos);
1832
+ this._attrIndex = new THREE__namespace.BufferAttribute(new Uint16Array(194), 1);
1833
+ this.setIndex(this._attrIndex);
1834
+ this._buildIndex();
1835
+ this.update();
1836
+ }
1837
+ update() {
1838
+ let shouldUpdateGeometry = false;
1839
+ if (this._currentRadius !== this.radius) {
1840
+ this._currentRadius = this.radius;
1841
+ shouldUpdateGeometry = true;
1842
+ }
1843
+ if (!this._currentTail.equals(this.tail)) {
1844
+ this._currentTail.copy(this.tail);
1845
+ shouldUpdateGeometry = true;
1846
+ }
1847
+ if (shouldUpdateGeometry) {
1848
+ this._buildPosition();
1849
+ }
1850
+ }
1851
+ _buildPosition() {
1852
+ for (let i = 0; i < 32; i++) {
1853
+ const t = (i / 16.0) * Math.PI;
1854
+ this._attrPos.setXYZ(i, Math.cos(t), Math.sin(t), 0.0);
1855
+ this._attrPos.setXYZ(32 + i, 0.0, Math.cos(t), Math.sin(t));
1856
+ this._attrPos.setXYZ(64 + i, Math.sin(t), 0.0, Math.cos(t));
1857
+ }
1858
+ this.scale(this._currentRadius, this._currentRadius, this._currentRadius);
1859
+ this.translate(this._currentTail.x, this._currentTail.y, this._currentTail.z);
1860
+ this._attrPos.setXYZ(96, 0, 0, 0);
1861
+ this._attrPos.setXYZ(97, this._currentTail.x, this._currentTail.y, this._currentTail.z);
1862
+ this._attrPos.needsUpdate = true;
1863
+ }
1864
+ _buildIndex() {
1865
+ for (let i = 0; i < 32; i++) {
1866
+ const i1 = (i + 1) % 32;
1867
+ this._attrIndex.setXY(i * 2, i, i1);
1868
+ this._attrIndex.setXY(64 + i * 2, 32 + i, 32 + i1);
1869
+ this._attrIndex.setXY(128 + i * 2, 64 + i, 64 + i1);
1870
+ }
1871
+ this._attrIndex.setXY(192, 96, 97);
1872
+ this._attrIndex.needsUpdate = true;
1873
+ }
1874
1874
  }
1875
1875
 
1876
- const _quatA$1 = new THREE__namespace.Quaternion();
1877
- const _quatB$1 = new THREE__namespace.Quaternion();
1878
- const _v3A$1 = new THREE__namespace.Vector3();
1879
- const _v3B$1 = new THREE__namespace.Vector3();
1880
- const SQRT_2_OVER_2 = Math.sqrt(2.0) / 2.0;
1881
- const QUAT_XY_CW90 = new THREE__namespace.Quaternion(0, 0, -SQRT_2_OVER_2, SQRT_2_OVER_2);
1882
- const VEC3_POSITIVE_Y = new THREE__namespace.Vector3(0.0, 1.0, 0.0);
1883
- class VRMLookAtHelper extends THREE__namespace.Group {
1884
- constructor(lookAt) {
1885
- super();
1886
- this.matrixAutoUpdate = false;
1887
- this.vrmLookAt = lookAt;
1888
- {
1889
- const geometry = new FanBufferGeometry();
1890
- geometry.radius = 0.5;
1891
- const material = new THREE__namespace.MeshBasicMaterial({
1892
- color: 0x00ff00,
1893
- transparent: true,
1894
- opacity: 0.5,
1895
- side: THREE__namespace.DoubleSide,
1896
- depthTest: false,
1897
- depthWrite: false,
1898
- });
1899
- this._meshPitch = new THREE__namespace.Mesh(geometry, material);
1900
- this.add(this._meshPitch);
1901
- }
1902
- {
1903
- const geometry = new FanBufferGeometry();
1904
- geometry.radius = 0.5;
1905
- const material = new THREE__namespace.MeshBasicMaterial({
1906
- color: 0xff0000,
1907
- transparent: true,
1908
- opacity: 0.5,
1909
- side: THREE__namespace.DoubleSide,
1910
- depthTest: false,
1911
- depthWrite: false,
1912
- });
1913
- this._meshYaw = new THREE__namespace.Mesh(geometry, material);
1914
- this.add(this._meshYaw);
1915
- }
1916
- {
1917
- const geometry = new LineAndSphereBufferGeometry();
1918
- geometry.radius = 0.1;
1919
- const material = new THREE__namespace.LineBasicMaterial({
1920
- color: 0xffffff,
1921
- depthTest: false,
1922
- depthWrite: false,
1923
- });
1924
- this._lineTarget = new THREE__namespace.LineSegments(geometry, material);
1925
- this._lineTarget.frustumCulled = false;
1926
- this.add(this._lineTarget);
1927
- }
1928
- }
1929
- dispose() {
1930
- this._meshYaw.geometry.dispose();
1931
- this._meshYaw.material.dispose();
1932
- this._meshPitch.geometry.dispose();
1933
- this._meshPitch.material.dispose();
1934
- this._lineTarget.geometry.dispose();
1935
- this._lineTarget.material.dispose();
1936
- }
1937
- updateMatrixWorld(force) {
1938
- this.vrmLookAt.getLookAtWorldPosition(_v3A$1);
1939
- this.vrmLookAt.getLookAtWorldQuaternion(_quatA$1);
1940
- const yaw = this.vrmLookAt.euler.y;
1941
- const pitch = this.vrmLookAt.euler.x;
1942
- this._meshYaw.geometry.theta = yaw;
1943
- this._meshYaw.geometry.update();
1944
- this._meshYaw.position.copy(_v3A$1);
1945
- this._meshYaw.quaternion.copy(_quatA$1);
1946
- this._meshPitch.geometry.theta = pitch;
1947
- this._meshPitch.geometry.update();
1948
- this._meshPitch.position.copy(_v3A$1);
1949
- this._meshPitch.quaternion.copy(_quatA$1);
1950
- this._meshPitch.quaternion.multiply(_quatB$1.setFromAxisAngle(VEC3_POSITIVE_Y, yaw));
1951
- this._meshPitch.quaternion.multiply(QUAT_XY_CW90);
1952
- const target = this.vrmLookAt.target;
1953
- if (target != null) {
1954
- target.getWorldPosition(_v3B$1).sub(_v3A$1);
1955
- this._lineTarget.geometry.tail.copy(_v3B$1);
1956
- this._lineTarget.geometry.update();
1957
- this._lineTarget.position.copy(_v3A$1);
1958
- }
1959
- super.updateMatrixWorld(force);
1960
- }
1876
+ const _quatA$1 = new THREE__namespace.Quaternion();
1877
+ const _quatB$1 = new THREE__namespace.Quaternion();
1878
+ const _v3A$1 = new THREE__namespace.Vector3();
1879
+ const _v3B$1 = new THREE__namespace.Vector3();
1880
+ const SQRT_2_OVER_2 = Math.sqrt(2.0) / 2.0;
1881
+ const QUAT_XY_CW90 = new THREE__namespace.Quaternion(0, 0, -SQRT_2_OVER_2, SQRT_2_OVER_2);
1882
+ const VEC3_POSITIVE_Y = new THREE__namespace.Vector3(0.0, 1.0, 0.0);
1883
+ class VRMLookAtHelper extends THREE__namespace.Group {
1884
+ constructor(lookAt) {
1885
+ super();
1886
+ this.matrixAutoUpdate = false;
1887
+ this.vrmLookAt = lookAt;
1888
+ {
1889
+ const geometry = new FanBufferGeometry();
1890
+ geometry.radius = 0.5;
1891
+ const material = new THREE__namespace.MeshBasicMaterial({
1892
+ color: 0x00ff00,
1893
+ transparent: true,
1894
+ opacity: 0.5,
1895
+ side: THREE__namespace.DoubleSide,
1896
+ depthTest: false,
1897
+ depthWrite: false,
1898
+ });
1899
+ this._meshPitch = new THREE__namespace.Mesh(geometry, material);
1900
+ this.add(this._meshPitch);
1901
+ }
1902
+ {
1903
+ const geometry = new FanBufferGeometry();
1904
+ geometry.radius = 0.5;
1905
+ const material = new THREE__namespace.MeshBasicMaterial({
1906
+ color: 0xff0000,
1907
+ transparent: true,
1908
+ opacity: 0.5,
1909
+ side: THREE__namespace.DoubleSide,
1910
+ depthTest: false,
1911
+ depthWrite: false,
1912
+ });
1913
+ this._meshYaw = new THREE__namespace.Mesh(geometry, material);
1914
+ this.add(this._meshYaw);
1915
+ }
1916
+ {
1917
+ const geometry = new LineAndSphereBufferGeometry();
1918
+ geometry.radius = 0.1;
1919
+ const material = new THREE__namespace.LineBasicMaterial({
1920
+ color: 0xffffff,
1921
+ depthTest: false,
1922
+ depthWrite: false,
1923
+ });
1924
+ this._lineTarget = new THREE__namespace.LineSegments(geometry, material);
1925
+ this._lineTarget.frustumCulled = false;
1926
+ this.add(this._lineTarget);
1927
+ }
1928
+ }
1929
+ dispose() {
1930
+ this._meshYaw.geometry.dispose();
1931
+ this._meshYaw.material.dispose();
1932
+ this._meshPitch.geometry.dispose();
1933
+ this._meshPitch.material.dispose();
1934
+ this._lineTarget.geometry.dispose();
1935
+ this._lineTarget.material.dispose();
1936
+ }
1937
+ updateMatrixWorld(force) {
1938
+ this.vrmLookAt.getLookAtWorldPosition(_v3A$1);
1939
+ this.vrmLookAt.getLookAtWorldQuaternion(_quatA$1);
1940
+ const yaw = this.vrmLookAt.euler.y;
1941
+ const pitch = this.vrmLookAt.euler.x;
1942
+ this._meshYaw.geometry.theta = yaw;
1943
+ this._meshYaw.geometry.update();
1944
+ this._meshYaw.position.copy(_v3A$1);
1945
+ this._meshYaw.quaternion.copy(_quatA$1);
1946
+ this._meshPitch.geometry.theta = pitch;
1947
+ this._meshPitch.geometry.update();
1948
+ this._meshPitch.position.copy(_v3A$1);
1949
+ this._meshPitch.quaternion.copy(_quatA$1);
1950
+ this._meshPitch.quaternion.multiply(_quatB$1.setFromAxisAngle(VEC3_POSITIVE_Y, yaw));
1951
+ this._meshPitch.quaternion.multiply(QUAT_XY_CW90);
1952
+ const target = this.vrmLookAt.target;
1953
+ if (target != null) {
1954
+ target.getWorldPosition(_v3B$1).sub(_v3A$1);
1955
+ this._lineTarget.geometry.tail.copy(_v3B$1);
1956
+ this._lineTarget.geometry.update();
1957
+ this._lineTarget.position.copy(_v3A$1);
1958
+ }
1959
+ super.updateMatrixWorld(force);
1960
+ }
1961
1961
  }
1962
1962
 
1963
- const _position = new THREE__namespace.Vector3();
1964
- const _scale = new THREE__namespace.Vector3();
1965
- /**
1966
- * Extract world rotation of an object from its world space matrix, in cheaper way.
1967
- *
1968
- * @param object The object
1969
- * @param out Target vector
1970
- */
1971
- function getWorldQuaternionLite(object, out) {
1972
- object.matrixWorld.decompose(_position, out, _scale);
1973
- return out;
1963
+ const _position = new THREE__namespace.Vector3();
1964
+ const _scale = new THREE__namespace.Vector3();
1965
+ /**
1966
+ * Extract world rotation of an object from its world space matrix, in cheaper way.
1967
+ *
1968
+ * @param object The object
1969
+ * @param out Target vector
1970
+ */
1971
+ function getWorldQuaternionLite(object, out) {
1972
+ object.matrixWorld.decompose(_position, out, _scale);
1973
+ return out;
1974
1974
  }
1975
1975
 
1976
- const _v3A = new THREE__namespace.Vector3();
1977
- const _v3B = new THREE__namespace.Vector3();
1978
- const _v3C = new THREE__namespace.Vector3();
1979
- const _quatA = new THREE__namespace.Quaternion();
1980
- const _quatB = new THREE__namespace.Quaternion();
1981
- /**
1982
- * A class controls eye gaze movements of a VRM.
1983
- */
1984
- class VRMLookAt {
1985
- /**
1986
- * Create a new {@link VRMLookAt}.
1987
- *
1988
- * @param humanoid A {@link VRMHumanoid}
1989
- * @param applier A {@link VRMLookAtApplier}
1990
- */
1991
- constructor(humanoid, applier) {
1992
- /**
1993
- * The origin of LookAt. Position offset from the head bone.
1994
- */
1995
- this.offsetFromHeadBone = new THREE__namespace.Vector3();
1996
- /**
1997
- * If this is true, the LookAt will be updated automatically by calling {@link update}, towarding the direction to the {@link target}.
1998
- * `true` by default.
1999
- *
2000
- * See also: {@link target}
2001
- */
2002
- this.autoUpdate = true;
2003
- /**
2004
- * The front direction of the face.
2005
- * Intended to be used for VRM 0.0 compat (VRM 0.0 models are facing Z- instead of Z+).
2006
- * You usually don't want to touch this.
2007
- */
2008
- this.faceFront = new THREE__namespace.Vector3(0.0, 0.0, 1.0);
2009
- this._euler = new THREE__namespace.Euler(0.0, 0.0, 0.0, VRMLookAt.EULER_ORDER);
2010
- this.humanoid = humanoid;
2011
- this.applier = applier;
2012
- }
2013
- /**
2014
- * Its current euler direction.
2015
- */
2016
- get euler() {
2017
- return this._euler.clone();
2018
- }
2019
- /**
2020
- * Copy the given {@link VRMLookAt} into this one.
2021
- * {@link humanoid} must be same as the source one.
2022
- * {@link applier} will reference the same instance as the source one.
2023
- * @param source The {@link VRMLookAt} you want to copy
2024
- * @returns this
2025
- */
2026
- copy(source) {
2027
- if (this.humanoid !== source.humanoid) {
2028
- throw new Error('VRMLookAt: humanoid must be same in order to copy');
2029
- }
2030
- this.offsetFromHeadBone.copy(source.offsetFromHeadBone);
2031
- this.applier = source.applier;
2032
- this.autoUpdate = source.autoUpdate;
2033
- this.target = source.target;
2034
- this.faceFront.copy(source.faceFront);
2035
- return this;
2036
- }
2037
- /**
2038
- * Returns a clone of this {@link VRMLookAt}.
2039
- * Note that {@link humanoid} and {@link applier} will reference the same instance as this one.
2040
- * @returns Copied {@link VRMLookAt}
2041
- */
2042
- clone() {
2043
- return new VRMLookAt(this.humanoid, this.applier).copy(this);
2044
- }
2045
- /**
2046
- * Reset the lookAt direction to initial direction.
2047
- */
2048
- reset() {
2049
- this._euler.set(0.0, 0.0, 0.0);
2050
- this.applier.lookAt(this._euler);
2051
- }
2052
- /**
2053
- * Get its head position in world coordinate.
2054
- *
2055
- * @param target A target `THREE.Vector3`
2056
- */
2057
- getLookAtWorldPosition(target) {
2058
- const head = this.humanoid.getBoneNode('head');
2059
- return target.copy(this.offsetFromHeadBone).applyMatrix4(head.matrixWorld);
2060
- }
2061
- /**
2062
- * Get its LookAt orientation in world coordinate.
2063
- *
2064
- * @param target A target `THREE.Vector3`
2065
- */
2066
- getLookAtWorldQuaternion(target) {
2067
- const head = this.humanoid.getBoneNode('head');
2068
- return getWorldQuaternionLite(head, target);
2069
- }
2070
- /**
2071
- * Get its LookAt direction in world coordinate.
2072
- *
2073
- * @param target A target `THREE.Vector3`
2074
- */
2075
- getLookAtWorldDirection(target) {
2076
- this.getLookAtWorldQuaternion(_quatA);
2077
- return target.copy(this.faceFront).applyEuler(this._euler).applyQuaternion(_quatA);
2078
- }
2079
- /**
2080
- * Set its LookAt position.
2081
- * Note that its result will be instantly overwritten if {@link VRMLookAtHead.autoUpdate} is enabled.
2082
- *
2083
- * @param position A target position
2084
- */
2085
- lookAt(position) {
2086
- this._calcEuler(this._euler, position);
2087
- this.applier.lookAt(this._euler);
2088
- }
2089
- /**
2090
- * Update the VRMLookAtHead.
2091
- * If {@link VRMLookAtHead.autoUpdate} is disabled, it will do nothing.
2092
- *
2093
- * @param delta deltaTime, it isn't used though. You can use the parameter if you want to use this in your own extended {@link VRMLookAt}.
2094
- */
2095
- update(delta) {
2096
- if (this.target && this.autoUpdate) {
2097
- this.lookAt(this.target.getWorldPosition(_v3A));
2098
- this.applier.lookAt(this._euler);
2099
- }
2100
- }
2101
- _calcEuler(target, position) {
2102
- // Look at direction in local coordinate
2103
- const headRotInv = quatInvertCompat(this.getLookAtWorldQuaternion(_quatA));
2104
- const headPos = this.getLookAtWorldPosition(_v3B);
2105
- const lookAtDir = _v3C.copy(position).sub(headPos).applyQuaternion(headRotInv).normalize();
2106
- // calculate the rotation
2107
- const rotLocal = _quatB.setFromUnitVectors(this.faceFront, lookAtDir);
2108
- // Transform the direction into local coordinate from the first person bone
2109
- _v3C.set(0.0, 0.0, 1.0).applyQuaternion(rotLocal);
2110
- // convert the direction into euler
2111
- target.x = Math.atan2(-_v3C.y, Math.sqrt(_v3C.x * _v3C.x + _v3C.z * _v3C.z));
2112
- target.y = Math.atan2(_v3C.x, _v3C.z);
2113
- return target;
2114
- }
2115
- }
1976
+ const _v3A = new THREE__namespace.Vector3();
1977
+ const _v3B = new THREE__namespace.Vector3();
1978
+ const _v3C = new THREE__namespace.Vector3();
1979
+ const _quatA = new THREE__namespace.Quaternion();
1980
+ const _quatB = new THREE__namespace.Quaternion();
1981
+ /**
1982
+ * A class controls eye gaze movements of a VRM.
1983
+ */
1984
+ class VRMLookAt {
1985
+ /**
1986
+ * Create a new {@link VRMLookAt}.
1987
+ *
1988
+ * @param humanoid A {@link VRMHumanoid}
1989
+ * @param applier A {@link VRMLookAtApplier}
1990
+ */
1991
+ constructor(humanoid, applier) {
1992
+ /**
1993
+ * The origin of LookAt. Position offset from the head bone.
1994
+ */
1995
+ this.offsetFromHeadBone = new THREE__namespace.Vector3();
1996
+ /**
1997
+ * If this is true, the LookAt will be updated automatically by calling {@link update}, towarding the direction to the {@link target}.
1998
+ * `true` by default.
1999
+ *
2000
+ * See also: {@link target}
2001
+ */
2002
+ this.autoUpdate = true;
2003
+ /**
2004
+ * The front direction of the face.
2005
+ * Intended to be used for VRM 0.0 compat (VRM 0.0 models are facing Z- instead of Z+).
2006
+ * You usually don't want to touch this.
2007
+ */
2008
+ this.faceFront = new THREE__namespace.Vector3(0.0, 0.0, 1.0);
2009
+ this._euler = new THREE__namespace.Euler(0.0, 0.0, 0.0, VRMLookAt.EULER_ORDER);
2010
+ this.humanoid = humanoid;
2011
+ this.applier = applier;
2012
+ }
2013
+ /**
2014
+ * Its current euler direction.
2015
+ */
2016
+ get euler() {
2017
+ return this._euler.clone();
2018
+ }
2019
+ /**
2020
+ * Copy the given {@link VRMLookAt} into this one.
2021
+ * {@link humanoid} must be same as the source one.
2022
+ * {@link applier} will reference the same instance as the source one.
2023
+ * @param source The {@link VRMLookAt} you want to copy
2024
+ * @returns this
2025
+ */
2026
+ copy(source) {
2027
+ if (this.humanoid !== source.humanoid) {
2028
+ throw new Error('VRMLookAt: humanoid must be same in order to copy');
2029
+ }
2030
+ this.offsetFromHeadBone.copy(source.offsetFromHeadBone);
2031
+ this.applier = source.applier;
2032
+ this.autoUpdate = source.autoUpdate;
2033
+ this.target = source.target;
2034
+ this.faceFront.copy(source.faceFront);
2035
+ return this;
2036
+ }
2037
+ /**
2038
+ * Returns a clone of this {@link VRMLookAt}.
2039
+ * Note that {@link humanoid} and {@link applier} will reference the same instance as this one.
2040
+ * @returns Copied {@link VRMLookAt}
2041
+ */
2042
+ clone() {
2043
+ return new VRMLookAt(this.humanoid, this.applier).copy(this);
2044
+ }
2045
+ /**
2046
+ * Reset the lookAt direction to initial direction.
2047
+ */
2048
+ reset() {
2049
+ this._euler.set(0.0, 0.0, 0.0);
2050
+ this.applier.lookAt(this._euler);
2051
+ }
2052
+ /**
2053
+ * Get its head position in world coordinate.
2054
+ *
2055
+ * @param target A target `THREE.Vector3`
2056
+ */
2057
+ getLookAtWorldPosition(target) {
2058
+ const head = this.humanoid.getBoneNode('head');
2059
+ return target.copy(this.offsetFromHeadBone).applyMatrix4(head.matrixWorld);
2060
+ }
2061
+ /**
2062
+ * Get its LookAt orientation in world coordinate.
2063
+ *
2064
+ * @param target A target `THREE.Vector3`
2065
+ */
2066
+ getLookAtWorldQuaternion(target) {
2067
+ const head = this.humanoid.getBoneNode('head');
2068
+ return getWorldQuaternionLite(head, target);
2069
+ }
2070
+ /**
2071
+ * Get its LookAt direction in world coordinate.
2072
+ *
2073
+ * @param target A target `THREE.Vector3`
2074
+ */
2075
+ getLookAtWorldDirection(target) {
2076
+ this.getLookAtWorldQuaternion(_quatA);
2077
+ return target.copy(this.faceFront).applyEuler(this._euler).applyQuaternion(_quatA);
2078
+ }
2079
+ /**
2080
+ * Set its LookAt position.
2081
+ * Note that its result will be instantly overwritten if {@link VRMLookAtHead.autoUpdate} is enabled.
2082
+ *
2083
+ * @param position A target position
2084
+ */
2085
+ lookAt(position) {
2086
+ this._calcEuler(this._euler, position);
2087
+ this.applier.lookAt(this._euler);
2088
+ }
2089
+ /**
2090
+ * Update the VRMLookAtHead.
2091
+ * If {@link VRMLookAtHead.autoUpdate} is disabled, it will do nothing.
2092
+ *
2093
+ * @param delta deltaTime, it isn't used though. You can use the parameter if you want to use this in your own extended {@link VRMLookAt}.
2094
+ */
2095
+ update(delta) {
2096
+ if (this.target && this.autoUpdate) {
2097
+ this.lookAt(this.target.getWorldPosition(_v3A));
2098
+ this.applier.lookAt(this._euler);
2099
+ }
2100
+ }
2101
+ _calcEuler(target, position) {
2102
+ // Look at direction in local coordinate
2103
+ const headRotInv = quatInvertCompat(this.getLookAtWorldQuaternion(_quatA));
2104
+ const headPos = this.getLookAtWorldPosition(_v3B);
2105
+ const lookAtDir = _v3C.copy(position).sub(headPos).applyQuaternion(headRotInv).normalize();
2106
+ // calculate the rotation
2107
+ const rotLocal = _quatB.setFromUnitVectors(this.faceFront, lookAtDir);
2108
+ // Transform the direction into local coordinate from the first person bone
2109
+ _v3C.set(0.0, 0.0, 1.0).applyQuaternion(rotLocal);
2110
+ // convert the direction into euler
2111
+ target.x = Math.atan2(-_v3C.y, Math.sqrt(_v3C.x * _v3C.x + _v3C.z * _v3C.z));
2112
+ target.y = Math.atan2(_v3C.x, _v3C.z);
2113
+ return target;
2114
+ }
2115
+ }
2116
2116
  VRMLookAt.EULER_ORDER = 'YXZ'; // yaw-pitch-roll
2117
2117
 
2118
- const _eulerA = new THREE__namespace.Euler(0.0, 0.0, 0.0, 'YXZ');
2119
- /**
2120
- * A class that applies eye gaze directions to a VRM.
2121
- * It will be used by {@link VRMLookAt}.
2122
- */
2123
- class VRMLookAtBoneApplier {
2124
- /**
2125
- * Create a new {@link VRMLookAtBoneApplier}.
2126
- *
2127
- * @param humanoid A {@link VRMHumanoid}
2128
- * @param rangeMapHorizontalInner A {@link VRMLookAtRangeMap} used for inner transverse direction
2129
- * @param rangeMapHorizontalOuter A {@link VRMLookAtRangeMap} used for outer transverse direction
2130
- * @param rangeMapVerticalDown A {@link VRMLookAtRangeMap} used for down direction
2131
- * @param rangeMapVerticalUp A {@link VRMLookAtRangeMap} used for up direction
2132
- */
2133
- constructor(humanoid, rangeMapHorizontalInner, rangeMapHorizontalOuter, rangeMapVerticalDown, rangeMapVerticalUp) {
2134
- this.humanoid = humanoid;
2135
- this.rangeMapHorizontalInner = rangeMapHorizontalInner;
2136
- this.rangeMapHorizontalOuter = rangeMapHorizontalOuter;
2137
- this.rangeMapVerticalDown = rangeMapVerticalDown;
2138
- this.rangeMapVerticalUp = rangeMapVerticalUp;
2139
- }
2140
- /**
2141
- * Apply the input angle to its associated VRM model.
2142
- *
2143
- * @param angle An input angle
2144
- */
2145
- lookAt(angle) {
2146
- const srcX = (angle.x * 180.0) / Math.PI;
2147
- const srcY = (angle.y * 180.0) / Math.PI;
2148
- const leftEye = this.humanoid.getBoneNode('leftEye');
2149
- const rightEye = this.humanoid.getBoneNode('rightEye');
2150
- // left
2151
- if (leftEye) {
2152
- if (srcX < 0.0) {
2153
- _eulerA.x = (-this.rangeMapVerticalDown.map(-srcX) / 180.0) * Math.PI;
2154
- }
2155
- else {
2156
- _eulerA.x = (this.rangeMapVerticalUp.map(srcX) / 180.0) * Math.PI;
2157
- }
2158
- if (srcY < 0.0) {
2159
- _eulerA.y = (-this.rangeMapHorizontalInner.map(-srcY) / 180.0) * Math.PI;
2160
- }
2161
- else {
2162
- _eulerA.y = (this.rangeMapHorizontalOuter.map(srcY) / 180.0) * Math.PI;
2163
- }
2164
- leftEye.quaternion.setFromEuler(_eulerA);
2165
- }
2166
- // right
2167
- if (rightEye) {
2168
- if (srcX < 0.0) {
2169
- _eulerA.x = (-this.rangeMapVerticalDown.map(-srcX) / 180.0) * Math.PI;
2170
- }
2171
- else {
2172
- _eulerA.x = (this.rangeMapVerticalUp.map(srcX) / 180.0) * Math.PI;
2173
- }
2174
- if (srcY < 0.0) {
2175
- _eulerA.y = (-this.rangeMapHorizontalOuter.map(-srcY) / 180.0) * Math.PI;
2176
- }
2177
- else {
2178
- _eulerA.y = (this.rangeMapHorizontalInner.map(srcY) / 180.0) * Math.PI;
2179
- }
2180
- rightEye.quaternion.setFromEuler(_eulerA);
2181
- }
2182
- }
2183
- }
2184
- /**
2185
- * Represent its type of applier.
2186
- */
2118
+ const _eulerA = new THREE__namespace.Euler(0.0, 0.0, 0.0, 'YXZ');
2119
+ /**
2120
+ * A class that applies eye gaze directions to a VRM.
2121
+ * It will be used by {@link VRMLookAt}.
2122
+ */
2123
+ class VRMLookAtBoneApplier {
2124
+ /**
2125
+ * Create a new {@link VRMLookAtBoneApplier}.
2126
+ *
2127
+ * @param humanoid A {@link VRMHumanoid}
2128
+ * @param rangeMapHorizontalInner A {@link VRMLookAtRangeMap} used for inner transverse direction
2129
+ * @param rangeMapHorizontalOuter A {@link VRMLookAtRangeMap} used for outer transverse direction
2130
+ * @param rangeMapVerticalDown A {@link VRMLookAtRangeMap} used for down direction
2131
+ * @param rangeMapVerticalUp A {@link VRMLookAtRangeMap} used for up direction
2132
+ */
2133
+ constructor(humanoid, rangeMapHorizontalInner, rangeMapHorizontalOuter, rangeMapVerticalDown, rangeMapVerticalUp) {
2134
+ this.humanoid = humanoid;
2135
+ this.rangeMapHorizontalInner = rangeMapHorizontalInner;
2136
+ this.rangeMapHorizontalOuter = rangeMapHorizontalOuter;
2137
+ this.rangeMapVerticalDown = rangeMapVerticalDown;
2138
+ this.rangeMapVerticalUp = rangeMapVerticalUp;
2139
+ }
2140
+ /**
2141
+ * Apply the input angle to its associated VRM model.
2142
+ *
2143
+ * @param angle An input angle
2144
+ */
2145
+ lookAt(angle) {
2146
+ const srcX = (angle.x * 180.0) / Math.PI;
2147
+ const srcY = (angle.y * 180.0) / Math.PI;
2148
+ const leftEye = this.humanoid.getBoneNode('leftEye');
2149
+ const rightEye = this.humanoid.getBoneNode('rightEye');
2150
+ // left
2151
+ if (leftEye) {
2152
+ if (srcX < 0.0) {
2153
+ _eulerA.x = (-this.rangeMapVerticalDown.map(-srcX) / 180.0) * Math.PI;
2154
+ }
2155
+ else {
2156
+ _eulerA.x = (this.rangeMapVerticalUp.map(srcX) / 180.0) * Math.PI;
2157
+ }
2158
+ if (srcY < 0.0) {
2159
+ _eulerA.y = (-this.rangeMapHorizontalInner.map(-srcY) / 180.0) * Math.PI;
2160
+ }
2161
+ else {
2162
+ _eulerA.y = (this.rangeMapHorizontalOuter.map(srcY) / 180.0) * Math.PI;
2163
+ }
2164
+ leftEye.quaternion.setFromEuler(_eulerA);
2165
+ }
2166
+ // right
2167
+ if (rightEye) {
2168
+ if (srcX < 0.0) {
2169
+ _eulerA.x = (-this.rangeMapVerticalDown.map(-srcX) / 180.0) * Math.PI;
2170
+ }
2171
+ else {
2172
+ _eulerA.x = (this.rangeMapVerticalUp.map(srcX) / 180.0) * Math.PI;
2173
+ }
2174
+ if (srcY < 0.0) {
2175
+ _eulerA.y = (-this.rangeMapHorizontalOuter.map(-srcY) / 180.0) * Math.PI;
2176
+ }
2177
+ else {
2178
+ _eulerA.y = (this.rangeMapHorizontalInner.map(srcY) / 180.0) * Math.PI;
2179
+ }
2180
+ rightEye.quaternion.setFromEuler(_eulerA);
2181
+ }
2182
+ }
2183
+ }
2184
+ /**
2185
+ * Represent its type of applier.
2186
+ */
2187
2187
  VRMLookAtBoneApplier.type = 'bone';
2188
2188
 
2189
- /**
2190
- * A class that applies eye gaze directions to a VRM.
2191
- * It will be used by {@link VRMLookAt}.
2192
- */
2193
- class VRMLookAtExpressionApplier {
2194
- /**
2195
- * Create a new {@link VRMLookAtExpressionApplier}.
2196
- *
2197
- * @param expressions A {@link VRMExpressionManager}
2198
- * @param rangeMapHorizontalInner A {@link VRMLookAtRangeMap} used for inner transverse direction
2199
- * @param rangeMapHorizontalOuter A {@link VRMLookAtRangeMap} used for outer transverse direction
2200
- * @param rangeMapVerticalDown A {@link VRMLookAtRangeMap} used for down direction
2201
- * @param rangeMapVerticalUp A {@link VRMLookAtRangeMap} used for up direction
2202
- */
2203
- constructor(expressions, rangeMapHorizontalInner, rangeMapHorizontalOuter, rangeMapVerticalDown, rangeMapVerticalUp) {
2204
- this.expressions = expressions;
2205
- this.rangeMapHorizontalInner = rangeMapHorizontalInner;
2206
- this.rangeMapHorizontalOuter = rangeMapHorizontalOuter;
2207
- this.rangeMapVerticalDown = rangeMapVerticalDown;
2208
- this.rangeMapVerticalUp = rangeMapVerticalUp;
2209
- }
2210
- /**
2211
- * Apply the input angle to its associated VRM model.
2212
- *
2213
- * @param angle An input angle
2214
- */
2215
- lookAt(angle) {
2216
- const srcX = (angle.x * 180.0) / Math.PI;
2217
- const srcY = (angle.y * 180.0) / Math.PI;
2218
- if (srcX < 0.0) {
2219
- this.expressions.setValue('lookDown', 0.0);
2220
- this.expressions.setValue('lookUp', this.rangeMapVerticalUp.map(-srcX));
2221
- }
2222
- else {
2223
- this.expressions.setValue('lookUp', 0.0);
2224
- this.expressions.setValue('lookDown', this.rangeMapVerticalDown.map(srcX));
2225
- }
2226
- if (srcY < 0.0) {
2227
- this.expressions.setValue('lookLeft', 0.0);
2228
- this.expressions.setValue('lookRight', this.rangeMapHorizontalOuter.map(-srcY));
2229
- }
2230
- else {
2231
- this.expressions.setValue('lookRight', 0.0);
2232
- this.expressions.setValue('lookLeft', this.rangeMapHorizontalOuter.map(srcY));
2233
- }
2234
- }
2235
- }
2236
- /**
2237
- * Represent its type of applier.
2238
- */
2189
+ /**
2190
+ * A class that applies eye gaze directions to a VRM.
2191
+ * It will be used by {@link VRMLookAt}.
2192
+ */
2193
+ class VRMLookAtExpressionApplier {
2194
+ /**
2195
+ * Create a new {@link VRMLookAtExpressionApplier}.
2196
+ *
2197
+ * @param expressions A {@link VRMExpressionManager}
2198
+ * @param rangeMapHorizontalInner A {@link VRMLookAtRangeMap} used for inner transverse direction
2199
+ * @param rangeMapHorizontalOuter A {@link VRMLookAtRangeMap} used for outer transverse direction
2200
+ * @param rangeMapVerticalDown A {@link VRMLookAtRangeMap} used for down direction
2201
+ * @param rangeMapVerticalUp A {@link VRMLookAtRangeMap} used for up direction
2202
+ */
2203
+ constructor(expressions, rangeMapHorizontalInner, rangeMapHorizontalOuter, rangeMapVerticalDown, rangeMapVerticalUp) {
2204
+ this.expressions = expressions;
2205
+ this.rangeMapHorizontalInner = rangeMapHorizontalInner;
2206
+ this.rangeMapHorizontalOuter = rangeMapHorizontalOuter;
2207
+ this.rangeMapVerticalDown = rangeMapVerticalDown;
2208
+ this.rangeMapVerticalUp = rangeMapVerticalUp;
2209
+ }
2210
+ /**
2211
+ * Apply the input angle to its associated VRM model.
2212
+ *
2213
+ * @param angle An input angle
2214
+ */
2215
+ lookAt(angle) {
2216
+ const srcX = (angle.x * 180.0) / Math.PI;
2217
+ const srcY = (angle.y * 180.0) / Math.PI;
2218
+ if (srcX < 0.0) {
2219
+ this.expressions.setValue('lookDown', 0.0);
2220
+ this.expressions.setValue('lookUp', this.rangeMapVerticalUp.map(-srcX));
2221
+ }
2222
+ else {
2223
+ this.expressions.setValue('lookUp', 0.0);
2224
+ this.expressions.setValue('lookDown', this.rangeMapVerticalDown.map(srcX));
2225
+ }
2226
+ if (srcY < 0.0) {
2227
+ this.expressions.setValue('lookLeft', 0.0);
2228
+ this.expressions.setValue('lookRight', this.rangeMapHorizontalOuter.map(-srcY));
2229
+ }
2230
+ else {
2231
+ this.expressions.setValue('lookRight', 0.0);
2232
+ this.expressions.setValue('lookLeft', this.rangeMapHorizontalOuter.map(srcY));
2233
+ }
2234
+ }
2235
+ }
2236
+ /**
2237
+ * Represent its type of applier.
2238
+ */
2239
2239
  VRMLookAtExpressionApplier.type = 'expression';
2240
2240
 
2241
- class VRMLookAtRangeMap {
2242
- /**
2243
- * Create a new {@link VRMLookAtRangeMap}.
2244
- *
2245
- * @param inputMaxValue The {@link inputMaxValue} of the map
2246
- * @param outputScale The {@link outputScale} of the map
2247
- */
2248
- constructor(inputMaxValue, outputScale) {
2249
- this.inputMaxValue = inputMaxValue;
2250
- this.outputScale = outputScale;
2251
- }
2252
- /**
2253
- * Evaluate an input value and output a mapped value.
2254
- * @param src The input value
2255
- */
2256
- map(src) {
2257
- return this.outputScale * saturate(src / this.inputMaxValue);
2258
- }
2241
+ class VRMLookAtRangeMap {
2242
+ /**
2243
+ * Create a new {@link VRMLookAtRangeMap}.
2244
+ *
2245
+ * @param inputMaxValue The {@link inputMaxValue} of the map
2246
+ * @param outputScale The {@link outputScale} of the map
2247
+ */
2248
+ constructor(inputMaxValue, outputScale) {
2249
+ this.inputMaxValue = inputMaxValue;
2250
+ this.outputScale = outputScale;
2251
+ }
2252
+ /**
2253
+ * Evaluate an input value and output a mapped value.
2254
+ * @param src The input value
2255
+ */
2256
+ map(src) {
2257
+ return this.outputScale * saturate(src / this.inputMaxValue);
2258
+ }
2259
2259
  }
2260
2260
 
2261
- /**
2262
- * A plugin of GLTFLoader that imports a {@link VRMLookAt} from a VRM extension of a GLTF.
2263
- */
2264
- class VRMLookAtLoaderPlugin {
2265
- constructor(parser, options) {
2266
- this.parser = parser;
2267
- this.helperRoot = options === null || options === void 0 ? void 0 : options.helperRoot;
2268
- }
2269
- get name() {
2270
- // We should use the extension name instead but we have multiple plugins for an extension...
2271
- return 'VRMLookAtLoaderPlugin';
2272
- }
2273
- afterRoot(gltf) {
2274
- return __awaiter(this, void 0, void 0, function* () {
2275
- const vrmHumanoid = gltf.userData.vrmHumanoid;
2276
- // explicitly distinguish null and undefined
2277
- // since vrmHumanoid might be null as a result
2278
- if (vrmHumanoid === null) {
2279
- return;
2280
- }
2281
- else if (vrmHumanoid === undefined) {
2282
- throw new Error('VRMFirstPersonLoaderPlugin: vrmHumanoid is undefined. VRMHumanoidLoaderPlugin have to be used first');
2283
- }
2284
- const vrmExpressionManager = gltf.userData.vrmExpressionManager;
2285
- if (vrmExpressionManager === null) {
2286
- return;
2287
- }
2288
- else if (vrmExpressionManager === undefined) {
2289
- throw new Error('VRMFirstPersonLoaderPlugin: vrmExpressionManager is undefined. VRMExpressionLoaderPlugin have to be used first');
2290
- }
2291
- gltf.userData.vrmLookAt = yield this._import(gltf, vrmHumanoid, vrmExpressionManager);
2292
- });
2293
- }
2294
- /**
2295
- * Import a {@link VRMLookAt} from a VRM.
2296
- *
2297
- * @param gltf A parsed result of GLTF taken from GLTFLoader
2298
- * @param humanoid A {@link VRMHumanoid} instance that represents the VRM
2299
- * @param expressions A {@link VRMExpressionManager} instance that represents the VRM
2300
- */
2301
- _import(gltf, humanoid, expressions) {
2302
- return __awaiter(this, void 0, void 0, function* () {
2303
- if (humanoid == null || expressions == null) {
2304
- return null;
2305
- }
2306
- const v1Result = yield this._v1Import(gltf, humanoid, expressions);
2307
- if (v1Result) {
2308
- return v1Result;
2309
- }
2310
- const v0Result = yield this._v0Import(gltf, humanoid, expressions);
2311
- if (v0Result) {
2312
- return v0Result;
2313
- }
2314
- return null;
2315
- });
2316
- }
2317
- _v1Import(gltf, humanoid, expressions) {
2318
- var _a, _b, _c;
2319
- return __awaiter(this, void 0, void 0, function* () {
2320
- const json = this.parser.json;
2321
- // early abort if it doesn't use vrm
2322
- const isVRMUsed = ((_a = json.extensionsUsed) === null || _a === void 0 ? void 0 : _a.indexOf('VRMC_vrm')) !== -1;
2323
- if (!isVRMUsed) {
2324
- return null;
2325
- }
2326
- const extension = (_b = json.extensions) === null || _b === void 0 ? void 0 : _b['VRMC_vrm'];
2327
- if (!extension) {
2328
- return null;
2329
- }
2330
- const specVersion = extension.specVersion;
2331
- if (specVersion !== '1.0-beta') {
2332
- return null;
2333
- }
2334
- const schemaLookAt = extension.lookAt;
2335
- if (!schemaLookAt) {
2336
- return null;
2337
- }
2338
- const defaultOutputScale = schemaLookAt.type === 'expression' ? 1.0 : 10.0;
2339
- const mapHI = this._v1ImportRangeMap(schemaLookAt.rangeMapHorizontalInner, defaultOutputScale);
2340
- const mapHO = this._v1ImportRangeMap(schemaLookAt.rangeMapHorizontalOuter, defaultOutputScale);
2341
- const mapVD = this._v1ImportRangeMap(schemaLookAt.rangeMapVerticalDown, defaultOutputScale);
2342
- const mapVU = this._v1ImportRangeMap(schemaLookAt.rangeMapVerticalUp, defaultOutputScale);
2343
- let applier;
2344
- if (schemaLookAt.type === 'expression') {
2345
- applier = new VRMLookAtExpressionApplier(expressions, mapHI, mapHO, mapVD, mapVU);
2346
- }
2347
- else {
2348
- applier = new VRMLookAtBoneApplier(humanoid, mapHI, mapHO, mapVD, mapVU);
2349
- }
2350
- const lookAt = this._importLookAt(humanoid, applier);
2351
- lookAt.offsetFromHeadBone.fromArray((_c = schemaLookAt.offsetFromHeadBone) !== null && _c !== void 0 ? _c : [0.0, 0.06, 0.0]);
2352
- return lookAt;
2353
- });
2354
- }
2355
- _v1ImportRangeMap(schemaRangeMap, defaultOutputScale) {
2356
- var _a, _b;
2357
- return new VRMLookAtRangeMap((_a = schemaRangeMap === null || schemaRangeMap === void 0 ? void 0 : schemaRangeMap.inputMaxValue) !== null && _a !== void 0 ? _a : 90.0, (_b = schemaRangeMap === null || schemaRangeMap === void 0 ? void 0 : schemaRangeMap.outputScale) !== null && _b !== void 0 ? _b : defaultOutputScale);
2358
- }
2359
- _v0Import(gltf, humanoid, expressions) {
2360
- var _a, _b, _c, _d;
2361
- return __awaiter(this, void 0, void 0, function* () {
2362
- const json = this.parser.json;
2363
- // early abort if it doesn't use vrm
2364
- const vrmExt = (_a = json.extensions) === null || _a === void 0 ? void 0 : _a.VRM;
2365
- if (!vrmExt) {
2366
- return null;
2367
- }
2368
- const schemaFirstPerson = vrmExt.firstPerson;
2369
- if (!schemaFirstPerson) {
2370
- return null;
2371
- }
2372
- const defaultOutputScale = schemaFirstPerson.lookAtTypeName === 'BlendShape' ? 1.0 : 10.0;
2373
- const mapHI = this._v0ImportDegreeMap(schemaFirstPerson.lookAtHorizontalInner, defaultOutputScale);
2374
- const mapHO = this._v0ImportDegreeMap(schemaFirstPerson.lookAtHorizontalOuter, defaultOutputScale);
2375
- const mapVD = this._v0ImportDegreeMap(schemaFirstPerson.lookAtVerticalDown, defaultOutputScale);
2376
- const mapVU = this._v0ImportDegreeMap(schemaFirstPerson.lookAtVerticalUp, defaultOutputScale);
2377
- let applier;
2378
- if (schemaFirstPerson.lookAtTypeName === 'BlendShape') {
2379
- applier = new VRMLookAtExpressionApplier(expressions, mapHI, mapHO, mapVD, mapVU);
2380
- }
2381
- else {
2382
- applier = new VRMLookAtBoneApplier(humanoid, mapHI, mapHO, mapVD, mapVU);
2383
- }
2384
- const lookAt = this._importLookAt(humanoid, applier);
2385
- if (schemaFirstPerson.firstPersonBoneOffset) {
2386
- lookAt.offsetFromHeadBone.set((_b = schemaFirstPerson.firstPersonBoneOffset.x) !== null && _b !== void 0 ? _b : 0.0, (_c = schemaFirstPerson.firstPersonBoneOffset.y) !== null && _c !== void 0 ? _c : 0.06, -((_d = schemaFirstPerson.firstPersonBoneOffset.z) !== null && _d !== void 0 ? _d : 0.0));
2387
- }
2388
- else {
2389
- lookAt.offsetFromHeadBone.set(0.0, 0.06, 0.0);
2390
- }
2391
- // VRM 0.0 are facing Z- instead of Z+
2392
- lookAt.faceFront.set(0.0, 0.0, -1.0);
2393
- return lookAt;
2394
- });
2395
- }
2396
- _v0ImportDegreeMap(schemaDegreeMap, defaultOutputScale) {
2397
- var _a, _b;
2398
- const curve = schemaDegreeMap === null || schemaDegreeMap === void 0 ? void 0 : schemaDegreeMap.curve;
2399
- if (JSON.stringify(curve) !== '[0,0,0,1,1,1,1,0]') {
2400
- console.warn('Curves of LookAtDegreeMap defined in VRM 0.0 are not supported');
2401
- }
2402
- return new VRMLookAtRangeMap((_a = schemaDegreeMap === null || schemaDegreeMap === void 0 ? void 0 : schemaDegreeMap.xRange) !== null && _a !== void 0 ? _a : 90.0, (_b = schemaDegreeMap === null || schemaDegreeMap === void 0 ? void 0 : schemaDegreeMap.yRange) !== null && _b !== void 0 ? _b : defaultOutputScale);
2403
- }
2404
- _importLookAt(humanoid, applier) {
2405
- const lookAt = new VRMLookAt(humanoid, applier);
2406
- if (this.helperRoot) {
2407
- const helper = new VRMLookAtHelper(lookAt);
2408
- this.helperRoot.add(helper);
2409
- helper.renderOrder = this.helperRoot.renderOrder;
2410
- }
2411
- return lookAt;
2412
- }
2261
+ /**
2262
+ * A plugin of GLTFLoader that imports a {@link VRMLookAt} from a VRM extension of a GLTF.
2263
+ */
2264
+ class VRMLookAtLoaderPlugin {
2265
+ constructor(parser, options) {
2266
+ this.parser = parser;
2267
+ this.helperRoot = options === null || options === void 0 ? void 0 : options.helperRoot;
2268
+ }
2269
+ get name() {
2270
+ // We should use the extension name instead but we have multiple plugins for an extension...
2271
+ return 'VRMLookAtLoaderPlugin';
2272
+ }
2273
+ afterRoot(gltf) {
2274
+ return __awaiter(this, void 0, void 0, function* () {
2275
+ const vrmHumanoid = gltf.userData.vrmHumanoid;
2276
+ // explicitly distinguish null and undefined
2277
+ // since vrmHumanoid might be null as a result
2278
+ if (vrmHumanoid === null) {
2279
+ return;
2280
+ }
2281
+ else if (vrmHumanoid === undefined) {
2282
+ throw new Error('VRMFirstPersonLoaderPlugin: vrmHumanoid is undefined. VRMHumanoidLoaderPlugin have to be used first');
2283
+ }
2284
+ const vrmExpressionManager = gltf.userData.vrmExpressionManager;
2285
+ if (vrmExpressionManager === null) {
2286
+ return;
2287
+ }
2288
+ else if (vrmExpressionManager === undefined) {
2289
+ throw new Error('VRMFirstPersonLoaderPlugin: vrmExpressionManager is undefined. VRMExpressionLoaderPlugin have to be used first');
2290
+ }
2291
+ gltf.userData.vrmLookAt = yield this._import(gltf, vrmHumanoid, vrmExpressionManager);
2292
+ });
2293
+ }
2294
+ /**
2295
+ * Import a {@link VRMLookAt} from a VRM.
2296
+ *
2297
+ * @param gltf A parsed result of GLTF taken from GLTFLoader
2298
+ * @param humanoid A {@link VRMHumanoid} instance that represents the VRM
2299
+ * @param expressions A {@link VRMExpressionManager} instance that represents the VRM
2300
+ */
2301
+ _import(gltf, humanoid, expressions) {
2302
+ return __awaiter(this, void 0, void 0, function* () {
2303
+ if (humanoid == null || expressions == null) {
2304
+ return null;
2305
+ }
2306
+ const v1Result = yield this._v1Import(gltf, humanoid, expressions);
2307
+ if (v1Result) {
2308
+ return v1Result;
2309
+ }
2310
+ const v0Result = yield this._v0Import(gltf, humanoid, expressions);
2311
+ if (v0Result) {
2312
+ return v0Result;
2313
+ }
2314
+ return null;
2315
+ });
2316
+ }
2317
+ _v1Import(gltf, humanoid, expressions) {
2318
+ var _a, _b, _c;
2319
+ return __awaiter(this, void 0, void 0, function* () {
2320
+ const json = this.parser.json;
2321
+ // early abort if it doesn't use vrm
2322
+ const isVRMUsed = ((_a = json.extensionsUsed) === null || _a === void 0 ? void 0 : _a.indexOf('VRMC_vrm')) !== -1;
2323
+ if (!isVRMUsed) {
2324
+ return null;
2325
+ }
2326
+ const extension = (_b = json.extensions) === null || _b === void 0 ? void 0 : _b['VRMC_vrm'];
2327
+ if (!extension) {
2328
+ return null;
2329
+ }
2330
+ const specVersion = extension.specVersion;
2331
+ if (specVersion !== '1.0-beta') {
2332
+ return null;
2333
+ }
2334
+ const schemaLookAt = extension.lookAt;
2335
+ if (!schemaLookAt) {
2336
+ return null;
2337
+ }
2338
+ const defaultOutputScale = schemaLookAt.type === 'expression' ? 1.0 : 10.0;
2339
+ const mapHI = this._v1ImportRangeMap(schemaLookAt.rangeMapHorizontalInner, defaultOutputScale);
2340
+ const mapHO = this._v1ImportRangeMap(schemaLookAt.rangeMapHorizontalOuter, defaultOutputScale);
2341
+ const mapVD = this._v1ImportRangeMap(schemaLookAt.rangeMapVerticalDown, defaultOutputScale);
2342
+ const mapVU = this._v1ImportRangeMap(schemaLookAt.rangeMapVerticalUp, defaultOutputScale);
2343
+ let applier;
2344
+ if (schemaLookAt.type === 'expression') {
2345
+ applier = new VRMLookAtExpressionApplier(expressions, mapHI, mapHO, mapVD, mapVU);
2346
+ }
2347
+ else {
2348
+ applier = new VRMLookAtBoneApplier(humanoid, mapHI, mapHO, mapVD, mapVU);
2349
+ }
2350
+ const lookAt = this._importLookAt(humanoid, applier);
2351
+ lookAt.offsetFromHeadBone.fromArray((_c = schemaLookAt.offsetFromHeadBone) !== null && _c !== void 0 ? _c : [0.0, 0.06, 0.0]);
2352
+ return lookAt;
2353
+ });
2354
+ }
2355
+ _v1ImportRangeMap(schemaRangeMap, defaultOutputScale) {
2356
+ var _a, _b;
2357
+ return new VRMLookAtRangeMap((_a = schemaRangeMap === null || schemaRangeMap === void 0 ? void 0 : schemaRangeMap.inputMaxValue) !== null && _a !== void 0 ? _a : 90.0, (_b = schemaRangeMap === null || schemaRangeMap === void 0 ? void 0 : schemaRangeMap.outputScale) !== null && _b !== void 0 ? _b : defaultOutputScale);
2358
+ }
2359
+ _v0Import(gltf, humanoid, expressions) {
2360
+ var _a, _b, _c, _d;
2361
+ return __awaiter(this, void 0, void 0, function* () {
2362
+ const json = this.parser.json;
2363
+ // early abort if it doesn't use vrm
2364
+ const vrmExt = (_a = json.extensions) === null || _a === void 0 ? void 0 : _a.VRM;
2365
+ if (!vrmExt) {
2366
+ return null;
2367
+ }
2368
+ const schemaFirstPerson = vrmExt.firstPerson;
2369
+ if (!schemaFirstPerson) {
2370
+ return null;
2371
+ }
2372
+ const defaultOutputScale = schemaFirstPerson.lookAtTypeName === 'BlendShape' ? 1.0 : 10.0;
2373
+ const mapHI = this._v0ImportDegreeMap(schemaFirstPerson.lookAtHorizontalInner, defaultOutputScale);
2374
+ const mapHO = this._v0ImportDegreeMap(schemaFirstPerson.lookAtHorizontalOuter, defaultOutputScale);
2375
+ const mapVD = this._v0ImportDegreeMap(schemaFirstPerson.lookAtVerticalDown, defaultOutputScale);
2376
+ const mapVU = this._v0ImportDegreeMap(schemaFirstPerson.lookAtVerticalUp, defaultOutputScale);
2377
+ let applier;
2378
+ if (schemaFirstPerson.lookAtTypeName === 'BlendShape') {
2379
+ applier = new VRMLookAtExpressionApplier(expressions, mapHI, mapHO, mapVD, mapVU);
2380
+ }
2381
+ else {
2382
+ applier = new VRMLookAtBoneApplier(humanoid, mapHI, mapHO, mapVD, mapVU);
2383
+ }
2384
+ const lookAt = this._importLookAt(humanoid, applier);
2385
+ if (schemaFirstPerson.firstPersonBoneOffset) {
2386
+ lookAt.offsetFromHeadBone.set((_b = schemaFirstPerson.firstPersonBoneOffset.x) !== null && _b !== void 0 ? _b : 0.0, (_c = schemaFirstPerson.firstPersonBoneOffset.y) !== null && _c !== void 0 ? _c : 0.06, -((_d = schemaFirstPerson.firstPersonBoneOffset.z) !== null && _d !== void 0 ? _d : 0.0));
2387
+ }
2388
+ else {
2389
+ lookAt.offsetFromHeadBone.set(0.0, 0.06, 0.0);
2390
+ }
2391
+ // VRM 0.0 are facing Z- instead of Z+
2392
+ lookAt.faceFront.set(0.0, 0.0, -1.0);
2393
+ return lookAt;
2394
+ });
2395
+ }
2396
+ _v0ImportDegreeMap(schemaDegreeMap, defaultOutputScale) {
2397
+ var _a, _b;
2398
+ const curve = schemaDegreeMap === null || schemaDegreeMap === void 0 ? void 0 : schemaDegreeMap.curve;
2399
+ if (JSON.stringify(curve) !== '[0,0,0,1,1,1,1,0]') {
2400
+ console.warn('Curves of LookAtDegreeMap defined in VRM 0.0 are not supported');
2401
+ }
2402
+ return new VRMLookAtRangeMap((_a = schemaDegreeMap === null || schemaDegreeMap === void 0 ? void 0 : schemaDegreeMap.xRange) !== null && _a !== void 0 ? _a : 90.0, (_b = schemaDegreeMap === null || schemaDegreeMap === void 0 ? void 0 : schemaDegreeMap.yRange) !== null && _b !== void 0 ? _b : defaultOutputScale);
2403
+ }
2404
+ _importLookAt(humanoid, applier) {
2405
+ const lookAt = new VRMLookAt(humanoid, applier);
2406
+ if (this.helperRoot) {
2407
+ const helper = new VRMLookAtHelper(lookAt);
2408
+ this.helperRoot.add(helper);
2409
+ helper.renderOrder = this.helperRoot.renderOrder;
2410
+ }
2411
+ return lookAt;
2412
+ }
2413
2413
  }
2414
2414
 
2415
- /* eslint-disable @typescript-eslint/naming-convention */
2416
- /**
2417
- * Represents a type of applier.
2418
- */
2419
- const VRMLookAtTypeName = {
2420
- Bone: 'bone',
2421
- Expression: 'expression',
2415
+ /* eslint-disable @typescript-eslint/naming-convention */
2416
+ /**
2417
+ * Represents a type of applier.
2418
+ */
2419
+ const VRMLookAtTypeName = {
2420
+ Bone: 'bone',
2421
+ Expression: 'expression',
2422
2422
  };
2423
2423
 
2424
- /**
2425
- * Yoinked from https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/GLTFLoader.js
2426
- */
2427
- function resolveURL(url, path) {
2428
- // Invalid URL
2429
- if (typeof url !== 'string' || url === '')
2430
- return '';
2431
- // Host Relative URL
2432
- if (/^https?:\/\//i.test(path) && /^\//.test(url)) {
2433
- path = path.replace(/(^https?:\/\/[^/]+).*/i, '$1');
2434
- }
2435
- // Absolute URL http://,https://,//
2436
- if (/^(https?:)?\/\//i.test(url))
2437
- return url;
2438
- // Data URI
2439
- if (/^data:.*,.*$/i.test(url))
2440
- return url;
2441
- // Blob URL
2442
- if (/^blob:.*$/i.test(url))
2443
- return url;
2444
- // Relative URL
2445
- return path + url;
2424
+ /**
2425
+ * Yoinked from https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/GLTFLoader.js
2426
+ */
2427
+ function resolveURL(url, path) {
2428
+ // Invalid URL
2429
+ if (typeof url !== 'string' || url === '')
2430
+ return '';
2431
+ // Host Relative URL
2432
+ if (/^https?:\/\//i.test(path) && /^\//.test(url)) {
2433
+ path = path.replace(/(^https?:\/\/[^/]+).*/i, '$1');
2434
+ }
2435
+ // Absolute URL http://,https://,//
2436
+ if (/^(https?:)?\/\//i.test(url))
2437
+ return url;
2438
+ // Data URI
2439
+ if (/^data:.*,.*$/i.test(url))
2440
+ return url;
2441
+ // Blob URL
2442
+ if (/^blob:.*$/i.test(url))
2443
+ return url;
2444
+ // Relative URL
2445
+ return path + url;
2446
2446
  }
2447
2447
 
2448
- /**
2449
- * A plugin of GLTFLoader that imports a {@link VRM1Meta} from a VRM extension of a GLTF.
2450
- */
2451
- class VRMMetaLoaderPlugin {
2452
- constructor(parser, options) {
2453
- var _a, _b, _c;
2454
- this.parser = parser;
2455
- this.needThumbnailImage = (_a = options === null || options === void 0 ? void 0 : options.needThumbnailImage) !== null && _a !== void 0 ? _a : true;
2456
- this.acceptLicenseUrls = (_b = options === null || options === void 0 ? void 0 : options.acceptLicenseUrls) !== null && _b !== void 0 ? _b : ['https://vrm.dev/licenses/1.0/'];
2457
- this.acceptV0Meta = (_c = options === null || options === void 0 ? void 0 : options.acceptV0Meta) !== null && _c !== void 0 ? _c : true;
2458
- }
2459
- get name() {
2460
- // We should use the extension name instead but we have multiple plugins for an extension...
2461
- return 'VRMMetaLoaderPlugin';
2462
- }
2463
- afterRoot(gltf) {
2464
- return __awaiter(this, void 0, void 0, function* () {
2465
- gltf.userData.vrmMeta = yield this._import(gltf);
2466
- });
2467
- }
2468
- _import(gltf) {
2469
- return __awaiter(this, void 0, void 0, function* () {
2470
- const v1Result = yield this._v1Import(gltf);
2471
- if (v1Result != null) {
2472
- return v1Result;
2473
- }
2474
- const v0Result = yield this._v0Import(gltf);
2475
- if (v0Result != null) {
2476
- return v0Result;
2477
- }
2478
- return null;
2479
- });
2480
- }
2481
- _v1Import(gltf) {
2482
- var _a, _b, _c;
2483
- return __awaiter(this, void 0, void 0, function* () {
2484
- const json = this.parser.json;
2485
- // early abort if it doesn't use vrm
2486
- const isVRMUsed = ((_a = json.extensionsUsed) === null || _a === void 0 ? void 0 : _a.indexOf('VRMC_vrm')) !== -1;
2487
- if (!isVRMUsed) {
2488
- return null;
2489
- }
2490
- const extension = (_b = json.extensions) === null || _b === void 0 ? void 0 : _b['VRMC_vrm'];
2491
- if (extension == null) {
2492
- return null;
2493
- }
2494
- const specVersion = extension.specVersion;
2495
- if (specVersion !== '1.0-beta') {
2496
- return null;
2497
- }
2498
- const schemaMeta = extension.meta;
2499
- if (!schemaMeta) {
2500
- return null;
2501
- }
2502
- // throw an error if acceptV0Meta is false
2503
- const licenseUrl = schemaMeta.licenseUrl;
2504
- const acceptLicenseUrlsSet = new Set(this.acceptLicenseUrls);
2505
- if (!acceptLicenseUrlsSet.has(licenseUrl)) {
2506
- throw new Error(`VRMMetaLoaderPlugin: The license url "${licenseUrl}" is not accepted`);
2507
- }
2508
- let thumbnailImage = undefined;
2509
- if (this.needThumbnailImage && schemaMeta.thumbnailImage != null) {
2510
- thumbnailImage = (_c = (yield this._extractGLTFImage(schemaMeta.thumbnailImage))) !== null && _c !== void 0 ? _c : undefined;
2511
- }
2512
- return {
2513
- metaVersion: '1',
2514
- name: schemaMeta.name,
2515
- version: schemaMeta.version,
2516
- authors: schemaMeta.authors,
2517
- copyrightInformation: schemaMeta.copyrightInformation,
2518
- contactInformation: schemaMeta.contactInformation,
2519
- references: schemaMeta.references,
2520
- thirdPartyLicenses: schemaMeta.thirdPartyLicenses,
2521
- thumbnailImage,
2522
- licenseUrl: schemaMeta.licenseUrl,
2523
- avatarPermission: schemaMeta.avatarPermission,
2524
- allowExcessivelyViolentUsage: schemaMeta.allowExcessivelyViolentUsage,
2525
- allowExcessivelySexualUsage: schemaMeta.allowExcessivelySexualUsage,
2526
- commercialUsage: schemaMeta.commercialUsage,
2527
- allowPoliticalOrReligiousUsage: schemaMeta.allowPoliticalOrReligiousUsage,
2528
- allowAntisocialOrHateUsage: schemaMeta.allowAntisocialOrHateUsage,
2529
- creditNotation: schemaMeta.creditNotation,
2530
- allowRedistribution: schemaMeta.allowRedistribution,
2531
- modification: schemaMeta.modification,
2532
- otherLicenseUrl: schemaMeta.otherLicenseUrl,
2533
- };
2534
- });
2535
- }
2536
- _v0Import(gltf) {
2537
- var _a;
2538
- return __awaiter(this, void 0, void 0, function* () {
2539
- const json = this.parser.json;
2540
- // early abort if it doesn't use vrm
2541
- const vrmExt = (_a = json.extensions) === null || _a === void 0 ? void 0 : _a.VRM;
2542
- if (!vrmExt) {
2543
- return null;
2544
- }
2545
- const schemaMeta = vrmExt.meta;
2546
- if (!schemaMeta) {
2547
- return null;
2548
- }
2549
- // throw an error if acceptV0Meta is false
2550
- if (!this.acceptV0Meta) {
2551
- throw new Error('VRMMetaLoaderPlugin: Attempted to load VRM0.X meta but acceptV0Meta is false');
2552
- }
2553
- // load thumbnail texture
2554
- let texture;
2555
- if (this.needThumbnailImage && schemaMeta.texture != null && schemaMeta.texture !== -1) {
2556
- texture = yield this.parser.getDependency('texture', schemaMeta.texture);
2557
- }
2558
- return {
2559
- metaVersion: '0',
2560
- allowedUserName: schemaMeta.allowedUserName,
2561
- author: schemaMeta.author,
2562
- commercialUssageName: schemaMeta.commercialUssageName,
2563
- contactInformation: schemaMeta.contactInformation,
2564
- licenseName: schemaMeta.licenseName,
2565
- otherLicenseUrl: schemaMeta.otherLicenseUrl,
2566
- otherPermissionUrl: schemaMeta.otherPermissionUrl,
2567
- reference: schemaMeta.reference,
2568
- sexualUssageName: schemaMeta.sexualUssageName,
2569
- texture: texture !== null && texture !== void 0 ? texture : undefined,
2570
- title: schemaMeta.title,
2571
- version: schemaMeta.version,
2572
- violentUssageName: schemaMeta.violentUssageName,
2573
- };
2574
- });
2575
- }
2576
- _extractGLTFImage(index) {
2577
- var _a;
2578
- return __awaiter(this, void 0, void 0, function* () {
2579
- const json = this.parser.json;
2580
- const source = (_a = json.images) === null || _a === void 0 ? void 0 : _a[index];
2581
- if (source == null) {
2582
- console.warn(`VRMMetaLoaderPlugin: Attempt to use images[${index}] of glTF as a thumbnail but the image doesn't exist`);
2583
- return null;
2584
- }
2585
- // Ref: https://github.com/mrdoob/three.js/blob/r124/examples/jsm/loaders/GLTFLoader.js#L2467
2586
- // `source.uri` might be a reference to a file
2587
- let sourceURI = source.uri;
2588
- // Load the binary as a blob
2589
- if (source.bufferView != null) {
2590
- const bufferView = yield this.parser.getDependency('bufferView', source.bufferView);
2591
- const blob = new Blob([bufferView], { type: source.mimeType });
2592
- sourceURI = URL.createObjectURL(blob);
2593
- }
2594
- if (sourceURI == null) {
2595
- console.warn(`VRMMetaLoaderPlugin: Attempt to use images[${index}] of glTF as a thumbnail but the image couldn't load properly`);
2596
- return null;
2597
- }
2598
- const loader = new THREE__namespace.ImageLoader();
2599
- return yield loader.loadAsync(resolveURL(sourceURI, this.parser.options.path)).catch((error) => {
2600
- console.error(error);
2601
- console.warn('VRMMetaLoaderPlugin: Failed to load a thumbnail image');
2602
- return null;
2603
- });
2604
- });
2605
- }
2448
+ /**
2449
+ * A plugin of GLTFLoader that imports a {@link VRM1Meta} from a VRM extension of a GLTF.
2450
+ */
2451
+ class VRMMetaLoaderPlugin {
2452
+ constructor(parser, options) {
2453
+ var _a, _b, _c;
2454
+ this.parser = parser;
2455
+ this.needThumbnailImage = (_a = options === null || options === void 0 ? void 0 : options.needThumbnailImage) !== null && _a !== void 0 ? _a : true;
2456
+ this.acceptLicenseUrls = (_b = options === null || options === void 0 ? void 0 : options.acceptLicenseUrls) !== null && _b !== void 0 ? _b : ['https://vrm.dev/licenses/1.0/'];
2457
+ this.acceptV0Meta = (_c = options === null || options === void 0 ? void 0 : options.acceptV0Meta) !== null && _c !== void 0 ? _c : true;
2458
+ }
2459
+ get name() {
2460
+ // We should use the extension name instead but we have multiple plugins for an extension...
2461
+ return 'VRMMetaLoaderPlugin';
2462
+ }
2463
+ afterRoot(gltf) {
2464
+ return __awaiter(this, void 0, void 0, function* () {
2465
+ gltf.userData.vrmMeta = yield this._import(gltf);
2466
+ });
2467
+ }
2468
+ _import(gltf) {
2469
+ return __awaiter(this, void 0, void 0, function* () {
2470
+ const v1Result = yield this._v1Import(gltf);
2471
+ if (v1Result != null) {
2472
+ return v1Result;
2473
+ }
2474
+ const v0Result = yield this._v0Import(gltf);
2475
+ if (v0Result != null) {
2476
+ return v0Result;
2477
+ }
2478
+ return null;
2479
+ });
2480
+ }
2481
+ _v1Import(gltf) {
2482
+ var _a, _b, _c;
2483
+ return __awaiter(this, void 0, void 0, function* () {
2484
+ const json = this.parser.json;
2485
+ // early abort if it doesn't use vrm
2486
+ const isVRMUsed = ((_a = json.extensionsUsed) === null || _a === void 0 ? void 0 : _a.indexOf('VRMC_vrm')) !== -1;
2487
+ if (!isVRMUsed) {
2488
+ return null;
2489
+ }
2490
+ const extension = (_b = json.extensions) === null || _b === void 0 ? void 0 : _b['VRMC_vrm'];
2491
+ if (extension == null) {
2492
+ return null;
2493
+ }
2494
+ const specVersion = extension.specVersion;
2495
+ if (specVersion !== '1.0-beta') {
2496
+ return null;
2497
+ }
2498
+ const schemaMeta = extension.meta;
2499
+ if (!schemaMeta) {
2500
+ return null;
2501
+ }
2502
+ // throw an error if acceptV0Meta is false
2503
+ const licenseUrl = schemaMeta.licenseUrl;
2504
+ const acceptLicenseUrlsSet = new Set(this.acceptLicenseUrls);
2505
+ if (!acceptLicenseUrlsSet.has(licenseUrl)) {
2506
+ throw new Error(`VRMMetaLoaderPlugin: The license url "${licenseUrl}" is not accepted`);
2507
+ }
2508
+ let thumbnailImage = undefined;
2509
+ if (this.needThumbnailImage && schemaMeta.thumbnailImage != null) {
2510
+ thumbnailImage = (_c = (yield this._extractGLTFImage(schemaMeta.thumbnailImage))) !== null && _c !== void 0 ? _c : undefined;
2511
+ }
2512
+ return {
2513
+ metaVersion: '1',
2514
+ name: schemaMeta.name,
2515
+ version: schemaMeta.version,
2516
+ authors: schemaMeta.authors,
2517
+ copyrightInformation: schemaMeta.copyrightInformation,
2518
+ contactInformation: schemaMeta.contactInformation,
2519
+ references: schemaMeta.references,
2520
+ thirdPartyLicenses: schemaMeta.thirdPartyLicenses,
2521
+ thumbnailImage,
2522
+ licenseUrl: schemaMeta.licenseUrl,
2523
+ avatarPermission: schemaMeta.avatarPermission,
2524
+ allowExcessivelyViolentUsage: schemaMeta.allowExcessivelyViolentUsage,
2525
+ allowExcessivelySexualUsage: schemaMeta.allowExcessivelySexualUsage,
2526
+ commercialUsage: schemaMeta.commercialUsage,
2527
+ allowPoliticalOrReligiousUsage: schemaMeta.allowPoliticalOrReligiousUsage,
2528
+ allowAntisocialOrHateUsage: schemaMeta.allowAntisocialOrHateUsage,
2529
+ creditNotation: schemaMeta.creditNotation,
2530
+ allowRedistribution: schemaMeta.allowRedistribution,
2531
+ modification: schemaMeta.modification,
2532
+ otherLicenseUrl: schemaMeta.otherLicenseUrl,
2533
+ };
2534
+ });
2535
+ }
2536
+ _v0Import(gltf) {
2537
+ var _a;
2538
+ return __awaiter(this, void 0, void 0, function* () {
2539
+ const json = this.parser.json;
2540
+ // early abort if it doesn't use vrm
2541
+ const vrmExt = (_a = json.extensions) === null || _a === void 0 ? void 0 : _a.VRM;
2542
+ if (!vrmExt) {
2543
+ return null;
2544
+ }
2545
+ const schemaMeta = vrmExt.meta;
2546
+ if (!schemaMeta) {
2547
+ return null;
2548
+ }
2549
+ // throw an error if acceptV0Meta is false
2550
+ if (!this.acceptV0Meta) {
2551
+ throw new Error('VRMMetaLoaderPlugin: Attempted to load VRM0.X meta but acceptV0Meta is false');
2552
+ }
2553
+ // load thumbnail texture
2554
+ let texture;
2555
+ if (this.needThumbnailImage && schemaMeta.texture != null && schemaMeta.texture !== -1) {
2556
+ texture = yield this.parser.getDependency('texture', schemaMeta.texture);
2557
+ }
2558
+ return {
2559
+ metaVersion: '0',
2560
+ allowedUserName: schemaMeta.allowedUserName,
2561
+ author: schemaMeta.author,
2562
+ commercialUssageName: schemaMeta.commercialUssageName,
2563
+ contactInformation: schemaMeta.contactInformation,
2564
+ licenseName: schemaMeta.licenseName,
2565
+ otherLicenseUrl: schemaMeta.otherLicenseUrl,
2566
+ otherPermissionUrl: schemaMeta.otherPermissionUrl,
2567
+ reference: schemaMeta.reference,
2568
+ sexualUssageName: schemaMeta.sexualUssageName,
2569
+ texture: texture !== null && texture !== void 0 ? texture : undefined,
2570
+ title: schemaMeta.title,
2571
+ version: schemaMeta.version,
2572
+ violentUssageName: schemaMeta.violentUssageName,
2573
+ };
2574
+ });
2575
+ }
2576
+ _extractGLTFImage(index) {
2577
+ var _a;
2578
+ return __awaiter(this, void 0, void 0, function* () {
2579
+ const json = this.parser.json;
2580
+ const source = (_a = json.images) === null || _a === void 0 ? void 0 : _a[index];
2581
+ if (source == null) {
2582
+ console.warn(`VRMMetaLoaderPlugin: Attempt to use images[${index}] of glTF as a thumbnail but the image doesn't exist`);
2583
+ return null;
2584
+ }
2585
+ // Ref: https://github.com/mrdoob/three.js/blob/r124/examples/jsm/loaders/GLTFLoader.js#L2467
2586
+ // `source.uri` might be a reference to a file
2587
+ let sourceURI = source.uri;
2588
+ // Load the binary as a blob
2589
+ if (source.bufferView != null) {
2590
+ const bufferView = yield this.parser.getDependency('bufferView', source.bufferView);
2591
+ const blob = new Blob([bufferView], { type: source.mimeType });
2592
+ sourceURI = URL.createObjectURL(blob);
2593
+ }
2594
+ if (sourceURI == null) {
2595
+ console.warn(`VRMMetaLoaderPlugin: Attempt to use images[${index}] of glTF as a thumbnail but the image couldn't load properly`);
2596
+ return null;
2597
+ }
2598
+ const loader = new THREE__namespace.ImageLoader();
2599
+ return yield loader.loadAsync(resolveURL(sourceURI, this.parser.options.path)).catch((error) => {
2600
+ console.error(error);
2601
+ console.warn('VRMMetaLoaderPlugin: Failed to load a thumbnail image');
2602
+ return null;
2603
+ });
2604
+ });
2605
+ }
2606
2606
  }
2607
2607
 
2608
- /**
2609
- * A class that represents a single VRM model.
2610
- * This class only includes core spec of the VRM (`VRMC_vrm`).
2611
- */
2612
- class VRMCore {
2613
- /**
2614
- * Create a new VRM instance.
2615
- *
2616
- * @param params [[VRMParameters]] that represents components of the VRM
2617
- */
2618
- constructor(params) {
2619
- this.scene = params.scene;
2620
- this.humanoid = params.humanoid;
2621
- this.expressionManager = params.expressionManager;
2622
- this.firstPerson = params.firstPerson;
2623
- this.lookAt = params.lookAt;
2624
- this.meta = params.meta;
2625
- }
2626
- /**
2627
- * **You need to call this on your update loop.**
2628
- *
2629
- * This function updates every VRM components.
2630
- *
2631
- * @param delta deltaTime
2632
- */
2633
- update(delta) {
2634
- if (this.lookAt) {
2635
- this.lookAt.update(delta);
2636
- }
2637
- if (this.expressionManager) {
2638
- this.expressionManager.update();
2639
- }
2640
- }
2608
+ /**
2609
+ * A class that represents a single VRM model.
2610
+ * This class only includes core spec of the VRM (`VRMC_vrm`).
2611
+ */
2612
+ class VRMCore {
2613
+ /**
2614
+ * Create a new VRM instance.
2615
+ *
2616
+ * @param params [[VRMParameters]] that represents components of the VRM
2617
+ */
2618
+ constructor(params) {
2619
+ this.scene = params.scene;
2620
+ this.humanoid = params.humanoid;
2621
+ this.expressionManager = params.expressionManager;
2622
+ this.firstPerson = params.firstPerson;
2623
+ this.lookAt = params.lookAt;
2624
+ this.meta = params.meta;
2625
+ }
2626
+ /**
2627
+ * **You need to call this on your update loop.**
2628
+ *
2629
+ * This function updates every VRM components.
2630
+ *
2631
+ * @param delta deltaTime
2632
+ */
2633
+ update(delta) {
2634
+ if (this.lookAt) {
2635
+ this.lookAt.update(delta);
2636
+ }
2637
+ if (this.expressionManager) {
2638
+ this.expressionManager.update();
2639
+ }
2640
+ }
2641
2641
  }
2642
2642
 
2643
- class VRMCoreLoaderPlugin {
2644
- constructor(parser, options) {
2645
- var _a, _b, _c, _d, _e;
2646
- this.parser = parser;
2647
- const helperRoot = options === null || options === void 0 ? void 0 : options.helperRoot;
2648
- this.expressionPlugin = (_a = options === null || options === void 0 ? void 0 : options.expressionPlugin) !== null && _a !== void 0 ? _a : new VRMExpressionLoaderPlugin(parser);
2649
- this.firstPersonPlugin = (_b = options === null || options === void 0 ? void 0 : options.firstPersonPlugin) !== null && _b !== void 0 ? _b : new VRMFirstPersonLoaderPlugin(parser);
2650
- this.humanoidPlugin = (_c = options === null || options === void 0 ? void 0 : options.humanoidPlugin) !== null && _c !== void 0 ? _c : new VRMHumanoidLoaderPlugin(parser);
2651
- this.lookAtPlugin = (_d = options === null || options === void 0 ? void 0 : options.lookAtPlugin) !== null && _d !== void 0 ? _d : new VRMLookAtLoaderPlugin(parser, { helperRoot });
2652
- this.metaPlugin = (_e = options === null || options === void 0 ? void 0 : options.metaPlugin) !== null && _e !== void 0 ? _e : new VRMMetaLoaderPlugin(parser);
2653
- }
2654
- get name() {
2655
- // We should use the extension name instead but we have multiple plugins for an extension...
2656
- return 'VRMC_vrm';
2657
- }
2658
- afterRoot(gltf) {
2659
- return __awaiter(this, void 0, void 0, function* () {
2660
- yield this.metaPlugin.afterRoot(gltf);
2661
- yield this.humanoidPlugin.afterRoot(gltf);
2662
- yield this.expressionPlugin.afterRoot(gltf);
2663
- yield this.lookAtPlugin.afterRoot(gltf);
2664
- yield this.firstPersonPlugin.afterRoot(gltf);
2665
- const vrmCore = new VRMCore({
2666
- scene: gltf.scene,
2667
- expressionManager: gltf.userData.vrmExpressionManager,
2668
- firstPerson: gltf.userData.vrmFirstPerson,
2669
- humanoid: gltf.userData.vrmHumanoid,
2670
- lookAt: gltf.userData.vrmLookAt,
2671
- meta: gltf.userData.vrmMeta,
2672
- });
2673
- gltf.userData.vrmCore = vrmCore;
2674
- });
2675
- }
2643
+ class VRMCoreLoaderPlugin {
2644
+ constructor(parser, options) {
2645
+ var _a, _b, _c, _d, _e;
2646
+ this.parser = parser;
2647
+ const helperRoot = options === null || options === void 0 ? void 0 : options.helperRoot;
2648
+ this.expressionPlugin = (_a = options === null || options === void 0 ? void 0 : options.expressionPlugin) !== null && _a !== void 0 ? _a : new VRMExpressionLoaderPlugin(parser);
2649
+ this.firstPersonPlugin = (_b = options === null || options === void 0 ? void 0 : options.firstPersonPlugin) !== null && _b !== void 0 ? _b : new VRMFirstPersonLoaderPlugin(parser);
2650
+ this.humanoidPlugin = (_c = options === null || options === void 0 ? void 0 : options.humanoidPlugin) !== null && _c !== void 0 ? _c : new VRMHumanoidLoaderPlugin(parser);
2651
+ this.lookAtPlugin = (_d = options === null || options === void 0 ? void 0 : options.lookAtPlugin) !== null && _d !== void 0 ? _d : new VRMLookAtLoaderPlugin(parser, { helperRoot });
2652
+ this.metaPlugin = (_e = options === null || options === void 0 ? void 0 : options.metaPlugin) !== null && _e !== void 0 ? _e : new VRMMetaLoaderPlugin(parser);
2653
+ }
2654
+ get name() {
2655
+ // We should use the extension name instead but we have multiple plugins for an extension...
2656
+ return 'VRMC_vrm';
2657
+ }
2658
+ afterRoot(gltf) {
2659
+ return __awaiter(this, void 0, void 0, function* () {
2660
+ yield this.metaPlugin.afterRoot(gltf);
2661
+ yield this.humanoidPlugin.afterRoot(gltf);
2662
+ yield this.expressionPlugin.afterRoot(gltf);
2663
+ yield this.lookAtPlugin.afterRoot(gltf);
2664
+ yield this.firstPersonPlugin.afterRoot(gltf);
2665
+ const vrmCore = new VRMCore({
2666
+ scene: gltf.scene,
2667
+ expressionManager: gltf.userData.vrmExpressionManager,
2668
+ firstPerson: gltf.userData.vrmFirstPerson,
2669
+ humanoid: gltf.userData.vrmHumanoid,
2670
+ lookAt: gltf.userData.vrmLookAt,
2671
+ meta: gltf.userData.vrmMeta,
2672
+ });
2673
+ gltf.userData.vrmCore = vrmCore;
2674
+ });
2675
+ }
2676
2676
  }
2677
2677
 
2678
2678
  exports.VRMCore = VRMCore;