Esempio n. 1
0
    def process(self):
        if not (self.inputs['Vertices'].is_linked):
            return
        if not (any(output.is_linked for output in self.outputs)):
            return

        vertices_s = self.inputs['Vertices'].sv_get(default=[[]])
        edges_s = self.inputs['Edges'].sv_get(default=[[]])
        faces_s = self.inputs['Polygons'].sv_get(default=[[]])
        face_data_s = self.inputs['FaceData'].sv_get(default=[[]])
        matrixes_s = self.inputs['Matrix'].sv_get(default=[[Matrix()]])

        result_vertices = []
        result_edges = []
        result_faces = []
        result_face_data = []

        meshes = match_long_repeat([vertices_s, edges_s, faces_s, face_data_s, matrixes_s])

        for vertices, edges, faces, face_data, matrixes in zip(*meshes):
            if face_data:
                fullList(face_data, len(faces))
            if isinstance(matrixes, list):
                matrix = matrixes[0]
            else:
                matrix = matrixes
            has_matrix = matrix is not None and matrix != Matrix()

            # TODO: this is actually a workaround for a known Blender bug
            # https://developer.blender.org/T59804
            mirror_axis = self.get_mirror_direction()
            if mirror_axis is not None:
                vertices = self.mirror(vertices, mirror_axis, matrix)
            bm = bmesh_from_pydata(vertices, edges, faces, markup_face_data=True)

            if has_matrix:
                bmesh.ops.transform(bm, matrix = matrix.inverted(), verts = list(bm.verts))

            bmesh.ops.symmetrize(
                bm, input = list(bm.verts) + list(bm.edges) + list(bm.faces),
                direction = self.get_symmetrize_direction(),
                dist = self.merge_dist
            )

            if has_matrix:
                bmesh.ops.transform(bm, matrix = matrix, verts = list(bm.verts))

            if face_data:
                new_vertices, new_edges, new_faces, new_face_data = pydata_from_bmesh(bm, face_data)
            else:
                new_vertices, new_edges, new_faces = pydata_from_bmesh(bm)
                new_face_data = []
            if mirror_axis is not None:
                new_vertices = self.mirror(new_vertices, mirror_axis, matrix)
            bm.free()

            result_vertices.append(new_vertices)
            result_edges.append(new_edges)
            result_faces.append(new_faces)
            result_face_data.append(new_face_data)

        self.outputs['Vertices'].sv_set(result_vertices)
        self.outputs['Edges'].sv_set(result_edges)
        self.outputs['Polygons'].sv_set(result_faces)
        self.outputs['FaceData'].sv_set(result_face_data)
Esempio n. 2
0
def screen(ot, context, event):
    preference = addon.preference()
    bc = context.window_manager.bc

    verts = [
        Vector((-1000.0, -1000.0, 0.0)),
        Vector((1000.0, -1000.0, 0.0)),
        Vector((-1000.0, 1000.0, 0.0)),
        Vector((1000.0, 1000.0, 0.0))
    ]

    edges = [(0, 2), (0, 1), (1, 3), (2, 3)]

    faces = [(0, 1, 3, 2)]

    data = bpy.data.meshes.new(name='Box')
    data.bc.removeable = True

    if not bc.snap.hit:
        data.from_pydata(verts, edges, faces)
        data.validate()

    box = bpy.data.objects.new(
        name='Box', object_data=data if not bc.snap.hit else bc.snap.mesh)
    bpy.context.scene.collection.objects.link(box)

    del data

    box.data.bc.removeable = True if not bc.snap.hit else False

    if not bc.snap.hit:
        mod = box.modifiers.new(name='Solidify', type='SOLIDIFY')
        mod.thickness = max(dimension
                            for dimension in ot.datablock['dimensions']) * 1.75
        mod.offset = 0

        modifier.apply(obj=box, mod=mod)

        del mod

        box.data.transform(
            context.region_data.view_rotation.to_euler().to_matrix().to_4x4())

        matrix = Matrix()
        matrix.translation = bc.original_active.matrix_world @ object.center(
            bc.original_active)

        box.data.transform(matrix)

    hit, ot.ray['location'], ot.ray['normal'], index = ray.cast.objects(
        *ot.mouse['location'], mesh=box.data)

    bpy.data.objects.remove(box)

    del box

    bc.lattice.matrix_world = context.region_data.view_rotation.to_euler(
    ).to_matrix().to_4x4()
    bc.lattice.matrix_world.translation = Vector(
        ot.ray['location'][:] if not bc.snap.hit else bc.snap.location)
    bc.shape.matrix_world = bc.lattice.matrix_world
    bc.plane.matrix_world = bc.lattice.matrix_world

    ot.start['matrix'] = bc.plane.matrix_world.copy()

    bc.location = ot.ray['location'] if not bc.snap.hit else bc.snap.location
    refresh.shape(ot, context, event)
Esempio n. 3
0
def to_base_vertices(deform_verts: bmesh.types.BMVertSeq, to_world_matrix, target_direction, target_origin, deform_vertex_index_weights: Dict[int, float], base_area_factor: float, project_vertically: bool) -> List[Vector]:
    ortho_projection_matrix = Matrix.OrthoProjection(target_direction, 4)

    f_l = 1
    intrinsic_matrix = Matrix([
        [f_l, 0.0, 0.0, 0.0],
        [0.0, f_l, 0.0, 0.0],
        [0.0, 0.0, f_l, 0.0],
        [0.0, 0.0, 0.0, 1.0]
    ])

    wide_projection_matrix: Matrix = intrinsic_matrix @ ortho_projection_matrix @ Matrix.Translation(-target_origin)

    wide_project_2d_vertices: Set[Tuple[float, float]] = set()
    wide_project_3d_vertices: List[Vector] = []

    deform_verts.ensure_lookup_table()
    for deform_vertex_index, deform_vertex_weight in deform_vertex_index_weights.items():
        wide_project_3d_vertex = wide_projection_matrix @ (to_world_matrix @ deform_verts[deform_vertex_index].co)
        wide_project_2d_vertex = wide_project_3d_vertex / wide_project_3d_vertex[2]

        wide_project_2d_vertices.add(wide_project_2d_vertex[0:2])
        wide_project_3d_vertices.append(wide_project_3d_vertex * (deform_vertex_weight**base_area_factor))

    box_fit_angle: float = mathutils.geometry.box_fit_2d(list(wide_project_2d_vertices))
    rotate_matrix: Matrix = Matrix.Rotation(+box_fit_angle, 4, target_direction) @ ortho_projection_matrix

    x_min = float('+inf')
    x_max = float('-inf')
    z_min = float('+inf')
    z_max = float('-inf')

    for vertex in wide_project_3d_vertices:
        rotate_vertex: Vector = rotate_matrix @ vertex

        if x_min > rotate_vertex.x:
            x_min = rotate_vertex.x

        if x_max < rotate_vertex.x:
            x_max = rotate_vertex.x

        if z_min > rotate_vertex.z:
            z_min = rotate_vertex.z

        if z_max < rotate_vertex.z:
            z_max = rotate_vertex.z

    rotate_matrix_invert: Matrix
    if project_vertically:
        front_vector = Vector([0, -1, 0])
        rotate_matrix_invert = Matrix.Rotation(-box_fit_angle, 4, front_vector) @ Matrix.OrthoProjection(front_vector, 4)
    else:
        rotate_matrix_invert = Matrix.Rotation(-box_fit_angle, 4, target_direction) @ ortho_projection_matrix

    base_vertices: List[Vector] = [
        rotate_matrix_invert @ Vector([x_min, 0, 0]),
        rotate_matrix_invert @ Vector([0, 0, z_min]),
        rotate_matrix_invert @ Vector([x_max, 0, 0]),
        rotate_matrix_invert @ Vector([0, 0, z_max]),
    ]

    return base_vertices
#         [m01, m11, m21, m31],
#         [m02, m12, m22, m32],
#         [m03, m13, m23, m33]))
#         
#    return m.transposed()


def quat_equals(q1,q2):
    return q1.w == q2.w and q1.x == q2.x and q1.y == q2.y and q1.z == q2.z


quat_transform_y_positive = Euler((pi/2, 0, 0),"XYZ").to_quaternion()

m4 = Matrix(
        ([1, 0, 0, 0],
         [0, 0, -1, 0],
         [0, 1, 0, 0],
         [0, 0, 0, 1]))

m3 = Matrix(
        ([1, 0, 0],
         [0, 0, -1],
         [0, 1, 0]))

matrix_3_transform_y_positive = Matrix((( 1, 0, 0 )   ,( 0, 0, 1 )   ,( 0,-1, 0 )                  ))
matrix_4_transform_y_positive = Matrix((( 1, 0, 0, 0 ),( 0, 0, 1, 0 ),( 0,-1, 0, 0 ),( 0, 0, 0, 1 )))
matrix_3_transform_z_positive = Matrix((( 1, 0, 0 )   ,( 0, 0,-1 )   ,( 0, 1, 0 )                  ))
matrix_4_transform_z_positive = Matrix((( 1, 0, 0, 0 ),( 0, 0,-1, 0 ),( 0, 1, 0, 0 ),( 0, 0, 0, 1 )))

class Matrix4f():
    
