def process(self): if not (self.inputs['Vertices'].is_linked): return if not (any(output.is_linked for output in self.outputs)): return vertices_s = self.inputs['Vertices'].sv_get(default=[[]]) edges_s = self.inputs['Edges'].sv_get(default=[[]]) faces_s = self.inputs['Polygons'].sv_get(default=[[]]) face_data_s = self.inputs['FaceData'].sv_get(default=[[]]) matrixes_s = self.inputs['Matrix'].sv_get(default=[[Matrix()]]) result_vertices = [] result_edges = [] result_faces = [] result_face_data = [] meshes = match_long_repeat([vertices_s, edges_s, faces_s, face_data_s, matrixes_s]) for vertices, edges, faces, face_data, matrixes in zip(*meshes): if face_data: fullList(face_data, len(faces)) if isinstance(matrixes, list): matrix = matrixes[0] else: matrix = matrixes has_matrix = matrix is not None and matrix != Matrix() # TODO: this is actually a workaround for a known Blender bug # https://developer.blender.org/T59804 mirror_axis = self.get_mirror_direction() if mirror_axis is not None: vertices = self.mirror(vertices, mirror_axis, matrix) bm = bmesh_from_pydata(vertices, edges, faces, markup_face_data=True) if has_matrix: bmesh.ops.transform(bm, matrix = matrix.inverted(), verts = list(bm.verts)) bmesh.ops.symmetrize( bm, input = list(bm.verts) + list(bm.edges) + list(bm.faces), direction = self.get_symmetrize_direction(), dist = self.merge_dist ) if has_matrix: bmesh.ops.transform(bm, matrix = matrix, verts = list(bm.verts)) if face_data: new_vertices, new_edges, new_faces, new_face_data = pydata_from_bmesh(bm, face_data) else: new_vertices, new_edges, new_faces = pydata_from_bmesh(bm) new_face_data = [] if mirror_axis is not None: new_vertices = self.mirror(new_vertices, mirror_axis, matrix) bm.free() result_vertices.append(new_vertices) result_edges.append(new_edges) result_faces.append(new_faces) result_face_data.append(new_face_data) self.outputs['Vertices'].sv_set(result_vertices) self.outputs['Edges'].sv_set(result_edges) self.outputs['Polygons'].sv_set(result_faces) self.outputs['FaceData'].sv_set(result_face_data)
def screen(ot, context, event): preference = addon.preference() bc = context.window_manager.bc verts = [ Vector((-1000.0, -1000.0, 0.0)), Vector((1000.0, -1000.0, 0.0)), Vector((-1000.0, 1000.0, 0.0)), Vector((1000.0, 1000.0, 0.0)) ] edges = [(0, 2), (0, 1), (1, 3), (2, 3)] faces = [(0, 1, 3, 2)] data = bpy.data.meshes.new(name='Box') data.bc.removeable = True if not bc.snap.hit: data.from_pydata(verts, edges, faces) data.validate() box = bpy.data.objects.new( name='Box', object_data=data if not bc.snap.hit else bc.snap.mesh) bpy.context.scene.collection.objects.link(box) del data box.data.bc.removeable = True if not bc.snap.hit else False if not bc.snap.hit: mod = box.modifiers.new(name='Solidify', type='SOLIDIFY') mod.thickness = max(dimension for dimension in ot.datablock['dimensions']) * 1.75 mod.offset = 0 modifier.apply(obj=box, mod=mod) del mod box.data.transform( context.region_data.view_rotation.to_euler().to_matrix().to_4x4()) matrix = Matrix() matrix.translation = bc.original_active.matrix_world @ object.center( bc.original_active) box.data.transform(matrix) hit, ot.ray['location'], ot.ray['normal'], index = ray.cast.objects( *ot.mouse['location'], mesh=box.data) bpy.data.objects.remove(box) del box bc.lattice.matrix_world = context.region_data.view_rotation.to_euler( ).to_matrix().to_4x4() bc.lattice.matrix_world.translation = Vector( ot.ray['location'][:] if not bc.snap.hit else bc.snap.location) bc.shape.matrix_world = bc.lattice.matrix_world bc.plane.matrix_world = bc.lattice.matrix_world ot.start['matrix'] = bc.plane.matrix_world.copy() bc.location = ot.ray['location'] if not bc.snap.hit else bc.snap.location refresh.shape(ot, context, event)
def to_base_vertices(deform_verts: bmesh.types.BMVertSeq, to_world_matrix, target_direction, target_origin, deform_vertex_index_weights: Dict[int, float], base_area_factor: float, project_vertically: bool) -> List[Vector]: ortho_projection_matrix = Matrix.OrthoProjection(target_direction, 4) f_l = 1 intrinsic_matrix = Matrix([ [f_l, 0.0, 0.0, 0.0], [0.0, f_l, 0.0, 0.0], [0.0, 0.0, f_l, 0.0], [0.0, 0.0, 0.0, 1.0] ]) wide_projection_matrix: Matrix = intrinsic_matrix @ ortho_projection_matrix @ Matrix.Translation(-target_origin) wide_project_2d_vertices: Set[Tuple[float, float]] = set() wide_project_3d_vertices: List[Vector] = [] deform_verts.ensure_lookup_table() for deform_vertex_index, deform_vertex_weight in deform_vertex_index_weights.items(): wide_project_3d_vertex = wide_projection_matrix @ (to_world_matrix @ deform_verts[deform_vertex_index].co) wide_project_2d_vertex = wide_project_3d_vertex / wide_project_3d_vertex[2] wide_project_2d_vertices.add(wide_project_2d_vertex[0:2]) wide_project_3d_vertices.append(wide_project_3d_vertex * (deform_vertex_weight**base_area_factor)) box_fit_angle: float = mathutils.geometry.box_fit_2d(list(wide_project_2d_vertices)) rotate_matrix: Matrix = Matrix.Rotation(+box_fit_angle, 4, target_direction) @ ortho_projection_matrix x_min = float('+inf') x_max = float('-inf') z_min = float('+inf') z_max = float('-inf') for vertex in wide_project_3d_vertices: rotate_vertex: Vector = rotate_matrix @ vertex if x_min > rotate_vertex.x: x_min = rotate_vertex.x if x_max < rotate_vertex.x: x_max = rotate_vertex.x if z_min > rotate_vertex.z: z_min = rotate_vertex.z if z_max < rotate_vertex.z: z_max = rotate_vertex.z rotate_matrix_invert: Matrix if project_vertically: front_vector = Vector([0, -1, 0]) rotate_matrix_invert = Matrix.Rotation(-box_fit_angle, 4, front_vector) @ Matrix.OrthoProjection(front_vector, 4) else: rotate_matrix_invert = Matrix.Rotation(-box_fit_angle, 4, target_direction) @ ortho_projection_matrix base_vertices: List[Vector] = [ rotate_matrix_invert @ Vector([x_min, 0, 0]), rotate_matrix_invert @ Vector([0, 0, z_min]), rotate_matrix_invert @ Vector([x_max, 0, 0]), rotate_matrix_invert @ Vector([0, 0, z_max]), ] return base_vertices
# [m01, m11, m21, m31], # [m02, m12, m22, m32], # [m03, m13, m23, m33])) # # return m.transposed() def quat_equals(q1,q2): return q1.w == q2.w and q1.x == q2.x and q1.y == q2.y and q1.z == q2.z quat_transform_y_positive = Euler((pi/2, 0, 0),"XYZ").to_quaternion() m4 = Matrix( ([1, 0, 0, 0], [0, 0, -1, 0], [0, 1, 0, 0], [0, 0, 0, 1])) m3 = Matrix( ([1, 0, 0], [0, 0, -1], [0, 1, 0])) matrix_3_transform_y_positive = Matrix((( 1, 0, 0 ) ,( 0, 0, 1 ) ,( 0,-1, 0 ) )) matrix_4_transform_y_positive = Matrix((( 1, 0, 0, 0 ),( 0, 0, 1, 0 ),( 0,-1, 0, 0 ),( 0, 0, 0, 1 ))) matrix_3_transform_z_positive = Matrix((( 1, 0, 0 ) ,( 0, 0,-1 ) ,( 0, 1, 0 ) )) matrix_4_transform_z_positive = Matrix((( 1, 0, 0, 0 ),( 0, 0,-1, 0 ),( 0, 1, 0, 0 ),( 0, 0, 0, 1 ))) class Matrix4f():
def read_file(operator, context): from mathutils import (Matrix, Vector) import math filepath = operator.filepath se3_mesh = get_se3_mesh_form_file(filepath) for se3_layer in se3_mesh.layers: fgon_edge_indices = [] vertices = se3_layer.vertex_maps[0].elements edges = [] real_faces = [] se3_surface_map_indices = [0] * len(se3_layer.polygons) material_indices = [] for se3_surface_map_index, se3_surface_map in enumerate( se3_layer.surface_maps): for polygon_index in se3_surface_map.polygons: se3_surface_map_indices[polygon_index] = se3_surface_map_index edge_index_count = 0 for se3_polygon_index, se3_polygon in enumerate(se3_layer.polygons): se3_num_of_vertex_indices = len(se3_polygon) se3_is_tri_or_quad = se3_num_of_vertex_indices <= 4 se3_surface_map_index = se3_surface_map_indices[se3_polygon_index] if se3_is_tri_or_quad: material_indices.append(se3_surface_map_index) face = get_bl_face(se3_layer, se3_polygon) real_faces.append(face) face_edges = get_bl_edges(face[0]) for face_edge in face_edges: """ if edge_not_in(face_edge, edges): edges.append(face_edge) edge_index_count += 1 """ edges.append(face_edge) edge_index_count += 1 else: ngon_face = get_bl_face(se3_layer, se3_polygon) bound_edges = get_bl_edges(ngon_face[0]) fgon_faces = get_bl_fgons(vertices, ngon_face[0]) for fgon_face in fgon_faces: material_indices.append(se3_surface_map_index) real_faces.append( tuple([ fgon_face, get_bl_face_uv_data(ngon_face, fgon_face) ])) face_edges = get_bl_edges(fgon_face) for face_edge in face_edges: is_fgon_edge = edge_not_in(face_edge, bound_edges) edges.append(face_edge) if is_fgon_edge: fgon_edge_indices.append(edge_index_count) edge_index_count += 1 faces = [real_face[0] for real_face in real_faces] mesh = bpy.data.meshes.new("Test mesh") mesh.from_pydata(vertices, edges, faces) for fgon_edge_index in fgon_edge_indices: mesh.edges[fgon_edge_index].is_fgon = True for uv_index, se3_texcoord_map in enumerate(se3_layer.texcoord_maps): uv_tex = mesh.uv_textures.new(se3_texcoord_map.name) uv_loop = mesh.uv_layers[0] for face_index, tex_data in enumerate(uv_tex.data): real_tex_face = real_faces[face_index][1][uv_index] poly = mesh.polygons[face_index] for j, k in enumerate(poly.loop_indices): uv_loop.data[k].uv = real_tex_face[j] tranf_mat = Matrix(((-1.0, 0.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, 1.0, 0.0, 0.0), (0.0, 0.0, 0.0, 1.0))) obj = bpy.data.objects.new(se3_layer.name, mesh) scene = context.scene scene.objects.link(obj) scene.objects.active = obj obj.select = True se3_non_basic_morph_map = se3_layer.non_basic_morph_maps se3_vertices = se3_layer.vertices if se3_non_basic_morph_map: obj.shape_key_add("position") shape_keys = [] for se3_other_mmap in se3_non_basic_morph_map: shape_keys.append(obj.shape_key_add(se3_other_mmap.name)) for se3_vertex in se3_vertices: other_morph_pnts = se3_vertex.non_basic_morph_pointers if other_morph_pnts: for idx, other_mp in enumerate(other_morph_pnts): type_idx = se3_layer.vertex_maps[ other_mp[0]].type_index se3_disp = se3_layer.vertex_maps[other_mp[0]].elements[ other_mp[1]] se3_vert = se3_vertex.basic_morph_pointer[1] vert_data = se3_layer.vertex_maps[ se3_vertex.basic_morph_pointer[0]].elements[ se3_vertex.basic_morph_pointer[1]] shape_keys[type_idx - 1].data[se3_vert].co = Vector( vert_data) + Vector(se3_disp) se3_weight_maps = se3_layer.weight_maps if se3_weight_maps: vertex_groups = [] for se3_weight_map in se3_weight_maps: vertex_groups.append(obj.vertex_groups.new( se3_weight_map.name)) for se3_vertex in se3_vertices: se3_weight_pointers = se3_vertex.weight_pointers if se3_weight_pointers: for se3_weight_pointer in se3_weight_pointers: vertex_index = se3_vertex.basic_morph_pointer[1] se3_vertex_map_index = se3_weight_pointer[0] se3_vertex_weight = se3_layer.vertex_maps[ se3_vertex_map_index].elements[ se3_weight_pointer[1]] vertex_group_index = se3_layer.vertex_maps[ se3_vertex_map_index].type_index vertex_groups[vertex_group_index].add( [vertex_index], se3_vertex_weight, 'REPLACE') if se3_layer.surface_maps: materials = [] for se3_surface_map in se3_layer.surface_maps: material = bpy.data.materials.new(se3_surface_map.name) materials.append(material) bpy.ops.object.material_slot_add() obj.material_slots[-1].material = material for face in mesh.polygons: face.material_index = material_indices[face.index] obj.matrix_world = tranf_mat bpy.ops.object.transform_apply(rotation=True) scene.update() return {'FINISHED'}
def array_to_matrix4(arr): """Convert a single 16-len tuple into a valid 4D Blender matrix""" # Blender matrix is row major, fbx is col major so transpose on read return Matrix(tuple(zip(*[iter(arr)]*4))).transposed()
# <pep8 compliant> import bpy from mathutils import Vector, Matrix from ..mu import MuMesh, MuRenderer, MuSkinnedMeshRenderer, MuBoneWeight from ..utils import collect_modifiers from .material import make_material from .export_util import is_collider from pprint import pprint #matrix for converting between LHS and RHS (works either direction) Matrix_YZ = Matrix(((1, 0, 0, 0), (0, 0, 1, 0), (0, 1, 0, 0), (0, 0, 0, 1))) MU_MAX_VERTS = 65534 def build_submeshes(mesh): submeshes = [] submesh = [] for i in range(len(mesh.loop_triangles)): submesh.append(i) submeshes.append(submesh) return submeshes def make_tris(mesh, submeshes, vertex_map): for sm in submeshes:
def convert_pose_array_to_matrix(R, T): mat = Matrix(R.reshape(3, 3)).to_4x4() mat.col[3][:3] = T return mat
def process(self): self.handle_attr_socket() if not (self.id_data.sv_show and self.activate): callback_disable(node_id(self)) return n_id = node_id(self) callback_disable(n_id) if not any([self.display_verts, self.display_edges, self.display_faces]): return verts_socket, edges_socket, faces_socket, matrix_socket = self.inputs[:4] if verts_socket.is_linked: display_faces = self.display_faces and faces_socket.is_linked display_edges = self.display_edges and (edges_socket.is_linked or faces_socket.is_linked) config = self.fill_config() data = self.get_data() if len(data[0]) > 1: coords, edge_indices, face_indices = mesh_join(data[0], data[1], data[2]) else: coords, edge_indices, face_indices = [d[0].tolist() if type(d[0]) == ndarray else d[0] for d in data[:3]] geom = lambda: None geom.verts = coords if self.display_verts and not any([display_edges, display_faces]): gl_instructions = self.format_draw_data(func=draw_verts, args=(geom, config)) callback_enable(n_id, gl_instructions) return if edges_socket.is_linked and not faces_socket.is_linked: if self.use_dashed: self.add_gl_stuff_to_config(config) geom.edges = edge_indices gl_instructions = self.format_draw_data(func=draw_edges, args=(geom, config)) callback_enable(n_id, gl_instructions) return if faces_socket.is_linked: # expecting mixed bag of tris/quads/ngons if self.display_faces: geom.faces = ensure_triangles(coords, face_indices, self.handle_concave_quads) if self.display_edges: if self.use_dashed: self.add_gl_stuff_to_config(config) # we don't want to draw the inner edges of triangulated faces; use original face_indices. # pass edges from socket if we can, else we manually compute them from faces geom.edges = edge_indices if edges_socket.is_linked else edges_from_faces(face_indices) if self.display_faces: self.faces_diplay(geom, config) gl_instructions = self.format_draw_data(func=draw_complex, args=(geom, config)) callback_enable(n_id, gl_instructions) return return elif matrix_socket.is_linked: matrices = matrix_socket.sv_get(deepcopy=False, default=[Matrix()]) gl_instructions = self.format_draw_data(func=draw_matrix, args=(matrices, )) callback_enable(n_id, gl_instructions)
def load(root_object, pia_files, armature, skeleton=None, bones=None): if not bones: bones = {} scs_globals = _get_scs_globals() print("\n************************************") print("** SCS PIA Importer **") print("** (c)2014 SCS Software **") print("************************************\n") import_scale = scs_globals.import_scale ind = ' ' for pia_filepath in pia_files: # Check if PIA file is for the actual skeleton... if skeleton: skeleton_match = _fast_check_for_pia_skeleton( pia_filepath, skeleton) else: skeleton_match, skeleton = _utter_check_for_pia_skeleton( pia_filepath, armature) # print('%r - %s' %(os.path.basename(pia_filepath), skeleton_match)) # print(' skeleton: %r' % skeleton) if skeleton_match: path = os.path.split(pia_filepath)[0] pis_filepath = os.path.join(path, skeleton) if os.path.isfile(pis_filepath): # print(' pis_filepath: %r' % pis_filepath) bones = _pis.load(pis_filepath, armature) else: lprint("""\nE The filepath "%s" doesn't exist!""", (pis_filepath.replace("\\", "/"), )) if skeleton_match: lprint('I ++ "%s" IMPORTING animation data...', (os.path.basename(pia_filepath), )) pia_container, state = _pix_parser.read_data(pia_filepath, ind) if not pia_container: lprint('\nE File "%s" is empty!', (pia_filepath.replace("\\", "/"), )) return {'CANCELLED'} if state == 'ERR': lprint('\nE File "%s" is not SCS Animation file!', (pia_filepath.replace("\\", "/"), )) return {'CANCELLED'} # TEST PRINTOUTS # ind = ' ' # for section in pia_container: # print('SEC.: "%s"' % section.type) # for prop in section.props: # print('%sProp: %s' % (ind, prop)) # for data in section.data: # print('%sdata: %s' % (ind, data)) # for sec in section.sections: # print_section(sec, ind) # print('\nTEST - Source: "%s"' % pia_container[0].props[1][1]) # print('') # TEST EXPORT # path, file = os.path.splitext(pia_filepath) # export_filepath = str(path + '_reex' + file) # result = pix_write.write_data(pia_container, export_filepath, ind) # if result == {'FINISHED'}: # Print(dump_level, '\nI Test export succesful! The new file:\n "%s"', export_filepath) # else: # Print(dump_level, '\nE Test export failed! File:\n "%s"', export_filepath) # LOAD HEADER format_version, source, f_type, animation_name, source_filename, author = _get_header( pia_container) if format_version != 3 or f_type != "Animation": return {'CANCELLED'} # LOAD GLOBALS skeleton, total_time, bone_channel_count, custom_channel_count = _get_globals( pia_container) # CREATE ANIMATION ACTIONS anim_action = bpy.data.actions.new(animation_name) anim_action.use_fake_user = True if total_time: anim_action.scs_props.action_length = total_time anim_data = armature.animation_data_create() anim_data.action = anim_action # LOAD BONE CHANNELS # print(' * armature: %r' % armature.name) if bone_channel_count > 0: bone_channels = _get_anim_channels(pia_container, section_name="BoneChannel") # ... for bone_name in bone_channels: # bone_name = channel[0] if bone_name in armature.data.bones: # print('%r is in armature %r' % (bone_name, armature.name)) ''' NOTE: skipped for now as no data needs to be readed stream_count = bone_channels[bone_name][0] keyframe_count = bone_channels[bone_name][1] ''' streams = bone_channels[bone_name][2] # print(' channel %r - streams %s - keyframes %s' % (bone_name, stream_count, keyframe_count)) # CREATE ANIMATION GROUP anim_group = anim_action.groups.new(bone_name) armature.pose.bones[ bone_name].rotation_mode = 'XYZ' # Set rotation mode. active_bone = armature.data.bones[bone_name] # parent_bone = active_bone.parent # CREATE FCURVES (pos_fcurves, rot_fcurves, sca_fcurves) = _create_fcurves( anim_action, anim_group, str('pose.bones["' + bone_name + '"]')) # GET BONE REST POSITION MATRIX bone_rest_matrix = active_bone.matrix_local bone_rest_matrix_scs = bones[bone_name][1].transposed() parent_bone_name = bones[bone_name][0] if parent_bone_name in bones: parent_bone_rest_matrix_scs = bones[ parent_bone_name][1].transposed() else: parent_bone_rest_matrix_scs = Matrix() parent_bone_rest_matrix_scs.identity() # if bone_name in ('LeftHand1', 'LeftHand'): # print('\n %r - bone_rest_matrix_scs:\n%s' % (bone_name, bone_rest_matrix_scs)) # print(' %r - bone_rest_matrix:\n%s' % (bone_name, bone_rest_matrix)) # print(' %r - parent_bone_rest_matrix_scs:\n%s' % (bone_name, parent_bone_rest_matrix_scs)) for key_time_i, key_time in enumerate(streams[0]): # print(' key_time: %s' % str(key_time[0])) # keyframe = key_time_i * (key_time[0] * 10) ## TODO: Do proper timing... keyframe = key_time_i + 1 # GET BONE ANIMATION MATRIX bone_animation_matrix_scs = streams[1][ key_time_i].transposed() # if bone_name in ('LeftHand1', 'LeftHand') and key_time_i == 0: print(' %r - bone_animation_matrix_scs (%i):\n%s' % ( # bone_name, key_time_i, bone_animation_matrix_scs)) # CREATE DELTA MATRIX delta_matrix = _get_delta_matrix( bone_rest_matrix, bone_rest_matrix_scs, parent_bone_rest_matrix_scs, bone_animation_matrix_scs, import_scale) # DECOMPOSE ANIMATION MATRIX location, rotation, scale = delta_matrix.decompose( ) # if bone_name in ('left_leg', 'root') and key_time_i == 0: print(' location:\n%s' % str(location)) rotation = rotation.to_euler('XYZ') # BUILD TRANSLATION CURVES pos_fcurves[0].keyframe_points.insert( frame=float(keyframe), value=location[0], options={'FAST'}) pos_fcurves[1].keyframe_points.insert( frame=float(keyframe), value=location[1], options={'FAST'}) pos_fcurves[2].keyframe_points.insert( frame=float(keyframe), value=location[2], options={'FAST'}) # BUILD ROTATION CURVES rot_fcurves[0].keyframe_points.insert( frame=float(keyframe), value=rotation[0], options={'FAST'}) rot_fcurves[1].keyframe_points.insert( frame=float(keyframe), value=rotation[1], options={'FAST'}) rot_fcurves[2].keyframe_points.insert( frame=float(keyframe), value=rotation[2], options={'FAST'}) # BUILD SCALE CURVES sca_fcurves[0].keyframe_points.insert( frame=float(keyframe), value=scale[0], options={'FAST'}) sca_fcurves[1].keyframe_points.insert( frame=float(keyframe), value=scale[1], options={'FAST'}) sca_fcurves[2].keyframe_points.insert( frame=float(keyframe), value=scale[2], options={'FAST'}) # SET LINEAR INTERPOLATION FOR ALL CURVES color_mode = 'AUTO_RAINBOW' # Or better 'AUTO_RGB'? for curve in pos_fcurves: curve.color_mode = color_mode for keyframe in curve.keyframe_points: keyframe.interpolation = 'LINEAR' for curve in rot_fcurves: curve.color_mode = color_mode for keyframe in curve.keyframe_points: keyframe.interpolation = 'LINEAR' for curve in sca_fcurves: curve.color_mode = color_mode for keyframe in curve.keyframe_points: keyframe.interpolation = 'LINEAR' # LOAD CUSTOM CHANNELS (ARMATURE OFFSET ANIMATION) # if custom_channel_count > 0: ## NOTE: Can't be used because exporter from Maya saves always 0 even if there are Custom Channels. custom_channels = _get_anim_channels(pia_container, section_name="CustomChannel") if len(custom_channels) > 0: for channel_name in custom_channels: # print(' >>> channel %r - %s' % (channel_name, str(custom_channels[channel_name]))) if channel_name == 'Prism Movement': ''' NOTE: skipped for now as no data needs to be readed stream_count = custom_channels[channel_name][0] keyframe_count = custom_channels[channel_name][1] ''' streams = custom_channels[channel_name][2] # print(' channel %r - streams %s - keyframes %s' % (channel_name, stream_count, keyframe_count)) # CREATE ANIMATION GROUP # anim_group = anim_action.groups.new(channel_name) anim_group = anim_action.groups.new('Location') # armature.[channel_name].rotation_mode = 'XYZ' ## Set rotation mode. # active_bone = armature.data.bones[channel_name] # parent_bone = active_bone.parent # CREATE FCURVES # pos_fcurves, rot_fcurves, sca_fcurves = _create_fcurves(anim_action, anim_group, anim_curve, rot_euler=True, # types='LocRotSca') # pos_fcurves, rot_fcurves, sca_fcurves = _create_fcurves(anim_action, anim_group, anim_curve, types='Loc') fcurve_pos_x = anim_action.fcurves.new('location', 0) fcurve_pos_y = anim_action.fcurves.new('location', 1) fcurve_pos_z = anim_action.fcurves.new('location', 2) fcurve_pos_x.group = anim_group fcurve_pos_y.group = anim_group fcurve_pos_z.group = anim_group pos_fcurves = (fcurve_pos_x, fcurve_pos_y, fcurve_pos_z) location = None for key_time_i, key_time in enumerate(streams[0]): # print(' key_time: %s' % str(key_time[0])) # keyframe = key_time_i * (key_time[0] * 10) ## TODO: Do proper timing... keyframe = key_time_i + 1 scs_offset = _convert_utils.change_to_scs_xyz_coordinates( custom_channels[channel_name][2][1] [key_time_i], import_scale) offset = Vector(scs_offset) if location is None: location = offset else: location = location + offset # print(' > location: %s' % str(location)) # BUILD TRANSLATION CURVES pos_fcurves[0].keyframe_points.insert( frame=float(keyframe), value=location[0], options={'FAST'}) pos_fcurves[1].keyframe_points.insert( frame=float(keyframe), value=location[1], options={'FAST'}) pos_fcurves[2].keyframe_points.insert( frame=float(keyframe), value=location[2], options={'FAST'}) # SET LINEAR INTERPOLATION FOR ALL CURVES for curve in pos_fcurves: for keyframe in curve.keyframe_points: keyframe.interpolation = 'LINEAR' else: lprint('W Unknown channel %r in "%s" file.', (channel_name, os.path.basename(pia_filepath))) # CREATE SCS ANIMATION animation = _animation_utils.add_animation_to_root( root_object, animation_name) animation.export = True animation.action = anim_action.name animation.anim_start = anim_action.frame_range[0] animation.anim_end = anim_action.frame_range[1] # animation.anim_export_step = # animation.anim_export_filepath = if total_time: animation.length = total_time # WARNING PRINTOUTS # if piece_count < 0: Print(dump_level, '\nW More Pieces found than were declared!') # if piece_count > 0: Print(dump_level, '\nW Some Pieces not found, but were declared!') # if dump_level > 1: print('') else: lprint('I "%s" file REJECTED', (os.path.basename(pia_filepath), )) print("************************************") return {'FINISHED'}
def apply_T(self, transform: Union[np.ndarray, Matrix]): """ Apply the given transformation to the pose of the entity. :param transform: A 4x4 matrix representing the transformation. """ self.blender_obj.matrix_world @= Matrix(transform)
def bvh_node_dict2armature(context, bvh_name, bvh_nodes, rotate_mode='XYZ', frame_start=1, IMPORT_LOOP=False): if frame_start < 1: frame_start = 1 # Add the new armature, scene = context.scene for obj in scene.objects: obj.select = False arm_data = bpy.data.armatures.new(bvh_name) arm_ob = bpy.data.objects.new(bvh_name, arm_data) scene.objects.link(arm_ob) arm_ob.select = True scene.objects.active = arm_ob bpy.ops.object.mode_set(mode='OBJECT', toggle=False) bpy.ops.object.mode_set(mode='EDIT', toggle=False) # Get the average bone length for zero length bones, we may not use this. average_bone_length = 0.0 nonzero_count = 0 for bvh_node in bvh_nodes.values(): l = (bvh_node.rest_head_local - bvh_node.rest_tail_local).length if l: average_bone_length += l nonzero_count += 1 # Very rare cases all bones couldbe zero length??? if not average_bone_length: average_bone_length = 0.1 else: # Normal operation average_bone_length = average_bone_length / nonzero_count # XXX, annoying, remove bone. while arm_data.edit_bones: arm_ob.edit_bones.remove(arm_data.edit_bones[-1]) ZERO_AREA_BONES = [] for name, bvh_node in bvh_nodes.items(): # New editbone bone = bvh_node.temp = arm_data.edit_bones.new(name) bone.head = bvh_node.rest_head_world bone.tail = bvh_node.rest_tail_world # ZERO AREA BONES. if (bone.head - bone.tail).length < 0.001: if bvh_node.parent: ofs = bvh_node.parent.rest_head_local - bvh_node.parent.rest_tail_local if ofs.length: # is our parent zero length also?? unlikely bone.tail = bone.tail + ofs else: bone.tail.y = bone.tail.y + average_bone_length else: bone.tail.y = bone.tail.y + average_bone_length ZERO_AREA_BONES.append(bone.name) for bvh_node in bvh_nodes.values(): if bvh_node.parent: # bvh_node.temp is the Editbone # Set the bone parent bvh_node.temp.parent = bvh_node.parent.temp # Set the connection state if not bvh_node.has_loc and\ bvh_node.parent and\ bvh_node.parent.temp.name not in ZERO_AREA_BONES and\ bvh_node.parent.rest_tail_local == bvh_node.rest_head_local: bvh_node.temp.use_connect = True # Replace the editbone with the editbone name, # to avoid memory errors accessing the editbone outside editmode for bvh_node in bvh_nodes.values(): bvh_node.temp = bvh_node.temp.name # Now Apply the animation to the armature # Get armature animation data bpy.ops.object.mode_set(mode='OBJECT', toggle=False) pose = arm_ob.pose pose_bones = pose.bones if rotate_mode == 'NATIVE': for bvh_node in bvh_nodes.values(): bone_name = bvh_node.temp # may not be the same name as the bvh_node, could have been shortened. pose_bone = pose_bones[bone_name] pose_bone.rotation_mode = bvh_node.rot_order_str elif rotate_mode != 'QUATERNION': for pose_bone in pose_bones: pose_bone.rotation_mode = rotate_mode else: # Quats default pass context.scene.update() arm_ob.animation_data_create() action = bpy.data.actions.new(name=bvh_name) arm_ob.animation_data.action = action # Replace the bvh_node.temp (currently an editbone) # With a tuple (pose_bone, armature_bone, bone_rest_matrix, bone_rest_matrix_inv) for bvh_node in bvh_nodes.values(): bone_name = bvh_node.temp # may not be the same name as the bvh_node, could have been shortened. pose_bone = pose_bones[bone_name] rest_bone = arm_data.bones[bone_name] bone_rest_matrix = rest_bone.matrix_local.to_3x3() bone_rest_matrix_inv = Matrix(bone_rest_matrix) bone_rest_matrix_inv.invert() bone_rest_matrix_inv.resize_4x4() bone_rest_matrix.resize_4x4() bvh_node.temp = (pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv) # Make a dict for fast access without rebuilding a list all the time. # KEYFRAME METHOD, SLOW, USE IPOS DIRECT # TODO: use f-point samples instead (Aligorith) if rotate_mode != 'QUATERNION': prev_euler = [Euler() for i in range(len(bvh_nodes))] # Animate the data, the last used bvh_node will do since they all have the same number of frames for frame_current in range(len(bvh_node.anim_data) - 1): # skip the first frame (rest frame) # print frame_current # if frame_current==40: # debugging # break scene.frame_set(frame_start + frame_current) # Dont neet to set the current frame for i, bvh_node in enumerate(bvh_nodes.values()): pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv = bvh_node.temp lx, ly, lz, rx, ry, rz = bvh_node.anim_data[frame_current + 1] if bvh_node.has_rot: # apply rotation order and convert to XYZ # note that the rot_order_str is reversed. bone_rotation_matrix = Euler( (rx, ry, rz), bvh_node.rot_order_str[::-1]).to_matrix().to_4x4() bone_rotation_matrix = bone_rest_matrix_inv * bone_rotation_matrix * bone_rest_matrix if rotate_mode == 'QUATERNION': pose_bone.rotation_quaternion = bone_rotation_matrix.to_quaternion( ) else: euler = bone_rotation_matrix.to_euler( bvh_node.rot_order_str, prev_euler[i]) pose_bone.rotation_euler = euler prev_euler[i] = euler if bvh_node.has_loc: pose_bone.location = ( bone_rest_matrix_inv * Matrix.Translation( Vector((lx, ly, lz)) - bvh_node.rest_head_local)).to_translation() if bvh_node.has_loc: pose_bone.keyframe_insert("location") if bvh_node.has_rot: if rotate_mode == 'QUATERNION': pose_bone.keyframe_insert("rotation_quaternion") else: pose_bone.keyframe_insert("rotation_euler") for cu in action.fcurves: if IMPORT_LOOP: pass # 2.5 doenst have cyclic now? for bez in cu.keyframe_points: bez.interpolation = 'LINEAR' return arm_ob
def process(self): if not any(socket.is_linked for socket in self.outputs): return fields_s = self.inputs['Field'].sv_get() min_x_s = self.inputs['MinX'].sv_get() max_x_s = self.inputs['MaxX'].sv_get() min_y_s = self.inputs['MinY'].sv_get() max_y_s = self.inputs['MaxY'].sv_get() value_s = self.inputs['Value'].sv_get() z_value_s = self.inputs['Z'].sv_get() samples_s = self.inputs['Samples'].sv_get() matrix_s = self.inputs['Matrix'].sv_get(default=[Matrix()]) value_s = ensure_nesting_level(value_s, 2) z_value_s = ensure_nesting_level(z_value_s, 2) fields_s = ensure_nesting_level(fields_s, 2, data_types=(SvScalarField, )) matrix_s = ensure_nesting_level(matrix_s, 2, data_types=(Matrix, )) parameters = zip_long_repeat(fields_s, matrix_s, min_x_s, max_x_s, min_y_s, max_y_s, z_value_s, value_s, samples_s) verts_out = [] edges_out = [] faces_out = [] for field_i, matrix_i, min_x_i, max_x_i, min_y_i, max_y_i, z_value_i, value_i, samples_i in parameters: objects = zip_long_repeat(field_i, matrix_i, min_x_i, max_x_i, min_y_i, max_y_i, z_value_i, value_i, samples_i) for field, matrix, min_x, max_x, min_y, max_y, z_value, value, samples in objects: has_matrix = matrix != Matrix() x_range = np.linspace(min_x, max_x, num=samples) y_range = np.linspace(min_y, max_y, num=samples) z_range = np.array([z_value]) xs, ys, zs = np.meshgrid(x_range, y_range, z_range, indexing='ij') xs, ys, zs = xs.flatten(), ys.flatten(), zs.flatten() if has_matrix: xs, ys, zs = self.apply_matrix(matrix, xs, ys, zs) field_values = field.evaluate_grid(xs, ys, zs) field_values = field_values.reshape((samples, samples)) contours = measure.find_contours(field_values, level=value) x_size = (max_x - min_x) / samples y_size = (max_y - min_y) / samples new_verts, new_edges, new_faces = make_contours( samples, samples, min_x, x_size, min_y, y_size, z_value, contours, make_faces=self.make_faces, connect_bounds=self.connect_bounds) if has_matrix: new_verts = self.unapply_matrix(matrix, new_verts) verts_out.extend(new_verts) edges_out.extend(new_edges) faces_out.extend(new_faces) self.outputs['Vertices'].sv_set(verts_out) self.outputs['Edges'].sv_set(edges_out) self.outputs['Faces'].sv_set(faces_out)
def to_interop_matrix4x4(mat): """Convert the input matrix to an InteropMatrix4x4 Args: mat (float[]): float multi-dimensional array of 4 * 4 items in [-inf, inf]. E.g. ((1.0, 0.0, 0.0, 0.0), (0.0, 1.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, 0.0, 0.0, 1.0)) Returns: InteropMatrix4x4 """ raise NotImplementedError( 'Matrices not supported anymore due to laziness. Upgrade.') # Swap euler y/z angles eul = mat.to_euler() eul.yz = eul.zy rot = eul.to_matrix().to_4x4() # Swap translation y/z t = mat.to_translation() loc = Matrix.Translation((t.x, t.z, t.y)) sca = mat.to_scale() scal.yz = sca.zy sca = sca.to_matrix().to_4x4() sca = Matrix.Scale(0.5, 4, (0.0, 0.0, 1.0)) m = loc @ rot @ sca RHS_Z_TO_LHS_Y = Matrix(((1.0, 0.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, 1.0, 0.0, 0.0), (0.0, 0.0, 0.0, 1.0))) # Math is still all wrong, also, not even going to bother at this point. # I'd rather transfer with 3 vec3s and reconstruct on unity's side. # It makes space transforms / swaps a lot easier. # Convert Blender's RHS Z-up matrix to Unity's LHS Y-up #m = mat * Matrix.Rotation(math.radians(90.0), 4, 'X') # RHS_Z_TO_LHS_Y @ mat m = mat result = InteropMatrix4x4() result.m00 = m[0][0] result.m01 = m[0][1] result.m02 = m[0][2] result.m03 = m[0][3] result.m10 = m[1][0] result.m11 = m[1][1] result.m12 = m[1][2] result.m13 = m[1][3] result.m20 = m[2][0] result.m21 = m[2][1] result.m22 = m[2][2] result.m23 = m[2][3] result.m30 = m[3][0] result.m31 = m[3][1] result.m32 = m[3][2] result.m33 = m[3][3] # Space conversion here! # position is easy - rotation is not. return result
def import_modes(context, report, filepath, file_format, molecule): logger.info("Reading modes file {}".format(filepath)) try: qpts = mb_io_files.MB_Modes.from_file(filepath, file_format) if not qpts or not qpts[0].modes: msg = "No modes found in {}\n".format(bpy.path.basename(filepath)) msg += "Did you chose the correct file format?" report({'ERROR'}, msg) return False nat = len(molecule.objects.atoms) for qmode in qpts: if np.linalg.norm(qmode.qvec) and not molecule["unit_cells"]: msg = "Can't convert qvecs to crystal coordinates because no" msg += " unit cell information is present" logger.error(msg) report({'ERROR'}, msg) for mode in qmode.modes: if nat % len(mode.evecs) != 0: msg = "number of displacement vectors " msg += "{}".format(len(mode.evecs)) msg += " is different than number of atoms {}".format(nat) msg += " in active molecule." logger.error(msg) report({'ERROR'}, msg) return False # This is only used for Quantum ESPRESSO, to calculate the crystal unit # cell. The cartesian unit cell is not written in the mode output, so # the conversion can't be done when reading the data. uc = Matrix(molecule["unit_cells"][0]) * 1.889725989 k_uc = Matrix( [uc[(dim + 1) % 3].cross(uc[(dim + 2) % 3]) for dim in range(3)]) fac = 2 * math.pi / uc[0].dot(uc[1].cross(uc[2])) k_uc = k_uc * fac inv_k_uc = k_uc.inverted() if qpts[0].qvecs_format == "QE": for nq, qmode in enumerate(qpts): qmode.qvec = (Vector(qmode.qvec) * 2 * math.pi / uc[0][0]) * inv_k_uc except: msg = "{} could not be imported. Check console.".format(filepath) report({'ERROR'}, msg) logger.exception("") return False logger.debug("Found {} q-points".format(len(qpts))) old_sel = context.selected_objects last_active = context.object try: # clear old modes first while len(molecule.qvecs): last = len(molecule.qvecs) - 1 qv = molecule.qvecs[last] if qv.mode_txt: bpy.data.texts.remove(qv.mode_txt, do_unlink=True) molecule.qvecs.remove(last) # Saving as file and loading is faster than writing to BlendDataText txt_list = [] txtname_fmt = ".modes_{}_qpt-{}.json" print("Start loading") for iq, qmode in enumerate(qpts): print(iq) logger.debug("Loading qpt {} as BlendDataText".format(qmode.iqpt)) qv = molecule.qvecs.add() qv.qvec = qmode.qvec qv.iqpt = qmode.iqpt with tempfile.NamedTemporaryFile(mode='w+') as fout: for line in qmode.lines_iter(): fout.write(line) fout.flush() try: txt = bpy.data.texts.load(filepath=fout.name, internal=True) txt_list.append(txt) except: logger.error("Problem with qpt {}".format(qmode.iqpt)) raise txt.name = txtname_fmt.format(molecule.name, qmode.iqpt) qv.mode_txt = txt txt.mb.parent = molecule.objects.parent txt.mb.type = "MODES" logger.debug("Done loading modes") for atom in molecule.objects.atoms: mb_utils.create_mode_action(context, atom, molecule) mb_utils.create_mode_arrow(context, atom, molecule, type='3D') molecule.active_mode = 0 if len(qpts) > 1 and file_format == "PHONOPY": report({'WARNING'}, "Please check if q!=0 modes have been imported" " properly. If not, please notify Flo to fix it.") return True except: for txt in txt_list: bpy.data.texts.remove(txt) while len(molecule.qvecs): last = len(molecule.qvecs) - 1 qv = molecule.qvecs[last] if qv.mode_txt: bpy.data.texts.remove(qv.mode_txt, do_unlink=True) molecule.qvecs.remove(last) msg = "Modes were read but couldn't be imported. Check console." report({'ERROR'}, msg) logger.exception("") return False finally: bpy.ops.object.select_all(action="DESELECT") for ob in old_sel: ob.select = True context.scene.objects.active = last_active
def blen_read_object(fbx_tmpl, fbx_obj, object_data): elem_name, elem_class = elem_split_name_class(fbx_obj) elem_name_utf8 = elem_name.decode('utf-8') const_vector_zero_3d = 0.0, 0.0, 0.0 const_vector_one_3d = 1.0, 1.0, 1.0 # Object data must be created already obj = bpy.data.objects.new(name=elem_name_utf8, object_data=object_data) fbx_props = (elem_find_first(fbx_obj, b'Properties70'), elem_find_first(fbx_tmpl, b'Properties70', fbx_elem_nil)) assert(fbx_props[0] is not None) # ---- # Misc Attributes obj.color[0:3] = elem_props_get_color_rgb(fbx_props, b'Color', (0.8, 0.8, 0.8)) # ---- # Transformation # This is quite involved, 'fbxRNode.cpp' from openscenegraph used as a reference loc = elem_props_get_vector_3d(fbx_props, b'Lcl Translation', const_vector_zero_3d) rot = elem_props_get_vector_3d(fbx_props, b'Lcl Rotation', const_vector_zero_3d) sca = elem_props_get_vector_3d(fbx_props, b'Lcl Scaling', const_vector_one_3d) rot_ofs = elem_props_get_vector_3d(fbx_props, b'RotationOffset', const_vector_zero_3d) rot_piv = elem_props_get_vector_3d(fbx_props, b'RotationPivot', const_vector_zero_3d) sca_ofs = elem_props_get_vector_3d(fbx_props, b'ScalingOffset', const_vector_zero_3d) sca_piv = elem_props_get_vector_3d(fbx_props, b'ScalingPivot', const_vector_zero_3d) is_rot_act = elem_props_get_bool(fbx_props, b'RotationActive', False) if is_rot_act: pre_rot = elem_props_get_vector_3d(fbx_props, b'PreRotation', const_vector_zero_3d) pst_rot = elem_props_get_vector_3d(fbx_props, b'PostRotation', const_vector_zero_3d) rot_ord = { 0: 'XYZ', 1: 'XYZ', 2: 'XZY', 3: 'YZX', 4: 'YXZ', 5: 'ZXY', 6: 'ZYX', }.get(elem_props_get_enum(fbx_props, b'RotationOrder', 0)) else: pre_rot = const_vector_zero_3d pst_rot = const_vector_zero_3d rot_ord = 'XYZ' from mathutils import Matrix, Euler from math import pi # translation lcl_translation = Matrix.Translation(loc) # rotation if obj.type == 'CAMERA': rot_alt_mat = Matrix.Rotation(pi / -2.0, 4, 'Y') elif obj.type == 'LAMP': rot_alt_mat = Matrix.Rotation(pi / -2.0, 4, 'X') else: rot_alt_mat = Matrix() # rotation lcl_rot = Euler(tuple_deg_to_rad(rot), rot_ord).to_matrix().to_4x4() * rot_alt_mat pre_rot = Euler(tuple_deg_to_rad(pre_rot), rot_ord).to_matrix().to_4x4() pst_rot = Euler(tuple_deg_to_rad(pst_rot), rot_ord).to_matrix().to_4x4() rot_ofs = Matrix.Translation(rot_ofs) rot_piv = Matrix.Translation(rot_piv) sca_ofs = Matrix.Translation(sca_ofs) sca_piv = Matrix.Translation(sca_piv) # scale lcl_scale = Matrix() lcl_scale[0][0], lcl_scale[1][1], lcl_scale[2][2] = sca obj.matrix_basis = ( lcl_translation * rot_ofs * rot_piv * pre_rot * lcl_rot * pst_rot * rot_piv.inverted() * sca_ofs * sca_piv * lcl_scale * sca_piv.inverted() ) return obj
FBX_DEFORMER_CLUSTER_VERSION = 100 FBX_MATERIAL_VERSION = 102 FBX_TEXTURE_VERSION = 202 FBX_ANIM_KEY_VERSION = 4008 FBX_NAME_CLASS_SEP = b"\x00\x01" FBX_ANIM_PROPSGROUP_NAME = "d" FBX_KTIME = 46186158000 # This is the number of "ktimes" in one second (yep, precision over the nanosecond...) MAT_CONVERT_LAMP = Matrix.Rotation(math.pi / 2.0, 4, 'X') # Blender is -Z, FBX is -Y. MAT_CONVERT_CAMERA = Matrix.Rotation(math.pi / 2.0, 4, 'Y') # Blender is -Z, FBX is +X. # XXX I can't get this working :( # MAT_CONVERT_BONE = Matrix.Rotation(math.pi / 2.0, 4, 'Z') # Blender is +Y, FBX is -X. MAT_CONVERT_BONE = Matrix() BLENDER_OTHER_OBJECT_TYPES = {'CURVE', 'SURFACE', 'FONT', 'META'} BLENDER_OBJECT_TYPES_MESHLIKE = {'MESH'} | BLENDER_OTHER_OBJECT_TYPES # Lamps. FBX_LIGHT_TYPES = { 'POINT': 0, # Point. 'SUN': 1, # Directional. 'SPOT': 2, # Spot. 'HEMI': 1, # Directional. 'AREA': 3, # Area. } FBX_LIGHT_DECAY_TYPES = {
animations animation tracks track keyframes keyframe translate rotate axis """ ZERO = Vector() QUAT_ID = Quaternion((1.0, 0.0, 0.0, 0.0)) MAT4_ROT = Matrix(( (0.0, 1.0, 0.0, 0.0), (-1.0, 0.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, 0.0, 0.0, 1.0), )) MAT4_ROT_INV = Matrix(( (0.0, -1.0, 0.0, 0.0), (1.0, 0.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, 0.0, 0.0, 1.0), )) MAT3_ROT_INV = Matrix(((0, -1, 0), (1, 0, 0), (0, 0, 1))) MAT_ROT_Y90_INV = Matrix(( (0.0, 0.0, -1.0, 0.0), (0.0, 1.0, 0.0, 0.0), (1.0, 0.0, 0.0, 0.0), (0.0, 0.0, 0.0, 1.0), ))
def get_matrix_local(self): if self._tag == 'OB': return self.bdata.matrix_local.copy() elif self._tag == 'DP': return self._ref.matrix_world.inverted_safe() * self._dupli_matrix else: # 'BO', current pose # PoseBone.matrix is in armature space, bring in back in real local one! par = self.bdata.parent par_mat_inv = self._ref.pose.bones[par.name].matrix.inverted_safe() if par else Matrix() return par_mat_inv * self._ref.pose.bones[self.bdata.name].matrix
def process(self): # inputs if not self.inputs['Vertices'].is_linked: return vertices_s = self.inputs['Vertices'].sv_get(deepcopy=False) edges_s = self.inputs['Edges'].sv_get(default=[[]], deepcopy=False) faces_s = self.inputs['Polygons'].sv_get(default=[[]], deepcopy=False) masks_s = self.inputs['Mask'].sv_get(default=[[1]], deepcopy=False) if self.transform_mode == "Matrix": matrices_s = [ self.inputs['Matrices'].sv_get(default=[Matrix()], deepcopy=False) ] heights_s = [0.0] scales_s = [1.0] else: matrices_s = [[]] heights_s = self.inputs['Height'].sv_get(deepcopy=False) scales_s = self.inputs['Scale'].sv_get(deepcopy=False) if 'FaceData' in self.inputs: face_data_s = self.inputs['FaceData'].sv_get(default=[[]], deepcopy=False) else: face_data_s = [[]] need_mask_out = 'Mask' in self.outputs and self.outputs[ 'Mask'].is_linked result_vertices = [] result_edges = [] result_faces = [] result_ext_vertices = [] result_ext_edges = [] result_ext_faces = [] result_face_data = [] result_mask = [] meshes = match_long_repeat([ vertices_s, edges_s, faces_s, masks_s, matrices_s, heights_s, scales_s, face_data_s ]) for vertices, edges, faces, masks, matrix_per_iteration, height_per_iteration, scale_per_iteration, face_data in zip( *meshes): if self.transform_mode == "Matrix": if not matrix_per_iteration: matrix_per_iteration = [Matrix()] if self.multiple: if self.transform_mode == "Matrix": n_iterations = len(matrix_per_iteration) else: n_iterations = max(len(height_per_iteration), len(scale_per_iteration)) height_per_iteration_matched = repeat_last_for_length( height_per_iteration, n_iterations) scale_per_iteration_matched = repeat_last_for_length( scale_per_iteration, n_iterations) else: n_iterations = 1 matrix_per_iteration = [matrix_per_iteration] mask_matched = repeat_last_for_length(masks, len(faces)) if face_data: face_data_matched = repeat_last_for_length( face_data, len(faces)) bm = bmesh_from_pydata(vertices, edges, faces, normal_update=True, markup_face_data=True) mask_layer = bm.faces.layers.int.new('mask') bm.faces.ensure_lookup_table() #fill_faces_layer(bm, masks, 'mask', int, MASK, invert_mask=True) b_faces = [] b_edges = set() b_verts = set() for mask, face in zip(mask_matched, bm.faces): if mask: b_faces.append(face) for edge in face.edges: b_edges.add(edge) for vert in face.verts: b_verts.add(vert) extrude_geom = b_faces + list(b_edges) + list(b_verts) extruded_verts_last = [] extruded_bm_verts_all = set() extruded_edges_last = [] extruded_faces_last = [] extruded_bm_faces_last = [] matrix_spaces = [Matrix()] for idx in range(n_iterations): for item in extrude_geom: if isinstance(item, bmesh.types.BMFace): item[mask_layer] = OUT if is_290: kwargs = { 'use_dissolve_ortho_edges': self.dissolve_ortho_edges } else: kwargs = {} new_geom = bmesh.ops.extrude_face_region( bm, geom=extrude_geom, edges_exclude=set(), use_keep_orig=self.keep_original, **kwargs)['geom'] extruded_verts = [ v for v in new_geom if isinstance(v, bmesh.types.BMVert) ] extruded_faces = [ f for f in new_geom if isinstance(f, bmesh.types.BMFace) ] if self.transform_mode == "Matrix": matrices = matrix_per_iteration[idx] if isinstance(matrices, Matrix): matrices = [matrices] matrix_spaces_matched = repeat_last_for_length( matrix_spaces, len(extruded_verts)) for vertex_idx, (vertex, matrix) in enumerate( zip(*match_long_repeat([extruded_verts, matrices ]))): bmesh.ops.transform( bm, verts=[vertex], matrix=matrix, space=matrix_spaces_matched[vertex_idx]) matrix_spaces_matched[vertex_idx] = matrix.inverted( ) @ matrix_spaces_matched[vertex_idx] else: height = height_per_iteration_matched[idx] scale = scale_per_iteration_matched[idx] normal = get_avg_normal(extruded_faces) dr = normal * height center = get_faces_center(extruded_faces) translation = Matrix.Translation(center) rotation = normal.rotation_difference( (0, 0, 1)).to_matrix().to_4x4() m = translation @ rotation bmesh.ops.scale(bm, vec=(scale, scale, scale), space=m.inverted(), verts=extruded_verts) bmesh.ops.translate(bm, verts=extruded_verts, vec=dr) extruded_bm_verts_all.update(extruded_verts) extruded_verts_last = [tuple(v.co) for v in extruded_verts] extruded_edges = [ e for e in new_geom if isinstance(e, bmesh.types.BMEdge) ] extruded_edges_last = [ tuple(v.index for v in edge.verts) for edge in extruded_edges ] extruded_bm_faces_last = extruded_faces extruded_faces_last = [[v.index for v in face.verts] for face in extruded_faces] extrude_geom = new_geom if face_data: new_vertices, new_edges, new_faces, new_face_data = pydata_from_bmesh( bm, face_data_matched) else: new_vertices, new_edges, new_faces = pydata_from_bmesh(bm) new_face_data = [] if need_mask_out: new_mask = self.get_out_mask(bm, extruded_bm_faces_last, extruded_bm_verts_all) result_mask.append(new_mask) bm.free() result_vertices.append(new_vertices) result_edges.append(new_edges) result_faces.append(new_faces) result_ext_vertices.append(extruded_verts_last) result_ext_edges.append(extruded_edges_last) result_ext_faces.append(extruded_faces_last) result_face_data.append(new_face_data) self.outputs['Vertices'].sv_set(result_vertices) self.outputs['Edges'].sv_set(result_edges) self.outputs['Polygons'].sv_set(result_faces) self.outputs['NewVertices'].sv_set(result_ext_vertices) self.outputs['NewEdges'].sv_set(result_ext_edges) self.outputs['NewFaces'].sv_set(result_ext_faces) if 'Mask' in self.outputs: self.outputs['Mask'].sv_set(result_mask) if 'FaceData' in self.outputs: self.outputs['FaceData'].sv_set(result_face_data)
def updateMatrixTable(evp, drw, jnt, currPacket, multiMatrixTable, matrixTable, isMatrixWeighted, use_scale): global dataholder for n in range(len(currPacket.matrixTable)): index = currPacket.matrixTable[n] # if index is 0xffff, use the last packet's data. if index != 0xffff: # 0xffff this means keep old entry if drw.isWeighted[index]: # corrected # --TODO: the EVP1 data should probably be used here, # --figure out how this works (most files look ok # --without this, but models/ji.bdl is for example # --broken this way) # --matrixTable[n] = def_; # --the following _does_ the right thing...it looks # --ok for all files, but i don't understand why :-P # --(and this code is slow as hell, so TODO: fix this) # --NO idea if this is right this way... m = Matrix() m.zero() # zero-ifiy m mm = evp.weightedIndices[ drw.data[index]] # -- get MultiMatrix # corrected singleMultiMatrixEntry = MultiMatrix() singleMultiMatrixEntry.weights = mm.weights.copy() singleMultiMatrixEntry.indices = mm.indices.copy() for r in range(len(mm.weights)): # did before. #singleMultiMatrixEntry.weights[r] = mm.weights[r] #singleMultiMatrixEntry.indices[r] = mm.indices[r] # corrected (r]+1) # -- (drw.data[mm.indices[r]+ 1] + 1) -- bone index # -- messageBox (mm.indices as string) # --if (mm.indices[r] != 0) then # -- ( sm1 = evp.matrices[mm.indices[r]] # -- const Matrix44f sm2 = LocalMatrix(jnt, mm.indices[r], use_scale) sm3 = sm2 * sm1 # ) # else # -- sm3 = (LocalMatrix mm.indices[r] ) Mad(m, sm3, mm.weights[r]) while len(multiMatrixTable) <= n: multiMatrixTable.append(None) multiMatrixTable[n] = singleMultiMatrixEntry m[3][3] = 1 # fixed while len(matrixTable) <= n: matrixTable.append(None) matrixTable[n] = m while len(isMatrixWeighted) <= n: isMatrixWeighted.append(None) isMatrixWeighted[n] = True else: while len(matrixTable) <= n: matrixTable.append(None) while len(isMatrixWeighted) <= n: isMatrixWeighted.append(None) matrixTable[n] = jnt.frames[ drw.data[index]].matrix # corrected x2 isMatrixWeighted[n] = False singleMultiMatrixEntry = MultiMatrix() singleMultiMatrixEntry.weights = [1] singleMultiMatrixEntry.indices = [ drw.data[index] ] # corrected x2 # -- bone index while len(multiMatrixTable) <= n: multiMatrixTable.append(None) multiMatrixTable[n] = singleMultiMatrixEntry
def bCreateSkeleton(meshData, name): if 'skeleton' not in meshData: return bonesData = meshData['skeleton'] # create Armature amt = bpy.data.armatures.new(name) rig = bpy.data.objects.new(name, amt) #rig.location = origin rig.show_x_ray = True #amt.show_names = True # Link object to scene scn = bpy.context.scene scn.objects.link(rig) scn.objects.active = rig scn.update() bpy.ops.object.mode_set(mode='EDIT') for bone in bonesData.keys(): boneData = bonesData[bone] boneName = boneData['name'] children = boneData['children'] boneObj = amt.edit_bones.new(boneName) #boneObj.head = boneData['posHAS'] #headPos = boneData['posHAS'] headPos = boneData['posHAS'] tailVector = 0.2 if len(children) == 1: tailVector = calcBoneLength(bonesData[children[0]]['position']) #boneObj.head = Vector([headPos[0],-headPos[2],headPos[1]]) #boneObj.tail = Vector([headPos[0],-headPos[2],headPos[1] + tailVector]) #print("bCreateSkeleton: bone=%s, boneObj.head=%s" % (bone, boneObj.head)) #print("bCreateSkeleton: bone=%s, boneObj.tail=%s" % (bone, boneObj.tail)) #boneObj.matrix = rotmat = boneData['rotmatAS'] #print(rotmat[1].to_tuple()) #boneObj.matrix = Matrix(rotmat[1],rotmat[0],rotmat[2]) if blender_version <= 262: r0 = [rotmat[0].x] + [rotmat[0].y] + [rotmat[0].z] r1 = [rotmat[1].x] + [rotmat[1].y] + [rotmat[1].z] r2 = [rotmat[2].x] + [rotmat[2].y] + [rotmat[2].z] boneRotMatrix = Matrix((r1, r0, r2)) elif blender_version > 262: # this is fugly was of flipping matrix r0 = [rotmat.col[0].x] + [rotmat.col[0].y] + [rotmat.col[0].z] r1 = [rotmat.col[1].x] + [rotmat.col[1].y] + [rotmat.col[1].z] r2 = [rotmat.col[2].x] + [rotmat.col[2].y] + [rotmat.col[2].z] tmpR = Matrix((r1, r0, r2)) boneRotMatrix = Matrix((tmpR.col[0], tmpR.col[1], tmpR.col[2])) #pos = Vector([headPos[0],-headPos[2],headPos[1]]) #axis, roll = mat3_to_vec_roll(boneRotMatrix.to_3x3()) #boneObj.head = pos #boneObj.tail = pos + axis #boneObj.roll = roll #print("bCreateSkeleton: bone=%s, newrotmat=%s" % (bone, Matrix((r1,r0,r2)))) #print(r1) #mtx = Matrix.to_3x3()Translation(boneObj.head) # Matrix((r1,r0,r2)) #boneObj.transform(Matrix((r1,r0,r2))) #print("bCreateSkeleton: bone=%s, matrix_before=%s" % (bone, boneObj.matrix)) #boneObj.use_local_location = False #boneObj.transform(Matrix((r1,r0,r2)) , False, False) #print("bCreateSkeleton: bone=%s, matrix_after=%s" % (bone, boneObj.matrix)) boneObj.head = Vector([0, 0, 0]) #boneObj.tail = Vector([0,0,tailVector]) boneObj.tail = Vector([0, tailVector, 0]) #matx = Matrix.Translation(Vector([headPos[0],-headPos[2],headPos[1]])) boneObj.transform(boneRotMatrix) #scn.update() boneObj.translate(Vector([headPos[0], -headPos[2], headPos[1]])) #scn.update() #boneObj.translate(Vector([headPos[0],-headPos[2],headPos[1]])) #boneObj.head = Vector([headPos[0],-headPos[2],headPos[1]]) #boneObj.tail = Vector([headPos[0],-headPos[2],headPos[1]]) + (Vector([0,0, tailVector]) * Matrix((r1,r0,r2))) #amt.bones[bone] = boneObj #amt.update_tag(refresh) # only after all bones are created we can link parents for bone in bonesData.keys(): boneData = bonesData[bone] parent = None if 'parent' in boneData.keys(): parent = boneData['parent'] # get bone obj boneData = bonesData[bone] boneName = boneData['name'] boneObj = amt.edit_bones[boneName] boneObj.parent = amt.edit_bones[parent] # need to refresh armature before removing bones bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.mode_set(mode='EDIT') # delete helper/zero bones for bone in amt.bones.keys(): #print("keys of bone=%s" % bonesData[bone].keys()) if 'flag' in bonesData[bone].keys(): #print ("deleting bone=%s" % bone) bpy.context.object.data.edit_bones.remove(amt.edit_bones[bone]) bpy.ops.object.mode_set(mode='OBJECT')
def create_animations(self): z = self.z_mesh s = z.skeleton s.armature.show_axes = True # Set ourselves into the pose mode of the armature with nothing selected. bpy.ops.object.select_all(action='DESELECT') bpy.ops.object.select_pattern(pattern=s.name) bpy.ops.object.mode_set(mode='POSE') bpy.ops.pose.select_all(action='DESELECT') frame_offset = 0 # Go through each Animation. for animation in z.animations: if animation.name != "Run": continue s.object.animation_data_create(); s.object.animation_data.action = bpy.data.actions.new(animation.name) s.object.animation_data.action.use_fake_user = 1 if self.DEBUG == True: print("Rendering Animation: " + animation.name + "...") frame_offset = 0 p_bones = [ ] s.bone_pose = dict() s.world_pose = dict() s.skin_pose = dict() last_matrix = dict() should_mat = dict() for bone_index in range(0, s.bone_count): last_matrix[bone_index] = Matrix() should_mat[bone_index] = False for frame in animation.frames: bpy.data.scenes[0].frame_current = frame_offset s.armature #if self.DEBUG == True: #print('Rendering Frame: ' + str(frame_offset)) # 1) Turn the translation and rotation into a Frame Matrix # 2) Create a World Matrix by multiplying the Parent World Matrix with the Frame Matrix # 3) Create the Product Matrix by multiplying the World Matrix with the Bone Matrix for bone_index in range(0, s.bone_count): bone_name = s.bone_name[bone_index] try: l = frame.bone_locs[bone_name].copy() r = frame.bone_rots[bone_name].copy() s.bone_pose[bone_index] = s.bone_pose[bone_name] = create_from_quaternion_position(r,l) except: ok = None s.world_pose[0] = mul(s.bone_pose[0], Matrix4f(), None) for bone_index in range(1, s.bone_count): parent_index = s.bone_parent[bone_index] s.world_pose[bone_index] = mul(s.bone_pose[bone_index].copy(), s.world_pose[parent_index].copy(), None) for bone_index in range(0, s.bone_count): bone_name = s.bone_name[bone_index] parent_index = s.bone_parent[bone_index] s.skin_pose[bone_index] = mul(s.offset_matrix[bone_index].copy(), s.world_pose[bone_index].copy(), None) for bone_index in range(1, s.bone_count): bone_name = s.bone_name[bone_index] bone = s.object.pose.bones[bone_name] s.poses[bone_name] = bone if bone_name == 'Root': continue p_bones.append(bone) bone_index = s.bone_index[bone_name] mat = s.skin_pose[bone_index].to_blender_matrix() if mat != last_matrix[bone_index]: bpy.ops.object.select_pattern(pattern=bone_name) parent_index = s.bone_parent[bone_index] bone.matrix = mat.copy() * bone.bone.matrix_local.copy() bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.mode_set(mode='POSE') bpy.context.scene.update() self.scene.update() try: bpy.ops.anim.keyframe_insert_menu(type='Location') except: ok = None try: bpy.ops.anim.keyframe_insert_menu(type='Rotation') except: ok = None bpy.ops.pose.select_all(action='DESELECT') last_matrix[bone_index] = mat self.scene.update() bpy.ops.pose.select_all(action='DESELECT') frame_offset += 1
def set_bone_transforms(gltf, skin_id, bone, node_id, parent): """Set bone transformations.""" pyskin = gltf.data.skins[skin_id] pynode = gltf.data.nodes[node_id] obj = bpy.data.objects[pyskin.blender_armature_name] # Set bone bind_pose by inverting bindpose matrix if node_id in pyskin.joints: index_in_skel = pyskin.joints.index(node_id) if pyskin.inverse_bind_matrices is not None: inverse_bind_matrices = BinaryData.get_data_from_accessor( gltf, pyskin.inverse_bind_matrices) # Needed to keep scale in matrix, as bone.matrix seems to drop it if index_in_skel < len(inverse_bind_matrices): pynode.blender_bone_matrix = matrix_gltf_to_blender( inverse_bind_matrices[index_in_skel]).inverted() bone.matrix = pynode.blender_bone_matrix else: gltf.log.error("Error with inverseBindMatrix for skin " + pyskin) else: pynode.blender_bone_matrix = Matrix() # 4x4 identity matrix else: print('No invBindMatrix for bone ' + str(node_id)) pynode.blender_bone_matrix = Matrix() # Parent the bone if parent is not None and hasattr(gltf.data.nodes[parent], "blender_bone_name"): bone.parent = obj.data.edit_bones[gltf.data.nodes[ parent].blender_bone_name] # TODO if in another scene # Switch to Pose mode bpy.ops.object.mode_set(mode="POSE") obj.data.pose_position = 'POSE' # Set posebone location/rotation/scale (in armature space) # location is actual bone location minus it's original (bind) location bind_location = Matrix.Translation( pynode.blender_bone_matrix.to_translation()) bind_rotation = pynode.blender_bone_matrix.to_quaternion() bind_scale = scale_to_matrix(pynode.blender_bone_matrix.to_scale()) location, rotation, scale = matrix_gltf_to_blender( pynode.transform).decompose() if parent is not None and hasattr(gltf.data.nodes[parent], "blender_bone_matrix"): parent_mat = gltf.data.nodes[parent].blender_bone_matrix # Get armature space location (bindpose + pose) # Then, remove original bind location from armspace location, and bind rotation if bpy.app.version < (2, 80, 0): final_location = ( bind_location.inverted() * parent_mat * Matrix.Translation(location)).to_translation() obj.pose.bones[pynode.blender_bone_name].location = \ bind_rotation.inverted().to_matrix().to_4x4() * final_location else: final_location = ( bind_location.inverted() @ parent_mat @ Matrix.Translation(location)).to_translation() obj.pose.bones[pynode.blender_bone_name].location = \ bind_rotation.inverted().to_matrix().to_4x4() @ final_location # Do the same for rotation & scale if bpy.app.version < (2, 80, 0): obj.pose.bones[pynode.blender_bone_name].rotation_quaternion = \ (pynode.blender_bone_matrix.inverted() * parent_mat * matrix_gltf_to_blender(pynode.transform)).to_quaternion() obj.pose.bones[pynode.blender_bone_name].scale = \ (bind_scale.inverted() * parent_mat * scale_to_matrix(scale)).to_scale() else: obj.pose.bones[pynode.blender_bone_name].rotation_quaternion = \ (pynode.blender_bone_matrix.inverted() @ parent_mat @ matrix_gltf_to_blender(pynode.transform)).to_quaternion() obj.pose.bones[pynode.blender_bone_name].scale = \ (bind_scale.inverted() @ parent_mat @ scale_to_matrix(scale)).to_scale() else: if bpy.app.version < (2, 80, 0): obj.pose.bones[ pynode. blender_bone_name].location = bind_location.inverted( ) * location obj.pose.bones[ pynode. blender_bone_name].rotation_quaternion = bind_rotation.inverted( ) * rotation obj.pose.bones[ pynode. blender_bone_name].scale = bind_scale.inverted() * scale else: obj.pose.bones[ pynode. blender_bone_name].location = bind_location.inverted( ) @ location obj.pose.bones[ pynode. blender_bone_name].rotation_quaternion = bind_rotation.inverted( ) @ rotation obj.pose.bones[ pynode. blender_bone_name].scale = bind_scale.inverted() @ scale
def custom(ot, context, event, axis=None): preference = addon.preference() bc = context.window_manager.bc verts = [ Vector((100000.0, 100000.0, 0.0)), Vector((-100000.0, 100000.0, 0.0)), Vector((-100000.0, -100000.0, 0.0)), Vector((100000.0, -100000.0, 0.0)) ] edges = [(0, 1), (1, 2), (2, 3), (3, 0)] faces = [(0, 1, 2, 3)] data = bpy.data.meshes.new(name='Box') data.bc.removeable = True if not bc.snap.hit: data.from_pydata(verts, edges, faces) data.validate() original_active = context.active_object box = bpy.data.objects.new( name='Box', object_data=data if not bc.snap.hit else bc.snap.mesh) bpy.context.scene.collection.objects.link(box) context.view_layer.objects.active = box if not axis: axis = preference.cursor_axis if not bc.snap.hit: current = {'X': 'Y', 'Y': 'X', 'Z': 'Z'} rotation = Matrix.Rotation(radians(-90 if axis in {'X', 'Y'} else 90), 4, current[axis]) cursor = context.scene.cursor.rotation_euler.to_matrix().to_4x4() cursor.translation = context.scene.cursor.location matrix = cursor @ rotation if preference.surface == 'CURSOR' else rotation box.data.transform(matrix) box.data.validate() context.scene.update() if bc.snap.hit: hit, ot.ray['location'], ot.ray['normal'], index = ray.cast.objects( *ot.mouse['location'], mesh=bc.snap.mesh) else: hit, ot.ray['location'], ot.ray['normal'], index = ray.cast.objects( *ot.mouse['location'], obj=box) if not hit: index = [axis == a for a in 'XYZ'].index(True) if index > 1: index = 0 else: index += 1 axis = 'XYZ'[index] bpy.data.objects.remove(box) del box custom(ot, context, event, axis=axis) return bc.lattice.matrix_world = matrix if not bc.snap.hit else Matrix() bc.lattice.matrix_world.translation = Vector( ot.ray['location'][:] if not bc.snap.hit else bc.snap.location) bc.shape.matrix_world = bc.lattice.matrix_world bc.plane.matrix_world = bc.lattice.matrix_world ot.start['matrix'] = bc.plane.matrix_world.copy() bc.location = ot.ray['location'] if not bc.snap.hit else bc.snap.location context.view_layer.objects.active = original_active bpy.data.objects.remove(box) del box refresh.shape(ot, context, event)
def draw_callback_view(n_id, cached_view, options): def Vector_generate2(prop): # try: # return [[Vector(v[:3]) for v in obj] for obj in prop] # except ValueEror: # return [] return [[Vector(v) for v in obj] for obj in prop] # context = bpy.context if options["timings"]: start = time.perf_counter() if options['draw_list'] == 0: sl1 = cached_view[n_id + 'v'] sl2 = cached_view[n_id + 'ep'] sl3 = cached_view[n_id + 'm'] if sl1: data_vector = Vector_generate2(sl1) verlen = len(data_vector) - 1 else: if not sl3: # end early: no matrix and no vertices callback_disable(n_id) return # display matrix repr only. data_vector = [] verlen = 0 options['verlen'] = verlen data_polygons = [] data_edges = [] if sl2 and sl2[0]: if isinstance(sl2[0], int): callback_disable(n_id) return len_sl2 = len(sl2[0][0]) if len_sl2 == 2: data_edges = sl2 elif len_sl2 > 2: data_polygons = sl2 if sl3: data_matrix = Matrix_generate(sl3) else: data_matrix = [Matrix() for i in range(verlen + 1)] if (data_vector, data_polygons, data_matrix, data_edges) == (0, 0, 0, 0): callback_disable(n_id) return try: the_display_list = glGenLists(1) glNewList(the_display_list, GL_COMPILE) draw_geometry(n_id, options, data_vector, data_polygons, data_matrix, data_edges) except Exception as err: print("Error in callback!:") traceback.print_exc() options['error'] = True finally: glEndList() options['genlist'] = the_display_list elif options['draw_list'] == 1: the_display_list = options['genlist'] if not 'error' in options: glCallList(the_display_list) glFlush() # restore to system state glLineWidth(1) if options["timings"]: stop = time.perf_counter() print("callback drawn in {:4f}".format(stop - start)) # has drawn once with success. options['draw_list'] = 1
def process(self): outputs = self.outputs if not outputs['Vertices'].is_linked: return IVerts, IFaces, IMask, Imatr = self.inputs vertices_s = IVerts.sv_get() faces_s = IFaces.sv_get() linked_extruded_polygons = outputs['ExtrudedPolys'].is_linked linked_other_polygons = outputs['OtherPolys'].is_linked result_vertices = [] result_edges = [] result_faces = [] result_extruded_faces = [] result_other_faces = [] bmlist = [ bmesh_from_pydata(verts, [], faces) for verts, faces in zip(vertices_s, faces_s) ] trans = Imatr.sv_get() if IMask.is_linked: flist = [ np.extract(mask, bm.faces[:]) for bm, mask in zip(bmlist, IMask.sv_get()) ] else: flist = [bm.faces for bm in bmlist] for bm, selfaces in zip(bmlist, flist): extrfaces = extrude_discrete_faces(bm, faces=selfaces)['faces'] fullList(trans, len(extrfaces)) new_extruded_faces = [] for face, ma in zip(extrfaces, trans): normal = face.normal if normal[0] == 0 and normal[1] == 0: m_r = Matrix() if normal[2] >= 0 else Matrix.Rotation( pi, 4, 'X') else: z_axis = normal x_axis = Vector( (z_axis[1] * -1, z_axis[0], 0)).normalized() y_axis = z_axis.cross(x_axis).normalized() m_r = Matrix(list([*zip(x_axis[:], y_axis[:], z_axis[:]) ])).to_4x4() m = (Matrix.Translation(face.calc_center_median()) @ m_r).inverted() transform(bm, matrix=ma, space=m, verts=face.verts) if linked_extruded_polygons or linked_other_polygons: new_extruded_faces.append([v.index for v in face.verts]) new_vertices, new_edges, new_faces = pydata_from_bmesh(bm) bm.free() new_other_faces = [ f for f in new_faces if f not in new_extruded_faces ] if linked_other_polygons else [] result_vertices.append(new_vertices) result_edges.append(new_edges) result_faces.append(new_faces) result_extruded_faces.append(new_extruded_faces) result_other_faces.append(new_other_faces) outputs['Vertices'].sv_set(result_vertices) outputs['Edges'].sv_set(result_edges) outputs['Polygons'].sv_set(result_faces) outputs['ExtrudedPolys'].sv_set(result_extruded_faces) outputs['OtherPolys'].sv_set(result_other_faces)
def dataCorrect2(self, destination, obj): if destination: return destination return [Matrix() for v in obj]
import bpy import sys from mathutils import Matrix args = sys.argv filepath = args[-1] name = args[-2] scene = bpy.context.scene group = bpy.data.groups.new(name) for ob in bpy.data.objects: scene.objects.link(ob) group.objects.link(ob) ob.matrix_world = Matrix() bpy.ops.wm.save_as_mainfile(filepath=filepath)
def add_object_align_init(context, operator): """ Return a matrix using the operator settings and view context. :arg context: The context to use. :type context: :class:`bpy.types.Context` :arg operator: The operator, checked for location and rotation properties. :type operator: :class:`bpy.types.Operator` :return: the matrix from the context and settings. :rtype: :class:`mathutils.Matrix` """ from mathutils import Matrix, Vector, Euler properties = operator.properties if operator is not None else None space_data = context.space_data if space_data and space_data.type != 'VIEW_3D': space_data = None # location if operator and properties.is_property_set("location"): location = Matrix.Translation(Vector(properties.location)) else: if space_data: # local view cursor is detected below location = Matrix.Translation(space_data.cursor_location) else: location = Matrix.Translation(context.scene.cursor_location) if operator: properties.location = location.to_translation() # rotation view_align = (context.user_preferences.edit.object_align == 'VIEW') view_align_force = False if operator: if properties.is_property_set("view_align"): view_align = view_align_force = operator.view_align else: if properties.is_property_set("rotation"): # ugh, 'view_align' callback resets value = properties.rotation[:] properties.view_align = view_align properties.rotation = value del value else: properties.view_align = view_align if operator and (properties.is_property_set("rotation") and not view_align_force): rotation = Euler(properties.rotation).to_matrix().to_4x4() else: if view_align and space_data: rotation = space_data.region_3d.view_matrix.to_3x3().inverted() rotation.resize_4x4() else: rotation = Matrix() # set the operator properties if operator: properties.rotation = rotation.to_euler() return location @ rotation