def set_bone_transforms(self, bone, node, parent): obj = bpy.data.objects[self.blender_armature_name] delta = Quaternion((0.7071068286895752, 0.7071068286895752, 0.0, 0.0)) mat = Matrix() if not parent: transform = node.get_transforms() mat = transform * delta.to_matrix().to_4x4() else: if not self.gltf.scene.nodes[ parent].is_joint: # TODO if Node in another scene transform = node.get_transforms() parent_mat = bpy.data.objects[ self.gltf.scene.nodes[parent].blender_object].matrix_world mat = transform * parent_mat.inverted() else: transform = node.get_transforms() parent_mat = obj.data.edit_bones[self.gltf.scene.nodes[ parent].blender_bone_name].matrix # Node in another scene mat = (parent_mat.to_quaternion() * delta.inverted() * transform.to_quaternion() * delta).to_matrix().to_4x4() mat = Matrix.Translation(parent_mat.to_translation() + (parent_mat.to_quaternion() * delta.inverted() * transform.to_translation())) * mat #TODO scaling of bones bone.matrix = mat return bone.matrix
class Eyes: def __init__(self, cross_eye=0.0, default_look_distance=200, eye_fov=40): self.default_look_target = Vector((0, default_look_distance, 0)) self.look_target = self.default_look_target self.rotation = Quaternion((1, 0, 0, 0)) self.position = Vector((0, 0, 0)) self.leye_pos = Vector((-5.96898, 6.09201, 3.69949)) self.reye_pos = Vector((5.96898, 6.09201, 3.69949)) self.leye_norm = Vector((cross_eye, 1, 0)) self.reye_norm = Vector((-cross_eye, 1, 0)) self.pupil_pos = np.zeros(4) # lx ly rx ry self.eye_fov = eye_fov def set_rotation(self, rotation): self.rotation = rotation def update(self): self.update_pupil_pos() new_look_target = self.update_look_target() if new_look_target: print("blonk") self.look_target = new_look_target self.update() else: print(self.pupil_pos) def update_pupil_pos(self): leye_pos = self.leye_pos.copy() leye_pos.rotate(self.rotation) leye_pos += self.position reye_pos = self.reye_pos.copy() reye_pos.rotate(self.rotation) reye_pos += self.position leye_beam = self.look_target.copy() - leye_pos reye_beam = self.look_target.copy() - reye_pos leye_beam.rotate(self.rotation.inverted()) leye_beam_angle = self.leye_norm.rotation_difference(leye_beam) reye_beam.rotate(self.rotation.inverted()) reye_beam_angle = self.reye_norm.rotation_difference(reye_beam) self.pupil_pos = -1*np.degrees([leye_beam_angle.z, leye_beam_angle.x, reye_beam_angle.z, reye_beam_angle.x]) def update_look_target(self, forced=False): fov = np.full(4, self.eye_fov) / np.array([2, 4, 2, 4]) if forced or np.any(self.pupil_pos < -1*fov) or np.any(self.pupil_pos > fov): new_look_target = self.default_look_target.copy() new_look_target.rotate(self.rotation) new_look_target += self.position return new_look_target else: return False
def execute(self, context): scn = context.scene if 'localgrid_menu_items_strings' in scn and \ 'localgrid_menu_items_float' in scn: strings_dict = scn['localgrid_menu_items_strings'] float_dict = scn['localgrid_menu_items_float'] for i in range(len(strings_dict.keys())): strings = strings_dict[str(i)] icon, name = strings.split(',', 1) ls = float_dict[str(i)] orig = Vector([ls[0], ls[1], ls[2]]) quat = Quaternion([ls[3], ls[4], ls[5], ls[6]]) item = scn.local_grid.items.add() item.item_name = name item.icon = icon item.orig = orig item.quat = quat.inverted() if 'localgrid_menu_items_strings' in scn: del (scn['localgrid_menu_items_strings']) if 'localgrid_menu_items_float' in scn: del (scn['localgrid_menu_items_float']) if hasattr(scn, 'localgrid_menu_items_strings'): del (scn.localgrid_menu_items_strings) if hasattr(scn, 'localgrid_menu_items_float'): del (scn.localgrid_menu_items_float) return {'FINISHED'}
def execute(self, context): scn = context.scene if 'localgrid_menu_items_strings' in scn and \ 'localgrid_menu_items_float' in scn: strings_dict = scn['localgrid_menu_items_strings'] float_dict = scn['localgrid_menu_items_float'] for i in range(len(strings_dict.keys())): strings = strings_dict[str(i)] icon, name = strings.split(',', 1) ls = float_dict[str(i)] orig = Vector([ls[0], ls[1], ls[2]]) quat = Quaternion([ls[3], ls[4], ls[5], ls[6]]) item = scn.local_grid.items.add() item.item_name = name item.icon = icon item.orig = orig item.quat = quat.inverted() if 'localgrid_menu_items_strings' in scn: del(scn['localgrid_menu_items_strings']) if 'localgrid_menu_items_float' in scn: del(scn['localgrid_menu_items_float']) if hasattr(scn, 'localgrid_menu_items_strings'): del(scn.localgrid_menu_items_strings) if hasattr(scn, 'localgrid_menu_items_float'): del(scn.localgrid_menu_items_float) return {'FINISHED'}
def write_track(xml, anm_data, fps): xml.tag_open_format(TRACK, bone=anm_data.name) xml.tag_open("keyframes") loc0, rot0_inv, first_frame = None, None, True for kfpts in anm_data: assert is_same_time(kfpts) loc = Vector(kfp.co.y for kfp in kfpts[0:3]) rot = Quaternion(kfp.co.y for kfp in kfpts[3:7]) loc, rot = calc_keyframe(anm_data.bone, loc, rot) if first_frame: loc0 = loc rot0_inv = rot.inverted() first_frame = False loc = loc - loc0 rot = rot0_inv * rot write_keyframe(xml, kfpts[0].co.x / fps, loc, rot) xml.tag_close("keyframes") xml.tag_close("track")
def set_transforms(gltf_node, obj, parent): obj.rotation_mode = 'QUATERNION' if hasattr(gltf_node, 'matrix'): obj.matrix_world = Conversion.matrix(gltf_node.matrix) elif gltf_node.is_joint: delta = Quaternion( (0.7071068286895752, 0.7071068286895752, 0.0, 0.0)) obj.matrix_world = Conversion.get_node_matrix( gltf_node) * delta.inverted().to_matrix().to_4x4() else: obj.location = Conversion.location(gltf_node.translation) obj.rotation_quaternion = Conversion.quaternion(gltf_node.rotation) obj.scale = Conversion.scale(gltf_node.scale)
def compute_pose(self, world_poses, local_rotations, joint_offsets, index): """ Compute a pose for an index. Returns the resulting mat4 """ parent_quat = Quaternion([1, 0, 0, 0]) parent_pose = Matrix() if index > 0: parent_quat = local_rotations[index - 1] parent_pose = world_poses[index - 1] local_pose = (parent_quat.inverted() * local_rotations[index]).to_matrix() local_pose.resize_4x4() return parent_pose * joint_offsets[index] * local_pose
def set_transforms(self, obj, parent): if parent is None: obj.matrix_world = self.transform return for node in self.gltf.scene.nodes.values( ): # TODO if parent is in another scene if node.index == parent: if node.is_joint == True: delta = Quaternion( (0.7071068286895752, 0.7071068286895752, 0.0, 0.0)) obj.matrix_world = self.transform * delta.inverted( ).to_matrix().to_4x4() return else: obj.matrix_world = self.transform return
def createTPose(context): rig = context.object scn = context.scene if rig.McpHasTPose: setTPose(context) return filepath = os.path.join(os.path.dirname(__file__), "t_pose.json") struct = loadJson(filepath) for name,value in struct: pb = rig.pose.bones[name] quat = Quaternion(value) pb.matrix_basis = quat.to_matrix().to_4x4() rest = quat.inverted() pb["McpRestW"] = rest.w pb["McpRestX"] = rest.x pb["McpRestY"] = rest.y pb["McpRestZ"] = rest.z children = [] for ob in scn.objects: if ob.type != 'MESH': continue for mod in ob.modifiers: if (mod.type == 'ARMATURE' and mod.object == rig): children.append((ob, mod.name)) scn.objects.active = ob bpy.ops.object.modifier_apply(apply_as='SHAPE', modifier=mod.name) ob.data.shape_keys.key_blocks[mod.name].value = 1 scn.objects.active = rig bpy.ops.pose.armature_apply() for ob,name in children: scn.objects.active = ob mod = ob.modifiers.new(name, 'ARMATURE') mod.object = rig mod.use_vertex_groups = True bpy.ops.object.modifier_move_up(modifier=name) setShapeKey(ob, name, 1.0) scn.objects.active = rig rig.McpHasTPose = True print("Created T-pose")
def extract_current_pose(): """ Convert current object's pose to OpenCV's "rvec" and "tvec". """ ob = bpy.context.object if ob.rotation_mode == "QUATERNION": q = ob.rotation_quaternion elif ob.rotation_mode == "AXIS_ANGLE": q = Quaternion(ob.rotation_axis_angle[1:4], ob.rotation_axis_angle[0]) else: assert ob.rotation_mode in ("XYZ", "XZY", "YXZ", "YZX", "ZXY", "ZYX") q = ob.rotation_euler.to_quaternion() # Rotate 180 deg around local X because a blender camera has Y and Z axes opposite to OpenCV's q *= Quaternion((1.0, 0.0, 0.0), radians(180.0)) aa = q.to_axis_angle() rvec = [c * -aa[1] for c in aa[0]] tvec = list(q.inverted() * (-ob.location)) return rvec, tvec
def anim(self): obj = bpy.data.objects[self.animation.gltf.skins[ self.animation.node.skin_id].blender_armature_name] bone = obj.pose.bones[self.animation.node.blender_bone_name] fps = bpy.context.scene.render.fps delta = Quaternion((0.7071068286895752, 0.7071068286895752, 0.0, 0.0)) for anim in self.animation.anims.keys(): if not self.animation.gltf.animations[anim].blender_action: if self.animation.gltf.animations[anim].name: name = self.animation.gltf.animations[anim].name else: name = "Animation_" + str( self.animation.gltf.animations[anim].index) action = bpy.data.actions.new(name) self.animation.gltf.animations[ anim].blender_action = action.name if not obj.animation_data: obj.animation_data_create() obj.animation_data.action = bpy.data.actions[ self.animation.gltf.animations[anim].blender_action] for channel in self.animation.anims[anim]: if channel.path == "translation": blender_path = "location" for key in channel.data: transform = Matrix.Translation( self.animation.gltf.convert.location(list(key[1]))) if not self.animation.node.parent: mat = transform * delta.to_matrix().to_4x4() else: if not self.animation.gltf.scene.nodes[ self.animation.node. parent].is_joint: # TODO if Node in another scene parent_mat = bpy.data.objects[ self.animation.gltf.scene.nodes[ self.animation.node.parent]. blender_object].matrix_world mat = transform * parent_mat.inverted() else: parent_mat = self.animation.gltf.scene.nodes[ self.animation.node. parent].blender_bone_matrix mat = (parent_mat.to_quaternion() * delta.inverted() * transform.to_quaternion() * delta).to_matrix().to_4x4() mat = Matrix.Translation( parent_mat.to_translation() + (parent_mat.to_quaternion() * delta.inverted() * transform.to_translation())) * mat #TODO scaling of bones bone.location = self.animation.node.blender_bone_matrix.to_translation( ) - mat.to_translation() bone.keyframe_insert(blender_path, frame=key[0] * fps, group='location') # Setting interpolation for fcurve in [ curve for curve in obj.animation_data.action.fcurves if curve.group.name == "rotation" ]: for kf in fcurve.keyframe_points: self.animation.set_interpolation( channel.interpolation, kf) elif channel.path == "rotation": blender_path = "rotation_quaternion" for key in channel.data: transform = (self.animation.gltf.convert.quaternion( key[1])).to_matrix().to_4x4() if not self.animation.node.parent: mat = transform * delta.to_matrix().to_4x4() else: if not self.animation.gltf.scene.nodes[ self.animation.node. parent].is_joint: # TODO if Node in another scene parent_mat = bpy.data.objects[ self.animation.gltf.scene.nodes[ self.animation.node.parent]. blender_object].matrix_world mat = transform * parent_mat.inverted() else: parent_mat = self.animation.gltf.scene.nodes[ self.animation.node. parent].blender_bone_matrix mat = (parent_mat.to_quaternion() * delta.inverted() * transform.to_quaternion() * delta).to_matrix().to_4x4() mat = Matrix.Translation( parent_mat.to_translation() + (parent_mat.to_quaternion() * delta.inverted() * transform.to_translation())) * mat #TODO scaling of bones bone.rotation_quaternion = self.animation.node.blender_bone_matrix.to_quaternion( ).inverted() * mat.to_quaternion() bone.keyframe_insert(blender_path, frame=key[0] * fps, group='rotation') # Setting interpolation for fcurve in [ curve for curve in obj.animation_data.action.fcurves if curve.group.name == "rotation" ]: for kf in fcurve.keyframe_points: self.animation.set_interpolation( channel.interpolation, kf) elif channel.path == "scale": blender_path = "scale" for key in channel.data: s = self.animation.gltf.convert.scale(list(key[1])) transform = Matrix([[s[0], 0, 0, 0], [0, s[1], 0, 0], [0, 0, s[2], 0], [0, 0, 0, 1]]) if not self.animation.node.parent: mat = transform * delta.to_matrix().to_4x4() else: if not self.animation.gltf.scene.nodes[ self.animation.node. parent].is_joint: # TODO if Node in another scene parent_mat = bpy.data.objects[ self.animation.gltf.scene.nodes[ self.animation.node.parent]. blender_object].matrix_world mat = transform * parent_mat.inverted() else: parent_mat = self.animation.gltf.scene.nodes[ self.animation.node. parent].blender_bone_matrix mat = (parent_mat.to_quaternion() * delta.inverted() * transform.to_quaternion() * delta).to_matrix().to_4x4() mat = Matrix.Translation( parent_mat.to_translation() + (parent_mat.to_quaternion() * delta.inverted() * transform.to_translation())) * mat #TODO scaling of bones #bone.scale # TODO bone.keyframe_insert(blender_path, frame=key[0] * fps, group='scale') # Setting interpolation for fcurve in [ curve for curve in obj.animation_data.action.fcurves if curve.group.name == "rotation" ]: for kf in fcurve.keyframe_points: self.animation.set_interpolation( channel.interpolation, kf)
def execute(self, context): if self.type == 'ACTIVE': actob = context.active_object if actob: rotation = actob.matrix_world.to_quaternion() else: return {'FINISHED'} elif self.type == 'GRID': v3d = context.space_data if v3d.use_local_grid: rotation = v3d.local_grid_rotation else: rotation = Quaternion((1, 0, 0, 0)) else: rotation = self.rotation # world_rot = parent_mat * parent_inv * delta_rot * rot override = context.copy() for ob in vaob.sorted_objects(context.selected_objects): if self.type == 'ACTIVE' and ob == context.active_object: continue # オペレータのソース部分を見ないと判らないってのはどうなのよ override['selected_objects'] = [ob] override['selected_editable_objects'] = [ob] if ob.parent: parent_mat = ob.parent.matrix_world.to_3x3() parent_inv = ob.matrix_parent_inverse.to_3x3() mat = parent_mat * parent_inv target_quat = mat.inverted().to_quaternion() * rotation else: target_quat = rotation if ob.rotation_mode == 'AXIS_ANGLE': def rotate(quat): angle, *axis = ob.rotation_axis_angle local_quat = Quaternion(axis, angle) q = quat * local_quat axis, angle = q.to_axis_angle() ob.rotation_axis_angle = [angle] + list(axis) rotate(target_quat.inverted()) context.scene.update() bpy.ops.object.transform_apply(override, rotation=True) rotate(target_quat) elif ob.rotation_mode == 'QUATERNION': # transform_apply()は # delta_rotation_quaternion * rotation_quaternion の回転状態で # 計算される。その後rotation_quaternionはクリアされるが # delta_rotation_quaternionの数値はそのまま残る if self.use_delta: delta = ob.delta_rotation_quaternion # normalize()必要? else: delta = Quaternion([1, 0, 0, 0]) rot = ob.rotation_quaternion # target_quatの逆回転を行いtransform_apply()、 # そしてtarget_quat分回転する # target.inverted() * delta * rot = delta * quat # quat = delta.inverted() * target.inverted() * delta * rot quat = delta.inverted() * target_quat.inverted() * delta * rot ob.rotation_quaternion = quat # ob.update_tag({'OBJECT', 'DATA'}) context.scene.update() bpy.ops.object.transform_apply(override, rotation=True) ob.rotation_quaternion = target_quat * ob.rotation_quaternion # ob.update_tag({'OBJECT', 'DATA'}) else: if self.use_delta: delta = ob.delta_rotation_euler.to_quaternion() else: delta = Quaternion([1, 0, 0, 0]) rot = ob.rotation_euler.to_quaternion() quat = delta.inverted() * target_quat.inverted() * delta * rot ob.rotation_euler = quat.to_euler(ob.rotation_mode) context.scene.update() bpy.ops.object.transform_apply(override, rotation=True) ob.rotation_euler = target_quat.to_euler(ob.rotation_mode) context.scene.update() return {'FINISHED'}
def blender_bone_create_anim(self): obj = bpy.data.objects[self.gltf.skins[ self.skin_id].blender_armature_name] bone = obj.pose.bones[self.blender_bone_name] fps = bpy.context.scene.render.fps delta = Quaternion((0.7071068286895752, 0.7071068286895752, 0.0, 0.0)) first_anim = True for anim in self.anims: if anim.path == "translation": blender_path = "location" for key in anim.data: transform = Matrix.Translation( self.convert_location(list(key[1]))) if not self.parent: mat = transform else: if not self.gltf.scene.nodes[self.parent].is_joint: parent_mat = self.gltf.scene.nodes[ self.parent].get_transforms() else: parent_mat = obj.pose.bones[ self.gltf.scene.nodes[self.parent]. blender_bone_name].matrix # Node in another scene mat = (parent_mat.to_quaternion() * delta.inverted() * transform.to_quaternion() * delta).to_matrix().to_4x4() mat = Matrix.Translation( parent_mat.to_translation() + (parent_mat.to_quaternion() * delta.inverted() * transform.to_translation())) * mat mat = obj.convert_space(bone, mat, 'WORLD', 'LOCAL') bone.location = mat.to_translation() bone.keyframe_insert(blender_path, frame=key[0] * fps, group='location') # Setting interpolation for fcurve in [ curve for curve in obj.animation_data.action.fcurves if curve.group.name == "rotation" ]: for kf in fcurve.keyframe_points: self.set_interpolation(anim.interpolation, kf) elif anim.path == "rotation": blender_path = "rotation_quaternion" for key in anim.data: transform = (self.convert_quaternion( key[1])).to_matrix().to_4x4() if not self.parent: mat = transform else: if not self.gltf.scene.nodes[self.parent].is_joint: parent_mat = self.gltf.scene.nodes[ self.parent].get_transforms() else: parent_mat = obj.pose.bones[ self.gltf.scene.nodes[self.parent]. blender_bone_name].matrix # Node in another scene mat = (parent_mat.to_quaternion() * delta.inverted() * transform.to_quaternion() * delta).to_matrix().to_4x4() mat = Matrix.Translation( parent_mat.to_translation() + (parent_mat.to_quaternion() * delta.inverted() * transform.to_translation())) * mat mat = obj.convert_space(bone, mat, 'WORLD', 'LOCAL') bone.rotation_quaternion = mat.to_quaternion() bone.keyframe_insert(blender_path, frame=key[0] * fps, group='rotation') # Setting interpolation for fcurve in [ curve for curve in obj.animation_data.action.fcurves if curve.group.name == "rotation" ]: for kf in fcurve.keyframe_points: self.set_interpolation(anim.interpolation, kf) elif anim.path == "scale": blender_path = "scale" for key in anim.data: s = self.convert_scale(list(key[1])) transform = Matrix([[s[0], 0, 0, 0], [0, s[1], 0, 0], [0, 0, s[2], 0], [0, 0, 0, 1]]) if not self.parent: mat = transform else: if not self.gltf.scene.nodes[self.parent].is_joint: parent_mat = self.gltf.scene.nodes[ self.parent].get_transforms() else: parent_mat = obj.pose.bones[ self.gltf.scene.nodes[self.parent]. blender_bone_name].matrix # Node in another scene mat = (parent_mat.to_quaternion() * delta.inverted() * transform.to_quaternion() * delta).to_matrix().to_4x4() mat = Matrix.Translation( parent_mat.to_translation() + (parent_mat.to_quaternion() * delta.inverted() * transform.to_translation())) * mat mat = obj.convert_space(bone, mat, 'WORLD', 'LOCAL') bone.scale = mat.to_scale() bone.keyframe_insert(blender_path, frame=key[0] * fps, group='scale') # Setting interpolation for fcurve in [ curve for curve in obj.animation_data.action.fcurves if curve.group.name == "rotation" ]: for kf in fcurve.keyframe_points: self.set_interpolation(anim.interpolation, kf) if first_anim == True: first_anim = False if anim.anim.name and obj.animation_data and obj.animation_data.action: obj.animation_data.action.name = anim.anim.name
def get_vector(loop_act, loop_prev, f_normal_act=None, f_normal_prev=None, rotaxis=None, threshold=1.0e-4): vec_edge_act = loop_act.link_loop_next.vert.co - loop_act.vert.co vec_edge_act.normalize() vec_edge_prev = loop_prev.vert.co - loop_prev.link_loop_next.vert.co vec_edge_prev.normalize() f_cross = None rotated = False if f_normal_act and f_normal_prev: f_normal_act = f_normal_act.normalized() f_normal_prev = f_normal_prev.normalized() f_angle = f_normal_act.angle(f_normal_prev) if threshold < f_angle < ANGLE_180 - threshold: vec_normal = f_normal_act + f_normal_prev vec_normal.normalize() f_cross = f_normal_act.cross(f_normal_prev) f_cross.normalize() elif f_angle > ANGLE_180 - threshold and rotaxis: # vec_edge and f_normal are slightly rotated # in order to manage folding faces. vec_edge_act_orig = vec_edge_act.copy() vec_edge_prev_orig = vec_edge_prev.copy() rot_act = Quaternion(rotaxis, 2 * threshold) rot_prev = rot_act.inverted() vec_edge_act.rotate(rot_act) vec_edge_prev.rotate(rot_prev) f_normal_act.rotate(rot_act) f_normal_prev.rotate(rot_prev) vec_normal = f_normal_act + f_normal_prev vec_normal.normalize() rotated = True else: vec_normal = f_normal_act elif f_normal_act or f_normal_prev: vec_normal = (f_normal_act or f_normal_prev).normalized() else: vec_normal = loop_act.face.normal.copy() if vec_normal.length == 0.0: if threshold < vec_edge_act.angle(Z_UP) < ANGLE_180 - threshold: vec_normal = Z_UP - Z_UP.project(vec_edge_act) vec_normal.normalize() else: # vec_edge is parallel to Z_UP vec_normal = Vector((0.0, 1.0, 0.0)) # 2d edge vectors are perpendicular to vec_normal vec_edge_act2d = vec_edge_act - vec_edge_act.project(vec_normal) vec_edge_act2d.normalize() vec_edge_prev2d = vec_edge_prev - vec_edge_prev.project(vec_normal) vec_edge_prev2d.normalize() angle2d = vec_edge_act2d.angle(vec_edge_prev2d) if angle2d < threshold: # folding corner corner_type = "FOLD" vec_tangent = vec_edge_act2d vec_angle2d = ANGLE_360 elif angle2d > ANGLE_180 - threshold: # straight corner corner_type = "STRAIGHT" vec_tangent = vec_edge_act2d.cross(vec_normal) vec_angle2d = ANGLE_180 else: direction = vec_edge_act2d.cross(vec_edge_prev2d).dot(vec_normal) if direction > 0.0: # convex corner corner_type = "CONVEX" vec_tangent = -(vec_edge_act2d + vec_edge_prev2d) vec_angle2d = angle2d else: # concave corner corner_type = "CONCAVE" vec_tangent = vec_edge_act2d + vec_edge_prev2d vec_angle2d = ANGLE_360 - angle2d if vec_tangent.dot(vec_normal): # Make vec_tangent perpendicular to vec_normal vec_tangent -= vec_tangent.project(vec_normal) vec_tangent.normalize() if f_cross: if vec_tangent.dot(f_cross) < 0.0: f_cross *= -1 angle_a = f_cross.angle(vec_edge_act2d) angle_p = f_cross.angle(vec_edge_prev2d) angle_sum = vec_angle2d + angle_a + angle_p if angle_a < threshold or angle_p < threshold or angle_sum > ANGLE_360 + threshold: # For the case in which vec_tangent is not # between vec_edge_act2d and vec_edge_prev2d. # Probably using 3d edge vectors is # more intuitive than 2d edge vectors. if corner_type == "CONVEX": vec_tangent = -(vec_edge_act + vec_edge_prev) else: # CONCAVE vec_tangent = vec_edge_act + vec_edge_prev vec_tangent.normalize() else: vec_tangent = f_cross if rotated: vec_edge_act = vec_edge_act_orig vec_edge_prev = vec_edge_prev_orig if corner_type == "FOLD": factor_act = factor_prev = 0 else: factor_act = 1.0 / sin(vec_tangent.angle(vec_edge_act)) factor_prev = 1.0 / sin(vec_tangent.angle(vec_edge_prev)) return vec_tangent, factor_act, factor_prev
def get_vector(loop_act, loop_prev, f_normal_act=None, f_normal_prev=None, rotaxis=None, threshold=1.0e-4): vec_edge_act = loop_act.link_loop_next.vert.co - loop_act.vert.co vec_edge_act.normalize() vec_edge_prev = loop_prev.vert.co - loop_prev.link_loop_next.vert.co vec_edge_prev.normalize() f_cross = None rotated = False if f_normal_act and f_normal_prev: f_normal_act = f_normal_act.normalized() f_normal_prev = f_normal_prev.normalized() f_angle = f_normal_act.angle(f_normal_prev) if threshold < f_angle < ANGLE_180 - threshold: vec_normal = f_normal_act + f_normal_prev vec_normal.normalize() f_cross = f_normal_act.cross(f_normal_prev) f_cross.normalize() elif f_angle > ANGLE_180 - threshold and rotaxis: # vec_edge and f_normal are slightly rotated # in order to manage folding faces. vec_edge_act_orig = vec_edge_act.copy() vec_edge_prev_orig = vec_edge_prev.copy() rot_act = Quaternion(rotaxis, 2 * threshold) rot_prev = rot_act.inverted() vec_edge_act.rotate(rot_act) vec_edge_prev.rotate(rot_prev) f_normal_act.rotate(rot_act) f_normal_prev.rotate(rot_prev) vec_normal = f_normal_act + f_normal_prev vec_normal.normalize() rotated = True else: vec_normal = f_normal_act elif f_normal_act or f_normal_prev: vec_normal = (f_normal_act or f_normal_prev).normalized() else: vec_normal = loop_act.face.normal.copy() if vec_normal.length == .0: if threshold < vec_edge_act.angle( Z_UP) < ANGLE_180 - threshold: vec_normal = Z_UP - Z_UP.project(vec_edge_act) vec_normal.normalize() else: # vec_edge is parallel to Z_UP vec_normal = Vector((.0, 1.0, .0)) # 2d edge vectors are perpendicular to vec_normal vec_edge_act2d = vec_edge_act - vec_edge_act.project(vec_normal) vec_edge_act2d.normalize() vec_edge_prev2d = vec_edge_prev - vec_edge_prev.project(vec_normal) vec_edge_prev2d.normalize() angle2d = vec_edge_act2d.angle(vec_edge_prev2d) if angle2d < threshold: # folding corner corner_type = 'FOLD' vec_tangent = vec_edge_act2d vec_angle2d = ANGLE_360 elif angle2d > ANGLE_180 - threshold: # straight corner corner_type = 'STRAIGHT' vec_tangent = vec_edge_act2d.cross(vec_normal) vec_angle2d = ANGLE_180 else: direction = vec_edge_act2d.cross(vec_edge_prev2d).dot(vec_normal) if direction > .0: # convex corner corner_type = 'CONVEX' vec_tangent = -(vec_edge_act2d + vec_edge_prev2d) vec_angle2d = angle2d else: # concave corner corner_type = 'CONCAVE' vec_tangent = vec_edge_act2d + vec_edge_prev2d vec_angle2d = ANGLE_360 - angle2d if vec_tangent.dot(vec_normal): # Make vec_tangent perpendicular to vec_normal vec_tangent -= vec_tangent.project(vec_normal) vec_tangent.normalize() if f_cross: if vec_tangent.dot(f_cross) < .0: f_cross *= -1 angle_a = f_cross.angle(vec_edge_act2d) angle_p = f_cross.angle(vec_edge_prev2d) angle_sum = vec_angle2d + angle_a + angle_p if (angle_a < threshold or angle_p < threshold or angle_sum > ANGLE_360 + threshold): # For the case in which vec_tangent is not # between vec_edge_act2d and vec_edge_prev2d. # Probably using 3d edge vectors is # more intuitive than 2d edge vectors. if corner_type == 'CONVEX': vec_tangent = -(vec_edge_act + vec_edge_prev) else: # CONCAVE vec_tangent = vec_edge_act + vec_edge_prev vec_tangent.normalize() else: vec_tangent = f_cross if rotated: vec_edge_act = vec_edge_act_orig vec_edge_prev = vec_edge_prev_orig if corner_type == 'FOLD': factor_act = factor_prev = 0 else: factor_act = 1. / sin(vec_tangent.angle(vec_edge_act)) factor_prev = 1. / sin(vec_tangent.angle(vec_edge_prev)) return vec_tangent, factor_act, factor_prev
def invertQuats(rig): for pb in rig.pose.bones: quat = Quaternion((pb.McpQuatW, pb.McpQuatX, pb.McpQuatY, pb.McpQuatZ)) pb.McpQuatW, pb.McpQuatX, pb.McpQuatY, pb.McpQuatZ = quat.inverted()
def execute(self, context): if self.type == "ACTIVE": actob = context.active_object if actob: rotation = actob.matrix_world.to_quaternion() else: return {"FINISHED"} elif self.type == "GRID": v3d = context.space_data if v3d.use_local_grid: rotation = v3d.local_grid_rotation else: rotation = Quaternion((1, 0, 0, 0)) else: rotation = self.rotation # world_rot = parent_mat * parent_inv * delta_rot * rot override = context.copy() for ob in vaob.sorted_objects(context.selected_objects): if self.type == "ACTIVE" and ob == context.active_object: continue # オペレータのソース部分を見ないと判らないってのはどうなのよ override["selected_objects"] = [ob] override["selected_editable_objects"] = [ob] if ob.parent: parent_mat = ob.parent.matrix_world.to_3x3() parent_inv = ob.matrix_parent_inverse.to_3x3() mat = parent_mat * parent_inv target_quat = mat.inverted().to_quaternion() * rotation else: target_quat = rotation if ob.rotation_mode == "AXIS_ANGLE": def rotate(quat): angle, *axis = ob.rotation_axis_angle local_quat = Quaternion(axis, angle) q = quat * local_quat axis, angle = q.to_axis_angle() ob.rotation_axis_angle = [angle] + list(axis) rotate(target_quat.inverted()) context.scene.update() bpy.ops.object.transform_apply(override, rotation=True) rotate(target_quat) elif ob.rotation_mode == "QUATERNION": # transform_apply()は # delta_rotation_quaternion * rotation_quaternion の回転状態で # 計算される。その後rotation_quaternionはクリアされるが # delta_rotation_quaternionの数値はそのまま残る if self.use_delta: delta = ob.delta_rotation_quaternion # normalize()必要? else: delta = Quaternion([1, 0, 0, 0]) rot = ob.rotation_quaternion # target_quatの逆回転を行いtransform_apply()、 # そしてtarget_quat分回転する # target.inverted() * delta * rot = delta * quat # quat = delta.inverted() * target.inverted() * delta * rot quat = delta.inverted() * target_quat.inverted() * delta * rot ob.rotation_quaternion = quat # ob.update_tag({'OBJECT', 'DATA'}) context.scene.update() bpy.ops.object.transform_apply(override, rotation=True) ob.rotation_quaternion = target_quat * ob.rotation_quaternion # ob.update_tag({'OBJECT', 'DATA'}) else: if self.use_delta: delta = ob.delta_rotation_euler.to_quaternion() else: delta = Quaternion([1, 0, 0, 0]) rot = ob.rotation_euler.to_quaternion() quat = delta.inverted() * target_quat.inverted() * delta * rot ob.rotation_euler = quat.to_euler(ob.rotation_mode) context.scene.update() bpy.ops.object.transform_apply(override, rotation=True) ob.rotation_euler = target_quat.to_euler(ob.rotation_mode) context.scene.update() return {"FINISHED"}