Esempio n. 5
0
def read_file(operator, context):
    from mathutils import (Matrix, Vector)
    import math

    filepath = operator.filepath

    se3_mesh = get_se3_mesh_form_file(filepath)

    for se3_layer in se3_mesh.layers:
        fgon_edge_indices = []
        vertices = se3_layer.vertex_maps[0].elements
        edges = []

        real_faces = []
        se3_surface_map_indices = [0] * len(se3_layer.polygons)
        material_indices = []

        for se3_surface_map_index, se3_surface_map in enumerate(
                se3_layer.surface_maps):
            for polygon_index in se3_surface_map.polygons:
                se3_surface_map_indices[polygon_index] = se3_surface_map_index

        edge_index_count = 0
        for se3_polygon_index, se3_polygon in enumerate(se3_layer.polygons):
            se3_num_of_vertex_indices = len(se3_polygon)
            se3_is_tri_or_quad = se3_num_of_vertex_indices <= 4

            se3_surface_map_index = se3_surface_map_indices[se3_polygon_index]

            if se3_is_tri_or_quad:
                material_indices.append(se3_surface_map_index)

                face = get_bl_face(se3_layer, se3_polygon)
                real_faces.append(face)

                face_edges = get_bl_edges(face[0])

                for face_edge in face_edges:
                    """
                    if edge_not_in(face_edge, edges):
                        edges.append(face_edge)
                        edge_index_count += 1
                    """
                    edges.append(face_edge)
                    edge_index_count += 1
            else:
                ngon_face = get_bl_face(se3_layer, se3_polygon)
                bound_edges = get_bl_edges(ngon_face[0])

                fgon_faces = get_bl_fgons(vertices, ngon_face[0])

                for fgon_face in fgon_faces:
                    material_indices.append(se3_surface_map_index)

                    real_faces.append(
                        tuple([
                            fgon_face,
                            get_bl_face_uv_data(ngon_face, fgon_face)
                        ]))
                    face_edges = get_bl_edges(fgon_face)

                    for face_edge in face_edges:
                        is_fgon_edge = edge_not_in(face_edge, bound_edges)

                        edges.append(face_edge)

                        if is_fgon_edge:
                            fgon_edge_indices.append(edge_index_count)

                        edge_index_count += 1

        faces = [real_face[0] for real_face in real_faces]

        mesh = bpy.data.meshes.new("Test mesh")
        mesh.from_pydata(vertices, edges, faces)

        for fgon_edge_index in fgon_edge_indices:
            mesh.edges[fgon_edge_index].is_fgon = True

        for uv_index, se3_texcoord_map in enumerate(se3_layer.texcoord_maps):
            uv_tex = mesh.uv_textures.new(se3_texcoord_map.name)
            uv_loop = mesh.uv_layers[0]

            for face_index, tex_data in enumerate(uv_tex.data):
                real_tex_face = real_faces[face_index][1][uv_index]
                poly = mesh.polygons[face_index]

                for j, k in enumerate(poly.loop_indices):
                    uv_loop.data[k].uv = real_tex_face[j]

        tranf_mat = Matrix(((-1.0, 0.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0),
                            (0.0, 1.0, 0.0, 0.0), (0.0, 0.0, 0.0, 1.0)))

        obj = bpy.data.objects.new(se3_layer.name, mesh)

        scene = context.scene
        scene.objects.link(obj)
        scene.objects.active = obj

        obj.select = True

        se3_non_basic_morph_map = se3_layer.non_basic_morph_maps

        se3_vertices = se3_layer.vertices

        if se3_non_basic_morph_map:
            obj.shape_key_add("position")

            shape_keys = []
            for se3_other_mmap in se3_non_basic_morph_map:
                shape_keys.append(obj.shape_key_add(se3_other_mmap.name))

            for se3_vertex in se3_vertices:
                other_morph_pnts = se3_vertex.non_basic_morph_pointers

                if other_morph_pnts:
                    for idx, other_mp in enumerate(other_morph_pnts):
                        type_idx = se3_layer.vertex_maps[
                            other_mp[0]].type_index
                        se3_disp = se3_layer.vertex_maps[other_mp[0]].elements[
                            other_mp[1]]
                        se3_vert = se3_vertex.basic_morph_pointer[1]
                        vert_data = se3_layer.vertex_maps[
                            se3_vertex.basic_morph_pointer[0]].elements[
                                se3_vertex.basic_morph_pointer[1]]

                        shape_keys[type_idx - 1].data[se3_vert].co = Vector(
                            vert_data) + Vector(se3_disp)

        se3_weight_maps = se3_layer.weight_maps

        if se3_weight_maps:
            vertex_groups = []

            for se3_weight_map in se3_weight_maps:
                vertex_groups.append(obj.vertex_groups.new(
                    se3_weight_map.name))

            for se3_vertex in se3_vertices:
                se3_weight_pointers = se3_vertex.weight_pointers

                if se3_weight_pointers:
                    for se3_weight_pointer in se3_weight_pointers:
                        vertex_index = se3_vertex.basic_morph_pointer[1]
                        se3_vertex_map_index = se3_weight_pointer[0]
                        se3_vertex_weight = se3_layer.vertex_maps[
                            se3_vertex_map_index].elements[
                                se3_weight_pointer[1]]
                        vertex_group_index = se3_layer.vertex_maps[
                            se3_vertex_map_index].type_index
                        vertex_groups[vertex_group_index].add(
                            [vertex_index], se3_vertex_weight, 'REPLACE')

        if se3_layer.surface_maps:
            materials = []

            for se3_surface_map in se3_layer.surface_maps:
                material = bpy.data.materials.new(se3_surface_map.name)
                materials.append(material)
                bpy.ops.object.material_slot_add()
                obj.material_slots[-1].material = material

            for face in mesh.polygons:
                face.material_index = material_indices[face.index]

        obj.matrix_world = tranf_mat
        bpy.ops.object.transform_apply(rotation=True)

        scene.update()

    return {'FINISHED'}
Esempio n. 6
0
def array_to_matrix4(arr):
    """Convert a single 16-len tuple into a valid 4D Blender matrix"""
    # Blender matrix is row major, fbx is col major so transpose on read
    return Matrix(tuple(zip(*[iter(arr)]*4))).transposed()
Esempio n. 7
0
# <pep8 compliant>

import bpy
from mathutils import Vector, Matrix

from ..mu import MuMesh, MuRenderer, MuSkinnedMeshRenderer, MuBoneWeight
from ..utils import collect_modifiers

from .material import make_material

from .export_util import is_collider

from pprint import pprint

#matrix for converting between LHS and RHS (works either direction)
Matrix_YZ = Matrix(((1, 0, 0, 0), (0, 0, 1, 0), (0, 1, 0, 0), (0, 0, 0, 1)))

MU_MAX_VERTS = 65534


def build_submeshes(mesh):
    submeshes = []
    submesh = []
    for i in range(len(mesh.loop_triangles)):
        submesh.append(i)
    submeshes.append(submesh)
    return submeshes


def make_tris(mesh, submeshes, vertex_map):
    for sm in submeshes:
Esempio n. 8
0
def convert_pose_array_to_matrix(R, T):
    mat = Matrix(R.reshape(3, 3)).to_4x4()
    mat.col[3][:3] = T
    return mat
Esempio n. 9
0
    def process(self):

        self.handle_attr_socket()

        if not (self.id_data.sv_show and self.activate):
            callback_disable(node_id(self))
            return

        n_id = node_id(self)
        callback_disable(n_id)

        if not any([self.display_verts, self.display_edges, self.display_faces]):
            return

        verts_socket, edges_socket, faces_socket, matrix_socket = self.inputs[:4]

        if verts_socket.is_linked:

            display_faces = self.display_faces and faces_socket.is_linked
            display_edges = self.display_edges and (edges_socket.is_linked or faces_socket.is_linked)

            config = self.fill_config()
            data = self.get_data()
            if len(data[0]) > 1:
                coords, edge_indices, face_indices = mesh_join(data[0], data[1], data[2])
            else:
                coords, edge_indices, face_indices = [d[0].tolist() if type(d[0]) == ndarray else d[0] for d in data[:3]]

            geom = lambda: None
            geom.verts = coords

            if self.display_verts and not any([display_edges, display_faces]):
                gl_instructions = self.format_draw_data(func=draw_verts, args=(geom, config))
                callback_enable(n_id, gl_instructions)
                return

            if edges_socket.is_linked and not faces_socket.is_linked:
                if self.use_dashed:
                    self.add_gl_stuff_to_config(config)

                geom.edges = edge_indices
                gl_instructions = self.format_draw_data(func=draw_edges, args=(geom, config))
                callback_enable(n_id, gl_instructions)
                return

            if faces_socket.is_linked:

                #  expecting mixed bag of tris/quads/ngons
                if self.display_faces:
                    geom.faces = ensure_triangles(coords, face_indices, self.handle_concave_quads)

                if self.display_edges:
                    if self.use_dashed:
                        self.add_gl_stuff_to_config(config)

                    # we don't want to draw the inner edges of triangulated faces; use original face_indices.
                    # pass edges from socket if we can, else we manually compute them from faces
                    geom.edges = edge_indices if edges_socket.is_linked else edges_from_faces(face_indices)

                if self.display_faces:
                    self.faces_diplay(geom, config)

                gl_instructions = self.format_draw_data(func=draw_complex, args=(geom, config))
                callback_enable(n_id, gl_instructions)
                return

            return

        elif matrix_socket.is_linked:
            matrices = matrix_socket.sv_get(deepcopy=False, default=[Matrix()])
            gl_instructions = self.format_draw_data(func=draw_matrix, args=(matrices, ))
            callback_enable(n_id, gl_instructions)
