Three.js: Blender exporter not exporting model with animation at all

Created on 19 Apr 2016  路  27Comments  路  Source: mrdoob/three.js

Description of the problem

three.js blender exporter is not creating a .json file for a rigged(/animated) blender model.

I have attached the settings I am using to export the files, as well as my export settings. Blender will perfectly export the generic blender cube (when creating a new file), but will not even create a .json for both attached files.

I am trying to export to the path C:\Users\Doug\Desktop\Blender Objs\OUT.json

Three.js version

r75

Blender Version

2.77

OS

Windows

Person & PersonAnim (Blender .zip) (Neither export with default settings, ignoring animation)

settings

Most helpful comment

Also to help navigate the maze, here's some other things I've discovered:

Sorry to dump this all in a specific ticket. I plan to write a blog post about this process because it's really difficult to navigate right now.

All 27 comments

Animation export seems to be disabled in the settings above.

There were many issues with the exporter in r75 and some of them have recently been fixed. Would you mind trying the dev branch? Also, please search the issues - AFAICT animation export is still pretty rough around the edges.

Switching to the dev branch, and exporting the same model (Person.blend) still gave me no output file. (Default Export Settings)

Also, @tschw, I know that the animations are disabled. I was just trying to see if the default export would work. I knew I wasn't going to get animations. If animations are not enabled, then it should just output a still model, no?

still gave me no output file

It probably gave you an error, then. It's sometimes difficult to see the box that Blender shows in this case (disappears quickly).

Please check the log console. You can access it by drag-opening the view with the main menu (pull it down when everything is default).

(I went to Window>Toggle System Console) Every time I run the exporter, I get the line Log: None and that's it.

EDIT: After enabling --debug-all in the console, I get

