Заменить костную структуру (дерево) пустыми - PullRequest
0 голосов
/ 10 мая 2019

В блендере я хочу заменить целую древовидную структуру костей пустой.Рассмотрим эту модель костного дерева:

Костное дерево

Вся структура должна быть преобразована в дерево пустот с сохранением имен и порядка родительских / дочерних элементов:

(я только что изобразил первый уровень здесь, так как я думаю, что вы поняли идею)

Примечание: анимации на этом рисунке не интересны!

Пустое дерево

В данный момент я читаю во всех костях, сохраняю их в некотором списке 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)

Сам массив выглядит так:

Структура массива

Таким образом, в основном это представляет древовидную структуру таким образом, что «голова», которая содержит дочерние элементы (поддеревья), всегда имеет индекс 0, если не осталось только одной единственной кости (как ['Root Ponytail1Nub']))

Рекурсивная функция работает как-то.Таким образом, это добавляет, по крайней мере, все головы.Но как только первый уровень рекурсии из одной головы был сделан, он не может правильно добавить childs.

Результат выглядит так:

Результат

Теперь я знаю, в чем проблема.Я постоянно увеличиваю индекс массива до тех пор, пока он не выйдет за пределы диапазона, и затем произойдет следующий уровень рекурсии:

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

Но это приводит к индексу == Нет ошибокили бесконечная рекурсия.

Суть всего этого в том, что я думаю, что главная проблема в том, что моя функция рекурсии работает так, что индекс будет увеличиваться до тех пор, пока не будет пройдено одно поддерево, но когда будет выбран следующий дочерний элемент, и это будетГлава следующего поддерева "index + = 1" приведет к проблемам.

Может быть, кто-то может просветить меня здесь:).

...