blender插件笔记

目录

文件拖拽导入

smpl导入导出

好像可以导入动画

smpl_blender_addon导入一帧

保存pose

导入导出完整代码


文件拖拽导入

https://github.com/mika-f/blender-drag-and-drop

支持格式:

  • *.abc
  • *.bvh
  • *.dae
  • *.fbx
  • *.glb
  • *.gltf
  • *.obj
  • *.ply
  • *.stl
  • *.svg
  • *.usd
  • *.usda
  • *.usdc
  • *.vrm (Required VRM Add-on for Blender)
  • *.x3d
  • *.wrl

smpl导入导出

好像可以导入动画

https://github.com/vltmedia/QuickMocap-BlenderAddon

smpl_blender_addon导入一帧

这个也是一次只能导入一帧,不能导入动画

https://github.com/Meshcapade/SMPL_blender_addon

这个可以写pose,就是把旋转角度保存下来

class SMPLSnapGroundPlane(bpy.types.Operator):bl_idname = "object.smpl_snap_ground_plane"bl_label = "Snap To Ground Plane"bl_description = ("Snaps mesh to the XY ground plane")bl_options = {'REGISTER', 'UNDO'}@classmethoddef poll(cls, context):try:# Enable button only if mesh or armature is active objectreturn ((context.object.type == 'MESH') or (context.object.type == 'ARMATURE'))except: return Falsedef execute(self, context):bpy.ops.object.mode_set(mode='OBJECT')obj = bpy.context.objectif obj.type == 'ARMATURE':armature = objobj = bpy.context.object.children[0]else:armature = obj.parent# Get vertices with applied skin modifier in object coordinatesdepsgraph = context.evaluated_depsgraph_get()object_eval = obj.evaluated_get(depsgraph)mesh_from_eval = object_eval.to_mesh()# Get vertices in world coordinatesmatrix_world = obj.matrix_worldvertices_world = [matrix_world @ vertex.co for vertex in mesh_from_eval.vertices]z_min = (min(vertices_world, key=lambda item: item.z)).zobject_eval.to_mesh_clear() # Remove temporary mesh# Translate armature edit bonescontext.view_layer.objects.active = armaturebpy.ops.object.mode_set(mode='EDIT')for edit_bone in armature.data.edit_bones:if edit_bone.name != "root":edit_bone.translate(Vector((0.0, 0.0, -z_min)))# Translate skinned mesh and apply translationbpy.ops.object.mode_set(mode='OBJECT')context.view_layer.objects.active = objobj.location = (0.0, 0.0, -z_min)bpy.ops.object.transform_apply(location = True)return {'FINISHED'}

保存pose

class SMPLWritePose(bpy.types.Operator):bl_idname = "object.smpl_write_pose"bl_label = "Write Pose1"bl_description = ("Writes SMPL pose thetas to console window")bl_options = {'REGISTER', 'UNDO'}@classmethoddef poll(cls, context):try:# Enable button only if mesh or armature is active objectreturn (context.object.type == 'MESH') or (context.object.type == 'ARMATURE')except: return Falsedef execute(self, context):obj = bpy.context.objectif obj.type == 'MESH':armature = obj.parentelse:armature = obj# Get armature pose in rodrigues representationpose = [0.0] * (len(SMPL_JOINT_NAMES) * 3)for index in range(len(SMPL_JOINT_NAMES)):joint_name = SMPL_JOINT_NAMES[index]joint_pose = rodrigues_from_pose(armature, joint_name)pose[index*3 + 0] = joint_pose[0]pose[index*3 + 1] = joint_pose[1]pose[index*3 + 2] = joint_pose[2]print("pose = " + str(pose))npz_file="1234.npz"np.savez_compressed(npz_file, joints_3d={"data": pose})return {'FINISHED'}

导入导出完整代码

这个可以导入导出,代码没有报错了,但是加载后没有显示出来,而且只能保存一帧,不能保存动画

