Design of the New Animation Export Code - X-Plane/XPlane2Blender GitHub Wiki
Data Model
An X-Plane bone represents a single 'frame' of animation context - basically what is inside an ANIM_begin/ANIM_end in the final object.
- Every bone may have zero or one parent bones; the "root" bone is not animated and represents the OBJ's coordinate system - only it may have None for a parent.
- Every exportable drawing entity (meshes, lamps, etc.) has a parent bone; non-animated entities have the root bone as their parent.
- Every bone is capable of "writing" it's own animation commands to the final OBJ file. Precisely what those animations are will depend on the specifics of the bone, below.
Every bone has a source data block - the Blender object that causes a bone to be needed. There are two major cases:
- If an object in blender has key framed animation, then that object can be the source of the bone.
- If an armature has armature-bone animation, then XXXX is the source of the bone.
TODO: determine what the source is for armature animations. The armature data block is ambiguous because it can be animated via data block key framing OR via its pose bones; the pose bone is not a great "handle" to find our source information. It may be necessary to have a state flag or something gross like that. A key thing to note: when an armature is animated via an armature an by key framing its location, then we must build two bones, and each sees a different "aspect" of the armature, allowing for nesting of the armature animation inside the object animation.
Bake Matrices and Transforms
For any given exportable entity and Blender and its parent bone, there exists a 4x4 bake matrix (possibly the identity matrix) that goes from the coordinate system of the bone (after animation) to the coordinate system of the entity. For example, if the origin of our mesh is at 10,0,0 and we have a rotation around 0,-4,0 then the bake matrix for the entity will include a static transform with a vector of 10,4,0 to "move the origin" from 0,-4,0 (where it is left by the rotation) to 10,0,0 (where the entity needs it).
Bake matrices also exist between any bone and its parent!
Every exportable entity must be able to export "with a bake matrix", typically as follows:
- Meshes - the vertices of the mesh are transformed by the bake matrix pre-export.
- Lamps - the bake matrix is decomposed to a transform + eulers and statically applied via rotations to "pose" the lamp. This is needed when an author takes a lamp and rotates it, for example.
- Nested bones - the bake matrix can be applied to the child bones, but will almost certainly result in a static transform being emitted pre-rotation; this is typical of most rotations in X-Plane since they are always around the origin.
To simplify development, it is always -possible- (but not optimal) to emit bake matrices as a series of static transforms, e.g. like the lamp case, as a way to test whether the true "baking" code is working.
Exporting specific animations from bones
Because a bone has a Blender source, it has detailed access to the generator of those transformations -at export time-. This can fix a number of bugs:
- For armatures, the bone can access the armature's axis of rotation and write it directly as a single rotation; no decomposition of matrices is necessary. This will fix a number of off-axis armature-export bugs.
- For object animations, the bone can read the animation 'order' of the object (e.g. XYZ, ZXY, etc.) and write the rotations -in that order-, thus allowing all arbitrary object rotations.
- For rotations where the rotation angle is > 180 degrees, the exporter can read the key frame values directly, rather than decomposing a matrix. This will fix rotation through wide angles and directional issues.