All pastes #502084 Raw Edit

Unnamed

public python v1 · immutable
·published 2007-05-22 10:36 UTC
rendered paste body
Index: Read.py===================================================================--- Read.py	(revision 2128)+++ Read.py	(working copy)@@ -276,10 +276,10 @@     _READ_PROGRESS = 0.0     _BLOCKS_READ = 0.0     # preprocessing:-    +     # scale tree-    scale_tree(root_block, _CONFIG['IMPORT_SCALE_CORRECTION'])-    +    root_block.applyScale(_CONFIG['IMPORT_SCALE_CORRECTION'])+     # sets the root block parent to None, so that when crawling back the script won't barf     root_block._parent = None     @@ -290,7 +290,8 @@     mark_armatures_bones(root_block)          # and merge armatures that are bones of others armatures-    merge_armatures()+    # *** DISABLED *** only single skeleton root supported+    #merge_armatures()          if _VERBOSE and _MSG_LEVEL >= 4:         for arm in _ARMATURES.keys():@@ -390,9 +391,9 @@                     if b_mesh:                         # correct the transform                         # it's parented to the armature!-                        armature_matrix_inverse = fb_global_bind_matrix(niArmature)+                        armature_matrix_inverse = fb_global_matrix(niArmature)                         armature_matrix_inverse.invert()-                        b_mesh.setMatrix(fb_global_bind_matrix(child) * armature_matrix_inverse)+                        b_mesh.setMatrix(fb_global_matrix(child) * armature_matrix_inverse)                         # add a vertex group if it's parented to a bone                         par_bone = get_closest_bone(child)                         if par_bone:@@ -452,14 +453,7 @@ # Retrieves a niBlock's transform matrix as a Mathutil.Matrix def fb_matrix(niBlock):     """Retrieves a niBlock's transform matrix as a Mathutil.Matrix"""-    r = niBlock.rotation # 3*3 matrix -    t = niBlock.translation # translation, vector3-    v = niBlock.velocity # ??? velocity, vector3, pretty much always 0, 0, 0-    b_matrix = Matrix(  [r.m11, r.m12, r.m13, v.x],\-                        [r.m21, r.m22, r.m23, v.y],\-                        [r.m31, r.m32, r.m33, v.z],\-                        [  t.x,   t.y,   t.z, 1.0])-    return b_matrix+    return Matrix(*niBlock.getTransform().asList())  # Retrieves a block's global transform matrix def fb_global_matrix(niBlock):@@ -470,20 +464,23 @@     return b_matrix  # Retrieves a node's bind position matrix-def fb_bind_matrix(niBlock):-    """Retrieves a node's bind position matrix"""-    # I need this hack to trap a few errors-    try:-        return niBlock._bindMatrix-    except AttributeError:-        return fb_matrix(niBlock)+# *** DISABLED *** doesn't do what it should do...+##def fb_bind_matrix(niBlock):+##    """Retrieves a node's bind position matrix relative to the armature."""+##    # I need this hack to trap a few errors+##    try:+##        return niBlock._bindMatrix+##    except AttributeError:+##        return fb_matrix(niBlock)+  # Retrieves a block's global bind position matrix-def fb_global_bind_matrix(niBlock):-    """Retrieves a node's global bind position matrix"""-    if niBlock._parent:-        return fb_bind_matrix(niBlock) * fb_global_bind_matrix(niBlock._parent) # yay, recursion-    return fb_bind_matrix(niBlock)+# *** DISABLED *** doesn't do what it should do...+##def fb_global_bind_matrix(niBlock):+##    """Retrieves a node's global bind position matrix"""+##    if niBlock._parent:+##        return fb_bind_matrix(niBlock) * fb_global_bind_matrix(niBlock._parent) # yay, recursion+##    return fb_bind_matrix(niBlock)  # Decompose Blender transform matrix as a scale, rotation matrix, and translation vector def decompose_srt(m):@@ -524,7 +521,7 @@ def fb_armature(niBlock):     global _SCENE     armature_name = fb_name(niBlock,22)-    armature_matrix_inverse = fb_global_bind_matrix(niBlock)+    armature_matrix_inverse = fb_global_matrix(niBlock)     armature_matrix_inverse.invert()     b_armature = Blender.Object.New('Armature', armature_name)     b_armatureData = Blender.Armature.Armature()@@ -551,6 +548,9 @@     # The armature has been created in editmode,     # now we are ready to set the bone keyframes. +    # *** DISABLED *** until everything else works :-)+    return b_armature+     # create an action     action = Blender.Armature.NLA.NewAction()     action.setActive(b_armature)@@ -720,6 +720,7 @@  # Adds a bone to the armature in edit mode. def fb_bone(niBlock, b_armature, b_armatureData, armature_matrix_inverse):+    # check if it is used at all     global _BONES, _BONES_EXTRA_MATRIX, _BONE_CORRECTION_MATRICES, _CONFIG     bone_name = fb_name(niBlock, 32)     niChildren = niBlock.children@@ -729,20 +730,22 @@         # create bones here...         b_bone = Blender.Armature.Editbone()         # head: get position from niBlock-        armature_space_matrix = fb_global_bind_matrix(niBlock) * armature_matrix_inverse+        #armature_space_matrix = fb_global_bind_matrix(niBlock) * armature_matrix_inverse+        armature_space_matrix = getattr(niBlock, '_bindMatrix', fb_global_matrix(niBlock) * armature_matrix_inverse)         b_bone_head_x = armature_space_matrix[3][0]         b_bone_head_y = armature_space_matrix[3][1]         b_bone_head_z = armature_space_matrix[3][2]         # tail: average of children location         if len(niChildNodes) > 0:-            child_matrices = [(fb_global_bind_matrix(child) * armature_matrix_inverse) for child in niChildNodes]+            child_matrices = [(fb_global_matrix(child) * armature_matrix_inverse) for child in niChildNodes]             b_bone_tail_x = sum([child_matrix[3][0] for child_matrix in child_matrices]) / len(child_matrices)             b_bone_tail_y = sum([child_matrix[3][1] for child_matrix in child_matrices]) / len(child_matrices)             b_bone_tail_z = sum([child_matrix[3][2] for child_matrix in child_matrices]) / len(child_matrices)         else:             # no children... continue bone sequence in the same direction as parent, with the same length             # this seems to work fine-            parent_matrix = fb_global_bind_matrix(niBlock._parent) * armature_matrix_inverse+            #parent_matrix = fb_global_bind_matrix(niBlock._parent) * armature_matrix_inverse+            parent_matrix = niBlock._parent._bindMatrix             b_parent_head_x = parent_matrix[3][0]             b_parent_head_y = parent_matrix[3][1]             b_parent_head_z = parent_matrix[3][2]@@ -765,30 +768,33 @@             # sets the bone heads & tails             b_bone.head = Vector(b_bone_head_x, b_bone_head_y, b_bone_head_z)             b_bone.tail = Vector(b_bone_tail_x, b_bone_tail_y, b_bone_tail_z)-            # here we explicitly try to set the matrix from the NIF matrix; this has the following consequences:-            # - head is preserved-            # - bone length is preserved-            # - tail is lost (up to bone length)-            (sum_x, sum_y, sum_z, dummy) = fb_matrix(niBlock)[3]-            if len(niChildNodes) > 0:-                child_local_matrices = [fb_matrix(child) for child in niChildNodes]-                sum_x = sum([cm[3][0] for cm in child_local_matrices])-                sum_y = sum([cm[3][1] for cm in child_local_matrices])-                sum_z = sum([cm[3][2] for cm in child_local_matrices])-            listXYZ = [int(c*200) for c in (sum_x, sum_y, sum_z, -sum_x, -sum_y, -sum_z)]-            idx_correction = listXYZ.index(max(listXYZ))-            alignment_offset = 0.0-            if idx_correction == 0 or idx_correction == 3:-                alignment_offset = float(abs(sum_y) + abs(sum_z)) / abs(sum_x)-            elif idx_correction == 1 or idx_correction == 4:-                alignment_offset = float(abs(sum_z) + abs(sum_x)) / abs(sum_y)-            else:-                alignment_offset = float(abs(sum_x) + abs(sum_y)) / abs(sum_z)-            # if alignment is good enough, use the (corrected) NIF matrix-            if alignment_offset < 0.25:-                m_correction = _BONE_CORRECTION_MATRICES[idx_correction]-                b_bone.matrix = m_correction * armature_space_matrix.rotationPart()-        # set bone name and store the niBlock for future reference+            b_bone.matrix = armature_space_matrix.rotationPart()+            +# *** DISABLED *** no bone correction until binding works+##            # here we explicitly try to set the matrix from the NIF matrix; this has the following consequences:+##            # - head is preserved+##            # - bone length is preserved+##            # - tail is lost (up to bone length)+##            (sum_x, sum_y, sum_z, dummy) = fb_matrix(niBlock)[3]+##            if len(niChildNodes) > 0:+##                child_local_matrices = [fb_matrix(child) for child in niChildNodes]+##                sum_x = sum([cm[3][0] for cm in child_local_matrices])+##                sum_y = sum([cm[3][1] for cm in child_local_matrices])+##                sum_z = sum([cm[3][2] for cm in child_local_matrices])+##            listXYZ = [int(c*200) for c in (sum_x, sum_y, sum_z, -sum_x, -sum_y, -sum_z)]+##            idx_correction = listXYZ.index(max(listXYZ))+##            alignment_offset = 0.0+##            if idx_correction == 0 or idx_correction == 3:+##                alignment_offset = float(abs(sum_y) + abs(sum_z)) / abs(sum_x)+##            elif idx_correction == 1 or idx_correction == 4:+##                alignment_offset = float(abs(sum_z) + abs(sum_x)) / abs(sum_y)+##            else:+##                alignment_offset = float(abs(sum_x) + abs(sum_y)) / abs(sum_z)+##            # if alignment is good enough, use the (corrected) NIF matrix+##            if alignment_offset < 0.25:+##                m_correction = _BONE_CORRECTION_MATRICES[idx_correction]+##                b_bone.matrix = m_correction * armature_space_matrix.rotationPart()+##        # set bone name and store the niBlock for future reference         b_armatureData.bones[bone_name] = b_bone         _BONES[bone_name] = niBlock         # calculate bone difference matrix; we will need this when importing animation@@ -1054,7 +1060,7 @@         b_mesh.setDrawType(4) # not hidden: shaded      # Mesh transform matrix, sets the transform matrix for the object.-    b_mesh.setMatrix(fb_bind_matrix(niBlock))+    b_mesh.setMatrix(fb_matrix(niBlock))          # Mesh geometry data. From this I can retrieve all geometry info     niData = niBlock.data@@ -1474,71 +1480,54 @@     # search for all NiTriShape or NiTriStrips blocks...     if isinstance(niBlock, NifFormat.NiTriBasedGeom):         # yes, we found one, get its skin instance-        skininst = niBlock.skinInstance-        if skininst:-            msg("Skin instance found on block '%s'" % niBlock.name,3)-            -            -            # retrieves scaling corrections. I have to do it here because skin instances-            # are not affected by the scale_tree function. Might be fixed later-            scale = _CONFIG["IMPORT_SCALE_CORRECTION"]-            +        if niBlock.isSkin():+            msg("skin found on block '%s'" % niBlock.name,3)+             # it has a skin instance, so get the skeleton root             # which is an armature only if it's not a skinning influence             # so mark the node to be imported as an armature-            skelroot = skininst.skeletonRoot-            -            # stores the bind offset matrices for later use-            skinInstData = skininst.data-            r = skinInstData.rotation-            s = skinInstData.scale-            t = skinInstData.translation-            --            bindMatrix = Matrix(-                [r.m11, r.m12, r.m13, 0.0],\-                [r.m21, r.m22, r.m23, 0.0],\-                [r.m31, r.m32, r.m33, 0.0],\-                [t.x*scale, t.y*scale, t.z*scale, 1.0])-            -            # only non-identity matrices are stored in the bind offset list-            # sets the bind offset for the affected skin-            if (bindMatrix != _IDENTITY44):-                niBlock._bindMatrix = bindMatrix-                +            skelroot = niBlock.skinInstance.skeletonRoot             if not _ARMATURES.has_key(skelroot):+                if _ARMATURES.keys():+                    raise NIFImportError('models with multiple skeleton roots not yet supported')                 _ARMATURES[skelroot] = []                 msg("'%s' is an armature" % skelroot.name,3)+            +            # stores the mesh bind position for later use+            # note that this matrix is relative to the skeleton root+            bindMatrix = Matrix(*niBlock.getGeometryRestPosition().asList())+            niBlock._bindMatrix = bindMatrix                 -            for i, bone in enumerate(skininst.bones):+            for boneBlock, boneRestPos in niBlock.getBoneRestPositions().items():                 # add them, if we haven't already-                if not bone in _ARMATURES[skelroot]:-                    skinData = skinInstData.boneList[i]-                    r = skinData.rotation-                    s = skinData.scale-                    t = skinData.translation-                    bindMatrix = Matrix(-                        [r.m11, r.m12, r.m13, 0.0],\-                        [r.m21, r.m22, r.m23, 0.0],\-                        [r.m31, r.m32, r.m33, 0.0],\-                        [t.x*s*scale, t.y*s*scale, t.z*s*scale, 1.0])-                    # only non-identity matrices are stored in the bind offset list-                    # sets the bind offset for the affected skin-                    if (bindMatrix != _IDENTITY44):-                        bone._bindMatrix = bindMatrix-                    _ARMATURES[skelroot].append(bone)-                    msg("'%s' is a bone of armature '%s'" % (bone.name, skelroot.name), 3)+                if not boneBlock in _ARMATURES[skelroot]:+                    # sets the rest position for the affected skin+                    boneBlock._bindMatrix = Matrix(*boneRestPos.asList())+                    _ARMATURES[skelroot].append(boneBlock)+                    msg("'%s' is a bone of armature '%s'" % (boneBlock.name, skelroot.name), 3)+                else:+                    # ensure that rest position is unique+                    # ... hmmm Blender docs say matrix comparison works+                    # but apparently it doesn't so commented out for now ...+                    #if Matrix(*boneRestPos.asList()) != boneBlock._bindMatrix:+                    tmp = 0.0+                    for v in Matrix(*boneRestPos.asList())-boneBlock._bindMatrix:+                        tmp += v.length+                    if tmp > _EPSILON:+                        print 'warning for bone', boneBlock.name+                        print Matrix(*boneRestPos.asList())+                        print boneBlock._bindMatrix+                        print 'multiple geometries influenced by the same bone with different rest poses'                 # now we "attach" the bone to the armature:                 # we make sure all NiNodes from this bone all the way                 # down to the armature NiNode are marked as bones-                complete_bone_tree(bone, skelroot)+                # *** DISABLED ***+                #complete_bone_tree(bone, skelroot)     # nope, it's not a NiTriShape or NiTriStrips-    # so if it's a NiNode-    elif isinstance(niBlock, NifFormat.NiNode):-        children = niBlock.children-        if children: # empty tuple is false-            for child in children:-                mark_armatures_bones(child)+    # so continue down the tree+    else:+        for child in niBlock.getRefs():+            mark_armatures_bones(child)   @@ -1546,6 +1535,9 @@ # all the way down to the armature node # just call it on all bones of a skin instance def complete_bone_tree(bone, skelroot):+    # *** DISABLED ***+    return+     global _ARMATURES     # we must already have marked this one as a bone     assert _ARMATURES.has_key(skelroot) # debug@@ -1568,6 +1560,9 @@  # merge armatures that are bones of other armatures def merge_armatures():+    # *** DISABLED ***+    return+     global _ARMATURES     for arm, bones in _ARMATURES.items():         for arm2, bones2 in _ARMATURES.items():@@ -1633,6 +1628,9 @@  # Loads basic animation info for this object def set_animation(niBlock, b_obj):+    # *** DISABLED ***+    return+     progress = 0.1     kfc = find_controller(niBlock, NifFormat.NiKeyframeController)     if kfc:@@ -1702,60 +1700,3 @@             b_obj.insertIpoKey(Blender.Object.LOC)                      Blender.Set('curframe', 1)---# Scale NIF file.-def scale_tree(niBlock, scale):-    # scale only works for nodes, and there's no point in scaling if the scale is 1/1-    if abs(1.0 - scale) > _EPSILON:-        # is it a node?-        # data should be scaled here as well, but isn't necessarily linked in the tree, so I scale it as I find it-        if isinstance(niBlock, NifFormat.NiAVObject):-            niBlock.translation.x *= scale-            niBlock.translation.y *= scale-            niBlock.translation.z *= scale-            # Controller data block scale-            ctrl = niBlock.controller-            while ctrl:-                if isinstance(ctrl, NifFormat.NiKeyframeController):-                    kfd = ctrl.data-                    assert(kfd)-                    # just to make sure, NiNode/NiTriShape controllers should have keyframe data-                    assert(isinstance(kfd, NifFormat.NiKeyframeData))-                    translations = kfd.translations-                    if translations:-                        for key in translations.keys:-                            key.value.x *= scale-                            key.value.y *= scale-                            key.value.z *= scale-                elif isinstance(ctrl, NifFormat.NiGeomMorpherController):-                    gmd = ctrl.data-                    assert(gmd)-                    assert(isinstance(gmd, NifFormat.NiMorphData))-                    for morph in gmd.morphs:-                        vects = morph.vectors-                        for v in range( len( vects ) ):-                            vects[v].x *= scale-                            vects[v].y *= scale-                            vects[v].z *= scale-                ctrl = ctrl.nextController-            # Child block scale-            if isinstance(niBlock, NifFormat.NiNode):-                children = niBlock.children-                if children: # block has children-                    for child in children:-                        scale_tree(child, scale)-            else:-                blockData = niBlock.data-                if blockData: # block has data-                    scale_tree(blockData, scale) # scale the data-        -        if isinstance(niBlock, NifFormat.NiTriBasedGeom): # is it a shape?-            # Scale all vertices-            shapedata = niBlock.data-            vertlist = shapedata.vertices-            if vertlist:-                for vert in vertlist:-                    vert.x *= scale-                    vert.y *= scale-                    vert.z *= scale