fbx2egg

I’ve started work on making a free, pure Python model and animation converter that will take a FBX file as input and produce a egg model. The main goal is to get rigged and animated characters.

The code will be hosted here:
github.com/wezu/fbx2egg

Planed features:
-convert vertices (done)
-convert polygons (done)
-convert normals (done)
-convert binormals and tangent vectors (done)
-convert UVs (done)
-convert vertex colors (done)
-apply textures to right polygons (groups)(done)
-convert joints (done)
-convert (baked) animations WIP - works for one bone
-GUI (tkinter)

Features that may be added, but only if it is easy :unamused: :
-multiple uv sets
-morphs
-nested model hierarchy
-materials

Features that where not planed but where added anyway:
-support for both triangulated meshes and meshes with higher order polygons (quads) (done)

Planed features for the GUI:
-changing/adding/removing textures
-setting texture options (envtype, wrapping, filters, format, stage-name, compression, anisotropic-degree, alpha )
-selecting groups that the textures will be applied to
-adding collision tags
-adding tags
-tagging groups so they don’t get flattened when they are part of an Actor (like with egg-optchar)
-adding tags like visibility, draw-order, depth-offset
-renaming groups and joints
-saving the animation data as a separate egg

Features that are not planed:
-support for binary FBX format
-nurbs, splines, empties/dummies, lights, cameras and any other non-geometry, non-bones objects
-keyframe interpolation (fbx can have say 4 keyframes for a 10 second animation and a ‘curve’ that defines transformations for the rest, egg wants a keyframe for every frame of the animation).
-generating tangent and binormals if they are not present in the fbx.

That’s the plan. I’ll be asking for help when I bump into something I can’t do myself, and later for help testing the script. Wish me luck :mrgreen:

applauds

I think I have it working for basic, static meshes.
It would be nice is someone could test it with fbx files from various sources… or just paste a link here to such files so I can test them myself.

It looks like I won’t be using any of the matrix in the fbx. Not sure anymore what they are - it looks like theres a ‘BindPose’ where the mesh is not transformed by the joints/bones and the bones/joints have some transform applied, something like the egg , but I’m not sure how that should work and anyway the matrix for this is only available for joints that do deform some mesh, so if you have a joint for props (swords, shields etc) it would probably end up at the characters feet.

I’ll try to use rotations and translations but I fear something will go wrong with them, a node that is not rotated at all in the modeling package ends up with some small rotation in the fbx file (looks random +/- 0-3 deg.)

But wait! I’m not posting just to cry about my problems with the converter, I need to ask something:
How do you use the " { degrees x y z }" tag in the egg format? I understand { degrees }, { degrees }, { degrees }, but I’d like to make the file a bit shorter… or is this for quaternions? Angle+ (normalized?) axis? Hmm…that would make sense actually.

And one more - the 3ds exporter and egg-* utilities like to add a comment to every vert that is used by some joint, like:

<Vertex> 18 {
        5 -5 5.57627e-019
        <UV> {
          0 0
          <Tangent> { 0 1 0 }
          <Binormal> { 0 0 1 }
        }
        <Normal> { 1 0 0 }
        // Bone001:1
      }

Has this any use?

And finally - Verts are grouped in the joint groups by membership value, so if I have 10k verts and each has a different membership value I’d need to make 10k ? Also do I risk anything else then a bloated file if I do put each vertex in it’s own VertexRef (even if there are multiple verts with the same weight)?

They’re axis rotations. { angle } is equivalent to:

<Rotate> { angle 1 0 0 }

Keep in mind that the order in which they are applied matters - look in the FBX specification in which order the transformations are supposed to be applied.

Good luck! Figuring out how all the transformations fit together can be challenging, especially for animated models. It’s the reason why I never managed to add animation support to dae2egg.

(In fact, if you run into trouble, there might be something to learn from the questions David answered for me during my adolescent attempts.)

The comments basically contain a list of the joints that that vertex is a member of with the appropriate membership value. They’re just comments; useful for humans reading the .egg file, but ignored by the .egg loader.

Yes, each joint should reference each vertex that has membership. This sounds like this could be a lot of vertices, but in practice, this usually doesn’t turn out to be all that many.

No, that doesn’t matter. It’d just be a file size optimization, as you suggested. If you’re worried about that, you could always pass it through egg-trans with no options, just to parse and write out your .egg file (it will also add in those funny group-ref comments).

For a simple test object (with 2 bones) I’ve managed to:
-export the model from my modeling package to fbx
-export the animation for it to egg (using the exporter that ships with the panda sdk)
-convert the fbx model to egg
-use the animation with the converted model

I’m only converting the data written in the fbx to a egg format so in theory it all should look the same - and at a glance it looks at least similar. Things move, the mesh doesn’t explode so I’ll call it a success :mrgreen:

The converted egg files aren’t identical to the exported ones because the converted have more verts (will look into this, but I trust the loader to optimize the mesh anyway). The exported egg uses matrixes… em matrixeses… matrices(??) and the converted got RotX Translate etc.

The code is getting a bit ugly (42 for loops :smiley: ), but as long as it works I don’t care much.

I will take a shot at animations after dinner, but I think I’ll need to google a bit to find out what KeyAttrFlags and KeyAttrDataFloat is in the fbx file.

I’ve got an animation working… if it’s an animation with 2 bones and only one of the bones move (provided it’s the first bone in the hierarchy)

The good news is that i think I know what to do to fix it. But right now my brain is fried.

I’m trying to get the fps from the fbx and I’m kind of stunned by it.
The fbx has a ‘KeyTime’ entry and as I understand it, it’s the time between keyframes (in tens of picoseconds?), the number increases by 1539538600 for each frame. This value looks to be fixed (or the exporter I use is bugged) and is the same for 24fps, 30fps, or 60fps.
I can’t figure out what 1539538600 is meant to represent
60 fps = 1 frame per 16.6666667 milliseconds
30 fps = 1 frame per 33.33333333 milliseconds
24 fps = 1 frame per 41.66666667 milliseconds
if 1539538600 should represent 15.39538600 milliseconds then the fps would be ~65 fps (15.384615385 ms).
When played at 30fps the animation looks ‘about right’ (as in the modeling package, but played side by side they misalign after a few loops).

From the FBX SDK documentation:
help.autodesk.com/view/FBX/2015/ … curve_html

46186158000 / 1539538600 = 30 FPS.

1/46186158000…? Right, ok, thx.

Hi Wezu,

Nice tool!

Is it already available? With it I could convert directly from .fbx generated from C4D to .egg without use Blender.

Unfortunately no. fbx files turned out to be fiddly. The code got abandoned at some point - I got it to work with one test model, but it only ever worked with that one model.
As far as I can remember the animations where the main problem for me.

Anyway - these days we have Assimp in Panda3D and I think it supports fbx models out of the box.

Hmmm… Not such “out of the box”… I can’t import FBX file but I can the same model in X. format using Assimp… I need FBX because it preserve the geom objects (.X mesh all geometries into a single “dummy node”)…