Ai_Assistant/client/node_modules/@pixiv/three-vrm/lib/three-vrm.cjs

6761 lines
943 KiB
JavaScript
Raw Permalink Normal View History

2026-05-24 13:31:30 +02:00
/*!
* @pixiv/three-vrm v3.4.1
* VRM file loader for three.js.
*
* Copyright (c) 2019-2025 pixiv Inc.
* @pixiv/three-vrm is distributed under MIT License
* https://github.com/pixiv/three-vrm/blob/release/LICENSE
*/
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// src/index.ts
var src_exports = {};
__export(src_exports, {
MToonMaterial: () => MToonMaterial,
MToonMaterialDebugMode: () => MToonMaterialDebugMode,
MToonMaterialLoaderPlugin: () => MToonMaterialLoaderPlugin,
MToonMaterialOutlineWidthMode: () => MToonMaterialOutlineWidthMode,
VRM: () => VRM,
VRMAimConstraint: () => VRMAimConstraint,
VRMCore: () => VRMCore,
VRMCoreLoaderPlugin: () => VRMCoreLoaderPlugin,
VRMExpression: () => VRMExpression,
VRMExpressionLoaderPlugin: () => VRMExpressionLoaderPlugin,
VRMExpressionManager: () => VRMExpressionManager,
VRMExpressionMaterialColorBind: () => VRMExpressionMaterialColorBind,
VRMExpressionMaterialColorType: () => VRMExpressionMaterialColorType,
VRMExpressionMorphTargetBind: () => VRMExpressionMorphTargetBind,
VRMExpressionOverrideType: () => VRMExpressionOverrideType,
VRMExpressionPresetName: () => VRMExpressionPresetName,
VRMExpressionTextureTransformBind: () => VRMExpressionTextureTransformBind,
VRMFirstPerson: () => VRMFirstPerson,
VRMFirstPersonLoaderPlugin: () => VRMFirstPersonLoaderPlugin,
VRMFirstPersonMeshAnnotationType: () => VRMFirstPersonMeshAnnotationType,
VRMHumanBoneList: () => VRMHumanBoneList,
VRMHumanBoneName: () => VRMHumanBoneName,
VRMHumanBoneParentMap: () => VRMHumanBoneParentMap,
VRMHumanoid: () => VRMHumanoid,
VRMHumanoidHelper: () => VRMHumanoidHelper,
VRMHumanoidLoaderPlugin: () => VRMHumanoidLoaderPlugin,
VRMLoaderPlugin: () => VRMLoaderPlugin,
VRMLookAt: () => VRMLookAt,
VRMLookAtBoneApplier: () => VRMLookAtBoneApplier,
VRMLookAtExpressionApplier: () => VRMLookAtExpressionApplier,
VRMLookAtHelper: () => VRMLookAtHelper,
VRMLookAtLoaderPlugin: () => VRMLookAtLoaderPlugin,
VRMLookAtRangeMap: () => VRMLookAtRangeMap,
VRMLookAtTypeName: () => VRMLookAtTypeName,
VRMMetaLoaderPlugin: () => VRMMetaLoaderPlugin,
VRMNodeConstraint: () => VRMNodeConstraint,
VRMNodeConstraintHelper: () => VRMNodeConstraintHelper,
VRMNodeConstraintLoaderPlugin: () => VRMNodeConstraintLoaderPlugin,
VRMNodeConstraintManager: () => VRMNodeConstraintManager,
VRMRequiredHumanBoneName: () => VRMRequiredHumanBoneName,
VRMRollConstraint: () => VRMRollConstraint,
VRMRotationConstraint: () => VRMRotationConstraint,
VRMSpringBoneCollider: () => VRMSpringBoneCollider,
VRMSpringBoneColliderHelper: () => VRMSpringBoneColliderHelper,
VRMSpringBoneColliderShape: () => VRMSpringBoneColliderShape,
VRMSpringBoneColliderShapeCapsule: () => VRMSpringBoneColliderShapeCapsule,
VRMSpringBoneColliderShapePlane: () => VRMSpringBoneColliderShapePlane,
VRMSpringBoneColliderShapeSphere: () => VRMSpringBoneColliderShapeSphere,
VRMSpringBoneJoint: () => VRMSpringBoneJoint,
VRMSpringBoneJointHelper: () => VRMSpringBoneJointHelper,
VRMSpringBoneLoaderPlugin: () => VRMSpringBoneLoaderPlugin,
VRMSpringBoneManager: () => VRMSpringBoneManager,
VRMUtils: () => VRMUtils
});
module.exports = __toCommonJS(src_exports);
// ../three-vrm-core/lib/three-vrm-core.module.js
var THREE = __toESM(require("three"), 1);
var THREE4 = __toESM(require("three"), 1);
var THREE2 = __toESM(require("three"), 1);
var THREE3 = __toESM(require("three"), 1);
var THREE5 = __toESM(require("three"), 1);
var THREE6 = __toESM(require("three"), 1);
var THREE7 = __toESM(require("three"), 1);
var THREE8 = __toESM(require("three"), 1);
var THREE11 = __toESM(require("three"), 1);
var THREE9 = __toESM(require("three"), 1);
var THREE10 = __toESM(require("three"), 1);
var THREE13 = __toESM(require("three"), 1);
var THREE12 = __toESM(require("three"), 1);
var THREE14 = __toESM(require("three"), 1);
var THREE15 = __toESM(require("three"), 1);
var THREE16 = __toESM(require("three"), 1);
var __async2 = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
var VRMExpression = class extends THREE.Object3D {
constructor(expressionName) {
super();
this.weight = 0;
this.isBinary = false;
this.overrideBlink = "none";
this.overrideLookAt = "none";
this.overrideMouth = "none";
this._binds = [];
this.name = `VRMExpression_${expressionName}`;
this.expressionName = expressionName;
this.type = "VRMExpression";
this.visible = false;
}
/**
* Binds that this expression influences.
*/
get binds() {
return this._binds;
}
/**
* A value represents how much it should override blink expressions.
* `0.0` == no override at all, `1.0` == completely block the expressions.
*/
get overrideBlinkAmount() {
if (this.overrideBlink === "block") {
return 0 < this.outputWeight ? 1 : 0;
} else if (this.overrideBlink === "blend") {
return this.outputWeight;
} else {
return 0;
}
}
/**
* A value represents how much it should override lookAt expressions.
* `0.0` == no override at all, `1.0` == completely block the expressions.
*/
get overrideLookAtAmount() {
if (this.overrideLookAt === "block") {
return 0 < this.outputWeight ? 1 : 0;
} else if (this.overrideLookAt === "blend") {
return this.outputWeight;
} else {
return 0;
}
}
/**
* A value represents how much it should override mouth expressions.
* `0.0` == no override at all, `1.0` == completely block the expressions.
*/
get overrideMouthAmount() {
if (this.overrideMouth === "block") {
return 0 < this.outputWeight ? 1 : 0;
} else if (this.overrideMouth === "blend") {
return this.outputWeight;
} else {
return 0;
}
}
/**
* An output weight of this expression, considering the {@link isBinary}.
*/
get outputWeight() {
if (this.isBinary) {
return this.weight > 0.5 ? 1 : 0;
}
return this.weight;
}
/**
* Add an expression bind to the expression.
*
* @param bind A bind to add
*/
addBind(bind) {
this._binds.push(bind);
}
/**
* Delete an expression bind from the expression.
*
* @param bind A bind to delete
*/
deleteBind(bind) {
const index = this._binds.indexOf(bind);
if (index >= 0) {
this._binds.splice(index, 1);
}
}
/**
* Apply weight to every assigned blend shapes.
* Should be called every frame.
*/
applyWeight(options) {
var _a;
let actualWeight = this.outputWeight;
actualWeight *= (_a = options == null ? void 0 : options.multiplier) != null ? _a : 1;
if (this.isBinary && actualWeight < 1) {
actualWeight = 0;
}
this._binds.forEach((bind) => bind.applyWeight(actualWeight));
}
/**
* Clear previously assigned blend shapes.
*/
clearAppliedWeight() {
this._binds.forEach((bind) => bind.clearAppliedWeight());
}
};
function extractPrimitivesInternal(gltf, nodeIndex, node) {
var _a, _b;
const json = gltf.parser.json;
const schemaNode = (_a = json.nodes) == null ? void 0 : _a[nodeIndex];
if (schemaNode == null) {
console.warn(`extractPrimitivesInternal: Attempt to use nodes[${nodeIndex}] of glTF but the node doesn't exist`);
return null;
}
const meshIndex = schemaNode.mesh;
if (meshIndex == null) {
return null;
}
const schemaMesh = (_b = json.meshes) == null ? void 0 : _b[meshIndex];
if (schemaMesh == null) {
console.warn(`extractPrimitivesInternal: Attempt to use meshes[${meshIndex}] of glTF but the mesh doesn't exist`);
return null;
}
const primitiveCount = schemaMesh.primitives.length;
const primitives = [];
node.traverse((object) => {
if (primitives.length < primitiveCount) {
if (object.isMesh) {
primitives.push(object);
}
}
});
return primitives;
}
function gltfExtractPrimitivesFromNode(gltf, nodeIndex) {
return __async2(this, null, function* () {
const node = yield gltf.parser.getDependency("node", nodeIndex);
return extractPrimitivesInternal(gltf, nodeIndex, node);
});
}
function gltfExtractPrimitivesFromNodes(gltf) {
return __async2(this, null, function* () {
const nodes = yield gltf.parser.getDependencies("node");
const map = /* @__PURE__ */ new Map();
nodes.forEach((node, index) => {
const result = extractPrimitivesInternal(gltf, index, node);
if (result != null) {
map.set(index, result);
}
});
return map;
});
}
var VRMExpressionPresetName = {
Aa: "aa",
Ih: "ih",
Ou: "ou",
Ee: "ee",
Oh: "oh",
Blink: "blink",
Happy: "happy",
Angry: "angry",
Sad: "sad",
Relaxed: "relaxed",
LookUp: "lookUp",
Surprised: "surprised",
LookDown: "lookDown",
LookLeft: "lookLeft",
LookRight: "lookRight",
BlinkLeft: "blinkLeft",
BlinkRight: "blinkRight",
Neutral: "neutral"
};
function saturate(value) {
return Math.max(Math.min(value, 1), 0);
}
var VRMExpressionManager = class _VRMExpressionManager {
/**
* Create a new {@link VRMExpressionManager}.
*/
constructor() {
this.blinkExpressionNames = ["blink", "blinkLeft", "blinkRight"];
this.lookAtExpressionNames = ["lookLeft", "lookRight", "lookUp", "lookDown"];
this.mouthExpressionNames = ["aa", "ee", "ih", "oh", "ou"];
this._expressions = [];
this._expressionMap = {};
}
get expressions() {
return this._expressions.concat();
}
get expressionMap() {
return Object.assign({}, this._expressionMap);
}
/**
* A map from name to expression, but excluding custom expressions.
*/
get presetExpressionMap() {
const result = {};
const presetNameSet = new Set(Object.values(VRMExpressionPresetName));
Object.entries(this._expressionMap).forEach(([name, expression]) => {
if (presetNameSet.has(name)) {
result[name] = expression;
}
});
return result;
}
/**
* A map from name to expression, but excluding preset expressions.
*/
get customExpressionMap() {
const result = {};
const presetNameSet = new Set(Object.values(VRMExpressionPresetName));
Object.entries(this._expressionMap).forEach(([name, expression]) => {
if (!presetNameSet.has(name)) {
result[name] = expression;
}
});
return result;
}
/**
* Copy the given {@link VRMExpressionManager} into this one.
* @param source The {@link VRMExpressionManager} you want to copy
* @returns this
*/
copy(source) {
const expressions = this._expressions.concat();
expressions.forEach((expression) => {
this.unregisterExpression(expression);
});
source._expressions.forEach((expression) => {
this.registerExpression(expression);
});
this.blinkExpressionNames = source.blinkExpressionNames.concat();
this.lookAtExpressionNames = source.lookAtExpressionNames.concat();
this.mouthExpressionNames = source.mouthExpressionNames.concat();
return this;
}
/**
* Returns a clone of this {@link VRMExpressionManager}.
* @returns Copied {@link VRMExpressionManager}
*/
clone() {
return new _VRMExpressionManager().copy(this);
}
/**
* Return a registered expression.
* If it cannot find an expression, it will return `null` instead.
*
* @param name Name or preset name of the expression
*/
getExpression(name) {
var _a;
return (_a = this._expressionMap[name]) != null ? _a : null;
}
/**
* Register an expression.
*
* @param expression {@link VRMExpression} that describes the expression
*/
registerExpression(expression) {
this._expressions.push(expression);
this._expressionMap[expression.expressionName] = expression;
}
/**
* Unregister an expression.
*
* @param expression The expression you want to unregister
*/
unregisterExpression(expression) {
const index = this._expressions.indexOf(expression);
if (index === -1) {
console.warn("VRMExpressionManager: The specified expressions is not registered");
}
this._expressions.splice(index, 1);
delete this._expressionMap[expression.expressionName];
}
/**
* Get the current weight of the specified expression.
* If it doesn't have an expression of given name, it will return `null` instead.
*
* @param name Name of the expression
*/
getValue(name) {
var _a;
const expression = this.getExpression(name);
return (_a = expression == null ? void 0 : expression.weight) != null ? _a : null;
}
/**
* Set a weight to the specified expression.
*
* @param name Name of the expression
* @param weight Weight
*/
setValue(name, weight) {
const expression = this.getExpression(name);
if (expression) {
expression.weight = saturate(weight);
}
}
/**
* Reset weights of all expressions to `0.0`.
*/
resetValues() {
this._expressions.forEach((expression) => {
expression.weight = 0;
});
}
/**
* Get a track name of specified expression.
* This track name is needed to manipulate its expression via keyframe animations.
*
* @example Manipulate an expression using keyframe animation
* ```js
* const trackName = vrm.expressionManager.getExpressionTrackName( 'blink' );
* const track = new THREE.NumberKeyframeTrack(
* name,
* [ 0.0, 0.5, 1.0 ], // times
* [ 0.0, 1.0, 0.0 ] // values
* );
*
* const clip = new THREE.AnimationClip(
* 'blink', // name
* 1.0, // duration
* [ track ] // tracks
* );
*
* const mixer = new THREE.AnimationMixer( vrm.scene );
* const action = mixer.clipAction( clip );
* action.play();
* ```
*
* @param name Name of the expression
*/
getExpressionTrackName(name) {
const expression = this.getExpression(name);
return expression ? `${expression.name}.weight` : null;
}
/**
* Update every expressions.
*/
update() {
const weightMultipliers = this._calculateWeightMultipliers();
this._expressions.forEach((expression) => {
expression.clearAppliedWeight();
});
this._expressions.forEach((expression) => {
let multiplier = 1;
const name = expression.expressionName;
if (this.blinkExpressionNames.indexOf(name) !== -1) {
multiplier *= weightMultipliers.blink;
}
if (this.lookAtExpressionNames.indexOf(name) !== -1) {
multiplier *= weightMultipliers.lookAt;
}
if (this.mouthExpressionNames.indexOf(name) !== -1) {
multiplier *= weightMultipliers.mouth;
}
expression.applyWeight({ multiplier });
});
}
/**
* Calculate sum of override amounts to see how much we should multiply weights of certain expressions.
*/
_calculateWeightMultipliers() {
let blink = 1;
let lookAt = 1;
let mouth = 1;
this._expressions.forEach((expression) => {
blink -= expression.overrideBlinkAmount;
lookAt -= expression.overrideLookAtAmount;
mouth -= expression.overrideMouthAmount;
});
blink = Math.max(0, blink);
lookAt = Math.max(0, lookAt);
mouth = Math.max(0, mouth);
return { blink, lookAt, mouth };
}
};
var VRMExpressionMaterialColorType = {
Color: "color",
EmissionColor: "emissionColor",
ShadeColor: "shadeColor",
MatcapColor: "matcapColor",
RimColor: "rimColor",
OutlineColor: "outlineColor"
};
var v0ExpressionMaterialColorMap = {
_Color: VRMExpressionMaterialColorType.Color,
_EmissionColor: VRMExpressionMaterialColorType.EmissionColor,
_ShadeColor: VRMExpressionMaterialColorType.ShadeColor,
_RimColor: VRMExpressionMaterialColorType.RimColor,
_OutlineColor: VRMExpressionMaterialColorType.OutlineColor
};
var _color = new THREE2.Color();
var _VRMExpressionMaterialColorBind = class _VRMExpressionMaterialColorBind2 {
constructor({
material,
type,
targetValue,
targetAlpha
}) {
this.material = material;
this.type = type;
this.targetValue = targetValue;
this.targetAlpha = targetAlpha != null ? targetAlpha : 1;
const color = this._initColorBindState();
const alpha = this._initAlphaBindState();
this._state = { color, alpha };
}
applyWeight(weight) {
const { color, alpha } = this._state;
if (color != null) {
const { propertyName, deltaValue } = color;
const target = this.material[propertyName];
if (target != void 0) {
target.add(_color.copy(deltaValue).multiplyScalar(weight));
}
}
if (alpha != null) {
const { propertyName, deltaValue } = alpha;
const target = this.material[propertyName];
if (target != void 0) {
this.material[propertyName] += deltaValue * weight;
}
}
}
clearAppliedWeight() {
const { color, alpha } = this._state;
if (color != null) {
const { propertyName, initialValue } = color;
const target = this.material[propertyName];
if (target != void 0) {
target.copy(initialValue);
}
}
if (alpha != null) {
const { propertyName, initialValue } = alpha;
const target = this.material[propertyName];
if (target != void 0) {
this.material[propertyName] = initialValue;
}
}
}
_initColorBindState() {
var _a, _b, _c;
const { material, type, targetValue } = this;
const propertyNameMap = this._getPropertyNameMap();
const propertyName = (_b = (_a = propertyNameMap == null ? void 0 : propertyNameMap[type]) == null ? void 0 : _a[0]) != null ? _b : null;
if (propertyName == null) {
console.warn(
`Tried to add a material color bind to the material ${(_c = material.name) != null ? _c : "(no name)"}, the type ${type} but the material or the type is not supported.`
);
return null;
}
const target = material[propertyName];
const initialValue = target.clone();
const deltaValue = new THREE2.Color(
targetValue.r - initialValue.r,
targetValue.g - initialValue.g,
targetValue.b - initialValue.b
);
return { propertyName, initialValue, deltaValue };
}
_initAlphaBindState() {
var _a, _b, _c;
const { material, type, targetAlpha } = this;
const propertyNameMap = this._getPropertyNameMap();
const propertyName = (_b = (_a = propertyNameMap == null ? void 0 : propertyNameMap[type]) == null ? void 0 : _a[1]) != null ? _b : null;
if (propertyName == null && targetAlpha !== 1) {
console.warn(
`Tried to add a material alpha bind to the material ${(_c = material.name) != null ? _c : "(no name)"}, the type ${type} but the material or the type does not support alpha.`
);
return null;
}
if (propertyName == null) {
return null;
}
const initialValue = material[propertyName];
const deltaValue = targetAlpha - initialValue;
return { propertyName, initialValue, deltaValue };
}
_getPropertyNameMap() {
var _a, _b;
return (_b = (_a = Object.entries(_VRMExpressionMaterialColorBind2._propertyNameMapMap).find(([distinguisher]) => {
return this.material[distinguisher] === true;
})) == null ? void 0 : _a[1]) != null ? _b : null;
}
};
_VRMExpressionMaterialColorBind._propertyNameMapMap = {
isMeshStandardMaterial: {
color: ["color", "opacity"],
emissionColor: ["emissive", null]
},
isMeshBasicMaterial: {
color: ["color", "opacity"]
},
isMToonMaterial: {
color: ["color", "opacity"],
emissionColor: ["emissive", null],
outlineColor: ["outlineColorFactor", null],
matcapColor: ["matcapFactor", null],
rimColor: ["parametricRimColorFactor", null],
shadeColor: ["shadeColorFactor", null]
}
};
var VRMExpressionMaterialColorBind = _VRMExpressionMaterialColorBind;
var VRMExpressionMorphTargetBind = class {
constructor({
primitives,
index,
weight
}) {
this.primitives = primitives;
this.index = index;
this.weight = weight;
}
applyWeight(weight) {
this.primitives.forEach((mesh) => {
var _a;
if (((_a = mesh.morphTargetInfluences) == null ? void 0 : _a[this.index]) != null) {
mesh.morphTargetInfluences[this.index] += this.weight * weight;
}
});
}
clearAppliedWeight() {
this.primitives.forEach((mesh) => {
var _a;
if (((_a = mesh.morphTargetInfluences) == null ? void 0 : _a[this.index]) != null) {
mesh.morphTargetInfluences[this.index] = 0;
}
});
}
};
var _v2 = new THREE3.Vector2();
var _VRMExpressionTextureTransformBind = class _VRMExpressionTextureTransformBind2 {
constructor({
material,
scale,
offset
}) {
var _a, _b;
this.material = material;
this.scale = scale;
this.offset = offset;
const propertyNames = (_a = Object.entries(_VRMExpressionTextureTransformBind2._propertyNamesMap).find(
([distinguisher]) => {
return material[distinguisher] === true;
}
)) == null ? void 0 : _a[1];
if (propertyNames == null) {
console.warn(
`Tried to add a texture transform bind to the material ${(_b = material.name) != null ? _b : "(no name)"} but the material is not supported.`
);
this._properties = [];
} else {
this._properties = [];
propertyNames.forEach((propertyName) => {
var _a2;
const texture = (_a2 = material[propertyName]) == null ? void 0 : _a2.clone();
if (!texture) {
return null;
}
material[propertyName] = texture;
const initialOffset = texture.offset.clone();
const initialScale = texture.repeat.clone();
const deltaOffset = offset.clone().sub(initialOffset);
const deltaScale = scale.clone().sub(initialScale);
this._properties.push({
name: propertyName,
initialOffset,
deltaOffset,
initialScale,
deltaScale
});
});
}
}
applyWeight(weight) {
this._properties.forEach((property) => {
const target = this.material[property.name];
if (target === void 0) {
return;
}
target.offset.add(_v2.copy(property.deltaOffset).multiplyScalar(weight));
target.repeat.add(_v2.copy(property.deltaScale).multiplyScalar(weight));
});
}
clearAppliedWeight() {
this._properties.forEach((property) => {
const target = this.material[property.name];
if (target === void 0) {
return;
}
target.offset.copy(property.initialOffset);
target.repeat.copy(property.initialScale);
});
}
};
_VRMExpressionTextureTransformBind._propertyNamesMap = {
isMeshStandardMaterial: [
"map",
"emissiveMap",
"bumpMap",
"normalMap",
"displacementMap",
"roughnessMap",
"metalnessMap",
"alphaMap"
],
isMeshBasicMaterial: ["map", "specularMap", "alphaMap"],
isMToonMaterial: [
"map",
"normalMap",
"emissiveMap",
"shadeMultiplyTexture",
"rimMultiplyTexture",
"outlineWidthMultiplyTexture",
"uvAnimationMaskTexture"
]
};
var VRMExpressionTextureTransformBind = _VRMExpressionTextureTransformBind;
var POSSIBLE_SPEC_VERSIONS = /* @__PURE__ */ new Set(["1.0", "1.0-beta"]);
var _VRMExpressionLoaderPlugin = class _VRMExpressionLoaderPlugin2 {
get name() {
return "VRMExpressionLoaderPlugin";
}
constructor(parser) {
this.parser = parser;
}
afterRoot(gltf) {
return __async2(this, null, function* () {
gltf.userData.vrmExpressionManager = yield this._import(gltf);
});
}
/**
* Import a {@link VRMExpressionManager} from a VRM.
*
* @param gltf A parsed result of GLTF taken from GLTFLoader
*/
_import(gltf) {
return __async2(this, null, function* () {
const v1Result = yield this._v1Import(gltf);
if (v1Result) {
return v1Result;
}
const v0Result = yield this._v0Import(gltf);
if (v0Result) {
return v0Result;
}
return null;
});
}
_v1Import(gltf) {
return __async2(this, null, function* () {
var _a, _b;
const json = this.parser.json;
const isVRMUsed = ((_a = json.extensionsUsed) == null ? void 0 : _a.indexOf("VRMC_vrm")) !== -1;
if (!isVRMUsed) {
return null;
}
const extension = (_b = json.extensions) == null ? void 0 : _b["VRMC_vrm"];
if (!extension) {
return null;
}
const specVersion = extension.specVersion;
if (!POSSIBLE_SPEC_VERSIONS.has(specVersion)) {
console.warn(`VRMExpressionLoaderPlugin: Unknown VRMC_vrm specVersion "${specVersion}"`);
return null;
}
const schemaExpressions = extension.expressions;
if (!schemaExpressions) {
return null;
}
const presetNameSet = new Set(Object.values(VRMExpressionPresetName));
const nameSchemaExpressionMap = /* @__PURE__ */ new Map();
if (schemaExpressions.preset != null) {
Object.entries(schemaExpressions.preset).forEach(([name, schemaExpression]) => {
if (schemaExpression == null) {
return;
}
if (!presetNameSet.has(name)) {
console.warn(`VRMExpressionLoaderPlugin: Unknown preset name "${name}" detected. Ignoring the expression`);
return;
}
nameSchemaExpressionMap.set(name, schemaExpression);
});
}
if (schemaExpressions.custom != null) {
Object.entries(schemaExpressions.custom).forEach(([name, schemaExpression]) => {
if (presetNameSet.has(name)) {
console.warn(
`VRMExpressionLoaderPlugin: Custom expression cannot have preset name "${name}". Ignoring the expression`
);
return;
}
nameSchemaExpressionMap.set(name, schemaExpression);
});
}
const manager = new VRMExpressionManager();
yield Promise.all(
Array.from(nameSchemaExpressionMap.entries()).map((_0) => __async2(this, [_0], function* ([name, schemaExpression]) {
var _a2, _b2, _c, _d, _e, _f, _g;
const expression = new VRMExpression(name);
gltf.scene.add(expression);
expression.isBinary = (_a2 = schemaExpression.isBinary) != null ? _a2 : false;
expression.overrideBlink = (_b2 = schemaExpression.overrideBlink) != null ? _b2 : "none";
expression.overrideLookAt = (_c = schemaExpression.overrideLookAt) != null ? _c : "none";
expression.overrideMouth = (_d = schemaExpression.overrideMouth) != null ? _d : "none";
(_e = schemaExpression.morphTargetBinds) == null ? void 0 : _e.forEach((bind) => __async2(this, null, function* () {
var _a3;
if (bind.node === void 0 || bind.index === void 0) {
return;
}
const primitives = yield gltfExtractPrimitivesFromNode(gltf, bind.node);
const morphTargetIndex = bind.index;
if (!primitives.every(
(primitive) => Array.isArray(primitive.morphTargetInfluences) && morphTargetIndex < primitive.morphTargetInfluences.length
)) {
console.warn(
`VRMExpressionLoaderPlugin: ${schemaExpression.name} attempts to index morph #${morphTargetIndex} but not found.`
);
return;
}
expression.addBind(
new VRMExpressionMorphTargetBind({
primitives,
index: morphTargetIndex,
weight: (_a3 = bind.weight) != null ? _a3 : 1
})
);
}));
if (schemaExpression.materialColorBinds || schemaExpression.textureTransformBinds) {
const gltfMaterials = [];
gltf.scene.traverse((object) => {
const material = object.material;
if (material) {
if (Array.isArray(material)) {
gltfMaterials.push(...material);
} else {
gltfMaterials.push(material);
}
}
});
(_f = schemaExpression.materialColorBinds) == null ? void 0 : _f.forEach((bind) => __async2(this, null, function* () {
const materials = gltfMaterials.filter((material) => {
var _a3;
const materialIndex = (_a3 = this.parser.associations.get(material)) == null ? void 0 : _a3.materials;
return bind.material === materialIndex;
});
materials.forEach((material) => {
expression.addBind(
new VRMExpressionMaterialColorBind({
material,
type: bind.type,
targetValue: new THREE4.Color().fromArray(bind.targetValue),
targetAlpha: bind.targetValue[3]
})
);
});
}));
(_g = schemaExpression.textureTransformBinds) == null ? void 0 : _g.forEach((bind) => __async2(this, null, function* () {
const materials = gltfMaterials.filter((material) => {
var _a3;
const materialIndex = (_a3 = this.parser.associations.get(material)) == null ? void 0 : _a3.materials;
return bind.material === materialIndex;
});
materials.forEach((material) => {
var _a3, _b3;
expression.addBind(
new VRMExpressionTextureTransformBind({
material,
offset: new THREE4.Vector2().fromArray((_a3 = bind.offset) != null ? _a3 : [0, 0]),
scale: new THREE4.Vector2().fromArray((_b3 = bind.scale) != null ? _b3 : [1, 1])
})
);
});
}));
}
manager.registerExpression(expression);
}))
);
return manager;
});
}
_v0Import(gltf) {
return __async2(this, null, function* () {
var _a;
const json = this.parser.json;
const vrmExt = (_a = json.extensions) == null ? void 0 : _a.VRM;
if (!vrmExt) {
return null;
}
const schemaBlendShape = vrmExt.blendShapeMaster;
if (!schemaBlendShape) {
return null;
}
const manager = new VRMExpressionManager();
const schemaBlendShapeGroups = schemaBlendShape.blendShapeGroups;
if (!schemaBlendShapeGroups) {
return manager;
}
const blendShapeNameSet = /* @__PURE__ */ new Set();
yield Promise.all(
schemaBlendShapeGroups.map((schemaGroup) => __async2(this, null, function* () {
var _a2;
const v0PresetName = schemaGroup.presetName;
const v1PresetName = v0PresetName != null && _VRMExpressionLoaderPlugin2.v0v1PresetNameMap[v0PresetName] || null;
const name = v1PresetName != null ? v1PresetName : schemaGroup.name;
if (name == null) {
console.warn("VRMExpressionLoaderPlugin: One of custom expressions has no name. Ignoring the expression");
return;
}
if (blendShapeNameSet.has(name)) {
console.warn(
`VRMExpressionLoaderPlugin: An expression preset ${v0PresetName} has duplicated entries. Ignoring the expression`
);
return;
}
blendShapeNameSet.add(name);
const expression = new VRMExpression(name);
gltf.scene.add(expression);
expression.isBinary = (_a2 = schemaGroup.isBinary) != null ? _a2 : false;
if (schemaGroup.binds) {
schemaGroup.binds.forEach((bind) => __async2(this, null, function* () {
var _a3;
if (bind.mesh === void 0 || bind.index === void 0) {
return;
}
const nodesUsingMesh = [];
(_a3 = json.nodes) == null ? void 0 : _a3.forEach((node, i) => {
if (node.mesh === bind.mesh) {
nodesUsingMesh.push(i);
}
});
const morphTargetIndex = bind.index;
yield Promise.all(
nodesUsingMesh.map((nodeIndex) => __async2(this, null, function* () {
var _a4;
const primitives = yield gltfExtractPrimitivesFromNode(gltf, nodeIndex);
if (!primitives.every(
(primitive) => Array.isArray(primitive.morphTargetInfluences) && morphTargetIndex < primitive.morphTargetInfluences.length
)) {
console.warn(
`VRMExpressionLoaderPlugin: ${schemaGroup.name} attempts to index ${morphTargetIndex}th morph but not found.`
);
return;
}
expression.addBind(
new VRMExpressionMorphTargetBind({
primitives,
index: morphTargetIndex,
weight: 0.01 * ((_a4 = bind.weight) != null ? _a4 : 100)
// narrowing the range from [ 0.0 - 100.0 ] to [ 0.0 - 1.0 ]
})
);
}))
);
}));
}
const materialValues = schemaGroup.materialValues;
if (materialValues && materialValues.length !== 0) {
materialValues.forEach((materialValue) => {
if (materialValue.materialName === void 0 || materialValue.propertyName === void 0 || materialValue.targetValue === void 0) {
return;
}
const materials = [];
gltf.scene.traverse((object) => {
if (object.material) {
const material = object.material;
if (Array.isArray(material)) {
materials.push(
...material.filter(
(mtl) => (mtl.name === materialValue.materialName || mtl.name === materialValue.materialName + " (Outline)") && materials.indexOf(mtl) === -1
)
);
} else if (material.name === materialValue.materialName && materials.indexOf(material) === -1) {
materials.push(material);
}
}
});
const materialPropertyName = materialValue.propertyName;
materials.forEach((material) => {
if (materialPropertyName === "_MainTex_ST") {
const scale = new THREE4.Vector2(materialValue.targetValue[0], materialValue.targetValue[1]);
const offset = new THREE4.Vector2(materialValue.targetValue[2], materialValue.targetValue[3]);
offset.y = 1 - offset.y - scale.y;
expression.addBind(
new VRMExpressionTextureTransformBind({
material,
scale,
offset
})
);
return;
}
const materialColorType = v0ExpressionMaterialColorMap[materialPropertyName];
if (materialColorType) {
expression.addBind(
new VRMExpressionMaterialColorBind({
material,
type: materialColorType,
targetValue: new THREE4.Color().fromArray(materialValue.targetValue),
targetAlpha: materialValue.targetValue[3]
})
);
return;
}
console.warn(materialPropertyName + " is not supported");
});
});
}
manager.registerExpression(expression);
}))
);
return manager;
});
}
};
_VRMExpressionLoaderPlugin.v0v1PresetNameMap = {
a: "aa",
e: "ee",
i: "ih",
o: "oh",
u: "ou",
blink: "blink",
joy: "happy",
angry: "angry",
sorrow: "sad",
fun: "relaxed",
lookup: "lookUp",
lookdown: "lookDown",
lookleft: "lookLeft",
lookright: "lookRight",
// eslint-disable-next-line @typescript-eslint/naming-convention
blink_l: "blinkLeft",
// eslint-disable-next-line @typescript-eslint/naming-convention
blink_r: "blinkRight",
neutral: "neutral"
};
var VRMExpressionLoaderPlugin = _VRMExpressionLoaderPlugin;
var VRMExpressionOverrideType = {
None: "none",
Block: "block",
Blend: "blend"
};
var _VRMFirstPerson = class _VRMFirstPerson2 {
/**
* Create a new VRMFirstPerson object.
*
* @param humanoid A {@link VRMHumanoid}
* @param meshAnnotations A {@link VRMFirstPersonMeshAnnotation}
*/
constructor(humanoid, meshAnnotations) {
this._firstPersonOnlyLayer = _VRMFirstPerson2.DEFAULT_FIRSTPERSON_ONLY_LAYER;
this._thirdPersonOnlyLayer = _VRMFirstPerson2.DEFAULT_THIRDPERSON_ONLY_LAYER;
this._initializedLayers = false;
this.humanoid = humanoid;
this.meshAnnotations = meshAnnotations;
}
/**
* Copy the given {@link VRMFirstPerson} into this one.
* {@link humanoid} must be same as the source one.
* @param source The {@link VRMFirstPerson} you want to copy
* @returns this
*/
copy(source) {
if (this.humanoid !== source.humanoid) {
throw new Error("VRMFirstPerson: humanoid must be same in order to copy");
}
this.meshAnnotations = source.meshAnnotations.map((annotation) => ({
meshes: annotation.meshes.concat(),
type: annotation.type
}));
return this;
}
/**
* Returns a clone of this {@link VRMFirstPerson}.
* @returns Copied {@link VRMFirstPerson}
*/
clone() {
return new _VRMFirstPerson2(this.humanoid, this.meshAnnotations).copy(this);
}
/**
* A camera layer represents `FirstPersonOnly` layer.
* Note that **you must call {@link setup} first before you use the layer feature** or it does not work properly.
*
* The value is {@link DEFAULT_FIRSTPERSON_ONLY_LAYER} by default but you can change the layer by specifying via {@link setup} if you prefer.
*
* @see https://vrm.dev/en/univrm/api/univrm_use_firstperson/
* @see https://threejs.org/docs/#api/en/core/Layers
*/
get firstPersonOnlyLayer() {
return this._firstPersonOnlyLayer;
}
/**
* A camera layer represents `ThirdPersonOnly` layer.
* Note that **you must call {@link setup} first before you use the layer feature** or it does not work properly.
*
* The value is {@link DEFAULT_THIRDPERSON_ONLY_LAYER} by default but you can change the layer by specifying via {@link setup} if you prefer.
*
* @see https://vrm.dev/en/univrm/api/univrm_use_firstperson/
* @see https://threejs.org/docs/#api/en/core/Layers
*/
get thirdPersonOnlyLayer() {
return this._thirdPersonOnlyLayer;
}
/**
* In this method, it assigns layers for every meshes based on mesh annotations.
* You must call this method first before you use the layer feature.
*
* 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.
*
* The `cameraLayer` parameter specifies which layer will be assigned for `FirstPersonOnly` / `ThirdPersonOnly`.
* In UniVRM, we specified those by naming each desired layer as `FIRSTPERSON_ONLY_LAYER` / `THIRDPERSON_ONLY_LAYER`
* but we are going to specify these layers at here since we are unable to name layers in Three.js.
*
* @param cameraLayer Specify which layer will be for `FirstPersonOnly` / `ThirdPersonOnly`.
*/
setup({
firstPersonOnlyLayer = _VRMFirstPerson2.DEFAULT_FIRSTPERSON_ONLY_LAYER,
thirdPersonOnlyLayer = _VRMFirstPerson2.DEFAULT_THIRDPERSON_ONLY_LAYER
} = {}) {
if (this._initializedLayers) {
return;
}
this._firstPersonOnlyLayer = firstPersonOnlyLayer;
this._thirdPersonOnlyLayer = thirdPersonOnlyLayer;
this.meshAnnotations.forEach((item) => {
item.meshes.forEach((mesh) => {
if (item.type === "firstPersonOnly") {
mesh.layers.set(this._firstPersonOnlyLayer);
mesh.traverse((child) => child.layers.set(this._firstPersonOnlyLayer));
} else if (item.type === "thirdPersonOnly") {
mesh.layers.set(this._thirdPersonOnlyLayer);
mesh.traverse((child) => child.layers.set(this._thirdPersonOnlyLayer));
} else if (item.type === "auto") {
this._createHeadlessModel(mesh);
}
});
});
this._initializedLayers = true;
}
_excludeTriangles(triangles, bws, skinIndex, exclude) {
let count = 0;
if (bws != null && bws.length > 0) {
for (let i = 0; i < triangles.length; i += 3) {
const a = triangles[i];
const b = triangles[i + 1];
const c = triangles[i + 2];
const bw0 = bws[a];
const skin0 = skinIndex[a];
if (bw0[0] > 0 && exclude.includes(skin0[0])) continue;
if (bw0[1] > 0 && exclude.includes(skin0[1])) continue;
if (bw0[2] > 0 && exclude.includes(skin0[2])) continue;
if (bw0[3] > 0 && exclude.includes(skin0[3])) continue;
const bw1 = bws[b];
const skin1 = skinIndex[b];
if (bw1[0] > 0 && exclude.includes(skin1[0])) continue;
if (bw1[1] > 0 && exclude.includes(skin1[1])) continue;
if (bw1[2] > 0 && exclude.includes(skin1[2])) continue;
if (bw1[3] > 0 && exclude.includes(skin1[3])) continue;
const bw2 = bws[c];
const skin2 = skinIndex[c];
if (bw2[0] > 0 && exclude.includes(skin2[0])) continue;
if (bw2[1] > 0 && exclude.includes(skin2[1])) continue;
if (bw2[2] > 0 && exclude.includes(skin2[2])) continue;
if (bw2[3] > 0 && exclude.includes(skin2[3])) continue;
triangles[count++] = a;
triangles[count++] = b;
triangles[count++] = c;
}
}
return count;
}
_createErasedMesh(src, erasingBonesIndex) {
const dst = new THREE5.SkinnedMesh(src.geometry.clone(), src.material);
dst.name = `${src.name}(erase)`;
dst.frustumCulled = src.frustumCulled;
dst.layers.set(this._firstPersonOnlyLayer);
const geometry = dst.geometry;
const skinIndexAttr = geometry.getAttribute("skinIndex");
const skinIndexAttrArray = skinIndexAttr instanceof THREE5.GLBufferAttribute ? [] : skinIndexAttr.array;
const skinIndex = [];
for (let i = 0; i < skinIndexAttrArray.length; i += 4) {
skinIndex.push([
skinIndexAttrArray[i],
skinIndexAttrArray[i + 1],
skinIndexAttrArray[i + 2],
skinIndexAttrArray[i + 3]
]);
}
const skinWeightAttr = geometry.getAttribute("skinWeight");
const skinWeightAttrArray = skinWeightAttr instanceof THREE5.GLBufferAttribute ? [] : skinWeightAttr.array;
const skinWeight = [];
for (let i = 0; i < skinWeightAttrArray.length; i += 4) {
skinWeight.push([
skinWeightAttrArray[i],
skinWeightAttrArray[i + 1],
skinWeightAttrArray[i + 2],
skinWeightAttrArray[i + 3]
]);
}
const index = geometry.getIndex();
if (!index) {
throw new Error("The geometry doesn't have an index buffer");
}
const oldTriangles = Array.from(index.array);
const count = this._excludeTriangles(oldTriangles, skinWeight, skinIndex, erasingBonesIndex);
const newTriangle = [];
for (let i = 0; i < count; i++) {
newTriangle[i] = oldTriangles[i];
}
geometry.setIndex(newTriangle);
if (src.onBeforeRender) {
dst.onBeforeRender = src.onBeforeRender;
}
dst.bind(new THREE5.Skeleton(src.skeleton.bones, src.skeleton.boneInverses), new THREE5.Matrix4());
return dst;
}
_createHeadlessModelForSkinnedMesh(parent, mesh) {
const eraseBoneIndexes = [];
mesh.skeleton.bones.forEach((bone, index) => {
if (this._isEraseTarget(bone)) eraseBoneIndexes.push(index);
});
if (!eraseBoneIndexes.length) {
mesh.layers.enable(this._thirdPersonOnlyLayer);
mesh.layers.enable(this._firstPersonOnlyLayer);
return;
}
mesh.layers.set(this._thirdPersonOnlyLayer);
const newMesh = this._createErasedMesh(mesh, eraseBoneIndexes);
parent.add(newMesh);
}
_createHeadlessModel(node) {
if (node.type === "Group") {
node.layers.set(this._thirdPersonOnlyLayer);
if (this._isEraseTarget(node)) {
node.traverse((child) => child.layers.set(this._thirdPersonOnlyLayer));
} else {
const parent = new THREE5.Group();
parent.name = `_headless_${node.name}`;
parent.layers.set(this._firstPersonOnlyLayer);
node.parent.add(parent);
node.children.filter((child) => child.type === "SkinnedMesh").forEach((child) => {
const skinnedMesh = child;
this._createHeadlessModelForSkinnedMesh(parent, skinnedMesh);
});
}
} else if (node.type === "SkinnedMesh") {
const skinnedMesh = node;
this._createHeadlessModelForSkinnedMesh(node.parent, skinnedMesh);
} else {
if (this._isEraseTarget(node)) {
node.layers.set(this._thirdPersonOnlyLayer);
node.traverse((child) => child.layers.set(this._thirdPersonOnlyLayer));
}
}
}
_isEraseTarget(bone) {
if (bone === this.humanoid.getRawBoneNode("head")) {
return true;
} else if (!bone.parent) {
return false;
} else {
return this._isEraseTarget(bone.parent);
}
}
};
_VRMFirstPerson.DEFAULT_FIRSTPERSON_ONLY_LAYER = 9;
_VRMFirstPerson.DEFAULT_THIRDPERSON_ONLY_LAYER = 10;
var VRMFirstPerson = _VRMFirstPerson;
var POSSIBLE_SPEC_VERSIONS2 = /* @__PURE__ */ new Set(["1.0", "1.0-beta"]);
var VRMFirstPersonLoaderPlugin = class {
get name() {
return "VRMFirstPersonLoaderPlugin";
}
constructor(parser) {
this.parser = parser;
}
afterRoot(gltf) {
return __async2(this, null, function* () {
const vrmHumanoid = gltf.userData.vrmHumanoid;
if (vrmHumanoid === null) {
return;
} else if (vrmHumanoid === void 0) {
throw new Error(
"VRMFirstPersonLoaderPlugin: vrmHumanoid is undefined. VRMHumanoidLoaderPlugin have to be used first"
);
}
gltf.userData.vrmFirstPerson = yield this._import(gltf, vrmHumanoid);
});
}
/**
* Import a {@link VRMFirstPerson} from a VRM.
*
* @param gltf A parsed result of GLTF taken from GLTFLoader
* @param humanoid A {@link VRMHumanoid} instance that represents the VRM
*/
_import(gltf, humanoid) {
return __async2(this, null, function* () {
if (humanoid == null) {
return null;
}
const v1Result = yield this._v1Import(gltf, humanoid);
if (v1Result) {
return v1Result;
}
const v0Result = yield this._v0Import(gltf, humanoid);
if (v0Result) {
return v0Result;
}
return null;
});
}
_v1Import(gltf, humanoid) {
return __async2(this, null, function* () {
var _a, _b;
const json = this.parser.json;
const isVRMUsed = ((_a = json.extensionsUsed) == null ? void 0 : _a.indexOf("VRMC_vrm")) !== -1;
if (!isVRMUsed) {
return null;
}
const extension = (_b = json.extensions) == null ? void 0 : _b["VRMC_vrm"];
if (!extension) {
return null;
}
const specVersion = extension.specVersion;
if (!POSSIBLE_SPEC_VERSIONS2.has(specVersion)) {
console.warn(`VRMFirstPersonLoaderPlugin: Unknown VRMC_vrm specVersion "${specVersion}"`);
return null;
}
const schemaFirstPerson = extension.firstPerson;
const meshAnnotations = [];
const nodePrimitivesMap = yield gltfExtractPrimitivesFromNodes(gltf);
Array.from(nodePrimitivesMap.entries()).forEach(([nodeIndex, primitives]) => {
var _a2, _b2;
const annotation = (_a2 = schemaFirstPerson == null ? void 0 : schemaFirstPerson.meshAnnotations) == null ? void 0 : _a2.find((a) => a.node === nodeIndex);
meshAnnotations.push({
meshes: primitives,
type: (_b2 = annotation == null ? void 0 : annotation.type) != null ? _b2 : "auto"
});
});
return new VRMFirstPerson(humanoid, meshAnnotations);
});
}
_v0Import(gltf, humanoid) {
return __async2(this, null, function* () {
var _a;
const json = this.parser.json;
const vrmExt = (_a = json.extensions) == null ? void 0 : _a.VRM;
if (!vrmExt) {
return null;
}
const schemaFirstPerson = vrmExt.firstPerson;
if (!schemaFirstPerson) {
return null;
}
const meshAnnotations = [];
const nodePrimitivesMap = yield gltfExtractPrimitivesFromNodes(gltf);
Array.from(nodePrimitivesMap.entries()).forEach(([nodeIndex, primitives]) => {
const schemaNode = json.nodes[nodeIndex];
const flag = schemaFirstPerson.meshAnnotations ? schemaFirstPerson.meshAnnotations.find((a) => a.mesh === schemaNode.mesh) : void 0;
meshAnnotations.push({
meshes: primitives,
type: this._convertV0FlagToV1Type(flag == null ? void 0 : flag.firstPersonFlag)
});
});
return new VRMFirstPerson(humanoid, meshAnnotations);
});
}
_convertV0FlagToV1Type(flag) {
if (flag === "FirstPersonOnly") {
return "firstPersonOnly";
} else if (flag === "ThirdPersonOnly") {
return "thirdPersonOnly";
} else if (flag === "Both") {
return "both";
} else {
return "auto";
}
}
};
var VRMFirstPersonMeshAnnotationType = {
Auto: "auto",
Both: "both",
ThirdPersonOnly: "thirdPersonOnly",
FirstPersonOnly: "firstPersonOnly"
};
var _v3A = new THREE6.Vector3();
var _v3B = new THREE6.Vector3();
var _quatA = new THREE6.Quaternion();
var VRMHumanoidHelper = class extends THREE6.Group {
constructor(humanoid) {
super();
this.vrmHumanoid = humanoid;
this._boneAxesMap = /* @__PURE__ */ new Map();
Object.values(humanoid.humanBones).forEach((bone) => {
const helper = new THREE6.AxesHelper(1);
helper.matrixAutoUpdate = false;
helper.material.depthTest = false;
helper.material.depthWrite = false;
this.add(helper);
this._boneAxesMap.set(bone, helper);
});
}
dispose() {
Array.from(this._boneAxesMap.values()).forEach((axes) => {
axes.geometry.dispose();
axes.material.dispose();
});
}
updateMatrixWorld(force) {
Array.from(this._boneAxesMap.entries()).forEach(([bone, axes]) => {
bone.node.updateWorldMatrix(true, false);
bone.node.matrixWorld.decompose(_v3A, _quatA, _v3B);
const scale = _v3A.set(0.1, 0.1, 0.1).divide(_v3B);
axes.matrix.copy(bone.node.matrixWorld).scale(scale);
});
super.updateMatrixWorld(force);
}
};
var VRMHumanBoneList = [
"hips",
"spine",
"chest",
"upperChest",
"neck",
"head",
"leftEye",
"rightEye",
"jaw",
"leftUpperLeg",
"leftLowerLeg",
"leftFoot",
"leftToes",
"rightUpperLeg",
"rightLowerLeg",
"rightFoot",
"rightToes",
"leftShoulder",
"leftUpperArm",
"leftLowerArm",
"leftHand",
"rightShoulder",
"rightUpperArm",
"rightLowerArm",
"rightHand",
"leftThumbMetacarpal",
"leftThumbProximal",
"leftThumbDistal",
"leftIndexProximal",
"leftIndexIntermediate",
"leftIndexDistal",
"leftMiddleProximal",
"leftMiddleIntermediate",
"leftMiddleDistal",
"leftRingProximal",
"leftRingIntermediate",
"leftRingDistal",
"leftLittleProximal",
"leftLittleIntermediate",
"leftLittleDistal",
"rightThumbMetacarpal",
"rightThumbProximal",
"rightThumbDistal",
"rightIndexProximal",
"rightIndexIntermediate",
"rightIndexDistal",
"rightMiddleProximal",
"rightMiddleIntermediate",
"rightMiddleDistal",
"rightRingProximal",
"rightRingIntermediate",
"rightRingDistal",
"rightLittleProximal",
"rightLittleIntermediate",
"rightLittleDistal"
];
var VRMHumanBoneName = {
Hips: "hips",
Spine: "spine",
Chest: "chest",
UpperChest: "upperChest",
Neck: "neck",
Head: "head",
LeftEye: "leftEye",
RightEye: "rightEye",
Jaw: "jaw",
LeftUpperLeg: "leftUpperLeg",
LeftLowerLeg: "leftLowerLeg",
LeftFoot: "leftFoot",
LeftToes: "leftToes",
RightUpperLeg: "rightUpperLeg",
RightLowerLeg: "rightLowerLeg",
RightFoot: "rightFoot",
RightToes: "rightToes",
LeftShoulder: "leftShoulder",
LeftUpperArm: "leftUpperArm",
LeftLowerArm: "leftLowerArm",
LeftHand: "leftHand",
RightShoulder: "rightShoulder",
RightUpperArm: "rightUpperArm",
RightLowerArm: "rightLowerArm",
RightHand: "rightHand",
LeftThumbMetacarpal: "leftThumbMetacarpal",
LeftThumbProximal: "leftThumbProximal",
LeftThumbDistal: "leftThumbDistal",
LeftIndexProximal: "leftIndexProximal",
LeftIndexIntermediate: "leftIndexIntermediate",
LeftIndexDistal: "leftIndexDistal",
LeftMiddleProximal: "leftMiddleProximal",
LeftMiddleIntermediate: "leftMiddleIntermediate",
LeftMiddleDistal: "leftMiddleDistal",
LeftRingProximal: "leftRingProximal",
LeftRingIntermediate: "leftRingIntermediate",
LeftRingDistal: "leftRingDistal",
LeftLittleProximal: "leftLittleProximal",
LeftLittleIntermediate: "leftLittleIntermediate",
LeftLittleDistal: "leftLittleDistal",
RightThumbMetacarpal: "rightThumbMetacarpal",
RightThumbProximal: "rightThumbProximal",
RightThumbDistal: "rightThumbDistal",
RightIndexProximal: "rightIndexProximal",
RightIndexIntermediate: "rightIndexIntermediate",
RightIndexDistal: "rightIndexDistal",
RightMiddleProximal: "rightMiddleProximal",
RightMiddleIntermediate: "rightMiddleIntermediate",
RightMiddleDistal: "rightMiddleDistal",
RightRingProximal: "rightRingProximal",
RightRingIntermediate: "rightRingIntermediate",
RightRingDistal: "rightRingDistal",
RightLittleProximal: "rightLittleProximal",
RightLittleIntermediate: "rightLittleIntermediate",
RightLittleDistal: "rightLittleDistal"
};
var VRMHumanBoneParentMap = {
hips: null,
spine: "hips",
chest: "spine",
upperChest: "chest",
neck: "upperChest",
head: "neck",
leftEye: "head",
rightEye: "head",
jaw: "head",
leftUpperLeg: "hips",
leftLowerLeg: "leftUpperLeg",
leftFoot: "leftLowerLeg",
leftToes: "leftFoot",
rightUpperLeg: "hips",
rightLowerLeg: "rightUpperLeg",
rightFoot: "rightLowerLeg",
rightToes: "rightFoot",
leftShoulder: "upperChest",
leftUpperArm: "leftShoulder",
leftLowerArm: "leftUpperArm",
leftHand: "leftLowerArm",
rightShoulder: "upperChest",
rightUpperArm: "rightShoulder",
rightLowerArm: "rightUpperArm",
rightHand: "rightLowerArm",
leftThumbMetacarpal: "leftHand",
leftThumbProximal: "leftThumbMetacarpal",
leftThumbDistal: "leftThumbProximal",
leftIndexProximal: "leftHand",
leftIndexIntermediate: "leftIndexProximal",
leftIndexDistal: "leftIndexIntermediate",
leftMiddleProximal: "leftHand",
leftMiddleIntermediate: "leftMiddleProximal",
leftMiddleDistal: "leftMiddleIntermediate",
leftRingProximal: "leftHand",
leftRingIntermediate: "leftRingProximal",
leftRingDistal: "leftRingIntermediate",
leftLittleProximal: "leftHand",
leftLittleIntermediate: "leftLittleProximal",
leftLittleDistal: "leftLittleIntermediate",
rightThumbMetacarpal: "rightHand",
rightThumbProximal: "rightThumbMetacarpal",
rightThumbDistal: "rightThumbProximal",
rightIndexProximal: "rightHand",
rightIndexIntermediate: "rightIndexProximal",
rightIndexDistal: "rightIndexIntermediate",
rightMiddleProximal: "rightHand",
rightMiddleIntermediate: "rightMiddleProximal",
rightMiddleDistal: "rightMiddleIntermediate",
rightRingProximal: "rightHand",
rightRingIntermediate: "rightRingProximal",
rightRingDistal: "rightRingIntermediate",
rightLittleProximal: "rightHand",
rightLittleIntermediate: "rightLittleProximal",
rightLittleDistal: "rightLittleIntermediate"
};
function quatInvertCompat(target) {
if (target.invert) {
target.invert();
} else {
target.inverse();
}
return target;
}
var _v3A2 = new THREE7.Vector3();
var _quatA2 = new THREE7.Quaternion();
var VRMRig = class {
/**
* Create a new {@link VRMHumanoid}.
* @param humanBones A {@link VRMHumanBones} contains all the bones of the new humanoid
*/
constructor(humanBones) {
this.humanBones = humanBones;
this.restPose = this.getAbsolutePose();
}
/**
* Return the current absolute pose of this humanoid as a {@link VRMPose}.
* Note that the output result will contain initial state of the VRM and not compatible between different models.
* You might want to use {@link getPose} instead.
*/
getAbsolutePose() {
const pose = {};
Object.keys(this.humanBones).forEach((vrmBoneNameString) => {
const vrmBoneName = vrmBoneNameString;
const node = this.getBoneNode(vrmBoneName);
if (!node) {
return;
}
_v3A2.copy(node.position);
_quatA2.copy(node.quaternion);
pose[vrmBoneName] = {
position: _v3A2.toArray(),
rotation: _quatA2.toArray()
};
});
return pose;
}
/**
* Return the current pose of this humanoid as a {@link VRMPose}.
*
* Each transform is a local transform relative from rest pose (T-pose).
*/
getPose() {
const pose = {};
Object.keys(this.humanBones).forEach((boneNameString) => {
const boneName = boneNameString;
const node = this.getBoneNode(boneName);
if (!node) {
return;
}
_v3A2.set(0, 0, 0);
_quatA2.identity();
const restState = this.restPose[boneName];
if (restState == null ? void 0 : restState.position) {
_v3A2.fromArray(restState.position).negate();
}
if (restState == null ? void 0 : restState.rotation) {
quatInvertCompat(_quatA2.fromArray(restState.rotation));
}
_v3A2.add(node.position);
_quatA2.premultiply(node.quaternion);
pose[boneName] = {
position: _v3A2.toArray(),
rotation: _quatA2.toArray()
};
});
return pose;
}
/**
* Let the humanoid do a specified pose.
*
* Each transform have to be a local transform relative from rest pose (T-pose).
* You can pass what you got from {@link getPose}.
*
* @param poseObject A {@link VRMPose} that represents a single pose
*/
setPose(poseObject) {
Object.entries(poseObject).forEach(([boneNameString, state]) => {
const boneName = boneNameString;
const node = this.getBoneNode(boneName);
if (!node) {
return;
}
const restState = this.restPose[boneName];
if (!restState) {
return;
}
if (state == null ? void 0 : state.position) {
node.position.fromArray(state.position);
if (restState.position) {
node.position.add(_v3A2.fromArray(restState.position));
}
}
if (state == null ? void 0 : state.rotation) {
node.quaternion.fromArray(state.rotation);
if (restState.rotation) {
node.quaternion.multiply(_quatA2.fromArray(restState.rotation));
}
}
});
}
/**
* Reset the humanoid to its rest pose.
*/
resetPose() {
Object.entries(this.restPose).forEach(([boneName, rest]) => {
const node = this.getBoneNode(boneName);
if (!node) {
return;
}
if (rest == null ? void 0 : rest.position) {
node.position.fromArray(rest.position);
}
if (rest == null ? void 0 : rest.rotation) {
node.quaternion.fromArray(rest.rotation);
}
});
}
/**
* Return a bone bound to a specified {@link VRMHumanBoneName}, as a {@link VRMHumanBone}.
*
* @param name Name of the bone you want
*/
getBone(name) {
var _a;
return (_a = this.humanBones[name]) != null ? _a : void 0;
}
/**
* Return a bone bound to a specified {@link VRMHumanBoneName}, as a `THREE.Object3D`.
*
* @param name Name of the bone you want
*/
getBoneNode(name) {
var _a, _b;
return (_b = (_a = this.humanBones[name]) == null ? void 0 : _a.node) != null ? _b : null;
}
};
var _v3A3 = new THREE8.Vector3();
var _quatA3 = new THREE8.Quaternion();
var _boneWorldPos = new THREE8.Vector3();
var VRMHumanoidRig = class _VRMHumanoidRig extends VRMRig {
static _setupTransforms(modelRig) {
const root = new THREE8.Object3D();
root.name = "VRMHumanoidRig";
const boneWorldPositions = {};
const boneWorldRotations = {};
const boneRotations = {};
const parentWorldRotations = {};
VRMHumanBoneList.forEach((boneName) => {
var _a;
const boneNode = modelRig.getBoneNode(boneName);
if (boneNode) {
const boneWorldPosition = new THREE8.Vector3();
const boneWorldRotation = new THREE8.Quaternion();
boneNode.updateWorldMatrix(true, false);
boneNode.matrixWorld.decompose(boneWorldPosition, boneWorldRotation, _v3A3);
boneWorldPositions[boneName] = boneWorldPosition;
boneWorldRotations[boneName] = boneWorldRotation;
boneRotations[boneName] = boneNode.quaternion.clone();
const parentWorldRotation = new THREE8.Quaternion();
(_a = boneNode.parent) == null ? void 0 : _a.matrixWorld.decompose(_v3A3, parentWorldRotation, _v3A3);
parentWorldRotations[boneName] = parentWorldRotation;
}
});
const rigBones = {};
VRMHumanBoneList.forEach((boneName) => {
var _a;
const boneNode = modelRig.getBoneNode(boneName);
if (boneNode) {
const boneWorldPosition = boneWorldPositions[boneName];
let currentBoneName = boneName;
let parentBoneWorldPosition;
while (parentBoneWorldPosition == null) {
currentBoneName = VRMHumanBoneParentMap[currentBoneName];
if (currentBoneName == null) {
break;
}
parentBoneWorldPosition = boneWorldPositions[currentBoneName];
}
const rigBoneNode = new THREE8.Object3D();
rigBoneNode.name = "Normalized_" + boneNode.name;
const parentRigBoneNode = currentBoneName ? (_a = rigBones[currentBoneName]) == null ? void 0 : _a.node : root;
parentRigBoneNode.add(rigBoneNode);
rigBoneNode.position.copy(boneWorldPosition);
if (parentBoneWorldPosition) {
rigBoneNode.position.sub(parentBoneWorldPosition);
}
rigBones[boneName] = { node: rigBoneNode };
}
});
return {
rigBones,
root,
parentWorldRotations,
boneRotations
};
}
constructor(humanoid) {
const { rigBones, root, parentWorldRotations, boneRotations } = _VRMHumanoidRig._setupTransforms(humanoid);
super(rigBones);
this.original = humanoid;
this.root = root;
this._parentWorldRotations = parentWorldRotations;
this._boneRotations = boneRotations;
}
/**
* Update this humanoid rig.
*/
update() {
VRMHumanBoneList.forEach((boneName) => {
const boneNode = this.original.getBoneNode(boneName);
if (boneNode != null) {
const rigBoneNode = this.getBoneNode(boneName);
const parentWorldRotation = this._parentWorldRotations[boneName];
const invParentWorldRotation = _quatA3.copy(parentWorldRotation).invert();
const boneRotation = this._boneRotations[boneName];
boneNode.quaternion.copy(rigBoneNode.quaternion).multiply(parentWorldRotation).premultiply(invParentWorldRotation).multiply(boneRotation);
if (boneName === "hips") {
const boneWorldPosition = rigBoneNode.getWorldPosition(_boneWorldPos);
boneNode.parent.updateWorldMatrix(true, false);
const parentWorldMatrix = boneNode.parent.matrixWorld;
const localPosition = boneWorldPosition.applyMatrix4(parentWorldMatrix.invert());
boneNode.position.copy(localPosition);
}
}
});
}
};
var VRMHumanoid = class _VRMHumanoid {
// TODO: Rename
/**
* @deprecated Deprecated. Use either {@link rawRestPose} or {@link normalizedRestPose} instead.
*/
get restPose() {
console.warn("VRMHumanoid: restPose is deprecated. Use either rawRestPose or normalizedRestPose instead.");
return this.rawRestPose;
}
/**
* A {@link VRMPose} of its raw human bones that is its default state.
* Note that it's not compatible with {@link setRawPose} and {@link getRawPose}, since it contains non-relative values of each local transforms.
*/
get rawRestPose() {
return this._rawHumanBones.restPose;
}
/**
* A {@link VRMPose} of its normalized human bones that is its default state.
* Note that it's not compatible with {@link setNormalizedPose} and {@link getNormalizedPose}, since it contains non-relative values of each local transforms.
*/
get normalizedRestPose() {
return this._normalizedHumanBones.restPose;
}
/**
* A map from {@link VRMHumanBoneName} to raw {@link VRMHumanBone}s.
*/
get humanBones() {
return this._rawHumanBones.humanBones;
}
/**
* A map from {@link VRMHumanBoneName} to raw {@link VRMHumanBone}s.
*/
get rawHumanBones() {
return this._rawHumanBones.humanBones;
}
/**
* A map from {@link VRMHumanBoneName} to normalized {@link VRMHumanBone}s.
*/
get normalizedHumanBones() {
return this._normalizedHumanBones.humanBones;
}
/**
* The root of normalized {@link VRMHumanBone}s.
*/
get normalizedHumanBonesRoot() {
return this._normalizedHumanBones.root;
}
/**
* Create a new {@link VRMHumanoid}.
* @param humanBones A {@link VRMHumanBones} contains all the bones of the new humanoid
* @param autoUpdateHumanBones Whether it copies pose from normalizedHumanBones to rawHumanBones on {@link update}. `true` by default.
*/
constructor(humanBones, options) {
var _a;
this.autoUpdateHumanBones = (_a = options == null ? void 0 : options.autoUpdateHumanBones) != null ? _a : true;
this._rawHumanBones = new VRMRig(humanBones);
this._normalizedHumanBones = new VRMHumanoidRig(this._rawHumanBones);
}
/**
* Copy the given {@link VRMHumanoid} into this one.
* @param source The {@link VRMHumanoid} you want to copy
* @returns this
*/
copy(source) {
this.autoUpdateHumanBones = source.autoUpdateHumanBones;
this._rawHumanBones = new VRMRig(source.humanBones);
this._normalizedHumanBones = new VRMHumanoidRig(this._rawHumanBones);
return this;
}
/**
* Returns a clone of this {@link VRMHumanoid}.
* @returns Copied {@link VRMHumanoid}
*/
clone() {
return new _VRMHumanoid(this.humanBones, { autoUpdateHumanBones: this.autoUpdateHumanBones }).copy(this);
}
/**
* @deprecated Deprecated. Use either {@link getRawAbsolutePose} or {@link getNormalizedAbsolutePose} instead.
*/
getAbsolutePose() {
console.warn(
"VRMHumanoid: getAbsolutePose() is deprecated. Use either getRawAbsolutePose() or getNormalizedAbsolutePose() instead."
);
return this.getRawAbsolutePose();
}
/**
* Return the current absolute pose of this raw human bones as a {@link VRMPose}.
* Note that the output result will contain initial state of the VRM and not compatible between different models.
* You might want to use {@link getRawPose} instead.
*/
getRawAbsolutePose() {
return this._rawHumanBones.getAbsolutePose();
}
/**
* Return the current absolute pose of this normalized human bones as a {@link VRMPose}.
* Note that the output result will contain initial state of the VRM and not compatible between different models.
* You might want to use {@link getNormalizedPose} instead.
*/
getNormalizedAbsolutePose() {
return this._normalizedHumanBones.getAbsolutePose();
}
/**
* @deprecated Deprecated. Use either {@link getRawPose} or {@link getNormalizedPose} instead.
*/
getPose() {
console.warn("VRMHumanoid: getPose() is deprecated. Use either getRawPose() or getNormalizedPose() instead.");
return this.getRawPose();
}
/**
* Return the current pose of raw human bones as a {@link VRMPose}.
*
* Each transform is a local transform relative from rest pose (T-pose).
*/
getRawPose() {
return this._rawHumanBones.getPose();
}
/**
* Return the current pose of normalized human bones as a {@link VRMPose}.
*
* Each transform is a local transform relative from rest pose (T-pose).
*/
getNormalizedPose() {
return this._normalizedHumanBones.getPose();
}
/**
* @deprecated Deprecated. Use either {@link setRawPose} or {@link setNormalizedPose} instead.
*/
setPose(poseObject) {
console.warn("VRMHumanoid: setPose() is deprecated. Use either setRawPose() or setNormalizedPose() instead.");
return this.setRawPose(poseObject);
}
/**
* Let the raw human bones do a specified pose.
*
* Each transform have to be a local transform relative from rest pose (T-pose).
* You can pass what you got from {@link getRawPose}.
*
* If you are using {@link autoUpdateHumanBones}, you might want to use {@link setNormalizedPose} instead.
*
* @param poseObject A {@link VRMPose} that represents a single pose
*/
setRawPose(poseObject) {
return this._rawHumanBones.setPose(poseObject);
}
/**
* Let the normalized human bones do a specified pose.
*
* Each transform have to be a local transform relative from rest pose (T-pose).
* You can pass what you got from {@link getNormalizedPose}.
*
* @param poseObject A {@link VRMPose} that represents a single pose
*/
setNormalizedPose(poseObject) {
return this._normalizedHumanBones.setPose(poseObject);
}
/**
* @deprecated Deprecated. Use either {@link resetRawPose} or {@link resetNormalizedPose} instead.
*/
resetPose() {
console.warn("VRMHumanoid: resetPose() is deprecated. Use either resetRawPose() or resetNormalizedPose() instead.");
return this.resetRawPose();
}
/**
* Reset the raw humanoid to its rest pose.
*
* If you are using {@link autoUpdateHumanBones}, you might want to use {@link resetNormalizedPose} instead.
*/
resetRawPose() {
return this._rawHumanBones.resetPose();
}
/**
* Reset the normalized humanoid to its rest pose.
*/
resetNormalizedPose() {
return this._normalizedHumanBones.resetPose();
}
/**
* @deprecated Deprecated. Use either {@link getRawBone} or {@link getNormalizedBone} instead.
*/
getBone(name) {
console.warn("VRMHumanoid: getBone() is deprecated. Use either getRawBone() or getNormalizedBone() instead.");
return this.getRawBone(name);
}
/**
* Return a raw {@link VRMHumanBone} bound to a specified {@link VRMHumanBoneName}.
*
* @param name Name of the bone you want
*/
getRawBone(name) {
return this._rawHumanBones.getBone(name);
}
/**
* Return a normalized {@link VRMHumanBone} bound to a specified {@link VRMHumanBoneName}.
*
* @param name Name of the bone you want
*/
getNormalizedBone(name) {
return this._normalizedHumanBones.getBone(name);
}
/**
* @deprecated Deprecated. Use either {@link getRawBoneNode} or {@link getNormalizedBoneNode} instead.
*/
getBoneNode(name) {
console.warn(
"VRMHumanoid: getBoneNode() is deprecated. Use either getRawBoneNode() or getNormalizedBoneNode() instead."
);
return this.getRawBoneNode(name);
}
/**
* Return a raw bone as a `THREE.Object3D` bound to a specified {@link VRMHumanBoneName}.
*
* @param name Name of the bone you want
*/
getRawBoneNode(name) {
return this._rawHumanBones.getBoneNode(name);
}
/**
* Return a normalized bone as a `THREE.Object3D` bound to a specified {@link VRMHumanBoneName}.
*
* @param name Name of the bone you want
*/
getNormalizedBoneNode(name) {
return this._normalizedHumanBones.getBoneNode(name);
}
/**
* Update the humanoid component.
*
* If {@link autoUpdateHumanBones} is `true`, it transfers the pose of normalized human bones to raw human bones.
*/
update() {
if (this.autoUpdateHumanBones) {
this._normalizedHumanBones.update();
}
}
};
var VRMRequiredHumanBoneName = {
Hips: "hips",
Spine: "spine",
Head: "head",
LeftUpperLeg: "leftUpperLeg",
LeftLowerLeg: "leftLowerLeg",
LeftFoot: "leftFoot",
RightUpperLeg: "rightUpperLeg",
RightLowerLeg: "rightLowerLeg",
RightFoot: "rightFoot",
LeftUpperArm: "leftUpperArm",
LeftLowerArm: "leftLowerArm",
LeftHand: "leftHand",
RightUpperArm: "rightUpperArm",
RightLowerArm: "rightLowerArm",
RightHand: "rightHand"
};
var POSSIBLE_SPEC_VERSIONS3 = /* @__PURE__ */ new Set(["1.0", "1.0-beta"]);
var thumbBoneNameMap = {
leftThumbProximal: "leftThumbMetacarpal",
leftThumbIntermediate: "leftThumbProximal",
rightThumbProximal: "rightThumbMetacarpal",
rightThumbIntermediate: "rightThumbProximal"
};
var VRMHumanoidLoaderPlugin = class {
get name() {
return "VRMHumanoidLoaderPlugin";
}
constructor(parser, options) {
this.parser = parser;
this.helperRoot = options == null ? void 0 : options.helperRoot;
this.autoUpdateHumanBones = options == null ? void 0 : options.autoUpdateHumanBones;
}
afterRoot(gltf) {
return __async2(this, null, function* () {
gltf.userData.vrmHumanoid = yield this._import(gltf);
});
}
/**
* Import a {@link VRMHumanoid} from a VRM.
*
* @param gltf A parsed result of GLTF taken from GLTFLoader
*/
_import(gltf) {
return __async2(this, null, function* () {
const v1Result = yield this._v1Import(gltf);
if (v1Result) {
return v1Result;
}
const v0Result = yield this._v0Import(gltf);
if (v0Result) {
return v0Result;
}
return null;
});
}
_v1Import(gltf) {
return __async2(this, null, function* () {
var _a, _b;
const json = this.parser.json;
const isVRMUsed = ((_a = json.extensionsUsed) == null ? void 0 : _a.indexOf("VRMC_vrm")) !== -1;
if (!isVRMUsed) {
return null;
}
const extension = (_b = json.extensions) == null ? void 0 : _b["VRMC_vrm"];
if (!extension) {
return null;
}
const specVersion = extension.specVersion;
if (!POSSIBLE_SPEC_VERSIONS3.has(specVersion)) {
console.warn(`VRMHumanoidLoaderPlugin: Unknown VRMC_vrm specVersion "${specVersion}"`);
return null;
}
const schemaHumanoid = extension.humanoid;
if (!schemaHumanoid) {
return null;
}
const existsPreviousThumbName = schemaHumanoid.humanBones.leftThumbIntermediate != null || schemaHumanoid.humanBones.rightThumbIntermediate != null;
const humanBones = {};
if (schemaHumanoid.humanBones != null) {
yield Promise.all(
Object.entries(schemaHumanoid.humanBones).map((_0) => __async2(this, [_0], function* ([boneNameString, schemaHumanBone]) {
let boneName = boneNameString;
const index = schemaHumanBone.node;
if (existsPreviousThumbName) {
const thumbBoneName = thumbBoneNameMap[boneName];
if (thumbBoneName != null) {
boneName = thumbBoneName;
}
}
const node = yield this.parser.getDependency("node", index);
if (node == null) {
console.warn(`A glTF node bound to the humanoid bone ${boneName} (index = ${index}) does not exist`);
return;
}
humanBones[boneName] = { node };
}))
);
}
const humanoid = new VRMHumanoid(this._ensureRequiredBonesExist(humanBones), {
autoUpdateHumanBones: this.autoUpdateHumanBones
});
gltf.scene.add(humanoid.normalizedHumanBonesRoot);
if (this.helperRoot) {
const helper = new VRMHumanoidHelper(humanoid);
this.helperRoot.add(helper);
helper.renderOrder = this.helperRoot.renderOrder;
}
return humanoid;
});
}
_v0Import(gltf) {
return __async2(this, null, function* () {
var _a;
const json = this.parser.json;
const vrmExt = (_a = json.extensions) == null ? void 0 : _a.VRM;
if (!vrmExt) {
return null;
}
const schemaHumanoid = vrmExt.humanoid;
if (!schemaHumanoid) {
return null;
}
const humanBones = {};
if (schemaHumanoid.humanBones != null) {
yield Promise.all(
schemaHumanoid.humanBones.map((bone) => __async2(this, null, function* () {
const boneName = bone.bone;
const index = bone.node;
if (boneName == null || index == null) {
return;
}
const node = yield this.parser.getDependency("node", index);
if (node == null) {
console.warn(`A glTF node bound to the humanoid bone ${boneName} (index = ${index}) does not exist`);
return;
}
const thumbBoneName = thumbBoneNameMap[boneName];
const newBoneName = thumbBoneName != null ? thumbBoneName : boneName;
if (humanBones[newBoneName] != null) {
console.warn(
`Multiple bone entries for ${newBoneName} detected (index = ${index}), ignoring duplicated entries.`
);
return;
}
humanBones[newBoneName] = { node };
}))
);
}
const humanoid = new VRMHumanoid(this._ensureRequiredBonesExist(humanBones), {
autoUpdateHumanBones: this.autoUpdateHumanBones
});
gltf.scene.add(humanoid.normalizedHumanBonesRoot);
if (this.helperRoot) {
const helper = new VRMHumanoidHelper(humanoid);
this.helperRoot.add(helper);
helper.renderOrder = this.helperRoot.renderOrder;
}
return humanoid;
});
}
/**
* Ensure required bones exist in given human bones.
* @param humanBones Human bones
* @returns Human bones, no longer partial!
*/
_ensureRequiredBonesExist(humanBones) {
const missingRequiredBones = Object.values(VRMRequiredHumanBoneName).filter(
(requiredBoneName) => humanBones[requiredBoneName] == null
);
if (missingRequiredBones.length > 0) {
throw new Error(
`VRMHumanoidLoaderPlugin: These humanoid bones are required but not exist: ${missingRequiredBones.join(", ")}`
);
}
return humanBones;
}
};
var FanBufferGeometry = class extends THREE9.BufferGeometry {
constructor() {
super();
this._currentTheta = 0;
this._currentRadius = 0;
this.theta = 0;
this.radius = 0;
this._currentTheta = 0;
this._currentRadius = 0;
this._attrPos = new THREE9.BufferAttribute(new Float32Array(65 * 3), 3);
this.setAttribute("position", this._attrPos);
this._attrIndex = new THREE9.BufferAttribute(new Uint16Array(3 * 63), 1);
this.setIndex(this._attrIndex);
this._buildIndex();
this.update();
}
update() {
let shouldUpdateGeometry = false;
if (this._currentTheta !== this.theta) {
this._currentTheta = this.theta;
shouldUpdateGeometry = true;
}
if (this._currentRadius !== this.radius) {
this._currentRadius = this.radius;
shouldUpdateGeometry = true;
}
if (shouldUpdateGeometry) {
this._buildPosition();
}
}
_buildPosition() {
this._attrPos.setXYZ(0, 0, 0, 0);
for (let i = 0; i < 64; i++) {
const t = i / 63 * this._currentTheta;
this._attrPos.setXYZ(i + 1, this._currentRadius * Math.sin(t), 0, this._currentRadius * Math.cos(t));
}
this._attrPos.needsUpdate = true;
}
_buildIndex() {
for (let i = 0; i < 63; i++) {
this._attrIndex.setXYZ(i * 3, 0, i + 1, i + 2);
}
this._attrIndex.needsUpdate = true;
}
};
var LineAndSphereBufferGeometry = class extends THREE10.BufferGeometry {
constructor() {
super();
this.radius = 0;
this._currentRadius = 0;
this.tail = new THREE10.Vector3();
this._currentTail = new THREE10.Vector3();
this._attrPos = new THREE10.BufferAttribute(new Float32Array(294), 3);
this.setAttribute("position", this._attrPos);
this._attrIndex = new THREE10.BufferAttribute(new Uint16Array(194), 1);
this.setIndex(this._attrIndex);
this._buildIndex();
this.update();
}
update() {
let shouldUpdateGeometry = false;
if (this._currentRadius !== this.radius) {
this._currentRadius = this.radius;
shouldUpdateGeometry = true;
}
if (!this._currentTail.equals(this.tail)) {
this._currentTail.copy(this.tail);
shouldUpdateGeometry = true;
}
if (shouldUpdateGeometry) {
this._buildPosition();
}
}
_buildPosition() {
for (let i = 0; i < 32; i++) {
const t = i / 16 * Math.PI;
this._attrPos.setXYZ(i, Math.cos(t), Math.sin(t), 0);
this._attrPos.setXYZ(32 + i, 0, Math.cos(t), Math.sin(t));
this._attrPos.setXYZ(64 + i, Math.sin(t), 0, Math.cos(t));
}
this.scale(this._currentRadius, this._currentRadius, this._currentRadius);
this.translate(this._currentTail.x, this._currentTail.y, this._currentTail.z);
this._attrPos.setXYZ(96, 0, 0, 0);
this._attrPos.setXYZ(97, this._currentTail.x, this._currentTail.y, this._currentTail.z);
this._attrPos.needsUpdate = true;
}
_buildIndex() {
for (let i = 0; i < 32; i++) {
const i1 = (i + 1) % 32;
this._attrIndex.setXY(i * 2, i, i1);
this._attrIndex.setXY(64 + i * 2, 32 + i, 32 + i1);
this._attrIndex.setXY(128 + i * 2, 64 + i, 64 + i1);
}
this._attrIndex.setXY(192, 96, 97);
this._attrIndex.needsUpdate = true;
}
};
var _quatA4 = new THREE11.Quaternion();
var _quatB = new THREE11.Quaternion();
var _v3A4 = new THREE11.Vector3();
var _v3B2 = new THREE11.Vector3();
var SQRT_2_OVER_2 = Math.sqrt(2) / 2;
var QUAT_XY_CW90 = new THREE11.Quaternion(0, 0, -SQRT_2_OVER_2, SQRT_2_OVER_2);
var VEC3_POSITIVE_Y = new THREE11.Vector3(0, 1, 0);
var VRMLookAtHelper = class extends THREE11.Group {
constructor(lookAt) {
super();
this.matrixAutoUpdate = false;
this.vrmLookAt = lookAt;
{
const geometry = new FanBufferGeometry();
geometry.radius = 0.5;
const material = new THREE11.MeshBasicMaterial({
color: 65280,
transparent: true,
opacity: 0.5,
side: THREE11.DoubleSide,
depthTest: false,
depthWrite: false
});
this._meshPitch = new THREE11.Mesh(geometry, material);
this.add(this._meshPitch);
}
{
const geometry = new FanBufferGeometry();
geometry.radius = 0.5;
const material = new THREE11.MeshBasicMaterial({
color: 16711680,
transparent: true,
opacity: 0.5,
side: THREE11.DoubleSide,
depthTest: false,
depthWrite: false
});
this._meshYaw = new THREE11.Mesh(geometry, material);
this.add(this._meshYaw);
}
{
const geometry = new LineAndSphereBufferGeometry();
geometry.radius = 0.1;
const material = new THREE11.LineBasicMaterial({
color: 16777215,
depthTest: false,
depthWrite: false
});
this._lineTarget = new THREE11.LineSegments(geometry, material);
this._lineTarget.frustumCulled = false;
this.add(this._lineTarget);
}
}
dispose() {
this._meshYaw.geometry.dispose();
this._meshYaw.material.dispose();
this._meshPitch.geometry.dispose();
this._meshPitch.material.dispose();
this._lineTarget.geometry.dispose();
this._lineTarget.material.dispose();
}
updateMatrixWorld(force) {
const yaw = THREE11.MathUtils.DEG2RAD * this.vrmLookAt.yaw;
this._meshYaw.geometry.theta = yaw;
this._meshYaw.geometry.update();
const pitch = THREE11.MathUtils.DEG2RAD * this.vrmLookAt.pitch;
this._meshPitch.geometry.theta = pitch;
this._meshPitch.geometry.update();
this.vrmLookAt.getLookAtWorldPosition(_v3A4);
this.vrmLookAt.getLookAtWorldQuaternion(_quatA4);
_quatA4.multiply(this.vrmLookAt.getFaceFrontQuaternion(_quatB));
this._meshYaw.position.copy(_v3A4);
this._meshYaw.quaternion.copy(_quatA4);
this._meshPitch.position.copy(_v3A4);
this._meshPitch.quaternion.copy(_quatA4);
this._meshPitch.quaternion.multiply(_quatB.setFromAxisAngle(VEC3_POSITIVE_Y, yaw));
this._meshPitch.quaternion.multiply(QUAT_XY_CW90);
const { target, autoUpdate } = this.vrmLookAt;
if (target != null && autoUpdate) {
target.getWorldPosition(_v3B2).sub(_v3A4);
this._lineTarget.geometry.tail.copy(_v3B2);
this._lineTarget.geometry.update();
this._lineTarget.position.copy(_v3A4);
}
super.updateMatrixWorld(force);
}
};
var _position = new THREE12.Vector3();
var _scale = new THREE12.Vector3();
function getWorldQuaternionLite(object, out) {
object.matrixWorld.decompose(_position, out, _scale);
return out;
}
function calcAzimuthAltitude(vector) {
return [Math.atan2(-vector.z, vector.x), Math.atan2(vector.y, Math.sqrt(vector.x * vector.x + vector.z * vector.z))];
}
function sanitizeAngle(angle) {
const roundTurn = Math.round(angle / 2 / Math.PI);
return angle - 2 * Math.PI * roundTurn;
}
var VEC3_POSITIVE_Z = new THREE13.Vector3(0, 0, 1);
var _v3A5 = new THREE13.Vector3();
var _v3B3 = new THREE13.Vector3();
var _v3C = new THREE13.Vector3();
var _quatA5 = new THREE13.Quaternion();
var _quatB2 = new THREE13.Quaternion();
var _quatC = new THREE13.Quaternion();
var _quatD = new THREE13.Quaternion();
var _eulerA = new THREE13.Euler();
var _VRMLookAt = class _VRMLookAt2 {
/**
* Create a new {@link VRMLookAt}.
*
* @param humanoid A {@link VRMHumanoid}
* @param applier A {@link VRMLookAtApplier}
*/
constructor(humanoid, applier) {
this.offsetFromHeadBone = new THREE13.Vector3();
this.autoUpdate = true;
this.faceFront = new THREE13.Vector3(0, 0, 1);
this.humanoid = humanoid;
this.applier = applier;
this._yaw = 0;
this._pitch = 0;
this._needsUpdate = true;
this._restHeadWorldQuaternion = this.getLookAtWorldQuaternion(new THREE13.Quaternion());
}
/**
* Its current angle around Y axis, in degree.
*/
get yaw() {
return this._yaw;
}
/**
* Its current angle around Y axis, in degree.
*/
set yaw(value) {
this._yaw = value;
this._needsUpdate = true;
}
/**
* Its current angle around X axis, in degree.
*/
get pitch() {
return this._pitch;
}
/**
* Its current angle around X axis, in degree.
*/
set pitch(value) {
this._pitch = value;
this._needsUpdate = true;
}
/**
* @deprecated Use {@link getEuler} instead.
*/
get euler() {
console.warn("VRMLookAt: euler is deprecated. use getEuler() instead.");
return this.getEuler(new THREE13.Euler());
}
/**
* Get its yaw-pitch angles as an `Euler`.
* Does NOT consider {@link faceFront}; it returns `Euler(0, 0, 0; "YXZ")` by default regardless of the faceFront value.
*
* @param target The target euler
*/
getEuler(target) {
return target.set(THREE13.MathUtils.DEG2RAD * this._pitch, THREE13.MathUtils.DEG2RAD * this._yaw, 0, "YXZ");
}
/**
* Copy the given {@link VRMLookAt} into this one.
* {@link humanoid} must be same as the source one.
* {@link applier} will reference the same instance as the source one.
* @param source The {@link VRMLookAt} you want to copy
* @returns this
*/
copy(source) {
if (this.humanoid !== source.humanoid) {
throw new Error("VRMLookAt: humanoid must be same in order to copy");
}
this.offsetFromHeadBone.copy(source.offsetFromHeadBone);
this.applier = source.applier;
this.autoUpdate = source.autoUpdate;
this.target = source.target;
this.faceFront.copy(source.faceFront);
return this;
}
/**
* Returns a clone of this {@link VRMLookAt}.
* Note that {@link humanoid} and {@link applier} will reference the same instance as this one.
* @returns Copied {@link VRMLookAt}
*/
clone() {
return new _VRMLookAt2(this.humanoid, this.applier).copy(this);
}
/**
* Reset the lookAt direction (yaw and pitch) to the initial direction.
*/
reset() {
this._yaw = 0;
this._pitch = 0;
this._needsUpdate = true;
}
/**
* Get its lookAt position in world coordinate.
*
* @param target A target `THREE.Vector3`
*/
getLookAtWorldPosition(target) {
const head = this.humanoid.getRawBoneNode("head");
return target.copy(this.offsetFromHeadBone).applyMatrix4(head.matrixWorld);
}
/**
* Get its lookAt rotation in world coordinate.
* Does NOT consider {@link faceFront}.
*
* @param target A target `THREE.Quaternion`
*/
getLookAtWorldQuaternion(target) {
const head = this.humanoid.getRawBoneNode("head");
return getWorldQuaternionLite(head, target);
}
/**
* Get a quaternion that rotates the +Z unit vector of the humanoid Head to the {@link faceFront} direction.
*
* @param target A target `THREE.Quaternion`
*/
getFaceFrontQuaternion(target) {
if (this.faceFront.distanceToSquared(VEC3_POSITIVE_Z) < 0.01) {
return target.copy(this._restHeadWorldQuaternion).invert();
}
const [faceFrontAzimuth, faceFrontAltitude] = calcAzimuthAltitude(this.faceFront);
_eulerA.set(0, 0.5 * Math.PI + faceFrontAzimuth, faceFrontAltitude, "YZX");
return target.setFromEuler(_eulerA).premultiply(_quatD.copy(this._restHeadWorldQuaternion).invert());
}
/**
* Get its LookAt direction in world coordinate.
*
* @param target A target `THREE.Vector3`
*/
getLookAtWorldDirection(target) {
this.getLookAtWorldQuaternion(_quatB2);
this.getFaceFrontQuaternion(_quatC);
return target.copy(VEC3_POSITIVE_Z).applyQuaternion(_quatB2).applyQuaternion(_quatC).applyEuler(this.getEuler(_eulerA));
}
/**
* Set its lookAt target position.
*
* Note that its result will be instantly overwritten if {@link VRMLookAtHead.autoUpdate} is enabled.
*
* If you want to track an object continuously, you might want to use {@link target} instead.
*
* @param position A target position, in world space
*/
lookAt(position) {
const headRotDiffInv = _quatA5.copy(this._restHeadWorldQuaternion).multiply(quatInvertCompat(this.getLookAtWorldQuaternion(_quatB2)));
const headPos = this.getLookAtWorldPosition(_v3B3);
const lookAtDir = _v3C.copy(position).sub(headPos).applyQuaternion(headRotDiffInv).normalize();
const [azimuthFrom, altitudeFrom] = calcAzimuthAltitude(this.faceFront);
const [azimuthTo, altitudeTo] = calcAzimuthAltitude(lookAtDir);
const yaw = sanitizeAngle(azimuthTo - azimuthFrom);
const pitch = sanitizeAngle(altitudeFrom - altitudeTo);
this._yaw = THREE13.MathUtils.RAD2DEG * yaw;
this._pitch = THREE13.MathUtils.RAD2DEG * pitch;
this._needsUpdate = true;
}
/**
* Update the VRMLookAtHead.
* If {@link autoUpdate} is enabled, this will make it look at the {@link target}.
*
* @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}.
*/
update(delta) {
if (this.target != null && this.autoUpdate) {
this.lookAt(this.target.getWorldPosition(_v3A5));
}
if (this._needsUpdate) {
this._needsUpdate = false;
this.applier.applyYawPitch(this._yaw, this._pitch);
}
}
};
_VRMLookAt.EULER_ORDER = "YXZ";
var VRMLookAt = _VRMLookAt;
var VEC3_POSITIVE_Z2 = new THREE14.Vector3(0, 0, 1);
var _quatA6 = new THREE14.Quaternion();
var _quatB3 = new THREE14.Quaternion();
var _eulerA2 = new THREE14.Euler(0, 0, 0, "YXZ");
var VRMLookAtBoneApplier = class {
/**
* Create a new {@link VRMLookAtBoneApplier}.
*
* @param humanoid A {@link VRMHumanoid}
* @param rangeMapHorizontalInner A {@link VRMLookAtRangeMap} used for inner transverse direction
* @param rangeMapHorizontalOuter A {@link VRMLookAtRangeMap} used for outer transverse direction
* @param rangeMapVerticalDown A {@link VRMLookAtRangeMap} used for down direction
* @param rangeMapVerticalUp A {@link VRMLookAtRangeMap} used for up direction
*/
constructor(humanoid, rangeMapHorizontalInner, rangeMapHorizontalOuter, rangeMapVerticalDown, rangeMapVerticalUp) {
this.humanoid = humanoid;
this.rangeMapHorizontalInner = rangeMapHorizontalInner;
this.rangeMapHorizontalOuter = rangeMapHorizontalOuter;
this.rangeMapVerticalDown = rangeMapVerticalDown;
this.rangeMapVerticalUp = rangeMapVerticalUp;
this.faceFront = new THREE14.Vector3(0, 0, 1);
this._restQuatLeftEye = new THREE14.Quaternion();
this._restQuatRightEye = new THREE14.Quaternion();
this._restLeftEyeParentWorldQuat = new THREE14.Quaternion();
this._restRightEyeParentWorldQuat = new THREE14.Quaternion();
const leftEye = this.humanoid.getRawBoneNode("leftEye");
const rightEye = this.humanoid.getRawBoneNode("rightEye");
if (leftEye) {
this._restQuatLeftEye.copy(leftEye.quaternion);
getWorldQuaternionLite(leftEye.parent, this._restLeftEyeParentWorldQuat);
}
if (rightEye) {
this._restQuatRightEye.copy(rightEye.quaternion);
getWorldQuaternionLite(rightEye.parent, this._restRightEyeParentWorldQuat);
}
}
/**
* Apply the input angle to its associated VRM model.
*
* @param yaw Rotation around Y axis, in degree
* @param pitch Rotation around X axis, in degree
*/
applyYawPitch(yaw, pitch) {
const leftEye = this.humanoid.getRawBoneNode("leftEye");
const rightEye = this.humanoid.getRawBoneNode("rightEye");
const leftEyeNormalized = this.humanoid.getNormalizedBoneNode("leftEye");
const rightEyeNormalized = this.humanoid.getNormalizedBoneNode("rightEye");
if (leftEye) {
if (pitch < 0) {
_eulerA2.x = -THREE14.MathUtils.DEG2RAD * this.rangeMapVerticalDown.map(-pitch);
} else {
_eulerA2.x = THREE14.MathUtils.DEG2RAD * this.rangeMapVerticalUp.map(pitch);
}
if (yaw < 0) {
_eulerA2.y = -THREE14.MathUtils.DEG2RAD * this.rangeMapHorizontalInner.map(-yaw);
} else {
_eulerA2.y = THREE14.MathUtils.DEG2RAD * this.rangeMapHorizontalOuter.map(yaw);
}
_quatA6.setFromEuler(_eulerA2);
this._getWorldFaceFrontQuat(_quatB3);
leftEyeNormalized.quaternion.copy(_quatB3).multiply(_quatA6).multiply(_quatB3.invert());
_quatA6.copy(this._restLeftEyeParentWorldQuat);
leftEye.quaternion.copy(leftEyeNormalized.quaternion).multiply(_quatA6).premultiply(_quatA6.invert()).multiply(this._restQuatLeftEye);
}
if (rightEye) {
if (pitch < 0) {
_eulerA2.x = -THREE14.MathUtils.DEG2RAD * this.rangeMapVerticalDown.map(-pitch);
} else {
_eulerA2.x = THREE14.MathUtils.DEG2RAD * this.rangeMapVerticalUp.map(pitch);
}
if (yaw < 0) {
_eulerA2.y = -THREE14.MathUtils.DEG2RAD * this.rangeMapHorizontalOuter.map(-yaw);
} else {
_eulerA2.y = THREE14.MathUtils.DEG2RAD * this.rangeMapHorizontalInner.map(yaw);
}
_quatA6.setFromEuler(_eulerA2);
this._getWorldFaceFrontQuat(_quatB3);
rightEyeNormalized.quaternion.copy(_quatB3).multiply(_quatA6).multiply(_quatB3.invert());
_quatA6.copy(this._restRightEyeParentWorldQuat);
rightEye.quaternion.copy(rightEyeNormalized.quaternion).multiply(_quatA6).premultiply(_quatA6.invert()).multiply(this._restQuatRightEye);
}
}
/**
* @deprecated Use {@link applyYawPitch} instead.
*/
lookAt(euler) {
console.warn("VRMLookAtBoneApplier: lookAt() is deprecated. use apply() instead.");
const yaw = THREE14.MathUtils.RAD2DEG * euler.y;
const pitch = THREE14.MathUtils.RAD2DEG * euler.x;
this.applyYawPitch(yaw, pitch);
}
/**
* Get a quaternion that rotates the world-space +Z unit vector to the {@link faceFront} direction.
*
* @param target A target `THREE.Quaternion`
*/
_getWorldFaceFrontQuat(target) {
if (this.faceFront.distanceToSquared(VEC3_POSITIVE_Z2) < 0.01) {
return target.identity();
}
const [faceFrontAzimuth, faceFrontAltitude] = calcAzimuthAltitude(this.faceFront);
_eulerA2.set(0, 0.5 * Math.PI + faceFrontAzimuth, faceFrontAltitude, "YZX");
return target.setFromEuler(_eulerA2);
}
};
VRMLookAtBoneApplier.type = "bone";
var VRMLookAtExpressionApplier = class {
/**
* Create a new {@link VRMLookAtExpressionApplier}.
*
* @param expressions A {@link VRMExpressionManager}
* @param rangeMapHorizontalInner A {@link VRMLookAtRangeMap} used for inner transverse direction
* @param rangeMapHorizontalOuter A {@link VRMLookAtRangeMap} used for outer transverse direction
* @param rangeMapVerticalDown A {@link VRMLookAtRangeMap} used for down direction
* @param rangeMapVerticalUp A {@link VRMLookAtRangeMap} used for up direction
*/
constructor(expressions, rangeMapHorizontalInner, rangeMapHorizontalOuter, rangeMapVerticalDown, rangeMapVerticalUp) {
this.expressions = expressions;
this.rangeMapHorizontalInner = rangeMapHorizontalInner;
this.rangeMapHorizontalOuter = rangeMapHorizontalOuter;
this.rangeMapVerticalDown = rangeMapVerticalDown;
this.rangeMapVerticalUp = rangeMapVerticalUp;
}
/**
* Apply the input angle to its associated VRM model.
*
* @param yaw Rotation around Y axis, in degree
* @param pitch Rotation around X axis, in degree
*/
applyYawPitch(yaw, pitch) {
if (pitch < 0) {
this.expressions.setValue("lookDown", 0);
this.expressions.setValue("lookUp", this.rangeMapVerticalUp.map(-pitch));
} else {
this.expressions.setValue("lookUp", 0);
this.expressions.setValue("lookDown", this.rangeMapVerticalDown.map(pitch));
}
if (yaw < 0) {
this.expressions.setValue("lookLeft", 0);
this.expressions.setValue("lookRight", this.rangeMapHorizontalOuter.map(-yaw));
} else {
this.expressions.setValue("lookRight", 0);
this.expressions.setValue("lookLeft", this.rangeMapHorizontalOuter.map(yaw));
}
}
/**
* @deprecated Use {@link applyYawPitch} instead.
*/
lookAt(euler) {
console.warn("VRMLookAtBoneApplier: lookAt() is deprecated. use apply() instead.");
const yaw = THREE15.MathUtils.RAD2DEG * euler.y;
const pitch = THREE15.MathUtils.RAD2DEG * euler.x;
this.applyYawPitch(yaw, pitch);
}
};
VRMLookAtExpressionApplier.type = "expression";
var VRMLookAtRangeMap = class {
/**
* Create a new {@link VRMLookAtRangeMap}.
*
* @param inputMaxValue The {@link inputMaxValue} of the map
* @param outputScale The {@link outputScale} of the map
*/
constructor(inputMaxValue, outputScale) {
this.inputMaxValue = inputMaxValue;
this.outputScale = outputScale;
}
/**
* Evaluate an input value and output a mapped value.
* @param src The input value
*/
map(src) {
return this.outputScale * saturate(src / this.inputMaxValue);
}
};
var POSSIBLE_SPEC_VERSIONS4 = /* @__PURE__ */ new Set(["1.0", "1.0-beta"]);
var INPUT_MAX_VALUE_MINIMUM = 0.01;
var VRMLookAtLoaderPlugin = class {
get name() {
return "VRMLookAtLoaderPlugin";
}
constructor(parser, options) {
this.parser = parser;
this.helperRoot = options == null ? void 0 : options.helperRoot;
}
afterRoot(gltf) {
return __async2(this, null, function* () {
const vrmHumanoid = gltf.userData.vrmHumanoid;
if (vrmHumanoid === null) {
return;
} else if (vrmHumanoid === void 0) {
throw new Error("VRMLookAtLoaderPlugin: vrmHumanoid is undefined. VRMHumanoidLoaderPlugin have to be used first");
}
const vrmExpressionManager = gltf.userData.vrmExpressionManager;
if (vrmExpressionManager === null) {
return;
} else if (vrmExpressionManager === void 0) {
throw new Error(
"VRMLookAtLoaderPlugin: vrmExpressionManager is undefined. VRMExpressionLoaderPlugin have to be used first"
);
}
gltf.userData.vrmLookAt = yield this._import(gltf, vrmHumanoid, vrmExpressionManager);
});
}
/**
* Import a {@link VRMLookAt} from a VRM.
*
* @param gltf A parsed result of GLTF taken from GLTFLoader
* @param humanoid A {@link VRMHumanoid} instance that represents the VRM
* @param expressions A {@link VRMExpressionManager} instance that represents the VRM
*/
_import(gltf, humanoid, expressions) {
return __async2(this, null, function* () {
if (humanoid == null || expressions == null) {
return null;
}
const v1Result = yield this._v1Import(gltf, humanoid, expressions);
if (v1Result) {
return v1Result;
}
const v0Result = yield this._v0Import(gltf, humanoid, expressions);
if (v0Result) {
return v0Result;
}
return null;
});
}
_v1Import(gltf, humanoid, expressions) {
return __async2(this, null, function* () {
var _a, _b, _c;
const json = this.parser.json;
const isVRMUsed = ((_a = json.extensionsUsed) == null ? void 0 : _a.indexOf("VRMC_vrm")) !== -1;
if (!isVRMUsed) {
return null;
}
const extension = (_b = json.extensions) == null ? void 0 : _b["VRMC_vrm"];
if (!extension) {
return null;
}
const specVersion = extension.specVersion;
if (!POSSIBLE_SPEC_VERSIONS4.has(specVersion)) {
console.warn(`VRMLookAtLoaderPlugin: Unknown VRMC_vrm specVersion "${specVersion}"`);
return null;
}
const schemaLookAt = extension.lookAt;
if (!schemaLookAt) {
return null;
}
const defaultOutputScale = schemaLookAt.type === "expression" ? 1 : 10;
const mapHI = this._v1ImportRangeMap(schemaLookAt.rangeMapHorizontalInner, defaultOutputScale);
const mapHO = this._v1ImportRangeMap(schemaLookAt.rangeMapHorizontalOuter, defaultOutputScale);
const mapVD = this._v1ImportRangeMap(schemaLookAt.rangeMapVerticalDown, defaultOutputScale);
const mapVU = this._v1ImportRangeMap(schemaLookAt.rangeMapVerticalUp, defaultOutputScale);
let applier;
if (schemaLookAt.type === "expression") {
applier = new VRMLookAtExpressionApplier(expressions, mapHI, mapHO, mapVD, mapVU);
} else {
applier = new VRMLookAtBoneApplier(humanoid, mapHI, mapHO, mapVD, mapVU);
}
const lookAt = this._importLookAt(humanoid, applier);
lookAt.offsetFromHeadBone.fromArray((_c = schemaLookAt.offsetFromHeadBone) != null ? _c : [0, 0.06, 0]);
return lookAt;
});
}
_v1ImportRangeMap(schemaRangeMap, defaultOutputScale) {
var _a, _b;
let inputMaxValue = (_a = schemaRangeMap == null ? void 0 : schemaRangeMap.inputMaxValue) != null ? _a : 90;
const outputScale = (_b = schemaRangeMap == null ? void 0 : schemaRangeMap.outputScale) != null ? _b : defaultOutputScale;
if (inputMaxValue < INPUT_MAX_VALUE_MINIMUM) {
console.warn(
"VRMLookAtLoaderPlugin: inputMaxValue of a range map is too small. Consider reviewing the range map!"
);
inputMaxValue = INPUT_MAX_VALUE_MINIMUM;
}
return new VRMLookAtRangeMap(inputMaxValue, outputScale);
}
_v0Import(gltf, humanoid, expressions) {
return __async2(this, null, function* () {
var _a, _b, _c, _d;
const json = this.parser.json;
const vrmExt = (_a = json.extensions) == null ? void 0 : _a.VRM;
if (!vrmExt) {
return null;
}
const schemaFirstPerson = vrmExt.firstPerson;
if (!schemaFirstPerson) {
return null;
}
const defaultOutputScale = schemaFirstPerson.lookAtTypeName === "BlendShape" ? 1 : 10;
const mapHI = this._v0ImportDegreeMap(schemaFirstPerson.lookAtHorizontalInner, defaultOutputScale);
const mapHO = this._v0ImportDegreeMap(schemaFirstPerson.lookAtHorizontalOuter, defaultOutputScale);
const mapVD = this._v0ImportDegreeMap(schemaFirstPerson.lookAtVerticalDown, defaultOutputScale);
const mapVU = this._v0ImportDegreeMap(schemaFirstPerson.lookAtVerticalUp, defaultOutputScale);
let applier;
if (schemaFirstPerson.lookAtTypeName === "BlendShape") {
applier = new VRMLookAtExpressionApplier(expressions, mapHI, mapHO, mapVD, mapVU);
} else {
applier = new VRMLookAtBoneApplier(humanoid, mapHI, mapHO, mapVD, mapVU);
}
const lookAt = this._importLookAt(humanoid, applier);
if (schemaFirstPerson.firstPersonBoneOffset) {
lookAt.offsetFromHeadBone.set(
(_b = schemaFirstPerson.firstPersonBoneOffset.x) != null ? _b : 0,
(_c = schemaFirstPerson.firstPersonBoneOffset.y) != null ? _c : 0.06,
-((_d = schemaFirstPerson.firstPersonBoneOffset.z) != null ? _d : 0)
);
} else {
lookAt.offsetFromHeadBone.set(0, 0.06, 0);
}
lookAt.faceFront.set(0, 0, -1);
if (applier instanceof VRMLookAtBoneApplier) {
applier.faceFront.set(0, 0, -1);
}
return lookAt;
});
}
_v0ImportDegreeMap(schemaDegreeMap, defaultOutputScale) {
var _a, _b;
const curve = schemaDegreeMap == null ? void 0 : schemaDegreeMap.curve;
if (JSON.stringify(curve) !== "[0,0,0,1,1,1,1,0]") {
console.warn("Curves of LookAtDegreeMap defined in VRM 0.0 are not supported");
}
let xRange = (_a = schemaDegreeMap == null ? void 0 : schemaDegreeMap.xRange) != null ? _a : 90;
const yRange = (_b = schemaDegreeMap == null ? void 0 : schemaDegreeMap.yRange) != null ? _b : defaultOutputScale;
if (xRange < INPUT_MAX_VALUE_MINIMUM) {
console.warn("VRMLookAtLoaderPlugin: xRange of a degree map is too small. Consider reviewing the degree map!");
xRange = INPUT_MAX_VALUE_MINIMUM;
}
return new VRMLookAtRangeMap(xRange, yRange);
}
_importLookAt(humanoid, applier) {
const lookAt = new VRMLookAt(humanoid, applier);
if (this.helperRoot) {
const helper = new VRMLookAtHelper(lookAt);
this.helperRoot.add(helper);
helper.renderOrder = this.helperRoot.renderOrder;
}
return lookAt;
}
};
var VRMLookAtTypeName = {
Bone: "bone",
Expression: "expression"
};
function resolveURL(url, path) {
if (typeof url !== "string" || url === "") return "";
if (/^https?:\/\//i.test(path) && /^\//.test(url)) {
path = path.replace(/(^https?:\/\/[^/]+).*/i, "$1");
}
if (/^(https?:)?\/\//i.test(url)) return url;
if (/^data:.*,.*$/i.test(url)) return url;
if (/^blob:.*$/i.test(url)) return url;
return path + url;
}
var POSSIBLE_SPEC_VERSIONS5 = /* @__PURE__ */ new Set(["1.0", "1.0-beta"]);
var VRMMetaLoaderPlugin = class {
get name() {
return "VRMMetaLoaderPlugin";
}
constructor(parser, options) {
var _a, _b, _c;
this.parser = parser;
this.needThumbnailImage = (_a = options == null ? void 0 : options.needThumbnailImage) != null ? _a : false;
this.acceptLicenseUrls = (_b = options == null ? void 0 : options.acceptLicenseUrls) != null ? _b : ["https://vrm.dev/licenses/1.0/"];
this.acceptV0Meta = (_c = options == null ? void 0 : options.acceptV0Meta) != null ? _c : true;
}
afterRoot(gltf) {
return __async2(this, null, function* () {
gltf.userData.vrmMeta = yield this._import(gltf);
});
}
_import(gltf) {
return __async2(this, null, function* () {
const v1Result = yield this._v1Import(gltf);
if (v1Result != null) {
return v1Result;
}
const v0Result = yield this._v0Import(gltf);
if (v0Result != null) {
return v0Result;
}
return null;
});
}
_v1Import(gltf) {
return __async2(this, null, function* () {
var _a, _b, _c;
const json = this.parser.json;
const isVRMUsed = ((_a = json.extensionsUsed) == null ? void 0 : _a.indexOf("VRMC_vrm")) !== -1;
if (!isVRMUsed) {
return null;
}
const extension = (_b = json.extensions) == null ? void 0 : _b["VRMC_vrm"];
if (extension == null) {
return null;
}
const specVersion = extension.specVersion;
if (!POSSIBLE_SPEC_VERSIONS5.has(specVersion)) {
console.warn(`VRMMetaLoaderPlugin: Unknown VRMC_vrm specVersion "${specVersion}"`);
return null;
}
const schemaMeta = extension.meta;
if (!schemaMeta) {
return null;
}
const licenseUrl = schemaMeta.licenseUrl;
const acceptLicenseUrlsSet = new Set(this.acceptLicenseUrls);
if (!acceptLicenseUrlsSet.has(licenseUrl)) {
throw new Error(`VRMMetaLoaderPlugin: The license url "${licenseUrl}" is not accepted`);
}
let thumbnailImage = void 0;
if (this.needThumbnailImage && schemaMeta.thumbnailImage != null) {
thumbnailImage = (_c = yield this._extractGLTFImage(schemaMeta.thumbnailImage)) != null ? _c : void 0;
}
return {
metaVersion: "1",
name: schemaMeta.name,
version: schemaMeta.version,
authors: schemaMeta.authors,
copyrightInformation: schemaMeta.copyrightInformation,
contactInformation: schemaMeta.contactInformation,
references: schemaMeta.references,
thirdPartyLicenses: schemaMeta.thirdPartyLicenses,
thumbnailImage,
licenseUrl: schemaMeta.licenseUrl,
avatarPermission: schemaMeta.avatarPermission,
allowExcessivelyViolentUsage: schemaMeta.allowExcessivelyViolentUsage,
allowExcessivelySexualUsage: schemaMeta.allowExcessivelySexualUsage,
commercialUsage: schemaMeta.commercialUsage,
allowPoliticalOrReligiousUsage: schemaMeta.allowPoliticalOrReligiousUsage,
allowAntisocialOrHateUsage: schemaMeta.allowAntisocialOrHateUsage,
creditNotation: schemaMeta.creditNotation,
allowRedistribution: schemaMeta.allowRedistribution,
modification: schemaMeta.modification,
otherLicenseUrl: schemaMeta.otherLicenseUrl
};
});
}
_v0Import(gltf) {
return __async2(this, null, function* () {
var _a;
const json = this.parser.json;
const vrmExt = (_a = json.extensions) == null ? void 0 : _a.VRM;
if (!vrmExt) {
return null;
}
const schemaMeta = vrmExt.meta;
if (!schemaMeta) {
return null;
}
if (!this.acceptV0Meta) {
throw new Error("VRMMetaLoaderPlugin: Attempted to load VRM0.0 meta but acceptV0Meta is false");
}
let texture;
if (this.needThumbnailImage && schemaMeta.texture != null && schemaMeta.texture !== -1) {
texture = yield this.parser.getDependency("texture", schemaMeta.texture);
}
return {
metaVersion: "0",
allowedUserName: schemaMeta.allowedUserName,
author: schemaMeta.author,
commercialUssageName: schemaMeta.commercialUssageName,
contactInformation: schemaMeta.contactInformation,
licenseName: schemaMeta.licenseName,
otherLicenseUrl: schemaMeta.otherLicenseUrl,
otherPermissionUrl: schemaMeta.otherPermissionUrl,
reference: schemaMeta.reference,
sexualUssageName: schemaMeta.sexualUssageName,
texture: texture != null ? texture : void 0,
title: schemaMeta.title,
version: schemaMeta.version,
violentUssageName: schemaMeta.violentUssageName
};
});
}
_extractGLTFImage(index) {
return __async2(this, null, function* () {
var _a;
const json = this.parser.json;
const source = (_a = json.images) == null ? void 0 : _a[index];
if (source == null) {
console.warn(
`VRMMetaLoaderPlugin: Attempt to use images[${index}] of glTF as a thumbnail but the image doesn't exist`
);
return null;
}
let sourceURI = source.uri;
if (source.bufferView != null) {
const bufferView = yield this.parser.getDependency("bufferView", source.bufferView);
const blob = new Blob([bufferView], { type: source.mimeType });
sourceURI = URL.createObjectURL(blob);
}
if (sourceURI == null) {
console.warn(
`VRMMetaLoaderPlugin: Attempt to use images[${index}] of glTF as a thumbnail but the image couldn't load properly`
);
return null;
}
const loader = new THREE16.ImageLoader();
return yield loader.loadAsync(resolveURL(sourceURI, this.parser.options.path)).catch((error) => {
console.error(error);
console.warn("VRMMetaLoaderPlugin: Failed to load a thumbnail image");
return null;
});
});
}
};
var VRMCore = class {
/**
* Create a new VRM instance.
*
* @param params {@link VRMParameters} that represents components of the VRM
*/
constructor(params) {
this.scene = params.scene;
this.meta = params.meta;
this.humanoid = params.humanoid;
this.expressionManager = params.expressionManager;
this.firstPerson = params.firstPerson;
this.lookAt = params.lookAt;
}
/**
* **You need to call this on your update loop.**
*
* This function updates every VRM components.
*
* @param delta deltaTime
*/
update(delta) {
this.humanoid.update();
if (this.lookAt) {
this.lookAt.update(delta);
}
if (this.expressionManager) {
this.expressionManager.update();
}
}
};
var VRMCoreLoaderPlugin = class {
get name() {
return "VRMC_vrm";
}
constructor(parser, options) {
var _a, _b, _c, _d, _e;
this.parser = parser;
const helperRoot = options == null ? void 0 : options.helperRoot;
const autoUpdateHumanBones = options == null ? void 0 : options.autoUpdateHumanBones;
this.expressionPlugin = (_a = options == null ? void 0 : options.expressionPlugin) != null ? _a : new VRMExpressionLoaderPlugin(parser);
this.firstPersonPlugin = (_b = options == null ? void 0 : options.firstPersonPlugin) != null ? _b : new VRMFirstPersonLoaderPlugin(parser);
this.humanoidPlugin = (_c = options == null ? void 0 : options.humanoidPlugin) != null ? _c : new VRMHumanoidLoaderPlugin(parser, { helperRoot, autoUpdateHumanBones });
this.lookAtPlugin = (_d = options == null ? void 0 : options.lookAtPlugin) != null ? _d : new VRMLookAtLoaderPlugin(parser, { helperRoot });
this.metaPlugin = (_e = options == null ? void 0 : options.metaPlugin) != null ? _e : new VRMMetaLoaderPlugin(parser);
}
afterRoot(gltf) {
return __async2(this, null, function* () {
yield this.metaPlugin.afterRoot(gltf);
yield this.humanoidPlugin.afterRoot(gltf);
yield this.expressionPlugin.afterRoot(gltf);
yield this.lookAtPlugin.afterRoot(gltf);
yield this.firstPersonPlugin.afterRoot(gltf);
const meta = gltf.userData.vrmMeta;
const humanoid = gltf.userData.vrmHumanoid;
if (meta && humanoid) {
const vrmCore = new VRMCore({
scene: gltf.scene,
expressionManager: gltf.userData.vrmExpressionManager,
firstPerson: gltf.userData.vrmFirstPerson,
humanoid,
lookAt: gltf.userData.vrmLookAt,
meta
});
gltf.userData.vrmCore = vrmCore;
}
});
}
};
// src/VRM.ts
var VRM = class extends VRMCore {
/**
* Create a new VRM instance.
*
* @param params {@link VRMParameters} that represents components of the VRM
*/
constructor(params) {
super(params);
this.materials = params.materials;
this.springBoneManager = params.springBoneManager;
this.nodeConstraintManager = params.nodeConstraintManager;
}
/**
* **You need to call this on your update loop.**
*
* This function updates every VRM components.
*
* @param delta deltaTime
*/
update(delta) {
super.update(delta);
if (this.nodeConstraintManager) {
this.nodeConstraintManager.update();
}
if (this.springBoneManager) {
this.springBoneManager.update(delta);
}
if (this.materials) {
this.materials.forEach((material) => {
if (material.update) {
material.update(delta);
}
});
}
}
};
// ../three-vrm-materials-mtoon/lib/three-vrm-materials-mtoon.module.js
var THREE52 = __toESM(require("three"), 1);
var THREE22 = __toESM(require("three"), 1);
var THREE17 = __toESM(require("three"), 1);
var THREE42 = __toESM(require("three"), 1);
var THREE32 = __toESM(require("three"), 1);
var __defProp2 = Object.defineProperty;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp2 = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp2.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __async3 = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
var colorSpaceEncodingMap = {
// eslint-disable-next-line @typescript-eslint/naming-convention
"": 3e3,
srgb: 3001
};
function setTextureColorSpace(texture, colorSpace) {
if (parseInt(THREE17.REVISION, 10) >= 152) {
texture.colorSpace = colorSpace;
} else {
texture.encoding = colorSpaceEncodingMap[colorSpace];
}
}
var GLTFMToonMaterialParamsAssignHelper = class {
get pending() {
return Promise.all(this._pendings);
}
constructor(parser, materialParams) {
this._parser = parser;
this._materialParams = materialParams;
this._pendings = [];
}
assignPrimitive(key, value) {
if (value != null) {
this._materialParams[key] = value;
}
}
assignColor(key, value, convertSRGBToLinear) {
if (value != null) {
this._materialParams[key] = new THREE22.Color().fromArray(value);
if (convertSRGBToLinear) {
this._materialParams[key].convertSRGBToLinear();
}
}
}
assignTexture(key, texture, isColorTexture) {
return __async3(this, null, function* () {
const promise = (() => __async3(this, null, function* () {
if (texture != null) {
yield this._parser.assignTexture(this._materialParams, key, texture);
if (isColorTexture) {
setTextureColorSpace(this._materialParams[key], "srgb");
}
}
}))();
this._pendings.push(promise);
return promise;
});
}
assignTextureByIndex(key, textureIndex, isColorTexture) {
return __async3(this, null, function* () {
return this.assignTexture(key, textureIndex != null ? { index: textureIndex } : void 0, isColorTexture);
});
}
};
var mtoon_default = "// #define PHONG\n\nvarying vec3 vViewPosition;\n\n#ifndef FLAT_SHADED\n varying vec3 vNormal;\n#endif\n\n#include <common>\n\n// #include <uv_pars_vertex>\n#ifdef MTOON_USE_UV\n varying vec2 vUv;\n\n // COMPAT: pre-r151 uses a common uvTransform\n #if THREE_VRM_THREE_REVISION < 151\n uniform mat3 uvTransform;\n #endif\n#endif\n\n// #include <uv2_pars_vertex>\n// COMAPT: pre-r151 uses uv2 for lightMap and aoMap\n#if THREE_VRM_THREE_REVISION < 151\n #if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n attribute vec2 uv2;\n varying vec2 vUv2;\n uniform mat3 uv2Transform;\n #endif\n#endif\n\n// #include <displacementmap_pars_vertex>\n// #include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\n\n#ifdef USE_OUTLINEWIDTHMULTIPLYTEXTURE\n uniform sampler2D outlineWidthMultiplyTexture;\n uniform mat3 outlineWidthMultiplyTextureUvTransform;\n#endif\n\nuniform float outlineWidthFactor;\n\nvoid main() {\n\n // #include <uv_vertex>\n #ifdef MTOON_USE_UV\n // COMPAT: pre-r151 uses a common uvTransform\n #if THREE_VRM_THREE_REVISION >= 151\n vUv = uv;\n #else\n vUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n #endif\n #endif\n\n // #include <uv2_vertex>\n // COMAPT: pre-r151 uses uv2 for lightMap and aoMap\n #if THREE_VRM_THREE_REVISION < 151\n #if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n vUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n #endif\n #endif\n\n #include <color_vertex>\n\n #include <beginnormal_vertex>\n #include <morphnormal_vertex>\n #include <skinbase_vertex>\n #include <skinnormal_vertex>\n\n // we need this to compute the outline properly\n objectNormal = normalize( objectNormal );\n\n #include <defaultnormal_vertex>\n\n #ifndef FLAT_SHADED // Normal computed with derivatives when FLAT_SHADED\n vNormal = normalize( transformedNormal );\n #endif\n\n #include <begin_vertex>\n\n #include <morphtarget_vertex>\n #include <skinning_vertex>\n // #include <displacementmap_vertex>\n #include <project_vertex>\n #include <logdepthbuf_vertex>\n #include <clipping_planes_vertex>\n\n vViewPosition = - mvPosition.xyz;\n\n #ifdef OUTLINE\n float worldNormalLength = length( transformedNormal );\n vec3 outlineOffset = outlineWidthFactor * worldNormalLength * objectNormal;\n\n #ifdef USE_OUTLINEWIDTHMULTIPLYTEXTURE\n vec2 outlineWidthMultiplyTextureUv = ( outlineWidthMultiplyTextureUvTransform * vec3( vUv, 1 ) ).xy;\n float outlineTex = texture2D( outlineWidthMultiplyTexture, outlineWidthMultiplyTextureUv ).g;\n outlineOffset *= outlineTex;\n #endif\n\n #ifdef OUTLINE_WIDTH_SCREEN\n outlineOffset *= vViewPosition.z / projectionMatrix[ 1 ].y;\n #endif\n\n gl_Position = projectionMatrix * modelViewMatrix * vec4( outlineOffset + transformed, 1.0 );\n\n gl_Position.z += 1E-6 * gl_Position.w; // anti-artifact magic\n #endif\n\n #include <worldpos_vertex>\n // #include <envmap_vertex>\n #include <shadowmap_vertex>\n #include <fog_vertex>\n\n}";
var mtoon_default2 = "// #define PHONG\n\nuniform vec3 litFactor;\n\nuniform float opacity;\n\nuniform vec3 shadeColorFactor;\n#ifdef USE_SHADEMULTIPLYTEXTURE\n uniform sampler2D shadeMultiplyTexture;\n uniform mat3 shadeMultiplyTextureUvTransform;\n#endif\n\nuniform float shadingShiftFactor;\nuniform float shadingToonyFactor;\n\n#ifdef USE_SHADINGSHIFTTEXTURE\n uniform sampler2D shadingShiftTexture;\n uniform mat3 shadingShiftTextureUvTransform;\n uniform float shadingShiftTextureScale;\n#endif\n\nuniform float giEqualizationFactor;\n\nuniform vec3 parametricRimColorFactor;\n#ifdef USE_RIMMULTIPLYTEXTURE\n uniform sampler2D rimMultiplyTexture;\n uniform mat3 rimMultiplyTextureUvTransform;\n#endif\nuniform float rimLightingMixFactor;\nuniform float parametricRimFresnelPowerFactor;\nuniform float parametricRimLiftFactor;\n\n#ifdef USE_MATCAPTEXTURE\n uniform vec3 matcapFactor;\n uniform sampler2D matcapTexture;\n uniform mat3 matcapTextureUvTransform;\n#endif\n\nuniform vec3 emissive;\nuniform float emissiveIntensity;\n\nuniform vec3 outlineColorFactor;\nuniform float outlineLightingMixFactor;\n\n#ifdef USE_UVANIMATIONMASKTEXTURE\n uniform sampler2D uvAnimationMaskTexture;\n uniform mat3 uvAnimationMaskTextureUvTransform;\n#endif\n\nuniform float uvAnimationScrollXOffset;\nuniform float uvAnimationScrollYOffset;\nuniform float uvAnimationRotationPhase;\n\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n\n// #include <uv_pars_fragment>\n#if ( defined( MTOON_USE_UV ) && !defined( MTOON_UVS_VERTEX_ONLY ) )\n varying vec2 vUv;\n#endif\n\n// #include <uv2_pars_fragment>\n// COMAPT: pre-r151 uses uv2 for lightMap and aoMap\n#if THREE_VRM_THREE_REVISION < 151\n #if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n varying vec2 vUv2;\n #endif\n#endif\n\n#include <map_pars_fragment>\n\n#ifdef USE_MAP\n uniform mat3 mapUvTransform;\n#endif\n\n// #include <alphamap_pars_fragment>\n\n#include <alphatest_pars_fragment>\n\n#include <aomap_pars_fragment>\n// #include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n\n#ifdef USE_EMISSIVEMAP\n uniform mat3 emissiveMapUvTransform;\n#endif\n\n// #include <envmap_common_pars_fragment>\n// #include <envmap_pars_fragment>\n// #include <cube_uv_reflection_fragment>\n#include <fog_pars_fragment>\n\n// #include <bsdfs>\n// COMPAT: pre-r151 doesn't have BRDF_Lambert in <common>\n#if THREE_VRM_THREE_REVISION < 151\n vec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n return RECIPROCAL_PI * diffuseColor;\n }\n#endif\n\n#include <lights_pars_begin>\n\n#include <normal_pars_fragment>\n\n// #include <lights_phong_pars_fragment>\nvarying vec3 vViewPosition;\n\nstruct MToonMaterial {\n vec3 diffuseColor;\n vec3 shadeColor;\n float shadingShift;\n};\n\nfloat linearstep( float a, float b, float t ) {\n return clamp( ( t - a ) / ( b - a ), 0.0, 1.0 );\n}\n\n/**\n * Convert NdotL into toon shading factor using shadingShift and shadingToony\n */\nfloat getShading(\n const in float dotNL,\n const in float shadow,\n const in float shadingShift\n) {\n float shading = dotNL;\n shading = shading + shadingShift;\n shading = linearstep( -1.0 + shadingToonyFactor, 1.0 - shadingToonyFactor, shading );\n shading *= shadow;\n return shading;\n}\n\n/**\n * Mix diffuseColor and shadeColor using shading factor and light color\n */\nvec3 getDiffuse(\n const in MToonMaterial material,\n const in float shading,\n in vec3 lightColor\n) {\n #ifdef DEBUG_LITSHADERATE\n return vec3( BRDF_Lambert( shading * lightColor ) );\n #endif\n\n vec3 col = lightColor * BRDF_Lambert( mix( material.shadeColor, material.diffuseColor, shading ) );\n\n // The \"comment out if you want to PBR absolutely\" line\n #ifdef V0_COMPAT_SHADE\n col = min( col, material.diffuseColor );\n #endif\n\n return col;\n}\n\n// COMPAT: pre-r156 uses a struct GeometricContext\n#if THREE_VRM_THREE_REVISION >= 157\n void RE_Direct_MToon( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const
var MToonMaterialDebugMode = {
/**
* Render normally.
*/
None: "none",
/**
* Visualize normals of the surface.
*/
Normal: "normal",
/**
* Visualize lit/shade of the surface.
*/
LitShadeRate: "litShadeRate",
/**
* Visualize UV of the surface.
*/
UV: "uv"
};
var MToonMaterialOutlineWidthMode = {
None: "none",
WorldCoordinates: "worldCoordinates",
ScreenCoordinates: "screenCoordinates"
};
var encodingColorSpaceMap = {
// eslint-disable-next-line @typescript-eslint/naming-convention
3e3: "",
// eslint-disable-next-line @typescript-eslint/naming-convention
3001: "srgb"
};
function getTextureColorSpace(texture) {
if (parseInt(THREE32.REVISION, 10) >= 152) {
return texture.colorSpace;
} else {
return encodingColorSpaceMap[texture.encoding];
}
}
var MToonMaterial = class extends THREE42.ShaderMaterial {
constructor(parameters = {}) {
var _a;
super({ vertexShader: mtoon_default, fragmentShader: mtoon_default2 });
this.uvAnimationScrollXSpeedFactor = 0;
this.uvAnimationScrollYSpeedFactor = 0;
this.uvAnimationRotationSpeedFactor = 0;
this.fog = true;
this.normalMapType = THREE42.TangentSpaceNormalMap;
this._ignoreVertexColor = true;
this._v0CompatShade = false;
this._debugMode = MToonMaterialDebugMode.None;
this._outlineWidthMode = MToonMaterialOutlineWidthMode.None;
this._isOutline = false;
if (parameters.transparentWithZWrite) {
parameters.depthWrite = true;
}
delete parameters.transparentWithZWrite;
parameters.fog = true;
parameters.lights = true;
parameters.clipping = true;
this.uniforms = THREE42.UniformsUtils.merge([
THREE42.UniformsLib.common,
// map
THREE42.UniformsLib.normalmap,
// normalMap
THREE42.UniformsLib.emissivemap,
// emissiveMap
THREE42.UniformsLib.fog,
THREE42.UniformsLib.lights,
{
litFactor: { value: new THREE42.Color(1, 1, 1) },
mapUvTransform: { value: new THREE42.Matrix3() },
colorAlpha: { value: 1 },
normalMapUvTransform: { value: new THREE42.Matrix3() },
shadeColorFactor: { value: new THREE42.Color(0, 0, 0) },
shadeMultiplyTexture: { value: null },
shadeMultiplyTextureUvTransform: { value: new THREE42.Matrix3() },
shadingShiftFactor: { value: 0 },
shadingShiftTexture: { value: null },
shadingShiftTextureUvTransform: { value: new THREE42.Matrix3() },
shadingShiftTextureScale: { value: 1 },
shadingToonyFactor: { value: 0.9 },
giEqualizationFactor: { value: 0.9 },
matcapFactor: { value: new THREE42.Color(1, 1, 1) },
matcapTexture: { value: null },
matcapTextureUvTransform: { value: new THREE42.Matrix3() },
parametricRimColorFactor: { value: new THREE42.Color(0, 0, 0) },
rimMultiplyTexture: { value: null },
rimMultiplyTextureUvTransform: { value: new THREE42.Matrix3() },
rimLightingMixFactor: { value: 1 },
parametricRimFresnelPowerFactor: { value: 5 },
parametricRimLiftFactor: { value: 0 },
emissive: { value: new THREE42.Color(0, 0, 0) },
emissiveIntensity: { value: 1 },
emissiveMapUvTransform: { value: new THREE42.Matrix3() },
outlineWidthMultiplyTexture: { value: null },
outlineWidthMultiplyTextureUvTransform: { value: new THREE42.Matrix3() },
outlineWidthFactor: { value: 0 },
outlineColorFactor: { value: new THREE42.Color(0, 0, 0) },
outlineLightingMixFactor: { value: 1 },
uvAnimationMaskTexture: { value: null },
uvAnimationMaskTextureUvTransform: { value: new THREE42.Matrix3() },
uvAnimationScrollXOffset: { value: 0 },
uvAnimationScrollYOffset: { value: 0 },
uvAnimationRotationPhase: { value: 0 }
},
(_a = parameters.uniforms) != null ? _a : {}
]);
this.setValues(parameters);
this._uploadUniformsWorkaround();
this.customProgramCacheKey = () => [
...Object.entries(this._generateDefines()).map(([token, macro]) => `${token}:${macro}`),
this.matcapTexture ? `matcapTextureColorSpace:${getTextureColorSpace(this.matcapTexture)}` : "",
this.shadeMultiplyTexture ? `shadeMultiplyTextureColorSpace:${getTextureColorSpace(this.shadeMultiplyTexture)}` : "",
this.rimMultiplyTexture ? `rimMultiplyTextureColorSpace:${getTextureColorSpace(this.rimMultiplyTexture)}` : ""
].join(",");
this.onBeforeCompile = (shader) => {
const threeRevision = parseInt(THREE42.REVISION, 10);
const defines = Object.entries(__spreadValues(__spreadValues({}, this._generateDefines()), this.defines)).filter(([token, macro]) => !!macro).map(([token, macro]) => `#define ${token} ${macro}`).join("\n") + "\n";
shader.vertexShader = defines + shader.vertexShader;
shader.fragmentShader = defines + shader.fragmentShader;
if (threeRevision < 154) {
shader.fragmentShader = shader.fragmentShader.replace(
"#include <colorspace_fragment>",
"#include <encodings_fragment>"
);
}
};
}
get color() {
return this.uniforms.litFactor.value;
}
set color(value) {
this.uniforms.litFactor.value = value;
}
get map() {
return this.uniforms.map.value;
}
set map(value) {
this.uniforms.map.value = value;
}
get normalMap() {
return this.uniforms.normalMap.value;
}
set normalMap(value) {
this.uniforms.normalMap.value = value;
}
get normalScale() {
return this.uniforms.normalScale.value;
}
set normalScale(value) {
this.uniforms.normalScale.value = value;
}
get emissive() {
return this.uniforms.emissive.value;
}
set emissive(value) {
this.uniforms.emissive.value = value;
}
get emissiveIntensity() {
return this.uniforms.emissiveIntensity.value;
}
set emissiveIntensity(value) {
this.uniforms.emissiveIntensity.value = value;
}
get emissiveMap() {
return this.uniforms.emissiveMap.value;
}
set emissiveMap(value) {
this.uniforms.emissiveMap.value = value;
}
get shadeColorFactor() {
return this.uniforms.shadeColorFactor.value;
}
set shadeColorFactor(value) {
this.uniforms.shadeColorFactor.value = value;
}
get shadeMultiplyTexture() {
return this.uniforms.shadeMultiplyTexture.value;
}
set shadeMultiplyTexture(value) {
this.uniforms.shadeMultiplyTexture.value = value;
}
get shadingShiftFactor() {
return this.uniforms.shadingShiftFactor.value;
}
set shadingShiftFactor(value) {
this.uniforms.shadingShiftFactor.value = value;
}
get shadingShiftTexture() {
return this.uniforms.shadingShiftTexture.value;
}
set shadingShiftTexture(value) {
this.uniforms.shadingShiftTexture.value = value;
}
get shadingShiftTextureScale() {
return this.uniforms.shadingShiftTextureScale.value;
}
set shadingShiftTextureScale(value) {
this.uniforms.shadingShiftTextureScale.value = value;
}
get shadingToonyFactor() {
return this.uniforms.shadingToonyFactor.value;
}
set shadingToonyFactor(value) {
this.uniforms.shadingToonyFactor.value = value;
}
get giEqualizationFactor() {
return this.uniforms.giEqualizationFactor.value;
}
set giEqualizationFactor(value) {
this.uniforms.giEqualizationFactor.value = value;
}
get matcapFactor() {
return this.uniforms.matcapFactor.value;
}
set matcapFactor(value) {
this.uniforms.matcapFactor.value = value;
}
get matcapTexture() {
return this.uniforms.matcapTexture.value;
}
set matcapTexture(value) {
this.uniforms.matcapTexture.value = value;
}
get parametricRimColorFactor() {
return this.uniforms.parametricRimColorFactor.value;
}
set parametricRimColorFactor(value) {
this.uniforms.parametricRimColorFactor.value = value;
}
get rimMultiplyTexture() {
return this.uniforms.rimMultiplyTexture.value;
}
set rimMultiplyTexture(value) {
this.uniforms.rimMultiplyTexture.value = value;
}
get rimLightingMixFactor() {
return this.uniforms.rimLightingMixFactor.value;
}
set rimLightingMixFactor(value) {
this.uniforms.rimLightingMixFactor.value = value;
}
get parametricRimFresnelPowerFactor() {
return this.uniforms.parametricRimFresnelPowerFactor.value;
}
set parametricRimFresnelPowerFactor(value) {
this.uniforms.parametricRimFresnelPowerFactor.value = value;
}
get parametricRimLiftFactor() {
return this.uniforms.parametricRimLiftFactor.value;
}
set parametricRimLiftFactor(value) {
this.uniforms.parametricRimLiftFactor.value = value;
}
get outlineWidthMultiplyTexture() {
return this.uniforms.outlineWidthMultiplyTexture.value;
}
set outlineWidthMultiplyTexture(value) {
this.uniforms.outlineWidthMultiplyTexture.value = value;
}
get outlineWidthFactor() {
return this.uniforms.outlineWidthFactor.value;
}
set outlineWidthFactor(value) {
this.uniforms.outlineWidthFactor.value = value;
}
get outlineColorFactor() {
return this.uniforms.outlineColorFactor.value;
}
set outlineColorFactor(value) {
this.uniforms.outlineColorFactor.value = value;
}
get outlineLightingMixFactor() {
return this.uniforms.outlineLightingMixFactor.value;
}
set outlineLightingMixFactor(value) {
this.uniforms.outlineLightingMixFactor.value = value;
}
get uvAnimationMaskTexture() {
return this.uniforms.uvAnimationMaskTexture.value;
}
set uvAnimationMaskTexture(value) {
this.uniforms.uvAnimationMaskTexture.value = value;
}
get uvAnimationScrollXOffset() {
return this.uniforms.uvAnimationScrollXOffset.value;
}
set uvAnimationScrollXOffset(value) {
this.uniforms.uvAnimationScrollXOffset.value = value;
}
get uvAnimationScrollYOffset() {
return this.uniforms.uvAnimationScrollYOffset.value;
}
set uvAnimationScrollYOffset(value) {
this.uniforms.uvAnimationScrollYOffset.value = value;
}
get uvAnimationRotationPhase() {
return this.uniforms.uvAnimationRotationPhase.value;
}
set uvAnimationRotationPhase(value) {
this.uniforms.uvAnimationRotationPhase.value = value;
}
/**
* When this is `true`, vertex colors will be ignored.
* `true` by default.
*/
get ignoreVertexColor() {
return this._ignoreVertexColor;
}
set ignoreVertexColor(value) {
this._ignoreVertexColor = value;
this.needsUpdate = true;
}
/**
* There is a line of the shader called "comment out if you want to PBR absolutely" in VRM0.0 MToon.
* When this is true, the material enables the line to make it compatible with the legacy rendering of VRM.
* Usually not recommended to turn this on.
* `false` by default.
*/
get v0CompatShade() {
return this._v0CompatShade;
}
/**
* There is a line of the shader called "comment out if you want to PBR absolutely" in VRM0.0 MToon.
* When this is true, the material enables the line to make it compatible with the legacy rendering of VRM.
* Usually not recommended to turn this on.
* `false` by default.
*/
set v0CompatShade(v) {
this._v0CompatShade = v;
this.needsUpdate = true;
}
/**
* Debug mode for the material.
* You can visualize several components for diagnosis using debug mode.
*
* See: {@link MToonMaterialDebugMode}
*/
get debugMode() {
return this._debugMode;
}
/**
* Debug mode for the material.
* You can visualize several components for diagnosis using debug mode.
*
* See: {@link MToonMaterialDebugMode}
*/
set debugMode(m) {
this._debugMode = m;
this.needsUpdate = true;
}
get outlineWidthMode() {
return this._outlineWidthMode;
}
set outlineWidthMode(m) {
this._outlineWidthMode = m;
this.needsUpdate = true;
}
get isOutline() {
return this._isOutline;
}
set isOutline(b) {
this._isOutline = b;
this.needsUpdate = true;
}
/**
* Readonly boolean that indicates this is a {@link MToonMaterial}.
*/
get isMToonMaterial() {
return true;
}
/**
* Update this material.
*
* @param delta deltaTime since last update
*/
update(delta) {
this._uploadUniformsWorkaround();
this._updateUVAnimation(delta);
}
copy(source) {
super.copy(source);
this.map = source.map;
this.normalMap = source.normalMap;
this.emissiveMap = source.emissiveMap;
this.shadeMultiplyTexture = source.shadeMultiplyTexture;
this.shadingShiftTexture = source.shadingShiftTexture;
this.matcapTexture = source.matcapTexture;
this.rimMultiplyTexture = source.rimMultiplyTexture;
this.outlineWidthMultiplyTexture = source.outlineWidthMultiplyTexture;
this.uvAnimationMaskTexture = source.uvAnimationMaskTexture;
this.normalMapType = source.normalMapType;
this.uvAnimationScrollXSpeedFactor = source.uvAnimationScrollXSpeedFactor;
this.uvAnimationScrollYSpeedFactor = source.uvAnimationScrollYSpeedFactor;
this.uvAnimationRotationSpeedFactor = source.uvAnimationRotationSpeedFactor;
this.ignoreVertexColor = source.ignoreVertexColor;
this.v0CompatShade = source.v0CompatShade;
this.debugMode = source.debugMode;
this.outlineWidthMode = source.outlineWidthMode;
this.isOutline = source.isOutline;
this.needsUpdate = true;
return this;
}
/**
* Update UV animation state.
* Intended to be called via {@link update}.
* @param delta deltaTime
*/
_updateUVAnimation(delta) {
this.uniforms.uvAnimationScrollXOffset.value += delta * this.uvAnimationScrollXSpeedFactor;
this.uniforms.uvAnimationScrollYOffset.value += delta * this.uvAnimationScrollYSpeedFactor;
this.uniforms.uvAnimationRotationPhase.value += delta * this.uvAnimationRotationSpeedFactor;
this.uniforms.alphaTest.value = this.alphaTest;
this.uniformsNeedUpdate = true;
}
/**
* Upload uniforms that need to upload but doesn't automatically because of reasons.
* Intended to be called via {@link constructor} and {@link update}.
*/
_uploadUniformsWorkaround() {
this.uniforms.opacity.value = this.opacity;
this._updateTextureMatrix(this.uniforms.map, this.uniforms.mapUvTransform);
this._updateTextureMatrix(this.uniforms.normalMap, this.uniforms.normalMapUvTransform);
this._updateTextureMatrix(this.uniforms.emissiveMap, this.uniforms.emissiveMapUvTransform);
this._updateTextureMatrix(this.uniforms.shadeMultiplyTexture, this.uniforms.shadeMultiplyTextureUvTransform);
this._updateTextureMatrix(this.uniforms.shadingShiftTexture, this.uniforms.shadingShiftTextureUvTransform);
this._updateTextureMatrix(this.uniforms.matcapTexture, this.uniforms.matcapTextureUvTransform);
this._updateTextureMatrix(this.uniforms.rimMultiplyTexture, this.uniforms.rimMultiplyTextureUvTransform);
this._updateTextureMatrix(
this.uniforms.outlineWidthMultiplyTexture,
this.uniforms.outlineWidthMultiplyTextureUvTransform
);
this._updateTextureMatrix(this.uniforms.uvAnimationMaskTexture, this.uniforms.uvAnimationMaskTextureUvTransform);
this.uniformsNeedUpdate = true;
}
/**
* Returns a map object of preprocessor token and macro of the shader program.
*/
_generateDefines() {
const threeRevision = parseInt(THREE42.REVISION, 10);
const useUvInVert = this.outlineWidthMultiplyTexture !== null;
const useUvInFrag = this.map !== null || this.normalMap !== null || this.emissiveMap !== null || this.shadeMultiplyTexture !== null || this.shadingShiftTexture !== null || this.rimMultiplyTexture !== null || this.uvAnimationMaskTexture !== null;
return {
// Temporary compat against shader change @ Three.js r126
// See: #21205, #21307, #21299
THREE_VRM_THREE_REVISION: threeRevision,
OUTLINE: this._isOutline,
MTOON_USE_UV: useUvInVert || useUvInFrag,
// we can't use `USE_UV` , it will be redefined in WebGLProgram.js
MTOON_UVS_VERTEX_ONLY: useUvInVert && !useUvInFrag,
V0_COMPAT_SHADE: this._v0CompatShade,
USE_SHADEMULTIPLYTEXTURE: this.shadeMultiplyTexture !== null,
USE_SHADINGSHIFTTEXTURE: this.shadingShiftTexture !== null,
USE_MATCAPTEXTURE: this.matcapTexture !== null,
USE_RIMMULTIPLYTEXTURE: this.rimMultiplyTexture !== null,
USE_OUTLINEWIDTHMULTIPLYTEXTURE: this._isOutline && this.outlineWidthMultiplyTexture !== null,
USE_UVANIMATIONMASKTEXTURE: this.uvAnimationMaskTexture !== null,
IGNORE_VERTEX_COLOR: this._ignoreVertexColor === true,
DEBUG_NORMAL: this._debugMode === "normal",
DEBUG_LITSHADERATE: this._debugMode === "litShadeRate",
DEBUG_UV: this._debugMode === "uv",
OUTLINE_WIDTH_SCREEN: this._isOutline && this._outlineWidthMode === MToonMaterialOutlineWidthMode.ScreenCoordinates
};
}
_updateTextureMatrix(src, dst) {
if (src.value) {
if (src.value.matrixAutoUpdate) {
src.value.updateMatrix();
}
dst.value.copy(src.value.matrix);
}
}
};
var POSSIBLE_SPEC_VERSIONS6 = /* @__PURE__ */ new Set(["1.0", "1.0-beta"]);
var _MToonMaterialLoaderPlugin = class _MToonMaterialLoaderPlugin2 {
get name() {
return _MToonMaterialLoaderPlugin2.EXTENSION_NAME;
}
constructor(parser, options = {}) {
var _a, _b, _c, _d;
this.parser = parser;
this.materialType = (_a = options.materialType) != null ? _a : MToonMaterial;
this.renderOrderOffset = (_b = options.renderOrderOffset) != null ? _b : 0;
this.v0CompatShade = (_c = options.v0CompatShade) != null ? _c : false;
this.debugMode = (_d = options.debugMode) != null ? _d : "none";
this._mToonMaterialSet = /* @__PURE__ */ new Set();
}
beforeRoot() {
return __async3(this, null, function* () {
this._removeUnlitExtensionIfMToonExists();
});
}
afterRoot(gltf) {
return __async3(this, null, function* () {
gltf.userData.vrmMToonMaterials = Array.from(this._mToonMaterialSet);
});
}
getMaterialType(materialIndex) {
const v1Extension = this._getMToonExtension(materialIndex);
if (v1Extension) {
return this.materialType;
}
return null;
}
extendMaterialParams(materialIndex, materialParams) {
const extension = this._getMToonExtension(materialIndex);
if (extension) {
return this._extendMaterialParams(extension, materialParams);
}
return null;
}
loadMesh(meshIndex) {
return __async3(this, null, function* () {
var _a;
const parser = this.parser;
const json = parser.json;
const meshDef = (_a = json.meshes) == null ? void 0 : _a[meshIndex];
if (meshDef == null) {
throw new Error(
`MToonMaterialLoaderPlugin: Attempt to use meshes[${meshIndex}] of glTF but the mesh doesn't exist`
);
}
const primitivesDef = meshDef.primitives;
const meshOrGroup = yield parser.loadMesh(meshIndex);
if (primitivesDef.length === 1) {
const mesh = meshOrGroup;
const materialIndex = primitivesDef[0].material;
if (materialIndex != null) {
this._setupPrimitive(mesh, materialIndex);
}
} else {
const group = meshOrGroup;
for (let i = 0; i < primitivesDef.length; i++) {
const mesh = group.children[i];
const materialIndex = primitivesDef[i].material;
if (materialIndex != null) {
this._setupPrimitive(mesh, materialIndex);
}
}
}
return meshOrGroup;
});
}
/**
* Delete use of `KHR_materials_unlit` from its `materials` if the material is using MToon.
*
* Since GLTFLoader have so many hardcoded procedure related to `KHR_materials_unlit`
* we have to delete the extension before we start to parse the glTF.
*/
_removeUnlitExtensionIfMToonExists() {
const parser = this.parser;
const json = parser.json;
const materialDefs = json.materials;
materialDefs == null ? void 0 : materialDefs.map((materialDef, iMaterial) => {
var _a;
const extension = this._getMToonExtension(iMaterial);
if (extension && ((_a = materialDef.extensions) == null ? void 0 : _a["KHR_materials_unlit"])) {
delete materialDef.extensions["KHR_materials_unlit"];
}
});
}
_getMToonExtension(materialIndex) {
var _a, _b;
const parser = this.parser;
const json = parser.json;
const materialDef = (_a = json.materials) == null ? void 0 : _a[materialIndex];
if (materialDef == null) {
console.warn(
`MToonMaterialLoaderPlugin: Attempt to use materials[${materialIndex}] of glTF but the material doesn't exist`
);
return void 0;
}
const extension = (_b = materialDef.extensions) == null ? void 0 : _b[_MToonMaterialLoaderPlugin2.EXTENSION_NAME];
if (extension == null) {
return void 0;
}
const specVersion = extension.specVersion;
if (!POSSIBLE_SPEC_VERSIONS6.has(specVersion)) {
console.warn(
`MToonMaterialLoaderPlugin: Unknown ${_MToonMaterialLoaderPlugin2.EXTENSION_NAME} specVersion "${specVersion}"`
);
return void 0;
}
return extension;
}
_extendMaterialParams(extension, materialParams) {
return __async3(this, null, function* () {
var _a;
delete materialParams.metalness;
delete materialParams.roughness;
const assignHelper = new GLTFMToonMaterialParamsAssignHelper(this.parser, materialParams);
assignHelper.assignPrimitive("transparentWithZWrite", extension.transparentWithZWrite);
assignHelper.assignColor("shadeColorFactor", extension.shadeColorFactor);
assignHelper.assignTexture("shadeMultiplyTexture", extension.shadeMultiplyTexture, true);
assignHelper.assignPrimitive("shadingShiftFactor", extension.shadingShiftFactor);
assignHelper.assignTexture("shadingShiftTexture", extension.shadingShiftTexture, true);
assignHelper.assignPrimitive("shadingShiftTextureScale", (_a = extension.shadingShiftTexture) == null ? void 0 : _a.scale);
assignHelper.assignPrimitive("shadingToonyFactor", extension.shadingToonyFactor);
assignHelper.assignPrimitive("giEqualizationFactor", extension.giEqualizationFactor);
assignHelper.assignColor("matcapFactor", extension.matcapFactor);
assignHelper.assignTexture("matcapTexture", extension.matcapTexture, true);
assignHelper.assignColor("parametricRimColorFactor", extension.parametricRimColorFactor);
assignHelper.assignTexture("rimMultiplyTexture", extension.rimMultiplyTexture, true);
assignHelper.assignPrimitive("rimLightingMixFactor", extension.rimLightingMixFactor);
assignHelper.assignPrimitive("parametricRimFresnelPowerFactor", extension.parametricRimFresnelPowerFactor);
assignHelper.assignPrimitive("parametricRimLiftFactor", extension.parametricRimLiftFactor);
assignHelper.assignPrimitive("outlineWidthMode", extension.outlineWidthMode);
assignHelper.assignPrimitive("outlineWidthFactor", extension.outlineWidthFactor);
assignHelper.assignTexture("outlineWidthMultiplyTexture", extension.outlineWidthMultiplyTexture, false);
assignHelper.assignColor("outlineColorFactor", extension.outlineColorFactor);
assignHelper.assignPrimitive("outlineLightingMixFactor", extension.outlineLightingMixFactor);
assignHelper.assignTexture("uvAnimationMaskTexture", extension.uvAnimationMaskTexture, false);
assignHelper.assignPrimitive("uvAnimationScrollXSpeedFactor", extension.uvAnimationScrollXSpeedFactor);
assignHelper.assignPrimitive("uvAnimationScrollYSpeedFactor", extension.uvAnimationScrollYSpeedFactor);
assignHelper.assignPrimitive("uvAnimationRotationSpeedFactor", extension.uvAnimationRotationSpeedFactor);
assignHelper.assignPrimitive("v0CompatShade", this.v0CompatShade);
assignHelper.assignPrimitive("debugMode", this.debugMode);
yield assignHelper.pending;
});
}
/**
* This will do two processes that is required to render MToon properly.
*
* - Set render order
* - Generate outline
*
* @param mesh A target GLTF primitive
* @param materialIndex The material index of the primitive
*/
_setupPrimitive(mesh, materialIndex) {
const extension = this._getMToonExtension(materialIndex);
if (extension) {
const renderOrder = this._parseRenderOrder(extension);
mesh.renderOrder = renderOrder + this.renderOrderOffset;
this._generateOutline(mesh);
this._addToMaterialSet(mesh);
return;
}
}
/**
* Check whether the material should generate outline or not.
* @param surfaceMaterial The material to check
* @returns True if the material should generate outline
*/
_shouldGenerateOutline(surfaceMaterial) {
return typeof surfaceMaterial.outlineWidthMode === "string" && surfaceMaterial.outlineWidthMode !== "none" && typeof surfaceMaterial.outlineWidthFactor === "number" && surfaceMaterial.outlineWidthFactor > 0;
}
/**
* Generate outline for the given mesh, if it needs.
*
* @param mesh The target mesh
*/
_generateOutline(mesh) {
const surfaceMaterial = mesh.material;
if (!(surfaceMaterial instanceof THREE52.Material)) {
return;
}
if (!this._shouldGenerateOutline(surfaceMaterial)) {
return;
}
mesh.material = [surfaceMaterial];
const outlineMaterial = surfaceMaterial.clone();
outlineMaterial.name += " (Outline)";
outlineMaterial.isOutline = true;
outlineMaterial.side = THREE52.BackSide;
mesh.material.push(outlineMaterial);
const geometry = mesh.geometry;
const primitiveVertices = geometry.index ? geometry.index.count : geometry.attributes.position.count / 3;
geometry.addGroup(0, primitiveVertices, 0);
geometry.addGroup(0, primitiveVertices, 1);
}
_addToMaterialSet(mesh) {
const materialOrMaterials = mesh.material;
const materialSet = /* @__PURE__ */ new Set();
if (Array.isArray(materialOrMaterials)) {
materialOrMaterials.forEach((material) => materialSet.add(material));
} else {
materialSet.add(materialOrMaterials);
}
for (const material of materialSet) {
this._mToonMaterialSet.add(material);
}
}
_parseRenderOrder(extension) {
var _a;
const enabledZWrite = extension.transparentWithZWrite;
return (enabledZWrite ? 0 : 19) + ((_a = extension.renderQueueOffsetNumber) != null ? _a : 0);
}
};
_MToonMaterialLoaderPlugin.EXTENSION_NAME = "VRMC_materials_mtoon";
var MToonMaterialLoaderPlugin = _MToonMaterialLoaderPlugin;
// ../three-vrm-materials-hdr-emissive-multiplier/lib/three-vrm-materials-hdr-emissive-multiplier.module.js
var __async4 = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
var _VRMMaterialsHDREmissiveMultiplierLoaderPlugin = class _VRMMaterialsHDREmissiveMultiplierLoaderPlugin2 {
get name() {
return _VRMMaterialsHDREmissiveMultiplierLoaderPlugin2.EXTENSION_NAME;
}
constructor(parser) {
this.parser = parser;
}
extendMaterialParams(materialIndex, materialParams) {
return __async4(this, null, function* () {
const extension = this._getHDREmissiveMultiplierExtension(materialIndex);
if (extension == null) {
return;
}
console.warn(
"VRMMaterialsHDREmissiveMultiplierLoaderPlugin: `VRMC_materials_hdr_emissiveMultiplier` is archived. Use `KHR_materials_emissive_strength` instead."
);
const emissiveMultiplier = extension.emissiveMultiplier;
materialParams.emissiveIntensity = emissiveMultiplier;
});
}
_getHDREmissiveMultiplierExtension(materialIndex) {
var _a, _b;
const parser = this.parser;
const json = parser.json;
const materialDef = (_a = json.materials) == null ? void 0 : _a[materialIndex];
if (materialDef == null) {
console.warn(
`VRMMaterialsHDREmissiveMultiplierLoaderPlugin: Attempt to use materials[${materialIndex}] of glTF but the material doesn't exist`
);
return void 0;
}
const extension = (_b = materialDef.extensions) == null ? void 0 : _b[_VRMMaterialsHDREmissiveMultiplierLoaderPlugin2.EXTENSION_NAME];
if (extension == null) {
return void 0;
}
return extension;
}
};
_VRMMaterialsHDREmissiveMultiplierLoaderPlugin.EXTENSION_NAME = "VRMC_materials_hdr_emissiveMultiplier";
var VRMMaterialsHDREmissiveMultiplierLoaderPlugin = _VRMMaterialsHDREmissiveMultiplierLoaderPlugin;
// ../three-vrm-materials-v0compat/lib/three-vrm-materials-v0compat.module.js
var THREE18 = __toESM(require("three"), 1);
var __defProp3 = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols2 = Object.getOwnPropertySymbols;
var __hasOwnProp3 = Object.prototype.hasOwnProperty;
var __propIsEnum2 = Object.prototype.propertyIsEnumerable;
var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues2 = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp3.call(b, prop))
__defNormalProp2(a, prop, b[prop]);
if (__getOwnPropSymbols2)
for (var prop of __getOwnPropSymbols2(b)) {
if (__propIsEnum2.call(b, prop))
__defNormalProp2(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __async5 = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
function gammaEOTF(e) {
return Math.pow(e, 2.2);
}
var VRMMaterialsV0CompatPlugin = class {
get name() {
return "VRMMaterialsV0CompatPlugin";
}
constructor(parser) {
var _a;
this.parser = parser;
this._renderQueueMapTransparent = /* @__PURE__ */ new Map();
this._renderQueueMapTransparentZWrite = /* @__PURE__ */ new Map();
const json = this.parser.json;
json.extensionsUsed = (_a = json.extensionsUsed) != null ? _a : [];
if (json.extensionsUsed.indexOf("KHR_texture_transform") === -1) {
json.extensionsUsed.push("KHR_texture_transform");
}
}
beforeRoot() {
return __async5(this, null, function* () {
var _a;
const json = this.parser.json;
const v0VRMExtension = (_a = json.extensions) == null ? void 0 : _a["VRM"];
const v0MaterialProperties = v0VRMExtension == null ? void 0 : v0VRMExtension.materialProperties;
if (!v0MaterialProperties) {
return;
}
this._populateRenderQueueMap(v0MaterialProperties);
v0MaterialProperties.forEach((materialProperties, materialIndex) => {
var _a2, _b;
const materialDef = (_a2 = json.materials) == null ? void 0 : _a2[materialIndex];
if (materialDef == null) {
console.warn(
`VRMMaterialsV0CompatPlugin: Attempt to use materials[${materialIndex}] of glTF but the material doesn't exist`
);
return;
}
if (materialProperties.shader === "VRM/MToon") {
const material = this._parseV0MToonProperties(materialProperties, materialDef);
json.materials[materialIndex] = material;
} else if ((_b = materialProperties.shader) == null ? void 0 : _b.startsWith("VRM/Unlit")) {
const material = this._parseV0UnlitProperties(materialProperties, materialDef);
json.materials[materialIndex] = material;
} else if (materialProperties.shader === "VRM_USE_GLTFSHADER") {
} else {
console.warn(`VRMMaterialsV0CompatPlugin: Unknown shader: ${materialProperties.shader}`);
}
});
});
}
_parseV0MToonProperties(materialProperties, schemaMaterial) {
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X, _Y, _Z, __, _$, _aa;
const isTransparent = (_b = (_a = materialProperties.keywordMap) == null ? void 0 : _a["_ALPHABLEND_ON"]) != null ? _b : false;
const enabledZWrite = ((_c = materialProperties.floatProperties) == null ? void 0 : _c["_ZWrite"]) === 1;
const transparentWithZWrite = enabledZWrite && isTransparent;
const renderQueueOffsetNumber = this._v0ParseRenderQueue(materialProperties);
const isCutoff = (_e = (_d = materialProperties.keywordMap) == null ? void 0 : _d["_ALPHATEST_ON"]) != null ? _e : false;
const alphaMode = isTransparent ? "BLEND" : isCutoff ? "MASK" : "OPAQUE";
const alphaCutoff = isCutoff ? (_g = (_f = materialProperties.floatProperties) == null ? void 0 : _f["_Cutoff"]) != null ? _g : 0.5 : void 0;
const cullMode = (_i = (_h = materialProperties.floatProperties) == null ? void 0 : _h["_CullMode"]) != null ? _i : 2;
const doubleSided = cullMode === 0;
const textureTransformExt = this._portTextureTransform(materialProperties);
const baseColorFactor = ((_k = (_j = materialProperties.vectorProperties) == null ? void 0 : _j["_Color"]) != null ? _k : [1, 1, 1, 1]).map(
(v, i) => i === 3 ? v : gammaEOTF(v)
// alpha channel is stored in linear
);
const baseColorTextureIndex = (_l = materialProperties.textureProperties) == null ? void 0 : _l["_MainTex"];
const baseColorTexture = baseColorTextureIndex != null ? {
index: baseColorTextureIndex,
extensions: __spreadValues2({}, textureTransformExt)
} : void 0;
const normalTextureScale = (_n = (_m = materialProperties.floatProperties) == null ? void 0 : _m["_BumpScale"]) != null ? _n : 1;
const normalTextureIndex = (_o = materialProperties.textureProperties) == null ? void 0 : _o["_BumpMap"];
const normalTexture = normalTextureIndex != null ? {
index: normalTextureIndex,
scale: normalTextureScale,
extensions: __spreadValues2({}, textureTransformExt)
} : void 0;
const emissiveFactor = ((_q = (_p = materialProperties.vectorProperties) == null ? void 0 : _p["_EmissionColor"]) != null ? _q : [0, 0, 0, 1]).map(
gammaEOTF
);
const emissiveTextureIndex = (_r = materialProperties.textureProperties) == null ? void 0 : _r["_EmissionMap"];
const emissiveTexture = emissiveTextureIndex != null ? {
index: emissiveTextureIndex,
extensions: __spreadValues2({}, textureTransformExt)
} : void 0;
const shadeColorFactor = ((_t = (_s = materialProperties.vectorProperties) == null ? void 0 : _s["_ShadeColor"]) != null ? _t : [0.97, 0.81, 0.86, 1]).map(
gammaEOTF
);
const shadeMultiplyTextureIndex = (_u = materialProperties.textureProperties) == null ? void 0 : _u["_ShadeTexture"];
const shadeMultiplyTexture = shadeMultiplyTextureIndex != null ? {
index: shadeMultiplyTextureIndex,
extensions: __spreadValues2({}, textureTransformExt)
} : void 0;
let shadingShiftFactor = (_w = (_v = materialProperties.floatProperties) == null ? void 0 : _v["_ShadeShift"]) != null ? _w : 0;
let shadingToonyFactor = (_y = (_x = materialProperties.floatProperties) == null ? void 0 : _x["_ShadeToony"]) != null ? _y : 0.9;
shadingToonyFactor = THREE18.MathUtils.lerp(shadingToonyFactor, 1, 0.5 + 0.5 * shadingShiftFactor);
shadingShiftFactor = -shadingShiftFactor - (1 - shadingToonyFactor);
const giIntensityFactor = (_A = (_z = materialProperties.floatProperties) == null ? void 0 : _z["_IndirectLightIntensity"]) != null ? _A : 0.1;
const giEqualizationFactor = giIntensityFactor ? 1 - giIntensityFactor : void 0;
const matcapTextureIndex = (_B = materialProperties.textureProperties) == null ? void 0 : _B["_SphereAdd"];
const matcapFactor = matcapTextureIndex != null ? [1, 1, 1] : void 0;
const matcapTexture = matcapTextureIndex != null ? {
index: matcapTextureIndex
} : void 0;
const rimLightingMixFactor = (_D = (_C = materialProperties.floatProperties) == null ? void 0 : _C["_RimLightingMix"]) != null ? _D : 0;
const rimMultiplyTextureIndex = (_E = materialProperties.textureProperties) == null ? void 0 : _E["_RimTexture"];
const rimMultiplyTexture = rimMultiplyTextureIndex != null ? {
index: rimMultiplyTextureIndex,
extensions: __spreadValues2({}, textureTransformExt)
} : void 0;
const parametricRimColorFactor = ((_G = (_F = materialProperties.vectorProperties) == null ? void 0 : _F["_RimColor"]) != null ? _G : [0, 0, 0, 1]).map(
gammaEOTF
);
const parametricRimFresnelPowerFactor = (_I = (_H = materialProperties.floatProperties) == null ? void 0 : _H["_RimFresnelPower"]) != null ? _I : 1;
const parametricRimLiftFactor = (_K = (_J = materialProperties.floatProperties) == null ? void 0 : _J["_RimLift"]) != null ? _K : 0;
const outlineWidthMode = ["none", "worldCoordinates", "screenCoordinates"][(_M = (_L = materialProperties.floatProperties) == null ? void 0 : _L["_OutlineWidthMode"]) != null ? _M : 0];
let outlineWidthFactor = (_O = (_N = materialProperties.floatProperties) == null ? void 0 : _N["_OutlineWidth"]) != null ? _O : 0;
outlineWidthFactor = 0.01 * outlineWidthFactor;
const outlineWidthMultiplyTextureIndex = (_P = materialProperties.textureProperties) == null ? void 0 : _P["_OutlineWidthTexture"];
const outlineWidthMultiplyTexture = outlineWidthMultiplyTextureIndex != null ? {
index: outlineWidthMultiplyTextureIndex,
extensions: __spreadValues2({}, textureTransformExt)
} : void 0;
const outlineColorFactor = ((_R = (_Q = materialProperties.vectorProperties) == null ? void 0 : _Q["_OutlineColor"]) != null ? _R : [0, 0, 0]).map(
gammaEOTF
);
const outlineColorMode = (_T = (_S = materialProperties.floatProperties) == null ? void 0 : _S["_OutlineColorMode"]) != null ? _T : 0;
const outlineLightingMixFactor = outlineColorMode === 1 ? (_V = (_U = materialProperties.floatProperties) == null ? void 0 : _U["_OutlineLightingMix"]) != null ? _V : 1 : 0;
const uvAnimationMaskTextureIndex = (_W = materialProperties.textureProperties) == null ? void 0 : _W["_UvAnimMaskTexture"];
const uvAnimationMaskTexture = uvAnimationMaskTextureIndex != null ? {
index: uvAnimationMaskTextureIndex,
extensions: __spreadValues2({}, textureTransformExt)
} : void 0;
const uvAnimationScrollXSpeedFactor = (_Y = (_X = materialProperties.floatProperties) == null ? void 0 : _X["_UvAnimScrollX"]) != null ? _Y : 0;
let uvAnimationScrollYSpeedFactor = (__ = (_Z = materialProperties.floatProperties) == null ? void 0 : _Z["_UvAnimScrollY"]) != null ? __ : 0;
if (uvAnimationScrollYSpeedFactor != null) {
uvAnimationScrollYSpeedFactor = -uvAnimationScrollYSpeedFactor;
}
const uvAnimationRotationSpeedFactor = (_aa = (_$ = materialProperties.floatProperties) == null ? void 0 : _$["_UvAnimRotation"]) != null ? _aa : 0;
const mtoonExtension = {
specVersion: "1.0",
transparentWithZWrite,
renderQueueOffsetNumber,
shadeColorFactor,
shadeMultiplyTexture,
shadingShiftFactor,
shadingToonyFactor,
giEqualizationFactor,
matcapFactor,
matcapTexture,
rimLightingMixFactor,
rimMultiplyTexture,
parametricRimColorFactor,
parametricRimFresnelPowerFactor,
parametricRimLiftFactor,
outlineWidthMode,
outlineWidthFactor,
outlineWidthMultiplyTexture,
outlineColorFactor,
outlineLightingMixFactor,
uvAnimationMaskTexture,
uvAnimationScrollXSpeedFactor,
uvAnimationScrollYSpeedFactor,
uvAnimationRotationSpeedFactor
};
return __spreadProps(__spreadValues2({}, schemaMaterial), {
pbrMetallicRoughness: {
baseColorFactor,
baseColorTexture
},
normalTexture,
emissiveTexture,
emissiveFactor,
alphaMode,
alphaCutoff,
doubleSided,
extensions: {
// eslint-disable-next-line @typescript-eslint/naming-convention
VRMC_materials_mtoon: mtoonExtension
}
});
}
_parseV0UnlitProperties(materialProperties, schemaMaterial) {
var _a, _b, _c, _d, _e;
const isTransparentZWrite = materialProperties.shader === "VRM/UnlitTransparentZWrite";
const isTransparent = materialProperties.shader === "VRM/UnlitTransparent" || isTransparentZWrite;
const renderQueueOffsetNumber = this._v0ParseRenderQueue(materialProperties);
const isCutoff = materialProperties.shader === "VRM/UnlitCutout";
const alphaMode = isTransparent ? "BLEND" : isCutoff ? "MASK" : "OPAQUE";
const alphaCutoff = isCutoff ? (_b = (_a = materialProperties.floatProperties) == null ? void 0 : _a["_Cutoff"]) != null ? _b : 0.5 : void 0;
const textureTransformExt = this._portTextureTransform(materialProperties);
const baseColorFactor = ((_d = (_c = materialProperties.vectorProperties) == null ? void 0 : _c["_Color"]) != null ? _d : [1, 1, 1, 1]).map(gammaEOTF);
const baseColorTextureIndex = (_e = materialProperties.textureProperties) == null ? void 0 : _e["_MainTex"];
const baseColorTexture = baseColorTextureIndex != null ? {
index: baseColorTextureIndex,
extensions: __spreadValues2({}, textureTransformExt)
} : void 0;
const mtoonExtension = {
specVersion: "1.0",
transparentWithZWrite: isTransparentZWrite,
renderQueueOffsetNumber,
shadeColorFactor: baseColorFactor,
shadeMultiplyTexture: baseColorTexture
};
return __spreadProps(__spreadValues2({}, schemaMaterial), {
pbrMetallicRoughness: {
baseColorFactor,
baseColorTexture
},
alphaMode,
alphaCutoff,
extensions: {
// eslint-disable-next-line @typescript-eslint/naming-convention
VRMC_materials_mtoon: mtoonExtension
}
});
}
/**
* Create a glTF `KHR_texture_transform` extension from v0 texture transform info.
*/
_portTextureTransform(materialProperties) {
var _a, _b, _c, _d, _e;
const textureTransform = (_a = materialProperties.vectorProperties) == null ? void 0 : _a["_MainTex"];
if (textureTransform == null) {
return {};
}
const offset = [(_b = textureTransform == null ? void 0 : textureTransform[0]) != null ? _b : 0, (_c = textureTransform == null ? void 0 : textureTransform[1]) != null ? _c : 0];
const scale = [(_d = textureTransform == null ? void 0 : textureTransform[2]) != null ? _d : 1, (_e = textureTransform == null ? void 0 : textureTransform[3]) != null ? _e : 1];
offset[1] = 1 - scale[1] - offset[1];
return {
// eslint-disable-next-line @typescript-eslint/naming-convention
KHR_texture_transform: { offset, scale }
};
}
/**
* Convert v0 render order into v1 render order.
* This uses a map from v0 render queue to v1 compliant render queue offset which is generated in {@link _populateRenderQueueMap}.
*/
_v0ParseRenderQueue(materialProperties) {
var _a, _b;
const isTransparentZWrite = materialProperties.shader === "VRM/UnlitTransparentZWrite";
const isTransparent = ((_a = materialProperties.keywordMap) == null ? void 0 : _a["_ALPHABLEND_ON"]) != void 0 || materialProperties.shader === "VRM/UnlitTransparent" || isTransparentZWrite;
const enabledZWrite = ((_b = materialProperties.floatProperties) == null ? void 0 : _b["_ZWrite"]) === 1 || isTransparentZWrite;
let offset = 0;
if (isTransparent) {
const v0Queue = materialProperties.renderQueue;
if (v0Queue != null) {
if (enabledZWrite) {
offset = this._renderQueueMapTransparentZWrite.get(v0Queue);
} else {
offset = this._renderQueueMapTransparent.get(v0Queue);
}
}
}
return offset;
}
/**
* Create a map which maps v0 render queue to v1 compliant render queue offset.
* This lists up all render queues the model use and creates a map to new render queue offsets in the same order.
*/
_populateRenderQueueMap(materialPropertiesList) {
const renderQueuesTransparent = /* @__PURE__ */ new Set();
const renderQueuesTransparentZWrite = /* @__PURE__ */ new Set();
materialPropertiesList.forEach((materialProperties) => {
var _a, _b;
const isTransparentZWrite = materialProperties.shader === "VRM/UnlitTransparentZWrite";
const isTransparent = ((_a = materialProperties.keywordMap) == null ? void 0 : _a["_ALPHABLEND_ON"]) != void 0 || materialProperties.shader === "VRM/UnlitTransparent" || isTransparentZWrite;
const enabledZWrite = ((_b = materialProperties.floatProperties) == null ? void 0 : _b["_ZWrite"]) === 1 || isTransparentZWrite;
if (isTransparent) {
const v0Queue = materialProperties.renderQueue;
if (v0Queue != null) {
if (enabledZWrite) {
renderQueuesTransparentZWrite.add(v0Queue);
} else {
renderQueuesTransparent.add(v0Queue);
}
}
}
});
if (renderQueuesTransparent.size > 10) {
console.warn(
`VRMMaterialsV0CompatPlugin: This VRM uses ${renderQueuesTransparent.size} render queues for Transparent materials while VRM 1.0 only supports up to 10 render queues. The model might not be rendered correctly.`
);
}
if (renderQueuesTransparentZWrite.size > 10) {
console.warn(
`VRMMaterialsV0CompatPlugin: This VRM uses ${renderQueuesTransparentZWrite.size} render queues for TransparentZWrite materials while VRM 1.0 only supports up to 10 render queues. The model might not be rendered correctly.`
);
}
Array.from(renderQueuesTransparent).sort().forEach((queue, i) => {
const newQueueOffset = Math.min(Math.max(i - renderQueuesTransparent.size + 1, -9), 0);
this._renderQueueMapTransparent.set(queue, newQueueOffset);
});
Array.from(renderQueuesTransparentZWrite).sort().forEach((queue, i) => {
const newQueueOffset = Math.min(Math.max(i, 0), 9);
this._renderQueueMapTransparentZWrite.set(queue, newQueueOffset);
});
}
};
// ../three-vrm-node-constraint/lib/three-vrm-node-constraint.module.js
var THREE19 = __toESM(require("three"), 1);
var THREE33 = __toESM(require("three"), 1);
var THREE23 = __toESM(require("three"), 1);
var THREE43 = __toESM(require("three"), 1);
var THREE53 = __toESM(require("three"), 1);
var __async6 = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
var _v3A6 = new THREE19.Vector3();
var VRMNodeConstraintHelper = class extends THREE19.Group {
constructor(constraint) {
super();
this._attrPosition = new THREE19.BufferAttribute(new Float32Array([0, 0, 0, 0, 0, 0]), 3);
this._attrPosition.setUsage(THREE19.DynamicDrawUsage);
const geometry = new THREE19.BufferGeometry();
geometry.setAttribute("position", this._attrPosition);
const material = new THREE19.LineBasicMaterial({
color: 16711935,
depthTest: false,
depthWrite: false
});
this._line = new THREE19.Line(geometry, material);
this.add(this._line);
this.constraint = constraint;
}
updateMatrixWorld(force) {
_v3A6.setFromMatrixPosition(this.constraint.destination.matrixWorld);
this._attrPosition.setXYZ(0, _v3A6.x, _v3A6.y, _v3A6.z);
if (this.constraint.source) {
_v3A6.setFromMatrixPosition(this.constraint.source.matrixWorld);
}
this._attrPosition.setXYZ(1, _v3A6.x, _v3A6.y, _v3A6.z);
this._attrPosition.needsUpdate = true;
super.updateMatrixWorld(force);
}
};
function decomposePosition(matrix, target) {
return target.set(matrix.elements[12], matrix.elements[13], matrix.elements[14]);
}
var _v3A22 = new THREE23.Vector3();
var _v3B4 = new THREE23.Vector3();
function decomposeRotation(matrix, target) {
matrix.decompose(_v3A22, target, _v3B4);
return target;
}
function quatInvertCompat2(target) {
if (target.invert) {
target.invert();
} else {
target.inverse();
}
return target;
}
var VRMNodeConstraint = class {
/**
* @param destination The destination object
* @param source The source object
*/
constructor(destination, source) {
this.destination = destination;
this.source = source;
this.weight = 1;
}
};
var _v3A32 = new THREE33.Vector3();
var _v3B22 = new THREE33.Vector3();
var _v3C2 = new THREE33.Vector3();
var _quatA7 = new THREE33.Quaternion();
var _quatB4 = new THREE33.Quaternion();
var _quatC2 = new THREE33.Quaternion();
var VRMAimConstraint = class extends VRMNodeConstraint {
/**
* The aim axis of the constraint.
*/
get aimAxis() {
return this._aimAxis;
}
/**
* The aim axis of the constraint.
*/
set aimAxis(aimAxis) {
this._aimAxis = aimAxis;
this._v3AimAxis.set(
aimAxis === "PositiveX" ? 1 : aimAxis === "NegativeX" ? -1 : 0,
aimAxis === "PositiveY" ? 1 : aimAxis === "NegativeY" ? -1 : 0,
aimAxis === "PositiveZ" ? 1 : aimAxis === "NegativeZ" ? -1 : 0
);
}
get dependencies() {
const set = /* @__PURE__ */ new Set([this.source]);
if (this.destination.parent) {
set.add(this.destination.parent);
}
return set;
}
constructor(destination, source) {
super(destination, source);
this._aimAxis = "PositiveX";
this._v3AimAxis = new THREE33.Vector3(1, 0, 0);
this._dstRestQuat = new THREE33.Quaternion();
}
setInitState() {
this._dstRestQuat.copy(this.destination.quaternion);
}
update() {
this.destination.updateWorldMatrix(true, false);
this.source.updateWorldMatrix(true, false);
const dstParentWorldQuat = _quatA7.identity();
const invDstParentWorldQuat = _quatB4.identity();
if (this.destination.parent) {
decomposeRotation(this.destination.parent.matrixWorld, dstParentWorldQuat);
quatInvertCompat2(invDstParentWorldQuat.copy(dstParentWorldQuat));
}
const a0 = _v3A32.copy(this._v3AimAxis).applyQuaternion(this._dstRestQuat).applyQuaternion(dstParentWorldQuat);
const a1 = decomposePosition(this.source.matrixWorld, _v3B22).sub(decomposePosition(this.destination.matrixWorld, _v3C2)).normalize();
const targetQuat = _quatC2.setFromUnitVectors(a0, a1).premultiply(invDstParentWorldQuat).multiply(dstParentWorldQuat).multiply(this._dstRestQuat);
this.destination.quaternion.copy(this._dstRestQuat).slerp(targetQuat, this.weight);
}
};
function traverseAncestorsFromRoot(object, callback) {
const ancestors = [object];
let head = object.parent;
while (head !== null) {
ancestors.unshift(head);
head = head.parent;
}
ancestors.forEach((ancestor) => {
callback(ancestor);
});
}
var VRMNodeConstraintManager = class {
constructor() {
this._constraints = /* @__PURE__ */ new Set();
this._objectConstraintsMap = /* @__PURE__ */ new Map();
}
get constraints() {
return this._constraints;
}
addConstraint(constraint) {
this._constraints.add(constraint);
let objectSet = this._objectConstraintsMap.get(constraint.destination);
if (objectSet == null) {
objectSet = /* @__PURE__ */ new Set();
this._objectConstraintsMap.set(constraint.destination, objectSet);
}
objectSet.add(constraint);
}
deleteConstraint(constraint) {
this._constraints.delete(constraint);
const objectSet = this._objectConstraintsMap.get(constraint.destination);
objectSet.delete(constraint);
}
setInitState() {
const constraintsTried = /* @__PURE__ */ new Set();
const constraintsDone = /* @__PURE__ */ new Set();
for (const constraint of this._constraints) {
this._processConstraint(constraint, constraintsTried, constraintsDone, (constraint2) => constraint2.setInitState());
}
}
update() {
const constraintsTried = /* @__PURE__ */ new Set();
const constraintsDone = /* @__PURE__ */ new Set();
for (const constraint of this._constraints) {
this._processConstraint(constraint, constraintsTried, constraintsDone, (constraint2) => constraint2.update());
}
}
/**
* Update a constraint.
* If there are other constraints that are dependant, it will try to update them recursively.
* It might throw an error if there are circular dependencies.
*
* Intended to be used in {@link update} and {@link _processConstraint} itself recursively.
*
* @param constraint A constraint you want to update
* @param constraintsTried Set of constraints that are already tried to be updated
* @param constraintsDone Set of constraints that are already up to date
*/
_processConstraint(constraint, constraintsTried, constraintsDone, callback) {
if (constraintsDone.has(constraint)) {
return;
}
if (constraintsTried.has(constraint)) {
throw new Error("VRMNodeConstraintManager: Circular dependency detected while updating constraints");
}
constraintsTried.add(constraint);
const depObjects = constraint.dependencies;
for (const depObject of depObjects) {
traverseAncestorsFromRoot(depObject, (depObjectAncestor) => {
const objectSet = this._objectConstraintsMap.get(depObjectAncestor);
if (objectSet) {
for (const depConstraint of objectSet) {
this._processConstraint(depConstraint, constraintsTried, constraintsDone, callback);
}
}
});
}
callback(constraint);
constraintsDone.add(constraint);
}
};
var _quatA22 = new THREE43.Quaternion();
var _quatB22 = new THREE43.Quaternion();
var VRMRotationConstraint = class extends VRMNodeConstraint {
get dependencies() {
return /* @__PURE__ */ new Set([this.source]);
}
constructor(destination, source) {
super(destination, source);
this._dstRestQuat = new THREE43.Quaternion();
this._invSrcRestQuat = new THREE43.Quaternion();
}
setInitState() {
this._dstRestQuat.copy(this.destination.quaternion);
quatInvertCompat2(this._invSrcRestQuat.copy(this.source.quaternion));
}
update() {
const srcDeltaQuat = _quatA22.copy(this._invSrcRestQuat).multiply(this.source.quaternion);
const targetQuat = _quatB22.copy(this._dstRestQuat).multiply(srcDeltaQuat);
this.destination.quaternion.copy(this._dstRestQuat).slerp(targetQuat, this.weight);
}
};
var _v3A42 = new THREE53.Vector3();
var _quatA32 = new THREE53.Quaternion();
var _quatB32 = new THREE53.Quaternion();
var VRMRollConstraint = class extends VRMNodeConstraint {
/**
* The roll axis of the constraint.
*/
get rollAxis() {
return this._rollAxis;
}
/**
* The roll axis of the constraint.
*/
set rollAxis(rollAxis) {
this._rollAxis = rollAxis;
this._v3RollAxis.set(rollAxis === "X" ? 1 : 0, rollAxis === "Y" ? 1 : 0, rollAxis === "Z" ? 1 : 0);
}
get dependencies() {
return /* @__PURE__ */ new Set([this.source]);
}
constructor(destination, source) {
super(destination, source);
this._rollAxis = "X";
this._v3RollAxis = new THREE53.Vector3(1, 0, 0);
this._dstRestQuat = new THREE53.Quaternion();
this._invDstRestQuat = new THREE53.Quaternion();
this._invSrcRestQuatMulDstRestQuat = new THREE53.Quaternion();
}
setInitState() {
this._dstRestQuat.copy(this.destination.quaternion);
quatInvertCompat2(this._invDstRestQuat.copy(this._dstRestQuat));
quatInvertCompat2(this._invSrcRestQuatMulDstRestQuat.copy(this.source.quaternion)).multiply(this._dstRestQuat);
}
update() {
const quatDelta = _quatA32.copy(this._invDstRestQuat).multiply(this.source.quaternion).multiply(this._invSrcRestQuatMulDstRestQuat);
const n1 = _v3A42.copy(this._v3RollAxis).applyQuaternion(quatDelta);
const quatFromTo = _quatB32.setFromUnitVectors(n1, this._v3RollAxis);
const targetQuat = quatFromTo.premultiply(this._dstRestQuat).multiply(quatDelta);
this.destination.quaternion.copy(this._dstRestQuat).slerp(targetQuat, this.weight);
}
};
var POSSIBLE_SPEC_VERSIONS7 = /* @__PURE__ */ new Set(["1.0", "1.0-beta"]);
var _VRMNodeConstraintLoaderPlugin = class _VRMNodeConstraintLoaderPlugin2 {
get name() {
return _VRMNodeConstraintLoaderPlugin2.EXTENSION_NAME;
}
constructor(parser, options) {
this.parser = parser;
this.helperRoot = options == null ? void 0 : options.helperRoot;
}
afterRoot(gltf) {
return __async6(this, null, function* () {
gltf.userData.vrmNodeConstraintManager = yield this._import(gltf);
});
}
/**
* Import constraints from a GLTF and returns a {@link VRMNodeConstraintManager}.
* It might return `null` instead when it does not need to be created or something go wrong.
*
* @param gltf A parsed result of GLTF taken from GLTFLoader
*/
_import(gltf) {
return __async6(this, null, function* () {
var _a;
const json = this.parser.json;
const isConstraintsUsed = ((_a = json.extensionsUsed) == null ? void 0 : _a.indexOf(_VRMNodeConstraintLoaderPlugin2.EXTENSION_NAME)) !== -1;
if (!isConstraintsUsed) {
return null;
}
const manager = new VRMNodeConstraintManager();
const threeNodes = yield this.parser.getDependencies("node");
threeNodes.forEach((node, nodeIndex) => {
var _a2;
const schemaNode = json.nodes[nodeIndex];
const extension = (_a2 = schemaNode == null ? void 0 : schemaNode.extensions) == null ? void 0 : _a2[_VRMNodeConstraintLoaderPlugin2.EXTENSION_NAME];
if (extension == null) {
return;
}
const specVersion = extension.specVersion;
if (!POSSIBLE_SPEC_VERSIONS7.has(specVersion)) {
console.warn(
`VRMNodeConstraintLoaderPlugin: Unknown ${_VRMNodeConstraintLoaderPlugin2.EXTENSION_NAME} specVersion "${specVersion}"`
);
return;
}
const constraintDef = extension.constraint;
if (constraintDef.roll != null) {
const constraint = this._importRollConstraint(node, threeNodes, constraintDef.roll);
manager.addConstraint(constraint);
} else if (constraintDef.aim != null) {
const constraint = this._importAimConstraint(node, threeNodes, constraintDef.aim);
manager.addConstraint(constraint);
} else if (constraintDef.rotation != null) {
const constraint = this._importRotationConstraint(node, threeNodes, constraintDef.rotation);
manager.addConstraint(constraint);
}
});
gltf.scene.updateMatrixWorld();
manager.setInitState();
return manager;
});
}
_importRollConstraint(destination, nodes, rollConstraintDef) {
const { source: sourceIndex, rollAxis, weight } = rollConstraintDef;
const source = nodes[sourceIndex];
const constraint = new VRMRollConstraint(destination, source);
if (rollAxis != null) {
constraint.rollAxis = rollAxis;
}
if (weight != null) {
constraint.weight = weight;
}
if (this.helperRoot) {
const helper = new VRMNodeConstraintHelper(constraint);
this.helperRoot.add(helper);
}
return constraint;
}
_importAimConstraint(destination, nodes, aimConstraintDef) {
const { source: sourceIndex, aimAxis, weight } = aimConstraintDef;
const source = nodes[sourceIndex];
const constraint = new VRMAimConstraint(destination, source);
if (aimAxis != null) {
constraint.aimAxis = aimAxis;
}
if (weight != null) {
constraint.weight = weight;
}
if (this.helperRoot) {
const helper = new VRMNodeConstraintHelper(constraint);
this.helperRoot.add(helper);
}
return constraint;
}
_importRotationConstraint(destination, nodes, rotationConstraintDef) {
const { source: sourceIndex, weight } = rotationConstraintDef;
const source = nodes[sourceIndex];
const constraint = new VRMRotationConstraint(destination, source);
if (weight != null) {
constraint.weight = weight;
}
if (this.helperRoot) {
const helper = new VRMNodeConstraintHelper(constraint);
this.helperRoot.add(helper);
}
return constraint;
}
};
_VRMNodeConstraintLoaderPlugin.EXTENSION_NAME = "VRMC_node_constraint";
var VRMNodeConstraintLoaderPlugin = _VRMNodeConstraintLoaderPlugin;
// ../three-vrm-springbone/lib/three-vrm-springbone.module.js
var THREE72 = __toESM(require("three"), 1);
var THREE20 = __toESM(require("three"), 1);
var THREE24 = __toESM(require("three"), 1);
var THREE34 = __toESM(require("three"), 1);
var THREE44 = __toESM(require("three"), 1);
var THREE54 = __toESM(require("three"), 1);
var THREE62 = __toESM(require("three"), 1);
var THREE92 = __toESM(require("three"), 1);
var THREE82 = __toESM(require("three"), 1);
var THREE102 = __toESM(require("three"), 1);
var THREE132 = __toESM(require("three"), 1);
var THREE122 = __toESM(require("three"), 1);
var THREE112 = __toESM(require("three"), 1);
var THREE142 = __toESM(require("three"), 1);
var __async7 = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
var VRMSpringBoneColliderShape = class {
};
var _v3A7 = new THREE20.Vector3();
var _v3B5 = new THREE20.Vector3();
var VRMSpringBoneColliderShapeCapsule = class extends VRMSpringBoneColliderShape {
get type() {
return "capsule";
}
constructor(params) {
var _a, _b, _c, _d;
super();
this.offset = (_a = params == null ? void 0 : params.offset) != null ? _a : new THREE20.Vector3(0, 0, 0);
this.tail = (_b = params == null ? void 0 : params.tail) != null ? _b : new THREE20.Vector3(0, 0, 0);
this.radius = (_c = params == null ? void 0 : params.radius) != null ? _c : 0;
this.inside = (_d = params == null ? void 0 : params.inside) != null ? _d : false;
}
calculateCollision(colliderMatrix, objectPosition, objectRadius, target) {
_v3A7.setFromMatrixPosition(colliderMatrix);
_v3B5.subVectors(this.tail, this.offset).applyMatrix4(colliderMatrix);
_v3B5.sub(_v3A7);
const lengthSqCapsule = _v3B5.lengthSq();
target.copy(objectPosition).sub(_v3A7);
const dot = _v3B5.dot(target);
if (dot <= 0) {
} else if (lengthSqCapsule <= dot) {
target.sub(_v3B5);
} else {
_v3B5.multiplyScalar(dot / lengthSqCapsule);
target.sub(_v3B5);
}
const length = target.length();
const distance = this.inside ? this.radius - objectRadius - length : length - objectRadius - this.radius;
if (distance < 0) {
target.multiplyScalar(1 / length);
if (this.inside) {
target.negate();
}
}
return distance;
}
};
var _v3A23 = new THREE24.Vector3();
var _mat3A = new THREE24.Matrix3();
var VRMSpringBoneColliderShapePlane = class extends VRMSpringBoneColliderShape {
get type() {
return "plane";
}
constructor(params) {
var _a, _b;
super();
this.offset = (_a = params == null ? void 0 : params.offset) != null ? _a : new THREE24.Vector3(0, 0, 0);
this.normal = (_b = params == null ? void 0 : params.normal) != null ? _b : new THREE24.Vector3(0, 0, 1);
}
calculateCollision(colliderMatrix, objectPosition, objectRadius, target) {
target.setFromMatrixPosition(colliderMatrix);
target.negate().add(objectPosition);
_mat3A.getNormalMatrix(colliderMatrix);
_v3A23.copy(this.normal).applyNormalMatrix(_mat3A).normalize();
const distance = target.dot(_v3A23) - objectRadius;
target.copy(_v3A23);
return distance;
}
};
var _v3A33 = new THREE34.Vector3();
var VRMSpringBoneColliderShapeSphere = class extends VRMSpringBoneColliderShape {
get type() {
return "sphere";
}
constructor(params) {
var _a, _b, _c;
super();
this.offset = (_a = params == null ? void 0 : params.offset) != null ? _a : new THREE34.Vector3(0, 0, 0);
this.radius = (_b = params == null ? void 0 : params.radius) != null ? _b : 0;
this.inside = (_c = params == null ? void 0 : params.inside) != null ? _c : false;
}
calculateCollision(colliderMatrix, objectPosition, objectRadius, target) {
target.subVectors(objectPosition, _v3A33.setFromMatrixPosition(colliderMatrix));
const length = target.length();
const distance = this.inside ? this.radius - objectRadius - length : length - objectRadius - this.radius;
if (distance < 0) {
target.multiplyScalar(1 / length);
if (this.inside) {
target.negate();
}
}
return distance;
}
};
var _v3A43 = new THREE44.Vector3();
var ColliderShapeCapsuleBufferGeometry = class extends THREE44.BufferGeometry {
constructor(shape) {
super();
this.worldScale = 1;
this._currentRadius = 0;
this._currentOffset = new THREE44.Vector3();
this._currentTail = new THREE44.Vector3();
this._shape = shape;
this._attrPos = new THREE44.BufferAttribute(new Float32Array(396), 3);
this.setAttribute("position", this._attrPos);
this._attrIndex = new THREE44.BufferAttribute(new Uint16Array(264), 1);
this.setIndex(this._attrIndex);
this._buildIndex();
this.update();
}
update() {
let shouldUpdateGeometry = false;
const radius = this._shape.radius / this.worldScale;
if (this._currentRadius !== radius) {
this._currentRadius = radius;
shouldUpdateGeometry = true;
}
if (!this._currentOffset.equals(this._shape.offset)) {
this._currentOffset.copy(this._shape.offset);
shouldUpdateGeometry = true;
}
const tail = _v3A43.copy(this._shape.tail).divideScalar(this.worldScale);
if (this._currentTail.distanceToSquared(tail) > 1e-10) {
this._currentTail.copy(tail);
shouldUpdateGeometry = true;
}
if (shouldUpdateGeometry) {
this._buildPosition();
}
}
_buildPosition() {
_v3A43.copy(this._currentTail).sub(this._currentOffset);
const l = _v3A43.length() / this._currentRadius;
for (let i = 0; i <= 16; i++) {
const t = i / 16 * Math.PI;
this._attrPos.setXYZ(i, -Math.sin(t), -Math.cos(t), 0);
this._attrPos.setXYZ(17 + i, l + Math.sin(t), Math.cos(t), 0);
this._attrPos.setXYZ(34 + i, -Math.sin(t), 0, -Math.cos(t));
this._attrPos.setXYZ(51 + i, l + Math.sin(t), 0, Math.cos(t));
}
for (let i = 0; i < 32; i++) {
const t = i / 16 * Math.PI;
this._attrPos.setXYZ(68 + i, 0, Math.sin(t), Math.cos(t));
this._attrPos.setXYZ(100 + i, l, Math.sin(t), Math.cos(t));
}
const theta = Math.atan2(_v3A43.y, Math.sqrt(_v3A43.x * _v3A43.x + _v3A43.z * _v3A43.z));
const phi = -Math.atan2(_v3A43.z, _v3A43.x);
this.rotateZ(theta);
this.rotateY(phi);
this.scale(this._currentRadius, this._currentRadius, this._currentRadius);
this.translate(this._currentOffset.x, this._currentOffset.y, this._currentOffset.z);
this._attrPos.needsUpdate = true;
}
_buildIndex() {
for (let i = 0; i < 34; i++) {
const i1 = (i + 1) % 34;
this._attrIndex.setXY(i * 2, i, i1);
this._attrIndex.setXY(68 + i * 2, 34 + i, 34 + i1);
}
for (let i = 0; i < 32; i++) {
const i1 = (i + 1) % 32;
this._attrIndex.setXY(136 + i * 2, 68 + i, 68 + i1);
this._attrIndex.setXY(200 + i * 2, 100 + i, 100 + i1);
}
this._attrIndex.needsUpdate = true;
}
};
var ColliderShapePlaneBufferGeometry = class extends THREE54.BufferGeometry {
constructor(shape) {
super();
this.worldScale = 1;
this._currentOffset = new THREE54.Vector3();
this._currentNormal = new THREE54.Vector3();
this._shape = shape;
this._attrPos = new THREE54.BufferAttribute(new Float32Array(6 * 3), 3);
this.setAttribute("position", this._attrPos);
this._attrIndex = new THREE54.BufferAttribute(new Uint16Array(10), 1);
this.setIndex(this._attrIndex);
this._buildIndex();
this.update();
}
update() {
let shouldUpdateGeometry = false;
if (!this._currentOffset.equals(this._shape.offset)) {
this._currentOffset.copy(this._shape.offset);
shouldUpdateGeometry = true;
}
if (!this._currentNormal.equals(this._shape.normal)) {
this._currentNormal.copy(this._shape.normal);
shouldUpdateGeometry = true;
}
if (shouldUpdateGeometry) {
this._buildPosition();
}
}
_buildPosition() {
this._attrPos.setXYZ(0, -0.5, -0.5, 0);
this._attrPos.setXYZ(1, 0.5, -0.5, 0);
this._attrPos.setXYZ(2, 0.5, 0.5, 0);
this._attrPos.setXYZ(3, -0.5, 0.5, 0);
this._attrPos.setXYZ(4, 0, 0, 0);
this._attrPos.setXYZ(5, 0, 0, 0.25);
this.translate(this._currentOffset.x, this._currentOffset.y, this._currentOffset.z);
this.lookAt(this._currentNormal);
this._attrPos.needsUpdate = true;
}
_buildIndex() {
this._attrIndex.setXY(0, 0, 1);
this._attrIndex.setXY(2, 1, 2);
this._attrIndex.setXY(4, 2, 3);
this._attrIndex.setXY(6, 3, 0);
this._attrIndex.setXY(8, 4, 5);
this._attrIndex.needsUpdate = true;
}
};
var ColliderShapeSphereBufferGeometry = class extends THREE62.BufferGeometry {
constructor(shape) {
super();
this.worldScale = 1;
this._currentRadius = 0;
this._currentOffset = new THREE62.Vector3();
this._shape = shape;
this._attrPos = new THREE62.BufferAttribute(new Float32Array(32 * 3 * 3), 3);
this.setAttribute("position", this._attrPos);
this._attrIndex = new THREE62.BufferAttribute(new Uint16Array(64 * 3), 1);
this.setIndex(this._attrIndex);
this._buildIndex();
this.update();
}
update() {
let shouldUpdateGeometry = false;
const radius = this._shape.radius / this.worldScale;
if (this._currentRadius !== radius) {
this._currentRadius = radius;
shouldUpdateGeometry = true;
}
if (!this._currentOffset.equals(this._shape.offset)) {
this._currentOffset.copy(this._shape.offset);
shouldUpdateGeometry = true;
}
if (shouldUpdateGeometry) {
this._buildPosition();
}
}
_buildPosition() {
for (let i = 0; i < 32; i++) {
const t = i / 16 * Math.PI;
this._attrPos.setXYZ(i, Math.cos(t), Math.sin(t), 0);
this._attrPos.setXYZ(32 + i, 0, Math.cos(t), Math.sin(t));
this._attrPos.setXYZ(64 + i, Math.sin(t), 0, Math.cos(t));
}
this.scale(this._currentRadius, this._currentRadius, this._currentRadius);
this.translate(this._currentOffset.x, this._currentOffset.y, this._currentOffset.z);
this._attrPos.needsUpdate = true;
}
_buildIndex() {
for (let i = 0; i < 32; i++) {
const i1 = (i + 1) % 32;
this._attrIndex.setXY(i * 2, i, i1);
this._attrIndex.setXY(64 + i * 2, 32 + i, 32 + i1);
this._attrIndex.setXY(128 + i * 2, 64 + i, 64 + i1);
}
this._attrIndex.needsUpdate = true;
}
};
var _v3A52 = new THREE72.Vector3();
var VRMSpringBoneColliderHelper = class extends THREE72.Group {
constructor(collider) {
super();
this.matrixAutoUpdate = false;
this.collider = collider;
if (this.collider.shape instanceof VRMSpringBoneColliderShapeSphere) {
this._geometry = new ColliderShapeSphereBufferGeometry(this.collider.shape);
} else if (this.collider.shape instanceof VRMSpringBoneColliderShapeCapsule) {
this._geometry = new ColliderShapeCapsuleBufferGeometry(this.collider.shape);
} else if (this.collider.shape instanceof VRMSpringBoneColliderShapePlane) {
this._geometry = new ColliderShapePlaneBufferGeometry(this.collider.shape);
} else {
throw new Error("VRMSpringBoneColliderHelper: Unknown collider shape type detected");
}
const material = new THREE72.LineBasicMaterial({
color: 16711935,
depthTest: false,
depthWrite: false
});
this._line = new THREE72.LineSegments(this._geometry, material);
this.add(this._line);
}
dispose() {
this._geometry.dispose();
}
updateMatrixWorld(force) {
this.collider.updateWorldMatrix(true, false);
this.matrix.copy(this.collider.matrixWorld);
const matrixWorldElements = this.matrix.elements;
this._geometry.worldScale = _v3A52.set(matrixWorldElements[0], matrixWorldElements[1], matrixWorldElements[2]).length();
this._geometry.update();
super.updateMatrixWorld(force);
}
};
var SpringBoneBufferGeometry = class extends THREE82.BufferGeometry {
constructor(springBone) {
super();
this.worldScale = 1;
this._currentRadius = 0;
this._currentTail = new THREE82.Vector3();
this._springBone = springBone;
this._attrPos = new THREE82.BufferAttribute(new Float32Array(294), 3);
this.setAttribute("position", this._attrPos);
this._attrIndex = new THREE82.BufferAttribute(new Uint16Array(194), 1);
this.setIndex(this._attrIndex);
this._buildIndex();
this.update();
}
update() {
let shouldUpdateGeometry = false;
const radius = this._springBone.settings.hitRadius / this.worldScale;
if (this._currentRadius !== radius) {
this._currentRadius = radius;
shouldUpdateGeometry = true;
}
if (!this._currentTail.equals(this._springBone.initialLocalChildPosition)) {
this._currentTail.copy(this._springBone.initialLocalChildPosition);
shouldUpdateGeometry = true;
}
if (shouldUpdateGeometry) {
this._buildPosition();
}
}
_buildPosition() {
for (let i = 0; i < 32; i++) {
const t = i / 16 * Math.PI;
this._attrPos.setXYZ(i, Math.cos(t), Math.sin(t), 0);
this._attrPos.setXYZ(32 + i, 0, Math.cos(t), Math.sin(t));
this._attrPos.setXYZ(64 + i, Math.sin(t), 0, Math.cos(t));
}
this.scale(this._currentRadius, this._currentRadius, this._currentRadius);
this.translate(this._currentTail.x, this._currentTail.y, this._currentTail.z);
this._attrPos.setXYZ(96, 0, 0, 0);
this._attrPos.setXYZ(97, this._currentTail.x, this._currentTail.y, this._currentTail.z);
this._attrPos.needsUpdate = true;
}
_buildIndex() {
for (let i = 0; i < 32; i++) {
const i1 = (i + 1) % 32;
this._attrIndex.setXY(i * 2, i, i1);
this._attrIndex.setXY(64 + i * 2, 32 + i, 32 + i1);
this._attrIndex.setXY(128 + i * 2, 64 + i, 64 + i1);
}
this._attrIndex.setXY(192, 96, 97);
this._attrIndex.needsUpdate = true;
}
};
var _v3A62 = new THREE92.Vector3();
var VRMSpringBoneJointHelper = class extends THREE92.Group {
constructor(springBone) {
super();
this.matrixAutoUpdate = false;
this.springBone = springBone;
this._geometry = new SpringBoneBufferGeometry(this.springBone);
const material = new THREE92.LineBasicMaterial({
color: 16776960,
depthTest: false,
depthWrite: false
});
this._line = new THREE92.LineSegments(this._geometry, material);
this.add(this._line);
}
dispose() {
this._geometry.dispose();
}
updateMatrixWorld(force) {
this.springBone.bone.updateWorldMatrix(true, false);
this.matrix.copy(this.springBone.bone.matrixWorld);
const matrixWorldElements = this.matrix.elements;
this._geometry.worldScale = _v3A62.set(matrixWorldElements[0], matrixWorldElements[1], matrixWorldElements[2]).length();
this._geometry.update();
super.updateMatrixWorld(force);
}
};
var VRMSpringBoneCollider = class extends THREE102.Object3D {
constructor(shape) {
super();
this.colliderMatrix = new THREE102.Matrix4();
this.shape = shape;
}
updateWorldMatrix(updateParents, updateChildren) {
super.updateWorldMatrix(updateParents, updateChildren);
updateColliderMatrix(this.colliderMatrix, this.matrixWorld, this.shape.offset);
}
};
function updateColliderMatrix(colliderMatrix, matrixWorld, offset) {
const me = matrixWorld.elements;
colliderMatrix.copy(matrixWorld);
if (offset) {
colliderMatrix.elements[12] = me[0] * offset.x + me[4] * offset.y + me[8] * offset.z + me[12];
colliderMatrix.elements[13] = me[1] * offset.x + me[5] * offset.y + me[9] * offset.z + me[13];
colliderMatrix.elements[14] = me[2] * offset.x + me[6] * offset.y + me[10] * offset.z + me[14];
}
}
var _matA = new THREE112.Matrix4();
function mat4InvertCompat(target) {
if (target.invert) {
target.invert();
} else {
target.getInverse(_matA.copy(target));
}
return target;
}
var Matrix4InverseCache = class {
constructor(matrix) {
this._inverseCache = new THREE122.Matrix4();
this._shouldUpdateInverse = true;
this.matrix = matrix;
const handler = {
set: (obj, prop, newVal) => {
this._shouldUpdateInverse = true;
obj[prop] = newVal;
return true;
}
};
this._originalElements = matrix.elements;
matrix.elements = new Proxy(matrix.elements, handler);
}
/**
* Inverse of given matrix.
* Note that it will return its internal private instance.
* Make sure copying this before mutate this.
*/
get inverse() {
if (this._shouldUpdateInverse) {
mat4InvertCompat(this._inverseCache.copy(this.matrix));
this._shouldUpdateInverse = false;
}
return this._inverseCache;
}
revert() {
this.matrix.elements = this._originalElements;
}
};
var IDENTITY_MATRIX4 = new THREE132.Matrix4();
var _v3A72 = new THREE132.Vector3();
var _v3B23 = new THREE132.Vector3();
var _worldSpacePosition = new THREE132.Vector3();
var _nextTail = new THREE132.Vector3();
var _matA2 = new THREE132.Matrix4();
var VRMSpringBoneJoint = class {
/**
* Create a new VRMSpringBone.
*
* @param bone An Object3D that will be attached to this bone
* @param child An Object3D that will be used as a tail of this spring bone. It can be null when the spring bone is imported from VRM 0.0
* @param settings Several parameters related to behavior of the spring bone
* @param colliderGroups Collider groups that will be collided with this spring bone
*/
constructor(bone, child, settings = {}, colliderGroups = []) {
this._currentTail = new THREE132.Vector3();
this._prevTail = new THREE132.Vector3();
this._boneAxis = new THREE132.Vector3();
this._worldSpaceBoneLength = 0;
this._center = null;
this._initialLocalMatrix = new THREE132.Matrix4();
this._initialLocalRotation = new THREE132.Quaternion();
this._initialLocalChildPosition = new THREE132.Vector3();
var _a, _b, _c, _d, _e, _f;
this.bone = bone;
this.bone.matrixAutoUpdate = false;
this.child = child;
this.settings = {
hitRadius: (_a = settings.hitRadius) != null ? _a : 0,
stiffness: (_b = settings.stiffness) != null ? _b : 1,
gravityPower: (_c = settings.gravityPower) != null ? _c : 0,
gravityDir: (_e = (_d = settings.gravityDir) == null ? void 0 : _d.clone()) != null ? _e : new THREE132.Vector3(0, -1, 0),
dragForce: (_f = settings.dragForce) != null ? _f : 0.4
};
this.colliderGroups = colliderGroups;
}
/**
* Set of dependencies that need to be updated before this joint.
*/
get dependencies() {
const set = /* @__PURE__ */ new Set();
const parent = this.bone.parent;
if (parent) {
set.add(parent);
}
for (let cg = 0; cg < this.colliderGroups.length; cg++) {
for (let c = 0; c < this.colliderGroups[cg].colliders.length; c++) {
set.add(this.colliderGroups[cg].colliders[c]);
}
}
return set;
}
get center() {
return this._center;
}
set center(center) {
var _a;
if ((_a = this._center) == null ? void 0 : _a.userData.inverseCacheProxy) {
this._center.userData.inverseCacheProxy.revert();
delete this._center.userData.inverseCacheProxy;
}
this._center = center;
if (this._center) {
if (!this._center.userData.inverseCacheProxy) {
this._center.userData.inverseCacheProxy = new Matrix4InverseCache(this._center.matrixWorld);
}
}
}
get initialLocalChildPosition() {
return this._initialLocalChildPosition;
}
/**
* Returns the world matrix of its parent object.
* Note that it returns a reference to the matrix. Don't mutate this directly!
*/
get _parentMatrixWorld() {
return this.bone.parent ? this.bone.parent.matrixWorld : IDENTITY_MATRIX4;
}
/**
* Set the initial state of this spring bone.
* You might want to call {@link VRMSpringBoneManager.setInitState} instead.
*/
setInitState() {
this._initialLocalMatrix.copy(this.bone.matrix);
this._initialLocalRotation.copy(this.bone.quaternion);
if (this.child) {
this._initialLocalChildPosition.copy(this.child.position);
} else {
this._initialLocalChildPosition.copy(this.bone.position).normalize().multiplyScalar(0.07);
}
const matrixWorldToCenter = this._getMatrixWorldToCenter();
this.bone.localToWorld(this._currentTail.copy(this._initialLocalChildPosition)).applyMatrix4(matrixWorldToCenter);
this._prevTail.copy(this._currentTail);
this._boneAxis.copy(this._initialLocalChildPosition).normalize();
}
/**
* Reset the state of this bone.
* You might want to call {@link VRMSpringBoneManager.reset} instead.
*/
reset() {
this.bone.quaternion.copy(this._initialLocalRotation);
this.bone.updateMatrix();
this.bone.matrixWorld.multiplyMatrices(this._parentMatrixWorld, this.bone.matrix);
const matrixWorldToCenter = this._getMatrixWorldToCenter();
this.bone.localToWorld(this._currentTail.copy(this._initialLocalChildPosition)).applyMatrix4(matrixWorldToCenter);
this._prevTail.copy(this._currentTail);
}
/**
* Update the state of this bone.
* You might want to call {@link VRMSpringBoneManager.update} instead.
*
* @param delta deltaTime
*/
update(delta) {
if (delta <= 0) return;
this._calcWorldSpaceBoneLength();
const worldSpaceBoneAxis = _v3B23.copy(this._boneAxis).transformDirection(this._initialLocalMatrix).transformDirection(this._parentMatrixWorld);
_nextTail.copy(this._currentTail).add(_v3A72.subVectors(this._currentTail, this._prevTail).multiplyScalar(1 - this.settings.dragForce)).applyMatrix4(this._getMatrixCenterToWorld()).addScaledVector(worldSpaceBoneAxis, this.settings.stiffness * delta).addScaledVector(this.settings.gravityDir, this.settings.gravityPower * delta);
_worldSpacePosition.setFromMatrixPosition(this.bone.matrixWorld);
_nextTail.sub(_worldSpacePosition).normalize().multiplyScalar(this._worldSpaceBoneLength).add(_worldSpacePosition);
this._collision(_nextTail);
this._prevTail.copy(this._currentTail);
this._currentTail.copy(_nextTail).applyMatrix4(this._getMatrixWorldToCenter());
const worldSpaceInitialMatrixInv = _matA2.multiplyMatrices(this._parentMatrixWorld, this._initialLocalMatrix).invert();
this.bone.quaternion.setFromUnitVectors(this._boneAxis, _v3A72.copy(_nextTail).applyMatrix4(worldSpaceInitialMatrixInv).normalize()).premultiply(this._initialLocalRotation);
this.bone.updateMatrix();
this.bone.matrixWorld.multiplyMatrices(this._parentMatrixWorld, this.bone.matrix);
}
/**
* Do collision math against every colliders attached to this bone.
*
* @param tail The tail you want to process
*/
_collision(tail) {
for (let cg = 0; cg < this.colliderGroups.length; cg++) {
for (let c = 0; c < this.colliderGroups[cg].colliders.length; c++) {
const collider = this.colliderGroups[cg].colliders[c];
const dist = collider.shape.calculateCollision(collider.colliderMatrix, tail, this.settings.hitRadius, _v3A72);
if (dist < 0) {
tail.addScaledVector(_v3A72, -dist);
tail.sub(_worldSpacePosition);
const length = tail.length();
tail.multiplyScalar(this._worldSpaceBoneLength / length).add(_worldSpacePosition);
}
}
}
}
/**
* Calculate the {@link _worldSpaceBoneLength}.
* Intended to be used in {@link update}.
*/
_calcWorldSpaceBoneLength() {
_v3A72.setFromMatrixPosition(this.bone.matrixWorld);
if (this.child) {
_v3B23.setFromMatrixPosition(this.child.matrixWorld);
} else {
_v3B23.copy(this._initialLocalChildPosition);
_v3B23.applyMatrix4(this.bone.matrixWorld);
}
this._worldSpaceBoneLength = _v3A72.sub(_v3B23).length();
}
/**
* Create a matrix that converts center space into world space.
*/
_getMatrixCenterToWorld() {
return this._center ? this._center.matrixWorld : IDENTITY_MATRIX4;
}
/**
* Create a matrix that converts world space into center space.
*/
_getMatrixWorldToCenter() {
return this._center ? this._center.userData.inverseCacheProxy.inverse : IDENTITY_MATRIX4;
}
};
function traverseAncestorsFromRoot2(object, callback) {
const ancestors = [];
let head = object;
while (head !== null) {
ancestors.unshift(head);
head = head.parent;
}
ancestors.forEach((ancestor) => {
callback(ancestor);
});
}
function traverseChildrenUntilConditionMet(object, callback) {
object.children.forEach((child) => {
const result = callback(child);
if (!result) {
traverseChildrenUntilConditionMet(child, callback);
}
});
}
function lowestCommonAncestor(objects) {
var _a;
const sharedAncestors = /* @__PURE__ */ new Map();
for (const object of objects) {
let current = object;
do {
const newValue = ((_a = sharedAncestors.get(current)) != null ? _a : 0) + 1;
if (newValue === objects.size) {
return current;
}
sharedAncestors.set(current, newValue);
current = current.parent;
} while (current !== null);
}
return null;
}
var VRMSpringBoneManager = class {
constructor() {
this._joints = /* @__PURE__ */ new Set();
this._sortedJoints = [];
this._hasWarnedCircularDependency = false;
this._ancestors = [];
this._objectSpringBonesMap = /* @__PURE__ */ new Map();
this._isSortedJointsDirty = false;
this._relevantChildrenUpdated = this._relevantChildrenUpdated.bind(this);
}
get joints() {
return this._joints;
}
/**
* @deprecated Use {@link joints} instead.
*/
get springBones() {
console.warn("VRMSpringBoneManager: springBones is deprecated. use joints instead.");
return this._joints;
}
get colliderGroups() {
const set = /* @__PURE__ */ new Set();
this._joints.forEach((springBone) => {
springBone.colliderGroups.forEach((colliderGroup) => {
set.add(colliderGroup);
});
});
return Array.from(set);
}
get colliders() {
const set = /* @__PURE__ */ new Set();
this.colliderGroups.forEach((colliderGroup) => {
colliderGroup.colliders.forEach((collider) => {
set.add(collider);
});
});
return Array.from(set);
}
addJoint(joint) {
this._joints.add(joint);
let objectSet = this._objectSpringBonesMap.get(joint.bone);
if (objectSet == null) {
objectSet = /* @__PURE__ */ new Set();
this._objectSpringBonesMap.set(joint.bone, objectSet);
}
objectSet.add(joint);
this._isSortedJointsDirty = true;
}
/**
* @deprecated Use {@link addJoint} instead.
*/
addSpringBone(joint) {
console.warn("VRMSpringBoneManager: addSpringBone() is deprecated. use addJoint() instead.");
this.addJoint(joint);
}
deleteJoint(joint) {
this._joints.delete(joint);
const objectSet = this._objectSpringBonesMap.get(joint.bone);
objectSet.delete(joint);
this._isSortedJointsDirty = true;
}
/**
* @deprecated Use {@link deleteJoint} instead.
*/
deleteSpringBone(joint) {
console.warn("VRMSpringBoneManager: deleteSpringBone() is deprecated. use deleteJoint() instead.");
this.deleteJoint(joint);
}
setInitState() {
this._sortJoints();
for (let i = 0; i < this._sortedJoints.length; i++) {
const springBone = this._sortedJoints[i];
springBone.bone.updateMatrix();
springBone.bone.updateWorldMatrix(false, false);
springBone.setInitState();
}
}
reset() {
this._sortJoints();
for (let i = 0; i < this._sortedJoints.length; i++) {
const springBone = this._sortedJoints[i];
springBone.bone.updateMatrix();
springBone.bone.updateWorldMatrix(false, false);
springBone.reset();
}
}
update(delta) {
this._sortJoints();
for (let i = 0; i < this._ancestors.length; i++) {
this._ancestors[i].updateWorldMatrix(i === 0, false);
}
for (let i = 0; i < this._sortedJoints.length; i++) {
const springBone = this._sortedJoints[i];
springBone.bone.updateMatrix();
springBone.bone.updateWorldMatrix(false, false);
springBone.update(delta);
traverseChildrenUntilConditionMet(springBone.bone, this._relevantChildrenUpdated);
}
}
/**
* Sorts the joints ensuring they are updated in the correct order taking dependencies into account.
*
* This method updates {@link _sortedJoints} and {@link _ancestors}.
* Make sure to call this before using them.
*/
_sortJoints() {
if (!this._isSortedJointsDirty) {
return;
}
const springBoneOrder = [];
const springBonesTried = /* @__PURE__ */ new Set();
const springBonesDone = /* @__PURE__ */ new Set();
const ancestors = /* @__PURE__ */ new Set();
for (const springBone of this._joints) {
this._insertJointSort(springBone, springBonesTried, springBonesDone, springBoneOrder, ancestors);
}
this._sortedJoints = springBoneOrder;
const lca = lowestCommonAncestor(ancestors);
this._ancestors = [];
if (lca) {
this._ancestors.push(lca);
traverseChildrenUntilConditionMet(lca, (object) => {
var _a, _b;
if (((_b = (_a = this._objectSpringBonesMap.get(object)) == null ? void 0 : _a.size) != null ? _b : 0) > 0) {
return true;
}
this._ancestors.push(object);
return false;
});
}
this._isSortedJointsDirty = false;
}
_insertJointSort(springBone, springBonesTried, springBonesDone, springBoneOrder, ancestors) {
if (springBonesDone.has(springBone)) {
return;
}
if (springBonesTried.has(springBone)) {
if (!this._hasWarnedCircularDependency) {
console.warn("VRMSpringBoneManager: Circular dependency detected");
this._hasWarnedCircularDependency = true;
}
return;
}
springBonesTried.add(springBone);
const depObjects = springBone.dependencies;
for (const depObject of depObjects) {
let encounteredSpringBone = false;
let ancestor = null;
traverseAncestorsFromRoot2(depObject, (depObjectAncestor) => {
const objectSet = this._objectSpringBonesMap.get(depObjectAncestor);
if (objectSet) {
for (const depSpringBone of objectSet) {
encounteredSpringBone = true;
this._insertJointSort(depSpringBone, springBonesTried, springBonesDone, springBoneOrder, ancestors);
}
} else if (!encounteredSpringBone) {
ancestor = depObjectAncestor;
}
});
if (ancestor) {
ancestors.add(ancestor);
}
}
springBoneOrder.push(springBone);
springBonesDone.add(springBone);
}
_relevantChildrenUpdated(object) {
var _a, _b;
if (((_b = (_a = this._objectSpringBonesMap.get(object)) == null ? void 0 : _a.size) != null ? _b : 0) > 0) {
return true;
}
object.updateWorldMatrix(false, false);
return false;
}
};
var EXTENSION_NAME_EXTENDED_COLLIDER = "VRMC_springBone_extended_collider";
var POSSIBLE_SPEC_VERSIONS8 = /* @__PURE__ */ new Set(["1.0", "1.0-beta"]);
var POSSIBLE_SPEC_VERSIONS_EXTENDED_COLLIDERS = /* @__PURE__ */ new Set(["1.0"]);
var _VRMSpringBoneLoaderPlugin = class _VRMSpringBoneLoaderPlugin2 {
get name() {
return _VRMSpringBoneLoaderPlugin2.EXTENSION_NAME;
}
constructor(parser, options) {
var _a;
this.parser = parser;
this.jointHelperRoot = options == null ? void 0 : options.jointHelperRoot;
this.colliderHelperRoot = options == null ? void 0 : options.colliderHelperRoot;
this.useExtendedColliders = (_a = options == null ? void 0 : options.useExtendedColliders) != null ? _a : true;
}
afterRoot(gltf) {
return __async7(this, null, function* () {
gltf.userData.vrmSpringBoneManager = yield this._import(gltf);
});
}
/**
* Import spring bones from a GLTF and return a {@link VRMSpringBoneManager}.
* It might return `null` instead when it does not need to be created or something go wrong.
*
* @param gltf A parsed result of GLTF taken from GLTFLoader
*/
_import(gltf) {
return __async7(this, null, function* () {
const v1Result = yield this._v1Import(gltf);
if (v1Result != null) {
return v1Result;
}
const v0Result = yield this._v0Import(gltf);
if (v0Result != null) {
return v0Result;
}
return null;
});
}
_v1Import(gltf) {
return __async7(this, null, function* () {
var _a, _b, _c, _d, _e;
const json = gltf.parser.json;
const isSpringBoneUsed = ((_a = json.extensionsUsed) == null ? void 0 : _a.indexOf(_VRMSpringBoneLoaderPlugin2.EXTENSION_NAME)) !== -1;
if (!isSpringBoneUsed) {
return null;
}
const manager = new VRMSpringBoneManager();
const threeNodes = yield gltf.parser.getDependencies("node");
const extension = (_b = json.extensions) == null ? void 0 : _b[_VRMSpringBoneLoaderPlugin2.EXTENSION_NAME];
if (!extension) {
return null;
}
const specVersion = extension.specVersion;
if (!POSSIBLE_SPEC_VERSIONS8.has(specVersion)) {
console.warn(
`VRMSpringBoneLoaderPlugin: Unknown ${_VRMSpringBoneLoaderPlugin2.EXTENSION_NAME} specVersion "${specVersion}"`
);
return null;
}
const colliders = (_c = extension.colliders) == null ? void 0 : _c.map((schemaCollider, iCollider) => {
var _a2, _b2, _c2, _d2, _e2, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
const node = threeNodes[schemaCollider.node];
if (node == null) {
console.warn(
`VRMSpringBoneLoaderPlugin: The collider #${iCollider} attempted to use the node #${schemaCollider.node} but not found`
);
return null;
}
const schemaShape = schemaCollider.shape;
const schemaExCollider = (_a2 = schemaCollider.extensions) == null ? void 0 : _a2[EXTENSION_NAME_EXTENDED_COLLIDER];
if (this.useExtendedColliders && schemaExCollider != null) {
const specVersionExCollider = schemaExCollider.specVersion;
if (!POSSIBLE_SPEC_VERSIONS_EXTENDED_COLLIDERS.has(specVersionExCollider)) {
console.warn(
`VRMSpringBoneLoaderPlugin: Unknown ${EXTENSION_NAME_EXTENDED_COLLIDER} specVersion "${specVersionExCollider}". Fallbacking to the ${_VRMSpringBoneLoaderPlugin2.EXTENSION_NAME} definition`
);
} else {
const schemaExShape = schemaExCollider.shape;
if (schemaExShape.sphere) {
return this._importSphereCollider(node, {
offset: new THREE142.Vector3().fromArray((_b2 = schemaExShape.sphere.offset) != null ? _b2 : [0, 0, 0]),
radius: (_c2 = schemaExShape.sphere.radius) != null ? _c2 : 0,
inside: (_d2 = schemaExShape.sphere.inside) != null ? _d2 : false
});
} else if (schemaExShape.capsule) {
return this._importCapsuleCollider(node, {
offset: new THREE142.Vector3().fromArray((_e2 = schemaExShape.capsule.offset) != null ? _e2 : [0, 0, 0]),
radius: (_f = schemaExShape.capsule.radius) != null ? _f : 0,
tail: new THREE142.Vector3().fromArray((_g = schemaExShape.capsule.tail) != null ? _g : [0, 0, 0]),
inside: (_h = schemaExShape.capsule.inside) != null ? _h : false
});
} else if (schemaExShape.plane) {
return this._importPlaneCollider(node, {
offset: new THREE142.Vector3().fromArray((_i = schemaExShape.plane.offset) != null ? _i : [0, 0, 0]),
normal: new THREE142.Vector3().fromArray((_j = schemaExShape.plane.normal) != null ? _j : [0, 0, 1])
});
}
}
}
if (schemaShape.sphere) {
return this._importSphereCollider(node, {
offset: new THREE142.Vector3().fromArray((_k = schemaShape.sphere.offset) != null ? _k : [0, 0, 0]),
radius: (_l = schemaShape.sphere.radius) != null ? _l : 0,
inside: false
});
} else if (schemaShape.capsule) {
return this._importCapsuleCollider(node, {
offset: new THREE142.Vector3().fromArray((_m = schemaShape.capsule.offset) != null ? _m : [0, 0, 0]),
radius: (_n = schemaShape.capsule.radius) != null ? _n : 0,
tail: new THREE142.Vector3().fromArray((_o = schemaShape.capsule.tail) != null ? _o : [0, 0, 0]),
inside: false
});
}
throw new Error(`VRMSpringBoneLoaderPlugin: The collider #${iCollider} has no valid shape`);
});
const colliderGroups = (_d = extension.colliderGroups) == null ? void 0 : _d.map(
(schemaColliderGroup, iColliderGroup) => {
var _a2;
const cols = ((_a2 = schemaColliderGroup.colliders) != null ? _a2 : []).flatMap((iCollider) => {
const col = colliders == null ? void 0 : colliders[iCollider];
if (col == null) {
console.warn(
`VRMSpringBoneLoaderPlugin: The colliderGroup #${iColliderGroup} attempted to use a collider #${iCollider} but not found`
);
return [];
}
return col;
});
return {
colliders: cols,
name: schemaColliderGroup.name
};
}
);
(_e = extension.springs) == null ? void 0 : _e.forEach((schemaSpring, iSpring) => {
var _a2;
const schemaJoints = schemaSpring.joints;
const colliderGroupsForSpring = (_a2 = schemaSpring.colliderGroups) == null ? void 0 : _a2.map((iColliderGroup) => {
const group = colliderGroups == null ? void 0 : colliderGroups[iColliderGroup];
if (group == null) {
throw new Error(
`VRMSpringBoneLoaderPlugin: The spring #${iSpring} attempted to use a colliderGroup ${iColliderGroup} but not found`
);
}
return group;
});
const center = schemaSpring.center != null ? threeNodes[schemaSpring.center] : void 0;
let prevSchemaJoint;
schemaJoints.forEach((schemaJoint) => {
if (prevSchemaJoint) {
const nodeIndex = prevSchemaJoint.node;
const node = threeNodes[nodeIndex];
const childIndex = schemaJoint.node;
const child = threeNodes[childIndex];
const setting = {
hitRadius: prevSchemaJoint.hitRadius,
dragForce: prevSchemaJoint.dragForce,
gravityPower: prevSchemaJoint.gravityPower,
stiffness: prevSchemaJoint.stiffness,
gravityDir: prevSchemaJoint.gravityDir != null ? new THREE142.Vector3().fromArray(prevSchemaJoint.gravityDir) : void 0
};
const joint = this._importJoint(node, child, setting, colliderGroupsForSpring);
if (center) {
joint.center = center;
}
manager.addJoint(joint);
}
prevSchemaJoint = schemaJoint;
});
});
manager.setInitState();
return manager;
});
}
_v0Import(gltf) {
return __async7(this, null, function* () {
var _a, _b, _c;
const json = gltf.parser.json;
const isVRMUsed = ((_a = json.extensionsUsed) == null ? void 0 : _a.indexOf("VRM")) !== -1;
if (!isVRMUsed) {
return null;
}
const extension = (_b = json.extensions) == null ? void 0 : _b["VRM"];
const schemaSecondaryAnimation = extension == null ? void 0 : extension.secondaryAnimation;
if (!schemaSecondaryAnimation) {
return null;
}
const schemaBoneGroups = schemaSecondaryAnimation == null ? void 0 : schemaSecondaryAnimation.boneGroups;
if (!schemaBoneGroups) {
return null;
}
const manager = new VRMSpringBoneManager();
const threeNodes = yield gltf.parser.getDependencies("node");
const colliderGroups = (_c = schemaSecondaryAnimation.colliderGroups) == null ? void 0 : _c.map(
(schemaColliderGroup) => {
var _a2;
const node = threeNodes[schemaColliderGroup.node];
const colliders = ((_a2 = schemaColliderGroup.colliders) != null ? _a2 : []).map((schemaCollider, iCollider) => {
var _a3, _b2, _c2;
const offset = new THREE142.Vector3(0, 0, 0);
if (schemaCollider.offset) {
offset.set(
(_a3 = schemaCollider.offset.x) != null ? _a3 : 0,
(_b2 = schemaCollider.offset.y) != null ? _b2 : 0,
schemaCollider.offset.z ? -schemaCollider.offset.z : 0
// z is opposite in VRM0.0
);
}
return this._importSphereCollider(node, {
offset,
radius: (_c2 = schemaCollider.radius) != null ? _c2 : 0,
inside: false
});
});
return { colliders };
}
);
schemaBoneGroups == null ? void 0 : schemaBoneGroups.forEach((schemaBoneGroup, iBoneGroup) => {
const rootIndices = schemaBoneGroup.bones;
if (!rootIndices) {
return;
}
rootIndices.forEach((rootIndex) => {
var _a2, _b2, _c2, _d;
const root = threeNodes[rootIndex];
const gravityDir = new THREE142.Vector3();
if (schemaBoneGroup.gravityDir) {
gravityDir.set(
(_a2 = schemaBoneGroup.gravityDir.x) != null ? _a2 : 0,
(_b2 = schemaBoneGroup.gravityDir.y) != null ? _b2 : 0,
(_c2 = schemaBoneGroup.gravityDir.z) != null ? _c2 : 0
);
} else {
gravityDir.set(0, -1, 0);
}
const center = schemaBoneGroup.center != null ? threeNodes[schemaBoneGroup.center] : void 0;
const setting = {
hitRadius: schemaBoneGroup.hitRadius,
dragForce: schemaBoneGroup.dragForce,
gravityPower: schemaBoneGroup.gravityPower,
stiffness: schemaBoneGroup.stiffiness,
gravityDir
};
const colliderGroupsForSpring = (_d = schemaBoneGroup.colliderGroups) == null ? void 0 : _d.map((iColliderGroup) => {
const group = colliderGroups == null ? void 0 : colliderGroups[iColliderGroup];
if (group == null) {
throw new Error(
`VRMSpringBoneLoaderPlugin: The spring #${iBoneGroup} attempted to use a colliderGroup ${iColliderGroup} but not found`
);
}
return group;
});
root.traverse((node) => {
var _a3;
const child = (_a3 = node.children[0]) != null ? _a3 : null;
const joint = this._importJoint(node, child, setting, colliderGroupsForSpring);
if (center) {
joint.center = center;
}
manager.addJoint(joint);
});
});
});
gltf.scene.updateMatrixWorld();
manager.setInitState();
return manager;
});
}
_importJoint(node, child, setting, colliderGroupsForSpring) {
const springBone = new VRMSpringBoneJoint(node, child, setting, colliderGroupsForSpring);
if (this.jointHelperRoot) {
const helper = new VRMSpringBoneJointHelper(springBone);
this.jointHelperRoot.add(helper);
helper.renderOrder = this.jointHelperRoot.renderOrder;
}
return springBone;
}
_importSphereCollider(destination, params) {
const shape = new VRMSpringBoneColliderShapeSphere(params);
const collider = new VRMSpringBoneCollider(shape);
destination.add(collider);
if (this.colliderHelperRoot) {
const helper = new VRMSpringBoneColliderHelper(collider);
this.colliderHelperRoot.add(helper);
helper.renderOrder = this.colliderHelperRoot.renderOrder;
}
return collider;
}
_importCapsuleCollider(destination, params) {
const shape = new VRMSpringBoneColliderShapeCapsule(params);
const collider = new VRMSpringBoneCollider(shape);
destination.add(collider);
if (this.colliderHelperRoot) {
const helper = new VRMSpringBoneColliderHelper(collider);
this.colliderHelperRoot.add(helper);
helper.renderOrder = this.colliderHelperRoot.renderOrder;
}
return collider;
}
_importPlaneCollider(destination, params) {
const shape = new VRMSpringBoneColliderShapePlane(params);
const collider = new VRMSpringBoneCollider(shape);
destination.add(collider);
if (this.colliderHelperRoot) {
const helper = new VRMSpringBoneColliderHelper(collider);
this.colliderHelperRoot.add(helper);
helper.renderOrder = this.colliderHelperRoot.renderOrder;
}
return collider;
}
};
_VRMSpringBoneLoaderPlugin.EXTENSION_NAME = "VRMC_springBone";
var VRMSpringBoneLoaderPlugin = _VRMSpringBoneLoaderPlugin;
// src/VRMLoaderPlugin.ts
var VRMLoaderPlugin = class {
get name() {
return "VRMLoaderPlugin";
}
constructor(parser, options) {
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
this.parser = parser;
const helperRoot = options == null ? void 0 : options.helperRoot;
const autoUpdateHumanBones = options == null ? void 0 : options.autoUpdateHumanBones;
this.expressionPlugin = (_a = options == null ? void 0 : options.expressionPlugin) != null ? _a : new VRMExpressionLoaderPlugin(parser);
this.firstPersonPlugin = (_b = options == null ? void 0 : options.firstPersonPlugin) != null ? _b : new VRMFirstPersonLoaderPlugin(parser);
this.humanoidPlugin = (_c = options == null ? void 0 : options.humanoidPlugin) != null ? _c : new VRMHumanoidLoaderPlugin(parser, {
helperRoot,
autoUpdateHumanBones
});
this.lookAtPlugin = (_d = options == null ? void 0 : options.lookAtPlugin) != null ? _d : new VRMLookAtLoaderPlugin(parser, { helperRoot });
this.metaPlugin = (_e = options == null ? void 0 : options.metaPlugin) != null ? _e : new VRMMetaLoaderPlugin(parser);
this.mtoonMaterialPlugin = (_f = options == null ? void 0 : options.mtoonMaterialPlugin) != null ? _f : new MToonMaterialLoaderPlugin(parser);
this.materialsHDREmissiveMultiplierPlugin = (_g = options == null ? void 0 : options.materialsHDREmissiveMultiplierPlugin) != null ? _g : new VRMMaterialsHDREmissiveMultiplierLoaderPlugin(parser);
this.materialsV0CompatPlugin = (_h = options == null ? void 0 : options.materialsV0CompatPlugin) != null ? _h : new VRMMaterialsV0CompatPlugin(parser);
this.springBonePlugin = (_i = options == null ? void 0 : options.springBonePlugin) != null ? _i : new VRMSpringBoneLoaderPlugin(parser, {
colliderHelperRoot: helperRoot,
jointHelperRoot: helperRoot
});
this.nodeConstraintPlugin = (_j = options == null ? void 0 : options.nodeConstraintPlugin) != null ? _j : new VRMNodeConstraintLoaderPlugin(parser, { helperRoot });
}
beforeRoot() {
return __async(this, null, function* () {
yield this.materialsV0CompatPlugin.beforeRoot();
yield this.mtoonMaterialPlugin.beforeRoot();
});
}
loadMesh(meshIndex) {
return __async(this, null, function* () {
return yield this.mtoonMaterialPlugin.loadMesh(meshIndex);
});
}
getMaterialType(materialIndex) {
const mtoonType = this.mtoonMaterialPlugin.getMaterialType(materialIndex);
if (mtoonType != null) {
return mtoonType;
}
return null;
}
extendMaterialParams(materialIndex, materialParams) {
return __async(this, null, function* () {
yield this.materialsHDREmissiveMultiplierPlugin.extendMaterialParams(materialIndex, materialParams);
yield this.mtoonMaterialPlugin.extendMaterialParams(materialIndex, materialParams);
});
}
afterRoot(gltf) {
return __async(this, null, function* () {
yield this.metaPlugin.afterRoot(gltf);
yield this.humanoidPlugin.afterRoot(gltf);
yield this.expressionPlugin.afterRoot(gltf);
yield this.lookAtPlugin.afterRoot(gltf);
yield this.firstPersonPlugin.afterRoot(gltf);
yield this.springBonePlugin.afterRoot(gltf);
yield this.nodeConstraintPlugin.afterRoot(gltf);
yield this.mtoonMaterialPlugin.afterRoot(gltf);
const meta = gltf.userData.vrmMeta;
const humanoid = gltf.userData.vrmHumanoid;
if (meta && humanoid) {
const vrm = new VRM({
scene: gltf.scene,
expressionManager: gltf.userData.vrmExpressionManager,
firstPerson: gltf.userData.vrmFirstPerson,
humanoid,
lookAt: gltf.userData.vrmLookAt,
meta,
materials: gltf.userData.vrmMToonMaterials,
springBoneManager: gltf.userData.vrmSpringBoneManager,
nodeConstraintManager: gltf.userData.vrmNodeConstraintManager
});
gltf.userData.vrm = vrm;
}
});
}
};
// src/VRMUtils/combineMorphs.ts
var THREE21 = __toESM(require("three"), 1);
function collectMeshes(scene) {
const meshes = /* @__PURE__ */ new Set();
scene.traverse((obj) => {
if (!obj.isMesh) {
return;
}
const mesh = obj;
meshes.add(mesh);
});
return meshes;
}
function combineMorph(positionAttributes, binds, morphTargetsRelative) {
if (binds.size === 1) {
const bind = binds.values().next().value;
if (bind.weight === 1) {
return positionAttributes[bind.index];
}
}
const newArray = new Float32Array(positionAttributes[0].count * 3);
let weightSum = 0;
if (morphTargetsRelative) {
weightSum = 1;
} else {
for (const bind of binds) {
weightSum += bind.weight;
}
}
for (const bind of binds) {
const src = positionAttributes[bind.index];
const weight = bind.weight / weightSum;
for (let i = 0; i < src.count; i++) {
newArray[i * 3 + 0] += src.getX(i) * weight;
newArray[i * 3 + 1] += src.getY(i) * weight;
newArray[i * 3 + 2] += src.getZ(i) * weight;
}
}
const newAttribute = new THREE21.BufferAttribute(newArray, 3);
return newAttribute;
}
function combineMorphs(vrm) {
var _a;
const meshes = collectMeshes(vrm.scene);
const meshNameBindSetMapMap = /* @__PURE__ */ new Map();
const expressionMap = (_a = vrm.expressionManager) == null ? void 0 : _a.expressionMap;
if (expressionMap != null) {
for (const [expressionName, expression] of Object.entries(expressionMap)) {
const bindsToDeleteSet = /* @__PURE__ */ new Set();
for (const bind of expression.binds) {
if (bind instanceof VRMExpressionMorphTargetBind) {
if (bind.weight !== 0) {
for (const mesh of bind.primitives) {
let nameBindSetMap = meshNameBindSetMapMap.get(mesh);
if (nameBindSetMap == null) {
nameBindSetMap = /* @__PURE__ */ new Map();
meshNameBindSetMapMap.set(mesh, nameBindSetMap);
}
let bindSet = nameBindSetMap.get(expressionName);
if (bindSet == null) {
bindSet = /* @__PURE__ */ new Set();
nameBindSetMap.set(expressionName, bindSet);
}
bindSet.add(bind);
}
}
bindsToDeleteSet.add(bind);
}
}
for (const bind of bindsToDeleteSet) {
expression.deleteBind(bind);
}
}
}
for (const mesh of meshes) {
const nameBindSetMap = meshNameBindSetMapMap.get(mesh);
if (nameBindSetMap == null) {
continue;
}
const originalMorphAttributes = mesh.geometry.morphAttributes;
mesh.geometry.morphAttributes = {};
const geometry = mesh.geometry.clone();
mesh.geometry = geometry;
const morphTargetsRelative = geometry.morphTargetsRelative;
const hasPMorph = originalMorphAttributes.position != null;
const hasNMorph = originalMorphAttributes.normal != null;
const morphAttributes = {};
const morphTargetDictionary = {};
const morphTargetInfluences = [];
if (hasPMorph || hasNMorph) {
if (hasPMorph) {
morphAttributes.position = [];
}
if (hasNMorph) {
morphAttributes.normal = [];
}
let i = 0;
for (const [name, bindSet] of nameBindSetMap) {
if (hasPMorph) {
morphAttributes.position[i] = combineMorph(originalMorphAttributes.position, bindSet, morphTargetsRelative);
}
if (hasNMorph) {
morphAttributes.normal[i] = combineMorph(originalMorphAttributes.normal, bindSet, morphTargetsRelative);
}
expressionMap == null ? void 0 : expressionMap[name].addBind(
new VRMExpressionMorphTargetBind({
index: i,
weight: 1,
primitives: [mesh]
})
);
morphTargetDictionary[name] = i;
morphTargetInfluences.push(0);
i++;
}
}
geometry.morphAttributes = morphAttributes;
mesh.morphTargetDictionary = morphTargetDictionary;
mesh.morphTargetInfluences = morphTargetInfluences;
}
}
// src/VRMUtils/combineSkeletons.ts
var THREE27 = __toESM(require("three"), 1);
// src/utils/attributeGetComponentCompat.ts
var THREE25 = __toESM(require("three"), 1);
function attributeGetComponentCompat(attribute, index, component) {
if (attribute.getComponent) {
return attribute.getComponent(index, component);
} else {
let value = attribute.array[index * attribute.itemSize + component];
if (attribute.normalized) {
value = THREE25.MathUtils.denormalize(value, attribute.array);
}
return value;
}
}
// src/utils/attributeSetComponentCompat.ts
var THREE26 = __toESM(require("three"), 1);
function attributeSetComponentCompat(attribute, index, component, value) {
if (attribute.setComponent) {
attribute.setComponent(index, component, value);
} else {
if (attribute.normalized) {
value = THREE26.MathUtils.normalize(value, attribute.array);
}
attribute.array[index * attribute.itemSize + component] = value;
}
}
// src/VRMUtils/combineSkeletons.ts
function combineSkeletons(root) {
var _a;
const skinnedMeshes = collectSkinnedMeshes(root);
const geometries = /* @__PURE__ */ new Set();
for (const mesh of skinnedMeshes) {
if (geometries.has(mesh.geometry)) {
mesh.geometry = shallowCloneBufferGeometry(mesh.geometry);
}
geometries.add(mesh.geometry);
}
const attributeUsedIndexSetMap = /* @__PURE__ */ new Map();
for (const geometry of geometries) {
const skinIndexAttr = geometry.getAttribute("skinIndex");
const skinIndexMap = (_a = attributeUsedIndexSetMap.get(skinIndexAttr)) != null ? _a : /* @__PURE__ */ new Map();
attributeUsedIndexSetMap.set(skinIndexAttr, skinIndexMap);
const skinWeightAttr = geometry.getAttribute("skinWeight");
const usedIndicesSet = listUsedIndices(skinIndexAttr, skinWeightAttr);
skinIndexMap.set(skinWeightAttr, usedIndicesSet);
}
const meshBoneInverseMapMap = /* @__PURE__ */ new Map();
for (const mesh of skinnedMeshes) {
const boneInverseMap = listUsedBones(mesh, attributeUsedIndexSetMap);
meshBoneInverseMapMap.set(mesh, boneInverseMap);
}
const groups = [];
for (const [mesh, boneInverseMap] of meshBoneInverseMapMap) {
let foundMergeableGroup = false;
for (const candidate of groups) {
const isMergeable = boneInverseMapIsMergeable(boneInverseMap, candidate.boneInverseMap);
if (isMergeable) {
foundMergeableGroup = true;
candidate.meshes.add(mesh);
for (const [bone, boneInverse] of boneInverseMap) {
candidate.boneInverseMap.set(bone, boneInverse);
}
break;
}
}
if (!foundMergeableGroup) {
groups.push({ boneInverseMap, meshes: /* @__PURE__ */ new Set([mesh]) });
}
}
const cache = /* @__PURE__ */ new Map();
const skinIndexDispatcher = new ObjectIndexDispatcher();
const skeletonDispatcher = new ObjectIndexDispatcher();
const boneDispatcher = new ObjectIndexDispatcher();
for (const group of groups) {
const { boneInverseMap, meshes } = group;
const newBones = Array.from(boneInverseMap.keys());
const newBoneInverses = Array.from(boneInverseMap.values());
const newSkeleton = new THREE27.Skeleton(newBones, newBoneInverses);
const skeletonKey = skeletonDispatcher.getOrCreate(newSkeleton);
for (const mesh of meshes) {
const skinIndexAttr = mesh.geometry.getAttribute("skinIndex");
const skinIndexKey = skinIndexDispatcher.getOrCreate(skinIndexAttr);
const bones = mesh.skeleton.bones;
const bonesKey = bones.map((bone) => boneDispatcher.getOrCreate(bone)).join(",");
const key = `${skinIndexKey};${skeletonKey};${bonesKey}`;
let newSkinIndexAttr = cache.get(key);
if (newSkinIndexAttr == null) {
newSkinIndexAttr = skinIndexAttr.clone();
remapSkinIndexAttribute(newSkinIndexAttr, bones, newBones);
cache.set(key, newSkinIndexAttr);
}
mesh.geometry.setAttribute("skinIndex", newSkinIndexAttr);
}
for (const mesh of meshes) {
mesh.bind(newSkeleton, new THREE27.Matrix4());
}
}
}
function collectSkinnedMeshes(scene) {
const skinnedMeshes = /* @__PURE__ */ new Set();
scene.traverse((obj) => {
if (!obj.isSkinnedMesh) {
return;
}
const skinnedMesh = obj;
skinnedMeshes.add(skinnedMesh);
});
return skinnedMeshes;
}
function listUsedIndices(skinIndexAttr, skinWeightAttr) {
const usedIndices = /* @__PURE__ */ new Set();
for (let i = 0; i < skinIndexAttr.count; i++) {
for (let j = 0; j < skinIndexAttr.itemSize; j++) {
const index = attributeGetComponentCompat(skinIndexAttr, i, j);
const weight = attributeGetComponentCompat(skinWeightAttr, i, j);
if (weight !== 0) {
usedIndices.add(index);
}
}
}
return usedIndices;
}
function listUsedBones(mesh, attributeUsedIndexSetMap) {
const boneInverseMap = /* @__PURE__ */ new Map();
const skeleton = mesh.skeleton;
const geometry = mesh.geometry;
const skinIndexAttr = geometry.getAttribute("skinIndex");
const skinWeightAttr = geometry.getAttribute("skinWeight");
const skinIndexMap = attributeUsedIndexSetMap.get(skinIndexAttr);
const usedIndicesSet = skinIndexMap == null ? void 0 : skinIndexMap.get(skinWeightAttr);
if (!usedIndicesSet) {
throw new Error(
"Unreachable. attributeUsedIndexSetMap does not know the skin index attribute or the skin weight attribute."
);
}
for (const index of usedIndicesSet) {
boneInverseMap.set(skeleton.bones[index], skeleton.boneInverses[index]);
}
return boneInverseMap;
}
function boneInverseMapIsMergeable(toCheck, candidate) {
for (const [bone, boneInverse] of toCheck.entries()) {
const candidateBoneInverse = candidate.get(bone);
if (candidateBoneInverse != null) {
if (!matrixEquals(boneInverse, candidateBoneInverse)) {
return false;
}
}
}
return true;
}
function remapSkinIndexAttribute(attribute, oldBones, newBones) {
const boneOldIndexMap = /* @__PURE__ */ new Map();
for (const bone of oldBones) {
boneOldIndexMap.set(bone, boneOldIndexMap.size);
}
const oldToNew = /* @__PURE__ */ new Map();
for (const [i, bone] of newBones.entries()) {
const oldIndex = boneOldIndexMap.get(bone);
oldToNew.set(oldIndex, i);
}
for (let i = 0; i < attribute.count; i++) {
for (let j = 0; j < attribute.itemSize; j++) {
const oldIndex = attributeGetComponentCompat(attribute, i, j);
const newIndex = oldToNew.get(oldIndex);
attributeSetComponentCompat(attribute, i, j, newIndex);
}
}
attribute.needsUpdate = true;
}
function matrixEquals(a, b, tolerance) {
tolerance = tolerance || 1e-4;
if (a.elements.length != b.elements.length) {
return false;
}
for (let i = 0, il = a.elements.length; i < il; i++) {
const delta = Math.abs(a.elements[i] - b.elements[i]);
if (delta > tolerance) {
return false;
}
}
return true;
}
var ObjectIndexDispatcher = class {
constructor() {
this._objectIndexMap = /* @__PURE__ */ new Map();
this._index = 0;
}
get(obj) {
return this._objectIndexMap.get(obj);
}
getOrCreate(obj) {
let index = this._objectIndexMap.get(obj);
if (index == null) {
index = this._index;
this._objectIndexMap.set(obj, index);
this._index++;
}
return index;
}
};
function shallowCloneBufferGeometry(geometry) {
var _a, _b, _c, _d;
const clone = new THREE27.BufferGeometry();
clone.name = geometry.name;
clone.setIndex(geometry.index);
for (const [name, attribute] of Object.entries(geometry.attributes)) {
clone.setAttribute(name, attribute);
}
for (const [key, morphAttributes] of Object.entries(geometry.morphAttributes)) {
const attributeName = key;
clone.morphAttributes[attributeName] = morphAttributes.concat();
}
clone.morphTargetsRelative = geometry.morphTargetsRelative;
clone.groups = [];
for (const group of geometry.groups) {
clone.addGroup(group.start, group.count, group.materialIndex);
}
clone.boundingSphere = (_b = (_a = geometry.boundingSphere) == null ? void 0 : _a.clone()) != null ? _b : null;
clone.boundingBox = (_d = (_c = geometry.boundingBox) == null ? void 0 : _c.clone()) != null ? _d : null;
clone.drawRange.start = geometry.drawRange.start;
clone.drawRange.count = geometry.drawRange.count;
clone.userData = geometry.userData;
return clone;
}
// src/VRMUtils/deepDispose.ts
function disposeMaterial(material) {
Object.values(material).forEach((value) => {
if (value == null ? void 0 : value.isTexture) {
const texture = value;
texture.dispose();
}
});
if (material.isShaderMaterial) {
const uniforms = material.uniforms;
if (uniforms) {
Object.values(uniforms).forEach((uniform) => {
const value = uniform.value;
if (value == null ? void 0 : value.isTexture) {
const texture = value;
texture.dispose();
}
});
}
}
material.dispose();
}
function dispose(object3D) {
const geometry = object3D.geometry;
if (geometry) {
geometry.dispose();
}
const skeleton = object3D.skeleton;
if (skeleton) {
skeleton.dispose();
}
const material = object3D.material;
if (material) {
if (Array.isArray(material)) {
material.forEach((material2) => disposeMaterial(material2));
} else if (material) {
disposeMaterial(material);
}
}
}
function deepDispose(object3D) {
object3D.traverse(dispose);
}
// src/VRMUtils/removeUnnecessaryJoints.ts
var THREE28 = __toESM(require("three"), 1);
function removeUnnecessaryJoints(root, options) {
var _a, _b;
console.warn(
"VRMUtils.removeUnnecessaryJoints: removeUnnecessaryJoints is deprecated. Use combineSkeletons instead. combineSkeletons contributes more to the performance improvement. This function will be removed in the next major version."
);
const experimentalSameBoneCounts = (_a = options == null ? void 0 : options.experimentalSameBoneCounts) != null ? _a : false;
const skinnedMeshes = [];
root.traverse((obj) => {
if (obj.type !== "SkinnedMesh") {
return;
}
skinnedMeshes.push(obj);
});
const attributeToBoneIndexMapMap = /* @__PURE__ */ new Map();
let maxBones = 0;
for (const mesh of skinnedMeshes) {
const geometry = mesh.geometry;
const attribute = geometry.getAttribute("skinIndex");
if (attributeToBoneIndexMapMap.has(attribute)) {
continue;
}
const oldToNew = /* @__PURE__ */ new Map();
const newToOld = /* @__PURE__ */ new Map();
for (let i = 0; i < attribute.count; i++) {
for (let j = 0; j < attribute.itemSize; j++) {
const oldIndex = attributeGetComponentCompat(attribute, i, j);
let newIndex = oldToNew.get(oldIndex);
if (newIndex == null) {
newIndex = oldToNew.size;
oldToNew.set(oldIndex, newIndex);
newToOld.set(newIndex, oldIndex);
}
attributeSetComponentCompat(attribute, i, j, newIndex);
}
}
attribute.needsUpdate = true;
attributeToBoneIndexMapMap.set(attribute, newToOld);
maxBones = Math.max(maxBones, oldToNew.size);
}
for (const mesh of skinnedMeshes) {
const geometry = mesh.geometry;
const attribute = geometry.getAttribute("skinIndex");
const newToOld = attributeToBoneIndexMapMap.get(attribute);
const bones = [];
const boneInverses = [];
const nBones = experimentalSameBoneCounts ? maxBones : newToOld.size;
for (let newIndex = 0; newIndex < nBones; newIndex++) {
const oldIndex = (_b = newToOld.get(newIndex)) != null ? _b : 0;
bones.push(mesh.skeleton.bones[oldIndex]);
boneInverses.push(mesh.skeleton.boneInverses[oldIndex]);
}
const skeleton = new THREE28.Skeleton(bones, boneInverses);
mesh.bind(skeleton, new THREE28.Matrix4());
}
}
// src/VRMUtils/removeUnnecessaryVertices.ts
var THREE29 = __toESM(require("three"), 1);
var import_three = require("three");
function removeUnnecessaryVertices(root) {
const geometryMap = /* @__PURE__ */ new Map();
root.traverse((obj) => {
var _a, _b, _c, _d;
if (!obj.isMesh) {
return;
}
const mesh = obj;
const geometry = mesh.geometry;
const originalIndex = geometry.index;
if (originalIndex == null) {
return;
}
const newGeometryAlreadyExisted = geometryMap.get(geometry);
if (newGeometryAlreadyExisted != null) {
mesh.geometry = newGeometryAlreadyExisted;
return;
}
const vertexCount = Object.values(geometry.attributes)[0].count;
const vertexInUse = new Array(vertexCount);
let verticesUsed = 0;
const originalIndexArray = originalIndex.array;
for (let i = 0; i < originalIndexArray.length; i++) {
const index = originalIndexArray[i];
if (!vertexInUse[index]) {
vertexInUse[index] = true;
verticesUsed++;
}
}
if (verticesUsed === vertexCount) {
return;
}
const originalIndexNewIndexMap = [];
const newIndexOriginalIndexMap = [];
let indexHead = 0;
for (let i = 0; i < vertexInUse.length; i++) {
if (vertexInUse[i]) {
const newIndex = indexHead++;
originalIndexNewIndexMap[i] = newIndex;
newIndexOriginalIndexMap[newIndex] = i;
}
}
const newGeometry = new THREE29.BufferGeometry();
newGeometry.name = geometry.name;
newGeometry.morphTargetsRelative = geometry.morphTargetsRelative;
geometry.groups.forEach((group) => {
newGeometry.addGroup(group.start, group.count, group.materialIndex);
});
newGeometry.boundingBox = (_b = (_a = geometry.boundingBox) == null ? void 0 : _a.clone()) != null ? _b : null;
newGeometry.boundingSphere = (_d = (_c = geometry.boundingSphere) == null ? void 0 : _c.clone()) != null ? _d : null;
newGeometry.setDrawRange(geometry.drawRange.start, geometry.drawRange.count);
newGeometry.userData = geometry.userData;
geometryMap.set(geometry, newGeometry);
{
const originalIndexArray2 = originalIndex.array;
const newIndexArray = new originalIndexArray2.constructor(originalIndexArray2.length);
for (let i = 0; i < originalIndexArray2.length; i++) {
const originalIndex2 = originalIndexArray2[i];
const newIndex = originalIndexNewIndexMap[originalIndex2];
newIndexArray[i] = newIndex;
}
newGeometry.setIndex(new import_three.BufferAttribute(newIndexArray, 1, false));
}
Object.keys(geometry.attributes).forEach((attributeName) => {
const originalAttribute = geometry.attributes[attributeName];
if (originalAttribute.isInterleavedBufferAttribute) {
throw new Error("removeUnnecessaryVertices: InterleavedBufferAttribute is not supported");
}
const originalAttributeArray = originalAttribute.array;
const { itemSize, normalized } = originalAttribute;
const newAttributeArray = new originalAttributeArray.constructor(
newIndexOriginalIndexMap.length * itemSize
);
newIndexOriginalIndexMap.forEach((originalIndex2, i) => {
for (let j = 0; j < itemSize; j++) {
newAttributeArray[i * itemSize + j] = originalAttributeArray[originalIndex2 * itemSize + j];
}
});
newGeometry.setAttribute(attributeName, new import_three.BufferAttribute(newAttributeArray, itemSize, normalized));
});
let isNullMorph = true;
for (const [key, morphAttributes] of Object.entries(geometry.morphAttributes)) {
const attributeName = key;
newGeometry.morphAttributes[attributeName] = [];
for (let iMorph = 0; iMorph < morphAttributes.length; iMorph++) {
const originalAttribute = morphAttributes[iMorph];
if (originalAttribute.isInterleavedBufferAttribute) {
throw new Error("removeUnnecessaryVertices: InterleavedBufferAttribute is not supported");
}
const originalAttributeArray = originalAttribute.array;
const { itemSize, normalized } = originalAttribute;
const newAttributeArray = new originalAttributeArray.constructor(
newIndexOriginalIndexMap.length * itemSize
);
newIndexOriginalIndexMap.forEach((originalIndex2, i) => {
for (let j = 0; j < itemSize; j++) {
newAttributeArray[i * itemSize + j] = originalAttributeArray[originalIndex2 * itemSize + j];
}
});
isNullMorph = isNullMorph && newAttributeArray.every((v) => v === 0);
newGeometry.morphAttributes[attributeName][iMorph] = new import_three.BufferAttribute(
newAttributeArray,
itemSize,
normalized
);
}
}
if (isNullMorph) {
newGeometry.morphAttributes = {};
}
mesh.geometry = newGeometry;
});
Array.from(geometryMap.keys()).forEach((originalGeometry) => {
originalGeometry.dispose();
});
}
// src/VRMUtils/rotateVRM0.ts
function rotateVRM0(vrm) {
var _a;
if (((_a = vrm.meta) == null ? void 0 : _a.metaVersion) === "0") {
vrm.scene.rotation.y = Math.PI;
}
}
// src/VRMUtils/index.ts
var VRMUtils = class {
constructor() {
}
};
VRMUtils.combineMorphs = combineMorphs;
VRMUtils.combineSkeletons = combineSkeletons;
VRMUtils.deepDispose = deepDispose;
VRMUtils.removeUnnecessaryJoints = removeUnnecessaryJoints;
VRMUtils.removeUnnecessaryVertices = removeUnnecessaryVertices;
VRMUtils.rotateVRM0 = rotateVRM0;
/*!
* @pixiv/three-vrm-core v3.4.1
* The implementation of core features of VRM, for @pixiv/three-vrm
*
* Copyright (c) 2019-2025 pixiv Inc.
* @pixiv/three-vrm-core is distributed under MIT License
* https://github.com/pixiv/three-vrm/blob/release/LICENSE
*/
/*!
* @pixiv/three-vrm-materials-mtoon v3.4.1
* MToon (toon material) module for @pixiv/three-vrm
*
* Copyright (c) 2019-2025 pixiv Inc.
* @pixiv/three-vrm-materials-mtoon is distributed under MIT License
* https://github.com/pixiv/three-vrm/blob/release/LICENSE
*/
/*!
* @pixiv/three-vrm-materials-hdr-emissive-multiplier v3.4.1
* Support VRMC_hdr_emissiveMultiplier for @pixiv/three-vrm
*
* Copyright (c) 2019-2025 pixiv Inc.
* @pixiv/three-vrm-materials-hdr-emissive-multiplier is distributed under MIT License
* https://github.com/pixiv/three-vrm/blob/release/LICENSE
*/
/*!
* @pixiv/three-vrm-materials-v0compat v3.4.1
* VRM0.0 materials compatibility layer plugin for @pixiv/three-vrm
*
* Copyright (c) 2019-2025 pixiv Inc.
* @pixiv/three-vrm-materials-v0compat is distributed under MIT License
* https://github.com/pixiv/three-vrm/blob/release/LICENSE
*/
/*!
* @pixiv/three-vrm-node-constraint v3.4.1
* Node constraint module for @pixiv/three-vrm
*
* Copyright (c) 2019-2025 pixiv Inc.
* @pixiv/three-vrm-node-constraint is distributed under MIT License
* https://github.com/pixiv/three-vrm/blob/release/LICENSE
*/
/*!
* @pixiv/three-vrm-springbone v3.4.1
* Spring bone module for @pixiv/three-vrm
*
* Copyright (c) 2019-2025 pixiv Inc.
* @pixiv/three-vrm-springbone is distributed under MIT License
* https://github.com/pixiv/three-vrm/blob/release/LICENSE
*/
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2luZGV4LnRzIiwgIi4uLy4uL3RocmVlLXZybS1jb3JlL3NyYy9leHByZXNzaW9ucy9WUk1FeHByZXNzaW9uLnRzIiwgIi4uLy4uL3RocmVlLXZybS1jb3JlL3NyYy9leHByZXNzaW9ucy9WUk1FeHByZXNzaW9uTG9hZGVyUGx1Z2luLnRzIiwgIi4uLy4uL3RocmVlLXZybS1jb3JlL3NyYy91dGlscy9nbHRmRXh0cmFjdFByaW1pdGl2ZXNGcm9tTm9kZS50cyIsICIuLi8uLi90aHJlZS12cm0tY29yZS9zcmMvZXhwcmVzc2lvbnMvVlJNRXhwcmVzc2lvblByZXNldE5hbWUudHMiLCAiLi4vLi4vdGhyZWUtdnJtLWNvcmUvc3JjL3V0aWxzL3NhdHVyYXRlLnRzIiwgIi4uLy4uL3RocmVlLXZybS1jb3JlL3NyYy9leHByZXNzaW9ucy9WUk1FeHByZXNzaW9uTWFuYWdlci50cyIsICIuLi8uLi90aHJlZS12cm0tY29yZS9zcmMvZXhwcmVzc2lvbnMvVlJNRXhwcmVzc2lvbk1hdGVyaWFsQ29sb3JUeXBlLnRzIiwgIi4uLy4uL3RocmVlLXZybS1jb3JlL3NyYy9leHByZXNzaW9ucy9WUk1FeHByZXNzaW9uTWF0ZXJpYWxDb2xvckJpbmQudHMiLCAiLi4vLi4vdGhyZWUtdnJtLWNvcmUvc3JjL2V4cHJlc3Npb25zL1ZSTUV4cHJlc3Npb25Nb3JwaFRhcmdldEJpbmQudHMiLCAiLi4vLi4vdGhyZWUtdnJtLWNvcmUvc3JjL2V4cHJlc3Npb25zL1ZSTUV4cHJlc3Npb25UZXh0dXJlVHJhbnNmb3JtQmluZC50cyIsICIuLi8uLi90aHJlZS12cm0tY29yZS9zcmMvZXhwcmVzc2lvbnMvVlJNRXhwcmVzc2lvbk92ZXJyaWRlVHlwZS50cyIsICIuLi8uLi90aHJlZS12cm0tY29yZS9zcmMvZmlyc3RQZXJzb24vVlJNRmlyc3RQZXJzb24udHMiLCAiLi4vLi4vdGhyZWUtdnJtLWNvcmUvc3JjL2ZpcnN0UGVyc29uL1ZSTUZpcnN0UGVyc29uTG9hZGVyUGx1Z2luLnRzIiwgIi4uLy4uL3RocmVlLXZybS1jb3JlL3NyYy9maXJzdFBlcnNvbi9WUk1GaXJzdFBlcnNvbk1lc2hBbm5vdGF0aW9uVHlwZS50cyIsICIuLi8uLi90aHJlZS12cm0tY29yZS9zcmMvaHVtYW5vaWQvaGVscGVycy9WUk1IdW1hbm9pZEhlbHBlci50cyIsICIuLi8uLi90aHJlZS12cm0tY29yZS9zcmMvaHVtYW5vaWQvVlJNSHVtYW5Cb25lTGlzdC50cyIsICIuLi8uLi90aHJlZS12cm0tY29yZS9zcmMvaHVtYW5vaWQvVlJNSHVtYW5Cb25lTmFtZS50cyIsICIuLi8uLi90aHJlZS12cm0tY29yZS9zcmMvaHVtYW5vaWQvVlJNSHVtYW5Cb25lUGFyZW50TWFwLnRzIiwgIi4uLy4uL3RocmVlLXZybS1jb3JlL3NyYy9odW1hbm9pZC9WUk1SaWcudHMiLCAiLi4vLi4vdGhyZWUtdnJtLWNvcmUvc3JjL3V0aWxzL3F1YXRJbnZlcnRDb21wYXQudHMiLCAiLi4vLi4vdGhyZWUtdnJtLWNvcmUvc3JjL2h1bWFub2lkL1ZSTUh1bWFub2lkUmlnLnRzIiwgIi4uLy4uL3RocmVlLXZybS1jb3JlL3NyYy9odW1hbm9pZC9WUk1IdW1hbm9pZC50cyIsICIuLi8uLi90aHJlZS12cm0tY29yZS9zcmMvaHVtYW5vaWQvVlJNUmVxdWlyZWRIdW1hbkJvbmVOYW1lLnRzIiwgIi4uLy4uL3RocmVlLXZybS1jb3JlL3NyYy9odW1hbm9pZC9WUk1IdW1hbm9pZExvYWRlclBsdWdpbi50cyIsICIuLi8uLi90aHJlZS12cm0tY29yZS9zcmMvbG9va0F0L2hlbHBlcnMvVlJNTG9va0F0SGVscGVyLnRzIiwgIi4uLy4uL3RocmVlLXZybS1jb3JlL3NyYy9sb29rQXQvaGVscGVycy91dGlscy9GYW5CdWZmZXJHZW9tZXRyeS50cyIsICIuLi8uLi90aHJlZS12cm0tY29yZS9zcmMvbG9va0F0L2hlbHBlcnMvdXRpbHMvTGluZUFuZFNwaGVyZUJ1ZmZlckdlb21ldHJ5LnRzIiwgIi4uLy4uL3RocmVlLXZybS1jb3JlL3NyYy9sb29rQXQvVlJNTG9va0F0LnRzIiwgIi4uLy4uL3RocmVlLXZybS1jb3JlL3NyYy91dGlscy9nZXRXb3JsZFF1YXRlcm5pb25MaXRlLnRzIiwgIi4uLy4uL3RocmVlLXZybS1jb3JlL3NyYy9sb29rQXQvdXRpbHMvY2FsY0F6aW11dGhBbHRpdHVkZS50cyIsICIuLi8uLi90aHJlZS12cm0tY29yZS9zcmMvbG9va0F0L3V0aWxzL3Nhbml0aXplQW5nbGUudHMiLCAiLi4vLi4vdGhyZWUtdnJtLWNvcmUvc3JjL2xvb2tBdC9WUk1Mb29rQXRCb25lQXBwbGllci50cyIsICIuLi8uLi90aHJlZS12cm0tY29yZS9zcmMvbG9va0F0L1ZSTUxvb2tBdEV4cHJlc3Npb25BcHBsaWVyLnRzIiwgIi4uLy4uL3RocmVlLXZybS1jb3JlL3NyYy9sb29rQXQvVlJNTG9va0F0UmFuZ2VNYXAudHMiLCAiLi4vLi4vdGhyZWUtdnJtLWNvcmUvc3JjL2xvb2tBdC9WUk1Mb29rQXRMb2FkZXJQbHVnaW4udHMiLCAiLi4vLi4vdGhyZWUtdnJtLWNvcmUvc3JjL2xvb2tBdC9WUk1Mb29rQXRUeXBlTmFtZS50cyIsICIuLi8uLi90aHJlZS12cm0tY29yZS9zcmMvbWV0YS9WUk1NZXRhTG9hZGVyUGx1Z2luLnRzIiwgIi4uLy4uL3RocmVlLXZybS1jb3JlL3NyYy91dGlscy9yZXNvbHZlVVJMLnRzIiwgIi4uLy4uL3RocmVlLXZybS1jb3JlL3NyYy9WUk1Db3JlLnRzIiwgIi4uLy4uL3RocmVlLXZybS1jb3JlL3NyYy9WUk1Db3JlTG9hZGVyUGx1Z2luLnRzIiwgIi4uL3NyYy9WUk0udHMiLCAiLi4vLi4vdGhyZWUtdnJtLW1hdGVyaWFscy1tdG9vbi9zcmMvTVRvb25NYXRlcmlhbExvYWRlclBsdWdpbi50cyIsICIuLi8uLi90aHJlZS12cm0tbWF0ZXJpYWxzLW10b29uL3NyYy9HTFRGTVRvb25NYXRlcmlhbFBhcmFtc0Fzc2lnbkhlbHBlci50cyIsICIuLi8uLi90aHJlZS12cm0tbWF0ZXJpYWxzLW10b29uL3NyYy91dGlscy9zZXRUZXh0dXJlQ29sb3JTcGFjZS50cyIsICIuLi8uLi90aHJlZS12cm0tbWF0ZXJpYWxzLW10b29uL3NyYy9NVG9vbk1hdGVyaWFsLnRzIiwgIi4uLy4uL3RocmVlLXZybS1tYXRlcmlhbHMtbXRvb24vc3JjL3NoYWRlcnMvbXRvb24udmVydCIsICIuLi8uLi90aHJlZS12cm0tbWF0ZXJpYWxzLW10b29uL3NyYy9zaGFkZXJzL210b29uLmZyYWciLCAiLi4vLi4vdGhyZWUtdnJtLW1hdGVyaWFscy1tdG9vbi9zcmMvTVRvb25NYXRlcmlhbERlYnVnTW9kZS50cyIsICIuLi8uLi90aHJlZS12cm0tbWF0ZXJpYWxzLW10b29uL3NyYy9NVG9vbk1hdGVyaWFsT3V0bGluZVdpZHRoT