disfigure
Version:
A library to rig non-rigged 3D models
3 lines (2 loc) • 14.4 kB
JavaScript
/*! disfigure v0.0.20 */
import{Color as t,WebGPURenderer as e,PCFSoftShadowMap as s,Scene as i,PerspectiveCamera as r,DirectionalLight as o,Mesh as a,CircleGeometry as n,MeshLambertMaterial as h,CanvasTexture as l,Vector3 as d,PlaneGeometry as c,MeshPhysicalNodeMaterial as u,Euler as p,MathUtils as m,Group as w,Matrix3 as g}from"three";import{GLTFLoader as _}from"three/addons/loaders/GLTFLoader.js";import{Fn as v,mat3 as f,vec3 as y,mix as x,positionGeometry as b,vec2 as z,float as k,rotate as M,If as S,transformNormalToView as E,normalGeometry as P,min as I,select as X,uniform as A}from"three/tsl";import{SimplexNoise as Y}from"three/addons/math/SimplexNoise.js";import{OrbitControls as j}from"three/addons/controls/OrbitControls.js";import H from"three/addons/libs/stats.module.js";var L=v((({color:t,roughness:e,metalness:s})=>f(t,y(e,s,0),y(0,0,0))),{color:"vec3",roughness:"float",metalness:"float",return:"mat3"}),T=v((({value:t,fromValue:e,toValue:s})=>t.greaterThanEqual(e).and(t.lessThanEqual(s))),{value:"float",fromValue:"float",toValue:"float",return:"float"}),C=v((([t,e,s])=>f(x(t[0],e[0],s),x(t[1],e[1],s),y(0,0,0))),{matA:"mat3",matB:"mat3",k:"float",return:"mat3"}),N=new t;function V(t){return N.set(t),y(...N)}function R(t){return L(V(t),.2,.3)}function W(t){return L(V(t).mul(3),1,1)}var q=v((({matA:t,matB:e,width:s=k(.1),options:i={}})=>{var r,o,{balance:a,blur:n,angle:h,polar:l,x:d,z:c}=i;return r=l?(o=b.xz.sub(z(d??0,c??0))).y.atan(o.x).div(k(s).mul(2)).cos():(o=M(b.xy,(h??0)*Math.PI/180)).y.div(s,1/Math.PI).cos(),a&&(r=r.add(a)),(n=n??1e-5)&&(r=r.smoothstep(-n,n)),C(t,e,r)})),G=v((({from:t,to:e,options:s={}})=>{var i=b.toVar(),r="yxzyx",o=0;s.side&&(o=1),s.front&&(o=2),s.angle&&i[r[o]].addAssign(i[r[o+1]].mul(Math.tan(s.angle*Math.PI/180))),s.sideAngle&&i[r[o]].addAssign(i[r[o+2]].mul(Math.tan(s.sideAngle*Math.PI/180)));var a=i[r[o]];if(s.wave){var n=i[r[o+1]].mul(k(Math.PI).div(s.width??Math.PI)).cos().toVar(),h=k(s.sharpness??0).mix(n,n.acos().mul(-2/Math.PI).sub(1)).mul(s.wave,.5);a=a.add(h)}return s.symmetry&&(a=a.abs()),T(a,t,e)})),U=v((([t])=>{var e=f(t[0]);for(let s=1;s<t.length;s+=2)S(t[s],(()=>{e.assign(t[s+1])}));return e})),Z=new Y;function B(t,e=0,s=-1,i=1){return s+(i-s)*(Z.noise(t,e)+1)/2}function O(t,e=0,s=-1,i=1){return s+(i-s)*(Math.sin(t+e)+1)/2}function D(t=-1,e=1){return t+(e-t)*Math.random()}var F=v((([t,e,s,i])=>{var r=t.sub(e).mul(s).add(e);return x(t,r,i)})),J=v((([t,e,s,i])=>{var r=t.mul(s);return x(t,r,i)}));function K(t){return E(nt(t,J,P))}var Q,$,tt,et,st,it,rt,ot,at,nt=v((([t,e,s])=>{s=s.toVar();var i=t.space;function r(r){for(var o of r)s.assign(e(s,i[o].pivot,t[o].umatrix,i[o].locus()))}return S(i.l_arm.locus(),(()=>{r(["l_wrist","l_forearm","l_elbow","l_arm"])})),S(i.r_arm.locus(),(()=>{r(["r_wrist","r_forearm","r_elbow","r_arm"])})),S(i.l_leg.locus(),(()=>{r(["l_foot","l_ankle","l_shin","l_knee","l_thigh","l_leg"])})),S(i.r_leg.locus(),(()=>{r(["r_foot","r_ankle","r_shin","r_knee","r_thigh","r_leg"])})),r(["head","chest","waist","torso"]),s})),ht=[];class lt{constructor(d){if((Q=new e({antialias:d?.antialias??!0})).setSize(innerWidth,innerHeight),Q.shadowMap.enabled=d?.shadows??!0,Q.shadowMap.type=s,document.body.appendChild(Q.domElement),document.body.style.overflow="hidden",document.body.style.margin="0",($=new i).background=new t("whitesmoke"),(tt=new r(30,innerWidth/innerHeight)).position.set(0,1.5,4),d?.stats&&(at=new H,document.body.appendChild(at.dom)),(d?.lights??1)&&((et=new o("white",1.5)).position.set(0,14,7),(d?.shadows??1)&&(et.shadow.mapSize.width=2048,et.shadow.mapSize.height=et.shadow.mapSize.width,et.shadow.camera.near=1,et.shadow.camera.far=50,et.shadow.camera.left=-5,et.shadow.camera.right=5,et.shadow.camera.top=5,et.shadow.camera.bottom=-5,et.shadow.normalBias=.01,et.autoUpdate=!1,et.castShadow=!0),$.add(et),(st=new o("white",1.5)).target=$,tt.add(st),$.add(tt)),(d?.controls??1)&&((it=new j(tt,Q.domElement)).enableDamping=!0,it.target.set(0,.9,0)),d?.ground??1){var c=document.createElement("CANVAS");c.width=128,c.height=128;var u=c.getContext("2d");u.fillStyle="white",u.filter="blur(10px)",u.beginPath(),u.arc(64,64,38,0,2*Math.PI),u.fill(),(rt=new a(new n(32),new h({color:"antiquewhite",transparent:!0,map:new l(c)}))).receiveShadow=!0,rt.rotation.x=-Math.PI/2,rt.renderOrder=-1,$.add(rt)}window.addEventListener("resize",(()=>{tt.aspect=innerWidth/innerHeight,tt.updateProjectionMatrix(),Q.setSize(innerWidth,innerHeight)})),Q.setAnimationLoop(ut)}}class dt extends Event{#t;constructor(){super("animate")}get target(){return this.#t}set target(t){this.#t=t}}var ct=new dt;function ut(t){try{ct.time=t,window.dispatchEvent(ct),ht.forEach((t=>{t.update(),t.dispatchEvent(ct)})),ot&&ot(t),it&&it.update(),at&&at.update(),Q.render($,tt)}catch(t){throw Q.setAnimationLoop(null),t}}function pt(t){ot=t}console.time("TSL");var mt=0,wt=document.getElementById("spinner");wt&&setTimeout((()=>wt.style.display="none"),1e4);const gt=v((([t,e])=>e.smoothstep(t.x,t.y).smoothstep(0,1).smoothstep(0,1)),{edge:"vec2",value:"float",return:"float"});var _t=v((([t,e,s,i])=>{var r=t.y,o=t.z;return r=r.add(o.sub(e.z).div(i)),gt(s,r)}),{pos:"vec3",pivot:"vec3",rangeY:"vec2",slope:"float",return:"float"}),vt=v((([t,e])=>gt(e,t.x)),{pos:"vec3",rangeX:"vec2",return:"float"}),ft=v((([t,e,s,i])=>{var r=t.x,o=t.y,a=o.sub(e.y).div(4,r.sign());return gt(s,r.add(a)).mul(I(o.smoothstep(i.x,x(i.x,i.y,.2)),o.smoothstep(i.y,x(i.y,i.x,.2)))).pow(2)}),{pos:"vec3",pivot:"vec3",rangeX:"vec2",rangeY:"vec2",return:"float"}),yt=v((([t,e,s,i,r])=>{var o=t.x,a=t.y,n=t.z,h=y(o.mul(2),a,n.min(0)).sub(y(0,e.y,0)).length().smoothstep(0,k(.13).div(k(r).add(1))).pow(10),l=a.sub(o.abs().mul(.2));return l=l.add(X(r.equal(1),n.abs().mul(.5),n.mul(1/6))),h.mul(o.smoothstep(s.x,s.y),gt(i,l).pow(2))}),{pos:"vec3",pivot:"vec3",rangeX:"vec2",rangeY:"vec2",grown:"float",return:"float"});class xt{constructor(t){this.pivot=new d(...t),this.isRight=!1}mirror(){return this.isRight=!0,this.pivot.x*=-1,this.rangeX&&(this.rangeX.value.x*=-1,this.rangeX.value.y*=-1),this}}class bt extends xt{constructor(t,e,s=0){super(t),this.rangeY=z(...e),this.slope=Math.tan((90-s)*Math.PI/180)}locus(){return _t(b,this.pivot,this.rangeY,this.slope)}}class zt extends xt{constructor(t,e){super(t),this.rangeX=z(...e)}locus(){return vt(b,this.rangeX)}}class kt extends zt{constructor(t,e,s){super(t,e),this.rangeY=z(...s)}locus(){return mt++,wt&&mt>=12*ht.length&&(console.timeLog("TSL",mt),wt.style.display="none"),ft(b,this.pivot,this.rangeX,this.rangeY)}}class Mt extends kt{constructor(t,e,s,i=0){super(t,e,s),this.grown=i}locus(){return yt(b,this.pivot,this.rangeX,this.rangeY,this.grown)}}class St{constructor(t){var e={head:bt,chest:bt,waist:bt,torso:bt},s={knee:bt,ankle:bt,shin:bt,thigh:bt,foot:bt,leg:Mt,elbow:zt,forearm:zt,wrist:zt,arm:kt};for(var i in e)this[i]=new e[i](...t[i]);for(var i in s)this["l_"+i]=new s[i](...t[i]),this["r_"+i]=new s[i](...t[i]).mirror()}}var Et=new _;const Pt=import.meta.url.replace("/src/body.js","/assets/models/");var It=new d,Xt=t=>180*t/Math.PI,At=t=>t/180*Math.PI,Yt=t=>Math.round(100*t)/100;function jt(t,e,s,i){Object.defineProperty(t,e,{get:()=>Xt(i*t.rotation[s]),set(e){t.rotation[s]=At(i*e),t.quaternion.setFromEuler(t.rotation,!1)}})}class Ht extends w{constructor(t,e,s,i,r,o,a,n,h,l="XZY"){super(),this.model=t,this.model.joints.push(this),this.space=s,this.umatrix=A(new g),this.rotation.reorder(l),jt(this,"bend",i,a),jt(this,"turn",r,n),jt(this,"tilt",o,h),jt(this,"foreward",i,a),jt(this,"straddle",o,h),(e??t).add(this)}attach(t,e,s,i){t.parent&&(t=t.clone()),void 0!==e&&t.position.set(e,s,i),this.add(t)}point(t,e,s){return It.set(t,e,s),this.localToWorld(It)}lockTo(t,e,s,i,r,o){this.model.position.set(0,0,0),It=this.point(t,e,s),this.model.position.sub(It),It.set(i,r,o),this.model.position.add(It)}}var Lt=new c,Tt=1;class Ct extends a{constructor(t,e){var s,i=Pt+t.URL,r=t.SPACE,o=t.HEIGHT;for(var a in super(Lt),this.url=i,this.uid=Tt,Tt+=1+10*Math.random(),this.castShadow=!0,this.receiveShadow=!0,this.joints=[],this.height=e??o,this.scale.setScalar(this.height/o),Et.load(this.url,(t=>{this.geometry=t.scene.children[0].geometry})),this.space=new St(r),this.torso=new Ht(this,null,this.space.torso,"x","y","z",1,1,-1),this.waist=new Ht(this,this.torso,this.space.waist,"x","y","z",1,1,-1),this.chest=new Ht(this,this.waist,this.space.chest,"x","y","z",1,1,-1),this.head=new Ht(this,this.chest,this.space.head,"x","y","z",1,1,-1),this.l_leg=new Ht(this,this.torso,this.space.l_leg,"x","y","z",-1,1,1,"ZYX"),this.l_thigh=new Ht(this,this.l_leg,this.space.l_thigh,"x","y","z",0,1,0),this.l_knee=new Ht(this,this.l_thigh,this.space.l_knee,"x","y","z",1,0,-1),this.l_shin=new Ht(this,this.l_knee,this.space.l_shin,"x","y","z",0,1,0),this.l_ankle=new Ht(this,this.l_shin,this.space.l_ankle,"x","y","z",1,0,1),this.l_foot=new Ht(this,this.l_ankle,this.space.l_foot,"x","y","z",1,0,0),this.r_leg=new Ht(this,this.torso,this.space.r_leg,"x","y","z",-1,-1,-1,"ZYX"),this.r_thigh=new Ht(this,this.r_leg,this.space.r_thigh,"x","y","z",0,-1,0),this.r_knee=new Ht(this,this.r_thigh,this.space.r_knee,"x","y","z",1,0,1),this.r_shin=new Ht(this,this.r_knee,this.space.r_shin,"x","y","z",0,-1,0),this.r_ankle=new Ht(this,this.r_shin,this.space.r_ankle,"x","y","z",1,0,-1),this.r_foot=new Ht(this,this.r_ankle,this.space.r_foot,"x","y","z",1,0,0),this.l_arm=new Ht(this,this.chest,this.space.l_arm,"y","x","z",-1,1,-1,"ZYX"),this.l_elbow=new Ht(this,this.l_arm,this.space.l_elbow,"y","x","z",-1,0,0),this.l_forearm=new Ht(this,this.l_elbow,this.space.l_forearm,"z","x","y",0,1,0),this.l_wrist=new Ht(this,this.l_forearm,this.space.l_wrist,"z","x","y",-1,0,-1),this.r_arm=new Ht(this,this.chest,this.space.r_arm,"y","x","z",1,1,1,"ZYX"),this.r_elbow=new Ht(this,this.r_arm,this.space.r_elbow,"y","x","z",1,0,0),this.r_forearm=new Ht(this,this.r_elbow,this.space.r_forearm,"z","x","y",0,1,0),this.r_wrist=new Ht(this,this.r_forearm,this.space.r_wrist,"z","x","y",1,0,1),this.material=new u({positionNode:(s=this,nt(s,F,b)),normalNode:K(this),colorNode:y(.99,.65,.49),metalness:0,roughness:.6}),this.position.y=0,this.castShadow=!0,this.receiveShadow=!0,ht.push(this),$&&$.add(this),this.l_arm.straddle=this.r_arm.straddle=65,this.l_elbow.bend=this.r_elbow.bend=20,this.space)this[a]&&this[a].position.copy(this.space[a].pivot);this.reposition(this.torso)}reposition(t){for(var e of t.children)this.reposition(e);t.position.sub(t.parent.position)}update(){for(var t of this.joints){var e=t.matrix.elements;t.umatrix.value.set(e[0],e[1],e[2],e[4],e[5],e[6],e[8],e[9],e[10])}}get posture(){var t=[];for(var e of this.joints)t.push(e.rotation.x,e.rotation.y,e.rotation.z);var s=[...this.position],i=[...this.rotation];return{version:8,position:s.map((t=>Yt(t))),rotation:i,angles:t.map((t=>Yt(Xt(t))))}}get postureString(){return JSON.stringify(this.posture)}set posture(t){8!=t.version&&console.error("Incompatible posture version");var e=t.angles.map((t=>At(t)));this.position.set(...t.position),this.rotation.set(...t.rotation);var s=0;for(var i of this.joints)i.rotation.set(e[s++],e[s++],e[s++]);this.update(),this.updateMatrixWorld(!0)}blend(t,e,s){function i(t,e){for(var i=[],r=0;r<t.length;r++)i[r]=m.lerp(t[r],e[r],s);return i}var r=new p(...t.rotation),o=new p(...e.rotation);r.reorder(o.order);var a={version:t.version,position:i(t.position,e.position),rotation:new p(...i([r.x,r.y,r.z],[o.x,o.y,o.z])),angles:i(t.angles,e.angles)};this.posture=a}dress(t){var e=U(t).toVar();this.material.colorNode=e[0].xyz,this.material.roughnessNode=e[1].x,this.material.metalnessNode=e[1].y}}class Nt extends Ct{static URL="man.glb";static HEIGHT=1.795;static SPACE={head:[[0,1.566,-.066],[1.495,1.647],30],chest:[[0,1.177,-.014],[.777,1.658],0,[.072,.538]],waist:[[0,1.014,-.016],[.547,1.498]],torso:[[0,1.014,-.016],[-3,-2]],leg:[[.074,.97,-.034],[-.004,.004],[1.229,.782]],thigh:[[.07,.737,-.034],[1.247,.242]],knee:[[.09,.504,-.041],[.603,.382],20],ankle:[[.074,.082,-.002],[.165,.008],-10],shin:[[.092,.36,-.052],[.762,-.027]],foot:[[.074,.026,.022],[.19,-.342],120],elbow:[[.427,1.453,-.072],[.413,.467]],forearm:[[.55,1.453,-.068],[.083,.879]],wrist:[[.673,1.462,-.072],[.635,.722]],arm:[[.153,1.408,-.072],[.054,.269],[1.067,1.616]]};constructor(t){super(Nt,t),this.l_leg.straddle=this.r_leg.straddle=5,this.l_ankle.tilt=this.r_ankle.tilt=-5,this.l_ankle.bend=this.r_ankle.bend=3}}class Vt extends Ct{static URL="woman.glb";static HEIGHT=1.691;static SPACE={head:[[.001,1.471,-.049],[1.395,1.551],30],chest:[[.001,1.114,-.012],[.737,1.568],0,[.069,.509]],waist:[[.001,.961,-.014],[.589,1.417]],torso:[[.001,.961,-.014],[-1.696,-1.694]],leg:[[.071,.92,-.031],[-.002,.005],[1.163,.742]],thigh:[[.076,.7,-.031],[1.18,.233]],knee:[[.086,.48,-.037],[.573,.365],20],shin:[[.088,.337,-.047],[.724,-.059]],ankle:[[.076,.083,-.005],[.161,.014],-10],foot:[[.076,.031,.022],[.184,-.316],120],elbow:[[.404,1.375,-.066],[.39,.441]],forearm:[[.506,1.375,-.063],[.093,.805]],wrist:[[.608,1.375,-.056],[.581,.644]],arm:[[.137,1.338,-.066],[.052,.233],[1.011,1.519]]};constructor(t){super(Vt,t),this.l_leg.straddle=this.r_leg.straddle=-2.9,this.l_ankle.tilt=this.r_ankle.tilt=2.9,this.l_ankle.bend=this.r_ankle.bend=3}}class Rt extends Ct{static URL="child.glb";static HEIGHT=1.352;static SPACE={head:[[0,1.149,-.058],[1.091,1.209],30],chest:[[0,.865,-.013],[.566,1.236],0,[.054,.406]],waist:[[0,.717,-.024],[.385,1.13]],torso:[[0,.717,-.024],[-1.354,-1.353]],leg:[[.054,.704,-.027],[-.001,.001],[.845,.581],1],thigh:[[.062,.547,-.021],[.946,.189]],knee:[[.068,.389,-.031],[.468,.299],20],shin:[[.069,.272,-.048],[.581,-.045]],ankle:[[.073,.065,-.033],[.109,.044],-10],foot:[[.073,.027,-.006],[.112,-.271],120],elbow:[[.337,1.072,-.09],[.311,.369]],forearm:[[.438,1.074,-.094],[.073,.642]],wrist:[[.538,1.084,-.091],[.519,.553]],arm:[[.108,1.072,-.068],[.041,.185],[.811,1.217]]};constructor(t){super(Rt,t),this.l_ankle.bend=this.r_ankle.bend=3}}console.log("\n%c⋮⋮⋮ Disfigure\n%chttps://boytchev.github.io/disfigure/\n","color: navy","font-size:80%");export{Rt as Child,Nt as Man,Vt as Woman,lt as World,q as bands,tt as camera,st as cameraLight,B as chaotic,it as controls,ht as everybody,rt as ground,R as latex,et as light,D as random,O as regular,Q as renderer,$ as scene,pt as setAnimationLoop,G as slice,W as velour};