Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Animation beta #1341

Merged
merged 16 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
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
Loading