示例#1
0
    def convertIKLimitAngles(min_angle, max_angle, bone_matrix, invert=False):
        mat = bone_matrix.to_3x3() * -1
        mat[1], mat[2] = mat[2].copy(), mat[1].copy()
        mat.transpose()
        if invert:
            mat.invert()

        # align matrix to global axes
        m = Matrix([[0, 0, 0], [0, 0, 0], [0, 0, 0]])
        i_set, j_set = [0, 1, 2], [0, 1, 2]
        for _ in range(3):
            ii, jj = i_set[0], j_set[0]
            for i in i_set:
                for j in j_set:
                    if abs(mat[i][j]) > abs(mat[ii][jj]):
                        ii, jj = i, j
            i_set.remove(ii)
            j_set.remove(jj)
            m[ii][jj] = -1 if mat[ii][jj] < 0 else 1

        new_min_angle = bpyutils.matmul(m, Vector(min_angle))
        new_max_angle = bpyutils.matmul(m, Vector(max_angle))
        for i in range(3):
            if new_min_angle[i] > new_max_angle[i]:
                new_min_angle[i], new_max_angle[i] = new_max_angle[
                    i], new_min_angle[i]
        return new_min_angle, new_max_angle
示例#2
0
 def buildJoints(self):
     for i in self.joints():
         rbc = i.rigid_body_constraint
         if rbc is None:
             continue
         m = self.__rigid_body_matrix_map.get(rbc.object1, None)
         if m is None:
             m = self.__rigid_body_matrix_map.get(rbc.object2, None)
             if m is None:
                 continue
         t, r, s = matmul(m, i.matrix_local).decompose()
         i.location = t
         i.rotation_euler = r.to_euler(i.rotation_mode)
示例#3
0
 def __init__(self, pose_bone, scale, invert=False):
     mat = pose_bone.matrix.to_3x3()
     mat[1], mat[2] = mat[2].copy(), mat[1].copy()
     self.__mat = mat.transposed()
     self.__scale = scale
     self.__mat_rot = pose_bone.matrix_basis.to_3x3()
     self.__mat_loc = matmul(self.__mat_rot, self.__mat)
     self.__offset = pose_bone.location.copy()
     self.convert_location = self._convert_location
     self.convert_rotation = self._convert_rotation
     if invert:
         self.__mat.invert()
         self.__mat_rot.invert()
         self.__mat_loc.invert()
         self.convert_location = self._convert_location_inverted
         self.convert_rotation = self._convert_rotation_inverted
示例#4
0
 def execute(self, context):
     from core.mmd_tools.bpyutils import matmul
     obj = context.active_object
     root = mmd_model.Model.findRoot(obj)
     mmd_root = root.mmd_root
     rig = mmd_model.Model(root)
     armature = rig.armature()
     utils.selectSingleBone(context, armature, None, True)
     morph = mmd_root.bone_morphs[mmd_root.active_morph]
     for morph_data in morph.data:
         p_bone = armature.pose.bones.get(morph_data.bone, None)
         if p_bone:
             p_bone.bone.select = True
             p_bone.location += morph_data.location
             p_bone.rotation_quaternion = matmul(p_bone.rotation_quaternion,
                                                 morph_data.rotation)
     return {'FINISHED'}
示例#5
0
 def _convert_rotation_inverted(self, rotation_xyzw):
     rot = Quaternion()
     rot.x, rot.y, rot.z, rot.w = rotation_xyzw
     rot = matmul(self.__mat_rot, rot.to_matrix()).to_quaternion()
     return Quaternion(matmul(self.__mat, rot.axis) * -1,
                       rot.angle).normalized()
示例#6
0
 def _convert_location_inverted(self, location):
     return matmul(self.__mat_loc,
                   Vector(location) - self.__offset) * self.__scale
示例#7
0
 def _convert_location(self, location):
     return self.__offset + matmul(self.__mat_loc,
                                   Vector(location)) * self.__scale