Esempio n. 10
0
def load(root_object, pia_files, armature, skeleton=None, bones=None):
    if not bones:
        bones = {}

    scs_globals = _get_scs_globals()

    print("\n************************************")
    print("**      SCS PIA Importer          **")
    print("**      (c)2014 SCS Software      **")
    print("************************************\n")

    import_scale = scs_globals.import_scale
    ind = '    '
    for pia_filepath in pia_files:
        # Check if PIA file is for the actual skeleton...
        if skeleton:
            skeleton_match = _fast_check_for_pia_skeleton(
                pia_filepath, skeleton)
        else:
            skeleton_match, skeleton = _utter_check_for_pia_skeleton(
                pia_filepath, armature)
            # print('%r - %s' %(os.path.basename(pia_filepath), skeleton_match))
            # print('  skeleton: %r' % skeleton)
            if skeleton_match:
                path = os.path.split(pia_filepath)[0]
                pis_filepath = os.path.join(path, skeleton)
                if os.path.isfile(pis_filepath):
                    # print('  pis_filepath: %r' % pis_filepath)
                    bones = _pis.load(pis_filepath, armature)
                else:
                    lprint("""\nE The filepath "%s" doesn't exist!""",
                           (pis_filepath.replace("\\", "/"), ))

        if skeleton_match:
            lprint('I ++ "%s" IMPORTING animation data...',
                   (os.path.basename(pia_filepath), ))
            pia_container, state = _pix_parser.read_data(pia_filepath, ind)
            if not pia_container:
                lprint('\nE File "%s" is empty!',
                       (pia_filepath.replace("\\", "/"), ))
                return {'CANCELLED'}
            if state == 'ERR':
                lprint('\nE File "%s" is not SCS Animation file!',
                       (pia_filepath.replace("\\", "/"), ))
                return {'CANCELLED'}

            # TEST PRINTOUTS
            # ind = '  '
            # for section in pia_container:
            # print('SEC.: "%s"' % section.type)
            # for prop in section.props:
            # print('%sProp: %s' % (ind, prop))
            # for data in section.data:
            # print('%sdata: %s' % (ind, data))
            # for sec in section.sections:
            # print_section(sec, ind)
            # print('\nTEST - Source: "%s"' % pia_container[0].props[1][1])
            # print('')

            # TEST EXPORT
            # path, file = os.path.splitext(pia_filepath)
            # export_filepath = str(path + '_reex' + file)
            # result = pix_write.write_data(pia_container, export_filepath, ind)
            # if result == {'FINISHED'}:
            # Print(dump_level, '\nI Test export succesful! The new file:\n  "%s"', export_filepath)
            # else:
            # Print(dump_level, '\nE Test export failed! File:\n  "%s"', export_filepath)

            # LOAD HEADER
            format_version, source, f_type, animation_name, source_filename, author = _get_header(
                pia_container)
            if format_version != 3 or f_type != "Animation":
                return {'CANCELLED'}

            # LOAD GLOBALS
            skeleton, total_time, bone_channel_count, custom_channel_count = _get_globals(
                pia_container)

            # CREATE ANIMATION ACTIONS
            anim_action = bpy.data.actions.new(animation_name)
            anim_action.use_fake_user = True
            if total_time:
                anim_action.scs_props.action_length = total_time
            anim_data = armature.animation_data_create()
            anim_data.action = anim_action

            # LOAD BONE CHANNELS
            # print(' * armature: %r' % armature.name)
            if bone_channel_count > 0:
                bone_channels = _get_anim_channels(pia_container,
                                                   section_name="BoneChannel")

                # ...
                for bone_name in bone_channels:
                    # bone_name = channel[0]
                    if bone_name in armature.data.bones:
                        # print('%r is in armature %r' % (bone_name, armature.name))
                        '''
                        NOTE: skipped for now as no data needs to be readed
                        stream_count = bone_channels[bone_name][0]
                        keyframe_count = bone_channels[bone_name][1]
                        '''
                        streams = bone_channels[bone_name][2]
                        # print('  channel %r - streams %s - keyframes %s' % (bone_name, stream_count, keyframe_count))

                        # CREATE ANIMATION GROUP
                        anim_group = anim_action.groups.new(bone_name)
                        armature.pose.bones[
                            bone_name].rotation_mode = 'XYZ'  # Set rotation mode.
                        active_bone = armature.data.bones[bone_name]
                        # parent_bone = active_bone.parent

                        # CREATE FCURVES
                        (pos_fcurves, rot_fcurves,
                         sca_fcurves) = _create_fcurves(
                             anim_action, anim_group,
                             str('pose.bones["' + bone_name + '"]'))

                        # GET BONE REST POSITION MATRIX
                        bone_rest_matrix = active_bone.matrix_local
                        bone_rest_matrix_scs = bones[bone_name][1].transposed()
                        parent_bone_name = bones[bone_name][0]
                        if parent_bone_name in bones:
                            parent_bone_rest_matrix_scs = bones[
                                parent_bone_name][1].transposed()
                        else:
                            parent_bone_rest_matrix_scs = Matrix()
                            parent_bone_rest_matrix_scs.identity()

                            # if bone_name in ('LeftHand1', 'LeftHand'):
                            # print('\n  %r - bone_rest_matrix_scs:\n%s' % (bone_name, bone_rest_matrix_scs))
                            # print('  %r - bone_rest_matrix:\n%s' % (bone_name, bone_rest_matrix))
                            # print('  %r - parent_bone_rest_matrix_scs:\n%s' % (bone_name, parent_bone_rest_matrix_scs))

                        for key_time_i, key_time in enumerate(streams[0]):
                            # print(' key_time: %s' % str(key_time[0]))
                            # keyframe = key_time_i * (key_time[0] * 10) ## TODO: Do proper timing...
                            keyframe = key_time_i + 1

                            # GET BONE ANIMATION MATRIX
                            bone_animation_matrix_scs = streams[1][
                                key_time_i].transposed()
                            # if bone_name in ('LeftHand1', 'LeftHand') and key_time_i == 0: print('  %r - bone_animation_matrix_scs (%i):\n%s' % (
                            # bone_name, key_time_i, bone_animation_matrix_scs))

                            # CREATE DELTA MATRIX
                            delta_matrix = _get_delta_matrix(
                                bone_rest_matrix, bone_rest_matrix_scs,
                                parent_bone_rest_matrix_scs,
                                bone_animation_matrix_scs, import_scale)

                            # DECOMPOSE ANIMATION MATRIX
                            location, rotation, scale = delta_matrix.decompose(
                            )
                            # if bone_name in ('left_leg', 'root') and key_time_i == 0: print('  location:\n%s' % str(location))
                            rotation = rotation.to_euler('XYZ')

                            # BUILD TRANSLATION CURVES
                            pos_fcurves[0].keyframe_points.insert(
                                frame=float(keyframe),
                                value=location[0],
                                options={'FAST'})
                            pos_fcurves[1].keyframe_points.insert(
                                frame=float(keyframe),
                                value=location[1],
                                options={'FAST'})
                            pos_fcurves[2].keyframe_points.insert(
                                frame=float(keyframe),
                                value=location[2],
                                options={'FAST'})

                            # BUILD ROTATION CURVES
                            rot_fcurves[0].keyframe_points.insert(
                                frame=float(keyframe),
                                value=rotation[0],
                                options={'FAST'})
                            rot_fcurves[1].keyframe_points.insert(
                                frame=float(keyframe),
                                value=rotation[1],
                                options={'FAST'})
                            rot_fcurves[2].keyframe_points.insert(
                                frame=float(keyframe),
                                value=rotation[2],
                                options={'FAST'})

                            # BUILD SCALE CURVES
                            sca_fcurves[0].keyframe_points.insert(
                                frame=float(keyframe),
                                value=scale[0],
                                options={'FAST'})
                            sca_fcurves[1].keyframe_points.insert(
                                frame=float(keyframe),
                                value=scale[1],
                                options={'FAST'})
                            sca_fcurves[2].keyframe_points.insert(
                                frame=float(keyframe),
                                value=scale[2],
                                options={'FAST'})

                        # SET LINEAR INTERPOLATION FOR ALL CURVES
                        color_mode = 'AUTO_RAINBOW'  # Or better 'AUTO_RGB'?
                        for curve in pos_fcurves:
                            curve.color_mode = color_mode
                            for keyframe in curve.keyframe_points:
                                keyframe.interpolation = 'LINEAR'
                        for curve in rot_fcurves:
                            curve.color_mode = color_mode
                            for keyframe in curve.keyframe_points:
                                keyframe.interpolation = 'LINEAR'
                        for curve in sca_fcurves:
                            curve.color_mode = color_mode
                            for keyframe in curve.keyframe_points:
                                keyframe.interpolation = 'LINEAR'

                                # LOAD CUSTOM CHANNELS (ARMATURE OFFSET ANIMATION)
            # if custom_channel_count > 0: ## NOTE: Can't be used because exporter from Maya saves always 0 even if there are Custom Channels.
            custom_channels = _get_anim_channels(pia_container,
                                                 section_name="CustomChannel")
            if len(custom_channels) > 0:
                for channel_name in custom_channels:
                    # print(' >>> channel %r - %s' % (channel_name, str(custom_channels[channel_name])))
                    if channel_name == 'Prism Movement':
                        '''
                        NOTE: skipped for now as no data needs to be readed
                        stream_count = custom_channels[channel_name][0]
                        keyframe_count = custom_channels[channel_name][1]
                        '''
                        streams = custom_channels[channel_name][2]
                        # print('  channel %r - streams %s - keyframes %s' % (channel_name, stream_count, keyframe_count))

                        # CREATE ANIMATION GROUP
                        # anim_group = anim_action.groups.new(channel_name)
                        anim_group = anim_action.groups.new('Location')
                        # armature.[channel_name].rotation_mode = 'XYZ' ## Set rotation mode.
                        # active_bone = armature.data.bones[channel_name]
                        # parent_bone = active_bone.parent

                        # CREATE FCURVES
                        # pos_fcurves, rot_fcurves, sca_fcurves = _create_fcurves(anim_action, anim_group, anim_curve, rot_euler=True,
                        # types='LocRotSca')
                        # pos_fcurves, rot_fcurves, sca_fcurves = _create_fcurves(anim_action, anim_group, anim_curve, types='Loc')
                        fcurve_pos_x = anim_action.fcurves.new('location', 0)
                        fcurve_pos_y = anim_action.fcurves.new('location', 1)
                        fcurve_pos_z = anim_action.fcurves.new('location', 2)
                        fcurve_pos_x.group = anim_group
                        fcurve_pos_y.group = anim_group
                        fcurve_pos_z.group = anim_group
                        pos_fcurves = (fcurve_pos_x, fcurve_pos_y,
                                       fcurve_pos_z)

                        location = None
                        for key_time_i, key_time in enumerate(streams[0]):
                            # print(' key_time: %s' % str(key_time[0]))
                            # keyframe = key_time_i * (key_time[0] * 10) ## TODO: Do proper timing...
                            keyframe = key_time_i + 1
                            scs_offset = _convert_utils.change_to_scs_xyz_coordinates(
                                custom_channels[channel_name][2][1]
                                [key_time_i], import_scale)
                            offset = Vector(scs_offset)
                            if location is None:
                                location = offset
                            else:
                                location = location + offset
                            # print(' > location: %s' % str(location))

                            # BUILD TRANSLATION CURVES
                            pos_fcurves[0].keyframe_points.insert(
                                frame=float(keyframe),
                                value=location[0],
                                options={'FAST'})
                            pos_fcurves[1].keyframe_points.insert(
                                frame=float(keyframe),
                                value=location[1],
                                options={'FAST'})
                            pos_fcurves[2].keyframe_points.insert(
                                frame=float(keyframe),
                                value=location[2],
                                options={'FAST'})

                        # SET LINEAR INTERPOLATION FOR ALL CURVES
                        for curve in pos_fcurves:
                            for keyframe in curve.keyframe_points:
                                keyframe.interpolation = 'LINEAR'
                    else:
                        lprint('W Unknown channel %r in "%s" file.',
                               (channel_name, os.path.basename(pia_filepath)))

                        # CREATE SCS ANIMATION
            animation = _animation_utils.add_animation_to_root(
                root_object, animation_name)
            animation.export = True
            animation.action = anim_action.name
            animation.anim_start = anim_action.frame_range[0]
            animation.anim_end = anim_action.frame_range[1]
            # animation.anim_export_step =
            # animation.anim_export_filepath =
            if total_time:
                animation.length = total_time

                # WARNING PRINTOUTS
                # if piece_count < 0: Print(dump_level, '\nW More Pieces found than were declared!')
                # if piece_count > 0: Print(dump_level, '\nW Some Pieces not found, but were declared!')
                # if dump_level > 1: print('')
        else:
            lprint('I    "%s" file REJECTED',
                   (os.path.basename(pia_filepath), ))

    print("************************************")
    return {'FINISHED'}
Esempio n. 11
0
    def apply_T(self, transform: Union[np.ndarray, Matrix]):
        """ Apply the given transformation to the pose of the entity.

        :param transform: A 4x4 matrix representing the transformation.
        """
        self.blender_obj.matrix_world @= Matrix(transform)