# ##### BEGIN GPL LICENSE BLOCK #####
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2
#  of the License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
import loggingbl_info = {"name": "SMPL for Blender","author": "Joachim Tesch, Max Planck Institute for Intelligent Systems","version": (2021, 6, 11),"blender": (2, 80, 0),"location": "Viewport > Right panel","description": "SMPL for Blender","wiki_url": "https://smpl.is.tue.mpg.de/","category": "SMPL"}import bpy
import bmesh
from bpy_extras.io_utils import ExportHelper # ExportHelper is a helper class, defines filename and invoke() function which calls the file selector.from mathutils import Vector, Quaternion
from math import radians
import numpy as np
import os
import picklefrom bpy.props import ( BoolProperty, EnumProperty, FloatProperty, PointerProperty )
from bpy.types import ( PropertyGroup )# SMPL globals
SMPL_JOINT_NAMES = {0:  'Pelvis',1:  'L_Hip',        4:  'L_Knee',            7:  'L_Ankle',           10: 'L_Foot',2:  'R_Hip',        5:  'R_Knee',            8:  'R_Ankle',           11: 'R_Foot',3:  'Spine1',       6:  'Spine2',            9:  'Spine3',            12: 'Neck',            15: 'Head',13: 'L_Collar',     16: 'L_Shoulder',       18: 'L_Elbow',            20: 'L_Wrist',         22: 'L_Hand',14: 'R_Collar',     17: 'R_Shoulder',       19: 'R_Elbow',            21: 'R_Wrist',         23: 'R_Hand',
}
smpl_joints = len(SMPL_JOINT_NAMES) 
# End SMPL globalsdef rodrigues_from_pose(armature, bone_name):# Ensure that rotation mode is AXIS_ANGLE so the we get a correct readout of current posearmature.pose.bones[bone_name].rotation_mode = 'AXIS_ANGLE'axis_angle = armature.pose.bones[bone_name].rotation_axis_angleangle = axis_angle[0]rodrigues = Vector((axis_angle[1], axis_angle[2], axis_angle[3]))rodrigues.normalize()rodrigues = rodrigues * anglereturn rodriguesdef update_corrective_poseshapes(self, context):if self.smpl_corrective_poseshapes:bpy.ops.object.smpl_set_poseshapes('EXEC_DEFAULT')else:bpy.ops.object.smpl_reset_poseshapes('EXEC_DEFAULT')# Property groups for UI
class PG_SMPLProperties(PropertyGroup):smpl_gender: EnumProperty(name = "Model",description = "SMPL model",items = [ ("female", "Female", ""), ("male", "Male", "") ])smpl_texture: EnumProperty(name = "",description = "SMPL model texture",items = [ ("NONE", "None", ""), ("UV_GRID", "UV Grid", ""), ("COLOR_GRID", "Color Grid", "") ])smpl_corrective_poseshapes: BoolProperty(name = "Corrective Pose Shapes",description = "Enable/disable corrective pose shapes of SMPL model",update = update_corrective_poseshapes)smpl_export_setting_shape_keys: EnumProperty(name = "",description = "Blend shape export settings",items = [ ("SHAPE_POSE", "All: Shape + Posecorrectives", "Export shape keys for body shape and pose correctives"), ("SHAPE", "Reduced: Shape space only", "Export only shape keys for body shape"), ("NONE", "None: Apply shape space", "Do not export any shape keys, shape keys for body shape will be baked into mesh") ],)class SMPLAddGender(bpy.types.Operator):bl_idname = "scene.smpl_add_gender"bl_label = "Add"bl_description = ("Add SMPL model of selected gender to scene")bl_options = {'REGISTER', 'UNDO'}@classmethoddef poll(cls, context):try:# Enable button only if in Object Modeif (context.active_object is None) or (context.active_object.mode == 'OBJECT'):return Trueelse: return Falseexcept: return Falsedef execute(self, context):gender = context.window_manager.smpl_tool.smpl_genderprint("Adding gender: " + gender)path = os.path.dirname(os.path.realpath(__file__))objects_path = os.path.join(path, "data", "smpl-model-20200803.blend", "Object")object_name = "SMPL-mesh-" + genderbpy.ops.wm.append(filename=object_name, directory=str(objects_path))# Select imported meshobject_name = context.selected_objects[0].namebpy.ops.object.select_all(action='DESELECT')context.view_layer.objects.active = bpy.data.objects[object_name]bpy.data.objects[object_name].select_set(True)return {'FINISHED'}class SMPLSetTexture(bpy.types.Operator):bl_idname = "scene.smpl_set_texture"bl_label = "Set"bl_description = ("Set selected texture")bl_options = {'REGISTER', 'UNDO'}@classmethoddef poll(cls, context):try:# Enable button only if in active object is meshif (context.object.type == 'MESH'):return Trueelse:return Falseexcept: return Falsedef execute(self, context):texture = context.window_manager.smpl_tool.smpl_textureprint("Setting texture: " + texture)obj = bpy.context.objectif (len(obj.data.materials) == 0) or (obj.data.materials[0] is None):self.report({'WARNING'}, "Selected mesh has no material: %s" % obj.name)return {'CANCELLED'}mat = obj.data.materials[0]links = mat.node_tree.linksnodes = mat.node_tree.nodes# Find texture nodenode_texture = Nonefor node in nodes:if node.type == 'TEX_IMAGE':node_texture = nodebreak# Find shader nodenode_shader = Nonefor node in nodes:if node.type.startswith('BSDF'):node_shader = nodebreakif texture == 'NONE':# Unlink texture nodeif node_texture is not None:for link in node_texture.outputs[0].links:links.remove(link)nodes.remove(node_texture)# 3D Viewport still shows previous texture when texture link is removed via script.# As a workaround we trigger desired viewport update by setting color value.node_shader.inputs[0].default_value = node_shader.inputs[0].default_valueelse:if node_texture is None:node_texture = nodes.new(type="ShaderNodeTexImage")if texture == 'UV_GRID':if texture not in bpy.data.images:bpy.ops.image.new(name=texture, generated_type='UV_GRID')image = bpy.data.images[texture]else:if texture not in bpy.data.images:bpy.ops.image.new(name=texture, generated_type='COLOR_GRID')image = bpy.data.images[texture]node_texture.image = image# Link texture node to shader node if not already linkedif len(node_texture.outputs[0].links) == 0:links.new(node_texture.outputs[0], node_shader.inputs[0])return {'FINISHED'}class SMPLRandomShapes(bpy.types.Operator):bl_idname = "object.smpl_random_shapes"bl_label = "Random Shapes"bl_description = ("Sets all shape blend shape keys to a random value")bl_options = {'REGISTER', 'UNDO'}@classmethoddef poll(cls, context):try:# Enable button only if mesh is active objectreturn context.object.type == 'MESH'except: return Falsedef execute(self, context):obj = bpy.context.objectbpy.ops.object.mode_set(mode='OBJECT')for key_block in obj.data.shape_keys.key_blocks:if key_block.name.startswith("Shape"):key_block.value = np.random.normal(0.0, 1.0)bpy.ops.object.smpl_update_joint_locations('EXEC_DEFAULT')return {'FINISHED'}class SMPLResetShapes(bpy.types.Operator):bl_idname = "object.smpl_reset_shapes"bl_label = "Reset"bl_description = ("Resets all blend shape keys for shape")bl_options = {'REGISTER', 'UNDO'}@classmethoddef poll(cls, context):try:# Enable button only if mesh is active objectreturn context.object.type == 'MESH'except: return Falsedef execute(self, context):obj = bpy.context.objectbpy.ops.object.mode_set(mode='OBJECT')for key_block in obj.data.shape_keys.key_blocks:if key_block.name.startswith("Shape"):key_block.value = 0.0bpy.ops.object.smpl_update_joint_locations('EXEC_DEFAULT')return {'FINISHED'}class SMPLSnapGroundPlane(bpy.types.Operator):bl_idname = "object.smpl_snap_ground_plane"bl_label = "Snap To Ground Plane"bl_description = ("Snaps mesh to the XY ground plane")bl_options = {'REGISTER', 'UNDO'}@classmethoddef poll(cls, context):try:# Enable button only if mesh or armature is active objectreturn ((context.object.type == 'MESH') or (context.object.type == 'ARMATURE'))except: return Falsedef execute(self, context):bpy.ops.object.mode_set(mode='OBJECT')obj = bpy.context.objectif obj.type == 'ARMATURE':armature = objobj = bpy.context.object.children[0]else:armature = obj.parent# Get vertices with applied skin modifier in object coordinatesdepsgraph = context.evaluated_depsgraph_get()object_eval = obj.evaluated_get(depsgraph)mesh_from_eval = object_eval.to_mesh()# Get vertices in world coordinatesmatrix_world = obj.matrix_worldvertices_world = [matrix_world @ vertex.co for vertex in mesh_from_eval.vertices]z_min = (min(vertices_world, key=lambda item: item.z)).zobject_eval.to_mesh_clear() # Remove temporary mesh# Translate armature edit bonescontext.view_layer.objects.active = armaturebpy.ops.object.mode_set(mode='EDIT')for edit_bone in armature.data.edit_bones:if edit_bone.name != "root":edit_bone.translate(Vector((0.0, 0.0, -z_min)))# Translate skinned mesh and apply translationbpy.ops.object.mode_set(mode='OBJECT')context.view_layer.objects.active = objobj.location = (0.0, 0.0, -z_min)bpy.ops.object.transform_apply(location = True)return {'FINISHED'}class SMPLUpdateJointLocations(bpy.types.Operator):bl_idname = "object.smpl_update_joint_locations"bl_label = "Update Joint Locations"bl_description = ("Update joint locations after shape/expression changes")bl_options = {'REGISTER', 'UNDO'}j_regressor_male = Nonej_regressor_female = None@classmethoddef poll(cls, context):try:# Enable button only if mesh is active objectreturn ((context.object.type == 'MESH') and (context.object.parent.type == 'ARMATURE'))except: return Falsedef execute(self, context):obj = bpy.context.objectbpy.ops.object.mode_set(mode='OBJECT')if self.j_regressor_female is None:path = os.path.dirname(os.path.realpath(__file__))regressor_path = os.path.join(path, "data", "smpl_joint_regressor_female.npz")with np.load(regressor_path) as data:self.j_regressor_female = data['joint_regressor']if self.j_regressor_male is None:path = os.path.dirname(os.path.realpath(__file__))regressor_path = os.path.join(path, "data", "smpl_joint_regressor_male.npz")with np.load(regressor_path) as data:self.j_regressor_male = data['joint_regressor']if "female" in obj.name:j_regressor = self.j_regressor_femaleelse:j_regressor = self.j_regressor_male# Store current bone rotationsarmature = obj.parentbone_rotations = {}for pose_bone in armature.pose.bones:pose_bone.rotation_mode = 'AXIS_ANGLE'axis_angle = pose_bone.rotation_axis_anglebone_rotations[pose_bone.name] = (axis_angle[0], axis_angle[1], axis_angle[2], axis_angle[3])# Set model in default posefor bone in armature.pose.bones:bpy.ops.object.smpl_reset_poseshapes('EXEC_DEFAULT')bone.rotation_mode = 'AXIS_ANGLE'bone.rotation_axis_angle = (0, 0, 1, 0)# Reset corrective poseshapes if usedif context.window_manager.smpl_tool.smpl_corrective_poseshapes:bpy.ops.object.smpl_reset_poseshapes('EXEC_DEFAULT')# Get vertices with applied skin modifierdepsgraph = context.evaluated_depsgraph_get()object_eval = obj.evaluated_get(depsgraph)mesh_from_eval = object_eval.to_mesh()# Get Blender vertices as numpy matrixvertices_np = np.zeros((len(mesh_from_eval.vertices)*3), dtype=np.float)mesh_from_eval.vertices.foreach_get("co", vertices_np)vertices_matrix = np.reshape(vertices_np, (len(mesh_from_eval.vertices), 3))object_eval.to_mesh_clear() # Remove temporary mesh# Note: Current joint regressor uses 6890 vertices as input which is slow numpy operationjoint_locations = j_regressor @ vertices_matrix# Set new bone joint locationsbpy.context.view_layer.objects.active = armaturebpy.ops.object.mode_set(mode='EDIT')for index in range(smpl_joints):bone = armature.data.edit_bones[SMPL_JOINT_NAMES[index]]bone.head = (0.0, 0.0, 0.0)bone.tail = (0.0, 0.0, 0.1)bone_start = Vector(joint_locations[index])bone.translate(bone_start)bpy.ops.object.mode_set(mode='OBJECT')bpy.context.view_layer.objects.active = obj# Restore posefor pose_bone in armature.pose.bones:pose_bone.rotation_mode = 'AXIS_ANGLE'pose_bone.rotation_axis_angle = bone_rotations[pose_bone.name]# Restore corrective poseshapes if usedif context.window_manager.smpl_tool.smpl_corrective_poseshapes:bpy.ops.object.smpl_set_poseshapes('EXEC_DEFAULT')return {'FINISHED'}class SMPLSetPoseshapes(bpy.types.Operator):bl_idname = "object.smpl_set_poseshapes"bl_label = "Set Pose Shapes"bl_description = ("Sets corrective poseshapes for current pose")bl_options = {'REGISTER', 'UNDO'}@classmethoddef poll(cls, context):try:# Enable button only if mesh is active object and parent is armaturereturn ( ((context.object.type == 'MESH') and (context.object.parent.type == 'ARMATURE')) or (context.object.type == 'ARMATURE'))except: return False# https://github.com/gulvarol/surreal/blob/master/datageneration/main_part1.py# Computes rotation matrix through Rodrigues formula as in cv2.Rodriguesdef rodrigues_to_mat(self, rotvec):theta = np.linalg.norm(rotvec)r = (rotvec/theta).reshape(3, 1) if theta > 0. else rotveccost = np.cos(theta)mat = np.asarray([[0, -r[2], r[1]],[r[2], 0, -r[0]],[-r[1], r[0], 0]])return(cost*np.eye(3) + (1-cost)*r.dot(r.T) + np.sin(theta)*mat)# https://github.com/gulvarol/surreal/blob/master/datageneration/main_part1.py# Calculate weights of pose corrective blend shapes# Input is pose of all 24 joints, output is weights for all joints except pelvis (23)def rodrigues_to_posecorrective_weight(self, pose):joints_posecorrective = smpl_jointsrod_rots = np.asarray(pose).reshape(joints_posecorrective, 3)mat_rots = [self.rodrigues_to_mat(rod_rot) for rod_rot in rod_rots]bshapes = np.concatenate([(mat_rot - np.eye(3)).ravel() for mat_rot in mat_rots[1:]])return(bshapes)def execute(self, context):obj = bpy.context.object# Get armature pose in rodrigues representationif obj.type == 'ARMATURE':armature = objobj = bpy.context.object.children[0]else:armature = obj.parentpose = [0.0] * (smpl_joints * 3)for index in range(smpl_joints):joint_name = SMPL_JOINT_NAMES[index]joint_pose = rodrigues_from_pose(armature, joint_name)pose[index*3 + 0] = joint_pose[0]pose[index*3 + 1] = joint_pose[1]pose[index*3 + 2] = joint_pose[2]# print("Current pose: " + str(pose))poseweights = self.rodrigues_to_posecorrective_weight(pose)# Set weights for pose corrective shape keysfor index, weight in enumerate(poseweights):obj.data.shape_keys.key_blocks["Pose%03d" % index].value = weight# Set checkbox without triggering update functioncontext.window_manager.smpl_tool["smpl_corrective_poseshapes"] = Truereturn {'FINISHED'}class SMPLResetPoseshapes(bpy.types.Operator):bl_idname = "object.smpl_reset_poseshapes"bl_label = "Reset"bl_description = ("Resets corrective poseshapes for current pose")bl_options = {'REGISTER', 'UNDO'}@classmethoddef poll(cls, context):try:# Enable button only if mesh is active object and parent is armaturereturn ( ((context.object.type == 'MESH') and (context.object.parent.type == 'ARMATURE')) or (context.object.type == 'ARMATURE'))except: return Falsedef execute(self, context):obj = bpy.context.objectif obj.type == 'ARMATURE':obj = bpy.context.object.children[0]for key_block in obj.data.shape_keys.key_blocks:if key_block.name.startswith("Pose"):key_block.value = 0.0return {'FINISHED'}def set_pose_from_rodrigues(armature, bone_name, rodrigues, rodrigues_reference=None, frame=1):  # I wish frame=bpy.data.scenes[0].frame_current worked here, but it doesn'trod = Vector((rodrigues[0], rodrigues[1], rodrigues[2]))angle_rad = rod.lengthaxis = rod.normalized()pbone = armature.pose.bones[bone_name]pbone.rotation_mode = 'QUATERNION'quat = Quaternion(axis, angle_rad)if rodrigues_reference is None:pbone.rotation_quaternion = quatelse:# SMPL-X is adding the reference rodrigues rotation to the# relaxed hand rodrigues rotation, so we have to do the same here.# This means that pose values for relaxed hand model cannot be# interpreted as rotations in the local joint coordinate system of the relaxed hand.# https://github.com/vchoutas/smplx/blob/f4206853a4746139f61bdcf58571f2cea0cbebad/smplx/body_models.py#L1190#   full_pose += self.pose_meanrod_reference = Vector((rodrigues_reference[0], rodrigues_reference[1], rodrigues_reference[2]))rod_result = rod + rod_referenceangle_rad_result = rod_result.lengthaxis_result = rod_result.normalized()quat_result = Quaternion(axis_result, angle_rad_result)pbone.rotation_quaternion = quat_resultpbone.keyframe_insert(data_path="rotation_quaternion", frame=frame)if bone_name == 'pelvis':pbone.keyframe_insert('location', frame=frame)return
class SMPLLoadPose(bpy.types.Operator):bl_idname = "object.smpl_load_pose"bl_label = "Load Pose"bl_description = ("Load SMPL pose thetas to console window")bl_options = {'REGISTER', 'UNDO'}@classmethoddef poll(cls, context):try:# Enable button only if mesh or armature is active objectreturn (context.object.type == 'MESH') or (context.object.type == 'ARMATURE')except: return Falsedef execute(self, context):self.frame_number=5obj = bpy.context.objectif obj.type == 'MESH':armature = obj.parentelse:armature = objobj = armature.children[0]context.view_layer.objects.active = obj  # mesh needs to be active object for recalculating joint locationsjoint_names = SMPL_JOINT_NAMESobj = bpy.context.objectnpz_path = r"C:\Program Files\Blender Foundation\Blender 4.0\1234.npz"npz_data = np.load(npz_path, allow_pickle=True)if 'joints_3d' not in npz_data:print('joints_3d not find')returndata = npz_data['joints_3d'].item()['data']body_pose = data.reshape(( 24, 3))logging.error("np.array(data):"+str(len(np.array(data))))# pose_index = max(0, min(self.frame_number, (len(np.array(data)))))  # clamp the frame they give you from 0 and the max number of frames in this poses array# body_pose = np.array(data[pose_index]).reshape(len(joint_names), 3)# pose the entire bodyfor index in range(len(joint_names)):pose_rodrigues = body_pose[index]bone_name = joint_names[index]set_pose_from_rodrigues(armature, bone_name, pose_rodrigues, frame=bpy.data.scenes[0].frame_current)return {'FINISHED'}
class SMPLWritePose(bpy.types.Operator):bl_idname = "object.smpl_write_pose"bl_label = "Write Pose1"bl_description = ("Writes SMPL pose thetas to console window")bl_options = {'REGISTER', 'UNDO'}@classmethoddef poll(cls, context):try:# Enable button only if mesh or armature is active objectreturn (context.object.type == 'MESH') or (context.object.type == 'ARMATURE')except: return Falsedef execute(self, context):obj = bpy.context.objectif obj.type == 'MESH':armature = obj.parentelse:armature = obj# Get armature pose in rodrigues representationpose = [0.0] * (len(SMPL_JOINT_NAMES) * 3)for index in range(len(SMPL_JOINT_NAMES)):joint_name = SMPL_JOINT_NAMES[index]joint_pose = rodrigues_from_pose(armature, joint_name)pose[index*3 + 0] = joint_pose[0]pose[index*3 + 1] = joint_pose[1]pose[index*3 + 2] = joint_pose[2]print("pose = " + str(pose))npz_file="1234.npz"np.savez_compressed(npz_file, joints_3d={"data": np.array([pose])})return {'FINISHED'}class SMPLResetPose(bpy.types.Operator):bl_idname = "object.smpl_reset_pose"bl_label = "Reset Pose"bl_description = ("Resets pose to default zero pose")bl_options = {'REGISTER', 'UNDO'}@classmethoddef poll(cls, context):try:# Enable button only if mesh is active objectreturn ( ((context.object.type == 'MESH') and (context.object.parent.type == 'ARMATURE')) or (context.object.type == 'ARMATURE'))except: return Falsedef execute(self, context):obj = bpy.context.objectif obj.type == 'MESH':armature = obj.parentelse:armature = objfor bone in armature.pose.bones:bone.rotation_mode = 'AXIS_ANGLE'bone.rotation_axis_angle = (0, 0, 1, 0)# Reset corrective pose shapesbpy.ops.object.smpl_reset_poseshapes('EXEC_DEFAULT')return {'FINISHED'}class SMPLExportUnityFBX(bpy.types.Operator, ExportHelper):bl_idname = "object.smpl_export_unity_fbx"bl_label = "Export Unity FBX"bl_description = ("Export skinned mesh to Unity in FBX format")bl_options = {'REGISTER', 'UNDO'}# ExportHelper mixin class uses thisfilename_ext = ".fbx"@classmethoddef poll(cls, context):try:# Enable button only if mesh is active objectreturn (context.object.type == 'MESH')except: return Falsedef execute(self, context):obj = bpy.context.objectexport_shape_keys = context.window_manager.smpl_tool.smpl_export_setting_shape_keysarmature_original = obj.parentskinned_mesh_original = obj# Operate on temporary copy of skinned mesh and armaturebpy.ops.object.select_all(action='DESELECT')skinned_mesh_original.select_set(True)armature_original.select_set(True)bpy.context.view_layer.objects.active = skinned_mesh_originalbpy.ops.object.duplicate()skinned_mesh = bpy.context.objectarmature = skinned_mesh.parent# Reset posebpy.ops.object.smpl_reset_pose('EXEC_DEFAULT')if export_shape_keys != 'SHAPE_POSE':# Remove pose corrective shape keysprint('Removing pose corrective shape keys')num_shape_keys = len(skinned_mesh.data.shape_keys.key_blocks.keys())current_shape_key_index = 0for index in range(0, num_shape_keys):bpy.context.object.active_shape_key_index = current_shape_key_indexif bpy.context.object.active_shape_key is not None:if bpy.context.object.active_shape_key.name.startswith('Pose'):bpy.ops.object.shape_key_remove(all=False)else:current_shape_key_index = current_shape_key_index + 1        if export_shape_keys == 'NONE':# Bake and remove shape keysprint("Baking shape and removing shape keys for shape")# Create shape mix for current shapebpy.ops.object.shape_key_add(from_mix=True)num_shape_keys = len(skinned_mesh.data.shape_keys.key_blocks.keys())# Remove all shape keys except newly added onebpy.context.object.active_shape_key_index = 0for count in range(0, num_shape_keys):bpy.ops.object.shape_key_remove(all=False)# Model (skeleton and skinned mesh) needs to have rotation of (90, 0, 0) when exporting so that it will have rotation (0, 0, 0) when imported into Unitybpy.ops.object.mode_set(mode='OBJECT')bpy.ops.object.select_all(action='DESELECT')skinned_mesh.select_set(True)skinned_mesh.rotation_euler = (radians(-90), 0, 0)bpy.context.view_layer.objects.active = skinned_meshbpy.ops.object.transform_apply(rotation = True)skinned_mesh.rotation_euler = (radians(90), 0, 0)skinned_mesh.select_set(False)armature.select_set(True)armature.rotation_euler = (radians(-90), 0, 0)bpy.context.view_layer.objects.active = armaturebpy.ops.object.transform_apply(rotation = True)armature.rotation_euler = (radians(90), 0, 0)# Select armature and skinned mesh for exportskinned_mesh.select_set(True)# Rename armature and skinned mesh to not contain Blender copy suffixif "female" in skinned_mesh.name:gender = "female"else:gender = "male"target_mesh_name = "SMPL-mesh-%s" % gendertarget_armature_name = "SMPL-%s" % genderif target_mesh_name in bpy.data.objects:bpy.data.objects[target_mesh_name].name = "SMPL-temp-mesh"skinned_mesh.name = target_mesh_nameif target_armature_name in bpy.data.objects:bpy.data.objects[target_armature_name].name = "SMPL-temp-armature"armature.name = target_armature_namebpy.ops.export_scene.fbx(filepath=self.filepath, use_selection=True, apply_scale_options="FBX_SCALE_ALL", add_leaf_bones=False)print("Exported: " + self.filepath)# Remove temporary copies of armature and skinned meshbpy.ops.object.select_all(action='DESELECT')skinned_mesh.select_set(True)armature.select_set(True)bpy.ops.object.delete()bpy.ops.object.select_all(action='DESELECT')skinned_mesh_original.select_set(True)bpy.context.view_layer.objects.active = skinned_mesh_originalif "SMPL-temp-mesh" in bpy.data.objects:bpy.data.objects["SMPL-temp-mesh"].name = target_mesh_nameif "SMPL-temp-armature" in bpy.data.objects:bpy.data.objects["SMPL-temp-armature"].name = target_armature_namereturn {'FINISHED'}class SMPL_PT_Model(bpy.types.Panel):bl_label = "SMPL Model"bl_category = "SMPL"bl_space_type = "VIEW_3D"bl_region_type = "UI"def draw(self, context):layout = self.layoutcol = layout.column(align=True)row = col.row(align=True)col.prop(context.window_manager.smpl_tool, "smpl_gender")col.operator("scene.smpl_add_gender", text="Add")col.separator()col.label(text="Texture:")row = col.row(align=True)split = row.split(factor=0.75, align=True)split.prop(context.window_manager.smpl_tool, "smpl_texture")split.operator("scene.smpl_set_texture", text="Set")class SMPL_PT_Shape(bpy.types.Panel):bl_label = "Shape"bl_category = "SMPL"bl_space_type = "VIEW_3D"bl_region_type = "UI"def draw(self, context):layout = self.layoutcol = layout.column(align=True)row = col.row(align=True)split = row.split(factor=0.75, align=True)split.operator("object.smpl_random_shapes")split.operator("object.smpl_reset_shapes")col.separator()col.operator("object.smpl_snap_ground_plane")col.separator()col.operator("object.smpl_update_joint_locations")class SMPL_PT_Pose(bpy.types.Panel):bl_label = "Pose"bl_category = "SMPL"bl_space_type = "VIEW_3D"bl_region_type = "UI"def draw(self, context):layout = self.layoutcol = layout.column(align=True)col.prop(context.window_manager.smpl_tool, "smpl_corrective_poseshapes")col.separator()col.operator("object.smpl_set_poseshapes")col.separator()col.operator("object.smpl_load_pose")col.separator()col.operator("object.smpl_write_pose")col.separator()class SMPL_PT_Export(bpy.types.Panel):bl_label = "Export"bl_category = "SMPL"bl_space_type = "VIEW_3D"bl_region_type = "UI"def draw(self, context):layout = self.layoutcol = layout.column(align=True)col.label(text="Shape Keys (Blend Shapes):")col.prop(context.window_manager.smpl_tool, "smpl_export_setting_shape_keys")col.separator()col.separator()col.operator("object.smpl_export_unity_fbx")col.separator()#        export_button = col.operator("export_scene.obj", text="Export OBJ [m]", icon='EXPORT')
#        export_button.global_scale = 1.0
#        export_button.use_selection = True
#        col.separator()row = col.row(align=True)row.operator("ed.undo", icon='LOOP_BACK')row.operator("ed.redo", icon='LOOP_FORWARDS')col.separator()(year, month, day) = bl_info["version"]col.label(text="Version: %s-%s-%s" % (year, month, day))classes = [PG_SMPLProperties,SMPLAddGender,SMPLSetTexture,SMPLRandomShapes,SMPLResetShapes,SMPLSnapGroundPlane,SMPLUpdateJointLocations,SMPLSetPoseshapes,SMPLResetPoseshapes,SMPLLoadPose,SMPLWritePose,SMPLResetPose,SMPLExportUnityFBX,SMPL_PT_Model,SMPL_PT_Shape,SMPL_PT_Pose,SMPL_PT_Export
]def register():from bpy.utils import register_classfor cls in classes:bpy.utils.register_class(cls)# Store properties under WindowManager (not Scene) so that they are not saved in .blend files and always show default values after loadingbpy.types.WindowManager.smpl_tool = PointerProperty(type=PG_SMPLProperties)def unregister():from bpy.utils import unregister_classfor cls in classes:bpy.utils.unregister_class(cls)del bpy.types.WindowManager.smpl_toolif __name__ == "__main__":register()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/768564.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【QT问题】 Qt信号函数如果重名,调用怎么处理

