1
votes

i am working with THREE.js for a while now and i am really enjoying it, except for one thing: bringing animated graphics from Blender to the game scene. After trying to solve it by myself and searching for a while, i ask my questions here. To put it bluntly, i am only a coder, not a graphic expert and i am not creating the blender-contents myself.

1. Is there anything special to know (or broken?) with exporting BufferGeometry with the THREE.js Blender exporter in the current version 86? When using BufferGeometry as export option, my filesize grows by factor 3, but no animations are included in the resulting .json file. Using the same options except for "Geometry" instead of "BufferGeometry" includes the animations and gives a smaller file size (exporter options and sample files below).

2. What could be the problem with a correct? .json not playing the animation in THREE.js? I have a working example (the Slimeblob) which can be exported, loaded and animated. Using the same code, most of my other animated models are loaded, but not animated. For example, i have a very simple cube with a short animation which is not played in THREE.js but with animation data in the .json (as well as in the runtime environment). .blend files and code below. That the animation is somehow loaded can be seen in the console output (at least in chrome browser).

Example Demonstration:

<!doctype html>
<html lang="en">
<head>
    <title>Animation Test</title>
    <style> body { padding: 0; margin: 0; overflow: hidden; } </style>
</head>
<body>

<script src="three.js"></script>
<script src="OrbitControls.js"></script>
<script>

var gameScene, gameCamera, renderer;
var clock = new THREE.Clock();
var delta;
var controls;

var jsonLoader = new THREE.JSONLoader();

var SlimeblobGeometry, SlimeblobGeometryAnimationMixer;
var AnimationExport, AnimationExportAnimationMixer;

init();

function init() {
    var windowHeight = window.innerHeight;
    var windowWidth = window.innerWidth;

    gameCamera = new THREE.PerspectiveCamera( 60, windowWidth / windowHeight, 1, 2100 );
    gameCamera.position.set( 0, 11, 11 );
    gameCamera.lookAt( new THREE.Vector3( 0, 0, 0 ) );

    gameScene = new THREE.Scene();

    renderer = new THREE.WebGLRenderer( { antialias: true } );
    renderer.setSize( windowWidth, windowHeight );
    renderer.setClearColor( 0xB2DFEE );
    document.body.appendChild( renderer.domElement );

    var light = new THREE.HemisphereLight( 0xffffff, 0x003300, 1 );
    light.position.set( -80, 500, 50 );
    gameScene.add( light );

    controls = new THREE.OrbitControls( gameCamera, renderer.domElement );

    jsonLoader.load( "SlimeblobGeometry.json",
                     function ( geometry, materials ) {
                         for ( var k in materials ) {
                             materials[ k ].skinning = true;
                         }
                         SlimeblobGeometry = new THREE.SkinnedMesh( geometry, materials );
                         SlimeblobGeometry.position.x = 5;
                         gameScene.add( SlimeblobGeometry );
                         SlimeblobGeometryAnimationMixer = new THREE.AnimationMixer( SlimeblobGeometry );
                         SlimeblobGeometryAnimationMixer.clipAction( SlimeblobGeometry.geometry.animations[ 0 ] ).play();
                     }
    );

    jsonLoader.load( "AnimationExport.json",
                     function ( geometry ) {
                         AnimationExport = new THREE.SkinnedMesh( geometry, new THREE.MeshLambertMaterial( { color: 0x436EEE } ) );
                         AnimationExport.position.x = -5;
                         gameScene.add( AnimationExport );
                         AnimationExportAnimationMixer = new THREE.AnimationMixer( AnimationExport );
                         AnimationExportAnimationMixer.clipAction( AnimationExport.geometry.animations[ 0 ] ).play();
                         console.log( AnimationExport.geometry.animations[ 0 ] ); /* Chrome Browser may be necessary for meaningful output */
                    }
    );

    updateFrame();
}

function updateFrame() {
    requestAnimationFrame( updateFrame );
    delta = clock.getDelta();

    if ( SlimeblobGeometryAnimationMixer ) {
        SlimeblobGeometryAnimationMixer.update( delta );
    }
    if ( AnimationExportAnimationMixer ) {
        AnimationExportAnimationMixer.update( delta );
    }

    controls.update();

    renderer.render( gameScene, gameCamera );
}

</script>

</body>
</html>

The code runs without errors and both models are loaded. The slime is animated properly, the cube is not. What am i missing?

The export settings (same for both)

Environment Details:

  • THREE.js Revision 86 (up-2-date at this time)
  • THREE.js Blender Exporter from Revision 86
  • Blender Version 2.77

Working Example: the code from above and the .json's and .blend's (directly working locally except for the cross-origin-policy blocks):

AnimationTest.7z

So far from me for now, thanks and best regards!

1

1 Answers

1
votes

Assign skinning: true to your cubes material, that solved it for me:

AnimationExport = new THREE.SkinnedMesh( geometry, new THREE.MeshLambertMaterial( { color: 0x436EEE, skinning: true } ) );

SkinnedMesh Animations and threejs were a pain to deal with, but got some love lately. That also means the animation system API is changing from time to time so I recommend reading through the issues and PRs on github :-)