[Bf-extensions-cvs] [80a753b] fbx_io_development: Merge branch 'master' into fbx_io_development

Bastien Montagne noreply at git.blender.org
Sun Jul 13 18:36:14 CEST 2014


Commit: 80a753be921cfa95a90e894f20c6b379883c416e
Author: Bastien Montagne
Date:   Sun Jul 13 18:12:44 2014 +0200
https://developer.blender.org/rBA80a753be921cfa95a90e894f20c6b379883c416e

Merge branch 'master' into fbx_io_development

Conflicts:
	io_scene_fbx/import_fbx.py

===================================================================



===================================================================

diff --cc io_scene_fbx/import_fbx.py
index 3466929,c5a12e0..757051d
--- a/io_scene_fbx/import_fbx.py
+++ b/io_scene_fbx/import_fbx.py
@@@ -405,370 -390,7 +404,371 @@@ def blen_read_object(fbx_tmpl, fbx_obj
      return obj
  
  
 +# --------
 +# Armature
 +
 +def blen_read_armatures_add_bone(bl_obj, bl_arm, bones, b_uuid, matrices, fbx_tmpl_model):
 +    from mathutils import Matrix, Vector
 +
 +    b_item, bsize, p_uuid, clusters = bones[b_uuid]
 +    fbx_bdata, bl_bname = b_item
 +    if bl_bname is not None:
 +        return bl_arm.edit_bones[bl_bname]  # Have already been created...
 +
 +    p_ebo = None
 +    if p_uuid is not None:
 +        # Recurse over parents!
 +        p_ebo = blen_read_armatures_add_bone(bl_obj, bl_arm, bones, p_uuid, matrices, fbx_tmpl_model)
 +
 +    if clusters:
 +        # Note in some cases, one bone can have several clusters (kind of LoD?), in Blender we'll always
 +        # use only the first, for now.
 +        fbx_cdata, meshes, objects = clusters[0]
 +        objects = {blen_o for fbx_o, blen_o in objects}
 +
 +        # We assume matrices in cluster are rest pose of bones (they are in Global space!).
 +        # TransformLink is matrix of bone, in global space.
 +        # TransformAssociateModel is matrix of armature, in global space (at bind time).
 +        elm = elem_find_first(fbx_cdata, b'Transform', default=None)
 +        mmat_bone = array_to_matrix4(elm.props[0]) if elm is not None else None
 +        elm = elem_find_first(fbx_cdata, b'TransformLink', default=None)
 +        bmat_glob = array_to_matrix4(elm.props[0]) if elm is not None else Matrix()
 +        elm = elem_find_first(fbx_cdata, b'TransformAssociateModel', default=None)
 +        amat_glob = array_to_matrix4(elm.props[0]) if elm is not None else Matrix()
 +
 +        mmat_glob = bmat_glob * mmat_bone
 +
 +        # We seek for matrix of bone in armature space...
 +        bmat_arm = amat_glob.inverted() * bmat_glob
 +
 +        # Bone correction, works here...
 +        bmat_loc = (p_ebo.matrix.inverted() * bmat_arm) if p_ebo else bmat_arm
 +        bmat_loc = bmat_loc * MAT_CONVERT_BONE
 +        bmat_arm = (p_ebo.matrix * bmat_loc) if p_ebo else bmat_loc
 +    else:
 +        # Armature bound to no mesh...
 +        fbx_cdata, meshes, objects = (None, (), ())
 +        mmat_bone = None
 +        amat_glob = bl_obj.matrix_world
 +
 +        fbx_props = (elem_find_first(fbx_bdata, b'Properties70'),
 +                     elem_find_first(fbx_tmpl_model, b'Properties70', fbx_elem_nil))
 +        assert(fbx_props[0] is not None)
 +
 +        # Bone correction, works here...
 +        transform_data = blen_read_object_transform_preprocess(fbx_props, fbx_bdata, MAT_CONVERT_BONE)
 +        bmat_loc = blen_read_object_transform_do(transform_data)
 +        # Bring back matrix in armature space.
 +        bmat_arm = (p_ebo.matrix * bmat_loc) if p_ebo else bmat_loc
 +
 +    # ----
 +    # Now, create the (edit)bone.
 +    bone_name = elem_name_ensure_class(fbx_bdata, b'Model')
 +
 +    ebo = bl_arm.edit_bones.new(name=bone_name)
 +    bone_name = ebo.name  # Might differ from FBX bone name!
 +    b_item[1] = bone_name  # since ebo is only valid in Edit mode... :/
 +
 +    # So that our bone gets its final length, but still Y-aligned in armature space.
 +    ebo.tail = Vector((0.0, 1.0, 0.0)) * bsize
 +    # And rotate/move it to its final "rest pose".
 +    ebo.matrix = bmat_arm.normalized()
 +
 +    # Connection to parent.
 +    if p_ebo is not None:
 +        ebo.parent = p_ebo
 +        if similar_values_iter(p_ebo.tail, ebo.head):
 +            ebo.use_connect = True
 +
 +    if fbx_cdata is not None:
 +        # ----
 +        # Add a new vgroup to the meshes (their objects, actually!).
 +        # Quite obviously, only one mesh is expected...
 +        indices = elem_prop_first(elem_find_first(fbx_cdata, b'Indexes', default=None), default=())
 +        weights = elem_prop_first(elem_find_first(fbx_cdata, b'Weights', default=None), default=())
 +        add_vgroup_to_objects(indices, weights, bone_name, objects)
 +
 +    # ----
 +    # If we get a valid mesh matrix (in bone space), store armature and mesh global matrices, we need to set temporarily
 +    # both objects to those matrices when actually binding them via the modifier.
 +    # Note we assume all bones were bound with the same mesh/armature (global) matrix, we do not support otherwise
 +    # in Blender anyway!
 +    if mmat_bone is not None:
 +        for obj in objects:
 +            if obj in matrices:
 +                continue
 +            matrices[obj] = (amat_glob, mmat_glob)
 +
 +    return ebo
 +
 +
 +def blen_read_armatures(fbx_tmpl, armatures, fbx_bones_to_fake_object, scene, global_matrix):
 +    from mathutils import Matrix
 +
 +    if global_matrix is None:
 +        global_matrix = Matrix()
 +
 +    for a_item, bones in armatures:
 +        fbx_adata, bl_adata = a_item
 +        matrices = {}
 +
 +        # ----
 +        # Armature data.
 +        elem_name_utf8 = elem_name_ensure_class(fbx_adata, b'Model')
 +        bl_arm = bpy.data.armatures.new(name=elem_name_utf8)
 +
 +        # Need to create the object right now, since we can only add bones in Edit mode... :/
 +        assert(a_item[1] is None)
 +
 +        if fbx_adata.props[2] in {b'LimbNode', b'Root'}:
 +            # rootbone-as-armature case...
 +            fbx_bones_to_fake_object[fbx_adata.props[0]] = bl_adata = blen_read_object(fbx_tmpl, fbx_adata, bl_arm)
 +            # reset transform.
 +            bl_adata.matrix_basis = Matrix()
 +        else:
 +            bl_adata = a_item[1] = blen_read_object(fbx_tmpl, fbx_adata, bl_arm)
 +
 +        # Instantiate in scene.
 +        obj_base = scene.objects.link(bl_adata)
 +        obj_base.select = True
 +
 +        # Switch to Edit mode.
 +        scene.objects.active = bl_adata
 +        bpy.ops.object.mode_set(mode='EDIT')
 +
 +        for b_uuid in bones:
 +            blen_read_armatures_add_bone(bl_adata, bl_arm, bones, b_uuid, matrices, fbx_tmpl)
 +
 +        bpy.ops.object.mode_set(mode='OBJECT')
 +
 +        # Bind armature to objects.
 +        arm_mat_back = bl_adata.matrix_basis.copy()
 +        for ob_me, (amat, mmat) in matrices.items():
 +            # bring global armature & mesh matrices into *Blender* global space.
 +            amat = global_matrix * amat
 +            mmat = global_matrix * mmat
 +
 +            bl_adata.matrix_basis = amat
 +            me_mat_back = ob_me.matrix_basis.copy()
 +            ob_me.matrix_basis = mmat
 +
 +            mod = ob_me.modifiers.new(elem_name_utf8, 'ARMATURE')
 +            mod.object = bl_adata
 +
 +            ob_me.parent = bl_adata
 +            ob_me.matrix_basis = me_mat_back
 +        bl_adata.matrix_basis = arm_mat_back
 +
 +        # Set Pose transformations...
 +        for b_item, _b_size, _p_uuid, _clusters in bones.values():
 +            fbx_bdata, bl_bname = b_item
 +            fbx_props = (elem_find_first(fbx_bdata, b'Properties70'),
 +                         elem_find_first(fbx_tmpl, b'Properties70', fbx_elem_nil))
 +            assert(fbx_props[0] is not None)
 +
 +            pbo = b_item[1] = bl_adata.pose.bones[bl_bname]
 +            transform_data = object_tdata_cache.get(pbo)
 +            if transform_data is None:
 +                # Bone correction, gives a mess as result. :(
 +                transform_data = blen_read_object_transform_preprocess(fbx_props, fbx_bdata, MAT_CONVERT_BONE)
 +                object_tdata_cache[pbo] = transform_data
 +            mat = blen_read_object_transform_do(transform_data)
 +            if pbo.parent:
 +                # Bring back matrix in armature space.
 +                mat = pbo.parent.matrix * mat
 +            pbo.matrix = mat
 +
 +
 +# ---------
 +# Animation
 +def blen_read_animations_curves_iter(curves, blen_start_offset, fbx_start_offset, fps):
 +    """
 +    Get raw FBX AnimCurve list, and yield values for all curves at each singular curves' keyframes,
 +    together with (blender) timing, in frames.
 +    blen_start_offset is expected in frames, while fbx_start_offset is expected in FBX ktime.
 +    """
 +    # As a first step, assume linear interpolation between key frames, we'll (try to!) handle more
 +    # of FBX curves later.
 +    from .fbx_utils import FBX_KTIME
 +    timefac = fps / FBX_KTIME
 +
 +    fbx_curves = tuple([0,
 +                        elem_prop_first(elem_find_first(c[2], b'KeyTime')),
 +                        elem_prop_first(elem_find_first(c[2], b'KeyValueFloat'))]
 +                       for c in curves)
 +
 +    while True:
 +        tmin = min(fbx_curves, key=lambda e: e[1][e[0]])
 +        curr_fbxktime = tmin[1][tmin[0]]
 +        curr_values = []
 +        do_break = True
 +        for item in fbx_curves:
 +            idx, times, values = item
 +            if idx != -1:
 +                do_break = False
 +            if times[idx] > curr_fbxktime:
 +                if idx == 0:
 +                    curr_values.append(values[idx])
 +                else:
 +                    # Interpolate between this key and the previous one.
 +                    ifac = (curr_fbxktime - times[idx - 1]) / (times[idx] - times[idx - 1])
 +                    curr_values.append((values[idx] - values[idx - 1]) * ifac + values[idx - 1])
 +            else:
 +                curr_values.append(values[idx])
 +                if idx >= 0:
 +                    idx += 1
 +                    if idx >= len(times):
 +                        # We have reached our last element for this curve, stay on it from now on...
 +                        idx = -1
 +                    item[0] = idx
 +        curr_blenkframe = (curr_fbxktime - fbx_start_offset) * timefac + blen_start_offset
 +        yield (curr_blenkframe, curr_values)
 +        if do_break:
 +            break
 +
 +
 +def blen_read_animations_action_object(action, ob, obpath, grpname, cnodes, global_matrix, fps):
 +    """
 +    'Bake' loc/rot/scale into the action, taking into account global_matrix if no parent is present.
 +    """
 +    from bpy.types import Object
 +    from mathutils import Euler, Matrix
 +    from itertools import chai

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-extensions-cvs mailing list