Skip to content

Commit

Permalink
Merge pull request #1341 from pixiv/animation-beta
Browse files Browse the repository at this point in the history
Animation beta
0b5vr authored Feb 15, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
2 parents c761707 + 1d5977b commit 5567cc1
Showing 32 changed files with 1,489 additions and 13 deletions.
3 changes: 0 additions & 3 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -24,9 +24,6 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
with:
# checkout is pinned to dev branch here
ref: dev
- name: Setup Node
uses: actions/setup-node@v3
with:
9 changes: 9 additions & 0 deletions packages/three-vrm-animation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# @pixiv/three-vrm-animation

The implementation of VRM Animation

[GitHub Repository](https://github.com/pixiv/three-vrm/tree/dev/packages/three-vrm-animation)

[Examples](https://pixiv.github.io/three-vrm/packages/three-vrm-animation/examples)

[Documentation](https://pixiv.github.io/three-vrm/packages/three-vrm-animation/docs)
2 changes: 2 additions & 0 deletions packages/three-vrm-animation/examples/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[*]
indent_style = tab
11 changes: 11 additions & 0 deletions packages/three-vrm-animation/examples/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"root": true,
"plugins": [
"html"
],
"extends": "mdcs",
"rules": {
"padded-blocks":"off",
"no-unused-vars": "off"
}
}
281 changes: 281 additions & 0 deletions packages/three-vrm-animation/examples/dnd.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,281 @@
<!DOCTYPE html>

<html>
<head>
<meta charset="utf-8" />
<title>three-vrm-animation example</title>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<style>
body {
margin: 0;
}
canvas {
display: block;
}
</style>
</head>

<body>
<!-- Import maps polyfill -->
<!-- Remove this when import maps will be widely supported -->
<script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script>

<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/",
"@pixiv/three-vrm": "https://unpkg.com/@pixiv/three-vrm@2.0.8/lib/three-vrm.module.js",
"@pixiv/three-vrm-animation": "../lib/three-vrm-animation.module.js"
}
}
</script>

<script type="module">
import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import GUI from 'three/addons/libs/lil-gui.module.min.js';
import { VRMLoaderPlugin, VRMUtils } from '@pixiv/three-vrm';
import { createVRMAnimationClip, VRMAnimationLoaderPlugin, VRMLookAtQuaternionProxy } from '@pixiv/three-vrm-animation';

// renderer
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setPixelRatio( window.devicePixelRatio );
document.body.appendChild( renderer.domElement );

// camera
const camera = new THREE.PerspectiveCamera( 30.0, window.innerWidth / window.innerHeight, 0.1, 20.0 );
camera.position.set( 0.0, 1.0, 5.0 );

// camera controls
const controls = new OrbitControls( camera, renderer.domElement );
controls.screenSpacePanning = true;
controls.target.set( 0.0, 1.0, 0.0 );
controls.update();

// scene
const scene = new THREE.Scene();

// light
const light = new THREE.DirectionalLight( 0xffffff, Math.PI );
light.position.set( 1.0, 1.0, 1.0 ).normalize();
scene.add( light );

// gltf, vrm, and vrma
let currentVrm = undefined;
let currentVrmAnimation = undefined;
let currentMixer = undefined;

const loader = new GLTFLoader();
loader.crossOrigin = 'anonymous';

loader.register( ( parser ) => {

return new VRMLoaderPlugin( parser );

} );

loader.register( ( parser ) => {

return new VRMAnimationLoaderPlugin( parser );

} );

