KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программирование » Thomas Larsson - Введение в написание скриптов на Питоне для Блендера 2.5x. Примеры кода

Thomas Larsson - Введение в написание скриптов на Питоне для Блендера 2.5x. Примеры кода

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Thomas Larsson, "Введение в написание скриптов на Питоне для Блендера 2.5x. Примеры кода" бесплатно, без регистрации.
Перейти на страницу:

Эта программа также показывает, как вызвать диалог выбора файлов, нажав кнопку на панели. Класс кнопки Load BVH наследуется от двух базовых классов bpy.types.Operator и ImportHelper.

class OBJECT_OT_LoadBvhButton(bpy.types.Operator, ImportHelper):

Класс ImportHelper (возможно, недокументированный) определяет некоторые атрибуты, которые используются для фильтрации файлов, отображающихся в диалоге выбора файлов.

filename_ext = ".bvh"

filter_glob = bpy.props.StringProperty(default="*.bvh", options={'HIDDEN'})

filepath = bpy.props.StringProperty(name="File Path",

    maxlen=1024, default="")

Существует аналогичный класс ExportHelper, который ограничивает имеющийся выбор файлов экспорта.



#----------------------------------------------------------

# File simple_bvh_import.py

# Simple bvh importer

#----------------------------------------------------------  


bl_info = {

    'name': 'Simple BVH importer (.bvh)',

    'author': 'Thomas Larsson',

    'version': (1, 0, 0),

    'blender': (2, 5, 7),

    'api': 34786,

    'location': "File > Import",

    'description': 'Simple import of Biovision bvh',

    'category': 'Import-Export'}  


import bpy, os, math, mathutils, time

from mathutils import Vector, Matrix

from io_utils import ImportHelper  


#

# class CNode:


class CNode:

    def __init__(self, words, parent):

        name = words[1]

        for word in words[2:]:

            name += ' '+word


    self.name = name

    self.parent = parent

    self.children = []

    self.head = Vector((0,0,0))

    self.offset = Vector((0,0,0))

    if parent:

        parent.children.append(self)

    self.channels = []

    self.matrix = None

    self.inverse = None

    return 


    def __repr__(self):

        return "CNode %s" % (self.name)  


    def display(self, pad):

        vec = self.offset

        if vec.length < Epsilon:

            c = '*'

        else: c = ' '

        print("%s%s%10s (%8.3f %8.3f %8.3f)" %

            (c, pad, self.name, vec[0], vec[1], vec[2]))

        for child in self.children:

            child.display(pad+" ")

        return 


    def build(self, amt, orig, parent):

        self.head = orig + self.offset

        if not self.children:

            return self.head


        zero = (self.offset.length < Epsilon)

        eb = amt.edit_bones.new(self.name)

        if parent:

            eb.parent = parent

        eb.head = self.head

        tails = Vector((0,0,0))

        for child in self.children:

            tails += child.build(amt, self.head, eb)

        n = len(self.children)

        eb.tail = tails/n

        (trans,quat,scale) = eb.matrix.decompose()

        self.matrix = quat.to_matrix()

        self.inverse = self.matrix.copy()

        self.inverse.invert()

        if zero:

            return eb.tail

        else:

            return eb.head 


#

# readBvhFile(context, filepath, rot90, scale):


Location = 1

Rotation = 2

Hierarchy = 1

Motion = 2

Frames = 3 


Deg2Rad = math.pi/180

Epsilon = 1e-5 


def readBvhFile(context, filepath, rot90, scale):

    fileName = os.path.realpath(os.path.expanduser(filepath))

    (shortName, ext) = os.path.splitext(fileName)

    if ext.lower() != ".bvh":

        raise NameError("Not a bvh file: " + fileName)

    print( "Loading BVH file "+ fileName )


    time1 = time.clock()

    level = 0

    nErrors = 0

    scn = context.scene


    fp = open(fileName, "rU")

    print( "Reading skeleton" )

    lineNo = 0

    for line in fp:

        words= line.split()

        lineNo += 1

        if len(words) == 0:

            continue

        key = words[0].upper()

        if key == 'HIERARCHY':

            status = Hierarchy

        elif key == 'MOTION':

            if level != 0:

                raise NameError("Tokenizer out of kilter %d" % level)

            amt = bpy.data.armatures.new("BvhAmt")

            rig = bpy.data.objects.new("BvhRig", amt)

            scn.objects.link(rig)

            scn.objects.active = rig

            bpy.ops.object.mode_set(mode='EDIT')

            root.build(amt, Vector((0,0,0)), None)