Esempio n. 12
0
def bvh_node_dict2armature(context,
                           bvh_name,
                           bvh_nodes,
                           rotate_mode='XYZ',
                           frame_start=1,
                           IMPORT_LOOP=False):

    if frame_start < 1:
        frame_start = 1

    # Add the new armature,
    scene = context.scene
    for obj in scene.objects:
        obj.select = False

    arm_data = bpy.data.armatures.new(bvh_name)
    arm_ob = bpy.data.objects.new(bvh_name, arm_data)

    scene.objects.link(arm_ob)

    arm_ob.select = True
    scene.objects.active = arm_ob

    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
    bpy.ops.object.mode_set(mode='EDIT', toggle=False)

    # Get the average bone length for zero length bones, we may not use this.
    average_bone_length = 0.0
    nonzero_count = 0
    for bvh_node in bvh_nodes.values():
        l = (bvh_node.rest_head_local - bvh_node.rest_tail_local).length
        if l:
            average_bone_length += l
            nonzero_count += 1

    # Very rare cases all bones couldbe zero length???
    if not average_bone_length:
        average_bone_length = 0.1
    else:
        # Normal operation
        average_bone_length = average_bone_length / nonzero_count

    # XXX, annoying, remove bone.
    while arm_data.edit_bones:
        arm_ob.edit_bones.remove(arm_data.edit_bones[-1])

    ZERO_AREA_BONES = []
    for name, bvh_node in bvh_nodes.items():
        # New editbone
        bone = bvh_node.temp = arm_data.edit_bones.new(name)

        bone.head = bvh_node.rest_head_world
        bone.tail = bvh_node.rest_tail_world

        # ZERO AREA BONES.
        if (bone.head - bone.tail).length < 0.001:
            if bvh_node.parent:
                ofs = bvh_node.parent.rest_head_local - bvh_node.parent.rest_tail_local
                if ofs.length:  # is our parent zero length also?? unlikely
                    bone.tail = bone.tail + ofs
                else:
                    bone.tail.y = bone.tail.y + average_bone_length
            else:
                bone.tail.y = bone.tail.y + average_bone_length

            ZERO_AREA_BONES.append(bone.name)

    for bvh_node in bvh_nodes.values():
        if bvh_node.parent:
            # bvh_node.temp is the Editbone

            # Set the bone parent
            bvh_node.temp.parent = bvh_node.parent.temp

            # Set the connection state
            if not bvh_node.has_loc and\
            bvh_node.parent and\
            bvh_node.parent.temp.name not in ZERO_AREA_BONES and\
            bvh_node.parent.rest_tail_local == bvh_node.rest_head_local:
                bvh_node.temp.use_connect = True

    # Replace the editbone with the editbone name,
    # to avoid memory errors accessing the editbone outside editmode
    for bvh_node in bvh_nodes.values():
        bvh_node.temp = bvh_node.temp.name

    # Now Apply the animation to the armature

    # Get armature animation data
    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

    pose = arm_ob.pose
    pose_bones = pose.bones

    if rotate_mode == 'NATIVE':
        for bvh_node in bvh_nodes.values():
            bone_name = bvh_node.temp  # may not be the same name as the bvh_node, could have been shortened.
            pose_bone = pose_bones[bone_name]
            pose_bone.rotation_mode = bvh_node.rot_order_str

    elif rotate_mode != 'QUATERNION':
        for pose_bone in pose_bones:
            pose_bone.rotation_mode = rotate_mode
    else:
        # Quats default
        pass

    context.scene.update()

    arm_ob.animation_data_create()
    action = bpy.data.actions.new(name=bvh_name)
    arm_ob.animation_data.action = action

    # Replace the bvh_node.temp (currently an editbone)
    # With a tuple  (pose_bone, armature_bone, bone_rest_matrix, bone_rest_matrix_inv)
    for bvh_node in bvh_nodes.values():
        bone_name = bvh_node.temp  # may not be the same name as the bvh_node, could have been shortened.
        pose_bone = pose_bones[bone_name]
        rest_bone = arm_data.bones[bone_name]
        bone_rest_matrix = rest_bone.matrix_local.to_3x3()

        bone_rest_matrix_inv = Matrix(bone_rest_matrix)
        bone_rest_matrix_inv.invert()

        bone_rest_matrix_inv.resize_4x4()
        bone_rest_matrix.resize_4x4()
        bvh_node.temp = (pose_bone, bone, bone_rest_matrix,
                         bone_rest_matrix_inv)

    # Make a dict for fast access without rebuilding a list all the time.

    # KEYFRAME METHOD, SLOW, USE IPOS DIRECT
    # TODO: use f-point samples instead (Aligorith)
    if rotate_mode != 'QUATERNION':
        prev_euler = [Euler() for i in range(len(bvh_nodes))]

    # Animate the data, the last used bvh_node will do since they all have the same number of frames
    for frame_current in range(len(bvh_node.anim_data) -
                               1):  # skip the first frame (rest frame)
        # print frame_current

        # if frame_current==40: # debugging
        # 	break

        scene.frame_set(frame_start + frame_current)

        # Dont neet to set the current frame
        for i, bvh_node in enumerate(bvh_nodes.values()):
            pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv = bvh_node.temp
            lx, ly, lz, rx, ry, rz = bvh_node.anim_data[frame_current + 1]

            if bvh_node.has_rot:
                # apply rotation order and convert to XYZ
                # note that the rot_order_str is reversed.
                bone_rotation_matrix = Euler(
                    (rx, ry, rz),
                    bvh_node.rot_order_str[::-1]).to_matrix().to_4x4()
                bone_rotation_matrix = bone_rest_matrix_inv * bone_rotation_matrix * bone_rest_matrix

                if rotate_mode == 'QUATERNION':
                    pose_bone.rotation_quaternion = bone_rotation_matrix.to_quaternion(
                    )
                else:
                    euler = bone_rotation_matrix.to_euler(
                        bvh_node.rot_order_str, prev_euler[i])
                    pose_bone.rotation_euler = euler
                    prev_euler[i] = euler

            if bvh_node.has_loc:
                pose_bone.location = (
                    bone_rest_matrix_inv * Matrix.Translation(
                        Vector((lx, ly, lz)) -
                        bvh_node.rest_head_local)).to_translation()

            if bvh_node.has_loc:
                pose_bone.keyframe_insert("location")
            if bvh_node.has_rot:
                if rotate_mode == 'QUATERNION':
                    pose_bone.keyframe_insert("rotation_quaternion")
                else:
                    pose_bone.keyframe_insert("rotation_euler")

    for cu in action.fcurves:
        if IMPORT_LOOP:
            pass  # 2.5 doenst have cyclic now?

        for bez in cu.keyframe_points:
            bez.interpolation = 'LINEAR'

    return arm_ob
Esempio n. 13
0
        def process(self):
            if not any(socket.is_linked for socket in self.outputs):
                return

            fields_s = self.inputs['Field'].sv_get()
            min_x_s = self.inputs['MinX'].sv_get()
            max_x_s = self.inputs['MaxX'].sv_get()
            min_y_s = self.inputs['MinY'].sv_get()
            max_y_s = self.inputs['MaxY'].sv_get()
            value_s = self.inputs['Value'].sv_get()
            z_value_s = self.inputs['Z'].sv_get()
            samples_s = self.inputs['Samples'].sv_get()
            matrix_s = self.inputs['Matrix'].sv_get(default=[Matrix()])

            value_s = ensure_nesting_level(value_s, 2)
            z_value_s = ensure_nesting_level(z_value_s, 2)
            fields_s = ensure_nesting_level(fields_s,
                                            2,
                                            data_types=(SvScalarField, ))
            matrix_s = ensure_nesting_level(matrix_s, 2, data_types=(Matrix, ))

            parameters = zip_long_repeat(fields_s, matrix_s, min_x_s, max_x_s,
                                         min_y_s, max_y_s, z_value_s, value_s,
                                         samples_s)

            verts_out = []
            edges_out = []
            faces_out = []
            for field_i, matrix_i, min_x_i, max_x_i, min_y_i, max_y_i, z_value_i, value_i, samples_i in parameters:
                objects = zip_long_repeat(field_i, matrix_i, min_x_i, max_x_i,
                                          min_y_i, max_y_i, z_value_i, value_i,
                                          samples_i)
                for field, matrix, min_x, max_x, min_y, max_y, z_value, value, samples in objects:

                    has_matrix = matrix != Matrix()

                    x_range = np.linspace(min_x, max_x, num=samples)
                    y_range = np.linspace(min_y, max_y, num=samples)
                    z_range = np.array([z_value])
                    xs, ys, zs = np.meshgrid(x_range,
                                             y_range,
                                             z_range,
                                             indexing='ij')
                    xs, ys, zs = xs.flatten(), ys.flatten(), zs.flatten()
                    if has_matrix:
                        xs, ys, zs = self.apply_matrix(matrix, xs, ys, zs)
                    field_values = field.evaluate_grid(xs, ys, zs)
                    field_values = field_values.reshape((samples, samples))

                    contours = measure.find_contours(field_values, level=value)

                    x_size = (max_x - min_x) / samples
                    y_size = (max_y - min_y) / samples

                    new_verts, new_edges, new_faces = make_contours(
                        samples,
                        samples,
                        min_x,
                        x_size,
                        min_y,
                        y_size,
                        z_value,
                        contours,
                        make_faces=self.make_faces,
                        connect_bounds=self.connect_bounds)
                    if has_matrix:
                        new_verts = self.unapply_matrix(matrix, new_verts)
                    verts_out.extend(new_verts)
                    edges_out.extend(new_edges)
                    faces_out.extend(new_faces)

            self.outputs['Vertices'].sv_set(verts_out)
            self.outputs['Edges'].sv_set(edges_out)
            self.outputs['Faces'].sv_set(faces_out)
Esempio n. 14
0
def to_interop_matrix4x4(mat):
    """Convert the input matrix to an InteropMatrix4x4

    Args:
        mat (float[]):  float multi-dimensional array of 4 * 4 items in [-inf, inf]. E.g.
                        ((1.0, 0.0, 0.0, 0.0), (0.0, 1.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, 0.0, 0.0, 1.0))
    Returns:
        InteropMatrix4x4
    """
    raise NotImplementedError(
        'Matrices not supported anymore due to laziness. Upgrade.')

    # Swap euler y/z angles
    eul = mat.to_euler()
    eul.yz = eul.zy
    rot = eul.to_matrix().to_4x4()

    # Swap translation y/z
    t = mat.to_translation()
    loc = Matrix.Translation((t.x, t.z, t.y))

    sca = mat.to_scale()
    scal.yz = sca.zy
    sca = sca.to_matrix().to_4x4()

    sca = Matrix.Scale(0.5, 4, (0.0, 0.0, 1.0))

    m = loc @ rot @ sca

    RHS_Z_TO_LHS_Y = Matrix(((1.0, 0.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0),
                             (0.0, 1.0, 0.0, 0.0), (0.0, 0.0, 0.0, 1.0)))

    # Math is still all wrong, also, not even going to bother at this point.
    # I'd rather transfer with 3 vec3s and reconstruct on unity's side.
    # It makes space transforms / swaps a lot easier.

    # Convert Blender's RHS Z-up matrix to Unity's LHS Y-up
    #m = mat * Matrix.Rotation(math.radians(90.0), 4, 'X') # RHS_Z_TO_LHS_Y @ mat
    m = mat

    result = InteropMatrix4x4()
    result.m00 = m[0][0]
    result.m01 = m[0][1]
    result.m02 = m[0][2]
    result.m03 = m[0][3]

    result.m10 = m[1][0]
    result.m11 = m[1][1]
    result.m12 = m[1][2]
    result.m13 = m[1][3]

    result.m20 = m[2][0]
    result.m21 = m[2][1]
    result.m22 = m[2][2]
    result.m23 = m[2][3]

    result.m30 = m[3][0]
    result.m31 = m[3][1]
    result.m32 = m[3][2]
    result.m33 = m[3][3]

    # Space conversion here!

    # position is easy - rotation is not.

    return result