示例#8
0
 def convert_rotation(self, rotation_xyzw):
     rot = Quaternion()
     rot.x, rot.y, rot.z, rot.w = rotation_xyzw
     return Quaternion(matmul(self.__mat, rot.axis) * -1,
                       rot.angle).normalized()
示例#9
0
 def convert_location(self, location):
     return matmul(self.__mat, Vector(location)) * self.__scale
示例#10
0
 def scale(mat_rot, w0, w1):
     s = s0 * w0 + s1 * w1
     return matmul(
         mat_rot,
         Matrix([(s[0], 0, 0), (0, s[1], 0), (0, 0, s[2])]))
示例#11
0
    def driver_function(cls, shapekey, obj_name, bulk_update, use_skip,
                        use_scale):
        obj = bpy.data.objects[obj_name]
        cls.__init_cache(obj, shapekey)
        if cls.__sdef_muted(obj, shapekey):
            return 0.0

        if not bulk_update:
            shapekey_data = shapekey.data
            if use_scale:
                # with scale
                for bone0, bone1, sdef_data, vids in cls.g_verts[hash(
                        obj)].values():
                    if use_skip and not cls.__check_bone_update(
                            obj, bone0, bone1):
                        continue
                    mat0 = matmul(bone0.matrix,
                                  bone0.bone.matrix_local.inverted())
                    mat1 = matmul(bone1.matrix,
                                  bone1.bone.matrix_local.inverted())
                    rot0 = mat0.to_quaternion()
                    rot1 = mat1.to_quaternion()
                    if rot1.dot(rot0) < 0:
                        rot1 = -rot1
                    s0, s1 = mat0.to_scale(), mat1.to_scale()
                    for vid, w0, w1, pos_c, cr0, cr1 in sdef_data:
                        s = s0 * w0 + s1 * w1
                        mat_rot = matmul(
                            (rot0 * w0 + rot1 * w1).normalized().to_matrix(),
                            Matrix([(s[0], 0, 0), (0, s[1], 0), (0, 0, s[2])]))
                        shapekey_data[vid].co = matmul(
                            mat_rot, pos_c) + matmul(mat0, cr0) * w0 + matmul(
                                mat1, cr1) * w1
            else:
                # default
                for bone0, bone1, sdef_data, vids in cls.g_verts[hash(
                        obj)].values():
                    if use_skip and not cls.__check_bone_update(
                            obj, bone0, bone1):
                        continue
                    mat0 = matmul(bone0.matrix,
                                  bone0.bone.matrix_local.inverted())
                    mat1 = matmul(bone1.matrix,
                                  bone1.bone.matrix_local.inverted())
                    rot0 = mat0.to_quaternion()
                    rot1 = mat1.to_quaternion()
                    if rot1.dot(rot0) < 0:
                        rot1 = -rot1
                    for vid, w0, w1, pos_c, cr0, cr1 in sdef_data:
                        mat_rot = (rot0 * w0 +
                                   rot1 * w1).normalized().to_matrix()
                        shapekey_data[vid].co = matmul(
                            mat_rot, pos_c) + matmul(mat0, cr0) * w0 + matmul(
                                mat1, cr1) * w1
        else:  # bulk update
            shapekey_data = cls.g_shapekey_data[hash(obj)]
            if use_scale:
                # scale & bulk update
                for bone0, bone1, sdef_data, vids in cls.g_verts[hash(
                        obj)].values():
                    if use_skip and not cls.__check_bone_update(
                            obj, bone0, bone1):
                        continue
                    mat0 = matmul(bone0.matrix,
                                  bone0.bone.matrix_local.inverted())
                    mat1 = matmul(bone1.matrix,
                                  bone1.bone.matrix_local.inverted())
                    rot0 = mat0.to_quaternion()
                    rot1 = mat1.to_quaternion()
                    if rot1.dot(rot0) < 0:
                        rot1 = -rot1
                    s0, s1 = mat0.to_scale(), mat1.to_scale()

                    def scale(mat_rot, w0, w1):
                        s = s0 * w0 + s1 * w1
                        return matmul(
                            mat_rot,
                            Matrix([(s[0], 0, 0), (0, s[1], 0), (0, 0, s[2])]))

                    shapekey_data[vids] = [
                        matmul(
                            scale((rot0 * w0 +
                                   rot1 * w1).normalized().to_matrix(), w0,
                                  w1), pos_c) + matmul(mat0, cr0) * w0 +
                        matmul(mat1, cr1) * w1
                        for vid, w0, w1, pos_c, cr0, cr1 in sdef_data
                    ]
            else:
                # bulk update
                for bone0, bone1, sdef_data, vids in cls.g_verts[hash(
                        obj)].values():
                    if use_skip and not cls.__check_bone_update(
                            obj, bone0, bone1):
                        continue
                    mat0 = matmul(bone0.matrix,
                                  bone0.bone.matrix_local.inverted())
                    mat1 = matmul(bone1.matrix,
                                  bone1.bone.matrix_local.inverted())
                    rot0 = mat0.to_quaternion()
                    rot1 = mat1.to_quaternion()
                    if rot1.dot(rot0) < 0:
                        rot1 = -rot1
                    shapekey_data[vids] = [
                        matmul(
                            (rot0 * w0 + rot1 * w1).normalized().to_matrix(),
                            pos_c) + matmul(mat0, cr0) * w0 +
                        matmul(mat1, cr1) * w1
                        for vid, w0, w1, pos_c, cr0, cr1 in sdef_data
                    ]
            shapekey.data.foreach_set(
                'co', shapekey_data.reshape(3 * len(shapekey.data)))

        return 1.0  # shapkey value
