def load_component(component_id): # get file first component_name = UTILS_constants.bmfile_componentList[component_id] selected_file = os.path.join(os.path.dirname(__file__), 'meshes', component_name + '.bin') # read file. please note this sector is sync with import_bm's mesh's code. when something change, please change each other. fmesh = open(selected_file, 'rb') # create real mesh, we don't need to consider name. blender will solve duplicated name mesh = bpy.data.meshes.new('mesh_' + component_name) vList = [] vnList = [] faceList = [] # in first read, store all data into list listCount = UTILS_file_io.read_uint32(fmesh) for i in range(listCount): cache = UTILS_file_io.read_3vector(fmesh) # switch yz vList.append((cache[0], cache[2], cache[1])) listCount = UTILS_file_io.read_uint32(fmesh) for i in range(listCount): cache = UTILS_file_io.read_3vector(fmesh) # switch yz vnList.append((cache[0], cache[2], cache[1])) listCount = UTILS_file_io.read_uint32(fmesh) for i in range(listCount): faceData = UTILS_file_io.read_component_face(fmesh) # we need invert triangle sort faceList.append((faceData[4], faceData[5], faceData[2], faceData[3], faceData[0], faceData[1])) # then, we need add correspond count for vertices mesh.vertices.add(len(vList)) mesh.loops.add(len(faceList) * 3) # triangle face confirmed mesh.polygons.add(len(faceList)) mesh.create_normals_split() # add vertices data mesh.vertices.foreach_set("co", unpack_list(vList)) mesh.loops.foreach_set( "vertex_index", unpack_list(_flat_component_vertices_index(faceList))) mesh.loops.foreach_set( "normal", unpack_list(_flat_component_vertices_normal(faceList, vnList))) for i in range(len(faceList)): mesh.polygons[i].loop_start = i * 3 mesh.polygons[i].loop_total = 3 mesh.polygons[i].use_smooth = True mesh.validate(clean_customdata=False) mesh.update(calc_edges=False, calc_edges_loose=False) fmesh.close() return mesh
def invoke(self, context, event): me = bpy.data.meshes.new("test") obmade = bpy.data.objects.new("TestObject",me) print("Create Simple Mesh") bpy.data.scenes[0].objects.link(obmade) for i in bpy.context.scene.objects: i.select = False #deselect all objects obmade.select = True bpy.context.scene.objects.active = obmade verts = [(0,0,0),(2,0,0),(2,0,2)] edges = [(0,1),(1,2),(2,0)] faces = [] faces.extend([(0,1,2,0)]) #me.vertices.add(len(verts)) #print(dir(me)) me.vertices.add(len(verts)) me.tessfaces.add(len(faces)) for face in me.tessfaces: print(dir(face)) me.vertices.foreach_set("co", unpack_list(verts)) me.tessfaces.foreach_set("vertices_raw", unpack_list(faces)) me.edges.add(len(edges)) me.edges.foreach_set("vertices", unpack_list(edges)) #print(len(me.tessfaces)) me.tessface_uv_textures.new("uvtexture") #for uv in me.tessface_uv_textures: #print(len(uv.data)) #print(dir(uv.data[0])) #print(dir(uv.data[0].uv1)) return {'RUNNING_MODAL'}
def create_mesh(self, name, options): if options.normals_algorithm == NormalsAlgorithm.SHARP_EDGES and self.roottype == RootType.MODEL: self.merge_similar_vertices(options.sharp_edge_angle) # Create the mesh itself mesh = bpy.data.meshes.new(name) mesh.vertices.add(len(self.verts)) mesh.vertices.foreach_set("co", unpack_list(self.verts)) num_faces = len(self.facelist.vertices) mesh.loops.add(3 * num_faces) mesh.loops.foreach_set("vertex_index", unpack_list(self.facelist.vertices)) mesh.polygons.add(num_faces) mesh.polygons.foreach_set("loop_start", range(0, 3 * num_faces, 3)) mesh.polygons.foreach_set("loop_total", (3, ) * num_faces) # Create materials for wok_mat in defines.WOK_MATERIALS: mat_name = wok_mat[0] # Walkmesh materials will be shared across multiple walkmesh objects if mat_name in bpy.data.materials: material = bpy.data.materials[mat_name] else: material = bpy.data.materials.new(mat_name) material.diffuse_color = [*wok_mat[1], 1.0] material.specular_color = (0.0, 0.0, 0.0) material.specular_intensity = wok_mat[2] mesh.materials.append(material) # Apply the walkmesh materials to each face for idx, polygon in enumerate(mesh.polygons): polygon.material_index = self.facelist.materials[idx] # Create UV map if len(self.uv1) > 0: uv = unpack_list( [self.uv1[i] for indices in self.facelist.uv for i in indices]) uv_layer = mesh.uv_layers.new(name=UV_MAP_DIFFUSE, do_init=False) uv_layer.data.foreach_set("uv", uv) # Create lightmap UV map if len(self.uv2) > 0: uv = unpack_list( [self.uv2[i] for indices in self.facelist.uv for i in indices]) uv_layer = mesh.uv_layers.new(name=UV_MAP_LIGHTMAP, do_init=False) uv_layer.data.foreach_set("uv", uv) mesh.update() if self.roottype == RootType.MODEL: self.post_process_mesh(mesh, options) return mesh
def instance_group_dupli_vert(self, name, default_material, component_stats): def get_orientations(v): orientations = defaultdict(list) for transform in v: loc, rot, scale = Matrix(transform).decompose() scale = (scale[0], scale[1], scale[2]) rot = (rot[0], rot[1], rot[2], rot[3]) orientations[(scale, rot)].append((loc[0], loc[1], loc[2])) for key, locs in orientations.items(): scale , rot = key yield scale , rot, locs for scale, rot, locs in get_orientations(component_stats[(name, default_material)]): verts = [] main_loc = Vector(locs[0]) for c in locs: verts.append(Vector(c) - main_loc) dme = bpy.data.meshes.new('DUPLI_' + name) dme.vertices.add(len(verts)) dme.vertices.foreach_set("co", unpack_list(verts)) dme.update(calc_edges=True) # Update mesh with new data dme.validate() dob = bpy.data.objects.new("DUPLI_" + name, dme) dob.location = main_loc dob.dupli_type = 'VERTS' ob = self.instance_object_or_group(name,default_material) ob.scale = scale ob.rotation_quaternion = Quaternion((rot[0], rot[1], rot[2], rot[3])) ob.parent = dob self.context.scene.objects.link(ob) self.context.scene.objects.link(dob) sketchupLog("Complex group {} {} instanced {} times, scale -> {}".format(name, default_material, len(verts), scale)) return
def addGeometry(cls, mesh, vertices, faces): from bpy_extras.io_utils import unpack_list, unpack_face_list mesh.vertices.add(len(vertices)) mesh.vertices.foreach_set("co", unpack_list(vertices)) mesh.tessfaces.add(len(faces)) mesh.tessfaces.foreach_set("vertices_raw", unpack_face_list(faces)) #mesh.from_pydata(vertices, [], faces) """ mesh.add_geometry(len(vertices), 0, len(faces)) # add vertex unpackedVertices=[] for v in vertices: unpackedVertices.extend(v) mesh.vertices.foreach_set("co", unpackedVertices) # add face unpackedFaces = [] for face in faces: if len(face) == 4: if face[3] == 0: # rotate indices if the 4th is 0 face = [face[3], face[0], face[1], face[2]] elif len(face) == 3: if face[2] == 0: # rotate indices if the 3rd is 0 face = [face[2], face[0], face[1], 0] else: face.append(0) unpackedFaces.extend(face) mesh.faces.foreach_set("verts_raw", unpackedFaces) """ assert (len(vertices) == len(mesh.vertices))
def create_canvas_object(context, name, hooks, cleanobject, cams): from bpy_extras.io_utils import unpack_list # get all locations of the hooks in the list coords = get_location(hooks) # create the vertices of the cleanplate mesh me = bpy.data.meshes.new(name) me.vertices.add(len(coords)) me.vertices.foreach_set("co", unpack_list(coords)) # create the object which is using the mesh ob = bpy.data.objects.new(name, me) ob.location = (0, 0, 0) # link it to the scene and make it active bpy.context.scene.objects.link(ob) bpy.context.scene.objects.active = ob ob.layers = [True] + [False] * 19 # go into edit mode, select all vertices and create the face if not context.object.mode == "EDIT": bpy.ops.object.mode_set(mode="EDIT") bpy.ops.mesh.select_all(action='SELECT') bpy.ops.mesh.edge_face_add() bpy.ops.object.mode_set(mode="OBJECT") cleanobject.append(ob) bpy.ops.object.select_all(action='DESELECT') camera = cams[0] ob.select = True bpy.context.scene.objects.active = camera bpy.ops.object.parent_set() camera.select = False
def create_canvas_object(context, name, hooks, cleanobject, cams): from bpy_extras.io_utils import unpack_list # get all locations of the hooks in the list coords=get_location(hooks) # create the vertices of the cleanplate mesh me = bpy.data.meshes.new(name) me.vertices.add(len(coords)) me.vertices.foreach_set("co", unpack_list(coords)) # create the object which is using the mesh ob = bpy.data.objects.new(name, me) ob.location = (0,0,0) # link it to the scene and make it active bpy.context.scene.objects.link(ob) bpy.context.scene.objects.active=ob ob.layers = [True] + [False] * 19 # go into edit mode, select all vertices and create the face if not context.object.mode=="EDIT": bpy.ops.object.mode_set(mode="EDIT") bpy.ops.mesh.select_all(action='SELECT') bpy.ops.mesh.edge_face_add() bpy.ops.object.mode_set(mode="OBJECT") cleanobject.append(ob) bpy.ops.object.select_all(action='DESELECT') camera = cams[0] ob.select = True bpy.context.scene.objects.active = camera bpy.ops.object.parent_set() camera.select = False
def execute(self, context): from bpy_extras.io_utils import unpack_list sc = context.space_data clip = sc.clip tracking_object = clip.tracking.objects.active new_verts = [] scene = context.scene camera = scene.camera matrix = Matrix.Identity(4) if camera: reconstruction = tracking_object.reconstruction framenr = scene.frame_current - clip.frame_start + 1 reconstructed_matrix = reconstruction.cameras.matrix_from_frame( framenr) matrix = camera.matrix_world * reconstructed_matrix.inverted() mesh = bpy.data.meshes.new(name="Tracks") for track in tracking_object.tracks: if track.has_bundle: new_verts.append(track.bundle) if new_verts: mesh.vertices.add(len(new_verts)) mesh.vertices.foreach_set("co", unpack_list(new_verts)) ob = bpy.data.objects.new(name="Tracks", object_data=mesh) ob.matrix_world = matrix context.scene.objects.link(ob) return {'FINISHED'}
def addGeometry(cls, mesh, vertices, faces): from bpy_extras.io_utils import unpack_list, unpack_face_list mesh.vertices.add(len(vertices)) mesh.vertices.foreach_set("co", unpack_list(vertices)) mesh.tessfaces.add(len(faces)) mesh.tessfaces.foreach_set("vertices_raw", unpack_face_list(faces)) #mesh.from_pydata(vertices, [], faces) """ mesh.add_geometry(len(vertices), 0, len(faces)) # add vertex unpackedVertices=[] for v in vertices: unpackedVertices.extend(v) mesh.vertices.foreach_set("co", unpackedVertices) # add face unpackedFaces = [] for face in faces: if len(face) == 4: if face[3] == 0: # rotate indices if the 4th is 0 face = [face[3], face[0], face[1], face[2]] elif len(face) == 3: if face[2] == 0: # rotate indices if the 3rd is 0 face = [face[2], face[0], face[1], 0] else: face.append(0) unpackedFaces.extend(face) mesh.faces.foreach_set("verts_raw", unpackedFaces) """ assert(len(vertices)==len(mesh.vertices))
def execute(self, context): from bpy_extras.io_utils import unpack_list sc = context.space_data clip = sc.clip tracking_object = clip.tracking.objects.active new_verts = [] scene = context.scene camera = scene.camera matrix = Matrix.Identity(4) if camera: reconstruction = tracking_object.reconstruction framenr = scene.frame_current - clip.frame_start + 1 reconstructed_matrix = reconstruction.cameras.matrix_from_frame(framenr) matrix = camera.matrix_world * reconstructed_matrix.inverted() mesh = bpy.data.meshes.new(name="Tracks") for track in tracking_object.tracks: if track.has_bundle: new_verts.append(track.bundle) if new_verts: mesh.vertices.add(len(new_verts)) mesh.vertices.foreach_set("co", unpack_list(new_verts)) ob = bpy.data.objects.new(name="Tracks", object_data=mesh) ob.matrix_world = matrix context.scene.objects.link(ob) return {"FINISHED"}
def execute(self, context): from bpy_extras.io_utils import unpack_list sc = context.space_data clip = sc.clip tracking_object = clip.tracking.objects.active new_verts = [] scene = context.scene camera = scene.camera matrix = Matrix.Identity(4) if camera: reconstruction = tracking_object.reconstruction framenr = scene.frame_current - clip.frame_start + 1 reconstructed_matrix = reconstruction.cameras.matrix_from_frame(frame=framenr) matrix = camera.matrix_world @ reconstructed_matrix.inverted() for track in tracking_object.tracks: if track.has_bundle and track.select: new_verts.append(track.bundle) if new_verts: mesh = bpy.data.meshes.new(name="Tracks") mesh.vertices.add(len(new_verts)) mesh.vertices.foreach_set("co", unpack_list(new_verts)) ob = bpy.data.objects.new(name="Tracks", object_data=mesh) ob.matrix_world = matrix context.collection.objects.link(ob) ob.select_set(True) context.view_layer.objects.active = ob else: self.report({'WARNING'}, "No usable tracks selected") return {'FINISHED'}
def make_mesh(verteces, faces, normals, uvs, global_matrix): mesh = bpy.data.meshes.new('name') mesh.vertices.add(len(verteces)) mesh.vertices.foreach_set("co", unpack_list(verteces)) mesh.tessfaces.add(len(faces)) mesh.tessfaces.foreach_set("vertices_raw", unpack_face_list(faces)) index = 0 for vertex in mesh.vertices: vertex.normal = normals[index] index += 1 uvtex = mesh.tessface_uv_textures.new() uvtex.name = "UV" for face, uv in enumerate(uvs): data = uvtex.data[face] data.uv1 = uv[0] data.uv2 = uv[1] data.uv3 = uv[2] mesh.update(calc_tessface=False, calc_edges=False) obj = bpy.data.objects.new('name', mesh) # apply transformation matrix obj.matrix_world = global_matrix bpy.context.scene.objects.link(obj) # link object to scene
def instance_group_dupli_face(self, name, default_material, component_stats): def get_orientations(v): orientations = defaultdict(list) for transform in v: loc, rot, scale = Matrix(transform).decompose() scale = (scale[0], scale[1], scale[2]) orientations[scale].append(transform) for scale, transforms in orientations.items(): yield scale, transforms for scale, transforms in get_orientations( component_stats[(name, default_material)]): main_loc, _, real_scale = Matrix(transforms[0]).decompose() verts = [] faces = [] f_count = 0 for c in transforms: l_loc, l_rot, l_scale = Matrix(c).decompose() mat = Matrix.Translation(l_loc) * l_rot.to_matrix().to_4x4() verts.append( Vector((mat * Vector((-0.05, -0.05, 0, 1.0)))[0:3]) - main_loc) verts.append( Vector((mat * Vector((0.05, -0.05, 0, 1.0)))[0:3]) - main_loc) verts.append( Vector((mat * Vector((0.05, 0.05, 0, 1.0)))[0:3]) - main_loc) verts.append( Vector((mat * Vector((-0.05, 0.05, 0, 1.0)))[0:3]) - main_loc) faces.append( (f_count + 0, f_count + 1, f_count + 2, f_count + 3)) f_count += 4 dme = bpy.data.meshes.new('DUPLI_' + name) dme.vertices.add(len(verts)) dme.vertices.foreach_set("co", unpack_list(verts)) dme.tessfaces.add(f_count / 4) dme.tessfaces.foreach_set("vertices_raw", unpack_face_list(faces)) dme.update(calc_edges=True) # Update mesh with new data dme.validate() dob = bpy.data.objects.new("DUPLI_" + name, dme) dob.dupli_type = 'FACES' dob.location = main_loc #dob.use_dupli_faces_scale = True #dob.dupli_faces_scale = 10 ob = self.instance_object_or_group(name, default_material) ob.scale = real_scale ob.parent = dob self.context.scene.objects.link(ob) self.context.scene.objects.link(dob) sketchupLog("Complex group {} {} instanced {} times".format( name, default_material, f_count / 4)) return
def build_blender_data(self, blender_context): from mdl_node_volume import MDL_NODE_VOLUME import bpy from bpy_extras.io_utils import unpack_list, unpack_face_list super(MDL_NODE_POLYHEDRON, self).build_blender_data(blender_context) print(type(self).__name__ + ".build_blender_data()") volume_name = None parent_node = self.parent # Get parents volume name while True: # Check if we found a volume node if type(parent_node) == MDL_NODE_VOLUME: volume_name = parent_node.volume_name break # Check if we reached the root node without finding a volume node elif parent_node == None: raise Exception("No parent volume node found") # Otherwise get the next parent else: parent_node = parent_node.parent # Create a new mesh with our parents volume name self.blender_mesh = bpy.data.meshes.new(volume_name) # Load vertices data into the mesh self.blender_mesh.vertices.add(len(self.vol.positions)) self.blender_mesh.vertices.foreach_set("co", unpack_list(self.vol.positions)) # Load face data into the mesh self.blender_mesh.tessfaces.add(len(self.vol.indeces)) self.blender_mesh.tessfaces.foreach_set("vertices", unpack_list(self.vol.indeces)) # Validate mesh self.blender_mesh.validate() # Update mesh self.blender_mesh.update(calc_edges=True)
def drawmesh(): global DEBUGLOG, plik,vertexes,uvcoord,faceslist,num_faces,facemat,facesmooth,m global vertexes_ids,bonesdata,meshesdata,groups,num_materials,skala,flipyz,flipuv,mat_faceslist global vertices,faces print(faces[0]) print("[CREATING MESH:]") me_ob = bpy.data.meshes.new('testmesh') #create mesh print("-Vertices count:",len(vertices)) me_ob.vertices.add(len(vertices)) print("-Faces count:",len(faces)) me_ob.tessfaces.add(len(faces)) print("-Creating vertices points...") me_ob.vertices.foreach_set("co", unpack_list(vertices)) print("-Creating faces idx...") me_ob.tessfaces.foreach_set("vertices_raw",unpack_list( faces)) for face in me_ob.tessfaces: print(dir(face)) face.use_smooth = facesmooth[face.index] #face.material_index = facemat[face.index]#not yet working print("-Creating UV Texture...") me_ob.tessface_uv_textures.new('uvtexture') #uvtex = me_ob.tessface_uv_textures[0] for uv in me_ob.tessface_uv_textures: for face in me_ob.tessfaces: #uv.data[face.index].uv1.x = #print(uv.data[face.index].uv1) #uv.data[face.index].uv1 = Vector(uvcoord[faces[face.index]][0],uvcoord[face.index][1]) print(face.vertices_raw[0],face.vertices_raw[1],face.vertices_raw[2]) uv.data[face.index].uv1 = mathutils.Vector((uvcoord[face.vertices_raw[0]][0],uvcoord[face.vertices_raw[0]][1])) uv.data[face.index].uv2 = mathutils.Vector((uvcoord[face.vertices_raw[1]][0],uvcoord[face.vertices_raw[1]][1])) uv.data[face.index].uv3 = mathutils.Vector((uvcoord[face.vertices_raw[2]][0],uvcoord[face.vertices_raw[2]][1])) ob = bpy.data.objects.new("TestObject",me_ob) #create vertex group for bone_id in range(len(bonesdata)): bonedata = bonesdata[str(bone_id)] namebone = bonedata[0]#.strip()[-25:] #print("NAME:",namebone) ob.vertex_groups.new(namebone) me_ob.update() bpy.context.scene.objects.link(ob)
def create_mesh(nvx2_vertices, nvx2_faces, nvx2_uvlayers): """TODO:Doc.""" me = bpy.data.meshes.new('nvx2_mesh') # Add vertices me.vertices.add(len(nvx2_vertices)) me.vertices.foreach_set('co', unpack_list(nvx2_vertices)) # Add faces me.tessfaces.add(len(nvx2_faces)) # TODO: eekadoodle fix me.tessfaces.foreach_set('vertices_raw', unpack_face_list(nvx2_faces)) # Add texture coordinates material = create_material('nvx2_material') me.materials.append(material) uv_data = nvx2_uvlayers[0] if (len(uv_data) > 0): uv = me.tessface_uv_textures.new('nvx2_uv') me.tessface_uv_textures.active = uv for i in range(len(nvx2_faces)): tessface = me.tessfaces[i] tessface.material_index = 0 tessfaceUV = me.tessface_uv_textures[0].data[i] face = nvx2_faces[i] # BEGIN EEEKADOODLE FIX # BUG: Evil eekadoodle problem where faces that have # vert index 0 at location 3 are shuffled. if face[2] == 0: face = [face[1], face[2], face[0]] # END EEEKADOODLE FIX tessfaceUV.uv1 = uv_data[face[0]] tessfaceUV.uv2 = uv_data[face[1]] tessfaceUV.uv3 = uv_data[face[2]] # Apply texture to uv face tessfaceUV.image = material.texture_slots[0].texture.image """ me.uv_textures.new('nvx2_uv') uv_layer = me.uv_layers[-1].data vert_loops = {} for l in me.loops: vert_loops.setdefault(l.vertex_index, []).append(l.index) for i, coord in enumerate(uv_data): # For every loop of a vertex for li in vert_loops[i]: uv_layer[li].uv = coord """ """ vi_uv = {i: uv for i, uv in enumerate(uv_coords)} per_loop_list = [0.0] * len(me.loops) for loop in me.loops: per_loop_list[loop.index] = vi_uv.get(loop.vertex_index) per_loop_list = [uv for pair in per_loop_list for uv in pair] me.uv_textures.new('nvx2_uv') me.uv_layers[-1].data.foreach_set("uv", per_loop_list) """ me.update() return me
def make_mesh(verteces, faces, normals, uvs, global_matrix): # Create a new mesh from the vertices and faces mesh = bpy.data.meshes.new("Imported Mesh") mesh.vertices.add(len(verteces)) mesh.vertices.foreach_set("co", unpack_list(verteces)) mesh.tessfaces.add(len(faces)) mesh.tessfaces.foreach_set("vertices_raw", unpack_face_list(faces)) # Generate normals index = 0 for vertex in mesh.vertices: vertex.normal = normals[index] index += 1 # Generate UV data uvtex = mesh.tessface_uv_textures.new(name="UVMap") for face, uv in enumerate(uvs): data = uvtex.data[face] data.uv1 = uv[0] data.uv2 = uv[1] data.uv3 = uv[2] # Update the mesh and link it to the scene mesh.update(calc_tessface=False, calc_edges=False) obj = bpy.data.objects.new( "Imported Mesh", mesh) # Create the mesh object for the imported mesh obj.matrix_world = global_matrix # Apply transformation matrix bpy.context.scene.objects.link(obj) # Link object to scene # Prep for mesh cleaning --> https://blender.stackexchange.com/questions/174525/how-to-merge-all-vertices-by-distance-and-remove-all-inner-faces merge_threshold = 0.0001 bpy.ops.object.select_all(action='DESELECT') obj.select = True # Select the object we just made bpy.context.scene.objects.active = obj bpy.ops.object.mode_set(mode="EDIT") # Combine tri's to make a solid mesh and to remove unnecessary vertices bpy.ops.mesh.select_all(action="SELECT") bpy.ops.mesh.remove_doubles(threshold=merge_threshold) bpy.ops.mesh.select_all(action="DESELECT") # Remove interior faces that won't be seen bpy.ops.mesh.select_mode(type="FACE") bpy.ops.mesh.select_interior_faces() bpy.ops.mesh.delete(type="FACE") # Restore the scene to object mode if bpy.context.mode != "OBJECT": bpy.ops.object.mode_set(mode="OBJECT")
def create_mesh(self, name): verts = [ ((self.xsize/2) / 100.0, (self.ysize/2) / 100.0, 0.0), ((self.xsize/2) / 100.0, (-self.ysize/2) / 100.0, 0.0), ((-self.xsize/2) / 100.0, (-self.ysize/2) / 100.0, 0.0), ((-self.xsize/2) / 100.0, (self.ysize/2) / 100.0, 0.0) ] indices = [ (0, 1, 2), (0, 2, 3) ] # Create the mesh itself mesh = bpy.data.meshes.new(name) mesh.vertices.add(len(verts)) mesh.vertices.foreach_set("co", unpack_list(verts)) num_faces = len(indices) mesh.loops.add(3 * num_faces) mesh.loops.foreach_set("vertex_index", unpack_list(indices)) mesh.polygons.add(num_faces) mesh.polygons.foreach_set("loop_start", range(0, 3 * num_faces, 3)) mesh.polygons.foreach_set("loop_total", (3,) * num_faces) mesh.update() return mesh
def create_mesh(self, name, options): if options.normals_algorithm == NormalsAlgorithm.SHARP_EDGES and self.roottype == RootType.MODEL: self.merge_similar_vertices(options.sharp_edge_angle) # Create the mesh itself mesh = bpy.data.meshes.new(name) mesh.vertices.add(len(self.verts)) mesh.vertices.foreach_set("co", unpack_list(self.verts)) num_faces = len(self.facelist.vertices) mesh.loops.add(3 * num_faces) mesh.loops.foreach_set("vertex_index", unpack_list(self.facelist.vertices)) mesh.polygons.add(num_faces) mesh.polygons.foreach_set("loop_start", range(0, 3 * num_faces, 3)) mesh.polygons.foreach_set("loop_total", (3, ) * num_faces) mesh.polygons.foreach_set("use_smooth", [True] * num_faces) # Create UV map if len(self.uv1) > 0: uv = unpack_list( [self.uv1[i] for indices in self.facelist.uv for i in indices]) uv_layer = mesh.uv_layers.new(name=UV_MAP_DIFFUSE, do_init=False) uv_layer.data.foreach_set("uv", uv) # Create lightmap UV map if len(self.uv2) > 0: uv = unpack_list( [self.uv2[i] for indices in self.facelist.uv for i in indices]) uv_layer = mesh.uv_layers.new(name=UV_MAP_LIGHTMAP, do_init=False) uv_layer.data.foreach_set("uv", uv) mesh.update() if self.roottype == RootType.MODEL: self.post_process_mesh(mesh, options) return mesh
def importGMSH(file): result = {'FINISHED'} model = Header() model.read(file) for me in model.meshes: mesh = bpy.data.meshes.new(ntpath.basename(file.name)) obj = bpy.data.objects.new(ntpath.basename(file.name), mesh) bpy.context.scene.objects.link(obj) bpy.context.scene.objects.active = obj mesh.vertices.add(me.numVertices) mesh.vertices.foreach_set("co", unpack_list(me.positions)) mesh.tessfaces.add(me.numTriangles) mesh.tessfaces.foreach_set("vertices_raw", unpack_face_list(me.triangles)) uvtex = mesh.tessface_uv_textures.new() uvtex.name = 'DefaultUV' if len(me.UVs) > 0: for v, face in enumerate(mesh.tessfaces): uvtex.data[v].uv1 = me.UVs[face.vertices_raw[0]] uvtex.data[v].uv2 = me.UVs[face.vertices_raw[1]] uvtex.data[v].uv3 = me.UVs[face.vertices_raw[2]] uvtex.data[v].uv4 = [0, 0] mesh.update() if len(me.normals) > 0: mesh.vertices.foreach_set("normal", unpack_list(me.normals)) file.close() return result
def createHiddenMeshObject(name, untransformedPositions, faces, matrix): mesh = bpy.data.meshes.new(name) meshObject = bpy.data.objects.new(name, mesh) meshObject.location = (0,0,0) transformedPositions = [] for v in untransformedPositions: transformedPositions.append(matrix * mathutils.Vector(v)) mesh.vertices.add(len(transformedPositions)) mesh.vertices.foreach_set("co", io_utils.unpack_list(transformedPositions)) mesh.tessfaces.add(len(faces)) mesh.tessfaces.foreach_set("vertices_raw", io_utils.unpack_face_list(faces)) mesh.update(calc_edges=True) return meshObject
def createGridIcoSphere(): me = bpy.data.meshes.new("M_GridPoint") me.from_pydata(verts, [], faces) for material in materials: mat = bpy.data.materials.get(material) if (mat == None): mat = bpy.data.materials.new(name=material) me.materials.append(mat) me.polygons.foreach_set("material_index", material_ids) me.uv_layers.new(do_init=False, name="UVMap") me.uv_layers["UVMap"].data.foreach_set("uv", unpack_list(uvs)) ob = bpy.data.objects.new("LightGrid", me) bpy.context.collection.objects.link(ob) return ob
def mesh_from_data(name,coords,uvs,faces,face_mats,mats): mesh = bpy.data.meshes.new(name) if not mats is None: [mesh.materials.append(materials[ma]) for ma in mats] mesh.vertices.add(len(coords)) mesh.vertices.foreach_set('co',unpack_list(coords)) mesh.tessfaces.add(len(faces)) mesh.tessfaces.foreach_set('vertices_raw',unpack_face_list(faces)) mesh.tessfaces.foreach_set('material_index',face_mats) mesh.tessface_uv_textures.new() for fdx in range(len(faces)): fa = faces[fdx] mesh.tessface_uv_textures[0].data[fdx].uv1 = uvs[fa[0]].to_tuple() mesh.tessface_uv_textures[0].data[fdx].uv2 = uvs[fa[1]].to_tuple() mesh.tessface_uv_textures[0].data[fdx].uv3 = uvs[fa[2]].to_tuple() mesh.update() return mesh
def instance_group_dupli_face(self, name, default_material, component_stats): def get_orientations( v): orientations = defaultdict(list) for transform in v: loc, rot, scale = Matrix(transform).decompose() scale = (scale[0], scale[1], scale[2]) orientations[scale].append(transform) for scale, transforms in orientations.items(): yield scale, transforms for scale, transforms in get_orientations(component_stats[(name, default_material)]): main_loc, _, real_scale = Matrix(transforms[0]).decompose() verts = [] faces = [] f_count = 0 for c in transforms: l_loc, l_rot, l_scale = Matrix(c).decompose() mat = Matrix.Translation(l_loc) * l_rot.to_matrix().to_4x4() verts.append(Vector((mat * Vector((-0.05, -0.05, 0, 1.0)))[0:3]) - main_loc) verts.append(Vector((mat * Vector(( 0.05, -0.05, 0, 1.0)))[0:3]) - main_loc) verts.append(Vector((mat * Vector(( 0.05, 0.05, 0, 1.0)))[0:3]) - main_loc) verts.append(Vector((mat * Vector((-0.05, 0.05, 0, 1.0)))[0:3]) - main_loc) faces.append( (f_count + 0, f_count + 1, f_count + 2, f_count + 3) ) f_count += 4 dme = bpy.data.meshes.new('DUPLI_' + name) dme.vertices.add(len(verts)) dme.vertices.foreach_set("co", unpack_list(verts)) dme.tessfaces.add(f_count /4 ) dme.tessfaces.foreach_set("vertices_raw", unpack_face_list(faces)) dme.update(calc_edges=True) # Update mesh with new data dme.validate() dob = bpy.data.objects.new("DUPLI_" + name, dme) dob.dupli_type = 'FACES' dob.location = main_loc #dob.use_dupli_faces_scale = True #dob.dupli_faces_scale = 10 ob = self.instance_object_or_group(name,default_material) ob.scale = real_scale ob.parent = dob self.context.scene.objects.link(ob) self.context.scene.objects.link(dob) sketchupLog("Complex group {} {} instanced {} times".format(name, default_material, f_count / 4)) return
def mesh_from_data(name, coords, uvs, faces, face_mats, mats): mesh = bpy.data.meshes.new(name) if not mats is None: [mesh.materials.append(materials[ma]) for ma in mats] mesh.vertices.add(len(coords)) mesh.vertices.foreach_set('co', unpack_list(coords)) mesh.tessfaces.add(len(faces)) mesh.tessfaces.foreach_set('vertices_raw', unpack_face_list(faces)) mesh.tessfaces.foreach_set('material_index', face_mats) mesh.tessface_uv_textures.new() for fdx in range(len(faces)): fa = faces[fdx] mesh.tessface_uv_textures[0].data[fdx].uv1 = uvs[fa[0]].to_tuple() mesh.tessface_uv_textures[0].data[fdx].uv2 = uvs[fa[1]].to_tuple() mesh.tessface_uv_textures[0].data[fdx].uv3 = uvs[fa[2]].to_tuple() mesh.update() return mesh
def _createMesh(scene, name, vertices, faces): from bpy_extras.io_utils import unpack_list, unpack_face_list mesh = bpy.data.meshes.new(name=name) mesh.vertices.add(len(vertices)) mesh.vertices.foreach_set("co", unpack_list(vertices)) mesh.faces.add(len(faces)) mesh.faces.foreach_set("vertices_raw", unpack_face_list(faces)) mesh.update(calc_edges=True) ob = bpy.data.objects.new(name=name, object_data=mesh) scene.objects.link(ob) return ob
def import_mesh(node): mesh = bpy.data.meshes.new(node.name) # join face arrays faces = [] for face in node.faces: faces.extend(face.indices) # create mesh from data mesh.from_pydata(flip_all(node.vertices), [], flip_all(faces)) # assign normals mesh.vertices.foreach_set('normal', unpack_list(node.normals)) # create object from mesh ob = bpy.data.objects.new(node.name, mesh) # assign uv coordinates vert_uvs = [(0,0) if len(uv)==0 else (uv[0], 1-uv[1]) for uv in node.uvs] me = ob.data me.uv_layers.new(do_init=False) me.uv_layers[-1].data.foreach_set("uv", [uv for pair in [vert_uvs[l.vertex_index] for l in me.loops] for uv in pair]) # assign materials and textures mat_slots = {} for face in node.faces: if face.brush_id in materials: mat = materials[face.brush_id] ob.data.materials.append(mat) mat_slots[face.brush_id] = len(ob.data.materials)-1 #for uv_face in ob.data.uv_layers.active.data: # if mat.active_texture: # uv_face.image = mat.active_texture.image # link object to scene ctx.scene.collection.objects.link(ob) if len(node.faces)>1: assign_material_slots(ob, node, mat_slots) #postprocess(ob, mesh, node) # breaks weighting return ob
def load(operator, context, filepath): # Parse mesh from OFF file # TODO: Add support for NOFF and COFF filepath = os.fsencode(filepath) file = open(filepath, 'r') file.readline() vcount, fcount, ecount = [int(x) for x in file.readline().split()] verts = [] facets = [] i=0; while i<vcount: line = file.readline() try: px, py, pz = [float(x) for x in line.split()] except ValueError: continue verts.append((px, py, pz)) i=i+1 i=0; while i<fcount: line = file.readline() try: unused, vid1, vid2, vid3 = [int(x) for x in line.split()] except ValueError: continue facets.append((vid1, vid2, vid3)) i=i+1 # Assemble mesh off_name = bpy.path.display_name_from_filepath(filepath) mesh = bpy.data.meshes.new(name=off_name) mesh.vertices.add(len(verts)) mesh.vertices.foreach_set("co", unpack_list(verts)) mesh.tessfaces.add(len(facets)) mesh.tessfaces.foreach_set("vertices_raw", unpack_face_list(facets)) mesh.validate() mesh.update() return mesh
def execute(self, context): from bpy_extras.io_utils import unpack_list sc = context.space_data clip = sc.clip new_verts = [] mesh = bpy.data.meshes.new(name="Tracks") for track in clip.tracking.tracks: if track.has_bundle: new_verts.append(track.bundle) if new_verts: mesh.vertices.add(len(new_verts)) mesh.vertices.foreach_set("co", unpack_list(new_verts)) ob = bpy.data.objects.new(name="Tracks", object_data=mesh) context.scene.objects.link(ob) return {'FINISHED'}
def _createMesh(collection, name, vertices, faces): from bpy_extras.io_utils import unpack_list mesh = bpy.data.meshes.new(name=name) mesh.vertices.add(len(vertices)) mesh.vertices.foreach_set("co", unpack_list(vertices)) nbr_loops = len(faces) nbr_polys = nbr_loops // 4 mesh.loops.add(nbr_loops) mesh.polygons.add(nbr_polys) mesh.polygons.foreach_set("loop_start", range(0, nbr_loops, 4)) mesh.polygons.foreach_set("loop_total", (4, ) * nbr_polys) mesh.loops.foreach_set("vertex_index", faces) mesh.update() ob = bpy.data.objects.new(name=name, object_data=mesh) collection.objects.link(ob) return ob
def _createMesh(collection, name, vertices, faces): from bpy_extras.io_utils import unpack_list mesh = bpy.data.meshes.new(name=name) mesh.vertices.add(len(vertices)) mesh.vertices.foreach_set("co", unpack_list(vertices)) nbr_loops = len(faces) nbr_polys = nbr_loops // 4 mesh.loops.add(nbr_loops) mesh.polygons.add(nbr_polys) mesh.polygons.foreach_set("loop_start", range(0, nbr_loops, 4)) mesh.polygons.foreach_set("loop_total", (4,) * nbr_polys) mesh.loops.foreach_set("vertex_index", faces) mesh.update() ob = bpy.data.objects.new(name=name, object_data=mesh) collection.objects.link(ob) return ob
def import_mesh(node, parent): global material_mapping mesh = bpy.data.meshes.new(node.name) # join face arrays faces = [] for face in node.faces: faces.extend(face.indices) # create mesh from data mesh.from_pydata(flip_all(node.vertices), [], flip_all(faces)) # assign normals mesh.vertices.foreach_set('normal', unpack_list(node.normals)) # create object from mesh ob = bpy.data.objects.new(node.name, mesh) # assign uv coordinates bpymesh = ob.data uvs = [(0,0) if len(uv)==0 else (uv[0], 1-uv[1]) for uv in node.uvs] uvlist = [i for poly in bpymesh.polygons for vidx in poly.vertices for i in uvs[vidx]] bpymesh.uv_layers.new().data.foreach_set('uv', uvlist) # adding object materials (insert-ordered) for key, value in material_mapping.items(): ob.data.materials.append(bpy.data.materials[value]) # assign material_indexes poly = 0 for face in node.faces: for _ in face.indices: ob.data.polygons[poly].material_index = face.brush_id poly += 1 return ob
def my_handler(scene): frame = scene.frame_current activationFlag = bpy.context.scene.lineGenActivate randomConnections = bpy.context.scene.randomConnections handle_random_mul = bpy.context.scene.randomizeInfluence coordinate_noise = bpy.context.scene.coordinate_noise coordinate_noise_influence = bpy.context.scene.coordinate_noise_influence coordinate_noise_scale = bpy.context.scene.coordinate_noise_scale coordinate_offset_dx = bpy.context.scene.coordinate_offset_dx coordinate_offset_dy = bpy.context.scene.coordinate_offset_dy coordinate_offset_dz = bpy.context.scene.coordinate_offset_dz curveOutward= bpy.context.scene.curveOutward pointLerp = bpy.context.scene.pointLerp pointIdentity = bpy.context.scene.pointIdentity randomNum=[] ANIM_DIST=bpy.context.scene.animDist print(str(activationFlag) + " " +str(ANIM_DIST)) if activationFlag == True: #go through each object in the group (set up index boundaries) xLength = len(pointList) #-1 indexA=0 bpy.ops.object.select_all(action='DESELECT') curvedata.splines.clear() for x in pointList: indexA= indexA+1 if indexA <= xLength: for indexY in range(indexA,xLength): y= pointList[indexY] locX=x.location locY=pointList[indexY].location distance = math.sqrt( (locX[0] - locY[0])**2 + (locX[1] - locY[1])**2 + (locX[2] - locY[2])**2) if (randomConnections): randomNum = random.random()*100 if randomNum <= bpy.context.scene.randomConnections_threshold: if distance >= ANIM_DIST: distance = ANIM_DIST*0.9 if randomNum >= bpy.context.scene.randomConnections_threshold: distance = ANIM_DIST*3 if distance <= ANIM_DIST: minimumRadius = bpy.context.scene.radius_minimum radius_multiplier = bpy.context.scene.radius_multiplier pointRadius = (1 - (distance / ANIM_DIST))*radius_multiplier + minimumRadius coordinate_Pairs = [] coordinate_Pairs.append(locX) coordinate_Pairs.append(locY) spline = curvedata.splines.new('BEZIER') spline.bezier_points.add(1) spline.bezier_points.foreach_set("co", unpack_list(coordinate_Pairs)) maxindex=2 if (pointIdentity): maxindex=1 for i in range(0,maxindex): left_dx = bpy.context.scene.left_dx left_dy = bpy.context.scene.left_dy left_dz = bpy.context.scene.left_dz right_dx = bpy.context.scene.right_dx right_dy = bpy.context.scene.right_dy right_dz = bpy.context.scene.right_dz spline.bezier_points[i].handle_left[0] += coordinate_Pairs[i][0]+left_dx spline.bezier_points[i].handle_left[1] += coordinate_Pairs[i][1]+left_dy spline.bezier_points[i].handle_left[2] += coordinate_Pairs[i][2]+left_dz spline.bezier_points[i].handle_right[0] += coordinate_Pairs[i][0]+right_dx spline.bezier_points[i].handle_right[1] += coordinate_Pairs[i][1]+right_dy spline.bezier_points[i].handle_right[2] += coordinate_Pairs[i][2]+right_dz if(curveOutward): #spline.bezier_points[i].handle_right.xyz = spline.bezier_points[i].co #v=mathutils.Vector((0.01,0.01,0.01)) #spline.bezier_points[i].handle_left.xyz = spline.bezier_points[i].co+v #spline.bezier_points[i].handle_right_type='FREE' #spline.bezier_points[i].handle_left_type='FREE' #spline.bezier_points[i].handle_right_type='ALIGNED' #spline.bezier_points[i].handle_left_type='ALIGNED' #spline.bezier_points[i].handle_right_type='VECTOR' #spline.bezier_points[i].handle_left_type='VECTOR' spline.bezier_points[i].handle_left.xyz += spline.bezier_points[i].handle_left.lerp(spline.bezier_points[i].co,pointLerp) spline.bezier_points[i].handle_right.xyz += spline.bezier_points[i].handle_right.lerp(spline.bezier_points[i].co,pointLerp) if(bpy.context.scene.randomHandles): spline.bezier_points[i].handle_left[0] +=(0.5-random.random())*handle_random_mul spline.bezier_points[i].handle_left[1] +=(0.5-random.random())*handle_random_mul spline.bezier_points[i].handle_left[2] +=(0.5-random.random())*handle_random_mul spline.bezier_points[i].handle_right[0] +=(0.5-random.random())*handle_random_mul spline.bezier_points[i].handle_right[1] +=(0.5-random.random())*handle_random_mul spline.bezier_points[i].handle_right[2] +=(0.5-random.random())*handle_random_mul if(coordinate_noise): spline.bezier_points[i].handle_left[0] +=math.sin(spline.bezier_points[i].handle_left[0]*coordinate_noise_scale+coordinate_offset_dx)*coordinate_noise_influence spline.bezier_points[i].handle_left[1] +=math.cos(spline.bezier_points[i].handle_left[1]*coordinate_noise_scale+coordinate_offset_dy)*coordinate_noise_influence spline.bezier_points[i].handle_left[2] +=math.sin(spline.bezier_points[i].handle_left[2]*coordinate_noise_scale+coordinate_offset_dz)*coordinate_noise_influence spline.bezier_points[i].handle_right[0] +=math.sin(spline.bezier_points[i].handle_left[0]*coordinate_noise_scale+coordinate_offset_dx)*coordinate_noise_influence spline.bezier_points[i].handle_right[1] +=math.cos(spline.bezier_points[i].handle_left[1]*coordinate_noise_scale+coordinate_offset_dy)*coordinate_noise_influence spline.bezier_points[i].handle_right[2] +=math.sin(spline.bezier_points[i].handle_left[2]*coordinate_noise_scale+coordinate_offset_dz)*coordinate_noise_influence spline.bezier_points[i].radius = pointRadius
def make_mesh(model, name, meshes, amtobj): print("importing mesh", name, "with", len(meshes), "parts") mesh = bpy.data.meshes.new(name) obj = bpy.data.objects.new(name, mesh) bpy.context.scene.objects.link(obj) bpy.context.scene.objects.active = obj # Set the mesh to single-sided to spot normal errors mesh.show_double_sided = False # Flip winding for m in meshes: m.faces = [x[::-1] for x in m.faces] # Positions, normals, blends and vertex groups go to vertices. # Material, texture coords and vertex colors go to faces. weld = {} out_vp, out_vn, out_vb = [], [], [] out_f, out_f_mat, out_f_img, out_ft, out_fc = [], [], [], [], [] for m in meshes: material, image = make_material(m.material) if material.name not in mesh.materials: mesh.materials.append(material) material_index = mesh.materials.find(material.name) out_from_in = [] for i, p in enumerate(m.positions): n = m.normals[i] if len(m.normals) > i else (0,0,1) b = m.blends[i] if len(m.blends) > i else None # TODO: vertex groups custom data key = p, n, b if not key in weld: weld[key] = len(out_vp) out_vp.append(p) out_vn.append(n) out_vb.append(b) out_from_in.append(weld[key]) vt, vt_names = gather_vt(model.vertexarrays, m) vc, vc_names = gather_vc(model.vertexarrays, m) print(vc_names) print(vc) for face in m.faces: f = [out_from_in[v] for v in face] ft = [[t[v] for t in vt] for v in face] fc = [[c[v] for c in vc] for v in face] f, ft, fc = reorder(f, ft, fc) if isdegenerate(f): print("degenerate face", f) continue out_f.append(f) out_ft.append(ft) out_fc.append(fc) out_f_mat.append(material_index) out_f_img.append(image) print("\tcollected %d vertices and %d faces" % (len(out_vp), len(out_f))) # Create mesh vertex and face data mesh.vertices.add(len(out_vp)) mesh.vertices.foreach_set("co", unpack_list(out_vp)) mesh.tessfaces.add(len(out_f)) mesh.tessfaces.foreach_set("vertices_raw", unpack_face_list(out_f)) for i, face in enumerate(mesh.tessfaces): face.use_smooth = True face.material_index = out_f_mat[i] for k, name in enumerate(vt_names): layer = mesh.tessface_uv_textures.new(name) for i, face in enumerate(mesh.tessfaces): data = layer.data[i] ft = out_ft[i] data.image = out_f_img[i] data.uv1 = (ft[0][k][0], 1-ft[0][k][1]) data.uv2 = (ft[1][k][0], 1-ft[1][k][1]) data.uv3 = (ft[2][k][0], 1-ft[2][k][1]) if len(ft) > 3: data.uv4 = (ft[3][k][0], 1-ft[3][k][1]) for k, name in enumerate(vc_names): layer = mesh.tessface_vertex_colors.new(name) for i, face in enumerate(mesh.tessfaces): data = layer.data[i] data.color1 = tuple(out_fc[i][0][k][:3]) data.color2 = tuple(out_fc[i][1][k][:3]) data.color3 = tuple(out_fc[i][2][k][:3]) if len(out_fc[i]) > 3: data.color4 = tuple(out_fc[i][3][k][:3]) # Vertex groups and armature modifier for skinning if amtobj: for iqbone in iqmodel.bones: obj.vertex_groups.new(iqbone[0]) for vgroup in obj.vertex_groups: for i, b in enumerate(out_vb): idx, wgt = b if idx == vgroup.index: vgroup.add([i], idx, 'REPLACE') mod = obj.modifiers.new("Armature", 'ARMATURE') mod.object = amtobj mod.use_vertex_groups = True # Update mesh polygons from tessfaces mesh.update() # Must set normals after mesh.update() or they will be recalculated. mesh.vertices.foreach_set("normal", unpack_list(out_vn)) return obj
def import_mesh(filename): print("importing", filename) name = filename.split("/")[-1].split("\\")[-1].split(".")[0] file = open(filename) line = file.readline() if not line.startswith("# Inter-Quake Export"): raise Exception("Not an IQE file!") has_vc = has_vt = False faces = [] mat, img = None, None for line in file.readlines(): if "#" in line or "\"" in line: line = shlex.split(line, "#") else: line = line.split() if len(line) == 0: pass elif line[0] == "mesh": in_vp, in_vn, in_vt, in_vc = [], [], [], [] elif line[0] == "material": mat, img = import_material(line[1]) elif line[0] == "vp": in_vp.append((float(line[1]), float(line[2]), float(line[3]))) elif line[0] == "vn": in_vn.append((float(line[1]), float(line[2]), float(line[3]))) elif line[0] == "vt": has_vt = True; in_vt.append((float(line[1]), 1.0 - float(line[2]))) elif line[0] == "vc": has_vc = True; in_vc.append((float(line[1]), float(line[2]), float(line[3]))) elif line[0] == "fm": verts = [] for f in [int(x) for x in line[1:]]: p, n = in_vp[f], in_vn[f] t = in_vt[f] if f < len(in_vt) else (0,0) c = in_vc[f] if f < len(in_vc) else (1,1,1) verts.insert(0, (p, n, t, c)) faces.append((verts, mat, img)) vertex_map = {} out_vp, out_vn, out_f, out_ft, out_fc, out_fm = [], [], [], [], [], [] for verts, mat, img in faces: f, ft, fc = [], [], [] for p, n, t, c in verts: if not (p,n) in vertex_map: vertex_map[(p,n)] = len(out_vp) out_vp.append(p) out_vn.append(n) f.append(vertex_map[p,n]) ft.append(t) fc.append(c) f, ft, fc = reorder(f, ft, fc) if isdegenerate(f): print("degenerate face", f) continue out_f.append(f) out_ft.append(ft) out_fc.append(fc) out_fm.append((mat, img)) mesh = bpy.data.meshes.new(name) obj = bpy.data.objects.new(name, mesh) grp = bpy.data.groups.new(name) grp.objects.link(obj) mesh.show_double_sided = False mesh.vertices.add(len(out_vp)) mesh.vertices.foreach_set("co", unpack_list(out_vp)) mesh.tessfaces.add(len(out_f)) mesh.tessfaces.foreach_set("vertices_raw", unpack_face_list(out_f)) if has_vt: uvlayer = mesh.tessface_uv_textures.new() if has_vc: vclayer = mesh.tessface_vertex_colors.new() for i, face in enumerate(mesh.tessfaces): mat, img = out_fm[i] if mat.name not in mesh.materials: mesh.materials.append(mat) face.material_index = mesh.materials.find(mat.name) face.use_smooth = True if has_vt: uvlayer.data[i].image = img uvlayer.data[i].uv1 = out_ft[i][0] uvlayer.data[i].uv2 = out_ft[i][1] uvlayer.data[i].uv3 = out_ft[i][2] uvlayer.data[i].uv4 = out_ft[i][3] if len(out_ft[i]) == 4 else (0,0) if has_vc: vclayer.data[i].color1 = out_fc[i][0] vclayer.data[i].color2 = out_fc[i][1] vclayer.data[i].color3 = out_fc[i][2] vclayer.data[i].color4 = out_fc[i][3] if len(out_fc[i]) == 4 else (1,1,1) for mat in mesh.materials: mat.use_vertex_color_paint = has_vc mesh.update() # Must set normals after mesh.update() or they will be recalculated mesh.vertices.foreach_set("normal", unpack_list(out_vn)) bpy.context.scene.objects.link(obj) bpy.context.scene.objects.active = obj
def make_mesh_data(iqmodel, name, meshes, amtobj, dir): print("importing mesh", name, "with", len(meshes), "parts") mesh = bpy.data.meshes.new(name) obj = bpy.data.objects.new(name, mesh) bpy.context.scene.objects.link(obj) bpy.context.scene.objects.active = obj # Set the mesh to single-sided to spot normal errors mesh.show_double_sided = False has_vn = len(iqmodel.meshes[0].vn) > 0 has_vt = len(iqmodel.meshes[0].vt) > 0 has_vc = len(iqmodel.meshes[0].vc) > 0 has_vb = len(iqmodel.meshes[0].vbi) > 0 and len(iqmodel.meshes[0].vbw) == len(iqmodel.meshes[0].vbi) has_v0 = len(iqmodel.meshes[0].v0) > 0 has_v1 = len(iqmodel.meshes[0].v1) > 0 has_v2 = len(iqmodel.meshes[0].v2) > 0 has_v3 = len(iqmodel.meshes[0].v3) > 0 has_v4 = len(iqmodel.meshes[0].v4) > 0 has_v5 = len(iqmodel.meshes[0].v5) > 0 has_v6 = len(iqmodel.meshes[0].v6) > 0 has_v7 = len(iqmodel.meshes[0].v7) > 0 has_v8 = len(iqmodel.meshes[0].v8) > 0 has_v9 = len(iqmodel.meshes[0].v9) > 0 # Flip winding and UV coords. for iqmesh in meshes: iqmesh.faces = [x[::-1] for x in iqmesh.faces] iqmesh.vt = [(u,1-v) for (u,v) in iqmesh.vt] # Blender has texcoords and colors on faces rather than vertices. # Create material slots for all materials used. # Create new vertices from unique vp/vn/vb sets (vertex data). # Create new faces which index these new vertices, and has associated face data. vertex_map = {} new_f = [] new_ft = [] new_fc = [] new_fm_m = [] new_fm_i = [] new_vp = [] new_vn = [] new_vbi = [] new_vbw = [] new_v0 = [] new_v1 = [] new_v2 = [] new_v3 = [] new_v4 = [] new_v5 = [] new_v6 = [] new_v7 = [] new_v8 = [] new_v9 = [] for iqmesh in meshes: material, image = make_material(iqmesh.material, dir) if material.name not in mesh.materials: mesh.materials.append(material) material_index = mesh.materials.find(material.name) for iqface in iqmesh.faces: f = [] ft = [] fc = [] for iqvert in iqface: vp = iqmesh.vp[iqvert] vn = iqmesh.vn[iqvert] if has_vn else None vbi = iqmesh.vbi[iqvert] if has_vb else None vbw = iqmesh.vbw[iqvert] if has_vb else None v0 = iqmesh.v0[iqvert] if has_v0 else None v1 = iqmesh.v1[iqvert] if has_v1 else None v2 = iqmesh.v2[iqvert] if has_v2 else None v3 = iqmesh.v3[iqvert] if has_v3 else None v4 = iqmesh.v4[iqvert] if has_v4 else None v5 = iqmesh.v5[iqvert] if has_v5 else None v6 = iqmesh.v6[iqvert] if has_v6 else None v7 = iqmesh.v7[iqvert] if has_v7 else None v8 = iqmesh.v8[iqvert] if has_v8 else None v9 = iqmesh.v9[iqvert] if has_v9 else None vertex = (vp, vn, vbi, vbw, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) if not vertex in vertex_map: vertex_map[vertex] = len(new_vp) new_vp.append(vp) new_vn.append(vn) new_vbi.append(vbi) new_vbw.append(vbw) new_v0.append(v0) new_v1.append(v1) new_v2.append(v2) new_v3.append(v3) new_v4.append(v4) new_v5.append(v5) new_v6.append(v6) new_v7.append(v7) new_v8.append(v8) new_v9.append(v9) f.append(vertex_map[vertex]) ft.append(iqmesh.vt[iqvert] if has_vt else None) fc.append(iqmesh.vc[iqvert] if has_vc else None) f, ft, fc = reorder(f, ft, fc) if isdegenerate(f): print("degenerate face", iqface, f) continue new_f.append(f) new_ft.append(ft) new_fc.append(fc) new_fm_m.append(material_index) new_fm_i.append(image) print("\tcollected %d vertices and %d faces" % (len(new_vp), len(new_f))) # Create mesh vertex and face data mesh.vertices.add(len(new_vp)) mesh.vertices.foreach_set("co", unpack_list(new_vp)) mesh.tessfaces.add(len(new_f)) mesh.tessfaces.foreach_set("vertices_raw", unpack_face_list(new_f)) # Set up UV and Color layers uvlayer = mesh.tessface_uv_textures.new() if has_vt else None clayer = mesh.tessface_vertex_colors.new() if has_vc else None for i, face in enumerate(mesh.tessfaces): face.use_smooth = True face.material_index = new_fm_m[i] if uvlayer: uvlayer.data[i].uv1 = new_ft[i][0] uvlayer.data[i].uv2 = new_ft[i][1] uvlayer.data[i].uv3 = new_ft[i][2] uvlayer.data[i].uv4 = new_ft[i][3] if len(new_ft[i]) == 4 else (0,0) uvlayer.data[i].image = new_fm_i[i] if clayer: clayer.data[i].color1 = new_fc[0] clayer.data[i].color2 = new_fc[1] clayer.data[i].color3 = new_fc[2] clayer.data[i].color4 = new_fc[3] if len(new_fc[i]) == 4 else (1,1,1) # Vertex groups and armature modifier for skinning if has_vb and amtobj: for iqbone in iqmodel.bones: obj.vertex_groups.new(iqbone.name) for vgroup in obj.vertex_groups: for v, vbi in enumerate(new_vbi): for i, bi in enumerate(vbi): bw = new_vbw[v][i] if bi == vgroup.index: vgroup.add([v], bw, 'REPLACE') mod = obj.modifiers.new("Armature", 'ARMATURE') mod.object = amtobj mod.use_vertex_groups = True # Vertex groups for custom attributes def make_custom_vgroup(obj, name, size, vdata): print("importing custom attribute as vertex group", name) if size == 1: xg = obj.vertex_groups.new(name) for i, v in enumerate(vdata): xg.add([i], v[0], 'REPLACE') if size == 2: xg = obj.vertex_groups.new(name + ".x") yg = obj.vertex_groups.new(name + ".y") for i, v in enumerate(vdata): xg.add([i], v[0], 'REPLACE') yg.add([i], v[1], 'REPLACE') if size == 3: xg = obj.vertex_groups.new(name + ".x") yg = obj.vertex_groups.new(name + ".y") zg = obj.vertex_groups.new(name + ".z") for i, v in enumerate(vdata): xg.add([i], v[0], 'REPLACE') yg.add([i], v[1], 'REPLACE') zg.add([i], v[2], 'REPLACE') if size == 4: xg = obj.vertex_groups.new(name + ".x") yg = obj.vertex_groups.new(name + ".y") zg = obj.vertex_groups.new(name + ".z") wg = obj.vertex_groups.new(name + ".z") for i, v in enumerate(vdata): xg.add([i], v[0], 'REPLACE') yg.add([i], v[1], 'REPLACE') zg.add([i], v[2], 'REPLACE') wg.add([i], v[3], 'REPLACE') if has_v0: make_custom_vgroup(obj, iqmodel.custom_name[0], iqmodel.custom_size[0], new_v0) if has_v1: make_custom_vgroup(obj, iqmodel.custom_name[1], iqmodel.custom_size[1], new_v1) if has_v2: make_custom_vgroup(obj, iqmodel.custom_name[2], iqmodel.custom_size[2], new_v2) if has_v3: make_custom_vgroup(obj, iqmodel.custom_name[3], iqmodel.custom_size[3], new_v3) if has_v4: make_custom_vgroup(obj, iqmodel.custom_name[4], iqmodel.custom_size[4], new_v4) if has_v5: make_custom_vgroup(obj, iqmodel.custom_name[5], iqmodel.custom_size[5], new_v5) if has_v6: make_custom_vgroup(obj, iqmodel.custom_name[6], iqmodel.custom_size[6], new_v6) if has_v7: make_custom_vgroup(obj, iqmodel.custom_name[7], iqmodel.custom_size[7], new_v7) if has_v8: make_custom_vgroup(obj, iqmodel.custom_name[8], iqmodel.custom_size[8], new_v8) if has_v9: make_custom_vgroup(obj, iqmodel.custom_name[9], iqmodel.custom_size[9], new_v9) # Update mesh polygons from tessfaces mesh.update() # Must set normals after mesh.update() or they will be recalculated. mesh.vertices.foreach_set("normal", unpack_list(new_vn)) return obj
def write_mesh_data(self, entities=None, name="", default_material='Material'): mesh_key = (name, default_material) if mesh_key in self.component_meshes: return self.component_meshes[mesh_key] verts = [] faces = [] mat_index = [] mats = keep_offset() seen = keep_offset() uv_list = [] alpha = False # We assume object does not need alpha flag uvs_used = False # We assume no uvs need to be added for f in entities.faces: if f.material: mat_number = mats[f.material.name] else: mat_number = mats[default_material] if default_material != 'Material': f.st_scale = self.materials_scales[default_material] vs, tri, uvs = f.tessfaces mapping = {} for i, (v, uv) in enumerate(zip(vs, uvs)): l = len(seen) mapping[i] = seen[v] if len(seen) > l: verts.append(v) uvs.append(uv) for face in tri: f0, f1, f2 = face[0], face[1], face[2] if mapping[f2] == 0: ## eeekadoodle dance faces.append((mapping[f2], mapping[f0], mapping[f1])) uv_list.append((uvs[f2][0], uvs[f2][1], uvs[f0][0], uvs[f0][1], uvs[f1][0], uvs[f1][1], 0, 0)) else: faces.append((mapping[f0], mapping[f1], mapping[f2])) uv_list.append((uvs[f0][0], uvs[f0][1], uvs[f1][0], uvs[f1][1], uvs[f2][0], uvs[f2][1], 0, 0)) mat_index.append(mat_number) # verts, faces, uv_list, mat_index, mats = entities.get__triangles_lists(default_material) if len(verts) == 0: return None, False me = bpy.data.meshes.new(name) me.vertices.add(len(verts)) me.tessfaces.add(len(faces)) if len(mats) >= 1: mats_sorted = OrderedDict(sorted(mats.items(), key=lambda x: x[1])) for k in mats_sorted.keys(): bmat = self.materials[k] me.materials.append(bmat) if bmat.alpha < 1.0: alpha = True try: if 'Image Texture' in bmat.node_tree.nodes.keys(): uvs_used = True except AttributeError as e: uvs_used = False else: sketchupLog("WARNING OBJECT {} HAS NO MATERIAL".format(name)) me.vertices.foreach_set("co", unpack_list(verts)) me.tessfaces.foreach_set("vertices_raw", unpack_face_list(faces)) me.tessfaces.foreach_set("material_index", mat_index) if uvs_used: me.tessface_uv_textures.new() for i in range(len(faces)): me.tessface_uv_textures[0].data[i].uv_raw = uv_list[i] me.update(calc_edges=True) me.validate() self.component_meshes[mesh_key] = me, alpha return me, alpha
def pskimport(infile, importmesh, importbone, bDebugLogPSK, importmultiuvtextures): global DEBUGLOG DEBUGLOG = bDebugLogPSK print("--------------------------------------------------") print("---------SCRIPT EXECUTING PYTHON IMPORTER---------") print("--------------------------------------------------") print(" DEBUG Log:", bDebugLogPSK) print("Importing file: ", infile) pskfile = open(infile, 'rb') if (DEBUGLOG): logpath = infile.replace(".psk", ".txt") print("logpath:", logpath) logf = open(logpath, 'w') def printlog(strdata): if (DEBUGLOG): logf.write(strdata) objName = infile.split('\\')[-1].split('.')[0] me_ob = bpy.data.meshes.new(objName) print("objName:", objName) printlog(("New Mesh = " + me_ob.name + "\n")) #read general header indata = unpack('20s3i', pskfile.read(32)) #not using the general header at this time #================================================================================================== # vertex point #================================================================================================== #read the PNTS0000 header indata = unpack('20s3i', pskfile.read(32)) recCount = indata[3] printlog(("Nbr of PNTS0000 records: " + str(recCount) + "\n")) counter = 0 verts = [] verts2 = [] while counter < recCount: counter = counter + 1 indata = unpack('3f', pskfile.read(12)) #print(indata[0], indata[1], indata[2]) verts.extend([(indata[0], indata[1], indata[2])]) verts2.extend([(indata[0], indata[1], indata[2])]) #print([(indata[0], indata[1], indata[2])]) printlog( str(indata[0]) + "|" + str(indata[1]) + "|" + str(indata[2]) + "\n") #Tmsh.vertices.append(NMesh.Vert(indata[0], indata[1], indata[2])) #================================================================================================== # UV #================================================================================================== #read the VTXW0000 header indata = unpack('20s3i', pskfile.read(32)) recCount = indata[3] printlog("Nbr of VTXW0000 records: " + str(recCount) + "\n") counter = 0 UVCoords = [] #UVCoords record format = [index to PNTS, U coord, v coord] printlog("[index to PNTS, U coord, v coord]\n") while counter < recCount: counter = counter + 1 indata = unpack('hhffhh', pskfile.read(16)) UVCoords.append([indata[0], indata[2], indata[3]]) printlog( str(indata[0]) + "|" + str(indata[2]) + "|" + str(indata[3]) + "\n") #print('mat index %i', indata(4)) #print([indata[0], indata[2], indata[3]]) #print([indata[1], indata[2], indata[3]]) #================================================================================================== # Face #================================================================================================== #read the FACE0000 header indata = unpack('20s3i', pskfile.read(32)) recCount = indata[3] printlog("Nbr of FACE0000 records: " + str(recCount) + "\n") #PSK FACE0000 fields: WdgIdx1|WdgIdx2|WdgIdx3|MatIdx|AuxMatIdx|SmthGrp #associate MatIdx to an image, associate SmthGrp to a material SGlist = [] counter = 0 faces = [] faceuv = [] facesmooth = [] #the psk values are: nWdgIdx1|WdgIdx2|WdgIdx3|MatIdx|AuxMatIdx|SmthGrp printlog("nWdgIdx1|WdgIdx2|WdgIdx3|MatIdx|AuxMatIdx|SmthGrp \n") while counter < recCount: counter = counter + 1 indata = unpack('hhhbbi', pskfile.read(12)) printlog( str(indata[0]) + "|" + str(indata[1]) + "|" + str(indata[2]) + "|" + str(indata[3]) + "|" + str(indata[4]) + "|" + str(indata[5]) + "\n") #indata[0] = index of UVCoords #UVCoords[indata[0]]=[index to PNTS, U coord, v coord] #UVCoords[indata[0]][0] = index to PNTS PNTSA = UVCoords[indata[2]][0] PNTSB = UVCoords[indata[1]][0] PNTSC = UVCoords[indata[0]][0] #print(PNTSA, PNTSB, PNTSC) #face id vertex #faces.extend([0, 1, 2, 0]) faces.extend([(PNTSA, PNTSB, PNTSC, 0)]) uv = [] u0 = UVCoords[indata[2]][1] v0 = UVCoords[indata[2]][2] uv.append([u0, 1.0 - v0]) u1 = UVCoords[indata[1]][1] v1 = UVCoords[indata[1]][2] uv.append([u1, 1.0 - v1]) u2 = UVCoords[indata[0]][1] v2 = UVCoords[indata[0]][2] uv.append([u2, 1.0 - v2]) faceuv.append([uv, indata[3], indata[4], indata[5]]) #print("material:", indata[3]) #print("UV: ", u0, v0) #update the uv var of the last item in the Tmsh.faces list # which is the face just added above ##Tmsh.faces[-1].uv = [(u0, v0), (u1, v1), (u2, v2)] #print("smooth:",indata[5]) #collect a list of the smoothing groups facesmooth.append(indata[5]) #print(indata[5]) if SGlist.count(indata[5]) == 0: SGlist.append(indata[5]) print("smooth:", indata[5]) #assign a material index to the face #Tmsh.faces[-1].materialIndex = SGlist.index(indata[5]) printlog("Using Materials to represent PSK Smoothing Groups...\n") #========== # skip something... #========== #================================================================================================== # Material #================================================================================================== ## #read the MATT0000 header indata = unpack('20s3i', pskfile.read(32)) recCount = indata[3] printlog("Nbr of MATT0000 records: " + str(recCount) + "\n") printlog( " - Not importing any material data now. PSKs are texture wrapped! \n") counter = 0 materialcount = 0 while counter < recCount: counter = counter + 1 indata = unpack('64s6i', pskfile.read(88)) materialcount += 1 print("Material", counter) print("Mat name %s", indata[0]) ## #================================================================================================== # Bones (Armature) #================================================================================================== #read the REFSKEL0 header indata = unpack('20s3i', pskfile.read(32)) recCount = indata[3] printlog("Nbr of REFSKEL0 records: " + str(recCount) + "\n") #REFSKEL0 fields - Name|Flgs|NumChld|PrntIdx|Qw|Qx|Qy|Qz|LocX|LocY|LocZ|Lngth|XSize|YSize|ZSize Bns = [] bone = [] md5_bones = [] bni_dict = {} #================================================================================================== # Bone Data #================================================================================================== counter = 0 print("---PRASE--BONES---") printlog( "Name|Flgs|NumChld|PrntIdx|Qx|Qy|Qz|Qw|LocX|LocY|LocZ|Lngth|XSize|YSize|ZSize\n" ) while counter < recCount: indata = unpack('64s3i11f', pskfile.read(120)) #print( "DATA",str(indata)) bone.append(indata) createbone = md5_bone() #temp_name = indata[0][:30] temp_name = indata[0] temp_name = bytes.decode(temp_name) temp_name = temp_name.lstrip(" ") temp_name = temp_name.rstrip(" ") temp_name = temp_name.strip() temp_name = temp_name.strip(bytes.decode(b'\x00')) printlog(temp_name + "|" + str(indata[1]) + "|" + str(indata[2]) + "|" + str(indata[3]) + "|" + str(indata[4]) + "|" + str(indata[5]) + "|" + str(indata[6]) + "|" + str(indata[7]) + "|" + str(indata[8]) + "|" + str(indata[9]) + "|" + str(indata[10]) + "|" + str(indata[11]) + "|" + str(indata[12]) + "|" + str(indata[13]) + "|" + str(indata[14]) + "\n") createbone.name = temp_name createbone.bone_index = counter createbone.parent_index = indata[3] createbone.bindpos[0] = indata[8] createbone.bindpos[1] = indata[9] createbone.bindpos[2] = indata[10] createbone.scale[0] = indata[12] createbone.scale[1] = indata[13] createbone.scale[2] = indata[14] bni_dict[createbone.name] = createbone.bone_index #w,x,y,z if (counter == 0): #main parent createbone.bindmat = mathutils.Quaternion( (indata[7], -indata[4], -indata[5], -indata[6])).to_matrix() createbone.origmat = mathutils.Quaternion( (indata[7], -indata[4], -indata[5], -indata[6])).to_matrix() else: createbone.bindmat = mathutils.Quaternion( (indata[7], -indata[4], -indata[5], -indata[6])).to_matrix() createbone.origmat = mathutils.Quaternion( (indata[7], -indata[4], -indata[5], -indata[6])).to_matrix() createbone.bindmat = mathutils.Matrix.Translation(mathutils.Vector((indata[8], indata[9], indata[10]))) * \ createbone.bindmat.to_4x4() md5_bones.append(createbone) counter = counter + 1 bnstr = (str(indata[0])) Bns.append(bnstr) for pbone in md5_bones: pbone.parent = md5_bones[pbone.parent_index] for pbone in md5_bones: if pbone.name != pbone.parent.name: pbone.bindmat = pbone.parent.bindmat * pbone.bindmat #print(pbone.name) #print(pbone.bindmat) #print("end") else: pbone.bindmat = pbone.bindmat for pbone in md5_bones: pbone.head = getheadpos(pbone, md5_bones) for pbone in md5_bones: pbone.tail = gettailpos(pbone, md5_bones) for pbone in md5_bones: pbone.parent = md5_bones[pbone.parent_index].name bonecount = 0 for armbone in bone: temp_name = armbone[0][:30] #print ("BONE NAME: ", len(temp_name)) temp_name = str((temp_name)) #temp_name = temp_name[1] #print ("BONE NAME: ", temp_name) bonecount += 1 print("-------------------------") print("----Creating--Armature---") print("-------------------------") #================================================================================================ #Check armature if exist if so create or update or remove all and addnew bone #================================================================================================ #bpy.ops.object.mode_set(mode='OBJECT') meshname = "ArmObject" objectname = "armaturedata" # arm = None # UNUSED if importbone: obj = bpy.data.objects.get(meshname) # arm = obj # UNUSED if not obj: armdata = bpy.data.armatures.new(objectname) ob_new = bpy.data.objects.new(meshname, armdata) #ob_new = bpy.data.objects.new(meshname, 'ARMATURE') #ob_new.data = armdata bpy.context.collection.objects.link(ob_new) #bpy.ops.object.mode_set(mode='OBJECT') for i in bpy.context.scene.objects: i.select_set(False) #deselect all objects ob_new.select_set(True) #set current armature to edit the bone bpy.context.view_layer.objects.active = ob_new #set mode to able to edit the bone if bpy.ops.object.mode_set.poll(): bpy.ops.object.mode_set(mode='EDIT') #newbone = ob_new.data.edit_bones.new('test') #newbone.tail.y = 1 print("creating bone(s)") bpy.ops.object.mode_set(mode='OBJECT') for bone in md5_bones: #print(dir(bone)) bpy.ops.object.mode_set( mode='EDIT') #Go to edit mode for the bones newbone = ob_new.data.edit_bones.new(bone.name) #parent the bone #print("DRI:", dir(newbone)) parentbone = None #note bone location is set in the real space or global not local bonesize = bpy.types.Scene.unrealbonesize if bone.name != bone.parent: pos_x = bone.bindpos[0] pos_y = bone.bindpos[1] pos_z = bone.bindpos[2] #print("LINKING:" , bone.parent ,"j") parentbone = ob_new.data.edit_bones[bone.parent] newbone.parent = parentbone rotmatrix = bone.bindmat newbone.head.x = bone.head[0] newbone.head.y = bone.head[1] newbone.head.z = bone.head[2] newbone.tail.x = bone.tail[0] newbone.tail.y = bone.tail[1] newbone.tail.z = bone.tail[2] vecp = parentbone.tail - parentbone.head vecc = newbone.tail - newbone.head vecc.normalize() vecp.normalize() if vecp.dot(vecc) > -0.8: newbone.roll = parentbone.roll else: newbone.roll = -parentbone.roll else: rotmatrix = bone.bindmat newbone.head.x = bone.head[0] newbone.head.y = bone.head[1] newbone.head.z = bone.head[2] newbone.tail.x = bone.tail[0] newbone.tail.y = bone.tail[1] newbone.tail.z = bone.tail[2] newbone.roll = math.radians(90.0) """ vec = newbone.tail - newbone.head if vec.z > 0.0: newbone.roll = math.radians(90.0) else: newbone.roll = math.radians(-90.0) """ bpy.context.view_layer.update() #================================================================================================== #END BONE DATA BUILD #================================================================================================== VtxCol = [] for x in range(len(Bns)): #change the overall darkness of each material in a range between 0.1 and 0.9 tmpVal = ((float(x) + 1.0) / (len(Bns)) * 0.7) + 0.1 tmpVal = int(tmpVal * 256) tmpCol = [tmpVal, tmpVal, tmpVal, 0] #Change the color of each material slightly if x % 3 == 0: if tmpCol[0] < 128: tmpCol[0] += 60 else: tmpCol[0] -= 60 if x % 3 == 1: if tmpCol[1] < 128: tmpCol[1] += 60 else: tmpCol[1] -= 60 if x % 3 == 2: if tmpCol[2] < 128: tmpCol[2] += 60 else: tmpCol[2] -= 60 #Add the material to the mesh VtxCol.append(tmpCol) #================================================================================================== # Bone Weight #================================================================================================== #read the RAWW0000 header indata = unpack('20s3i', pskfile.read(32)) recCount = indata[3] printlog("Nbr of RAWW0000 records: " + str(recCount) + "\n") #RAWW0000 fields: Weight|PntIdx|BoneIdx RWghts = [] counter = 0 while counter < recCount: counter = counter + 1 indata = unpack('fii', pskfile.read(12)) RWghts.append([indata[1], indata[2], indata[0]]) #print("weight:", [indata[1], indata[2], indata[0]]) #RWghts fields = PntIdx|BoneIdx|Weight RWghts.sort() printlog("Vertex point and groups count =" + str(len(RWghts)) + "\n") printlog("PntIdx|BoneIdx|Weight") for vg in RWghts: printlog(str(vg[0]) + "|" + str(vg[1]) + "|" + str(vg[2]) + "\n") #Tmsh.update_tag() #set the Vertex Colors of the faces #face.v[n] = RWghts[0] #RWghts[1] = index of VtxCol """ for x in range(len(Tmsh.faces)): for y in range(len(Tmsh.faces[x].v)): #find v in RWghts[n][0] findVal = Tmsh.faces[x].v[y].index n = 0 while findVal != RWghts[n][0]: n = n + 1 TmpCol = VtxCol[RWghts[n][1]] #check if a vertex has more than one influence if n != len(RWghts) - 1: if RWghts[n][0] == RWghts[n + 1][0]: #if there is more than one influence, use the one with the greater influence #for simplicity only 2 influences are checked, 2nd and 3rd influences are usually very small if RWghts[n][2] < RWghts[n + 1][2]: TmpCol = VtxCol[RWghts[n + 1][1]] Tmsh.faces[x].col.append(NMesh.Col(TmpCol[0], TmpCol[1], TmpCol[2], 0)) """ if (DEBUGLOG): logf.close() #================================================================================================== #Building Mesh #================================================================================================== print("vertex:", len(verts), "faces:", len(faces)) print("vertex2:", len(verts2)) me_ob.vertices.add(len(verts2)) me_ob.tessfaces.add(len(faces)) me_ob.vertices.foreach_set("co", unpack_list(verts2)) me_ob.tessfaces.foreach_set("vertices_raw", unpack_list(faces)) for face in me_ob.tessfaces: face.use_smooth = facesmooth[face.index] """ Material setup coding. First the mesh has to be create first to get the uv texture setup working. -Create material(s) list in the psk pack data from the list.(to do list) -Append the material to the from create the mesh object. -Create Texture(s) -face loop for uv assign and assign material index """ bpy.ops.object.mode_set(mode='OBJECT') #=================================================================================================== #Material Setup #=================================================================================================== print("-------------------------") print("----Creating--Materials--") print("-------------------------") materialname = "pskmat" materials = [] for matcount in range(materialcount): #if texturedata is not None: matdata = bpy.data.materials.new(materialname + str(matcount)) #mtex = matdata.texture_slots.new() #mtex.texture = texture[matcount].data #print(type(texture[matcount].data)) #print(dir(mtex)) #print(dir(matdata)) #for texno in range(len( bpy.data.textures)): #print((bpy.data.textures[texno].name)) #print(dir(bpy.data.textures[texno])) #matdata.active_texture = bpy.data.textures[matcount - 1] #matdata.texture_coords = 'UV' #matdata.active_texture = texturedata materials.append(matdata) for material in materials: #add material to the mesh list of materials me_ob.materials.append(material) #=================================================================================================== #UV Setup #=================================================================================================== print("-------------------------") print("-- Creating UV Texture --") print("-------------------------") texture = [] # texturename = "text1" # UNUSED countm = 0 for countm in range(materialcount): psktexname = "psk" + str(countm) me_ob.uv_textures.new(name=psktexname) countm += 1 print("INIT UV TEXTURE...") _matcount = 0 #for mattexcount in materials: #print("MATERIAL ID:", _matcount) _textcount = 0 for uv in me_ob.tessface_uv_textures: # uv texture print("UV TEXTURE ID:", _textcount) print(dir(uv)) for face in me_ob.tessfaces: # face, uv #print(dir(face)) if faceuv[face.index][ 1] == _textcount: #if face index and texture index matches assign it mfaceuv = faceuv[face.index] #face index _uv1 = mfaceuv[0][0] #(0,0) uv.data[face.index].uv1 = mathutils.Vector( (_uv1[0], _uv1[1])) #set them _uv2 = mfaceuv[0][1] #(0,0) uv.data[face.index].uv2 = mathutils.Vector( (_uv2[0], _uv2[1])) #set them _uv3 = mfaceuv[0][2] #(0,0) uv.data[face.index].uv3 = mathutils.Vector( (_uv3[0], _uv3[1])) #set them else: #if not match zero them uv.data[face.index].uv1 = mathutils.Vector((0, 0)) #zero them uv.data[face.index].uv2 = mathutils.Vector((0, 0)) #zero them uv.data[face.index].uv3 = mathutils.Vector((0, 0)) #zero them _textcount += 1 #_matcount += 1 #print(matcount) print("END UV TEXTURE...") print("UV TEXTURE LEN:", len(texture)) #for tex in me_ob.uv_textures: #print("mesh tex:", dir(tex)) #print((tex.name)) #for face in me_ob.faces: #print(dir(face)) #=================================================================================================== # #=================================================================================================== obmesh = bpy.data.objects.new(objName, me_ob) #=================================================================================================== #Mesh Vertex Group bone weight #=================================================================================================== print("---- building bone weight mesh ----") #print(dir(ob_new.data.bones)) #create bone vertex group #deal with bone id for index number for bone in ob_new.data.bones: #print("names:", bone.name, ":", dir(bone)) #print("names:", bone.name) group = obmesh.vertex_groups.new(name=bone.name) for vgroup in obmesh.vertex_groups: #print(vgroup.name, ":", vgroup.index) for vgp in RWghts: #bone index if vgp[1] == bni_dict[vgroup.name]: #print(vgp) #[vertex id],weight vgroup.add([vgp[0]], vgp[2], 'ADD') #check if there is a material to set to if len(materials) > 0: obmesh.active_material = materials[0] #material setup tmp print("---- adding mesh to the scene ----") bpy.ops.object.mode_set(mode='OBJECT') #bpy.ops.object.select_pattern(extend=True, pattern=obmesh.name, case_sensitive=True) #bpy.ops.object.select_pattern(extend=True, pattern=ob_new.name, case_sensitive=True) #bpy.ops.object.select_name(name=str(obmesh.name)) #bpy.ops.object.select_name(name=str(ob_new.name)) #bpy.context.scene.objects.active = ob_new me_ob.update() bpy.context.collection.objects.link(obmesh) bpy.context.view_layer.update() obmesh.select_set(False) ob_new.select_set(False) obmesh.select_set(True) ob_new.select_set(True) bpy.ops.object.parent_set(type="ARMATURE") print("PSK2Blender completed")
def create_mesh(sobj, use_smooth_groups, fore_is_y, import_textures): """Takes a submodel and adds a Blender mesh.""" m = sobj.get_mesh() if fore_is_y: m.flip_yz() me = bpy.data.meshes.new("{}-mesh".format(sobj.name.decode())) vert_list = m.verts face_list = m.faces me.vertices.add(len(vert_list)) me.vertices.foreach_set('co', unpack_list(vert_list)) me.tessfaces.add(len(face_list)) me.tessfaces.foreach_set('vertices_raw', unpack_face_list(face_list)) invisible_faces = 0 if import_textures: m.flip_v() uvtex = me.tessface_uv_textures.new() uvtex.name = me.name for n, tf in enumerate(m.uv): uv_data = uvtex.data[n] uv_data.uv1 = tf[0] uv_data.uv2 = tf[1] uv_data.uv3 = tf[2] if len(tf) == 4: uv_data.uv4 = tf[3] if m.tex_ids[n] is not None: tex_slot = import_textures[m.tex_ids[n]].texture_slots[0] else: tex_slot = None if tex_slot is not None: uv_data.image = tex_slot.texture.image else: invisible_faces += 1 for mat in import_textures: me.materials.append(mat) for i, f in enumerate(me.tessfaces): if m.tex_ids[n] is not None: f.material_index = m.tex_ids[i] uvtex.active = True uvtex.active_render = True # index edges in a dict by a frozenset of the vert coords # that way we don't have to worry about messed up indicies when # adding the seams for smoothgroups (an edge might be [v1, v2] or [v2, v1]) me.update(calc_edges=True) if use_smooth_groups: m.calc_sharp() for e in me.edges: v1 = tuple(me.vertices[e.vertices[0]].co) v2 = tuple(me.vertices[e.vertices[1]].co) this_edge = (v1, v2) this_edge = frozenset(this_edge) e.use_edge_sharp = m.edges[this_edge] for f in me.polygons: f.use_smooth = True bobj = bpy.data.objects.new("Mesh", me) bobj['POF model id'] = sobj.model_id bobj.name = sobj.name.decode() if use_smooth_groups: bobj.modifiers.new("POF smoothing", "EDGE_SPLIT") if invisible_faces > 2 * (len(me.polygons) / 3): bobj.draw_type = 'WIRE' return bobj
def build_model2(mod,**kwargs): default_materials() oname = mod.filename.replace('.mesh','.000') mname = oname+'.'+'mesh' ps = mod.pset.ps us = mod.uset.ps mats = ['generic','concrete1','grass2'] fs_lookup = {} for fmx in range(len(mats)): fs_lookup[mats[fmx]] = fmx for gfx in mod.gfxmeshes: faces = [f for f in gfx.faces if not f is None] face_mats = [fs_lookup[gfx.fs_mats[f][1]] for f in faces] oloc = (0,0,0) #mesh = mesh_from_data(mname,ps,us,faces,face_mats,mats) #def mesh_from_data(name,ps,us,faces,face_mats,mats): mesh = bpy.data.meshes.new(mname) if not mats is None: [mesh.materials.append(materials[ma]) for ma in mats] mesh.vertices.add(len(ps)) mesh.vertices.foreach_set('co',unpack_list(ps)) mesh.tessfaces.add(len(faces)) mesh.tessfaces.foreach_set('vertices_raw',unpack_face_list(faces)) mesh.tessfaces.foreach_set('material_index',face_mats) mesh.tessface_uv_textures.new() for fdx in range(len(faces)): fa = faces[fdx] mesh.tessface_uv_textures[0].data[fdx].uv1 = tuple(us[fa[0]])[:-1] mesh.tessface_uv_textures[0].data[fdx].uv2 = tuple(us[fa[1]])[:-1] mesh.tessface_uv_textures[0].data[fdx].uv3 = tuple(us[fa[2]])[:-1] mesh.update() '''# faces = mod.gfxmeshes[0].faces face_mats = [fs_lookup[mod.gfxmeshes[0].fs_mats[f]] for f in faces] #face_mats = [0]*len(faces) #mats = ['generic'] oloc = (0,0,0) #mesh = mesh_from_data(mname,ps,us,faces,face_mats,mats) #def mesh_from_data(name,ps,us,faces,face_mats,mats): mesh = bpy.data.meshes.new(mname) if not mats is None: [mesh.materials.append(materials[ma]) for ma in mats] mesh.vertices.add(len(ps)) mesh.vertices.foreach_set('co',unpack_list(ps)) mesh.tessfaces.add(len(faces)) mesh.tessfaces.foreach_set('vertices_raw',unpack_face_list(faces)) mesh.tessfaces.foreach_set('material_index',face_mats) mesh.tessface_uv_textures.new() for fdx in range(len(faces)): fa = faces[fdx] mesh.tessface_uv_textures[0].data[fdx].uv1 = tuple(us[fa[0]])[:-1] mesh.tessface_uv_textures[0].data[fdx].uv2 = tuple(us[fa[1]])[:-1] mesh.tessface_uv_textures[0].data[fdx].uv3 = tuple(us[fa[2]])[:-1] mesh.update() '''# obj = object_from_mesh(oname,mesh,oloc,mats) object_to_scene(obj) return obj
def load(operator, context, filepath, global_clamp_size=0.0, use_verbose=False, dump_first_only=False, use_uv_map=True, use_diffuse_texture=True, use_normal_texture=True, use_specular_texture=True, use_computed_normals=False, use_shadeless=True, viz_normals=True, viz_blendweights=False, use_specular=True, global_matrix=None, use_debug_bones=False ): ''' Called by the user interface or another script. load_obj(path) - should give acceptable results. This function passes the file and sends the data off to be split into objects and then converted into mesh objects ''' print('\nimporting crf %r' % filepath) filepath = os.fsencode(filepath) if global_matrix is None: global_matrix = mathutils.Matrix() new_objects = [] # put new objects here time_main = time.time() print("\tparsing crf file...") time_sub = time.time() file = open(filepath, "rb") CRF = CRF_object() CRF.parse_bin(file) meshfile = CRF.meshfile bad_vertex_list = [] # start importing meshes for i in range(0, meshfile.num_meshes): verts_loc = [] verts_tex0 = [] verts_tex1 = [] faces = [] # tuples of the faces face_tex = [] # tuples of uv coordinates for faces vertex_normals = [] vertex_specular = [] vertex_blendweights1 = [] mesh = meshfile.meshes[i] faces = mesh.face_list #convert from DirectX to Blender face vertex ordering bad_mesh_vertex_list = [] for i in range(0, len(faces)): v1,v2,v3 = faces[i] # if there are duplicated vertices in triangle, delete that face by making all vertices the same if v1 == v2 or v1 == v3 or v2 == v3: print("Found a bad face %i, eliminating %i,%i,%i" % (i,v1,v2,v3)) faces[i] = (v3,v3,v3) bad_mesh_vertex_list.append(v1) bad_mesh_vertex_list.append(v2) bad_mesh_vertex_list.append(v3) else: faces[i] = (v3,v2,v1) bad_vertex_list.append(bad_mesh_vertex_list) for vertex in mesh.vertices0: verts_loc.append( (vertex.x_blend, vertex.y_blend, vertex.z_blend) ) verts_tex0.append( (vertex.u0_blend, vertex.v0_blend) ) vertex_normals.append( (vertex.normal_x_blend, vertex.normal_y_blend, vertex.normal_z_blend, vertex.normal_w_blend) ) vertex_specular.append( (vertex.specular_red_blend, vertex.specular_green_blend, vertex.specular_blue_blend, vertex.specular_alpha_blend) ) vertex_blendweights1.append( (vertex.blendweights1_x_blend, vertex.blendweights1_y_blend, vertex.blendweights1_z_blend, vertex.blendweights1_w_blend) ) # deselect all if bpy.ops.object.select_all.poll(): bpy.ops.object.select_all(action='DESELECT') # create blender mesh me = bpy.data.meshes.new("Dumped_Mesh") # create a new mesh object_name = os.path.splitext(os.path.basename(filepath))[0] ob = bpy.data.objects.new(os.fsdecode(object_name) + "_%i" % mesh.mesh_number, me) # Fill the mesh with verts, edges, faces me.vertices.add(len(verts_loc)) me.vertices.foreach_set("co", unpack_list(verts_loc)) me.tessfaces.add(len(faces)) me.tessfaces.foreach_set("vertices_raw", unpack_face_list(faces)) # use computed normals if use_computed_normals: for vertex, vertex_normal in zip(me.vertices, vertex_normals): print("vertex index", vertex.index, vertex_normal) vertex.normal = vertex_normal[0:3] # fill face uv texture array for face in ob.data.tessfaces: verts_in_face = face.vertices[:] if use_verbose: print("face index", face.index) print("normal", face.normal) for vert in verts_in_face: print("vert", vert, " vert co", ob.data.vertices[vert].co) print("Normal X:%s Y:%s Z:%s " % (vertex_normals[vert][0], vertex_normals[vert][1], vertex_normals[vert][2])) print("specular R:%s G:%s B:%s " % (vertex_specular[vert][0], vertex_specular[vert][1], vertex_specular[vert][2])) print("UV0: ", verts_tex0[vert]) print() i = face.index v1 = verts_in_face[0] v2 = verts_in_face[1] v3 = verts_in_face[2] face_tex.append([ verts_tex0[v1], verts_tex0[v2], verts_tex0[v3] ]) # start all optional tasks # add uv map if use_uv_map: uvMain = createTextureLayer("UV_Main", me, face_tex) # add texture if use_diffuse_texture or use_normal_texture or use_specular_texture: # create a material to which textures can be added mat = createMaterial('TexMat', use_shadeless, viz_normals) if use_diffuse_texture: diffuse_texture = mesh.materials.diffuse_texture diffuse_texture_filepath = findTextureFile(os.fsdecode(filepath), diffuse_texture.decode(sys.stdout.encoding)) print("Adding diffuse texture ", diffuse_texture_filepath) if diffuse_texture_filepath != None and diffuse_texture_filepath != "": addDiffuseTexture(diffuse_texture_filepath, mat) mat.use_transparency = True mat.alpha = 0 #TODO check model data for this param if use_normal_texture: normal_texture = mesh.materials.normal_texture normal_texture_filepath = findTextureFile(os.fsdecode(filepath), normal_texture.decode(sys.stdout.encoding)) print("Adding normals texture ", normal_texture_filepath) if normal_texture_filepath != None and normal_texture_filepath != "": addNormalTexture(normal_texture_filepath, mat) if use_specular_texture: specular_texture = mesh.materials.specular_texture specular_texture_filepath = findTextureFile(os.fsdecode(filepath), specular_texture.decode(sys.stdout.encoding)) print("Adding normals texture ", specular_texture_filepath) if specular_texture_filepath != None and specular_texture_filepath != "": addSpecularTexture(specular_texture_filepath, mat) ob.data.materials.append(mat) # viz normals # add specular constant if use_specular: vertex_specular = [] for vertex in mesh.vertices0: vertex_specular.append((vertex.specular_red_blend, vertex.specular_green_blend, vertex.specular_blue_blend, vertex.specular_alpha_blend)) setVertexSpecularColors(me, ob.data.tessfaces, vertex_specular) # if no materials exist, create one+ if len(ob.data.materials) == 0: mat = createMaterial('Specular', use_shadeless, viz_normals) mat.specular_color = mesh.materials.specular_constant ob.data.materials.append(mat) else: if mesh.materials.specular_constant != None: ob.data.materials[0].specular_color = mesh.materials.specular_constant else: ob.data.materials[0].specular_color = (1, 0, 0) print("Failed to find specular constnat! FIXME") print(ob.data.materials[0].specular_color) # viz blendweights # end all optional tasks me.update(calc_tessface=True, calc_edges=True) new_objects.append(ob) # end loop for importing meshes # import bones, create armature if CRF.footer.get_jointmap() != None: amt = bpy.data.armatures.new("Armature") amt_ob = bpy.data.objects.new("Armature", amt) scn = bpy.context.scene scn.objects.link(amt_ob) scn.objects.active = amt_ob amt_ob.select = True bpy.ops.object.mode_set(mode='EDIT') make_skel(amt, CRF.jointmap, 0) if use_debug_bones: for key,value in CRF.jointmap.bone_dict.items(): crf_joint = CRF.jointmap.joint_list[key] m = bone_transform(crf_joint.matrix) print("Bone %i\n" % key, m, "parent", crf_joint.parent_id) bpy.ops.mesh.primitive_uv_sphere_add(size=0.1, location=(0,0,0)) bpy.context.object.matrix_world = m bpy.context.object.name = "joint_%s_%s" % (key, CRF.jointmap.bone_dict[key].bone_name) bpy.ops.object.mode_set(mode='OBJECT') amt_ob.select = False time_new = time.time() print("%.4f sec" % (time_new - time_sub)) time_sub = time_new print('\tloading materials and images...') time_new = time.time() print("%.4f sec" % (time_new - time_sub)) time_sub = time_new # Create new obj scene = context.scene for ob,bad_vertices in zip(new_objects,bad_vertex_list): base = scene.objects.link(ob) base.select = True # we could apply this anywhere before scaling. ob.matrix_world = global_matrix #delete bad vertices bpy.context.scene.objects.active = ob ob.select = True bpy.ops.object.mode_set(mode='EDIT') bpy.ops.mesh.select_all(action='DESELECT') bpy.ops.object.mode_set(mode='OBJECT') for v in bad_vertices: print("Deleting vertex %i in %s" % (v, ob.name)) ob.data.vertices[v].select = True bpy.ops.object.mode_set(mode='EDIT') bpy.ops.mesh.delete(type='VERT') bpy.ops.object.mode_set(mode='OBJECT') if CRF.footer.get_jointmap() != None: #select objects, select armature as active, parent objects to armature bpy.ops.object.select_all(action='DESELECT') #deselect all object for ob in new_objects: print("in loop ", ob) ob.select = True bpy.context.scene.objects.active = amt_ob #the active object will be the parent of all selected object bpy.ops.object.parent_set(type='ARMATURE_NAME') # print all vertex groups for each object #for ob in new_objects: # print(ob.vertex_groups.keys()) #for ob in new_objects: # for v in ob.data.vertices: # print("number of groups", len(v.groups)) obj_id = 0 for ob in new_objects: if len(CRF.meshfile.meshes[obj_id].vertices1) != 0: for v in ob.data.vertices: CRF.meshfile.meshes[obj_id].vertices1[v.index].raw2blend() # convert blendindices = CRF.meshfile.meshes[obj_id].vertices1[v.index].blendindices blendweights = CRF.meshfile.meshes[obj_id].vertices1[v.index].blendweights_blend """ try: pos = blendindices.index(CRF.jointmap.bone_name_id_dict[b"Bone01_L_Forearm"]) blendindices = [blendindices[pos]+1] blendweights = [1.0] except ValueError: blendindices = [] blendindices = [] """ #print(blendindices, blendweights) for bi,bw in zip(blendindices, blendweights): #print("Assign vertex %s group %s with weight %s" % (v.index, bi, bw)) new_objects[obj_id].vertex_groups[bi].add([v.index], bw, 'ADD') obj_id+=1 scene.update() axis_min = [1000000000] * 3 axis_max = [-1000000000] * 3 if global_clamp_size: # Get all object bounds for ob in new_objects: for v in ob.bound_box: for axis, value in enumerate(v): if axis_min[axis] > value: axis_min[axis] = value if axis_max[axis] < value: axis_max[axis] = value # Scale objects max_axis = max(axis_max[0] - axis_min[0], axis_max[1] - axis_min[1], axis_max[2] - axis_min[2]) scale = 1.0 while global_clamp_size < max_axis * scale: scale = scale / 10.0 for obj in new_objects: obj.scale = scale, scale, scale time_new = time.time() print("finished importing: %r in %.4f sec." % (filepath, (time_new - time_main))) return {'FINISHED'}
def pskimport(infile,importmesh,importbone,bDebugLogPSK,importmultiuvtextures): global DEBUGLOG DEBUGLOG = bDebugLogPSK print ("--------------------------------------------------") print ("---------SCRIPT EXECUTING PYTHON IMPORTER---------") print ("--------------------------------------------------") print (" DEBUG Log:",bDebugLogPSK) print ("Importing file: ", infile) pskfile = open(infile,'rb') if (DEBUGLOG): logpath = infile.replace(".psk", ".txt") print("logpath:",logpath) logf = open(logpath,'w') def printlog(strdata): if (DEBUGLOG): logf.write(strdata) objName = infile.split('\\')[-1].split('.')[0] me_ob = bpy.data.meshes.new(objName) print("objName:",objName) printlog(("New Mesh = " + me_ob.name + "\n")) #read general header indata = unpack('20s3i', pskfile.read(32)) #not using the general header at this time #================================================================================================== # vertex point #================================================================================================== #read the PNTS0000 header indata = unpack('20s3i', pskfile.read(32)) recCount = indata[3] printlog(("Nbr of PNTS0000 records: " + str(recCount) + "\n")) counter = 0 verts = [] verts2 = [] while counter < recCount: counter = counter + 1 indata = unpack('3f', pskfile.read(12)) #print(indata[0], indata[1], indata[2]) verts.extend([(indata[0], indata[1], indata[2])]) verts2.extend([(indata[0], indata[1], indata[2])]) #print([(indata[0], indata[1], indata[2])]) printlog(str(indata[0]) + "|" + str(indata[1]) + "|" + str(indata[2]) + "\n") #Tmsh.vertices.append(NMesh.Vert(indata[0], indata[1], indata[2])) #================================================================================================== # UV #================================================================================================== #read the VTXW0000 header indata = unpack('20s3i', pskfile.read(32)) recCount = indata[3] printlog("Nbr of VTXW0000 records: " + str(recCount)+ "\n") counter = 0 UVCoords = [] #UVCoords record format = [index to PNTS, U coord, v coord] printlog("[index to PNTS, U coord, v coord]\n"); while counter < recCount: counter = counter + 1 indata = unpack('hhffhh', pskfile.read(16)) UVCoords.append([indata[0], indata[2], indata[3]]) printlog(str(indata[0]) + "|" + str(indata[2]) + "|" + str(indata[3]) + "\n") #print('mat index %i', indata(4)) #print([indata[0], indata[2], indata[3]]) #print([indata[1], indata[2], indata[3]]) #================================================================================================== # Face #================================================================================================== #read the FACE0000 header indata = unpack('20s3i', pskfile.read(32)) recCount = indata[3] printlog("Nbr of FACE0000 records: " + str(recCount) + "\n") #PSK FACE0000 fields: WdgIdx1|WdgIdx2|WdgIdx3|MatIdx|AuxMatIdx|SmthGrp #associate MatIdx to an image, associate SmthGrp to a material SGlist = [] counter = 0 faces = [] faceuv = [] facesmooth = [] #the psk values are: nWdgIdx1|WdgIdx2|WdgIdx3|MatIdx|AuxMatIdx|SmthGrp printlog("nWdgIdx1|WdgIdx2|WdgIdx3|MatIdx|AuxMatIdx|SmthGrp \n") while counter < recCount: counter = counter + 1 indata = unpack('hhhbbi', pskfile.read(12)) printlog(str(indata[0]) + "|" + str(indata[1]) + "|" + str(indata[2]) + "|" + str(indata[3]) + "|" + str(indata[4]) + "|" + str(indata[5]) + "\n") #indata[0] = index of UVCoords #UVCoords[indata[0]]=[index to PNTS, U coord, v coord] #UVCoords[indata[0]][0] = index to PNTS PNTSA = UVCoords[indata[2]][0] PNTSB = UVCoords[indata[1]][0] PNTSC = UVCoords[indata[0]][0] #print(PNTSA, PNTSB, PNTSC) #face id vertex #faces.extend([0, 1, 2, 0]) faces.extend([(PNTSA, PNTSB, PNTSC, 0)]) uv = [] u0 = UVCoords[indata[2]][1] v0 = UVCoords[indata[2]][2] uv.append([u0, 1.0 - v0]) u1 = UVCoords[indata[1]][1] v1 = UVCoords[indata[1]][2] uv.append([u1, 1.0 - v1]) u2 = UVCoords[indata[0]][1] v2 = UVCoords[indata[0]][2] uv.append([u2, 1.0 - v2]) faceuv.append([uv, indata[3], indata[4], indata[5]]) #print("material:", indata[3]) #print("UV: ", u0, v0) #update the uv var of the last item in the Tmsh.faces list # which is the face just added above ##Tmsh.faces[-1].uv = [(u0, v0), (u1, v1), (u2, v2)] #print("smooth:",indata[5]) #collect a list of the smoothing groups facesmooth.append(indata[5]) #print(indata[5]) if SGlist.count(indata[5]) == 0: SGlist.append(indata[5]) print("smooth:", indata[5]) #assign a material index to the face #Tmsh.faces[-1].materialIndex = SGlist.index(indata[5]) printlog("Using Materials to represent PSK Smoothing Groups...\n") #========== # skip something... #========== #================================================================================================== # Material #================================================================================================== ## #read the MATT0000 header indata = unpack('20s3i', pskfile.read(32)) recCount = indata[3] printlog("Nbr of MATT0000 records: " + str(recCount) + "\n" ) printlog(" - Not importing any material data now. PSKs are texture wrapped! \n") counter = 0 materialcount = 0 while counter < recCount: counter = counter + 1 indata = unpack('64s6i', pskfile.read(88)) materialcount += 1 print("Material", counter) print("Mat name %s", indata[0]) ## #================================================================================================== # Bones (Armature) #================================================================================================== #read the REFSKEL0 header indata = unpack('20s3i', pskfile.read(32)) recCount = indata[3] printlog( "Nbr of REFSKEL0 records: " + str(recCount) + "\n") #REFSKEL0 fields - Name|Flgs|NumChld|PrntIdx|Qw|Qx|Qy|Qz|LocX|LocY|LocZ|Lngth|XSize|YSize|ZSize Bns = [] bone = [] md5_bones = [] bni_dict = {} #================================================================================================== # Bone Data #================================================================================================== counter = 0 print ("---PRASE--BONES---") printlog("Name|Flgs|NumChld|PrntIdx|Qx|Qy|Qz|Qw|LocX|LocY|LocZ|Lngth|XSize|YSize|ZSize\n") while counter < recCount: indata = unpack('64s3i11f', pskfile.read(120)) #print( "DATA",str(indata)) bone.append(indata) createbone = md5_bone() #temp_name = indata[0][:30] temp_name = indata[0] temp_name = bytes.decode(temp_name) temp_name = temp_name.lstrip(" ") temp_name = temp_name.rstrip(" ") temp_name = temp_name.strip() temp_name = temp_name.strip( bytes.decode(b'\x00')) printlog(temp_name + "|" + str(indata[1]) + "|" + str(indata[2]) + "|" + str(indata[3]) + "|" + str(indata[4]) + "|" + str(indata[5]) + "|" + str(indata[6]) + "|" + str(indata[7]) + "|" + str(indata[8]) + "|" + str(indata[9]) + "|" + str(indata[10]) + "|" + str(indata[11]) + "|" + str(indata[12]) + "|" + str(indata[13]) + "|" + str(indata[14]) + "\n") createbone.name = temp_name createbone.bone_index = counter createbone.parent_index = indata[3] createbone.bindpos[0] = indata[8] createbone.bindpos[1] = indata[9] createbone.bindpos[2] = indata[10] createbone.scale[0] = indata[12] createbone.scale[1] = indata[13] createbone.scale[2] = indata[14] bni_dict[createbone.name] = createbone.bone_index #w,x,y,z if (counter == 0):#main parent createbone.bindmat = mathutils.Quaternion((indata[7], -indata[4], -indata[5], -indata[6])).to_matrix() createbone.origmat = mathutils.Quaternion((indata[7], -indata[4], -indata[5], -indata[6])).to_matrix() else: createbone.bindmat = mathutils.Quaternion((indata[7], -indata[4], -indata[5], -indata[6])).to_matrix() createbone.origmat = mathutils.Quaternion((indata[7], -indata[4], -indata[5], -indata[6])).to_matrix() createbone.bindmat = mathutils.Matrix.Translation(mathutils.Vector((indata[8], indata[9], indata[10]))) * \ createbone.bindmat.to_4x4() md5_bones.append(createbone) counter = counter + 1 bnstr = (str(indata[0])) Bns.append(bnstr) for pbone in md5_bones: pbone.parent = md5_bones[pbone.parent_index] for pbone in md5_bones: if pbone.name != pbone.parent.name: pbone.bindmat = pbone.parent.bindmat * pbone.bindmat #print(pbone.name) #print(pbone.bindmat) #print("end") else: pbone.bindmat = pbone.bindmat for pbone in md5_bones: pbone.head = getheadpos(pbone, md5_bones) for pbone in md5_bones: pbone.tail = gettailpos(pbone, md5_bones) for pbone in md5_bones: pbone.parent = md5_bones[pbone.parent_index].name bonecount = 0 for armbone in bone: temp_name = armbone[0][:30] #print ("BONE NAME: ", len(temp_name)) temp_name=str((temp_name)) #temp_name = temp_name[1] #print ("BONE NAME: ", temp_name) bonecount += 1 print ("-------------------------") print ("----Creating--Armature---") print ("-------------------------") #================================================================================================ #Check armature if exist if so create or update or remove all and addnew bone #================================================================================================ #bpy.ops.object.mode_set(mode='OBJECT') meshname ="ArmObject" objectname = "armaturedata" # arm = None # UNUSED if importbone: obj = bpy.data.objects.get(meshname) # arm = obj # UNUSED if not obj: armdata = bpy.data.armatures.new(objectname) ob_new = bpy.data.objects.new(meshname, armdata) #ob_new = bpy.data.objects.new(meshname, 'ARMATURE') #ob_new.data = armdata bpy.context.scene.objects.link(ob_new) #bpy.ops.object.mode_set(mode='OBJECT') for i in bpy.context.scene.objects: i.select = False #deselect all objects ob_new.select = True #set current armature to edit the bone bpy.context.scene.objects.active = ob_new #set mode to able to edit the bone if bpy.ops.object.mode_set.poll(): bpy.ops.object.mode_set(mode='EDIT') #newbone = ob_new.data.edit_bones.new('test') #newbone.tail.y = 1 print("creating bone(s)") bpy.ops.object.mode_set(mode='OBJECT') for bone in md5_bones: #print(dir(bone)) bpy.ops.object.mode_set(mode='EDIT')#Go to edit mode for the bones newbone = ob_new.data.edit_bones.new(bone.name) #parent the bone #print("DRI:", dir(newbone)) parentbone = None #note bone location is set in the real space or global not local bonesize = bpy.types.Scene.unrealbonesize if bone.name != bone.parent: pos_x = bone.bindpos[0] pos_y = bone.bindpos[1] pos_z = bone.bindpos[2] #print("LINKING:" , bone.parent ,"j") parentbone = ob_new.data.edit_bones[bone.parent] newbone.parent = parentbone rotmatrix = bone.bindmat newbone.head.x = bone.head[0] newbone.head.y = bone.head[1] newbone.head.z = bone.head[2] newbone.tail.x = bone.tail[0] newbone.tail.y = bone.tail[1] newbone.tail.z = bone.tail[2] vecp = parentbone.tail - parentbone.head vecc = newbone.tail - newbone.head vecc.normalize() vecp.normalize() if vecp.dot(vecc) > -0.8: newbone.roll = parentbone.roll else: newbone.roll = - parentbone.roll else: rotmatrix = bone.bindmat newbone.head.x = bone.head[0] newbone.head.y = bone.head[1] newbone.head.z = bone.head[2] newbone.tail.x = bone.tail[0] newbone.tail.y = bone.tail[1] newbone.tail.z = bone.tail[2] newbone.roll = math.radians(90.0) """ vec = newbone.tail - newbone.head if vec.z > 0.0: newbone.roll = math.radians(90.0) else: newbone.roll = math.radians(-90.0) """ bpy.context.scene.update() #================================================================================================== #END BONE DATA BUILD #================================================================================================== VtxCol = [] for x in range(len(Bns)): #change the overall darkness of each material in a range between 0.1 and 0.9 tmpVal = ((float(x) + 1.0) / (len(Bns)) * 0.7) + 0.1 tmpVal = int(tmpVal * 256) tmpCol = [tmpVal, tmpVal, tmpVal, 0] #Change the color of each material slightly if x % 3 == 0: if tmpCol[0] < 128: tmpCol[0] += 60 else: tmpCol[0] -= 60 if x % 3 == 1: if tmpCol[1] < 128: tmpCol[1] += 60 else: tmpCol[1] -= 60 if x % 3 == 2: if tmpCol[2] < 128: tmpCol[2] += 60 else: tmpCol[2] -= 60 #Add the material to the mesh VtxCol.append(tmpCol) #================================================================================================== # Bone Weight #================================================================================================== #read the RAWW0000 header indata = unpack('20s3i', pskfile.read(32)) recCount = indata[3] printlog("Nbr of RAWW0000 records: " + str(recCount) +"\n") #RAWW0000 fields: Weight|PntIdx|BoneIdx RWghts = [] counter = 0 while counter < recCount: counter = counter + 1 indata = unpack('fii', pskfile.read(12)) RWghts.append([indata[1], indata[2], indata[0]]) #print("weight:", [indata[1], indata[2], indata[0]]) #RWghts fields = PntIdx|BoneIdx|Weight RWghts.sort() printlog("Vertex point and groups count =" + str(len(RWghts)) + "\n") printlog("PntIdx|BoneIdx|Weight") for vg in RWghts: printlog(str(vg[0]) + "|" + str(vg[1]) + "|" + str(vg[2]) + "\n") #Tmsh.update_tag() #set the Vertex Colors of the faces #face.v[n] = RWghts[0] #RWghts[1] = index of VtxCol """ for x in range(len(Tmsh.faces)): for y in range(len(Tmsh.faces[x].v)): #find v in RWghts[n][0] findVal = Tmsh.faces[x].v[y].index n = 0 while findVal != RWghts[n][0]: n = n + 1 TmpCol = VtxCol[RWghts[n][1]] #check if a vertex has more than one influence if n != len(RWghts) - 1: if RWghts[n][0] == RWghts[n + 1][0]: #if there is more than one influence, use the one with the greater influence #for simplicity only 2 influences are checked, 2nd and 3rd influences are usually very small if RWghts[n][2] < RWghts[n + 1][2]: TmpCol = VtxCol[RWghts[n + 1][1]] Tmsh.faces[x].col.append(NMesh.Col(TmpCol[0], TmpCol[1], TmpCol[2], 0)) """ if (DEBUGLOG): logf.close() #================================================================================================== #Building Mesh #================================================================================================== print("vertex:", len(verts), "faces:", len(faces)) print("vertex2:", len(verts2)) me_ob.vertices.add(len(verts2)) me_ob.tessfaces.add(len(faces)) me_ob.vertices.foreach_set("co", unpack_list(verts2)) me_ob.tessfaces.foreach_set("vertices_raw", unpack_list( faces)) for face in me_ob.tessfaces: face.use_smooth = facesmooth[face.index] """ Material setup coding. First the mesh has to be create first to get the uv texture setup working. -Create material(s) list in the psk pack data from the list.(to do list) -Append the material to the from create the mesh object. -Create Texture(s) -face loop for uv assign and assign material index """ bpy.ops.object.mode_set(mode='OBJECT') #=================================================================================================== #Material Setup #=================================================================================================== print ("-------------------------") print ("----Creating--Materials--") print ("-------------------------") materialname = "pskmat" materials = [] for matcount in range(materialcount): #if texturedata is not None: matdata = bpy.data.materials.new(materialname + str(matcount)) #mtex = matdata.texture_slots.new() #mtex.texture = texture[matcount].data #print(type(texture[matcount].data)) #print(dir(mtex)) #print(dir(matdata)) #for texno in range(len( bpy.data.textures)): #print((bpy.data.textures[texno].name)) #print(dir(bpy.data.textures[texno])) #matdata.active_texture = bpy.data.textures[matcount - 1] #matdata.texture_coords = 'UV' #matdata.active_texture = texturedata materials.append(matdata) for material in materials: #add material to the mesh list of materials me_ob.materials.append(material) #=================================================================================================== #UV Setup #=================================================================================================== print ("-------------------------") print ("-- Creating UV Texture --") print ("-------------------------") texture = [] # texturename = "text1" # UNUSED countm = 0 for countm in range(materialcount): psktexname = "psk" + str(countm) me_ob.uv_textures.new(name=psktexname) countm += 1 print("INIT UV TEXTURE...") _matcount = 0 #for mattexcount in materials: #print("MATERAIL ID:", _matcount) _textcount = 0 for uv in me_ob.tessface_uv_textures: # uv texture print("UV TEXTURE ID:",_textcount) print(dir(uv)) for face in me_ob.tessfaces:# face, uv #print(dir(face)) if faceuv[face.index][1] == _textcount: #if face index and texture index matches assign it mfaceuv = faceuv[face.index] #face index _uv1 = mfaceuv[0][0] #(0,0) uv.data[face.index].uv1 = mathutils.Vector((_uv1[0], _uv1[1])) #set them _uv2 = mfaceuv[0][1] #(0,0) uv.data[face.index].uv2 = mathutils.Vector((_uv2[0], _uv2[1])) #set them _uv3 = mfaceuv[0][2] #(0,0) uv.data[face.index].uv3 = mathutils.Vector((_uv3[0], _uv3[1])) #set them else: #if not match zero them uv.data[face.index].uv1 = mathutils.Vector((0, 0)) #zero them uv.data[face.index].uv2 = mathutils.Vector((0, 0)) #zero them uv.data[face.index].uv3 = mathutils.Vector((0, 0)) #zero them _textcount += 1 #_matcount += 1 #print(matcount) print("END UV TEXTURE...") print("UV TEXTURE LEN:", len(texture)) #for tex in me_ob.uv_textures: #print("mesh tex:", dir(tex)) #print((tex.name)) #for face in me_ob.faces: #print(dir(face)) #=================================================================================================== # #=================================================================================================== obmesh = bpy.data.objects.new(objName,me_ob) #=================================================================================================== #Mesh Vertex Group bone weight #=================================================================================================== print("---- building bone weight mesh ----") #print(dir(ob_new.data.bones)) #create bone vertex group #deal with bone id for index number for bone in ob_new.data.bones: #print("names:", bone.name, ":", dir(bone)) #print("names:", bone.name) group = obmesh.vertex_groups.new(bone.name) for vgroup in obmesh.vertex_groups: #print(vgroup.name, ":", vgroup.index) for vgp in RWghts: #bone index if vgp[1] == bni_dict[vgroup.name]: #print(vgp) #[vertex id],weight vgroup.add([vgp[0]], vgp[2], 'ADD') #check if there is a material to set to if len(materials) > 0: obmesh.active_material = materials[0] #material setup tmp print("---- adding mesh to the scene ----") bpy.ops.object.mode_set(mode='OBJECT') #bpy.ops.object.select_pattern(extend=True, pattern=obmesh.name, case_sensitive=True) #bpy.ops.object.select_pattern(extend=True, pattern=ob_new.name, case_sensitive=True) #bpy.ops.object.select_name(name=str(obmesh.name)) #bpy.ops.object.select_name(name=str(ob_new.name)) #bpy.context.scene.objects.active = ob_new me_ob.update() bpy.context.scene.objects.link(obmesh) bpy.context.scene.update() obmesh.select = False ob_new.select = False obmesh.select = True ob_new.select = True bpy.ops.object.parent_set(type="ARMATURE") print ("PSK2Blender completed")
def build_blender_data(self, blender_context): from mdl_node_bone import MDL_NODE_BONE import bpy from bpy_extras.io_utils import unpack_list, unpack_face_list from bpy_extras.image_utils import load_image super(MDL_NODE_VOLUMEVIEW, self).build_blender_data(blender_context) if self.ply: print(type(self).__name__ + ".build_blender_data()") bone_name = None naterial_node = None diffuse_node = None parent_node = self.parent # Get parents bone name while True: # Check if we found a bone node if type(parent_node) == MDL_NODE_BONE: bone_name = parent_node.bone_name break # Check if we reached the root node without finding a bone node elif parent_node == None: raise Exception("No parent bone node found") # Otherwise get the next parent else: parent_node = parent_node.parent # Create a new mesh with our parents bone name self.blender_mesh = bpy.data.meshes.new(bone_name) # Load vertices data into the mesh self.blender_mesh.vertices.add(len(self.ply.positions)) self.blender_mesh.vertices.foreach_set("co", unpack_list(self.ply.positions)) # Load face data into the mesh self.blender_mesh.tessfaces.add(len(self.ply.indices)) self.blender_mesh.tessfaces.foreach_set("vertices", unpack_list(self.ply.indices)) # Validate mesh self.blender_mesh.validate() # Update mesh self.blender_mesh.update(calc_edges=True) # Create a new UV layer self.blender_mesh.uv_textures.new() # Get the mesh UV layer uv_layer = self.blender_mesh.uv_layers.active # Process all faces of the mesh for face in self.blender_mesh.polygons: # Process all loops of the mesh for loop_index in face.loop_indices: # Use loop_index to get to the actual loop and then get the vertex index from it vertex_index = self.blender_mesh.loops[loop_index].vertex_index # With the vertex index, append the UV data from that vertex to the UV array uv_layer.data[loop_index].uv = self.ply.UVs[vertex_index] # Create blender object ob = bpy.data.objects.new(name=bone_name, object_data=self.blender_mesh) parent_node.blender_object_name = ob.name # Create the vertex groups for mesh in self.ply.meshes: vg = ob.vertex_groups.new(name=bone_name+'#'+mesh.material_file) vg.add(mesh.indices, 1.0, 'ADD') # Find material child nodes for material in self.nodes: if type(material) == MDL_NODE_MATERIAL: # Find texture child nodes for texture in material.nodes: if type(texture) == MDL_NODE_DIFFUSE: # Create a material mat = bpy.data.materials.new(name=bone_name+'#'+material.material_file) # Add the material to the object ob.data.materials.append(mat) # Create a texture tex = bpy.data.textures.new(name=bone_name+'#'+texture.texturename, type="IMAGE") # Apply image to the texture tex.image = texture.blender_images[texture.texturename] # Create a new texture slot inside the material tex_slot = mat.texture_slots.add() # Add the texture to the newly created slot tex_slot.texture = tex
def makeObject(self): print("Creating mesh", end='') # Create the mesh mesh = bpy.data.meshes.new(self.name) # Prepare vertices and faces mesh.vertices.add(self.numVerts) mesh.tessfaces.add(self.numTris) print('.', end='') # Verts mesh.vertices.foreach_set("co", unpack_list(self.frames[0])) mesh.transform(Matrix.Rotation(-pi / 2, 4, 'Z')) print('.', end='') # Tris mesh.tessfaces.foreach_set("vertices_raw", unpack_face_list([face[0] for face in self.tris])) print('.', end='') # Skins mesh.tessface_uv_textures.new() if self.numSkins > 0: material = bpy.data.materials.new(self.name) for skin in self.skins: skinImg = Util.loadImage(skin, self.filePath) if skinImg == None: skinImg = bpy.data.images.new(os.path.join(self.filePath, skin), self.skinWidth, self.skinHeight) skinImg.mapping = 'UV' skinImg.name = skin skinTex = bpy.data.textures.new(self.name + skin, type='IMAGE') skinTex.image = skinImg matTex = material.texture_slots.add() matTex.texture = skinTex matTex.texture_coords = 'UV' matTex.use_map_color_diffuse = True matTex.use_map_alpha = True matTex.uv_layer = mesh.tessface_uv_textures[0].name mesh.materials.append(material) print('.', end='') # UV mesh.tessface_uv_textures[0].data.foreach_set("uv_raw", unpack_list([self.uvs[i] for i in unpack_face_list([face[1] for face in self.tris])])) if self.numSkins > 0: image = mesh.materials[0].texture_slots[0].texture.image if image != None: for uv in mesh.tessface_uv_textures[0].data: uv.image = image print('.', end='') mesh.validate() mesh.update() obj = bpy.data.objects.new(mesh.name, mesh) base = bpy.context.scene.objects.link(obj) bpy.context.scene.objects.active = obj base.select = True print("Done") # Animate if self.options.fImportAnimation and self.numFrames > 1: for i, frame in enumerate(self.frames): progressStatus = i / self.numFrames * 100 #bpy.context.scene.frame_set(i + 1) obj.shape_key_add(from_mix=False) mesh.vertices.foreach_set("co", unpack_list(frame)) mesh.transform(Matrix.Rotation(-pi / 2, 4, 'Z')) mesh.shape_keys.key_blocks[i].value = 1.0 mesh.shape_keys.key_blocks[i].keyframe_insert("value", frame=i + 1) if i < len(self.frames) - 1: mesh.shape_keys.key_blocks[i].value = 0.0 mesh.shape_keys.key_blocks[i].keyframe_insert("value", frame=i + 2) if i > 0: mesh.shape_keys.key_blocks[i].value = 0.0 mesh.shape_keys.key_blocks[i].keyframe_insert("value", frame=i) print("Animating - progress: %3i%%\r" % int(progressStatus), end='') print("Animating - progress: 100%.") bpy.context.scene.update() print("Model imported")
def create_mesh(new_objects, has_ngons, use_ngons, use_edges, verts_loc, verts_tex, faces, unique_materials, unique_material_images, unique_smooth_groups, vertex_groups, dataname, ): """ Takes all the data gathered and generates a mesh, adding the new object to new_objects deals with ngons, sharp edges and assigning materials """ from bpy_extras.mesh_utils import ngon_tessellate if not has_ngons: use_ngons = False if unique_smooth_groups: sharp_edges = {} smooth_group_users = {context_smooth_group: {} for context_smooth_group in list(unique_smooth_groups.keys())} context_smooth_group_old = -1 # Split ngons into tri's fgon_edges = set() # Used for storing fgon keys if use_edges: edges = [] context_object = None # reverse loop through face indices for f_idx in range(len(faces) - 1, -1, -1): (face_vert_loc_indices, face_vert_tex_indices, context_material, context_smooth_group, context_object, ) = faces[f_idx] len_face_vert_loc_indices = len(face_vert_loc_indices) if len_face_vert_loc_indices == 1: faces.pop(f_idx) # cant add single vert faces elif not face_vert_tex_indices or len_face_vert_loc_indices == 2: # faces that have no texture coords are lines if use_edges: # generators are better in python 2.4+ but can't be used in 2.3 # edges.extend( (face_vert_loc_indices[i], face_vert_loc_indices[i+1]) for i in xrange(len_face_vert_loc_indices-1) ) edges.extend([(face_vert_loc_indices[i], face_vert_loc_indices[i + 1]) for i in range(len_face_vert_loc_indices - 1)]) faces.pop(f_idx) else: # Smooth Group if unique_smooth_groups and context_smooth_group: # Is a part of of a smooth group and is a face if context_smooth_group_old is not context_smooth_group: edge_dict = smooth_group_users[context_smooth_group] context_smooth_group_old = context_smooth_group for i in range(len_face_vert_loc_indices): i1 = face_vert_loc_indices[i] i2 = face_vert_loc_indices[i - 1] if i1 > i2: i1, i2 = i2, i1 try: edge_dict[i1, i2] += 1 except KeyError: edge_dict[i1, i2] = 1 # NGons into triangles if has_ngons and len_face_vert_loc_indices > 4: ngon_face_indices = ngon_tessellate(verts_loc, face_vert_loc_indices) faces.extend([([face_vert_loc_indices[ngon[0]], face_vert_loc_indices[ngon[1]], face_vert_loc_indices[ngon[2]], ], [face_vert_tex_indices[ngon[0]], face_vert_tex_indices[ngon[1]], face_vert_tex_indices[ngon[2]], ], context_material, context_smooth_group, context_object, ) for ngon in ngon_face_indices] ) # edges to make ngons if use_ngons: edge_users = {} for ngon in ngon_face_indices: for i in (0, 1, 2): i1 = face_vert_loc_indices[ngon[i]] i2 = face_vert_loc_indices[ngon[i - 1]] if i1 > i2: i1, i2 = i2, i1 try: edge_users[i1, i2] += 1 except KeyError: edge_users[i1, i2] = 1 for key, users in edge_users.items(): if users > 1: fgon_edges.add(key) # remove all after 3, means we dont have to pop this one. faces.pop(f_idx) # Build sharp edges if unique_smooth_groups: for edge_dict in list(smooth_group_users.values()): for key, users in list(edge_dict.items()): if users == 1: # This edge is on the boundry of a group sharp_edges[key] = None # map the material names to an index material_mapping = {name: i for i, name in enumerate(unique_materials)} # enumerate over unique_materials keys() materials = [None] * len(unique_materials) for name, index in list(material_mapping.items()): materials[index] = unique_materials[name] me = bpy.data.meshes.new(dataname.decode('utf-8', "replace")) # make sure the list isnt too big for material in materials: me.materials.append(material) me.vertices.add(len(verts_loc)) me.tessfaces.add(len(faces)) # verts_loc is a list of (x, y, z) tuples me.vertices.foreach_set("co", unpack_list(verts_loc)) # faces is a list of (vert_indices, texco_indices, ...) tuples # XXX faces should contain either 3 or 4 verts # XXX no check for valid face indices me.tessfaces.foreach_set("vertices_raw", unpack_face_list([f[0] for f in faces])) if verts_tex and me.tessfaces: me.tessface_uv_textures.new() context_material_old = -1 # avoid a dict lookup mat = 0 # rare case it may be un-initialized. me_faces = me.tessfaces for i, face in enumerate(faces): if len(face[0]) < 2: pass # raise "bad face" elif len(face[0]) == 2: if use_edges: edges.append(face[0]) else: blender_face = me.tessfaces[i] (face_vert_loc_indices, face_vert_tex_indices, context_material, context_smooth_group, context_object, ) = face if context_smooth_group: blender_face.use_smooth = True if context_material: if context_material_old is not context_material: mat = material_mapping[context_material] context_material_old = context_material blender_face.material_index = mat # blender_face.mat= mat if verts_tex: blender_tface = me.tessface_uv_textures[0].data[i] if context_material: image = unique_material_images[context_material] if image: # Can be none if the material dosnt have an image. blender_tface.image = image # BUG - Evil eekadoodle problem where faces that have vert index 0 location at 3 or 4 are shuffled. if len(face_vert_loc_indices) == 4: if face_vert_loc_indices[2] == 0 or face_vert_loc_indices[3] == 0: face_vert_tex_indices = face_vert_tex_indices[2], face_vert_tex_indices[3], face_vert_tex_indices[0], face_vert_tex_indices[1] else: # length of 3 if face_vert_loc_indices[2] == 0: face_vert_tex_indices = face_vert_tex_indices[1], face_vert_tex_indices[2], face_vert_tex_indices[0] # END EEEKADOODLE FIX # assign material, uv's and image blender_tface.uv1 = verts_tex[face_vert_tex_indices[0]] blender_tface.uv2 = verts_tex[face_vert_tex_indices[1]] blender_tface.uv3 = verts_tex[face_vert_tex_indices[2]] if len(face_vert_loc_indices) == 4: blender_tface.uv4 = verts_tex[face_vert_tex_indices[3]] # for ii, uv in enumerate(blender_face.uv): # uv.x, uv.y= verts_tex[face_vert_tex_indices[ii]] del me_faces # del ALPHA if use_edges and not edges: use_edges = False if use_edges: me.edges.add(len(edges)) # edges should be a list of (a, b) tuples me.edges.foreach_set("vertices", unpack_list(edges)) # me_edges.extend( edges ) # del me_edges # Add edge faces. # me_edges= me.edges def edges_match(e1, e2): return (e1[0] == e2[0] and e1[1] == e2[1]) or (e1[0] == e2[1] and e1[1] == e2[0]) me.validate() me.update(calc_edges=use_edges) if unique_smooth_groups and sharp_edges: import bmesh bm = bmesh.new() bm.from_mesh(me) # to avoid slow iterator lookups later / indexing verts is slow in bmesh bm_verts = bm.verts[:] for sharp_edge in sharp_edges.keys(): vert1 = bm_verts[sharp_edge[0]] vert2 = bm_verts[sharp_edge[1]] if vert1 != vert2: edge = bm.edges.get((vert1, vert2)) if edge is not None: me.edges[edge.index].use_edge_sharp = True bm.free() del bm mesh_untessellate(me, fgon_edges) # XXX slow # if unique_smooth_groups and sharp_edges: # for sharp_edge in sharp_edges.keys(): # for ed in me.edges: # if edges_match(sharp_edge, ed.vertices): # ed.use_edge_sharp = True # if unique_smooth_groups and sharp_edges: # SHARP= Mesh.EdgeFlags.SHARP # for ed in me.findEdges( sharp_edges.keys() ): # if ed is not None: # me_edges[ed].flag |= SHARP # del SHARP ob = bpy.data.objects.new(me.name, me) new_objects.append(ob) # Create the vertex groups. No need to have the flag passed here since we test for the # content of the vertex_groups. If the user selects to NOT have vertex groups saved then # the following test will never run for group_name, group_indices in vertex_groups.items(): group = ob.vertex_groups.new(group_name.decode('utf-8', "replace")) group.add(group_indices, 1.0, 'REPLACE')
def create_mesh(new_objects, use_edges, verts_loc, verts_nor, verts_tex, faces, unique_materials, unique_material_images, unique_smooth_groups, vertex_groups, dataname, ): """ Takes all the data gathered and generates a mesh, adding the new object to new_objects deals with ngons, sharp edges and assigning materials """ if unique_smooth_groups: sharp_edges = set() smooth_group_users = {context_smooth_group: {} for context_smooth_group in unique_smooth_groups.keys()} context_smooth_group_old = -1 fgon_edges = set() # Used for storing fgon keys when we need to tesselate/untesselate them (ngons with hole). edges = [] tot_loops = 0 context_object = None # reverse loop through face indices for f_idx in range(len(faces) - 1, -1, -1): (face_vert_loc_indices, face_vert_nor_indices, face_vert_tex_indices, context_material, context_smooth_group, context_object, face_invalid_blenpoly, ) = faces[f_idx] len_face_vert_loc_indices = len(face_vert_loc_indices) if len_face_vert_loc_indices == 1: faces.pop(f_idx) # cant add single vert faces # Face with a single item in face_vert_nor_indices is actually a polyline! elif len(face_vert_nor_indices) == 1 or len_face_vert_loc_indices == 2: if use_edges: edges.extend((face_vert_loc_indices[i], face_vert_loc_indices[i + 1]) for i in range(len_face_vert_loc_indices - 1)) faces.pop(f_idx) else: # Smooth Group if unique_smooth_groups and context_smooth_group: # Is a part of of a smooth group and is a face if context_smooth_group_old is not context_smooth_group: edge_dict = smooth_group_users[context_smooth_group] context_smooth_group_old = context_smooth_group prev_vidx = face_vert_loc_indices[-1] for vidx in face_vert_loc_indices: edge_key = (prev_vidx, vidx) if (prev_vidx < vidx) else (vidx, prev_vidx) prev_vidx = vidx edge_dict[edge_key] = edge_dict.get(edge_key, 0) + 1 # NGons into triangles if face_invalid_blenpoly: from bpy_extras.mesh_utils import ngon_tessellate ngon_face_indices = ngon_tessellate(verts_loc, face_vert_loc_indices) faces.extend([([face_vert_loc_indices[ngon[0]], face_vert_loc_indices[ngon[1]], face_vert_loc_indices[ngon[2]], ], [face_vert_nor_indices[ngon[0]], face_vert_nor_indices[ngon[1]], face_vert_nor_indices[ngon[2]], ] if face_vert_nor_indices else [], [face_vert_tex_indices[ngon[0]], face_vert_tex_indices[ngon[1]], face_vert_tex_indices[ngon[2]], ] if face_vert_tex_indices else [], context_material, context_smooth_group, context_object, [], ) for ngon in ngon_face_indices] ) tot_loops += 3 * len(ngon_face_indices) # edges to make ngons edge_users = set() for ngon in ngon_face_indices: prev_vidx = face_vert_loc_indices[ngon[-1]] for ngidx in ngon: vidx = face_vert_loc_indices[ngidx] if vidx == prev_vidx: continue # broken OBJ... Just skip. edge_key = (prev_vidx, vidx) if (prev_vidx < vidx) else (vidx, prev_vidx) prev_vidx = vidx if edge_key in edge_users: fgon_edges.add(edge_key) else: edge_users.add(edge_key) faces.pop(f_idx) else: tot_loops += len_face_vert_loc_indices # Build sharp edges if unique_smooth_groups: for edge_dict in smooth_group_users.values(): for key, users in edge_dict.items(): if users == 1: # This edge is on the boundry of a group sharp_edges.add(key) # map the material names to an index material_mapping = {name: i for i, name in enumerate(unique_materials)} # enumerate over unique_materials keys() materials = [None] * len(unique_materials) for name, index in material_mapping.items(): materials[index] = unique_materials[name] me = bpy.data.meshes.new(dataname) # make sure the list isnt too big for material in materials: me.materials.append(material) me.vertices.add(len(verts_loc)) me.loops.add(tot_loops) me.polygons.add(len(faces)) # verts_loc is a list of (x, y, z) tuples me.vertices.foreach_set("co", unpack_list(verts_loc)) loops_vert_idx = [] faces_loop_start = [] faces_loop_total = [] lidx = 0 for f in faces: vidx = f[0] nbr_vidx = len(vidx) loops_vert_idx.extend(vidx) faces_loop_start.append(lidx) faces_loop_total.append(nbr_vidx) lidx += nbr_vidx me.loops.foreach_set("vertex_index", loops_vert_idx) me.polygons.foreach_set("loop_start", faces_loop_start) me.polygons.foreach_set("loop_total", faces_loop_total) if verts_nor and me.loops: # Note: we store 'temp' normals in loops, since validate() may alter final mesh, # we can only set custom lnors *after* calling it. me.create_normals_split() if verts_tex and me.polygons: me.uv_textures.new() context_material_old = -1 # avoid a dict lookup mat = 0 # rare case it may be un-initialized. for i, (face, blen_poly) in enumerate(zip(faces, me.polygons)): if len(face[0]) < 3: raise Exception("bad face") # Shall not happen, we got rid of those earlier! (face_vert_loc_indices, face_vert_nor_indices, face_vert_tex_indices, context_material, context_smooth_group, context_object, face_invalid_blenpoly, ) = face if context_smooth_group: blen_poly.use_smooth = True if context_material: if context_material_old is not context_material: mat = material_mapping[context_material] context_material_old = context_material blen_poly.material_index = mat if verts_nor and face_vert_nor_indices: for face_noidx, lidx in zip(face_vert_nor_indices, blen_poly.loop_indices): me.loops[lidx].normal[:] = verts_nor[0 if (face_noidx is ...) else face_noidx] if verts_tex and face_vert_tex_indices: if context_material: image = unique_material_images[context_material] if image: # Can be none if the material dosnt have an image. me.uv_textures[0].data[i].image = image blen_uvs = me.uv_layers[0] for face_uvidx, lidx in zip(face_vert_tex_indices, blen_poly.loop_indices): blen_uvs.data[lidx].uv = verts_tex[0 if (face_uvidx is ...) else face_uvidx] use_edges = use_edges and bool(edges) if use_edges: me.edges.add(len(edges)) # edges should be a list of (a, b) tuples me.edges.foreach_set("vertices", unpack_list(edges)) me.validate(clean_customdata=False) # *Very* important to not remove lnors here! me.update(calc_edges=use_edges) # Un-tessellate as much as possible, in case we had to triangulate some ngons... if fgon_edges: import bmesh bm = bmesh.new() bm.from_mesh(me) verts = bm.verts[:] get = bm.edges.get edges = [get((verts[vidx1], verts[vidx2])) for vidx1, vidx2 in fgon_edges] try: bmesh.ops.dissolve_edges(bm, edges=edges, use_verts=False) except: # Possible dissolve fails for some edges, but don't fail silently in case this is a real bug. import traceback traceback.print_exc() bm.to_mesh(me) bm.free() # XXX If validate changes the geometry, this is likely to be broken... if unique_smooth_groups and sharp_edges: for e in me.edges: if e.key in sharp_edges: e.use_edge_sharp = True me.show_edge_sharp = True if verts_nor: clnors = array.array('f', [0.0] * (len(me.loops) * 3)) me.loops.foreach_get("normal", clnors) if not unique_smooth_groups: me.polygons.foreach_set("use_smooth", [True] * len(me.polygons)) me.normals_split_custom_set(tuple(zip(*(iter(clnors),) * 3))) me.use_auto_smooth = True me.show_edge_sharp = True ob = bpy.data.objects.new(me.name, me) new_objects.append(ob) # Create the vertex groups. No need to have the flag passed here since we test for the # content of the vertex_groups. If the user selects to NOT have vertex groups saved then # the following test will never run for group_name, group_indices in vertex_groups.items(): group = ob.vertex_groups.new(group_name.decode('utf-8', "replace")) group.add(group_indices, 1.0, 'REPLACE')
def read_scm(): global xy_to_xz_transform global scm_filepath # [0] both [1] path [2] name global sca_filepath # [0] both [1] path [2] name print("=== LOADING Sup Com Model ===") print("") #global counter # #if (counter < 10): # # bpy.utils.unregister_class(SimpleOperator) # SimpleOperator.bl_label = "toto"+str(counter) # bpy.utils.register_class(SimpleOperator) # # bpy.ops.object.simple_operator('INVOKE_DEFAULT') # # return # #xy_to_xz_transform.resize_4x4() #bpy.ops.object.mode_set(mode='OBJECT') #scene = Blender.Scene.GetCurrent() scene = bpy.context.scene mesh = scm_mesh() if (mesh.load(scm_filepath[0]) == None): print('Failed to load %s' % scm_filepath[2]) my_popup('Failed to load %s' % scm_filepath[2]) return #ProgBarLSCM = ProgressBar( "Imp: load SCM", (2*len(mesh.vertices) + len(mesh.faces))) armature_name = scm_filepath[2].rstrip(".scm") print("armature ", armature_name) ### CREATE ARMATURE armData = bpy.data.armatures.new(armature_name) armData.show_axes = True armObj = bpy.data.objects.new(armature_name, armData) scene.objects.link(armObj) scene.objects.active = armObj armObj.select = True armObj.show_x_ray = True bpy.ops.object.mode_set(mode='EDIT') for index in range(len(mesh.bones)): #print('boneIndex',index) bone = mesh.bones[index] #print('boneName',bone.name) blender_bone = armData.edit_bones.new(bone.name) #not nice parent may not exist, but usualy should exist (depends on storing in scm) if (bone.parent != 0): blender_bone.parent = armData.edit_bones[bone.parent.name] t_matrix = bone.rel_mat * xy_to_xz_transform loc, rot, sca = t_matrix.transposed().decompose() blender_bone.head = loc blender_bone.tail = (rot.to_matrix() * Vector( (0, 1, 0))) + blender_bone.head blender_bone.matrix = t_matrix.transposed() bpy.ops.object.mode_set(mode='OBJECT') meshData = bpy.data.meshes.new('Mesh') #add verts vertlist = [] for vert in mesh.vertices: #ProgBarLSCM.do() vertlist.append(Vector(vert.position) * xy_to_xz_transform) meshData.vertices.add(len(vertlist)) meshData.tessfaces.add(len(mesh.faces)) meshData.vertices.foreach_set("co", unpack_list(vertlist)) meshData.tessfaces.foreach_set("vertices_raw", unpack_list(mesh.faces)) print(len(meshData.tessfaces)) meshData.uv_textures.new(name='UVMap') for uv in meshData.tessface_uv_textures: # uv texture print(uv) for face in meshData.tessfaces: # face, uv uv1 = mesh.vertices[mesh.faces[face.index][0]].uv1 uv.data[face.index].uv1 = Vector((uv1[0], 1.0 - uv1[1])) uv1 = mesh.vertices[mesh.faces[face.index][1]].uv1 uv.data[face.index].uv2 = Vector((uv1[0], 1.0 - uv1[1])) uv1 = mesh.vertices[mesh.faces[face.index][2]].uv1 uv.data[face.index].uv3 = Vector((uv1[0], 1.0 - uv1[1])) mesh_obj = bpy.data.objects.new('Mesh', meshData) scene.objects.link(mesh_obj) scene.objects.active = mesh_obj mesh_obj.select = True meshData.update() #assigns vertex groups #mesh must be in object for bone in mesh.bones: mesh_obj.vertex_groups.new(bone.name) for vgroup in mesh_obj.vertex_groups: #print(vgroup.name, ":", vgroup.index) for vertex_index in range(len(mesh.vertices)): #bone index vertex = mesh.vertices[vertex_index] bone_index = vertex.bone_index[0] boneName = mesh.bones[bone_index].name if boneName == vgroup.name: vgroup.add([vertex_index], 1.0, 'ADD') meshData.update() bpy.context.scene.update() bpy.ops.object.select_all(action='DESELECT') mesh_obj.select = False armObj.select = False #armObj.select = True mesh_obj.select = True armObj.select = True scene.objects.active = armObj bpy.ops.object.parent_set(type="ARMATURE") if len(mesh.info): print("=== INFO ===") for info in mesh.info: print("", info) print("=== COMPLETE ===") global globMesh globMesh = mesh
def CriaBezierUnidoTeethDef(self, context): context = bpy.context obj = context.active_object scn = context.scene Pontos = [ obj for obj in bpy.context.scene.objects if fnmatch.fnmatchcase(obj.name, "PT_Linh*") ] coords = [] for i in Pontos: VetorAtual = i.location VetX = i.location[0] VetY = i.location[1] VetZ = i.location[2] coords.append((VetX, VetY, VetZ)) # edges = [] # for i in range(len(vertices)): # edges.append([i,i+1]) # del(edges[-1]) # Apaga o último elemento da cena # create the Curve Datablock curveData = bpy.data.curves.new('myCurve', type='CURVE') curveData.dimensions = '3D' # curveData.resolution_u = 6 curveData.resolution_u = 36 # map coords to spline polyline = curveData.splines.new('BEZIER') polyline.bezier_points.add(len(coords) - 1) # for i, coord in enumerate(coords): # x,y,z = coord # polyline.points[i].co = (x, y, z, 1) from bpy_extras.io_utils import unpack_list polyline.bezier_points.foreach_set("co", unpack_list(coords)) # Apaga pontos bpy.ops.object.select_all(action='DESELECT') for i in Pontos: i.select_set(True) bpy.ops.object.delete(use_global=False) # Cria Linha curveOB = bpy.data.objects.new('myCurve', curveData) # attach to scene and validate context scn = bpy.context.scene # scn.objects.link(curveOB) scn.collection.objects.link(curveOB) bpy.ops.object.select_all(action='DESELECT') bpy.context.view_layer.objects.active = curveOB curveOB.select_set(True) bpy.ops.object.editmode_toggle() bpy.ops.curve.select_all(action='SELECT') bpy.ops.curve.handle_type_set(type='AUTOMATIC') bpy.ops.curve.make_segment() bpy.ops.object.editmode_toggle() bpy.ops.object.modifier_add(type='SHRINKWRAP') bpy.context.object.modifiers["Shrinkwrap"].target = obj bpy.context.object.modifiers["Shrinkwrap"].offset = 0.01 # ORIGINAL 0.01 bpy.context.object.modifiers["Shrinkwrap"].wrap_mode = 'ABOVE_SURFACE' bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Shrinkwrap") # bpy.ops.object.modifier_add(type='SMOOTH') # bpy.context.object.modifiers["Smooth"].factor = 2 # bpy.context.object.modifiers["Smooth"].iterations = 3 bpy.context.object.data.bevel_depth = 0.2 ListaMateriais = [] MateriaisCena = bpy.data.materials for i in MateriaisCena: ListaMateriais.append(i.name) if 'MatModalPoints' in ListaMateriais: activeObject = bpy.context.active_object #Set active object to variable mat = bpy.data.materials[ "MatModalPointsTeeth"] #set new material to variable activeObject.data.materials.append( mat) #add the material to the object bpy.context.object.active_material.diffuse_color = (0.2, 0.2, 0.9, 1) else: activeObject = bpy.context.active_object #Set active object to variable mat = bpy.data.materials.new( name="MatModalPointsTeeth") #set new material to variable activeObject.data.materials.append( mat) #add the material to the object bpy.context.object.active_material.diffuse_color = (0.2, 0.2, 0.9, 1) bpy.ops.object.select_all(action='DESELECT') obj.select_set(True) bpy.context.view_layer.objects.active = obj
def CriaBezierUnidoDef(self, context): context = bpy.context obj = context.active_object scn = context.scene Pontos = [ obj for obj in bpy.context.scene.objects if fnmatch.fnmatchcase(obj.name, "PT_Linh*") ] coords = [] for i in Pontos: VetorAtual = i.location VetX = i.location[0] VetY = i.location[1] VetZ = i.location[2] coords.append((VetX, VetY, VetZ)) # edges = [] # for i in range(len(vertices)): # edges.append([i,i+1]) # del(edges[-1]) # Apaga o último elemento da cena # create the Curve Datablock curveData = bpy.data.curves.new('myCurve', type='CURVE') curveData.dimensions = '3D' # curveData.resolution_u = 6 curveData.resolution_u = 36 # map coords to spline polyline = curveData.splines.new('BEZIER') polyline.bezier_points.add(len(coords) - 1) # for i, coord in enumerate(coords): # x,y,z = coord # polyline.points[i].co = (x, y, z, 1) from bpy_extras.io_utils import unpack_list polyline.bezier_points.foreach_set("co", unpack_list(coords)) # Apaga pontos bpy.ops.object.select_all(action='DESELECT') for i in Pontos: i.select_set(True) bpy.ops.object.delete(use_global=False) # Cria Linha curveOB = bpy.data.objects.new('myCurve', curveData) # attach to scene and validate context scn = bpy.context.scene # scn.objects.link(curveOB) scn.collection.objects.link(curveOB) bpy.ops.object.select_all(action='DESELECT') bpy.context.view_layer.objects.active = curveOB curveOB.select_set(True) bpy.ops.object.editmode_toggle() bpy.ops.curve.select_all(action='SELECT') bpy.ops.curve.handle_type_set(type='AUTOMATIC') bpy.ops.curve.make_segment() bpy.ops.object.editmode_toggle() bpy.ops.object.modifier_add(type='SHRINKWRAP') bpy.context.object.modifiers["Shrinkwrap"].target = obj bpy.context.object.modifiers["Shrinkwrap"].offset = 0.01 bpy.context.object.modifiers["Shrinkwrap"].wrap_mode = 'ABOVE_SURFACE' bpy.ops.object.select_all(action='DESELECT') obj.select_set(True) bpy.context.view_layer.objects.active = obj
def write_mesh_data(self, entities, name, default_material='Material'): verts = [] faces = [] mat_index = [] mats = keep_offset() seen = keep_offset() uv_list = [] alpha = False # We assume object does not need alpha flag uvs_used = False # We assume no uvs need to be added for f in entities.faces: vs, tri, uvs = f.tessfaces if f.material: mat_number = mats[f.material.name] else: mat_number = mats[default_material] mapping = {} for i, (v, uv) in enumerate(zip(vs, uvs)): l = len(seen) mapping[i] = seen[v] if len(seen) > l: verts.append(v) uvs.append(uv) for face in tri: f0, f1, f2 = face[0], face[1], face[2] if f2 == 0: ## eeekadoodle dance faces.append( ( mapping[f1], mapping[f2], mapping[f0] ) ) uv_list.append(( uvs[f2][0], uvs[f2][1], uvs[f1][0], uvs[f1][1], uvs[f0][0], uvs[f0][1], 0, 0 ) ) else: faces.append( ( mapping[f0], mapping[f1], mapping[f2] ) ) uv_list.append(( uvs[f0][0], uvs[f0][1], uvs[f1][0], uvs[f1][1], uvs[f2][0], uvs[f2][1], 0, 0 ) ) mat_index.append(mat_number) # verts, faces, uv_list, mat_index, mats = entities.get__triangles_lists(default_material) if len(verts) == 0: return None, False me = bpy.data.meshes.new(name) me.vertices.add(len(verts)) me.tessfaces.add(len(faces)) if len(mats) >= 1: mats_sorted = OrderedDict(sorted(mats.items(), key=lambda x: x[1])) for k in mats_sorted.keys(): bmat = self.materials[k] me.materials.append(bmat) if bmat.alpha < 1.0: alpha = True try: if 'Image Texture' in bmat.node_tree.nodes.keys(): uvs_used = True except AttributeError as e: uvs_used = False else: sketchupLog("WARNING OBJECT {} HAS NO MATERIAL".format(name)) me.vertices.foreach_set("co", unpack_list(verts)) me.tessfaces.foreach_set("vertices_raw", unpack_face_list(faces)) me.tessfaces.foreach_set("material_index", mat_index) if uvs_used: me.tessface_uv_textures.new() for i in range(len(faces)): me.tessface_uv_textures[0].data[i].uv_raw = uv_list[i] me.update(calc_edges=True) me.validate() return me, alpha
def load(context, filepath): with open(filepath, "rb") as fd: ter = read_ter(fd) name = root_name(filepath) me = bpy.data.meshes.new(name) for orig_path in ter.materialNames: if not orig_path: continue mat_name = root_name(orig_path) mat_file = resolve_texture(filepath, mat_name) mat = bpy.data.materials.new(mat_name) me.materials.append(mat) if mat_file: try: image = bpy.data.images.load(mat_file) except: print("Cannot load image", mat_file) continue slot = mat.texture_slots.add() slot.texture = bpy.data.textures.new(mat_name, "IMAGE") slot.texture.image = image slot.texture_coords = "ORCO" slot.scale = 32, 32, 32 # This is a bit of a mess. # Feel free to clean it up :) # me.vertices.add(BlockSize2) # # for i, vert in enumerate(me.vertices): # vert.co = ( # (i // BlockSize) * 8 / 32, # (i % BlockSize) * 8 / -32, # ter.heightMap[i] / 32 / 32 # ) verts = [] for x in range(BlockSize + 1): for y in range(BlockSize + 1): i = (y % BlockSize) * BlockSize + (x % BlockSize) verts.append(( x * 8 - 1024, y * 8 - 1024, ter.heightMap[i] / 32 )) faces = [] for x in range(BlockSize): for y in range(BlockSize): vert0 = y * 257 + x vert1 = y * 257 + x + 1 vert2 = y * 257 + x + 257 vert3 = y * 257 + x + 258 if x % 2 == y % 2: faces.append(((vert0, vert2, vert3), (x, y))) faces.append(((vert3, vert1, vert0), (x, y))) else: faces.append(((vert0, vert2, vert1), (x, y))) faces.append(((vert3, vert1, vert2), (x, y))) me.vertices.add(len(verts)) me.vertices.foreach_set("co", unpack_list(verts)) me.polygons.add(len(faces)) me.loops.add(len(faces) * 3) # me.uv_textures.new() # uvs = me.uv_layers[0] for i, ((verts, (gx, gy)), poly) in enumerate(zip(faces, me.polygons)): poly.use_smooth = True poly.loop_total = 3 poly.loop_start = i * 3 # For now, just solidly fill in the material with the highest alpha best_mat_index = None best_mat_alpha = None grid_idx = gx * BlockSize + gy # ... this is the wrong way around? for mat_index in range(MaterialGroups): if ter.materialAlpha[mat_index]: alpha = ter.materialAlpha[mat_index][grid_idx] if best_mat_index == None or alpha > best_mat_alpha: best_mat_index = mat_index best_mat_alpha = alpha if best_mat_index is not None: poly.material_index = best_mat_index for j, index in zip(poly.loop_indices, verts): me.loops[j].vertex_index = index # uvs.data[j].uv = () me.validate() me.update() ob = bpy.data.objects.new(name, me) context.scene.objects.link(ob) return {"FINISHED"}
def do_import(path, DELETE_TOP_BONE=True): # limits MAX_NUMMESHES = 1000 MAX_NUMVERTS = 100000 MAX_NUMNORMALS = 100000 MAX_NUMTRIS = 100000 MAX_NUMMATS = 16 MAX_NUMBONES = 1000 MAX_NUMPOSKEYS = 1000 MAX_NUMROTKEYS = 1000 # get scene scn = bpy.context.scene if scn==None: return "No scene to import to!" # open the file try: file = open(path, 'r') except IOError: return "Failed to open the file!" try: if not path.endswith(".nb2"): raise IOError except IOError: return "Must be an nb2 file!" # Read frame info try: lines = getNextLine(file).split() if len(lines) != 2 or lines[0] != "Frames:": raise ValueError lines = getNextLine(file).split() if len(lines) != 2 or lines[0] != "Frame:": raise ValueError except ValueError: return "Frame information is invalid!" # Create the mesh meshName = "Mesh Object" # Before adding any meshes or armatures go into Object mode. if bpy.ops.object.mode_set.poll(): bpy.ops.object.mode_set(mode='OBJECT') # read the number of meshes try: lines = getNextLine(file).split() if len(lines)!=2 or lines[0]!="Meshes:": raise ValueError numMeshes = int(lines[1]) if numMeshes < 0 or numMeshes > MAX_NUMMESHES: raise ValueError except ValueError: return "Number of meshes is invalid!" # read meshes boneIds = [[],[],[],[]] boneWeights = [[],[],[],[]] meshVertexGroups = {} vCount = 0 meshes = [] meshObjects = [] for i in range(numMeshes): # read name, flags and material try: lines = re.findall(r'\".*\"|[^ ]+', getNextLine(file)) if len(lines)!=3: raise ValueError meshName = lines[0] meshName = meshName[1:-1] print ("processing mesh name:%s..." % meshName) material = int(lines[2]) except ValueError: return "Name, flags or material in mesh " + str(i+1) + " are invalid!" meshes.append(bpy.data.meshes.new(meshName)) meshObjects.append(bpy.data.objects.new(meshName + "Ob", meshes[i])) scn.objects.link(meshObjects[i]) # read the number of vertices try: numVerts = int(getNextLine(file)) if numVerts < 0 or numVerts > MAX_NUMVERTS: raise ValueError except ValueError: return "Number of vertices in mesh " + str(i+1) + " is invalid!" print ("Number of vertices in mesh:%d" % numVerts) # read vertices coords = [] uvs = [] for j in range(numVerts): try: lines = getNextLine(file).split() if len(lines)!=14: raise ValueError coords.append([float(lines[1]), float(lines[2]), float(lines[3])]) uvs.append([float(lines[4]), 1-float(lines[5])]) boneIds[0].append(int(lines[6])) boneWeights[0].append(float(lines[7])) boneIds[1].append(int(lines[8])) boneWeights[1].append(float(lines[9])) boneIds[2].append(int(lines[10])) boneWeights[2].append(float(lines[11])) boneIds[3].append(int(lines[12])) boneWeights[3].append(float(lines[13])) meshVertexGroups[vCount] = meshName # uses the long mesh name - may be > 21 chars vCount += 1 except ValueError: return "Vertex " + str(j+1) + " in mesh " + str(i+1) + " is invalid!" meshes[i].vertices.add(len(coords)) meshes[i].vertices.foreach_set("co", unpack_list(coords)) # read number of normals try: numNormals = int(getNextLine(file)) if numNormals < 0 or numNormals > MAX_NUMNORMALS: raise ValueError except ValueError: return "Number of normals in mesh " + str(i+1) + " is invalid!" print ("Number of normals in mesh:%d" % numNormals) # read normals normals = [] for j in range(numNormals): try: lines = getNextLine(file).split() if len(lines)!=3: raise ValueError normals.append([float(lines[0]), float(lines[1]), float(lines[2])]) except ValueError: return "Normal " + str(j+1) + " in mesh " + str(i+1) + " is invalid!" # read the number of triangles try: numTris = int(getNextLine(file)) if numTris < 0 or numTris > MAX_NUMTRIS: raise ValueError except ValueError: return "Number of triangles in mesh " + str(i+1) + " is invalid!" print ("Number of triangles in mesh:%d" % numTris) # read triangles faces = [] for j in range(numTris): # read the triangle try: lines = getNextLine(file).split() if len(lines) != 8: raise ValueError v1 = int(lines[1]) v2 = int(lines[2]) v3 = int(lines[3]) faces.append([v1,v2,v3,0]) except ValueError: return "Triangle " + str(j+1) + " in mesh " + str(i+1) + " is invalid!" meshes[i].tessfaces.add(len(faces)) for fi, fpol in enumerate(faces): vlen = len(fpol) if vlen == 3 or vlen == 4: for v in range(vlen): meshes[i].tessfaces[fi].vertices_raw[v]= fpol[v] # set texture coordinates and material meshes[i].tessface_uv_textures.new() for j, face in enumerate(meshes[i].tessfaces): face_uv = meshes[i].tessface_uv_textures[0].data[j] face_uv.uv1 = Vector(uvs[face.vertices[0]]); face_uv.uv2 = Vector(uvs[face.vertices[1]]); face_uv.uv3 = Vector(uvs[face.vertices[2]]); if material >= 0: face.material_index = material for mesh in meshes: mesh.update() # read the number of materials try: lines = getNextLine(file).split() if len(lines)!=2 or lines[0]!="Materials:": raise ValueError numMats = int(lines[1]) if numMats < 0 or numMats > MAX_NUMMATS: raise ValueError except ValueError: return "Number of materials is invalid!" # read the materials for i in range(numMats): # read name name = getNextLine(file)[1:-1] # create the material #mat = Blender.Material.New(name) #mesh.materials += [mat] # read ambient color try: lines = getNextLine(file).split() if len(lines)!=4: raise ValueError except ValueError: return "Ambient color in material " + str(i+1) + " is invalid!" # read diffuse color try: lines = getNextLine(file).split() if len(lines)!=4: raise ValueError except ValueError: return "Diffuse color in material " + str(i+1) + " is invalid!" # read specular color try: lines = getNextLine(file).split() if len(lines)!=4: raise ValueError except ValueError: return "Specular color in material " + str(i+1) + " is invalid!" # read emissive color try: lines = getNextLine(file).split() if len(lines)!=4: raise ValueError except ValueError: return "Emissive color in material " + str(i+1) + " is invalid!" # read shininess try: shi = float(getNextLine(file)) except ValueError: return "Shininess in material " + str(i+1) + " is invalid!" # read transparency try: alpha = float(getNextLine(file)) except ValueError: return "Transparency in material " + str(i+1) + " is invalid!" # read texturemap texturemap = getNextLine(file)[1:-1] alphamap = getNextLine(file)[1:-1] # read the number of bones try: lines = getNextLine(file).split() if len(lines)!=2 or lines[0]!="Bones:": raise ValueError numBones = int(lines[1]) if numBones < 0 or numBones > MAX_NUMBONES: raise ValueError except: return "Number of bones is invalid!" # create the armature armature = None armOb = None print ("numBones:") numBones if numBones > 0: armature = bpy.data.armatures.new("Armature") armOb = bpy.data.objects.new("ArmatureObject", armature) armature.draw_type = 'STICK' scn.objects.link(armOb) scn.objects.active = armOb # read bones posKeys = {} rotKeys = {} boneNames = [] bpy.ops.object.editmode_toggle() bpy.types.EditBone.rot_matrix = bpy.props.FloatVectorProperty(name="Rot Matrix", size=9) for i in range(numBones): # read name fullName = getNextLine(file)[1:-1] boneNames.append(fullName) bone = armature.edit_bones.new(fullName) # read parent parentBoneName = getNextLine(file)[1:-1] if len(parentBoneName) > 0: bone.parent = armature.bones.data.edit_bones[parentBoneName] # read position and rotation try: line = getNextLine(file) lines = line.split() if not (len(lines) == 8 or len(lines) == 24): raise ValueError pos = [float(lines[1]), float(lines[2]), float(lines[3])] quat = [float(lines[4]), float(lines[5]), float(lines[6]), float(lines[7])] #print 'Read bone: %s' % line except ValueError: return "Invalid position or orientation in a bone!" # # Granny Rotation Quaternions are stored X,Y,Z,W but Blender uses W,X,Y,Z quaternion = Quaternion((quat[3], quat[0], quat[1], quat[2])) rotMatrix = quaternion.to_matrix() rotMatrix.transpose() # Need to transpose to get same behaviour as 2.49 script print ("Bone Data") print (fullName) print (pos) print (rotMatrix) boneLength = 3 # set position and orientation if bone.parent: bone_parent_matrix = Matrix([[bone.parent.rot_matrix[0], bone.parent.rot_matrix[1], bone.parent.rot_matrix[2]], [bone.parent.rot_matrix[3], bone.parent.rot_matrix[4], bone.parent.rot_matrix[5]], [bone.parent.rot_matrix[6], bone.parent.rot_matrix[7], bone.parent.rot_matrix[8]]]) bone.head = Vector(pos) * bone_parent_matrix + bone.parent.head bone.tail = bone.head + Vector([boneLength,0,0]) tempM = rotMatrix * bone_parent_matrix bone.rot_matrix = [tempM[0][0], tempM[0][1], tempM[0][2], tempM[1][0], tempM[1][1], tempM[1][2], tempM[2][0], tempM[2][1], tempM[2][2]] bone.matrix = Matrix([[-bone.rot_matrix[3], bone.rot_matrix[0], bone.rot_matrix[6], bone.head[0]], [-bone.rot_matrix[4], bone.rot_matrix[1], bone.rot_matrix[7], bone.head[1]], [-bone.rot_matrix[5], bone.rot_matrix[2], bone.rot_matrix[8], bone.head[2]], [0, 0, 0, 1]]) else: bone.head = Vector(pos) bone.tail = bone.head + Vector([boneLength,0,0]) bone.rot_matrix = [rotMatrix[0][0], rotMatrix[0][1], rotMatrix[0][2], rotMatrix[1][0], rotMatrix[1][1], rotMatrix[1][2], rotMatrix[2][0], rotMatrix[2][1], rotMatrix[2][2]] bone.matrix = Matrix([[-bone.rot_matrix[3], bone.rot_matrix[0], bone.rot_matrix[6], bone.head[0]], [-bone.rot_matrix[4], bone.rot_matrix[1], bone.rot_matrix[7], bone.head[1]], [-bone.rot_matrix[5], bone.rot_matrix[2], bone.rot_matrix[8], bone.head[2]], [0, 0, 0, 1]]) print (bone.rot_matrix[0], bone.rot_matrix[1], bone.rot_matrix[2]) print (bone.rot_matrix[3], bone.rot_matrix[4], bone.rot_matrix[5]) print (bone.rot_matrix[6], bone.rot_matrix[7], bone.rot_matrix[8]) print (bone.head) print (bone.tail) print ("bone roll") print (bone.roll) # read the number of position key frames try: numPosKeys = int(getNextLine(file)) if numPosKeys < 0 or numPosKeys > MAX_NUMPOSKEYS: raise ValueError except ValueError: return "Invalid number of position key frames!" # read position key frames posKeys[name] = [] for j in range(numPosKeys): # read time and position try: lines = getNextLine(file).split() if len(lines) != 4: raise ValueError except ValueError: return "Invalid position key frame!" # read the number of rotation key frames try: numRotKeys = int(getNextLine(file)) if numRotKeys < 0 or numRotKeys > MAX_NUMROTKEYS: raise ValueError except ValueError: return "Invalid number of rotation key frames!" # read rotation key frames rotKeys[name] = [] for j in range(numRotKeys): # read time and rotation try: lines = getNextLine(file).split() if len(lines) != 4: raise ValueError except ValueError: return "Invalid rotation key frame!" # Roll Fix #for bone in armature.edit_bones: # if bone.parent: # roll = bone.roll # bone.roll = roll - math.radians(90.0) # Create Vertex Groups vi = 0 for meshOb in meshObjects: mesh = meshOb.data for mvi, vertex in enumerate(mesh.vertices): for bi in range(numBones): for j in range(4): if bi==boneIds[j][vi]: name = boneNames[bi] if not meshOb.vertex_groups.get(name): meshOb.vertex_groups.new(name) grp = meshOb.vertex_groups.get(name) grp.add([mvi], boneWeights[j][vi], 'ADD') vi = vi + 1 # Give mesh object an armature modifier, using vertex groups but # not envelopes mod = meshOb.modifiers.new('mod_' + mesh.name, 'ARMATURE') mod.object = armOb mod.use_bone_envelopes = False mod.use_vertex_groups = True if DELETE_TOP_BONE: # Adjust object names, remove top bone for Civ V - Deliverator #armature.makeEditable() bone = armature.bones.data.edit_bones[boneNames[0]] while not bone.parent is None: bone = bone.parent print ('Found World Bone: %s' % bone.name) name = bone.name armOb.name = name # Delete top bone unless that would leave zero bones if (len(armature.bones.data.edit_bones) > 1): bpy.ops.object.select_pattern(pattern=name) bpy.ops.armature.delete() #del armature.bones.data.edit_bones[name] # armature.update() bpy.ops.object.editmode_toggle() bpy.ops.object.editmode_toggle() bpy.ops.object.editmode_toggle() # The import was a success! return ""