Esempio n. 15
0
def import_modes(context, report, filepath, file_format, molecule):

    logger.info("Reading modes file {}".format(filepath))
    try:
        qpts = mb_io_files.MB_Modes.from_file(filepath, file_format)

        if not qpts or not qpts[0].modes:
            msg = "No modes found in {}\n".format(bpy.path.basename(filepath))
            msg += "Did you chose the correct file format?"
            report({'ERROR'}, msg)
            return False

        nat = len(molecule.objects.atoms)
        for qmode in qpts:
            if np.linalg.norm(qmode.qvec) and not molecule["unit_cells"]:
                msg = "Can't convert qvecs to crystal coordinates because no"
                msg += " unit cell information is present"
                logger.error(msg)
                report({'ERROR'}, msg)
            for mode in qmode.modes:
                if nat % len(mode.evecs) != 0:
                    msg = "number of displacement vectors "
                    msg += "{}".format(len(mode.evecs))
                    msg += " is different than number of atoms {}".format(nat)
                    msg += " in active molecule."
                    logger.error(msg)
                    report({'ERROR'}, msg)
                    return False

        # This is only used for Quantum ESPRESSO, to calculate the crystal unit
        # cell. The cartesian unit cell is not written in the mode output, so
        # the conversion can't be done when reading the data.
        uc = Matrix(molecule["unit_cells"][0]) * 1.889725989
        k_uc = Matrix(
            [uc[(dim + 1) % 3].cross(uc[(dim + 2) % 3]) for dim in range(3)])
        fac = 2 * math.pi / uc[0].dot(uc[1].cross(uc[2]))
        k_uc = k_uc * fac
        inv_k_uc = k_uc.inverted()

        if qpts[0].qvecs_format == "QE":
            for nq, qmode in enumerate(qpts):
                qmode.qvec = (Vector(qmode.qvec) * 2 * math.pi /
                              uc[0][0]) * inv_k_uc
    except:
        msg = "{} could not be imported. Check console.".format(filepath)
        report({'ERROR'}, msg)
        logger.exception("")
        return False
    logger.debug("Found {} q-points".format(len(qpts)))
    old_sel = context.selected_objects
    last_active = context.object
    try:
        # clear old modes first
        while len(molecule.qvecs):
            last = len(molecule.qvecs) - 1
            qv = molecule.qvecs[last]
            if qv.mode_txt:
                bpy.data.texts.remove(qv.mode_txt, do_unlink=True)
            molecule.qvecs.remove(last)

        # Saving as file and loading is faster than writing to BlendDataText
        txt_list = []
        txtname_fmt = ".modes_{}_qpt-{}.json"
        print("Start loading")
        for iq, qmode in enumerate(qpts):
            print(iq)
            logger.debug("Loading qpt {} as BlendDataText".format(qmode.iqpt))
            qv = molecule.qvecs.add()
            qv.qvec = qmode.qvec
            qv.iqpt = qmode.iqpt
            with tempfile.NamedTemporaryFile(mode='w+') as fout:
                for line in qmode.lines_iter():
                    fout.write(line)
                fout.flush()
                try:
                    txt = bpy.data.texts.load(filepath=fout.name,
                                              internal=True)
                    txt_list.append(txt)
                except:
                    logger.error("Problem with qpt {}".format(qmode.iqpt))
                    raise
            txt.name = txtname_fmt.format(molecule.name, qmode.iqpt)
            qv.mode_txt = txt
            txt.mb.parent = molecule.objects.parent
            txt.mb.type = "MODES"

        logger.debug("Done loading modes")

        for atom in molecule.objects.atoms:
            mb_utils.create_mode_action(context, atom, molecule)
            mb_utils.create_mode_arrow(context, atom, molecule, type='3D')

        molecule.active_mode = 0

        if len(qpts) > 1 and file_format == "PHONOPY":
            report({'WARNING'}, "Please check if q!=0 modes have been imported"
                   " properly. If not, please notify Flo to fix it.")
        return True
    except:
        for txt in txt_list:
            bpy.data.texts.remove(txt)
        while len(molecule.qvecs):
            last = len(molecule.qvecs) - 1
            qv = molecule.qvecs[last]
            if qv.mode_txt:
                bpy.data.texts.remove(qv.mode_txt, do_unlink=True)
            molecule.qvecs.remove(last)
        msg = "Modes were read but couldn't be imported. Check console."
        report({'ERROR'}, msg)
        logger.exception("")
        return False
    finally:
        bpy.ops.object.select_all(action="DESELECT")
        for ob in old_sel:
            ob.select = True
        context.scene.objects.active = last_active
Esempio n. 16
0
def blen_read_object(fbx_tmpl, fbx_obj, object_data):
    elem_name, elem_class = elem_split_name_class(fbx_obj)
    elem_name_utf8 = elem_name.decode('utf-8')

    const_vector_zero_3d = 0.0, 0.0, 0.0
    const_vector_one_3d = 1.0, 1.0, 1.0

    # Object data must be created already
    obj = bpy.data.objects.new(name=elem_name_utf8, object_data=object_data)

    fbx_props = (elem_find_first(fbx_obj, b'Properties70'),
                 elem_find_first(fbx_tmpl, b'Properties70', fbx_elem_nil))
    assert(fbx_props[0] is not None)

    # ----
    # Misc Attributes

    obj.color[0:3] = elem_props_get_color_rgb(fbx_props, b'Color', (0.8, 0.8, 0.8))

    # ----
    # Transformation

    # This is quite involved, 'fbxRNode.cpp' from openscenegraph used as a reference

    loc = elem_props_get_vector_3d(fbx_props, b'Lcl Translation', const_vector_zero_3d)
    rot = elem_props_get_vector_3d(fbx_props, b'Lcl Rotation', const_vector_zero_3d)
    sca = elem_props_get_vector_3d(fbx_props, b'Lcl Scaling', const_vector_one_3d)

    rot_ofs = elem_props_get_vector_3d(fbx_props, b'RotationOffset', const_vector_zero_3d)
    rot_piv = elem_props_get_vector_3d(fbx_props, b'RotationPivot', const_vector_zero_3d)
    sca_ofs = elem_props_get_vector_3d(fbx_props, b'ScalingOffset', const_vector_zero_3d)
    sca_piv = elem_props_get_vector_3d(fbx_props, b'ScalingPivot', const_vector_zero_3d)

    is_rot_act = elem_props_get_bool(fbx_props, b'RotationActive', False)

    if is_rot_act:
        pre_rot = elem_props_get_vector_3d(fbx_props, b'PreRotation', const_vector_zero_3d)
        pst_rot = elem_props_get_vector_3d(fbx_props, b'PostRotation', const_vector_zero_3d)
        rot_ord = {
            0: 'XYZ',
            1: 'XYZ',
            2: 'XZY',
            3: 'YZX',
            4: 'YXZ',
            5: 'ZXY',
            6: 'ZYX',
            }.get(elem_props_get_enum(fbx_props, b'RotationOrder', 0))
    else:
        pre_rot = const_vector_zero_3d
        pst_rot = const_vector_zero_3d
        rot_ord = 'XYZ'

    from mathutils import Matrix, Euler
    from math import pi

    # translation
    lcl_translation = Matrix.Translation(loc)

    # rotation
    if obj.type == 'CAMERA':
        rot_alt_mat = Matrix.Rotation(pi / -2.0, 4, 'Y')
    elif obj.type == 'LAMP':
        rot_alt_mat = Matrix.Rotation(pi / -2.0, 4, 'X')
    else:
        rot_alt_mat = Matrix()

    # rotation
    lcl_rot = Euler(tuple_deg_to_rad(rot), rot_ord).to_matrix().to_4x4() * rot_alt_mat
    pre_rot = Euler(tuple_deg_to_rad(pre_rot), rot_ord).to_matrix().to_4x4()
    pst_rot = Euler(tuple_deg_to_rad(pst_rot), rot_ord).to_matrix().to_4x4()

    rot_ofs = Matrix.Translation(rot_ofs)
    rot_piv = Matrix.Translation(rot_piv)
    sca_ofs = Matrix.Translation(sca_ofs)
    sca_piv = Matrix.Translation(sca_piv)

    # scale
    lcl_scale = Matrix()
    lcl_scale[0][0], lcl_scale[1][1], lcl_scale[2][2] = sca

    obj.matrix_basis = (
        lcl_translation *
        rot_ofs *
        rot_piv *
        pre_rot *
        lcl_rot *
        pst_rot *
        rot_piv.inverted() *
        sca_ofs *
        sca_piv *
        lcl_scale *
        sca_piv.inverted()
        )

    return obj
Esempio n. 17
0
FBX_DEFORMER_CLUSTER_VERSION = 100
FBX_MATERIAL_VERSION = 102
FBX_TEXTURE_VERSION = 202
FBX_ANIM_KEY_VERSION = 4008

FBX_NAME_CLASS_SEP = b"\x00\x01"
FBX_ANIM_PROPSGROUP_NAME = "d"

FBX_KTIME = 46186158000  # This is the number of "ktimes" in one second (yep, precision over the nanosecond...)


MAT_CONVERT_LAMP = Matrix.Rotation(math.pi / 2.0, 4, 'X')  # Blender is -Z, FBX is -Y.
MAT_CONVERT_CAMERA = Matrix.Rotation(math.pi / 2.0, 4, 'Y')  # Blender is -Z, FBX is +X.
# XXX I can't get this working :(
# MAT_CONVERT_BONE = Matrix.Rotation(math.pi / 2.0, 4, 'Z')  # Blender is +Y, FBX is -X.
MAT_CONVERT_BONE = Matrix()


BLENDER_OTHER_OBJECT_TYPES = {'CURVE', 'SURFACE', 'FONT', 'META'}
BLENDER_OBJECT_TYPES_MESHLIKE = {'MESH'} | BLENDER_OTHER_OBJECT_TYPES


