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
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)
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
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'}
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()
def _convert_location_inverted(self, location): return matmul(self.__mat_loc, Vector(location) - self.__offset) * self.__scale
def _convert_location(self, location): return self.__offset + matmul(self.__mat_loc, Vector(location)) * self.__scale
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()
def convert_location(self, location): return matmul(self.__mat, Vector(location)) * self.__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])]))
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
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)
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)]))
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