function tryInitVRM( gltf ) {

const vrm = gltf.userData.vrm;

if ( vrm == null ) {

return;

}

// calling these functions greatly improves the performance
VRMUtils.removeUnnecessaryVertices( gltf.scene );
VRMUtils.removeUnnecessaryJoints( gltf.scene );

if ( currentVrm ) {

scene.remove( currentVrm.scene );
VRMUtils.deepDispose( currentVrm.scene );

}

// Add look at quaternion proxy to the VRM; which is needed to play the look at animation
const lookAtQuatProxy = new VRMLookAtQuaternionProxy( vrm.lookAt );
lookAtQuatProxy.name = 'lookAtQuaternionProxy';
vrm.scene.add( lookAtQuatProxy );

// Disable frustum culling
vrm.scene.traverse( ( obj ) => {

obj.frustumCulled = false;

} );

currentVrm = vrm;
scene.add( vrm.scene );

// rotate if the VRM is VRM0.0
VRMUtils.rotateVRM0( vrm );

initAnimationClip();

console.log( vrm );

}

function tryInitVRMA( gltf ) {

const vrmAnimations = gltf.userData.vrmAnimations;

if ( vrmAnimations == null ) {

return;

}

currentVrmAnimation = vrmAnimations[ 0 ] ?? null;
initAnimationClip();

console.log( vrmAnimations );

}

function initAnimationClip() {

if ( currentVrm && currentVrmAnimation ) {

currentMixer = new THREE.AnimationMixer( currentVrm.scene );

const clip = createVRMAnimationClip( currentVrmAnimation, currentVrm );
currentMixer.clipAction( clip ).play();
currentMixer.timeScale = params.timeScale;

currentVrm.humanoid.resetNormalizedPose();
// currentVrm.expressions.resetAll(); // will implement later
currentVrm.lookAt.reset();
currentVrm.lookAt.autoUpdate = currentVrmAnimation.lookAtTrack != null;

}

}

function load( url ) {

loader.load(

url,

( gltf ) => {

tryInitVRM( gltf );
tryInitVRMA( gltf );

},

( progress ) => console.log( 'Loading model...', 100.0 * ( progress.loaded / progress.total ), '%' ),

( error ) => console.error( error )

);

}

load( './models/VRM1_Constraint_Twist_Sample.vrm' );
load( './models/test.vrma' );

// helpers
const gridHelper = new THREE.GridHelper( 10, 10 );
scene.add( gridHelper );

const axesHelper = new THREE.AxesHelper( 5 );
scene.add( axesHelper );

// animate
const clock = new THREE.Clock();
clock.start();

function animate() {

requestAnimationFrame( animate );

const deltaTime = clock.getDelta();

if ( currentMixer ) {

currentMixer.update( deltaTime );

}

if ( currentVrm ) {

currentVrm.update( deltaTime );

}

renderer.render( scene, camera );

}

animate();

// gui
const gui = new GUI();

const params = {

timeScale: 1.0,

};

gui.add( params, 'timeScale', 0.0, 2.0, 0.001 ).onChange( ( value ) => {

if ( currentMixer ) {

currentMixer.timeScale = value;

}

} );

// dnd handler
window.addEventListener( 'dragover', function ( event ) {

event.preventDefault();

} );

window.addEventListener( 'drop', function ( event ) {

event.preventDefault();

// read given file then convert it to blob url
const files = event.dataTransfer.files;
if ( ! files ) {

return;

}

const file = files[ 0 ];
if ( ! file ) {

return;

}

const blob = new Blob( [ file ], { type: "application/octet-stream" } );
const url = URL.createObjectURL( blob );
load( url );

} );
</script>
</body>
</html>
24 changes: 24 additions & 0 deletions packages/three-vrm-animation/examples/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!DOCTYPE html>

<html>
<head>
<meta charset="utf-8" />
<title>three-vrm-animation examples</title>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
</head>

<body>
<h1>examples of <a href="https://github.com/pixiv/three-vrm/tree/dev/packages/three-vrm-animation">@pixiv/three-vrm-animation</a></h1>
<p>
<a href="loader-plugin.html">loader-plugin.html</a><br />
Import a VRM Animation from gltf
</p>
<p>
<a href="dnd.html">dnd.html</a><br />
A slightly advanced example with a drag-and-drop capability
</p>
</body>
</html>
Loading

0 comments on commit 5567cc1

Please sign in to comment.