bpy.ops.export.three(filepath="C:\\Users\\Doug\\Desktop\\Blender Objs\\Person.js
on")
WM_operator_last_properties_store: storing properties for 'EXPORT_OT_three'

and still no .json being created.

I apologize. I wasn't selecting the mesh when exporting.

@FibreChips for rigged models, you must use the ObjectLoader and you must export the whole scene with hierarchy for it to work. The JSONLoader mangles rigged meshes (even though the file is .json)

These settings work for me. Do not select your mesh (or anything) and make sure the playhead is on the "idle" pose of your object before exporting. The process is brittle. Also note that currently morph targets ("shape keys" in blender) don't seem to be getting exported.

export-three-brittle

Hopefully this saves you some time.

@FibreChips

Every time I run the exporter, I get the line Log: None and that's it.
[ ... more info with --debug-all ]
I apologize. I wasn't selecting the mesh when exporting.

I think you should neither apologize nor close this ticket. Actually, this behavior is pretty damn quirky.

Even if nothing is selected for the export, the exporter should tell you that it expects something to _be_ selected by properly raising an error condition.

@DelvarWorld
Thanks for filling in on the current workaround.

Ah, okay thank you very much @DelvarWorld ! (And you too @tschw, you've been helping this whole time haha.

I closed it because I was unable to get the file to export, and now that I could I figured it was "closed". I guess I didn't expect more help -- Thankfully I was nicely surprised!

And now I can get the model to load in (Using ObjectLoader, and after rotating all axis -1.57 lol), but I can't for the life of me get the darn thing to animate. I can't seem to find any guides on animation using ObjectLoader, all of them seem to use JSONLoader. Would either of you be so kind as to direct me to a guide? (Or just show me the code example, whichever is easier!)

Thanks again!

@FibreChips
https://github.com/mrdoob/three.js/pull/8412#issuecomment-211451006 might be helpful

@FibreChips The example that helped me the most is animation / skinning / blending. Threejs is missing a lot of documentation, and animation is no exception. That example uses a class called BlendCharacter. It's not documented, and whether or not end users are supposed to use it, who knows! If you need simple animations, you might be able to get away with just using that file. You can see the basic API on these lines

blendMesh = new THREE.BlendCharacter();
blendMesh.load( "models/skinned/marine/marine_anims_core.json", start );

Internally this uses the undocumented AnimationMixer class. You can see how it's used in this section of BlendCharacter.js. Mainly something like:

   var mixer = new THREE.AnimationMixer( skinnedMesh );

    // Create the animations
    for ( var i = 0; i < skinnedMesh.geometry.animations.length; ++ i ) {
        mixer.clipAction( skinnedMesh.geometry.animations[ i ] );
    }

I removed the scope stuff to show how you might start separating it from BlendCharacter.js if you need more control. The AnimationMixer class has gone undocumented through at least two releases of Threejs. Are we as end users supposed to use it? Again, who knows. But it's used in the examples, even though the official examples have lots of oddities like this import of AnimationClipCreator.js which is never used, or commented out code.

I don't know what the "right" way currently is in Threejs, but this is the only clear-ish path I've found through the maze so far to get animated meshes.

Also to help navigate the maze, here's some other things I've discovered:

Sorry to dump this all in a specific ticket. I plan to write a blog post about this process because it's really difficult to navigate right now.

Finally, I just filed this issue because I just remembered it, where if you don't delete all of Blender's internal backup data (at least that's what I think it is), then your exported .json file will crash Three. A quick workaround, deleting the invalid top level "animations": [...] key from the exported JSON file, is what I've been doing for now.

@DelvarWorld Thank you so much! That example looks really great, and is fairly close to what I'm looking for. Except... I can't get that to work at all haha. If you want to take a look at what I have so far, you can see it at http://dougs.website/sites/cardboard_issue/.

What's supposed to happen is the guy on your right (when the page loads) is supposed to be waving. He's not. The code that affect him can be found at http://dougs.website/sites/cardboard_issue/js/custom.js and also near the bottom of index.html.

Again, thank you so much for your help!

@FibreChips There are Javascript errors in your console. You're calling animate before your model is fully loaded. The easiest solution is to not start animating until the start callback is called.

@DelvarWorld Thanks again. Removing that first animate call got rid of the console error, but didn't make the darn thing move. (Updated the code on the website)

@DelvarWorld

Sorry to dump this all in a specific ticket. I plan to write a blog post about this process because it's really difficult to navigate right now.

I think it's actually a good idea to bundle this info somewhere.

The AnimationMixer class has gone undocumented through at least two releases of Threejs.

I pretty much rewrote that class in r74 and was told to wait on the docs, because of upcoming API refinements. However, it's quite a while ago now, and I figure it might be better to have a documented interface that may change rather than no docs at all. We can get rid of old stuff within two release cycles via deprecation...

That example uses a class called BlendCharacter. It's not documented, and whether or not end users are supposed to use it, who knows!

This code has actually been ported to make the examples run. We should probably try to make it unnecessary - IOW improve the loader.

Ideally there'd be one global AnimationMixer and actions would be requested on demand, not upon program start.

var action = mixer.clipAction( myMesh.animations[ 'walk' ], myMesh ).play();

// then later
action.stop();

// alternatively, you can request the action from the mixer again in order to stop it
mixer.clipAction( myMesh.animations[ 'walk' ], myMesh ).stop();

It's not how the examples were ported - their structure is still based on older animation classes, but how the API is actually intended to be used.

@tschw Makes sense that I wouldn't find anything about AnimationMixer if there's no docs for it yet lol.

I added in an AnimationMixer, which made me end up with this for code

var mixer = new THREE.AnimationMixer();
var objectLoader = new THREE.ObjectLoader();
objectLoader.load('models/PersonAnim.json',function(object){
    object.position.set(12,5,6);
    object.rotation.set(0 * Math.PI/180, -120 * Math.PI/180, 0 * Math.PI/180);
    scene.add(object);
    var action = mixer.clipAction( object.animations[0], object ).play();
});

(I know, I need to fix the rotation thing.) The object loads fine, and is placed correctly in the scene. But still no motion. What am I still missing? (Again, http://dougs.website/sites/cardboard_issue/ has the most up-to-date version.)

EDIT: So after looking a bit more, object.animations[0] was a "valid" property, but it was empty. The real animation was hidden in object.children[0].geometry.animations[0]. Now, when running the same code as above, but replacing

var action = mixer.clipAction( object.animations[0], object ).play();

with

var action = mixer.clipAction( object.children[0].geometry.animations[0], object ).play();

gives me the console error can not bind to bones as node does not have a skeleton several times. (Approx. how many "steps" there are in the animation, all for the different bones in the animation rig.)

EDIT 2:
So, it looks like the .animations[0] object has 30 "steps" in it; 3 for each of the 10 bones I have, each of which positioning the Loc,Rot,Scale for all the bones. And that's it. So it makes sense that I wouldn't get any console errors, but I also wouldn't see any animation.

This just gets more and more convoluted it seems...

I pretty much rewrote that class in r74 and was told to wait on the docs, because of upcoming API refinements. However, it's quite a while ago now, and I figure it might be better to have a documented interface that may change rather than no docs at all. We can get rid of old stuff within two release cycles via deprecation...

Sorry, I haven't been able to take a look at all this yet. There is an up coming Web Animations API being worked on natively in browsers. They have started by implementing element.animate() but that's not useful for us as we're not dealing with DOM elements.

However, they seem to have intentions of adding an Animation() constructor and a Timeline.

So, it may be a good idea to try to move/rename things so it's more similar to that API and let the browser take care of that part in the future...

@mrdoob

However, they seem to have intentions of adding an Animation() constructor and a Timeline.

So, it may be a good idea to try to move/rename things so it's more similar to that API and let the browser take care of that part in the future...

That API looks very nice and actually provides a sequencer which our system currently lacks.

I don't think that an integration will be as simple as renaming things, however, and I'm not at all sure that turning our actions into Animations is really that desirable of a goal: They are pretty much "live thingies" by design. This trait might have been obscured by the fact that I pushed the envelope by adding more scheduling functionality in r74, but it might be better to separate that out into a layer on top (which would than be the one to interact with the browser).
This way, gaming applications could still use the interactive interface directly. It can still be shaped freely and for maximum efficiency, as the constraints in a 3D game may be a lot tighter than for an ordinary website. Similarly, the browser's API could be used for cases where a sequencer is useful (even in the same application, e.g. for global animations of the world that are just scripted, other than the actions of the protagonists that fire at will). Further, this approach would probably yield a better source code structure.

Sounds good! 馃憤

I've been trying several things to get this darn thing to work, and I keep running into the issues of either the animation not playing & not giving console errors, or I get the can not bind to bones as node does not have a skeleton error for all of the animation frames.

It looks like when I export the model/animation from Blender, having the "Scene" options ticked make it so I have to call object.children[0].... to find any of the animations/geometry that I actually need to use. When I don't include the "Scene" options, positioning the object and accessing the .animation arrays are much easier.

Sadly I don't seem to know enough about the inner workings of this to give more help on the subject, but I can agree in saying that it's rather messed up at the moment.

@FibreChips

It looks like when I export the model/animation from Blender, having the "Scene" options ticked make it so I have to call object.children[0].... to find any of the animations/geometry that I actually need to use.

IIRC checking "Scene" is currently the only option that works correctly for animations, but I could be wrong.

var action = mixer.clipAction( object.animations[0], object ).play();
can not bind to bones as node does not have a skeleton

Means object must have a .skeleton property / be a SkinnedMesh.

@tschw , my object does in fact have a .skeleton (according to Dev. Console), and judging by the fact that I'm not getting any console errors/no animation, I'm wondering if it's somehow not targeting the correct bones(?)

Also, I have three elements in my .animations[], named ArmatureAction, ArmatureAction.001, and ArmatureAction.002. I don't quite get how it would split those up, as I only have a single animation with 3 frames. Would it split all the frames into different "animations" for some reason?

@FibreChips

I'm wondering if it's somehow not targeting the correct bones(?)

Exact behavior depends on the path...

I suggest using three.js (not the minified build) and Chrome, then search for "PropertyBinding.js" (file names are in a comment on top of every file in the debug build), set a breakpoint and find out what's going wrong. Or better yet, fix it. In case you actually do, feel free to also improve the error reporting - even feel free to do so if there's nothing to fix or it's not easily fixable :)

Also, I have three elements in my .animations[], named ArmatureAction, ArmatureAction.001, and ArmatureAction.002. I don't quite get how it would split those up, as I only have a single animation with 3 frames. Would it split all the frames into different "animations" for some reason?

Leftover / unreferenced stuff Blender had still around, maybe?

Alright, I won't be able to look into it until at least Sunday night, if not Monday. But thanks for letting me know where to look, I'll be sure to report back with my findings/ maybe a pull request too :)

I was having similar issues, finally got to the point where I can get the skeleton to animate but not the actual mesh. Attached screencap and json file. Thanks for any help!
updated_export_8.json.zip

*edit: remove giant screencapture

OK figured out my problem with IRC help from DelvarWorld - material.skinning was false.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

DefinitelyMaybe picture DefinitelyMaybe  路  88Comments

goodsign picture goodsign  路  101Comments

mrdoob picture mrdoob  路  66Comments

lmcd picture lmcd  路  74Comments

danrossi picture danrossi  路  210Comments