UNPKG

@pixiv/three-vrm

Version:

VRM file loader for three.js.

16 lines (14 loc) 82.5 kB
/*! (c) 2019-2021 pixiv Inc. - https://github.com/pixiv/three-vrm/blob/release/LICENSE */ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("three")):"function"==typeof define&&define.amd?define(["exports","three"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).THREE_VRM={},e.THREE)}(this,(function(e,t){"use strict"; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */function n(e,t,n,i){return new(n||(n=Promise))((function(r,o){function a(e){try{l(i.next(e))}catch(e){o(e)}}function s(e){try{l(i.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?r(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,s)}l((i=i.apply(e,t||[])).next())}))}function i(e){Object.keys(e).forEach((t=>{const n=e[t];if(null==n?void 0:n.isTexture){n.dispose()}})),e.dispose()}function r(e){const t=e.geometry;t&&t.dispose();const n=e.material;n&&(Array.isArray(n)?n.forEach((e=>i(e))):n&&i(n))}var o;!function(e){e[e.NUMBER=0]="NUMBER",e[e.VECTOR2=1]="VECTOR2",e[e.VECTOR3=2]="VECTOR3",e[e.VECTOR4=3]="VECTOR4",e[e.COLOR=4]="COLOR"}(o||(o={}));const a=new t.Vector2,s=new t.Vector3,l=new t.Vector4,d=new t.Color;class h extends t.Object3D{constructor(e){super(),this.weight=0,this.isBinary=!1,this._binds=[],this._materialValues=[],this.name=`BlendShapeController_${e}`,this.type="BlendShapeController",this.visible=!1}addBind(e){const t=e.weight/100;this._binds.push({meshes:e.meshes,morphTargetIndex:e.morphTargetIndex,weight:t})}addMaterialValue(e){const n=e.material,i=e.propertyName;let r,a,s,l,d=n[i];d&&(d=e.defaultValue||d,d.isVector2?(r=o.VECTOR2,a=d.clone(),s=(new t.Vector2).fromArray(e.targetValue),l=s.clone().sub(a)):d.isVector3?(r=o.VECTOR3,a=d.clone(),s=(new t.Vector3).fromArray(e.targetValue),l=s.clone().sub(a)):d.isVector4?(r=o.VECTOR4,a=d.clone(),s=(new t.Vector4).fromArray([e.targetValue[2],e.targetValue[3],e.targetValue[0],e.targetValue[1]]),l=s.clone().sub(a)):d.isColor?(r=o.COLOR,a=d.clone(),s=(new t.Color).fromArray(e.targetValue),l=s.clone().sub(a)):(r=o.NUMBER,a=d,s=e.targetValue[0],l=s-a),this._materialValues.push({material:n,propertyName:i,defaultValue:a,targetValue:s,deltaValue:l,type:r}))}applyWeight(){const e=this.isBinary?this.weight<.5?0:1:this.weight;this._binds.forEach((t=>{t.meshes.forEach((n=>{n.morphTargetInfluences&&(n.morphTargetInfluences[t.morphTargetIndex]+=e*t.weight)}))})),this._materialValues.forEach((t=>{if(void 0!==t.material[t.propertyName]){if(t.type===o.NUMBER){const n=t.deltaValue;t.material[t.propertyName]+=n*e}else if(t.type===o.VECTOR2){const n=t.deltaValue;t.material[t.propertyName].add(a.copy(n).multiplyScalar(e))}else if(t.type===o.VECTOR3){const n=t.deltaValue;t.material[t.propertyName].add(s.copy(n).multiplyScalar(e))}else if(t.type===o.VECTOR4){const n=t.deltaValue;t.material[t.propertyName].add(l.copy(n).multiplyScalar(e))}else if(t.type===o.COLOR){const n=t.deltaValue;t.material[t.propertyName].add(d.copy(n).multiplyScalar(e))}"boolean"==typeof t.material.shouldApplyUniforms&&(t.material.shouldApplyUniforms=!0)}}))}clearAppliedWeight(){this._binds.forEach((e=>{e.meshes.forEach((t=>{t.morphTargetInfluences&&(t.morphTargetInfluences[e.morphTargetIndex]=0)}))})),this._materialValues.forEach((e=>{if(void 0!==e.material[e.propertyName]){if(e.type===o.NUMBER){const t=e.defaultValue;e.material[e.propertyName]=t}else if(e.type===o.VECTOR2){const t=e.defaultValue;e.material[e.propertyName].copy(t)}else if(e.type===o.VECTOR3){const t=e.defaultValue;e.material[e.propertyName].copy(t)}else if(e.type===o.VECTOR4){const t=e.defaultValue;e.material[e.propertyName].copy(t)}else if(e.type===o.COLOR){const t=e.defaultValue;e.material[e.propertyName].copy(t)}"boolean"==typeof e.material.shouldApplyUniforms&&(e.material.shouldApplyUniforms=!0)}}))}}var u,c,p,m,f,g,_;function v(e,t,n){const i=e.parser.json.nodes[t].mesh;if(null==i)return null;const r=e.parser.json.meshes[i].primitives.length,o=[];return n.traverse((e=>{o.length<r&&e.isMesh&&o.push(e)})),o}function M(e){return n(this,void 0,void 0,(function*(){const t=yield e.parser.getDependencies("node"),n=new Map;return t.forEach(((t,i)=>{const r=v(e,i,t);null!=r&&n.set(i,r)})),n}))}function T(e){return"_"!==e[0]?(console.warn(`renameMaterialProperty: Given property name "${e}" might be invalid`),e):(e=e.substring(1),/[A-Z]/.test(e[0])?e[0].toLowerCase()+e.substring(1):(console.warn(`renameMaterialProperty: Given property name "${e}" might be invalid`),e))}u=e.VRMSchema||(e.VRMSchema={}),(c=u.BlendShapePresetName||(u.BlendShapePresetName={})).A="a",c.Angry="angry",c.Blink="blink",c.BlinkL="blink_l",c.BlinkR="blink_r",c.E="e",c.Fun="fun",c.I="i",c.Joy="joy",c.Lookdown="lookdown",c.Lookleft="lookleft",c.Lookright="lookright",c.Lookup="lookup",c.Neutral="neutral",c.O="o",c.Sorrow="sorrow",c.U="u",c.Unknown="unknown",(p=u.FirstPersonLookAtTypeName||(u.FirstPersonLookAtTypeName={})).BlendShape="BlendShape",p.Bone="Bone",(m=u.HumanoidBoneName||(u.HumanoidBoneName={})).Chest="chest",m.Head="head",m.Hips="hips",m.Jaw="jaw",m.LeftEye="leftEye",m.LeftFoot="leftFoot",m.LeftHand="leftHand",m.LeftIndexDistal="leftIndexDistal",m.LeftIndexIntermediate="leftIndexIntermediate",m.LeftIndexProximal="leftIndexProximal",m.LeftLittleDistal="leftLittleDistal",m.LeftLittleIntermediate="leftLittleIntermediate",m.LeftLittleProximal="leftLittleProximal",m.LeftLowerArm="leftLowerArm",m.LeftLowerLeg="leftLowerLeg",m.LeftMiddleDistal="leftMiddleDistal",m.LeftMiddleIntermediate="leftMiddleIntermediate",m.LeftMiddleProximal="leftMiddleProximal",m.LeftRingDistal="leftRingDistal",m.LeftRingIntermediate="leftRingIntermediate",m.LeftRingProximal="leftRingProximal",m.LeftShoulder="leftShoulder",m.LeftThumbDistal="leftThumbDistal",m.LeftThumbIntermediate="leftThumbIntermediate",m.LeftThumbProximal="leftThumbProximal",m.LeftToes="leftToes",m.LeftUpperArm="leftUpperArm",m.LeftUpperLeg="leftUpperLeg",m.Neck="neck",m.RightEye="rightEye",m.RightFoot="rightFoot",m.RightHand="rightHand",m.RightIndexDistal="rightIndexDistal",m.RightIndexIntermediate="rightIndexIntermediate",m.RightIndexProximal="rightIndexProximal",m.RightLittleDistal="rightLittleDistal",m.RightLittleIntermediate="rightLittleIntermediate",m.RightLittleProximal="rightLittleProximal",m.RightLowerArm="rightLowerArm",m.RightLowerLeg="rightLowerLeg",m.RightMiddleDistal="rightMiddleDistal",m.RightMiddleIntermediate="rightMiddleIntermediate",m.RightMiddleProximal="rightMiddleProximal",m.RightRingDistal="rightRingDistal",m.RightRingIntermediate="rightRingIntermediate",m.RightRingProximal="rightRingProximal",m.RightShoulder="rightShoulder",m.RightThumbDistal="rightThumbDistal",m.RightThumbIntermediate="rightThumbIntermediate",m.RightThumbProximal="rightThumbProximal",m.RightToes="rightToes",m.RightUpperArm="rightUpperArm",m.RightUpperLeg="rightUpperLeg",m.Spine="spine",m.UpperChest="upperChest",(f=u.MetaAllowedUserName||(u.MetaAllowedUserName={})).Everyone="Everyone",f.ExplicitlyLicensedPerson="ExplicitlyLicensedPerson",f.OnlyAuthor="OnlyAuthor",(g=u.MetaUssageName||(u.MetaUssageName={})).Allow="Allow",g.Disallow="Disallow",(_=u.MetaLicenseName||(u.MetaLicenseName={})).Cc0="CC0",_.CcBy="CC_BY",_.CcByNc="CC_BY_NC",_.CcByNcNd="CC_BY_NC_ND",_.CcByNcSa="CC_BY_NC_SA",_.CcByNd="CC_BY_ND",_.CcBySa="CC_BY_SA",_.Other="Other",_.RedistributionProhibited="Redistribution_Prohibited";const y=new t.Vector3,x=new t.Vector3;function S(e,t){return e.matrixWorld.decompose(y,t,x),t}new t.Quaternion;class R{constructor(){this._blendShapeGroups={},this._blendShapePresetMap={},this._unknownGroupNames=[]}get expressions(){return Object.keys(this._blendShapeGroups)}get blendShapePresetMap(){return this._blendShapePresetMap}get unknownGroupNames(){return this._unknownGroupNames}getBlendShapeGroup(e){const t=this._blendShapePresetMap[e],n=t?this._blendShapeGroups[t]:this._blendShapeGroups[e];if(n)return n;console.warn(`no blend shape found by ${e}`)}registerBlendShapeGroup(e,t,n){this._blendShapeGroups[e]=n,t?this._blendShapePresetMap[t]=e:this._unknownGroupNames.push(e)}getValue(e){var t;const n=this.getBlendShapeGroup(e);return null!==(t=null==n?void 0:n.weight)&&void 0!==t?t:null}setValue(e,t){const n=this.getBlendShapeGroup(e);var i;n&&(n.weight=(i=t,Math.max(Math.min(i,1),0)))}getBlendShapeTrackName(e){const t=this.getBlendShapeGroup(e);return t?`${t.name}.weight`:null}update(){Object.keys(this._blendShapeGroups).forEach((e=>{this._blendShapeGroups[e].clearAppliedWeight()})),Object.keys(this._blendShapeGroups).forEach((e=>{this._blendShapeGroups[e].applyWeight()}))}}class L{import(t){var i;return n(this,void 0,void 0,(function*(){const r=null===(i=t.parser.json.extensions)||void 0===i?void 0:i.VRM;if(!r)return null;const o=r.blendShapeMaster;if(!o)return null;const a=new R,s=o.blendShapeGroups;if(!s)return a;const l={};return yield Promise.all(s.map((i=>n(this,void 0,void 0,(function*(){const r=i.name;if(void 0===r)return void console.warn("VRMBlendShapeImporter: One of blendShapeGroups has no name");let o;i.presetName&&i.presetName!==e.VRMSchema.BlendShapePresetName.Unknown&&!l[i.presetName]&&(o=i.presetName,l[i.presetName]=r);const s=new h(r);t.scene.add(s),s.isBinary=i.isBinary||!1,i.binds&&i.binds.forEach((e=>n(this,void 0,void 0,(function*(){if(void 0===e.mesh||void 0===e.index)return;const r=[];t.parser.json.nodes.forEach(((t,n)=>{t.mesh===e.mesh&&r.push(n)}));const o=e.index;yield Promise.all(r.map((r=>n(this,void 0,void 0,(function*(){var a;const l=yield function(e,t){return n(this,void 0,void 0,(function*(){const n=yield e.parser.getDependency("node",t);return v(e,t,n)}))}(t,r);l.every((e=>Array.isArray(e.morphTargetInfluences)&&o<e.morphTargetInfluences.length))?s.addBind({meshes:l,morphTargetIndex:o,weight:null!==(a=e.weight)&&void 0!==a?a:100}):console.warn(`VRMBlendShapeImporter: ${i.name} attempts to index ${o}th morph but not found.`)})))))}))));const d=i.materialValues;d&&d.forEach((e=>{if(void 0===e.materialName||void 0===e.propertyName||void 0===e.targetValue)return;const n=[];t.scene.traverse((t=>{if(t.material){const i=t.material;Array.isArray(i)?n.push(...i.filter((t=>t.name===e.materialName&&-1===n.indexOf(t)))):i.name===e.materialName&&-1===n.indexOf(i)&&n.push(i)}})),n.forEach((t=>{s.addMaterialValue({material:t,propertyName:T(e.propertyName),targetValue:e.targetValue})}))})),a.registerBlendShapeGroup(r,o,s)}))))),a}))}}const E=Object.freeze(new t.Vector3(0,0,-1)),w=new t.Quaternion;var P;!function(e){e[e.Auto=0]="Auto",e[e.Both=1]="Both",e[e.ThirdPersonOnly=2]="ThirdPersonOnly",e[e.FirstPersonOnly=3]="FirstPersonOnly"}(P||(P={}));class A{constructor(e,t){this.firstPersonFlag=A._parseFirstPersonFlag(e),this.primitives=t}static _parseFirstPersonFlag(e){switch(e){case"Both":return P.Both;case"ThirdPersonOnly":return P.ThirdPersonOnly;case"FirstPersonOnly":return P.FirstPersonOnly;default:return P.Auto}}}class C{constructor(e,t,n){this._meshAnnotations=[],this._firstPersonOnlyLayer=C._DEFAULT_FIRSTPERSON_ONLY_LAYER,this._thirdPersonOnlyLayer=C._DEFAULT_THIRDPERSON_ONLY_LAYER,this._initialized=!1,this._firstPersonBone=e,this._firstPersonBoneOffset=t,this._meshAnnotations=n}get firstPersonBone(){return this._firstPersonBone}get meshAnnotations(){return this._meshAnnotations}getFirstPersonWorldDirection(e){return e.copy(E).applyQuaternion(S(this._firstPersonBone,w))}get firstPersonOnlyLayer(){return this._firstPersonOnlyLayer}get thirdPersonOnlyLayer(){return this._thirdPersonOnlyLayer}getFirstPersonBoneOffset(e){return e.copy(this._firstPersonBoneOffset)}getFirstPersonWorldPosition(e){const n=this._firstPersonBoneOffset,i=new t.Vector4(n.x,n.y,n.z,1);return i.applyMatrix4(this._firstPersonBone.matrixWorld),e.set(i.x,i.y,i.z)}setup({firstPersonOnlyLayer:e=C._DEFAULT_FIRSTPERSON_ONLY_LAYER,thirdPersonOnlyLayer:t=C._DEFAULT_THIRDPERSON_ONLY_LAYER}={}){this._initialized||(this._initialized=!0,this._firstPersonOnlyLayer=e,this._thirdPersonOnlyLayer=t,this._meshAnnotations.forEach((e=>{e.firstPersonFlag===P.FirstPersonOnly?e.primitives.forEach((e=>{e.layers.set(this._firstPersonOnlyLayer)})):e.firstPersonFlag===P.ThirdPersonOnly?e.primitives.forEach((e=>{e.layers.set(this._thirdPersonOnlyLayer)})):e.firstPersonFlag===P.Auto&&this._createHeadlessModel(e.primitives)})))}_excludeTriangles(e,t,n,i){let r=0;if(null!=t&&t.length>0)for(let o=0;o<e.length;o+=3){const a=e[o],s=e[o+1],l=e[o+2],d=t[a],h=n[a];if(d[0]>0&&i.includes(h[0]))continue;if(d[1]>0&&i.includes(h[1]))continue;if(d[2]>0&&i.includes(h[2]))continue;if(d[3]>0&&i.includes(h[3]))continue;const u=t[s],c=n[s];if(u[0]>0&&i.includes(c[0]))continue;if(u[1]>0&&i.includes(c[1]))continue;if(u[2]>0&&i.includes(c[2]))continue;if(u[3]>0&&i.includes(c[3]))continue;const p=t[l],m=n[l];p[0]>0&&i.includes(m[0])||(p[1]>0&&i.includes(m[1])||p[2]>0&&i.includes(m[2])||p[3]>0&&i.includes(m[3])||(e[r++]=a,e[r++]=s,e[r++]=l))}return r}_createErasedMesh(e,n){const i=new t.SkinnedMesh(e.geometry.clone(),e.material);i.name=`${e.name}(erase)`,i.frustumCulled=e.frustumCulled,i.layers.set(this._firstPersonOnlyLayer);const r=i.geometry,o=r.getAttribute("skinIndex").array,a=[];for(let e=0;e<o.length;e+=4)a.push([o[e],o[e+1],o[e+2],o[e+3]]);const s=r.getAttribute("skinWeight").array,l=[];for(let e=0;e<s.length;e+=4)l.push([s[e],s[e+1],s[e+2],s[e+3]]);const d=r.getIndex();if(!d)throw new Error("The geometry doesn't have an index buffer");const h=Array.from(d.array),u=this._excludeTriangles(h,l,a,n),c=[];for(let e=0;e<u;e++)c[e]=h[e];return r.setIndex(c),e.onBeforeRender&&(i.onBeforeRender=e.onBeforeRender),i.bind(new t.Skeleton(e.skeleton.bones,e.skeleton.boneInverses),new t.Matrix4),i}_createHeadlessModelForSkinnedMesh(e,t){const n=[];if(t.skeleton.bones.forEach(((e,t)=>{this._isEraseTarget(e)&&n.push(t)})),!n.length)return t.layers.enable(this._thirdPersonOnlyLayer),void t.layers.enable(this._firstPersonOnlyLayer);t.layers.set(this._thirdPersonOnlyLayer);const i=this._createErasedMesh(t,n);e.add(i)}_createHeadlessModel(e){e.forEach((e=>{if("SkinnedMesh"===e.type){const t=e;this._createHeadlessModelForSkinnedMesh(t.parent,t)}else this._isEraseTarget(e)&&e.layers.set(this._thirdPersonOnlyLayer)}))}_isEraseTarget(e){return e===this._firstPersonBone||!!e.parent&&this._isEraseTarget(e.parent)}}C._DEFAULT_FIRSTPERSON_ONLY_LAYER=9,C._DEFAULT_THIRDPERSON_ONLY_LAYER=10;class O{import(i,r){var o;return n(this,void 0,void 0,(function*(){const n=null===(o=i.parser.json.extensions)||void 0===o?void 0:o.VRM;if(!n)return null;const a=n.firstPerson;if(!a)return null;const s=a.firstPersonBone;let l;if(l=void 0===s||-1===s?r.getBoneNode(e.VRMSchema.HumanoidBoneName.Head):yield i.parser.getDependency("node",s),!l)return console.warn("VRMFirstPersonImporter: Could not find firstPersonBone of the VRM"),null;const d=a.firstPersonBoneOffset?new t.Vector3(a.firstPersonBoneOffset.x,a.firstPersonBoneOffset.y,-a.firstPersonBoneOffset.z):new t.Vector3(0,.06,0),h=[],u=yield M(i);return Array.from(u.entries()).forEach((([e,t])=>{const n=i.parser.json.nodes[e],r=a.meshAnnotations?a.meshAnnotations.find((e=>e.mesh===n.mesh)):void 0;h.push(new A(null==r?void 0:r.firstPersonFlag,t))})),new C(l,d,h)}))}}class b{constructor(e,t){this.node=e,this.humanLimit=t}}function D(e){return e.invert?e.invert():e.inverse(),e}const N=new t.Vector3,V=new t.Quaternion;class U{constructor(e,t){this.restPose={},this.humanBones=this._createHumanBones(e),this.humanDescription=t,this.restPose=this.getPose()}getPose(){const e={};return Object.keys(this.humanBones).forEach((t=>{const n=this.getBoneNode(t);if(!n)return;if(e[t])return;N.set(0,0,0),V.identity();const i=this.restPose[t];(null==i?void 0:i.position)&&N.fromArray(i.position).negate(),(null==i?void 0:i.rotation)&&D(V.fromArray(i.rotation)),N.add(n.position),V.premultiply(n.quaternion),e[t]={position:N.toArray(),rotation:V.toArray()}}),{}),e}setPose(e){Object.keys(e).forEach((t=>{const n=e[t],i=this.getBoneNode(t);if(!i)return;const r=this.restPose[t];r&&(n.position&&(i.position.fromArray(n.position),r.position&&i.position.add(N.fromArray(r.position))),n.rotation&&(i.quaternion.fromArray(n.rotation),r.rotation&&i.quaternion.multiply(V.fromArray(r.rotation))))}))}resetPose(){Object.entries(this.restPose).forEach((([e,t])=>{const n=this.getBoneNode(e);n&&((null==t?void 0:t.position)&&n.position.fromArray(t.position),(null==t?void 0:t.rotation)&&n.quaternion.fromArray(t.rotation))}))}getBone(e){var t;return null!==(t=this.humanBones[e][0])&&void 0!==t?t:void 0}getBones(e){var t;return null!==(t=this.humanBones[e])&&void 0!==t?t:[]}getBoneNode(e){var t,n;return null!==(n=null===(t=this.humanBones[e][0])||void 0===t?void 0:t.node)&&void 0!==n?n:null}getBoneNodes(e){var t,n;return null!==(n=null===(t=this.humanBones[e])||void 0===t?void 0:t.map((e=>e.node)))&&void 0!==n?n:[]}_createHumanBones(t){const n=Object.values(e.VRMSchema.HumanoidBoneName).reduce(((e,t)=>(e[t]=[],e)),{});return t.forEach((e=>{n[e.name].push(e.bone)})),n}}class I{import(e){var i;return n(this,void 0,void 0,(function*(){const r=null===(i=e.parser.json.extensions)||void 0===i?void 0:i.VRM;if(!r)return null;const o=r.humanoid;if(!o)return null;const a=[];o.humanBones&&(yield Promise.all(o.humanBones.map((i=>n(this,void 0,void 0,(function*(){if(!i.bone||null==i.node)return;const n=yield e.parser.getDependency("node",i.node);a.push({name:i.bone,bone:new b(n,{axisLength:i.axisLength,center:i.center&&new t.Vector3(i.center.x,i.center.y,i.center.z),max:i.max&&new t.Vector3(i.max.x,i.max.y,i.max.z),min:i.min&&new t.Vector3(i.min.x,i.min.y,i.min.z),useDefaultValues:i.useDefaultValues})})}))))));const s={armStretch:o.armStretch,legStretch:o.legStretch,upperArmTwist:o.upperArmTwist,lowerArmTwist:o.lowerArmTwist,upperLegTwist:o.upperLegTwist,lowerLegTwist:o.lowerLegTwist,feetSpacing:o.feetSpacing,hasTranslationDoF:o.hasTranslationDoF};return new U(a,s)}))}}class B{constructor(e,t,n){this.curve=[0,0,0,1,1,1,1,0],this.curveXRangeDegree=90,this.curveYRangeDegree=10,void 0!==e&&(this.curveXRangeDegree=e),void 0!==t&&(this.curveYRangeDegree=t),void 0!==n&&(this.curve=n)}map(e){const t=Math.min(Math.max(e,0),this.curveXRangeDegree)/this.curveXRangeDegree;return this.curveYRangeDegree*((e,t)=>{if(e.length<8)throw new Error("evaluateCurve: Invalid curve detected! (Array length must be 8 at least)");if(e.length%4!=0)throw new Error("evaluateCurve: Invalid curve detected! (Array length must be multiples of 4");let n;for(n=0;;n++){if(e.length<=4*n)return e[4*n-3];if(t<=e[4*n])break}const i=n-1;if(i<0)return e[4*i+5];const r=e[4*i],o=(t-r)/(e[4*n]-r);return((e,t,n,i,r)=>{const o=r*r*r,a=r*r;return e+(t-e)*(-2*o+3*a)+n*(o-2*a+r)+i*(o-a)})(e[4*i+1],e[4*n+1],e[4*i+3],e[4*n+2],o)})(this.curve,t)}}class G{}class F extends G{constructor(t,n,i,r){super(),this.type=e.VRMSchema.FirstPersonLookAtTypeName.BlendShape,this._curveHorizontal=n,this._curveVerticalDown=i,this._curveVerticalUp=r,this._blendShapeProxy=t}name(){return e.VRMSchema.FirstPersonLookAtTypeName.BlendShape}lookAt(t){const n=t.x,i=t.y;n<0?(this._blendShapeProxy.setValue(e.VRMSchema.BlendShapePresetName.Lookup,0),this._blendShapeProxy.setValue(e.VRMSchema.BlendShapePresetName.Lookdown,this._curveVerticalDown.map(-n))):(this._blendShapeProxy.setValue(e.VRMSchema.BlendShapePresetName.Lookdown,0),this._blendShapeProxy.setValue(e.VRMSchema.BlendShapePresetName.Lookup,this._curveVerticalUp.map(n))),i<0?(this._blendShapeProxy.setValue(e.VRMSchema.BlendShapePresetName.Lookleft,0),this._blendShapeProxy.setValue(e.VRMSchema.BlendShapePresetName.Lookright,this._curveHorizontal.map(-i))):(this._blendShapeProxy.setValue(e.VRMSchema.BlendShapePresetName.Lookright,0),this._blendShapeProxy.setValue(e.VRMSchema.BlendShapePresetName.Lookleft,this._curveHorizontal.map(i)))}}const k=Object.freeze(new t.Vector3(0,0,-1)),W=new t.Vector3,H=new t.Vector3,z=new t.Vector3,j=new t.Quaternion;class Y{constructor(e,n){this.autoUpdate=!0,this._euler=new t.Euler(0,0,0,Y.EULER_ORDER),this.firstPerson=e,this.applyer=n}getLookAtWorldDirection(e){const t=S(this.firstPerson.firstPersonBone,j);return e.copy(k).applyEuler(this._euler).applyQuaternion(t)}lookAt(e){this._calcEuler(this._euler,e),this.applyer&&this.applyer.lookAt(this._euler)}update(e){this.target&&this.autoUpdate&&(this.lookAt(this.target.getWorldPosition(W)),this.applyer&&this.applyer.lookAt(this._euler))}_calcEuler(e,t){const n=this.firstPerson.getFirstPersonWorldPosition(H),i=z.copy(t).sub(n).normalize();return i.applyQuaternion(D(S(this.firstPerson.firstPersonBone,j))),e.x=Math.atan2(i.y,Math.sqrt(i.x*i.x+i.z*i.z)),e.y=Math.atan2(-i.x,-i.z),e}}Y.EULER_ORDER="YXZ";const X=new t.Euler(0,0,0,Y.EULER_ORDER);class q extends G{constructor(t,n,i,r,o){super(),this.type=e.VRMSchema.FirstPersonLookAtTypeName.Bone,this._curveHorizontalInner=n,this._curveHorizontalOuter=i,this._curveVerticalDown=r,this._curveVerticalUp=o,this._leftEye=t.getBoneNode(e.VRMSchema.HumanoidBoneName.LeftEye),this._rightEye=t.getBoneNode(e.VRMSchema.HumanoidBoneName.RightEye)}lookAt(e){const t=e.x,n=e.y;this._leftEye&&(X.x=t<0?-this._curveVerticalDown.map(-t):this._curveVerticalUp.map(t),X.y=n<0?-this._curveHorizontalInner.map(-n):this._curveHorizontalOuter.map(n),this._leftEye.quaternion.setFromEuler(X)),this._rightEye&&(X.x=t<0?-this._curveVerticalDown.map(-t):this._curveVerticalUp.map(t),X.y=n<0?-this._curveHorizontalOuter.map(-n):this._curveHorizontalInner.map(n),this._rightEye.quaternion.setFromEuler(X))}}const Q=Math.PI/180;class Z{import(e,t,n,i){var r;const o=null===(r=e.parser.json.extensions)||void 0===r?void 0:r.VRM;if(!o)return null;const a=o.firstPerson;if(!a)return null;const s=this._importApplyer(a,n,i);return new Y(t,s||void 0)}_importApplyer(t,n,i){const r=t.lookAtHorizontalInner,o=t.lookAtHorizontalOuter,a=t.lookAtVerticalDown,s=t.lookAtVerticalUp;switch(t.lookAtTypeName){case e.VRMSchema.FirstPersonLookAtTypeName.Bone:return void 0===r||void 0===o||void 0===a||void 0===s?null:new q(i,this._importCurveMapperBone(r),this._importCurveMapperBone(o),this._importCurveMapperBone(a),this._importCurveMapperBone(s));case e.VRMSchema.FirstPersonLookAtTypeName.BlendShape:return void 0===o||void 0===a||void 0===s?null:new F(n,this._importCurveMapperBlendShape(o),this._importCurveMapperBlendShape(a),this._importCurveMapperBlendShape(s));default:return null}}_importCurveMapperBone(e){return new B("number"==typeof e.xRange?Q*e.xRange:void 0,"number"==typeof e.yRange?Q*e.yRange:void 0,e.curve)}_importCurveMapperBlendShape(e){return new B("number"==typeof e.xRange?Q*e.xRange:void 0,e.yRange,e.curve)}}const $=(e,n)=>{const i=(e=>{switch(e){case t.LinearEncoding:return["Linear","( value )"];case t.sRGBEncoding:return["sRGB","( value )"];case t.RGBEEncoding:return["RGBE","( value )"];case t.RGBM7Encoding:return["RGBM","( value, 7.0 )"];case t.RGBM16Encoding:return["RGBM","( value, 16.0 )"];case t.RGBDEncoding:return["RGBD","( value, 256.0 )"];case t.GammaEncoding:return["Gamma","( value, float( GAMMA_FACTOR ) )"];default:throw new Error("unsupported encoding: "+e)}})(n);return"vec4 "+e+"( vec4 value ) { return "+i[0]+"ToLinear"+i[1]+"; }"};const J=2*Math.PI;var K,ee,te,ne,ie;(K=e.MToonMaterialCullMode||(e.MToonMaterialCullMode={}))[K.Off=0]="Off",K[K.Front=1]="Front",K[K.Back=2]="Back",(ee=e.MToonMaterialDebugMode||(e.MToonMaterialDebugMode={}))[ee.None=0]="None",ee[ee.Normal=1]="Normal",ee[ee.LitShadeRate=2]="LitShadeRate",ee[ee.UV=3]="UV",(te=e.MToonMaterialOutlineColorMode||(e.MToonMaterialOutlineColorMode={}))[te.FixedColor=0]="FixedColor",te[te.MixedLighting=1]="MixedLighting",(ne=e.MToonMaterialOutlineWidthMode||(e.MToonMaterialOutlineWidthMode={}))[ne.None=0]="None",ne[ne.WorldCoordinates=1]="WorldCoordinates",ne[ne.ScreenCoordinates=2]="ScreenCoordinates",(ie=e.MToonMaterialRenderMode||(e.MToonMaterialRenderMode={}))[ie.Opaque=0]="Opaque",ie[ie.Cutout=1]="Cutout",ie[ie.Transparent=2]="Transparent",ie[ie.TransparentWithZWrite=3]="TransparentWithZWrite";class re extends t.ShaderMaterial{constructor(n={}){super(),this.isMToonMaterial=!0,this.cutoff=.5,this.color=new t.Vector4(1,1,1,1),this.shadeColor=new t.Vector4(.97,.81,.86,1),this.map=null,this.mainTex_ST=new t.Vector4(0,0,1,1),this.shadeTexture=null,this.normalMap=null,this.normalMapType=t.TangentSpaceNormalMap,this.normalScale=new t.Vector2(1,1),this.receiveShadowRate=1,this.receiveShadowTexture=null,this.shadingGradeRate=1,this.shadingGradeTexture=null,this.shadeShift=0,this.shadeToony=.9,this.lightColorAttenuation=0,this.indirectLightIntensity=.1,this.rimTexture=null,this.rimColor=new t.Vector4(0,0,0,1),this.rimLightingMix=0,this.rimFresnelPower=1,this.rimLift=0,this.sphereAdd=null,this.emissionColor=new t.Vector4(0,0,0,1),this.emissiveMap=null,this.outlineWidthTexture=null,this.outlineWidth=.5,this.outlineScaledMaxDistance=1,this.outlineColor=new t.Vector4(0,0,0,1),this.outlineLightingMix=1,this.uvAnimMaskTexture=null,this.uvAnimScrollX=0,this.uvAnimScrollY=0,this.uvAnimRotation=0,this.shouldApplyUniforms=!0,this._debugMode=e.MToonMaterialDebugMode.None,this._blendMode=e.MToonMaterialRenderMode.Opaque,this._outlineWidthMode=e.MToonMaterialOutlineWidthMode.None,this._outlineColorMode=e.MToonMaterialOutlineColorMode.FixedColor,this._cullMode=e.MToonMaterialCullMode.Back,this._outlineCullMode=e.MToonMaterialCullMode.Front,this._isOutline=!1,this._uvAnimOffsetX=0,this._uvAnimOffsetY=0,this._uvAnimPhase=0,this.encoding=n.encoding||t.LinearEncoding,this.encoding!==t.LinearEncoding&&this.encoding!==t.sRGBEncoding&&console.warn("The specified color encoding does not work properly with MToonMaterial. You might want to use THREE.sRGBEncoding instead."),["mToonVersion","shadeTexture_ST","bumpMap_ST","receiveShadowTexture_ST","shadingGradeTexture_ST","rimTexture_ST","sphereAdd_ST","emissionMap_ST","outlineWidthTexture_ST","uvAnimMaskTexture_ST","srcBlend","dstBlend"].forEach((e=>{void 0!==n[e]&&delete n[e]})),n.fog=!0,n.lights=!0,n.clipping=!0,n.skinning=n.skinning||!1,n.morphTargets=n.morphTargets||!1,n.morphNormals=n.morphNormals||!1,n.uniforms=t.UniformsUtils.merge([t.UniformsLib.common,t.UniformsLib.normalmap,t.UniformsLib.emissivemap,t.UniformsLib.fog,t.UniformsLib.lights,{cutoff:{value:.5},color:{value:new t.Color(1,1,1)},colorAlpha:{value:1},shadeColor:{value:new t.Color(.97,.81,.86)},mainTex_ST:{value:new t.Vector4(0,0,1,1)},shadeTexture:{value:null},receiveShadowRate:{value:1},receiveShadowTexture:{value:null},shadingGradeRate:{value:1},shadingGradeTexture:{value:null},shadeShift:{value:0},shadeToony:{value:.9},lightColorAttenuation:{value:0},indirectLightIntensity:{value:.1},rimTexture:{value:null},rimColor:{value:new t.Color(0,0,0)},rimLightingMix:{value:0},rimFresnelPower:{value:1},rimLift:{value:0},sphereAdd:{value:null},emissionColor:{value:new t.Color(0,0,0)},outlineWidthTexture:{value:null},outlineWidth:{value:.5},outlineScaledMaxDistance:{value:1},outlineColor:{value:new t.Color(0,0,0)},outlineLightingMix:{value:1},uvAnimMaskTexture:{value:null},uvAnimOffsetX:{value:0},uvAnimOffsetY:{value:0},uvAnimTheta:{value:0}}]),this.setValues(n),this._updateShaderCode(),this._applyUniforms()}get mainTex(){return this.map}set mainTex(e){this.map=e}get bumpMap(){return this.normalMap}set bumpMap(e){this.normalMap=e}get bumpScale(){return this.normalScale.x}set bumpScale(e){this.normalScale.set(e,e)}get emissionMap(){return this.emissiveMap}set emissionMap(e){this.emissiveMap=e}get blendMode(){return this._blendMode}set blendMode(t){this._blendMode=t,this.depthWrite=this._blendMode!==e.MToonMaterialRenderMode.Transparent,this.transparent=this._blendMode===e.MToonMaterialRenderMode.Transparent||this._blendMode===e.MToonMaterialRenderMode.TransparentWithZWrite,this._updateShaderCode()}get debugMode(){return this._debugMode}set debugMode(e){this._debugMode=e,this._updateShaderCode()}get outlineWidthMode(){return this._outlineWidthMode}set outlineWidthMode(e){this._outlineWidthMode=e,this._updateShaderCode()}get outlineColorMode(){return this._outlineColorMode}set outlineColorMode(e){this._outlineColorMode=e,this._updateShaderCode()}get cullMode(){return this._cullMode}set cullMode(e){this._cullMode=e,this._updateCullFace()}get outlineCullMode(){return this._outlineCullMode}set outlineCullMode(e){this._outlineCullMode=e,this._updateCullFace()}get zWrite(){return this.depthWrite?1:0}set zWrite(e){this.depthWrite=.5<=e}get isOutline(){return this._isOutline}set isOutline(e){this._isOutline=e,this._updateShaderCode(),this._updateCullFace()}updateVRMMaterials(e){this._uvAnimOffsetX=this._uvAnimOffsetX+e*this.uvAnimScrollX,this._uvAnimOffsetY=this._uvAnimOffsetY-e*this.uvAnimScrollY,this._uvAnimPhase=this._uvAnimPhase+e*this.uvAnimRotation,this._applyUniforms()}copy(e){return super.copy(e),this.cutoff=e.cutoff,this.color.copy(e.color),this.shadeColor.copy(e.shadeColor),this.map=e.map,this.mainTex_ST.copy(e.mainTex_ST),this.shadeTexture=e.shadeTexture,this.normalMap=e.normalMap,this.normalMapType=e.normalMapType,this.normalScale.copy(this.normalScale),this.receiveShadowRate=e.receiveShadowRate,this.receiveShadowTexture=e.receiveShadowTexture,this.shadingGradeRate=e.shadingGradeRate,this.shadingGradeTexture=e.shadingGradeTexture,this.shadeShift=e.shadeShift,this.shadeToony=e.shadeToony,this.lightColorAttenuation=e.lightColorAttenuation,this.indirectLightIntensity=e.indirectLightIntensity,this.rimTexture=e.rimTexture,this.rimColor.copy(e.rimColor),this.rimLightingMix=e.rimLightingMix,this.rimFresnelPower=e.rimFresnelPower,this.rimLift=e.rimLift,this.sphereAdd=e.sphereAdd,this.emissionColor.copy(e.emissionColor),this.emissiveMap=e.emissiveMap,this.outlineWidthTexture=e.outlineWidthTexture,this.outlineWidth=e.outlineWidth,this.outlineScaledMaxDistance=e.outlineScaledMaxDistance,this.outlineColor.copy(e.outlineColor),this.outlineLightingMix=e.outlineLightingMix,this.uvAnimMaskTexture=e.uvAnimMaskTexture,this.uvAnimScrollX=e.uvAnimScrollX,this.uvAnimScrollY=e.uvAnimScrollY,this.uvAnimRotation=e.uvAnimRotation,this.debugMode=e.debugMode,this.blendMode=e.blendMode,this.outlineWidthMode=e.outlineWidthMode,this.outlineColorMode=e.outlineColorMode,this.cullMode=e.cullMode,this.outlineCullMode=e.outlineCullMode,this.isOutline=e.isOutline,this}_applyUniforms(){this.uniforms.uvAnimOffsetX.value=this._uvAnimOffsetX,this.uniforms.uvAnimOffsetY.value=this._uvAnimOffsetY,this.uniforms.uvAnimTheta.value=J*this._uvAnimPhase,this.shouldApplyUniforms&&(this.shouldApplyUniforms=!1,this.uniforms.cutoff.value=this.cutoff,this.uniforms.color.value.setRGB(this.color.x,this.color.y,this.color.z),this.uniforms.colorAlpha.value=this.color.w,this.uniforms.shadeColor.value.setRGB(this.shadeColor.x,this.shadeColor.y,this.shadeColor.z),this.uniforms.map.value=this.map,this.uniforms.mainTex_ST.value.copy(this.mainTex_ST),this.uniforms.shadeTexture.value=this.shadeTexture,this.uniforms.normalMap.value=this.normalMap,this.uniforms.normalScale.value.copy(this.normalScale),this.uniforms.receiveShadowRate.value=this.receiveShadowRate,this.uniforms.receiveShadowTexture.value=this.receiveShadowTexture,this.uniforms.shadingGradeRate.value=this.shadingGradeRate,this.uniforms.shadingGradeTexture.value=this.shadingGradeTexture,this.uniforms.shadeShift.value=this.shadeShift,this.uniforms.shadeToony.value=this.shadeToony,this.uniforms.lightColorAttenuation.value=this.lightColorAttenuation,this.uniforms.indirectLightIntensity.value=this.indirectLightIntensity,this.uniforms.rimTexture.value=this.rimTexture,this.uniforms.rimColor.value.setRGB(this.rimColor.x,this.rimColor.y,this.rimColor.z),this.uniforms.rimLightingMix.value=this.rimLightingMix,this.uniforms.rimFresnelPower.value=this.rimFresnelPower,this.uniforms.rimLift.value=this.rimLift,this.uniforms.sphereAdd.value=this.sphereAdd,this.uniforms.emissionColor.value.setRGB(this.emissionColor.x,this.emissionColor.y,this.emissionColor.z),this.uniforms.emissiveMap.value=this.emissiveMap,this.uniforms.outlineWidthTexture.value=this.outlineWidthTexture,this.uniforms.outlineWidth.value=this.outlineWidth,this.uniforms.outlineScaledMaxDistance.value=this.outlineScaledMaxDistance,this.uniforms.outlineColor.value.setRGB(this.outlineColor.x,this.outlineColor.y,this.outlineColor.z),this.uniforms.outlineLightingMix.value=this.outlineLightingMix,this.uniforms.uvAnimMaskTexture.value=this.uvAnimMaskTexture,this.encoding===t.sRGBEncoding&&(this.uniforms.color.value.convertSRGBToLinear(),this.uniforms.shadeColor.value.convertSRGBToLinear(),this.uniforms.rimColor.value.convertSRGBToLinear(),this.uniforms.emissionColor.value.convertSRGBToLinear(),this.uniforms.outlineColor.value.convertSRGBToLinear()),this._updateCullFace())}_updateShaderCode(){const n=null!==this.outlineWidthTexture,i=null!==this.map||null!==this.shadeTexture||null!==this.receiveShadowTexture||null!==this.shadingGradeTexture||null!==this.rimTexture||null!==this.uvAnimMaskTexture;this.defines={THREE_VRM_THREE_REVISION_126:parseInt(t.REVISION)>=126,OUTLINE:this._isOutline,BLENDMODE_OPAQUE:this._blendMode===e.MToonMaterialRenderMode.Opaque,BLENDMODE_CUTOUT:this._blendMode===e.MToonMaterialRenderMode.Cutout,BLENDMODE_TRANSPARENT:this._blendMode===e.MToonMaterialRenderMode.Transparent||this._blendMode===e.MToonMaterialRenderMode.TransparentWithZWrite,MTOON_USE_UV:n||i,MTOON_UVS_VERTEX_ONLY:n&&!i,USE_SHADETEXTURE:null!==this.shadeTexture,USE_RECEIVESHADOWTEXTURE:null!==this.receiveShadowTexture,USE_SHADINGGRADETEXTURE:null!==this.shadingGradeTexture,USE_RIMTEXTURE:null!==this.rimTexture,USE_SPHEREADD:null!==this.sphereAdd,USE_OUTLINEWIDTHTEXTURE:null!==this.outlineWidthTexture,USE_UVANIMMASKTEXTURE:null!==this.uvAnimMaskTexture,DEBUG_NORMAL:this._debugMode===e.MToonMaterialDebugMode.Normal,DEBUG_LITSHADERATE:this._debugMode===e.MToonMaterialDebugMode.LitShadeRate,DEBUG_UV:this._debugMode===e.MToonMaterialDebugMode.UV,OUTLINE_WIDTH_WORLD:this._outlineWidthMode===e.MToonMaterialOutlineWidthMode.WorldCoordinates,OUTLINE_WIDTH_SCREEN:this._outlineWidthMode===e.MToonMaterialOutlineWidthMode.ScreenCoordinates,OUTLINE_COLOR_FIXED:this._outlineColorMode===e.MToonMaterialOutlineColorMode.FixedColor,OUTLINE_COLOR_MIXED:this._outlineColorMode===e.MToonMaterialOutlineColorMode.MixedLighting};const r=(null!==this.shadeTexture?$("shadeTextureTexelToLinear",this.shadeTexture.encoding)+"\n":"")+(null!==this.sphereAdd?$("sphereAddTexelToLinear",this.sphereAdd.encoding)+"\n":"")+(null!==this.rimTexture?$("rimTextureTexelToLinear",this.rimTexture.encoding)+"\n":"");this.vertexShader="// #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 #ifdef MTOON_UVS_VERTEX_ONLY\n vec2 vUv;\n #else\n varying vec2 vUv;\n #endif\n\n uniform vec4 mainTex_ST;\n#endif\n\n#include <uv2_pars_vertex>\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_OUTLINEWIDTHTEXTURE\n uniform sampler2D outlineWidthTexture;\n#endif\n\nuniform float outlineWidth;\nuniform float outlineScaledMaxDistance;\n\nvoid main() {\n\n // #include <uv_vertex>\n #ifdef MTOON_USE_UV\n vUv = uv;\n vUv.y = 1.0 - vUv.y; // uv.y is opposite from UniVRM's\n vUv = mainTex_ST.st + mainTex_ST.pq * vUv;\n vUv.y = 1.0 - vUv.y; // reverting the previous flip\n #endif\n\n #include <uv2_vertex>\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 float outlineTex = 1.0;\n\n #ifdef OUTLINE\n #ifdef USE_OUTLINEWIDTHTEXTURE\n outlineTex = texture2D( outlineWidthTexture, vUv ).r;\n #endif\n\n #ifdef OUTLINE_WIDTH_WORLD\n float worldNormalLength = length( transformedNormal );\n vec3 outlineOffset = 0.01 * outlineWidth * outlineTex * worldNormalLength * objectNormal;\n gl_Position = projectionMatrix * modelViewMatrix * vec4( outlineOffset + transformed, 1.0 );\n #endif\n\n #ifdef OUTLINE_WIDTH_SCREEN\n vec3 clipNormal = ( projectionMatrix * modelViewMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n vec2 projectedNormal = normalize( clipNormal.xy );\n projectedNormal *= min( gl_Position.w, outlineScaledMaxDistance );\n projectedNormal.x *= projectionMatrix[ 0 ].x / projectionMatrix[ 1 ].y;\n gl_Position.xy += 0.01 * outlineWidth * outlineTex * projectedNormal.xy;\n #endif\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}",this.fragmentShader=r+'// #define PHONG\n\n#ifdef BLENDMODE_CUTOUT\n uniform float cutoff;\n#endif\n\nuniform vec3 color;\nuniform float colorAlpha;\nuniform vec3 shadeColor;\n#ifdef USE_SHADETEXTURE\n uniform sampler2D shadeTexture;\n#endif\n\nuniform float receiveShadowRate;\n#ifdef USE_RECEIVESHADOWTEXTURE\n uniform sampler2D receiveShadowTexture;\n#endif\n\nuniform float shadingGradeRate;\n#ifdef USE_SHADINGGRADETEXTURE\n uniform sampler2D shadingGradeTexture;\n#endif\n\nuniform float shadeShift;\nuniform float shadeToony;\nuniform float lightColorAttenuation;\nuniform float indirectLightIntensity;\n\n#ifdef USE_RIMTEXTURE\n uniform sampler2D rimTexture;\n#endif\nuniform vec3 rimColor;\nuniform float rimLightingMix;\nuniform float rimFresnelPower;\nuniform float rimLift;\n\n#ifdef USE_SPHEREADD\n uniform sampler2D sphereAdd;\n#endif\n\nuniform vec3 emissionColor;\n\nuniform vec3 outlineColor;\nuniform float outlineLightingMix;\n\n#ifdef USE_UVANIMMASKTEXTURE\n uniform sampler2D uvAnimMaskTexture;\n#endif\n\nuniform float uvAnimOffsetX;\nuniform float uvAnimOffsetY;\nuniform float uvAnimTheta;\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#include <map_pars_fragment>\n// #include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n// #include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n// #include <envmap_common_pars_fragment>\n// #include <envmap_pars_fragment>\n// #include <cube_uv_reflection_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n\n// #include <lights_phong_pars_fragment>\nvarying vec3 vViewPosition;\n\n#ifndef FLAT_SHADED\n varying vec3 vNormal;\n#endif\n\nstruct MToonMaterial {\n vec3 diffuseColor;\n vec3 shadeColor;\n float shadingGrade;\n float receiveShadow;\n};\n\n#define Material_LightProbeLOD( material ) (0)\n\n#include <shadowmap_pars_fragment>\n// #include <bumpmap_pars_fragment>\n\n// #include <normalmap_pars_fragment>\n#ifdef USE_NORMALMAP\n\n uniform sampler2D normalMap;\n uniform vec2 normalScale;\n\n#endif\n\n#ifdef OBJECTSPACE_NORMALMAP\n\n uniform mat3 normalMatrix;\n\n#endif\n\n#if ! defined ( USE_TANGENT ) && defined ( TANGENTSPACE_NORMALMAP )\n\n // Per-Pixel Tangent Space Normal Mapping\n // http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html\n\n // three-vrm specific change: it requires `uv` as an input in order to support uv scrolls\n\n // Temporary compat against shader change @ Three.js r126\n // See: #21205, #21307, #21299\n #ifdef THREE_VRM_THREE_REVISION_126\n\n vec3 perturbNormal2Arb( vec2 uv, vec3 eye_pos, vec3 surf_norm, vec3 mapN, float faceDirection ) {\n\n vec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n vec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n vec2 st0 = dFdx( uv.st );\n vec2 st1 = dFdy( uv.st );\n\n vec3 N = normalize( surf_norm );\n\n vec3 q1perp = cross( q1, N );\n vec3 q0perp = cross( N, q0 );\n\n vec3 T = q1perp * st0.x + q0perp * st1.x;\n vec3 B = q1perp * st0.y + q0perp * st1.y;\n\n // three-vrm specific change: Workaround for the issue that happens when delta of uv = 0.0\n // TODO: Is this still required? Or shall I make a PR about it?\n if ( length( T ) == 0.0 || length( B ) == 0.0 ) {\n return surf_norm;\n }\n\n float det = max( dot( T, T ), dot( B, B ) );\n float scale = ( det == 0.0 ) ? 0.0 : faceDirection * inversesqrt( det );\n\n return normalize( T * ( mapN.x * scale ) + B * ( mapN.y * scale ) + N * mapN.z );\n\n }\n\n #else\n\n vec3 perturbNormal2Arb( vec2 uv, vec3 eye_pos, vec3 surf_norm, vec3 mapN ) {\n\n // Workaround for Adreno 3XX dFd*( vec3 ) bug. See #9988\n\n vec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n vec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n vec2 st0 = dFdx( uv.st );\n vec2 st1 = dFdy( uv.st );\n\n float scale = sign( st1.t * st0.s - st0.t * st1.s ); // we do not care about the magnitude\n\n vec3 S = ( q0 * st1.t - q1 * st0.t ) * scale;\n vec3 T = ( - q0 * st1.s + q1 * st0.s ) * scale;\n\n // three-vrm specific change: Workaround for the issue that happens when delta of uv = 0.0\n // TODO: Is this still required? Or shall I make a PR about it?\n\n if ( length( S ) == 0.0 || length( T ) == 0.0 ) {\n return surf_norm;\n }\n\n S = normalize( S );\n T = normalize( T );\n vec3 N = normalize( surf_norm );\n\n #ifdef DOUBLE_SIDED\n\n // Workaround for Adreno GPUs gl_FrontFacing bug. See #15850 and #10331\n\n bool frontFacing = dot( cross( S, T ), N ) > 0.0;\n\n mapN.xy *= ( float( frontFacing ) * 2.0 - 1.0 );\n\n #else\n\n mapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\n #endif\n\n mat3 tsn = mat3( S, T, N );\n return normalize( tsn * mapN );\n\n }\n\n #endif\n\n#endif\n\n// #include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\n// == lighting stuff ===========================================================\nfloat getLightIntensity(\n const in IncidentLight directLight,\n const in GeometricContext geometry,\n const in float shadow,\n const in float shadingGrade\n) {\n float lightIntensity = dot( geometry.normal, directLight.direction );\n lightIntensity = 0.5 + 0.5 * lightIntensity;\n lightIntensity = lightIntensity * shadow;\n lightIntensity = lightIntensity * shadingGrade;\n lightIntensity = lightIntensity * 2.0 - 1.0;\n return shadeToony == 1.0\n ? step( shadeShift, lightIntensity )\n : smoothstep( shadeShift, shadeShift + ( 1.0 - shadeToony ), lightIntensity );\n}\n\nvec3 getLighting( const in vec3 lightColor ) {\n vec3 lighting = lightColor;\n lighting = mix(\n lighting,\n vec3( max( 0.001, max( lighting.x, max( lighting.y, lighting.z ) ) ) ),\n lightColorAttenuation\n );\n\n #ifndef PHYSICALLY_CORRECT_LIGHTS\n lighting *= PI;\n #endif\n\n return lighting;\n}\n\nvec3 getDiffuse(\n const in MToonMaterial material,\n const in float lightIntensity,\n const in vec3 lighting\n) {\n #ifdef DEBUG_LITSHADERATE\n return vec3( BRDF_Diffuse_Lambert( lightIntensity * lighting ) );\n #endif\n\n return lighting * BRDF_Diffuse_Lambert( mix( material.shadeColor, material.diffuseColor, lightIntensity ) );\n}\n\n// == post correction ==========================================================\nvoid postCorrection() {\n #include <tonemapping_fragment>\n #include <encodings_fragment>\n #include <fog_fragment>\n #include <premultiplied_alpha_fragment>\n #include <dithering_fragment>\n}\n\n// == main procedure ===========================================================\nvoid main() {\n #include <clipping_planes_fragment>\n\n vec2 uv = vec2(0.5, 0.5);\n\n #if ( defined( MTOON_USE_UV ) && !defined( MTOON_UVS_VERTEX_ONLY ) )\n uv = vUv;\n\n float uvAnimMask = 1.0;\n #ifdef USE_UVANIMMASKTEXTURE\n uvAnimMask = texture2D( uvAnimMaskTexture, uv ).x;\n #endif\n\n uv = uv + vec2( uvAnimOffsetX, uvAnimOffsetY ) * uvAnimMask;\n float uvRotCos = cos( uvAnimTheta * uvAnimMask );\n float uvRotSin = sin( uvAnimTheta * uvAnimMask );\n uv = mat2( uvRotCos, uvRotSin, -uvRotSin, uvRotCos ) * ( uv - 0.5 ) + 0.5;\n #endif\n\n #ifdef DEBUG_UV\n gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n #if ( defined( MTOON_USE_UV ) && !defined( MTOON_UVS_VERTEX_ONLY ) )\n gl_FragColor = vec4( uv, 0.0, 1.0 );\n #endif\n return;\n #endif\n\n vec4 diffuseColor = vec4( color, colorAlpha );\n ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n vec3 totalEmissiveRadiance = emissionColor;\n\n #include <logdepthbuf_fragment>\n\n // #include <map_fragment>\n #ifdef USE_MAP\n diffuseColor *= mapTexelToLinear( texture2D( map, uv ) );\n #endif\n\n #include <color_fragment>\n // #include <alphamap_fragment>\n\n // -- MToon: alpha -----------------------------------------------------------\n // #include <alphatest_fragment>\n #ifdef BLENDMODE_CUTOUT\n if ( diffuseColor.a <= cutoff ) { discard; }\n diffuseColor.a = 1.0;\n #endif\n\n #ifdef BLENDMODE_OPAQUE\n diffuseColor.a = 1.0;\n #endif\n\n #if defined( OUTLINE ) && defined( OUTLINE_COLOR_FIXED ) // omitting DebugMode\n gl_FragColor = vec4( outlineColor, diffuseColor.a );\n postCorrection();\n return;\n #endif\n\n // #include <specularmap_fragment>\n #include <normal_fragment_begin>\n\n #ifdef OUTLINE\n normal *= -1.0;\n #endif\n\n // #include <normal_fragment_maps>\n\n #ifdef OBJECTSPACE_NORMALMAP\n\n normal = texture2D( normalMap, uv ).xyz * 2.0 - 1.0; // overrides both flatShading and attribute normals\n\n #ifdef FLIP_SIDED\n\n normal = - normal;\n\n #endif\n\n #ifdef DOUBLE_SIDED\n\n // Temporary compat against shader change @ Three.js r126\n // See: #21205, #21307, #21299\n #ifdef THREE_VRM_THREE_REVISION_126\n\n normal = normal * faceDirection;\n\n #else\n\n normal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\n #endif\n\n #endif\n\n normal = normalize( normalMatrix * normal );\n\n #elif defined( TANGENTSPACE_NORMALMAP )\n\n vec3 mapN = texture2D( normalMap, uv ).xyz * 2.0 - 1.0;\n mapN.xy *= normalScale;\n\n #ifdef USE_TANGENT\n\n normal = normalize( vTBN * mapN );\n\n #else\n\n // Temporary compat against shader change @ Three.js r126\n // See: #21205, #21307, #21299\n #ifdef THREE_VRM_THREE_REVISION_126\n\n normal = perturbNormal2Arb( uv, -vViewPosition, normal, mapN, faceDirection );\n\n #else\n\n normal = perturbNormal2Arb( uv, -vViewPosition, normal, mapN );\n\n #endif\n\n #endif\n\n #endif\n\n // #include <emissivemap_fragment>\n #ifdef USE_EMISSIVEMAP\n totalEmissiveRadiance *= emissiveMapTexelToLinear( texture2D( emissiveMap, uv ) ).rgb;\n #endif\n\n #ifdef DEBUG_NORMAL\n gl_FragColor = vec4( 0.5 + 0.5 * normal, 1.0 );\n return;\n #endif\n\n // -- MToon: lighting --------------------------------------------------------\n // accumulation\n // #include <lights_phong_fragment>\n MToonMaterial material;\n\n material.diffuseColor = diffuseColor.rgb;\n\n material.shadeColor = shadeColor;\n #ifdef USE_SHADETEXTURE\n material.shadeColor *= shadeTextureTexelToLinear( texture2D( shadeTexture, uv ) ).rgb;\n #endif\n\n material.shadingGrade = 1.0;\n #ifdef USE_SHADINGGRADETEXTURE\n material.shadingGrade = 1.0 - shadingGradeRate * ( 1.0 - texture2D( shadingGradeTexture, uv ).r );\n #endif\n\n material.receiveShadow = receiveShadowRate;\n #ifdef USE_RECEIVESHADOWTEXTURE\n material.receiveShadow *= texture2D( receiveShadowTexture, uv ).a;\n #endif\n\n // #include <lights_fragment_begin>\n GeometricContext geometry;\n\n geometry.position = - vViewPosition;\n geometry.normal = normal;\n geometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n\n IncidentLight directLight;\n vec3 lightingSum = vec3( 0.0 );\n\n #if ( NUM_POINT_LIGHTS > 0 )\n PointLight pointLight;\n\n #if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n PointLightShadow pointLightShadow;\n #endif\n\n #pragma unroll_loop_start\n for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n pointLight = pointLights[ i ];\n getPointDirectLightIrradiance( pointLight, geometry, directLight );\n\n float atten = 1.0;\n #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n