用空容器替换骨骼结构(树)

时间:2019-05-09 21:39:08

标签: python blender

在搅拌机中,我想将整个骨骼结构替换为空。考虑这个模型骨树:

Bone tree

应将整个结构转换为空树,并保留名称和父子顺序:

(由于我想您已经明白了,所以我刚刚在这里画了第一张图)

注意:此图片中的动画不有趣!

Empty tree

目前,我正在阅读所有骨骼,将它们保存到一些2D python列表中,然后尝试通过递归遍历该数组来重新创建带有空的整个结构:

class ReplaceBones(bpy.types.Operator):
    bl_label = "Replace Bones"
    bl_idname = "replace.bones"
    bl_description = "Replaces all bones with empties."

    def execute(self, context):
        #Set mode to 'OBJECT'
        if not bpy.context.mode == 'OBJECT':
            bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

        #Deselect everything
        bpy.ops.object.select_all(action='DESELECT')

        #Check if Root exists
        if 'Root' in bpy.context.scene.objects:
            #Switch to Root
            root = bpy.data.objects['Root']            
            bpy.context.scene.objects.active = root        

            #Get all Bones
            contObj = bpy.context.object
            bones = contObj.data

            #Set mode to EDIT to access edit_bones
            bpy.ops.object.mode_set(mode='EDIT')            

            boneList = []
            childList = []

            #Loop through bones            
            for bone in bones.edit_bones:
                #boneList.append(bone.name)
                boneList.append(childList)

                childList = [bone.name]

                for child in bone.children:
                    childList.append(child.name)


            #test
            print()
            print("WHOLE LIST")
            for bone in boneList:
                print(bone)
                print(".......length: " + str(len(bone)))
            print()

            #Set mode back to  OBJECT
            bpy.ops.object.mode_set(mode='OBJECT')   

            #Add Empties
            self.recursiveAddEmpties(context, boneList, 'Root', 1)

        else:
            #Info pop up in blender
            self.report({'INFO'}, "No Root found! Forgot to import model?")

        return{"FINISHED"}

递归演练:

def recursiveAddEmpties(self, context, bones, activeObj, index):
        head = bones[index][0]
        children = bones[index]

        print()
        print("Recursion head: " + head)
        print("Recursion children: " + str(children))
        print("Recursion children len: " + str(len(children)))
        print("index: " + str(index))
        print()

        #add head
        if index == 1:
            bpy.ops.object.empty_add(type='PLAIN_AXES')
            bpy.context.object.name = head
        emptyHead = bpy.context.object

        if not len(children) == 1:
            root = bpy.data.objects[activeObj]            
            bpy.context.scene.objects.active = root
            print("Active object: " + str(bpy.context.scene.objects.active))

            #add childs
            for child in children:
                if not child == head:            
                    print("Active child: " + child)                    
                    bpy.ops.object.empty_add(type='PLAIN_AXES')
                    childObj = bpy.context.object
                    bpy.context.object.name = child
                    childObj.parent = emptyHead    
                    index += 1

                    print("index: " + str(index))
                    if not index == len(bones) - 1:                        
                        self.recursiveAddEmpties(context, bones, head, index)

数组本身看起来像这样:

Array structure

因此,基本上,它以一种方式表示树结构,其中包含子级(子树)的“头”始终位于索引0,除非仅剩一根骨头(例如['Root Ponytail1Nub'])

递归函数以某种方式起作用。从某种意义上说,它至少增加了所有头。但是,一旦完成了一个人的第一个递归级别,就无法正确添加子级。

结果如下:

Result

现在我有点知道问题可能出在哪里。我不断增加数组索引,直到超出范围为止,然后进行下一个递归级别:

index += 1

if not index == len(bones) - 1:                        
    self.recursiveAddEmpties(context, bones, head, index)  

这很有效,直到必须像L_Clavicle这样选择子树的下一个树头时才是子树。

看起来主结构正确构建,但是子树有点混乱。我试图实现一个功能来搜索下一个出现的头部,基本上是将索引设置为此列表中子数组的下一个索引:

index = self.getHeadIndex(context, index, head, bones)
if not index == len(bones) - 1:                        
     self.recursiveAddEmpties(context, bones, head, index)  

def getHeadIndex(self, context, index, head, bones):
        #try to find index of next occurance of head in bone list      
        print("Trying to find index. Actual index: " + str(index))
        print("for head: " + str(head))  
        #start = index + 1
        start = index + 1
        if not start > len(bones) - 1:
            print("start: " + str(start))
            for i in range(start, len(bones)):
                children = bones[i]
                print("i: " + str(i))
                for child in children:
                    print("child: " + child)
                    if head == child:
                        print("index found at " + str(i))
                        return i               
        else:
            print("index not found. returning " + str(index))
            return index

但是它导致索引== None错误或无穷递归。

这一切的底线是我认为主要的问题是,我的递归函数有效,其方式是直到下一个子树被行走之前,索引都会增加,但是当下一个孩子被选中并且是树的头部时,下一个子树“索引+ = 1”将导致问题。

也许有人可以在这里启发我:)。

0 个答案:

没有答案