javascriptthree.jsblenderskeletal-mesh

Three.js - Animation is not playing


I have problem with animating object exported via blender plugin from blender to THREE.js. Animation did not start running...

Of course, I tried many combinations of settings when exporting from blender and importing to THREE.js library, but without success.

Here is code, what I think should work. Comment Critical section annotate where is probably some mistake. Link to source JSON is in the example too. Of course, I can provide source *.blend file, if needed...

var tgaLoader = new THREE.TGALoader();
var objectLoader = new THREE.ObjectLoader();

var clock = new THREE.Clock();

var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;

renderer = new THREE.WebGLRenderer({ antialias: true });

renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
document.getElementById('container').appendChild(renderer.domElement);

objectLoader.load('//cdn.rawgit.com/PiranhaGreg/files/master/scavenger.json', function (loadedScene) {
  scene = loadedScene;
  mesh = scene.children[0];

  scene.background = new THREE.Color('white');
  mesh.material = new THREE.MeshPhongMaterial({ map: tgaLoader.load('//cdn.rawgit.com/PiranhaGreg/files/master/SCA_BODY_V0.TGA') });

  hemiLight = new THREE.HemisphereLight('white', 'white', 0.6);
  scene.add(hemiLight);

  camera = new THREE.PerspectiveCamera(30, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000);
  camera.position.set(500, 200, -100);

  controls = new THREE.OrbitControls(camera);
  controls.target.set(0, 50, 0);
  controls.update();

  var geometry = new THREE.PlaneBufferGeometry(200, 200);
  var material = new THREE.MeshPhongMaterial({ shininess: 0.1 });
  var ground = new THREE.Mesh(geometry, material);

  ground.rotation.x = - Math.PI / 2;

  scene.add(ground);

  mesh.scale.set(-1, -1, 1);

  // Critical section...
  mixer = new THREE.AnimationMixer(mesh);
  var sequence = THREE.AnimationClip.CreateFromMorphTargetSequence('animation', mesh.geometry.morphTargets, 25, true);
  var animation = mixer.clipAction(sequence);
  animation.play();
  // End of critital section

  animate();
});

window.onresize = function() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();

  renderer.setSize(window.innerWidth, window.innerHeight);
};

function animate() {
  requestAnimationFrame(animate);
  render();
}

function render() {
  var delta = 0.75 * clock.getDelta();
  mixer.update(delta);
  renderer.render(scene, camera);
}
body {
  margin: 0px;
  overflow: hidden;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/three.js/87/three.min.js"></script>
<script src="//cdn.rawgit.com/mrdoob/three.js/master/examples/js/loaders/TGALoader.js" type="application/javascript"></script>
<script src="//cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>
<div id="container"></div>

Thanks for any suggestion.


Solution

  • I dug in into animation and noticed that it uses morphTargets. And then I remembered about this example. So, the key moment is to set .morphTarget parameter of a material to true, so, I've applied it to the material in your code snippet and it started to work:

    mesh.material = new THREE.MeshPhongMaterial({
        map: tgaLoader.load('//cdn.rawgit.com/PiranhaGreg/files/master/SCA_BODY_V0.TGA'),
        morphTargets: true
    }); 
    

    Though, I'm not sure, if such an approach is correct, but, at least, it's working )

    var tgaLoader = new THREE.TGALoader();
    var objectLoader = new THREE.ObjectLoader();
    
    var clock = new THREE.Clock();
    
    var SCREEN_WIDTH = window.innerWidth;
    var SCREEN_HEIGHT = window.innerHeight;
    
    renderer = new THREE.WebGLRenderer({ antialias: true });
    
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
    document.getElementById('container').appendChild(renderer.domElement);
    
    objectLoader.load('//cdn.rawgit.com/PiranhaGreg/files/master/scavenger.json', function (loadedScene) {
      scene = loadedScene;
      mesh = scene.children[0];
    
      scene.background = new THREE.Color('white');
      mesh.material = new THREE.MeshPhongMaterial({ map: tgaLoader.load('//cdn.rawgit.com/PiranhaGreg/files/master/SCA_BODY_V0.TGA'), morphTargets: true });
    
      hemiLight = new THREE.HemisphereLight('white', 'white', 0.6);
      scene.add(hemiLight);
    
      camera = new THREE.PerspectiveCamera(30, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000);
      camera.position.set(500, 200, -100);
    
      controls = new THREE.OrbitControls(camera);
      controls.target.set(0, 50, 0);
      controls.update();
    
      var geometry = new THREE.PlaneBufferGeometry(200, 200);
      var material = new THREE.MeshPhongMaterial({ shininess: 0.1 });
      var ground = new THREE.Mesh(geometry, material);
    
      ground.rotation.x = - Math.PI / 2;
    
      scene.add(ground);
    
      mesh.scale.set(-1, -1, 1);
    
      // Critical section...
      mixer = new THREE.AnimationMixer(mesh);
      var sequence = THREE.AnimationClip.CreateFromMorphTargetSequence('animation', mesh.geometry.morphTargets, 25, true);
      var animation = mixer.clipAction(sequence);
      animation.play();
      // End of critital section
    
      animate();
    });
    
    window.onresize = function() {
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
    
      renderer.setSize(window.innerWidth, window.innerHeight);
    };
    
    function animate() {
      requestAnimationFrame(animate);
      render();
    }
    
    function render() {
      var delta = 0.75 * clock.getDelta();
      mixer.update(delta);
      renderer.render(scene, camera);
    }
    body {
      margin: 0px;
      overflow: hidden;
    }
    <script src="//cdnjs.cloudflare.com/ajax/libs/three.js/87/three.min.js"></script>
    <script src="//cdn.rawgit.com/mrdoob/three.js/master/examples/js/loaders/TGALoader.js" type="application/javascript"></script>
    <script src="//cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>
    <div id="container"></div>