示例#12
0
    def newMMDCameraAnimation(cameraObj,
                              cameraTarget=None,
                              scale=1.0,
                              min_distance=0.1):
        scene = bpy.context.scene
        mmd_cam = bpy.data.objects.new(
            name='Camera', object_data=bpy.data.cameras.new('Camera'))
        SceneOp(bpy.context).link_object(mmd_cam)
        MMDCamera.convertToMMDCamera(mmd_cam, scale=scale)
        mmd_cam_root = mmd_cam.parent

        _camera_override_func = None
        if cameraObj is None:
            if scene.camera is None:
                scene.camera = mmd_cam
                return MMDCamera(mmd_cam_root)
            _camera_override_func = lambda: scene.camera

        _target_override_func = None
        if cameraTarget is None:
            _target_override_func = lambda camObj: camObj.data.dof_object or camObj

        action_name = mmd_cam_root.name
        parent_action = bpy.data.actions.new(name=action_name)
        distance_action = bpy.data.actions.new(name=action_name + '_dis')
        MMDCamera.removeDrivers(mmd_cam)

        from math import atan
        from mathutils import Matrix, Vector
        from core.mmd_tools.bpyutils import matmul

        render = scene.render
        factor = (render.resolution_y * render.pixel_aspect_y) / (
            render.resolution_x * render.pixel_aspect_x)
        matrix_rotation = Matrix(
            ([1, 0, 0, 0], [0, 0, 1, 0], [0, -1, 0, 0], [0, 0, 0, 1]))
        neg_z_vector = Vector((0, 0, -1))
        frame_start, frame_end, frame_current = scene.frame_start, scene.frame_end + 1, scene.frame_current
        frame_count = frame_end - frame_start
        frames = range(frame_start, frame_end)

        fcurves = []
        for i in range(3):
            fcurves.append(
                parent_action.fcurves.new(data_path='location',
                                          index=i))  # x, y, z
        for i in range(3):
            fcurves.append(
                parent_action.fcurves.new(data_path='rotation_euler',
                                          index=i))  # rx, ry, rz
        fcurves.append(
            parent_action.fcurves.new(data_path='mmd_camera.angle'))  # fov
        fcurves.append(
            parent_action.fcurves.new(
                data_path='mmd_camera.is_perspective'))  # persp
        fcurves.append(
            distance_action.fcurves.new(data_path='location', index=1))  # dis
        for c in fcurves:
            c.keyframe_points.add(frame_count)

        for f, x, y, z, rx, ry, rz, fov, persp, dis in zip(
                frames, *(c.keyframe_points for c in fcurves)):
            scene.frame_set(f)
            if _camera_override_func:
                cameraObj = _camera_override_func()
            if _target_override_func:
                cameraTarget = _target_override_func(cameraObj)
            cam_matrix_world = cameraObj.matrix_world
            cam_target_loc = cameraTarget.matrix_world.translation
            cam_rotation = matmul(cam_matrix_world, matrix_rotation).to_euler(
                mmd_cam_root.rotation_mode)
            cam_vec = matmul(cam_matrix_world.to_3x3(), neg_z_vector)
            if cameraObj.data.type == 'ORTHO':
                cam_dis = -(9 / 5) * cameraObj.data.ortho_scale
                if cameraObj.data.sensor_fit != 'VERTICAL':
                    if cameraObj.data.sensor_fit == 'HORIZONTAL':
                        cam_dis *= factor
                    else:
                        cam_dis *= min(1, factor)
            else:
                target_vec = cam_target_loc - cam_matrix_world.translation
                cam_dis = -max(
                    target_vec.length * cam_vec.dot(target_vec.normalized()),
                    min_distance)
            cam_target_loc = cam_matrix_world.translation - cam_vec * cam_dis

            tan_val = cameraObj.data.sensor_height / cameraObj.data.lens / 2
            if cameraObj.data.sensor_fit != 'VERTICAL':
                ratio = cameraObj.data.sensor_width / cameraObj.data.sensor_height
                if cameraObj.data.sensor_fit == 'HORIZONTAL':
                    tan_val *= factor * ratio
                else:  # cameraObj.data.sensor_fit == 'AUTO'
                    tan_val *= min(ratio, factor * ratio)

            x.co, y.co, z.co = ((f, i) for i in cam_target_loc)
            rx.co, ry.co, rz.co = ((f, i) for i in cam_rotation)
            dis.co = (f, cam_dis)
            fov.co = (f, 2 * atan(tan_val))
            persp.co = (f, cameraObj.data.type != 'ORTHO')
            persp.interpolation = 'CONSTANT'
            for kp in (x, y, z, rx, ry, rz, fov, dis):
                kp.interpolation = 'LINEAR'

        MMDCamera.addDrivers(mmd_cam)
        mmd_cam_root.animation_data_create().action = parent_action
        mmd_cam.animation_data_create().action = distance_action
        scene.frame_set(frame_current)
        return MMDCamera(mmd_cam_root)
