17

Is it possible to create a dynamic animation by applying transformations to the bones of a 3D model using three.js? I tried moving and rotating the bones of a SkinnedMesh, but the mesh was not updated.

        loader = new THREE.JSONLoader();
        loader.load('/JS-Projects/Virtual-Jonah/Modelos/initialPose.js',function jsonReady( geometry )
        {
            mesh = new THREE.SkinnedMesh( geometry, new THREE.MeshNormalMaterial({skinning : true}) );
            mesh.scale.set( 10, 10, 10 );
            mesh.position.z = mesh.position.y = mesh.position.x = 0;
            mesh.geometry.dynamic = true;
            scene.add( mesh );

            var index = 0;
            for (var i = 0; i < mesh.bones.length; i++)
            {
                if (mesh.bones[i].name == "forearm_R")
                {
                    index = i;
                    break;
                }
            }


            setInterval (function ()
            {
                mesh.bones[index].useQuaternion = false;
                mesh.bones[index].position.z += 10;     
                mesh.bones[index].matrixAutoUpdate = true;
                mesh.bones[index].matrixWorldNeedsUpdate = true;
                mesh.geometry.verticesNeedUpdate = true;
                mesh.geometry.normalsNeedUpdate = true;

                renderer.render(scene, camera);
            }, 33);

            renderer.render(scene, camera);
        });

The model I am using was created with makeHuman (nightly build), exported to Collada, imported in Blender and exported to the three.js JSON model. The link to the model is the following:

https://www.dropbox.com/sh/x1606vnaoghes1y/gG_BcZcEKd/initial

Thank you!

Fabio Picchi
  • 1,202
  • 2
  • 10
  • 22
  • I guess the mesh needs to be updated according to new bone position. The method animation.update() may contain the answer. Otherwise, I found the method mesh.updateMorphTargets() and also Bone.update() that might help... – Charles HETIER Apr 28 '14 at 10:10
  • Is this specific to both three.js *and* Unity? Some of the answers seem to indicate it is. – Kenny Evitt Nov 29 '17 at 17:03

3 Answers3

15

Yes, you can! You need to set mesh.skeleton.bones[i], both mesh.skeleton.bones[i].rotation and mesh.skeleton.bones[i].position. Rotation is of type Euler. Position is of type Vector3. I have actually tested this using my code from here https://github.com/lucasdealmeidasm/three-mm3d (that includes a working skinned mesh with bone-attachable objects) and one can indeed do that.

Note that Inateno's answer is very wrong, there are many instances where this is necessary. For example, in a FPS, one uses both dynamic and non-dynamic animation. When a character runs and holds a gun, the direction he points the gun at is dynamically set (one could use mesh.skeleton.bones[i].rotation where "i" is the index for bone assigned to the arm for that) while the rest of the animation, including the walking, is made in the editor and loaded. One can, in three.js, use "THREE.AnimationHandler.update(delta);" and then change single bones' position and rotation in code to solve those issues.

Kenny Evitt
  • 9,291
  • 5
  • 65
  • 93
kdrnic
  • 501
  • 3
  • 5
  • Thank you Lucas, perfect answer! I was able to make it work now :) – Fabio Picchi Oct 17 '14 at 02:36
  • 1
    @ProllyGeek I'm sorry, I'm not used to making posts. It is now marked as corret answer =) – Fabio Picchi Feb 11 '15 at 17:04
  • @FábioPicchi glad you did , also glad you could find an answer :) – ProllyGeek Feb 11 '15 at 19:45
  • After exporting to Three.js, my mesh doesn't have a `skeleton` property. Instead it has a `geometry` property which has `pos` and `rotq` properties, both of which are arrays. Will this still work if I modify those values? Any idea why my export is different than yours? – adam0101 Mar 27 '15 at 21:42
  • I think I just figured it out myself. Just had to change my Three.Mesh into a Three.SkinnedMesh. – adam0101 Mar 27 '15 at 21:53
  • @Lucas, mesh.skeleton.bones[i].rotation and mesh.skeleton.bones[i].location seem to be doing the same thing. I was expecting mesh.skeleton.bones[i].location to move the bone accordingly. Do you know how to achieve that? Thanks. – June Wang Sep 09 '18 at 02:56
  • Do you think you would be able to answer my question ? : https://stackoverflow.com/questions/60036248/how-to-manipulate-individual-bones-of-a-3d-model-in-react-native I want to import a 3d model of a humanoid skeleton and dynamically set the position of hands, legs etc at run time by supplying quaternion. As I am new to react-native, I haven't been able to find the right API yet. – Rahul Iyer Feb 18 '20 at 09:00
-1

I know you can export a bone driven animation from Blender in JSON format, for use in THREE.js, there are a few tutorials of that around the web. I hope this helps. Good Luck.

Ryan Blevins
  • 166
  • 1
  • 9
-6

If I understund you want to create animations yourself inside the code ? You are note supposed to do this, in Unity you have a simple animation editor, you never manipulate bones directly in code.

It's long, boring, unperforming. To animate a model use animation directly. Here's a result of animation with some bones manipulation but there is an animation over.

http://threejs.org/examples/webgl_animation_skinning_morph.html

Here is a tutorial about making simple animation if you need http://blog.romanliutikov.com/post/60461559240/rigging-and-skeletal-animation-in-three-js

And here a related post about animations problems just in case Blender exports a three.js animation - bones rotate strangely

Hope this will help you :)

Community
  • 1
  • 1
Inateno
  • 115
  • 5
  • Sorry, I disagree. You're right in most of the basic cases, but since you need to make some advanced animations with reverse kinematic (to avoid moon walk, feet full contact) you necessarly need to apply dynamic rules to the bones, thus, make the code manage at least part of the skeleton; even using Unity – Charles HETIER Apr 28 '14 at 10:02