AshenDepths / clips.html
Quazim0t0's picture
Deploy Ashen Depths: player animated by skeleton_animator.pt
ee5ec19 verified
Raw
History Blame Contribute Delete
4.22 kB
<!DOCTYPE html><html><head><meta charset="utf-8"><title>player clips</title>
<style>html,body{margin:0;height:100%;background:#202028;overflow:hidden}
#hud{position:fixed;top:0;left:0;color:#0f0;font:12px monospace;z-index:9;padding:6px;background:#000a;white-space:pre}</style>
<script type="importmap">{"imports":{
"three":"https://unpkg.com/three@0.160.0/build/three.module.js",
"three/addons/":"https://unpkg.com/three@0.160.0/examples/jsm/",
"fflate":"https://unpkg.com/fflate@0.8.2/esm/browser.js"
}}</script></head>
<body><div id="hud">loading…</div>
<script type="module">
import * as THREE from 'three';
import {FBXLoader} from 'three/addons/loaders/FBXLoader.js';
const hud=document.getElementById('hud');
const renderer=new THREE.WebGLRenderer({antialias:true});
renderer.setPixelRatio(Math.min(devicePixelRatio,1.5));renderer.setSize(innerWidth,innerHeight);
renderer.shadowMap.enabled=true;document.body.appendChild(renderer.domElement);
const scene=new THREE.Scene();scene.background=new THREE.Color(0x202028);
scene.add(new THREE.HemisphereLight(0xffffff,0x445,1.3));
const dl=new THREE.DirectionalLight(0xffffff,2.2);dl.position.set(3,8,6);scene.add(dl);
const cam=new THREE.PerspectiveCamera(45,innerWidth/innerHeight,0.05,100);
scene.overrideMaterial=new THREE.MeshStandardMaterial({color:0xbfc4cc,roughness:.7});
const fbx=new FBXLoader();
let mixer,clips,root,cur=0,action;
fbx.load('assets/chars/player.fbx',obj=>{
root=obj;clips=obj.animations;
const box=new THREE.Box3().setFromObject(obj);const s=new THREE.Vector3();box.getSize(s);
const sc=1.8/s.y;obj.scale.setScalar(sc);obj.position.y=-box.min.y*sc;
scene.add(obj);
cam.position.set(0,1.1,3.4);cam.lookAt(0,1.0,0);
mixer=new THREE.AnimationMixer(obj);
window.__clip=(i)=>{cur=i;if(action)action.stop();action=mixer.clipAction(clips[i]);action.reset().play();
return {i,name:clips[i].name,dur:+clips[i].duration.toFixed(2)};};
window.__list=()=>clips.map((c,i)=>({i,name:c.name,dur:+c.duration.toFixed(2)}));
window.__seek=(t)=>{action.time=t;mixer.update(0);return action.time;};
const bn={};obj.traverse(o=>{if(o.isBone)bn[o.name]=o;});
const H=bn['mixamorigHips'],HEAD=bn['mixamorigHead'],RH=bn['mixamorigRightHand'],LH=bn['mixamorigLeftHand'],RF=bn['mixamorigRightFoot'];
const wp=(b)=>b.getWorldPosition(new THREE.Vector3());
window.__analyze=()=>{
const res=[];
for(let i=0;i<clips.length;i++){
const c=clips[i];if(c.duration<0.1){res.push({i,dur:+c.duration.toFixed(2),skip:1});continue;}
const a=mixer.clipAction(c);mixer.stopAllAction();a.reset().play();
let hipXZ=[1e9,-1e9,1e9,-1e9],hipY=[1e9,-1e9],headY=[1e9,-1e9],handAbove=-1e9,footY=[1e9,-1e9],tiltMax=0;
const N=24;
for(let k=0;k<=N;k++){a.time=c.duration*k/N;mixer.update(0);obj.updateMatrixWorld(true);
const h=wp(H),hd=wp(HEAD),rh=wp(RH),lh=wp(LH),rf=wp(RF);
hipXZ[0]=Math.min(hipXZ[0],h.x);hipXZ[1]=Math.max(hipXZ[1],h.x);hipXZ[2]=Math.min(hipXZ[2],h.z);hipXZ[3]=Math.max(hipXZ[3],h.z);
hipY[0]=Math.min(hipY[0],h.y);hipY[1]=Math.max(hipY[1],h.y);
headY[0]=Math.min(headY[0],hd.y);headY[1]=Math.max(headY[1],hd.y);
handAbove=Math.max(handAbove,rh.y-h.y,lh.y-h.y);
footY[0]=Math.min(footY[0],rf.y);footY[1]=Math.max(footY[1],rf.y);
const tv=hd.clone().sub(h);const tilt=Math.acos(Math.max(-1,Math.min(1,tv.y/tv.length())));tiltMax=Math.max(tiltMax,tilt);
}
res.push({i,dur:+c.duration.toFixed(2),
rootXZ:+Math.max(hipXZ[1]-hipXZ[0],hipXZ[3]-hipXZ[2]).toFixed(2),
hipYr:+(hipY[1]-hipY[0]).toFixed(2),
headMin:+headY[0].toFixed(2),
handAbove:+handAbove.toFixed(2),
footYr:+(footY[1]-footY[0]).toFixed(2),
tiltDeg:+(tiltMax*180/Math.PI).toFixed(0)});
}
mixer.stopAllAction();window.__clip(cur);
return res;
};
window.__clip(0);
hud.textContent='ready: '+clips.length+' clips. __clip(i) __seek(t)';
let last=performance.now();
(function loop(now){requestAnimationFrame(loop);const dt=(now-last)/1000;last=now;
if(mixer)mixer.update(dt);renderer.render(scene,cam);})(performance.now());
},undefined,e=>hud.textContent='ERR '+(e.message||e));
</script></body></html>