#root.display('')

            bpy.ops.object.mode_set(mode='OBJECT')

            status = Motion

        elif status == Hierarchy:

            if key == 'ROOT':

                node = CNode(words, None)

                root = node

                nodes = [root]

            elif key == 'JOINT':

                node = CNode(words, node)

                nodes.append(node)

            elif key == 'OFFSET':

                (x,y,z) = (float(words[1]), float(words[2]), float(words[3]))

                if rot90:

                    node.offset = scale*Vector((x,-z,y))

                else:

                    node.offset = scale*Vector((x,y,z))

            elif key == 'END':

                node = CNode(words, node)

            elif key == 'CHANNELS':

                oldmode = None

                for word in words[2:]:

                    if rot90:

                        (index, mode, sign) = channelZup(word)

                    else:

                        (index, mode, sign) = channelYup(word)

                    if mode != oldmode:

                        indices = []

                        node.channels.append((mode, indices))

                        oldmode = mode

                    indices.append((index, sign))

            elif key == '{':

                level += 1

            elif key == '}':

                level -= 1

                node = node.parent

            else:

                raise NameError("Did not expect %s" % words[0])

        elif status == Motion:

            if key == 'FRAMES:':

                nFrames = int(words[1])

            elif key == 'FRAME' and words[1].upper() == 'TIME:':

                frameTime = float(words[2])

                frameTime = 1

                status = Frames

                frame = 0

                t = 0

                bpy.ops.object.mode_set(mode='POSE')

                pbones = rig.pose.bones

                for pb in pbones:

                    pb.rotation_mode = 'QUATERNION'

        elif status == Frames:

            addFrame(words, frame, nodes, pbones, scale)

            t += frameTime

            frame += 1


    fp.close()

    time2 = time.clock()

    print("Bvh file loaded in %.3f s" % (time2-time1))

    return rig 


#

# channelYup(word):

# channelZup(word):


def channelYup(word):

    if word == 'Xrotation':

        return ('X', Rotation, +1)

    elif word == 'Yrotation':

        return ('Y', Rotation, +1)

    elif word == 'Zrotation':

        return ('Z', Rotation, +1)

    elif word == 'Xposition':

        return (0, Location, +1)

    elif word == 'Yposition':

        return (1, Location, +1)

    elif word == 'Zposition':

        return (2, Location, +1)  


def channelZup(word):

    if word == 'Xrotation':

        return ('X', Rotation, +1)

    elif word == 'Yrotation':

        return ('Z', Rotation, +1)

    elif word == 'Zrotation':

        return ('Y', Rotation, -1)

    elif word == 'Xposition':

        return (0, Location, +1)

    elif word == 'Yposition':

        return (2, Location, +1)

    elif word == 'Zposition':

        return (1, Location, -1)  


#

# addFrame(words, frame, nodes, pbones, scale):


def addFrame(words, frame, nodes, pbones, scale):

    m = 0

    for node in nodes:

        name = node.name

        try:

            pb = pbones[name]

        except:

            pb = None

        if pb:

            for (mode, indices) in node.channels:

                if mode == Location:

                    vec = Vector((0,0,0))

                    for (index, sign) in indices:

                        vec[index] = sign*float(words[m])

                        m += 1

                    pb.location = (scale * vec - node.head) * node.inverse

                    for n in range(3):

                        pb.keyframe_insert('location', index=n, frame=frame, group=name)

                elif mode == Rotation:

                    mats = []

                    for (axis, sign) in indices:

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*