问题描述: 在调用某个类的信号函数的时候,出现信号函数名字相同,参数不同的情况,但是Qt在链接信号槽的时候,又不需要指明信号函数参数,此时就会出现无法分辨的情况。 例如:QComboBox的信号 Q_…

前端学习之用css和html做一个仿淘宝的导航栏

代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>仿淘宝界面案例</title><style>/* 最外层盒子 */.container{width: 270px;height: 385px;border: 1px solid rgb(255, 208, 0);bord…

MacOS快速安装FFmpeg、ffprobe、ffplay

文章目录 一、工具简介二、mac 安装ffprobe、FFmpeg等相关工具2.1 方法一&#xff1a;使用Homebrew安装FFmpeg2.2 从官网下载FFmpeg安装包&#xff0c;源码安装2.3 macOS 无法验证开发者时安装 一、工具简介 这些工具都是与多媒体处理和流媒体相关的开源工具&#xff0c;它们都…

学习vue3第十节(插槽v-slot)

本节主要介绍一下 v-slot 插槽指令&#xff0c;以及插槽相关内容 1、定义&#xff1a; 子组件给父组件提供使用的一个位置&#xff0c;使用<slot></slot>表示&#xff0c;父组件可以在这个位置填充任何代码&#xff1b; 2、默认插槽 匿名插槽&#xff1a;会自定…

JavaScript中的正则表达式使用总结

JavaScript中的正则表达式是一种强大的工具&#xff0c;用于处理文本数据&#xff0c;包括搜索、匹配和替换文本中的特定字符或模式。以下是对JavaScript中正则表达式使用的一些总结&#xff1a; 1. 创建正则表达式 在JavaScript中&#xff0c;你可以使用字面量或RegExp对象来…

管道疏通房屋补漏官方网站源码-视频搭建教程

[安全]修复jquery低版本的xss安全漏洞&#xff0c;升级用最新版jquery&#xff1b; [新增]后台的登录页、欢迎页支持自定义模板文件&#xff1b; [新增]后台多语言列表管理支持手工同步文档数据&#xff1b; [新增]后台商品发布时&#xff0c;单规格商品支持会员折扣价的设置…

微信小程序多图列表页面性能问题为什么会出现?如何解决?

微信小程序中的多图列表页面性能问题主要是由于以下几个原因导致的&#xff1a; 图片过大&#xff1a;在多图列表页面中&#xff0c;如果图片过大&#xff0c;会导致页面加载时间过长&#xff0c;从而影响用户体验。请求过多&#xff1a;在多图列表页面中&#xff0c;如果一次…

C语言自定义类型联合体和枚举

union n.工会&#xff1b;联邦&#xff0c;联盟&#xff1b;协会&#xff0c;俱乐部&#xff1b;联合&#xff0c;合并&#xff1b; 结婚&#xff0c;婚姻&#xff1b;美利坚合众国&#xff08;the Union&#xff09;&#xff1b; &#xff08;数&#xff09;并&#xff0c;并集…

Java学习10

目录 一.多态&#xff1a; 1.方法的多态&#xff1a; 2.对象的多态&#xff1a; 3.多态的注意事项与细节&#xff1a; 5.多态的应用: 二.Java的动态绑定机制&#xff1a; 三.多态应用&#xff1a; 1.多态数组&#xff1a; 2.多态参数&#xff1a; 三.Object类&#xf…

交互式QGraphicsView(平移/缩放/旋转)

一 简述 Graphics View提供了一个平台&#xff0c;用于大量自定义 2D 图元的管理与交互&#xff0c;框架包括一个事件传播架构&#xff0c;支持场景 Scene 中的图元 Item 进行精确的双精度交互功能。Item 可以处理键盘事件、鼠标按下、移动、释放和双击事件&#xff0c;同时也…

golang实现枚举

golang实现枚举 golang实现枚举 golang本身是没有枚举类型的&#xff0c;不像c语言&#xff0c;但是可以通过const & iota实现枚举的能力。 枚举在类似于业务状态或者少量下拉选择框中经常使用&#xff0c;比如 业务状态&#xff1a;待开始、进行中、失败、成功package ma…

福昕阅读器 PDF 文档基本操作

福昕阅读器 PDF 文档基本操作 References 转至 PDF 顶部 快捷键&#xff1a;Home. 转至 PDF 顶部 快捷键&#xff1a;End. 打开超链接 文本选择工具 -> 手形工具 (Hand Tool) -> 点击超链接 福昕阅读器 同时在多个窗口中打开多个文件 文件 -> 偏好设置 -> 文…

高中信息技术教资刷题笔记_选择题篇

1.信息技术基础 位与字节的换算 模2除法运算 网页保存 进制之间的计算 教你快速学会二进制、十进制、十六进制之间的转换 - 知乎 (zhihu.com) 原码、补码、反码计算 物联网技术 位运算 按位与&#xff1a;同位置为1&#xff0c;则为1&#xff0c;其他都是0按位或&#xff1a;有…

黑帽子学Python

黑帽子学Python Python位运算符 运算符描述示例&按位与运算符&#xff1a;参与运算的两个值&#xff0c;如果两个相应位都为1&#xff0c;则该为的结果为1&#xff0c;否则为0(a&b)输出结果12&#xff0c;二进制解释&#xff1a;0000 1100按位或运算符&#xff1a;只…

MRC是谁?- 媒体评级委员会 Media Rating Council

在在线广告的世界里&#xff0c;有许多不同的技术和实践用于提供和衡量广告。对于广告商、出版商和营销人员来说&#xff0c;了解这些技术是如何工作的以及如何有效使用这些技术很重要。在这方面发挥关键作用的一个组织是媒体评级委员会&#xff08;MRC&#xff09;。 1. 了解…

Android 项目新建问题总结

title: Android 项目新建问题总结 search: 2024-03-24 tags: “#Android 项目新建问题总结” Android 项目新建问题总结 一、gradle 项目每次都自动下载依赖包到C盘 背景&#xff1a;idea 首次打开一个 gradle 项目&#xff0c;都会在 C 盘下载项目所需的依赖包&#xff0c;但…

Automatic Prompt Engineering

让大模型自己生成prompt&#xff0c;生成提示&#xff08;prompt&#xff09;存在两种不同的操作方式。第一种方式是在文本空间中进行&#xff0c;这种提示以离散的文本形式存在。第二种方式是将提示抽象成一个向量&#xff0c;在特征空间中进行操作&#xff0c;这种提示是抽象…

React高阶组件(HOC)

高阶组件的基本概念 高阶组件&#xff08;HOC&#xff0c;Higher-Order Components&#xff09;不是组件&#xff0c;而是一个函数&#xff0c;它会接收一个组件作为参数并返回一个经过改造的新组件&#xff1a; const EnhancedComponent higherOrderComponent(WrappedCompo…

Go 实现fsnotify

【官方操作】 package mainimport ("log""github.com/fsnotify/fsnotify" )func main() {watcher, err : fsnotify.NewWatcher()if err ! nil {log.Fatal(err)}defer watcher.Close()done : make(chan bool)go func() {for {select {case event, ok : <…

使用 Docker Compose 部署 Spring Boot 应用

使用 Docker Compose 部署 Spring Boot 应用 第一步&#xff1a;创建 Spring Boot 应用的 Dockerfile 在您的 Spring Boot 项目根目录中创建一个 Dockerfile。 编辑 Dockerfile&#xff0c;添加以下内容&#xff1a; # 基础镜像使用 OpenJDK FROM openjdk:11-jdk-slim# 维护者…