示例#13
0
 def __matrix_compose(loc, rot, scale):
     return matmul(
         matmul(Matrix.Translation(loc),
                rot.to_matrix().to_4x4()),
         Matrix([(scale[0], 0, 0, 0), (0, scale[1], 0, 0),
                 (0, 0, scale[2], 0), (0, 0, 0, 1)]))
示例#14
0
    def updateRigid(self, rigid_obj):
        assert (rigid_obj.mmd_type == 'RIGID_BODY')
        rb = rigid_obj.rigid_body
        if rb is None:
            return

        rigid = rigid_obj.mmd_rigid
        rigid_type = int(rigid.type)
        relation = rigid_obj.constraints['mmd_tools_rigid_parent']
        arm = relation.target
        bone_name = relation.subtarget

        if rigid_type == rigid_body.MODE_STATIC:
            rb.kinematic = True
        else:
            rb.kinematic = False

        if arm is not None and bone_name != '':
            target_bone = arm.pose.bones[bone_name]

            if rigid_type == rigid_body.MODE_STATIC:
                m = matmul(target_bone.matrix,
                           target_bone.bone.matrix_local.inverted())
                self.__rigid_body_matrix_map[rigid_obj] = m
                orig_scale = rigid_obj.scale.copy()
                to_matrix_world = matmul(rigid_obj.matrix_world,
                                         rigid_obj.matrix_local.inverted())
                matrix_world = matmul(to_matrix_world,
                                      matmul(m, rigid_obj.matrix_local))
                rigid_obj.parent = arm
                rigid_obj.parent_type = 'BONE'
                rigid_obj.parent_bone = bone_name
                rigid_obj.matrix_world = matrix_world
                rigid_obj.scale = orig_scale
                #relation.mute = False
                #relation.inverse_matrix = matmul(arm.matrix_world, target_bone.bone.matrix_local).inverted()
                fake_children = self.__fake_parent_map.get(rigid_obj, None)
                if fake_children:
                    for fake_child in fake_children:
                        logging.debug('          - fake_child: %s',
                                      fake_child.name)
                        t, r, s = matmul(m,
                                         fake_child.matrix_local).decompose()
                        fake_child.location = t
                        fake_child.rotation_euler = r.to_euler(
                            fake_child.rotation_mode)

            elif rigid_type in [
                    rigid_body.MODE_DYNAMIC, rigid_body.MODE_DYNAMIC_BONE
            ]:
                m = matmul(target_bone.matrix,
                           target_bone.bone.matrix_local.inverted())
                self.__rigid_body_matrix_map[rigid_obj] = m
                t, r, s = matmul(m, rigid_obj.matrix_local).decompose()
                rigid_obj.location = t
                rigid_obj.rotation_euler = r.to_euler(rigid_obj.rotation_mode)
                fake_children = self.__fake_parent_map.get(rigid_obj, None)
                if fake_children:
                    for fake_child in fake_children:
                        logging.debug('          - fake_child: %s',
                                      fake_child.name)
                        t, r, s = matmul(m,
                                         fake_child.matrix_local).decompose()
                        fake_child.location = t
                        fake_child.rotation_euler = r.to_euler(
                            fake_child.rotation_mode)

                if 'mmd_tools_rigid_track' not in target_bone.constraints:
                    empty = bpy.data.objects.new('mmd_bonetrack', None)
                    SceneOp(bpy.context).link_object(empty)
                    empty.matrix_world = target_bone.matrix
                    empty.empty_draw_size = 0.1 * self.__root.empty_draw_size
                    empty.empty_draw_type = 'ARROWS'
                    empty.mmd_type = 'TRACK_TARGET'
                    empty.hide = True
                    empty.parent = self.temporaryGroupObject()

                    rigid_obj.mmd_rigid.bone = bone_name
                    rigid_obj.constraints.remove(relation)

                    self.__empty_parent_map[empty] = rigid_obj

                    const_type = ('COPY_TRANSFORMS',
                                  'COPY_ROTATION')[rigid_type - 1]
                    const = target_bone.constraints.new(const_type)
                    const.mute = True
                    const.name = 'mmd_tools_rigid_track'
                    const.target = empty
                else:
                    empty = target_bone.constraints[
                        'mmd_tools_rigid_track'].target
                    ori_rigid_obj = self.__empty_parent_map[empty]
                    ori_rb = ori_rigid_obj.rigid_body
                    if ori_rb and rb.mass > ori_rb.mass:
                        logging.debug(
                            '        * Bone (%s): change target from [%s] to [%s]',
                            target_bone.name, ori_rigid_obj.name,
                            rigid_obj.name)
                        # re-parenting
                        rigid_obj.mmd_rigid.bone = bone_name
                        rigid_obj.constraints.remove(relation)
                        self.__empty_parent_map[empty] = rigid_obj
                        # revert change
                        ori_rigid_obj.mmd_rigid.bone = bone_name
                    else:
                        logging.debug('        * Bone (%s): track target [%s]',
                                      target_bone.name, ori_rigid_obj.name)

        rb.collision_shape = rigid.shape