# Lamps.
FBX_LIGHT_TYPES = {
    'POINT': 0,  # Point.
    'SUN': 1,    # Directional.
    'SPOT': 2,   # Spot.
    'HEMI': 1,   # Directional.
    'AREA': 3,   # Area.
}
FBX_LIGHT_DECAY_TYPES = {
Esempio n. 18
0
    animations
        animation
            tracks
                track
                    keyframes
                        keyframe
                            translate
                            rotate
                                axis
"""

ZERO = Vector()
QUAT_ID = Quaternion((1.0, 0.0, 0.0, 0.0))
MAT4_ROT = Matrix((
    (0.0, 1.0, 0.0, 0.0),
    (-1.0, 0.0, 0.0, 0.0),
    (0.0, 0.0, 1.0, 0.0),
    (0.0, 0.0, 0.0, 1.0),
))
MAT4_ROT_INV = Matrix((
    (0.0, -1.0, 0.0, 0.0),
    (1.0, 0.0, 0.0, 0.0),
    (0.0, 0.0, 1.0, 0.0),
    (0.0, 0.0, 0.0, 1.0),
))
MAT3_ROT_INV = Matrix(((0, -1, 0), (1, 0, 0), (0, 0, 1)))
MAT_ROT_Y90_INV = Matrix((
    (0.0, 0.0, -1.0, 0.0),
    (0.0, 1.0, 0.0, 0.0),
    (1.0, 0.0, 0.0, 0.0),
    (0.0, 0.0, 0.0, 1.0),
))
Esempio n. 19
0
 def get_matrix_local(self):
     if self._tag == 'OB':
         return self.bdata.matrix_local.copy()
     elif self._tag == 'DP':
         return self._ref.matrix_world.inverted_safe() * self._dupli_matrix
     else:  # 'BO', current pose
         # PoseBone.matrix is in armature space, bring in back in real local one!
         par = self.bdata.parent
         par_mat_inv = self._ref.pose.bones[par.name].matrix.inverted_safe() if par else Matrix()
         return par_mat_inv * self._ref.pose.bones[self.bdata.name].matrix
Esempio n. 20
0
    def process(self):
        # inputs
        if not self.inputs['Vertices'].is_linked:
            return

        vertices_s = self.inputs['Vertices'].sv_get(deepcopy=False)
        edges_s = self.inputs['Edges'].sv_get(default=[[]], deepcopy=False)
        faces_s = self.inputs['Polygons'].sv_get(default=[[]], deepcopy=False)
        masks_s = self.inputs['Mask'].sv_get(default=[[1]], deepcopy=False)
        if self.transform_mode == "Matrix":
            matrices_s = [
                self.inputs['Matrices'].sv_get(default=[Matrix()],
                                               deepcopy=False)
            ]
            heights_s = [0.0]
            scales_s = [1.0]
        else:
            matrices_s = [[]]
            heights_s = self.inputs['Height'].sv_get(deepcopy=False)
            scales_s = self.inputs['Scale'].sv_get(deepcopy=False)
        if 'FaceData' in self.inputs:
            face_data_s = self.inputs['FaceData'].sv_get(default=[[]],
                                                         deepcopy=False)
        else:
            face_data_s = [[]]

        need_mask_out = 'Mask' in self.outputs and self.outputs[
            'Mask'].is_linked

        result_vertices = []
        result_edges = []
        result_faces = []
        result_ext_vertices = []
        result_ext_edges = []
        result_ext_faces = []
        result_face_data = []
        result_mask = []

        meshes = match_long_repeat([
            vertices_s, edges_s, faces_s, masks_s, matrices_s, heights_s,
            scales_s, face_data_s
        ])

        for vertices, edges, faces, masks, matrix_per_iteration, height_per_iteration, scale_per_iteration, face_data in zip(
                *meshes):
            if self.transform_mode == "Matrix":
                if not matrix_per_iteration:
                    matrix_per_iteration = [Matrix()]

            if self.multiple:
                if self.transform_mode == "Matrix":
                    n_iterations = len(matrix_per_iteration)
                else:
                    n_iterations = max(len(height_per_iteration),
                                       len(scale_per_iteration))
                    height_per_iteration_matched = repeat_last_for_length(
                        height_per_iteration, n_iterations)
                    scale_per_iteration_matched = repeat_last_for_length(
                        scale_per_iteration, n_iterations)
            else:
                n_iterations = 1
                matrix_per_iteration = [matrix_per_iteration]

            mask_matched = repeat_last_for_length(masks, len(faces))
            if face_data:
                face_data_matched = repeat_last_for_length(
                    face_data, len(faces))

            bm = bmesh_from_pydata(vertices,
                                   edges,
                                   faces,
                                   normal_update=True,
                                   markup_face_data=True)
            mask_layer = bm.faces.layers.int.new('mask')
            bm.faces.ensure_lookup_table()
            #fill_faces_layer(bm, masks, 'mask', int, MASK, invert_mask=True)

            b_faces = []
            b_edges = set()
            b_verts = set()
            for mask, face in zip(mask_matched, bm.faces):
                if mask:
                    b_faces.append(face)
                    for edge in face.edges:
                        b_edges.add(edge)
                    for vert in face.verts:
                        b_verts.add(vert)

            extrude_geom = b_faces + list(b_edges) + list(b_verts)

            extruded_verts_last = []
            extruded_bm_verts_all = set()
            extruded_edges_last = []
            extruded_faces_last = []
            extruded_bm_faces_last = []

            matrix_spaces = [Matrix()]

            for idx in range(n_iterations):

                for item in extrude_geom:
                    if isinstance(item, bmesh.types.BMFace):
                        item[mask_layer] = OUT

                if is_290:
                    kwargs = {
                        'use_dissolve_ortho_edges': self.dissolve_ortho_edges
                    }
                else:
                    kwargs = {}

                new_geom = bmesh.ops.extrude_face_region(
                    bm,
                    geom=extrude_geom,
                    edges_exclude=set(),
                    use_keep_orig=self.keep_original,
                    **kwargs)['geom']

                extruded_verts = [
                    v for v in new_geom if isinstance(v, bmesh.types.BMVert)
                ]
                extruded_faces = [
                    f for f in new_geom if isinstance(f, bmesh.types.BMFace)
                ]

                if self.transform_mode == "Matrix":
                    matrices = matrix_per_iteration[idx]
                    if isinstance(matrices, Matrix):
                        matrices = [matrices]
                    matrix_spaces_matched = repeat_last_for_length(
                        matrix_spaces, len(extruded_verts))
                    for vertex_idx, (vertex, matrix) in enumerate(
                            zip(*match_long_repeat([extruded_verts, matrices
                                                    ]))):
                        bmesh.ops.transform(
                            bm,
                            verts=[vertex],
                            matrix=matrix,
                            space=matrix_spaces_matched[vertex_idx])
                        matrix_spaces_matched[vertex_idx] = matrix.inverted(
                        ) @ matrix_spaces_matched[vertex_idx]
                else:
                    height = height_per_iteration_matched[idx]
                    scale = scale_per_iteration_matched[idx]

                    normal = get_avg_normal(extruded_faces)
                    dr = normal * height
                    center = get_faces_center(extruded_faces)
                    translation = Matrix.Translation(center)
                    rotation = normal.rotation_difference(
                        (0, 0, 1)).to_matrix().to_4x4()
                    m = translation @ rotation
                    bmesh.ops.scale(bm,
                                    vec=(scale, scale, scale),
                                    space=m.inverted(),
                                    verts=extruded_verts)
                    bmesh.ops.translate(bm, verts=extruded_verts, vec=dr)

                extruded_bm_verts_all.update(extruded_verts)
                extruded_verts_last = [tuple(v.co) for v in extruded_verts]

                extruded_edges = [
                    e for e in new_geom if isinstance(e, bmesh.types.BMEdge)
                ]
                extruded_edges_last = [
                    tuple(v.index for v in edge.verts)
                    for edge in extruded_edges
                ]

                extruded_bm_faces_last = extruded_faces
                extruded_faces_last = [[v.index for v in face.verts]
                                       for face in extruded_faces]

                extrude_geom = new_geom

            if face_data:
                new_vertices, new_edges, new_faces, new_face_data = pydata_from_bmesh(
                    bm, face_data_matched)
            else:
                new_vertices, new_edges, new_faces = pydata_from_bmesh(bm)
                new_face_data = []

            if need_mask_out:
                new_mask = self.get_out_mask(bm, extruded_bm_faces_last,
                                             extruded_bm_verts_all)
                result_mask.append(new_mask)

            bm.free()

            result_vertices.append(new_vertices)
            result_edges.append(new_edges)
            result_faces.append(new_faces)
            result_ext_vertices.append(extruded_verts_last)
            result_ext_edges.append(extruded_edges_last)
            result_ext_faces.append(extruded_faces_last)
            result_face_data.append(new_face_data)

        self.outputs['Vertices'].sv_set(result_vertices)
        self.outputs['Edges'].sv_set(result_edges)
        self.outputs['Polygons'].sv_set(result_faces)
        self.outputs['NewVertices'].sv_set(result_ext_vertices)
        self.outputs['NewEdges'].sv_set(result_ext_edges)
        self.outputs['NewFaces'].sv_set(result_ext_faces)
        if 'Mask' in self.outputs:
            self.outputs['Mask'].sv_set(result_mask)
        if 'FaceData' in self.outputs:
            self.outputs['FaceData'].sv_set(result_face_data)
Esempio n. 21
0
def updateMatrixTable(evp, drw, jnt, currPacket, multiMatrixTable, matrixTable,
                      isMatrixWeighted, use_scale):
    global dataholder
    for n in range(len(currPacket.matrixTable)):
        index = currPacket.matrixTable[n]

        # if index is 0xffff, use the last packet's data.
        if index != 0xffff:  # 0xffff this means keep old entry
            if drw.isWeighted[index]:  # corrected
                # --TODO: the EVP1 data should probably be used here,
                # --figure out how this works (most files look ok
                # --without this, but models/ji.bdl is for example
                # --broken this way)
                # --matrixTable[n] = def_;

                # --the following _does_ the right thing...it looks
                # --ok for all files, but i don't understand why :-P
                # --(and this code is slow as hell, so TODO: fix this)

                # --NO idea if this is right this way...
                m = Matrix()
                m.zero()  # zero-ifiy m

                mm = evp.weightedIndices[
                    drw.data[index]]  # -- get MultiMatrix # corrected
                singleMultiMatrixEntry = MultiMatrix()

                singleMultiMatrixEntry.weights = mm.weights.copy()
                singleMultiMatrixEntry.indices = mm.indices.copy()
                for r in range(len(mm.weights)):
                    # did before.
                    #singleMultiMatrixEntry.weights[r] = mm.weights[r]
                    #singleMultiMatrixEntry.indices[r] = mm.indices[r]

                    # corrected (r]+1) # -- (drw.data[mm.indices[r]+ 1] + 1) -- bone index
                    # --  messageBox (mm.indices as string)
                    # --if (mm.indices[r] != 0) then
                    # -- (
                    sm1 = evp.matrices[mm.indices[r]]  # -- const Matrix44f
                    sm2 = LocalMatrix(jnt, mm.indices[r], use_scale)
                    sm3 = sm2 * sm1
                    # )
                    # else
                    # --	sm3 = (LocalMatrix mm.indices[r] )

                    Mad(m, sm3, mm.weights[r])

                while len(multiMatrixTable) <= n:
                    multiMatrixTable.append(None)
                multiMatrixTable[n] = singleMultiMatrixEntry
                m[3][3] = 1  # fixed
                while len(matrixTable) <= n:
                    matrixTable.append(None)
                matrixTable[n] = m
                while len(isMatrixWeighted) <= n:
                    isMatrixWeighted.append(None)
                isMatrixWeighted[n] = True
            else:
                while len(matrixTable) <= n:
                    matrixTable.append(None)
                while len(isMatrixWeighted) <= n:
                    isMatrixWeighted.append(None)
                matrixTable[n] = jnt.frames[
                    drw.data[index]].matrix  # corrected x2
                isMatrixWeighted[n] = False

                singleMultiMatrixEntry = MultiMatrix()
                singleMultiMatrixEntry.weights = [1]
                singleMultiMatrixEntry.indices = [
                    drw.data[index]
                ]  # corrected x2  # -- bone index

                while len(multiMatrixTable) <= n:
                    multiMatrixTable.append(None)
                multiMatrixTable[n] = singleMultiMatrixEntry
Esempio n. 22
0
def bCreateSkeleton(meshData, name):

    if 'skeleton' not in meshData:
        return
    bonesData = meshData['skeleton']

    # create Armature
    amt = bpy.data.armatures.new(name)
    rig = bpy.data.objects.new(name, amt)
    #rig.location = origin
    rig.show_x_ray = True
    #amt.show_names = True
    # Link object to scene
    scn = bpy.context.scene
    scn.objects.link(rig)
    scn.objects.active = rig
    scn.update()

    bpy.ops.object.mode_set(mode='EDIT')
    for bone in bonesData.keys():
        boneData = bonesData[bone]
        boneName = boneData['name']

        children = boneData['children']
        boneObj = amt.edit_bones.new(boneName)
        #boneObj.head = boneData['posHAS']
        #headPos = boneData['posHAS']
        headPos = boneData['posHAS']
        tailVector = 0.2
        if len(children) == 1:
            tailVector = calcBoneLength(bonesData[children[0]]['position'])

        #boneObj.head = Vector([headPos[0],-headPos[2],headPos[1]])
        #boneObj.tail = Vector([headPos[0],-headPos[2],headPos[1] + tailVector])

        #print("bCreateSkeleton: bone=%s, boneObj.head=%s" % (bone, boneObj.head))
        #print("bCreateSkeleton: bone=%s, boneObj.tail=%s" % (bone, boneObj.tail))
        #boneObj.matrix =
        rotmat = boneData['rotmatAS']
        #print(rotmat[1].to_tuple())
        #boneObj.matrix = Matrix(rotmat[1],rotmat[0],rotmat[2])
        if blender_version <= 262:
            r0 = [rotmat[0].x] + [rotmat[0].y] + [rotmat[0].z]
            r1 = [rotmat[1].x] + [rotmat[1].y] + [rotmat[1].z]
            r2 = [rotmat[2].x] + [rotmat[2].y] + [rotmat[2].z]
            boneRotMatrix = Matrix((r1, r0, r2))
        elif blender_version > 262:
            # this is fugly was of flipping matrix
            r0 = [rotmat.col[0].x] + [rotmat.col[0].y] + [rotmat.col[0].z]
            r1 = [rotmat.col[1].x] + [rotmat.col[1].y] + [rotmat.col[1].z]
            r2 = [rotmat.col[2].x] + [rotmat.col[2].y] + [rotmat.col[2].z]
            tmpR = Matrix((r1, r0, r2))
            boneRotMatrix = Matrix((tmpR.col[0], tmpR.col[1], tmpR.col[2]))

        #pos = Vector([headPos[0],-headPos[2],headPos[1]])
        #axis, roll = mat3_to_vec_roll(boneRotMatrix.to_3x3())

        #boneObj.head = pos
        #boneObj.tail = pos + axis
        #boneObj.roll = roll

        #print("bCreateSkeleton: bone=%s, newrotmat=%s" % (bone, Matrix((r1,r0,r2))))
        #print(r1)
        #mtx = Matrix.to_3x3()Translation(boneObj.head) # Matrix((r1,r0,r2))
        #boneObj.transform(Matrix((r1,r0,r2)))
        #print("bCreateSkeleton: bone=%s, matrix_before=%s" % (bone, boneObj.matrix))
        #boneObj.use_local_location = False
        #boneObj.transform(Matrix((r1,r0,r2)) , False, False)
        #print("bCreateSkeleton: bone=%s, matrix_after=%s" % (bone, boneObj.matrix))
        boneObj.head = Vector([0, 0, 0])
        #boneObj.tail = Vector([0,0,tailVector])
        boneObj.tail = Vector([0, tailVector, 0])
        #matx = Matrix.Translation(Vector([headPos[0],-headPos[2],headPos[1]]))

        boneObj.transform(boneRotMatrix)
        #scn.update()
        boneObj.translate(Vector([headPos[0], -headPos[2], headPos[1]]))
        #scn.update()
        #boneObj.translate(Vector([headPos[0],-headPos[2],headPos[1]]))
        #boneObj.head = Vector([headPos[0],-headPos[2],headPos[1]])
        #boneObj.tail = Vector([headPos[0],-headPos[2],headPos[1]]) + (Vector([0,0, tailVector])  * Matrix((r1,r0,r2)))

        #amt.bones[bone] = boneObj
        #amt.update_tag(refresh)

    # only after all bones are created we can link parents
    for bone in bonesData.keys():
        boneData = bonesData[bone]
        parent = None
        if 'parent' in boneData.keys():
            parent = boneData['parent']
            # get bone obj
            boneData = bonesData[bone]
            boneName = boneData['name']
            boneObj = amt.edit_bones[boneName]
            boneObj.parent = amt.edit_bones[parent]

    # need to refresh armature before removing bones
    bpy.ops.object.mode_set(mode='OBJECT')
    bpy.ops.object.mode_set(mode='EDIT')

    # delete helper/zero bones
    for bone in amt.bones.keys():
        #print("keys of bone=%s" % bonesData[bone].keys())
        if 'flag' in bonesData[bone].keys():
            #print ("deleting bone=%s" % bone)
            bpy.context.object.data.edit_bones.remove(amt.edit_bones[bone])

    bpy.ops.object.mode_set(mode='OBJECT')
    def create_animations(self):
        z = self.z_mesh
        s = z.skeleton
        s.armature.show_axes = True
        
        # Set ourselves into the pose mode of the armature with nothing selected.
        bpy.ops.object.select_all(action='DESELECT')
        bpy.ops.object.select_pattern(pattern=s.name)
        bpy.ops.object.mode_set(mode='POSE')
        bpy.ops.pose.select_all(action='DESELECT')
        
        frame_offset = 0
        
        # Go through each Animation.
        for animation in z.animations:
            if animation.name != "Run":
                continue
            s.object.animation_data_create();
            s.object.animation_data.action = bpy.data.actions.new(animation.name)
            s.object.animation_data.action.use_fake_user = 1
            if self.DEBUG == True:
                print("Rendering Animation: " + animation.name + "...")
            
            frame_offset = 0
            p_bones = [ ]
            
            s.bone_pose  = dict()
            s.world_pose = dict()
            s.skin_pose  = dict()
            
            last_matrix = dict()
            should_mat  = dict()
            for bone_index in range(0, s.bone_count):
                last_matrix[bone_index] = Matrix()
                should_mat[bone_index] = False
            
            for frame in animation.frames:
                bpy.data.scenes[0].frame_current = frame_offset                    
                
                s.armature
                #if self.DEBUG == True:
                    #print('Rendering Frame: ' + str(frame_offset))
                
                # 1) Turn the translation and rotation into a Frame Matrix
                # 2) Create a World Matrix by multiplying the Parent World Matrix with the Frame Matrix
                # 3) Create the Product Matrix by multiplying the World Matrix with the Bone Matrix
                
                
                for bone_index in range(0, s.bone_count):
                    bone_name    = s.bone_name[bone_index]
                    try:
                        l = frame.bone_locs[bone_name].copy()
                        r = frame.bone_rots[bone_name].copy()
                        s.bone_pose[bone_index] = s.bone_pose[bone_name] = create_from_quaternion_position(r,l)
                    except:
                        ok = None
                    
                s.world_pose[0] = mul(s.bone_pose[0], Matrix4f(), None)
                for bone_index in range(1, s.bone_count):
                    parent_index = s.bone_parent[bone_index]                    
                    s.world_pose[bone_index] = mul(s.bone_pose[bone_index].copy(), s.world_pose[parent_index].copy(), None)
    
                                    
                for bone_index in range(0, s.bone_count):
                    bone_name   = s.bone_name[bone_index]
                    parent_index = s.bone_parent[bone_index]
                    s.skin_pose[bone_index] = mul(s.offset_matrix[bone_index].copy(), s.world_pose[bone_index].copy(), None)
                                    
                for bone_index in range(1, s.bone_count):
                    bone_name   = s.bone_name[bone_index]
                    bone        = s.object.pose.bones[bone_name]
                    s.poses[bone_name] = bone
                    if bone_name == 'Root':
                        continue
                    p_bones.append(bone)
                    
                    bone_index = s.bone_index[bone_name]
                    
                    mat = s.skin_pose[bone_index].to_blender_matrix()
                    
                    if mat != last_matrix[bone_index]: 
                        
                        bpy.ops.object.select_pattern(pattern=bone_name) 
                        
                        parent_index = s.bone_parent[bone_index]

                        bone.matrix = mat.copy() * bone.bone.matrix_local.copy()
                            
                        bpy.ops.object.mode_set(mode='OBJECT')
                        bpy.ops.object.mode_set(mode='POSE')
                        
                        bpy.context.scene.update()
                        self.scene.update()
                        try:
                            bpy.ops.anim.keyframe_insert_menu(type='Location')
                        except:
                            ok = None
                        try:
                            bpy.ops.anim.keyframe_insert_menu(type='Rotation')
                        except:
                            ok = None
                        
                        bpy.ops.pose.select_all(action='DESELECT')
                        
                        last_matrix[bone_index] = mat

                self.scene.update()
                bpy.ops.pose.select_all(action='DESELECT')
                frame_offset += 1
Esempio n. 24
0
    def set_bone_transforms(gltf, skin_id, bone, node_id, parent):
        """Set bone transformations."""
        pyskin = gltf.data.skins[skin_id]
        pynode = gltf.data.nodes[node_id]

        obj = bpy.data.objects[pyskin.blender_armature_name]

        # Set bone bind_pose by inverting bindpose matrix
        if node_id in pyskin.joints:
            index_in_skel = pyskin.joints.index(node_id)
            if pyskin.inverse_bind_matrices is not None:
                inverse_bind_matrices = BinaryData.get_data_from_accessor(
                    gltf, pyskin.inverse_bind_matrices)
                # Needed to keep scale in matrix, as bone.matrix seems to drop it
                if index_in_skel < len(inverse_bind_matrices):
                    pynode.blender_bone_matrix = matrix_gltf_to_blender(
                        inverse_bind_matrices[index_in_skel]).inverted()
                    bone.matrix = pynode.blender_bone_matrix
                else:
                    gltf.log.error("Error with inverseBindMatrix for skin " +
                                   pyskin)
            else:
                pynode.blender_bone_matrix = Matrix()  # 4x4 identity matrix
        else:
            print('No invBindMatrix for bone ' + str(node_id))
            pynode.blender_bone_matrix = Matrix()

        # Parent the bone
        if parent is not None and hasattr(gltf.data.nodes[parent],
                                          "blender_bone_name"):
            bone.parent = obj.data.edit_bones[gltf.data.nodes[
                parent].blender_bone_name]  # TODO if in another scene

        # Switch to Pose mode
        bpy.ops.object.mode_set(mode="POSE")
        obj.data.pose_position = 'POSE'

        # Set posebone location/rotation/scale (in armature space)
        # location is actual bone location minus it's original (bind) location
        bind_location = Matrix.Translation(
            pynode.blender_bone_matrix.to_translation())
        bind_rotation = pynode.blender_bone_matrix.to_quaternion()
        bind_scale = scale_to_matrix(pynode.blender_bone_matrix.to_scale())

        location, rotation, scale = matrix_gltf_to_blender(
            pynode.transform).decompose()
        if parent is not None and hasattr(gltf.data.nodes[parent],
                                          "blender_bone_matrix"):
            parent_mat = gltf.data.nodes[parent].blender_bone_matrix

            # Get armature space location (bindpose + pose)
            # Then, remove original bind location from armspace location, and bind rotation
            if bpy.app.version < (2, 80, 0):
                final_location = (
                    bind_location.inverted() * parent_mat *
                    Matrix.Translation(location)).to_translation()
                obj.pose.bones[pynode.blender_bone_name].location = \
                    bind_rotation.inverted().to_matrix().to_4x4() * final_location
            else:
                final_location = (
                    bind_location.inverted() @ parent_mat
                    @ Matrix.Translation(location)).to_translation()
                obj.pose.bones[pynode.blender_bone_name].location = \
                    bind_rotation.inverted().to_matrix().to_4x4() @ final_location

            # Do the same for rotation & scale
            if bpy.app.version < (2, 80, 0):
                obj.pose.bones[pynode.blender_bone_name].rotation_quaternion = \
                    (pynode.blender_bone_matrix.inverted() * parent_mat *
                        matrix_gltf_to_blender(pynode.transform)).to_quaternion()
                obj.pose.bones[pynode.blender_bone_name].scale = \
                    (bind_scale.inverted() * parent_mat * scale_to_matrix(scale)).to_scale()
            else:
                obj.pose.bones[pynode.blender_bone_name].rotation_quaternion = \
                    (pynode.blender_bone_matrix.inverted() @ parent_mat @
                        matrix_gltf_to_blender(pynode.transform)).to_quaternion()
                obj.pose.bones[pynode.blender_bone_name].scale = \
                    (bind_scale.inverted() @ parent_mat @ scale_to_matrix(scale)).to_scale()

        else:
            if bpy.app.version < (2, 80, 0):
                obj.pose.bones[
                    pynode.
                    blender_bone_name].location = bind_location.inverted(
                    ) * location
                obj.pose.bones[
                    pynode.
                    blender_bone_name].rotation_quaternion = bind_rotation.inverted(
                    ) * rotation
                obj.pose.bones[
                    pynode.
                    blender_bone_name].scale = bind_scale.inverted() * scale
            else:
                obj.pose.bones[
                    pynode.
                    blender_bone_name].location = bind_location.inverted(
                    ) @ location
                obj.pose.bones[
                    pynode.
                    blender_bone_name].rotation_quaternion = bind_rotation.inverted(
                    ) @ rotation
                obj.pose.bones[
                    pynode.
                    blender_bone_name].scale = bind_scale.inverted() @ scale
Esempio n. 25
0
def custom(ot, context, event, axis=None):
    preference = addon.preference()
    bc = context.window_manager.bc

    verts = [
        Vector((100000.0, 100000.0, 0.0)),
        Vector((-100000.0, 100000.0, 0.0)),
        Vector((-100000.0, -100000.0, 0.0)),
        Vector((100000.0, -100000.0, 0.0))
    ]

    edges = [(0, 1), (1, 2), (2, 3), (3, 0)]

    faces = [(0, 1, 2, 3)]

    data = bpy.data.meshes.new(name='Box')
    data.bc.removeable = True

    if not bc.snap.hit:
        data.from_pydata(verts, edges, faces)
        data.validate()

    original_active = context.active_object

    box = bpy.data.objects.new(
        name='Box', object_data=data if not bc.snap.hit else bc.snap.mesh)
    bpy.context.scene.collection.objects.link(box)
    context.view_layer.objects.active = box

    if not axis:
        axis = preference.cursor_axis

    if not bc.snap.hit:
        current = {'X': 'Y', 'Y': 'X', 'Z': 'Z'}

        rotation = Matrix.Rotation(radians(-90 if axis in {'X', 'Y'} else 90),
                                   4, current[axis])

        cursor = context.scene.cursor.rotation_euler.to_matrix().to_4x4()
        cursor.translation = context.scene.cursor.location

        matrix = cursor @ rotation if preference.surface == 'CURSOR' else rotation

        box.data.transform(matrix)
        box.data.validate()
        context.scene.update()

    if bc.snap.hit:
        hit, ot.ray['location'], ot.ray['normal'], index = ray.cast.objects(
            *ot.mouse['location'], mesh=bc.snap.mesh)
    else:
        hit, ot.ray['location'], ot.ray['normal'], index = ray.cast.objects(
            *ot.mouse['location'], obj=box)

    if not hit:
        index = [axis == a for a in 'XYZ'].index(True)

        if index > 1:
            index = 0
        else:
            index += 1

        axis = 'XYZ'[index]

        bpy.data.objects.remove(box)

        del box

        custom(ot, context, event, axis=axis)
        return

    bc.lattice.matrix_world = matrix if not bc.snap.hit else Matrix()
    bc.lattice.matrix_world.translation = Vector(
        ot.ray['location'][:] if not bc.snap.hit else bc.snap.location)
    bc.shape.matrix_world = bc.lattice.matrix_world
    bc.plane.matrix_world = bc.lattice.matrix_world

    ot.start['matrix'] = bc.plane.matrix_world.copy()

    bc.location = ot.ray['location'] if not bc.snap.hit else bc.snap.location

    context.view_layer.objects.active = original_active

    bpy.data.objects.remove(box)

    del box

    refresh.shape(ot, context, event)
Esempio n. 26
0
def draw_callback_view(n_id, cached_view, options):
    def Vector_generate2(prop):
        # try:
        #     return [[Vector(v[:3]) for v in obj] for obj in prop]
        # except ValueEror:
        #     return []
        return [[Vector(v) for v in obj] for obj in prop]

    # context = bpy.context
    if options["timings"]:
        start = time.perf_counter()

    if options['draw_list'] == 0:

        sl1 = cached_view[n_id + 'v']
        sl2 = cached_view[n_id + 'ep']
        sl3 = cached_view[n_id + 'm']

        if sl1:
            data_vector = Vector_generate2(sl1)
            verlen = len(data_vector) - 1
        else:
            if not sl3:
                # end early: no matrix and no vertices
                callback_disable(n_id)
                return

            # display matrix repr only.
            data_vector = []
            verlen = 0

        options['verlen'] = verlen
        data_polygons = []
        data_edges = []

        if sl2 and sl2[0]:
            if isinstance(sl2[0], int):
                callback_disable(n_id)
                return

            len_sl2 = len(sl2[0][0])
            if len_sl2 == 2:
                data_edges = sl2
            elif len_sl2 > 2:
                data_polygons = sl2

        if sl3:
            data_matrix = Matrix_generate(sl3)
        else:
            data_matrix = [Matrix() for i in range(verlen + 1)]

        if (data_vector, data_polygons, data_matrix, data_edges) == (0, 0, 0,
                                                                     0):
            callback_disable(n_id)
            return
        try:
            the_display_list = glGenLists(1)
            glNewList(the_display_list, GL_COMPILE)
            draw_geometry(n_id, options, data_vector, data_polygons,
                          data_matrix, data_edges)
        except Exception as err:
            print("Error in callback!:")
            traceback.print_exc()
            options['error'] = True
        finally:
            glEndList()

        options['genlist'] = the_display_list

    elif options['draw_list'] == 1:
        the_display_list = options['genlist']

    if not 'error' in options:
        glCallList(the_display_list)
        glFlush()

    # restore to system state
    glLineWidth(1)

    if options["timings"]:
        stop = time.perf_counter()
        print("callback drawn in {:4f}".format(stop - start))

    # has drawn once with success.
    options['draw_list'] = 1
Esempio n. 27
0
 def process(self):
     outputs = self.outputs
     if not outputs['Vertices'].is_linked:
         return
     IVerts, IFaces, IMask, Imatr = self.inputs
     vertices_s = IVerts.sv_get()
     faces_s = IFaces.sv_get()
     linked_extruded_polygons = outputs['ExtrudedPolys'].is_linked
     linked_other_polygons = outputs['OtherPolys'].is_linked
     result_vertices = []
     result_edges = []
     result_faces = []
     result_extruded_faces = []
     result_other_faces = []
     bmlist = [
         bmesh_from_pydata(verts, [], faces)
         for verts, faces in zip(vertices_s, faces_s)
     ]
     trans = Imatr.sv_get()
     if IMask.is_linked:
         flist = [
             np.extract(mask, bm.faces[:])
             for bm, mask in zip(bmlist, IMask.sv_get())
         ]
     else:
         flist = [bm.faces for bm in bmlist]
     for bm, selfaces in zip(bmlist, flist):
         extrfaces = extrude_discrete_faces(bm, faces=selfaces)['faces']
         fullList(trans, len(extrfaces))
         new_extruded_faces = []
         for face, ma in zip(extrfaces, trans):
             normal = face.normal
             if normal[0] == 0 and normal[1] == 0:
                 m_r = Matrix() if normal[2] >= 0 else Matrix.Rotation(
                     pi, 4, 'X')
             else:
                 z_axis = normal
                 x_axis = Vector(
                     (z_axis[1] * -1, z_axis[0], 0)).normalized()
                 y_axis = z_axis.cross(x_axis).normalized()
                 m_r = Matrix(list([*zip(x_axis[:], y_axis[:], z_axis[:])
                                    ])).to_4x4()
             m = (Matrix.Translation(face.calc_center_median())
                  @ m_r).inverted()
             transform(bm, matrix=ma, space=m, verts=face.verts)
             if linked_extruded_polygons or linked_other_polygons:
                 new_extruded_faces.append([v.index for v in face.verts])
         new_vertices, new_edges, new_faces = pydata_from_bmesh(bm)
         bm.free()
         new_other_faces = [
             f for f in new_faces if f not in new_extruded_faces
         ] if linked_other_polygons else []
         result_vertices.append(new_vertices)
         result_edges.append(new_edges)
         result_faces.append(new_faces)
         result_extruded_faces.append(new_extruded_faces)
         result_other_faces.append(new_other_faces)
     outputs['Vertices'].sv_set(result_vertices)
     outputs['Edges'].sv_set(result_edges)
     outputs['Polygons'].sv_set(result_faces)
     outputs['ExtrudedPolys'].sv_set(result_extruded_faces)
     outputs['OtherPolys'].sv_set(result_other_faces)
Esempio n. 28
0
 def dataCorrect2(self, destination, obj):
     if destination:
         return destination
     return [Matrix() for v in obj]
Esempio n. 29
0
import bpy
import sys
from mathutils import Matrix

args = sys.argv

filepath = args[-1]
name = args[-2]

scene = bpy.context.scene

group = bpy.data.groups.new(name)

for ob in bpy.data.objects:
    scene.objects.link(ob)
    group.objects.link(ob)
    ob.matrix_world = Matrix()

bpy.ops.wm.save_as_mainfile(filepath=filepath)
Esempio n. 30
0
def add_object_align_init(context, operator):
    """
    Return a matrix using the operator settings and view context.

    :arg context: The context to use.
    :type context: :class:`bpy.types.Context`
    :arg operator: The operator, checked for location and rotation properties.
    :type operator: :class:`bpy.types.Operator`
    :return: the matrix from the context and settings.
    :rtype: :class:`mathutils.Matrix`
    """

    from mathutils import Matrix, Vector, Euler
    properties = operator.properties if operator is not None else None

    space_data = context.space_data
    if space_data and space_data.type != 'VIEW_3D':
        space_data = None

    # location
    if operator and properties.is_property_set("location"):
        location = Matrix.Translation(Vector(properties.location))
    else:
        if space_data:  # local view cursor is detected below
            location = Matrix.Translation(space_data.cursor_location)
        else:
            location = Matrix.Translation(context.scene.cursor_location)

        if operator:
            properties.location = location.to_translation()

    # rotation
    view_align = (context.user_preferences.edit.object_align == 'VIEW')
    view_align_force = False
    if operator:
        if properties.is_property_set("view_align"):
            view_align = view_align_force = operator.view_align
        else:
            if properties.is_property_set("rotation"):
                # ugh, 'view_align' callback resets
                value = properties.rotation[:]
                properties.view_align = view_align
                properties.rotation = value
                del value
            else:
                properties.view_align = view_align

    if operator and (properties.is_property_set("rotation") and
                     not view_align_force):

        rotation = Euler(properties.rotation).to_matrix().to_4x4()
    else:
        if view_align and space_data:
            rotation = space_data.region_3d.view_matrix.to_3x3().inverted()
            rotation.resize_4x4()
        else:
            rotation = Matrix()

        # set the operator properties
        if operator:
            properties.rotation = rotation.to_euler()

    return location @ rotation