def import_bounding_box(self, bbox): """Import a bounding box (BSBound, or NiNode with bounding box).""" # calculate bounds if isinstance(bbox, NifFormat.BSBound): b_mesh = bpy.data.meshes.new('BSBound') minx = bbox.center.x - bbox.dimensions.x miny = bbox.center.y - bbox.dimensions.y minz = bbox.center.z - bbox.dimensions.z maxx = bbox.center.x + bbox.dimensions.x maxy = bbox.center.y + bbox.dimensions.y maxz = bbox.center.z + bbox.dimensions.z elif isinstance(bbox, NifFormat.NiNode): if not bbox.has_bounding_box: raise ValueError("Expected NiNode with bounding box.") b_mesh = bpy.data.meshes.new('Bounding Box') #Ninode's(bbox) internal bounding_box behaves like a seperate mesh. #bounding_box center(bbox.bounding_box.translation) is relative to the bound_box minx = bbox.bounding_box.translation.x - bbox.translation.x - bbox.bounding_box.radius.x miny = bbox.bounding_box.translation.y - bbox.translation.y - bbox.bounding_box.radius.y minz = bbox.bounding_box.translation.z - bbox.translation.z - bbox.bounding_box.radius.z maxx = bbox.bounding_box.translation.x - bbox.translation.x + bbox.bounding_box.radius.x maxy = bbox.bounding_box.translation.y - bbox.translation.y + bbox.bounding_box.radius.y maxz = bbox.bounding_box.translation.z - bbox.translation.z + bbox.bounding_box.radius.z else: raise TypeError("Expected BSBound or NiNode but got %s." % bbox.__class__.__name__) # create mesh for x in [minx, maxx]: for y in [miny, maxy]: for z in [minz, maxz]: b_mesh.vertices.add(1) b_mesh.vertices[-1].co = (x,y,z) faces = [[0,1,3,2],[6,7,5,4],[0,2,6,4],[3,1,5,7],[4,5,1,0],[7,6,2,3]] b_mesh.faces.add(len(faces)) b_mesh.faces.foreach_set("vertices_raw", unpack_face_list(faces)) # link box to scene and set transform if isinstance(bbox, NifFormat.BSBound): b_obj = bpy.data.objects.new('BSBound', b_mesh) else: b_obj = bpy.data.objects.new('Bounding Box', b_mesh) # XXX this is set in the import_branch() method #ob.matrix_local = mathutils.Matrix( # *bbox.bounding_box.rotation.as_list()) #ob.setLocation( # *bbox.bounding_box.translation.as_list()) # set bounds type b_obj.show_bounds = True b_obj.draw_type = 'BOUNDS' b_obj.draw_bounds_type = 'BOX' #quick radius estimate b_obj.game.radius = max(maxx, maxy, maxz) bpy.context.scene.objects.link(b_obj) return b_obj
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 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 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 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 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 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 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 importGMDL(file): result = {'FINISHED'} header = Header() header.read(file) triForm = TriangleFormat() triForm.read(file) vertexForm = VertexFormat() vertexForm.read(file) # Let's create the mesh 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(vertexForm.vertexCount) for v in range(len(vertexForm.vertices)): mesh.vertices[v].co = vertexForm.vertices[v].positions print("Num triangles %i" % len(triForm.triangles)) mesh.tessfaces.add(len(triForm.triangles)) mesh.tessfaces.foreach_set("vertices_raw", unpack_face_list(triForm.triangles)) if len(vertexForm.vertices[0].uvs) > 0: uvtex = mesh.tessface_uv_textures.new() uvtex.name = 'DefaultUV' for i, face in enumerate(mesh.tessfaces): uvtex.data[i].uv1 = vertexForm.vertices[face.vertices_raw[0]].uvs uvtex.data[i].uv2 = vertexForm.vertices[face.vertices_raw[1]].uvs uvtex.data[i].uv3 = vertexForm.vertices[face.vertices_raw[2]].uvs uvtex.data[i].uv4 = [0, 0] mesh.update() if len(vertexForm.vertices[0].normals) > 0: for v, vertex in enumerate(vertexForm.vertices): mesh.vertices[v].normal = vertex.normals file.close() return result
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 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 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 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 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 processSkinnedGeneral(f, blocks): verts = [] faces = [] uvs = [] texs = [] #Get Version version = struct.unpack('<B', f.read(1))[0] #Get Flag flag = struct.unpack('<I', f.read(4))[0] print("Flag: %d" % flag) #skip unknown f.read(24) #Get Textures for i in range(8): length = struct.unpack('<I', f.read(4))[0] texStr = '<%ds' % length tex = struct.unpack(texStr, f.read(length))[0].decode() texs.append(tex) print("Texture: %s" % tex) #skip unknown data f.read(4) #Check Vertice Type if(version == 0 or flag != 0x80000): #Small Vertices print("Vertex Type: Small") #Get Vertex Count vertCount = struct.unpack('<I', f.read(4))[0] print("Vertices: %d" % vertCount) for vert in range(vertCount): x = struct.unpack('<f', f.read(4))[0] y = struct.unpack('<f', f.read(4))[0] z = struct.unpack('<f', f.read(4))[0] extra1 = struct.unpack('<B', f.read(1))[0] extra2 = struct.unpack('<B', f.read(1))[0] extra3 = struct.unpack('<B', f.read(1))[0] extra4 = struct.unpack('<B', f.read(1))[0] extra5 = struct.unpack('<B', f.read(1))[0] extra6 = struct.unpack('<B', f.read(1))[0] extra7 = struct.unpack('<B', f.read(1))[0] extra8 = struct.unpack('<B', f.read(1))[0] verts.append((x, z, y)) elif(version == 3 or flag == 0x80000): #Small Vertices print("Vertex Type: Big") #Get Vertex Count vertCount = struct.unpack('<I', f.read(4))[0] print("Vertices: %d" % vertCount) for vert in range(vertCount): x = struct.unpack('<f', f.read(4))[0] y = struct.unpack('<f', f.read(4))[0] z = struct.unpack('<f', f.read(4))[0] extra1 = struct.unpack('<I', f.read(4))[0] extra2 = struct.unpack('<I', f.read(4))[0] extra3 = struct.unpack('<i', f.read(4))[0] extra4 = struct.unpack('<I', f.read(4))[0] verts.append((x, z, y)) #Process Extra Data uvCount = struct.unpack('<I', f.read(4))[0] print("UVs: %d" % uvCount) for uv in range(uvCount): r = struct.unpack('<I', f.read(4))[0] g = struct.unpack('<I', f.read(4))[0] b = struct.unpack('<I', f.read(4))[0] u = struct.unpack('<f', f.read(4))[0] v = struct.unpack('<f', f.read(4))[0] uvs.append((u, 1-v)) #Process SkinBatch/Weights skinCount = struct.unpack('<I', f.read(4))[0] print("Skin: %d" % skinCount) for skin in range(skinCount): #skip unknown data f.read(8) #weights weightCount = struct.unpack('<I', f.read(4))[0] print("Weights: %d" % weightCount) for weight in range(weightCount): w = struct.unpack('<H', f.read(2)) #print("Weight: %d" % w) #process faces faceCount = struct.unpack('<I', f.read(4))[0] print("Faces: %d" % faceCount) for face in range(int(faceCount/3)): vert1 = struct.unpack('<H', f.read(2))[0] vert2 = struct.unpack('<H', f.read(2))[0] vert3 = struct.unpack('<H', f.read(2))[0] faces.append((vert1, vert3, vert2)) #Read Check check = struct.unpack('<I', f.read(4))[0] #Add object data mesh = bpy.data.meshes.new("Mesh") mesh.vertices.add(vertCount) mesh.tessfaces.add(faceCount/3) mesh.vertices.foreach_set("co", unpack_list(verts)) mesh.tessfaces.foreach_set("vertices_raw", unpack_face_list(faces)) mesh.tessface_uv_textures.new() for face in range(int(faceCount/3)): uv = mesh.tessface_uv_textures[0].data[face] uv.uv1 = uvs[faces[face][0]] uv.uv2 = uvs[faces[face][1]] uv.uv3 = uvs[faces[face][2]] mesh.validate() mesh.update() obj = bpy.data.objects.new("Mesh_SkinnedGeneral_0", mesh) blocks.append(obj)
def load_ply(filepath): import time from bpy_extras.io_utils import unpack_face_list # from bpy_extras.image_utils import load_image # UNUSED t = time.time() obj_spec, obj = read(filepath) if obj is None: print('Invalid file') return uvindices = colindices = None colmultiply = None # noindices = None # Ignore normals for el in obj_spec.specs: if el.name == b'vertex': vindices_x, vindices_y, vindices_z = el.index(b'x'), el.index(b'y'), el.index(b'z') # noindices = (el.index('nx'), el.index('ny'), el.index('nz')) # if -1 in noindices: noindices = None uvindices = (el.index(b's'), el.index(b't')) if -1 in uvindices: uvindices = None colindices = el.index(b'red'), el.index(b'green'), el.index(b'blue') if -1 in colindices: colindices = None else: # if not a float assume uchar colmultiply = [1.0 if el.properties[i].numeric_type in {'f', 'd'} else (1.0 / 256.0) for i in colindices] elif el.name == b'face': findex = el.index(b'vertex_indices') mesh_faces = [] mesh_uvs = [] mesh_colors = [] def add_face(vertices, indices, uvindices, colindices): mesh_faces.append(indices) if uvindices: mesh_uvs.append([(vertices[index][uvindices[0]], 1.0 - vertices[index][uvindices[1]]) for index in indices]) if colindices: mesh_colors.append([(vertices[index][colindices[0]] * colmultiply[0], vertices[index][colindices[1]] * colmultiply[1], vertices[index][colindices[2]] * colmultiply[2], ) for index in indices]) if uvindices or colindices: # If we have Cols or UVs then we need to check the face order. add_face_simple = add_face # EVIL EEKADOODLE - face order annoyance. def add_face(vertices, indices, uvindices, colindices): if len(indices) == 4: if indices[2] == 0 or indices[3] == 0: indices = indices[2], indices[3], indices[0], indices[1] elif len(indices) == 3: if indices[2] == 0: indices = indices[1], indices[2], indices[0] add_face_simple(vertices, indices, uvindices, colindices) verts = obj[b'vertex'] if b'face' in obj: for f in obj[b'face']: ind = f[findex] len_ind = len(ind) if len_ind <= 4: add_face(verts, ind, uvindices, colindices) else: # Fan fill the face for j in range(len_ind - 2): add_face(verts, (ind[0], ind[j + 1], ind[j + 2]), uvindices, colindices) ply_name = bpy.path.display_name_from_filepath(filepath) mesh = bpy.data.meshes.new(name=ply_name) mesh.vertices.add(len(obj[b'vertex'])) mesh.vertices.foreach_set("co", [a for v in obj[b'vertex'] for a in (v[vindices_x], v[vindices_y], v[vindices_z])]) if mesh_faces: mesh.faces.add(len(mesh_faces)) mesh.faces.foreach_set("vertices_raw", unpack_face_list(mesh_faces)) if uvindices or colindices: if uvindices: uvlay = mesh.uv_textures.new() if colindices: vcol_lay = mesh.vertex_colors.new() if uvindices: for i, f in enumerate(uvlay.data): ply_uv = mesh_uvs[i] for j, uv in enumerate(f.uv): uv[0], uv[1] = ply_uv[j] if colindices: for i, f in enumerate(vcol_lay.data): # XXX, colors dont come in right, needs further investigation. ply_col = mesh_colors[i] if len(ply_col) == 4: f_col = f.color1, f.color2, f.color3, f.color4 else: f_col = f.color1, f.color2, f.color3 for j, col in enumerate(f_col): col.r, col.g, col.b = ply_col[j] mesh.validate() mesh.update() scn = bpy.context.scene #scn.objects.selected = [] # XXX25 obj = bpy.data.objects.new(ply_name, mesh) scn.objects.link(obj) scn.objects.active = obj obj.select = True print('\nSuccessfully imported %r in %.3f sec' % (filepath, time.time() - t))
def processDeformableWindow(f, blocks): verts = [] faces = [] uvs = [] texs = [] print("44 Bytes") #Get Version version = struct.unpack('<B', f.read(1))[0] #Get Textures for i in range(8): length = struct.unpack('<I', f.read(4))[0] texStr = '<%ds' % length tex = struct.unpack(texStr, f.read(length))[0].decode() texs.append(tex) print("Texture: %s" % tex) #skip unknown data f.read(4) #skip unknown data if(version == 2): f.read(1024) #Get Vertices vertCount = struct.unpack('<I', f.read(4))[0] print("Vertices: %d" % vertCount) for vert in range(vertCount): x = struct.unpack('<f', f.read(4))[0] y = struct.unpack('<f', f.read(4))[0] z = struct.unpack('<f', f.read(4))[0] w = struct.unpack('<f', f.read(4))[0] extra1 = struct.unpack('<f', f.read(4))[0] extra2 = struct.unpack('<f', f.read(4))[0] extra3 = struct.unpack('<f', f.read(4))[0] extra4 = struct.unpack('<f', f.read(4))[0] extra5 = struct.unpack('<f', f.read(4))[0] extra6 = struct.unpack('<f', f.read(4))[0] u = struct.unpack('<f', f.read(4))[0] v = struct.unpack('<f', f.read(4))[0] verts.append((x, z, y)) uvs.append((u, 1-v)) #Get Faces faceCount = struct.unpack('<I', f.read(4))[0] print("Faces: %d" % faceCount) for face in range(int(faceCount/3)): vert1 = struct.unpack('<H', f.read(2))[0] vert2 = struct.unpack('<H', f.read(2))[0] vert3 = struct.unpack('<H', f.read(2))[0] faces.append((vert1, vert3, vert2)) #skip unknown data if(version == 1): f.read(1024) #Read Check check = struct.unpack('<I', f.read(4))[0] #Add object data mesh = bpy.data.meshes.new("Mesh") mesh.vertices.add(vertCount) mesh.tessfaces.add(faceCount/3) mesh.vertices.foreach_set("co", unpack_list(verts)) mesh.tessfaces.foreach_set("vertices_raw", unpack_face_list(faces)) mesh.tessface_uv_textures.new() for face in range(int(faceCount/3)): uv = mesh.tessface_uv_textures[0].data[face] uv.uv1 = uvs[faces[face][0]] uv.uv2 = uvs[faces[face][1]] uv.uv3 = uvs[faces[face][2]] mesh.validate() mesh.update() obj = bpy.data.objects.new("Mesh_DeformableWindow_0", mesh) blocks.append(obj)
def ReadMesh(self, mesh): print("Name: {}".format(mesh["name"])) print("Num Verts: {}".format(len(mesh["vertices"]))) print("Num Indices: {}".format(len(mesh["indices"][0]))) scn = bpy.context.scene for o in scn.objects: o.select = False blenmesh = bpy.data.meshes.new(mesh["name"]) blenmesh.vertices.add(len(mesh["vertices"])) blenmesh.vertices.foreach_set("co", unpack_list(mesh["vertices"])) blenmesh.tessfaces.add(len(mesh["indices"][0])) # Add faces blenmesh.tessfaces.foreach_set("vertices_raw", unpack_face_list(mesh["indices"][0])) uvlay = blenmesh.tessface_uv_textures.new() for i, f in enumerate(uvlay.data): index = mesh["indices"][0][i] for j, uv in enumerate(f.uv): uv[0] = mesh["uvs"][index[j]][0] uv[1] = mesh["uvs"][index[j]][1] #add object to scene blenmesh.update() blenmesh.validate() nobj = bpy.data.objects.new(mesh["name"], blenmesh) scn.objects.link(nobj) #print("Skel: {}".format(mesh["skeleton"])) # Create Armature and Object bpy.ops.object.add(type='ARMATURE', enter_editmode=True) object = bpy.context.object object.name = 'armguy' armature = object.data armature.name = 'armguy' #create bones for the_bone in mesh["skeleton"]: nobj.vertex_groups.new(name=the_bone["name"]) bone = armature.edit_bones.new(the_bone["name"]) bone.tail = Vector([0,0,0.1]) # if you won't do it, the bone will have zero lenghtand will be removed immediately by Blender #map parents for the_bone in mesh["skeleton"]: if 'parent' in the_bone: armature.edit_bones[the_bone['name']].parent = armature.edit_bones[the_bone['parent']] parent = self.FindBoneByName(mesh["skeleton"], the_bone['parent']) for the_bone in mesh["skeleton"]: matrix = Matrix(the_bone["matrix"]) matrix.transpose() matrix = matrix.inverted() armature.edit_bones[the_bone['name']].transform(matrix) for vidx in range(0, len(mesh["vertices"])): bones = mesh["bone_indices"][0][vidx] weights = mesh["weights"][0][vidx] print("Vertex: {}".format(vidx)) print("Data: {} {}".format(bones, weights)) for widx in range(0, len(weights)): bone_idx = bones[widx] if bone_idx == 0: break weight = weights[widx] nobj.vertex_groups[bone_idx].add([vidx], weight, 'ADD') # for vwidx, wval in enumerate(mesh["weights"][0]): # bones = mesh["bone_indices"][0][vwidx] # print("Vertex: {}".format(vwidx)) # print("Data: {} {}".format(bones, wval)) # for vwsidx, vwsval in enumerate(wval): # bone_idx = bones[vwsidx] # the_bone = mesh["skeleton"][bone_idx] # print("Bone: {} ({}): {}".format(bone_idx, the_bone["name"], vwsval)) # nobj.vertex_groups[bone_idx].add([vwidx], vwsval, 'ADD') return nobj
def makeObject(self): print("Creating mesh", end='') # Create the mesh mesh = bpy.data.meshes.new(self.name) mesh.tessface_uv_textures.new() # Skins if self.numSkins > 0: material = bpy.data.materials.new(self.name) for skin in self.skins: skinImg = Util.loadImage(skin, self.filePath) skinImg.mapping = 'UV' 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='') # 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].verts)) 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='') # 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: for i, frame in enumerate(self.frames): progressStatus = i / self.numFrames * 100 #bpy.context.scene.frame_set(i + 1) obj.shape_key_add(name=frame.name, from_mix=False) mesh.vertices.foreach_set("co", unpack_list(frame.verts)) 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%.") print("Model imported")
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 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 createMesh(self): model = self.model vertexClass = None if model.vFlags == 0x180007d: return # no vertices vertexClassName = "VertexFormat" + hex(self.model.vFlags) if not vertexClassName in m3.structMap: raise Exception("Vertex flags %s can't behandled yet" % hex(self.model.vFlags)) vertexClass = m3.structMap[vertexClassName] numberOfVertices = len(self.model.vertices) // vertexClass.size m3Vertices = vertexClass.createInstances(rawBytes=self.model.vertices, count=numberOfVertices) for division in self.model.divisions: divisionFaceIndices = division.faces for region in division.regions: bpy.ops.object.mode_set(mode='OBJECT') regionVertexIndices = range(region.firstVertexIndex,region.firstVertexIndex + region.numberOfVertices) firstVertexIndexIndex = region.firstFaceVertexIndexIndex lastVertexIndexIndex = firstVertexIndexIndex + region.numberOfFaceVertexIndices vertexIndexIndex = firstVertexIndexIndex firstVertexIndex = region.firstVertexIndex assert region.numberOfFaceVertexIndices % 3 == 0 facesWithOldIndices = [] # old index = index of vertex in m3Vertices while vertexIndexIndex + 2 <= lastVertexIndexIndex: i0 = firstVertexIndex + divisionFaceIndices[vertexIndexIndex] i1 = firstVertexIndex + divisionFaceIndices[vertexIndexIndex + 1] i2 = firstVertexIndex + divisionFaceIndices[vertexIndexIndex + 2] face = (i0, i1, i2) facesWithOldIndices.append(face) vertexIndexIndex += 3 mesh = bpy.data.meshes.new('Mesh') meshObject = bpy.data.objects.new('MeshObject', mesh) meshObject.location = (0,0,0) meshObject.show_name = True bpy.context.scene.objects.link(meshObject) # merge vertices together which have always the same position and normal: # This way there are not only fewer vertices to edit, # but also the calculated normals will more likly match # the given ones. vertexPositions = [] nextNewVertexIndex = 0 oldVertexIndexToNewVertexIndexMap = {} vertexIdTupleToNewIndexMap = {} for vertexIndex in regionVertexIndices: m3Vertex = m3Vertices[vertexIndex] v = m3Vertex idTuple = (v.position.x, v.position.y, v.position.z, v.boneWeight0, v.boneWeight1, v.boneWeight2, v.boneWeight3, v.boneLookupIndex0, v.boneLookupIndex1, v.boneLookupIndex2, v.boneLookupIndex3, v.normal.x, v.normal.y, v.normal.z) newIndex = vertexIdTupleToNewIndexMap.get(idTuple) if newIndex == None: newIndex = nextNewVertexIndex nextNewVertexIndex += 1 position = (m3Vertex.position.x, m3Vertex.position.y, m3Vertex.position.z) vertexPositions.append(position) vertexIdTupleToNewIndexMap[idTuple] = newIndex oldVertexIndexToNewVertexIndexMap[vertexIndex] = newIndex # since vertices got merged, the indices of the faces aren't correct anymore. # the old face indices however are still later required to figure out # what Uv coordinates a face has. facesWithNewIndices = [] for faceWithOldIndices in facesWithOldIndices: i0 = oldVertexIndexToNewVertexIndexMap[faceWithOldIndices[0]] i1 = oldVertexIndexToNewVertexIndexMap[faceWithOldIndices[1]] i2 = oldVertexIndexToNewVertexIndexMap[faceWithOldIndices[2]] faceWithNewIndices = (i0, i1, i2) facesWithNewIndices.append(faceWithNewIndices) mesh.vertices.add(len(vertexPositions)) mesh.vertices.foreach_set("co", io_utils.unpack_list(vertexPositions)) mesh.tessfaces.add(len(facesWithNewIndices)) mesh.tessfaces.foreach_set("vertices_raw", io_utils.unpack_face_list(facesWithNewIndices)) for vertexUVAttribute in ["uv0", "uv1", "uv2", "uv3"]: if vertexUVAttribute in vertexClass.fieldToTypeInfoMap: uvLayer = mesh.tessface_uv_textures.new() for faceIndex, face in enumerate(facesWithOldIndices): faceUV = uvLayer.data[faceIndex] faceUV.uv1 = toBlenderUVCoordinate(getattr(m3Vertices[face[0]],vertexUVAttribute)) faceUV.uv2 = toBlenderUVCoordinate(getattr(m3Vertices[face[1]],vertexUVAttribute)) faceUV.uv3 = toBlenderUVCoordinate(getattr(m3Vertices[face[2]],vertexUVAttribute)) mesh.update(calc_edges=True) boneIndexLookup = model.boneLookup[region.firstBoneLookupIndex:region.firstBoneLookupIndex + region.numberOfBoneLookupIndices] vertexGroupLookup = [] for boneIndex in boneIndexLookup: boneName = shared.toValidBoneName(model.bones[boneIndex].name) if boneName in meshObject.vertex_groups: vertexGroup = meshObject.vertex_groups[boneName] else: vertexGroup = meshObject.vertex_groups.new(boneName) vertexGroupLookup.append(vertexGroup) for vertexIndex in range(region.firstVertexIndex,region.firstVertexIndex + region.numberOfVertices): m3Vertex = m3Vertices[vertexIndex] boneWeightsAsInt = [m3Vertex.boneWeight0, m3Vertex.boneWeight1, m3Vertex.boneWeight2, m3Vertex.boneWeight3] boneLookupIndices = [m3Vertex.boneLookupIndex0, m3Vertex.boneLookupIndex1, m3Vertex.boneLookupIndex2, m3Vertex.boneLookupIndex3] boneWeights = [] for boneWeightAsInt, boneLookupIndex in zip(boneWeightsAsInt, boneLookupIndices): if boneWeightAsInt != 0: vertexGroup = vertexGroupLookup[boneLookupIndex] boneWeight = boneWeightAsInt / 255.0 vertexGroup.add([oldVertexIndexToNewVertexIndexMap[vertexIndex]], boneWeight, 'REPLACE') modifier = meshObject.modifiers.new('UseArmature', 'ARMATURE') modifier.object = self.armatureObject modifier.use_bone_envelopes = False modifier.use_vertex_groups = True
def load(operator, context, filepath, global_clamp_size=0.0, use_verbose=False, use_image_search=True, use_computed_normals=False, use_shadeless=True, viz_normals=True, viz_blendweights=False, use_specular=True, global_matrix=None, ): ''' 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() # time_sub= sys.time() file = open(filepath, "rb") crf_magick, = struct.unpack("<Q", file.read(8)) if crf_magick != 0x1636E6B66: print("Not a CRF file!") return footer_offset1,footer_offset2 = struct.unpack("<II", file.read(8)) # so far found model type 0x2 and 0x4 object_type, magick4, num_meshes_in_file = struct.unpack("<III", file.read(12)) LoX, LoY, LoZ = struct.unpack("<fff", file.read(12)) HiX, HiY, HiZ = struct.unpack("<fff", file.read(12)) #bounding box? print("(%f, %f, %f) (%f, %f, %f)" % (LoX, LoY, LoZ, HiX, HiY, HiZ)) print("Object type", hex(object_type)) # start unpacking loop here for model_number in range(0, num_meshes_in_file): 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 = [] number_of_verteces, = struct.unpack("<I", file.read(4)) number_of_faces, = struct.unpack("<I", file.read(4)) print("Model: %i, verteces: %i, faces: %i" % (model_number, number_of_verteces, number_of_faces)) # read in face/vertex index list for i in range(0, number_of_faces): v1, v2, v3 = struct.unpack("<HHH", file.read(6)) face_vert_loc_indices = [v1, v2, v3] face_vert_tex_indices = [v1, v2, v3] faces.append((v1, v2, v3)) if use_verbose: print("face index %s, verts (%s, %s, %s)" % (i, v1, v2, v3)) #read start token #0x0000200c01802102, 0x00 start_token, = struct.unpack("<Qx", file.read(9)) if use_verbose: print("Loading file, printing raw vertex information.") # read in verteces, vertex normals, ks, and UVs for i in range(0, number_of_verteces): vertex = CRF_vertex() vertex.index = i vertex.x, vertex.y, vertex.z, \ vertex.normal_x, vertex.normal_y, vertex.normal_z, vertex.normal_w, \ vertex.specular_blue, vertex.specular_green, vertex.specular_red, vertex.specular_alpha, \ vertex.u0, vertex.v0, vertex.u1, vertex.v1, \ vertex.blendweights1_x, vertex.blendweights1_y, \ vertex.blendweights1_z, vertex.blendweights1_w = struct.unpack("<fffBBBBBBBBhhhhBBBB", file.read(32)) vertex.raw2blend() if use_verbose: print(vertex) 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) ) #read in separator 0x000000080008000000 #TODO not all files have this separator print("Separator at", hex(file.tell())) separator = struct.unpack("<8B", file.read(8)) if use_verbose: print("Second vertex data stream at", hex(file.tell())) #read in second vertex stream, but don't use it for anything #TODO figure out why this is here for i in range(0, number_of_verteces): unknown0, unknown1 = struct.unpack("<ff", file.read(8)) if use_verbose: print("vert index=%s, x?=%s, y?=%s" % (i, unknown0, unknown1)) #if object type is 0x4, read in second set of blendweights #TODO not sure how this data is used if object_type == 0x4: if use_verbose: print("Second blendweight? list at", hex(file.tell())) unknown1, unknown2 = struct.unpack("<II", file.read(8)) for i in range(0, number_of_verteces): blendweights2, = struct.unpack("<I", file.read(4)) if use_verbose: print(i, blendweights2) # read in one more int #file.read(8) print(hex(file.tell())) #read in bounding box? bounding_box = struct.unpack("<6f", file.read(24)) if use_verbose: print("Bounding box? ", bounding_box) #read in material information texture_name = b'' normal_name = b'' specular_name = b'' specular_list = [] texture_name, normal_name, specular_name = parseMaterialInfo(file, specular_list) print(texture_name, normal_name, specular_name, specular_list) #next is object bone information, not parsed # deselect all if bpy.ops.object.select_all.poll(): bpy.ops.object.select_all(action='DESELECT') scene = context.scene # scn.objects.selected = [] 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" % model_number, me) # Fill the mesh with verts, edges, faces from bpy_extras.io_utils import unpack_list 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)) #me.update(calc_edges=True) # Update mesh with new data and in 2.63 convert tessfaces to poly # 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] ] ) if use_image_search: uvMain = createTextureLayer("UV_Main", me, face_tex) texture_filepath = findTextureFile(os.fsdecode(filepath), texture_name.decode(sys.stdout.encoding)) normals_filepath = findTextureFile(os.fsdecode(filepath), normal_name.decode(sys.stdout.encoding)) specular_filepath = findTextureFile(os.fsdecode(filepath), specular_name.decode(sys.stdout.encoding)) print(texture_filepath, normals_filepath, specular_filepath) mat = createMaterial('TexMat', use_shadeless, viz_normals) if texture_filepath != None and texture_filepath != "": addDiffuseTexture(texture_filepath, mat) if normals_filepath != None and normals_filepath != "": addNormalTexture(normals_filepath, mat) if use_specular and specular_filepath != None and specular_filepath != "": addSpecularTexture(specular_filepath, mat) ob.data.materials.append(mat) if viz_normals: setVertexNormalsColors(me, ob.data.tessfaces, vertex_normals) # if no materials exist, create one+ if len(ob.data.materials) == 0 and not use_image_search: mat = createMaterial('SimpleMat', use_shadeless, viz_normals) ob.data.materials.append(mat) 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] if use_specular: setVertexSpecularColors(me, ob.data.tessfaces, vertex_specular) # if no materials exist, create one+ if len(ob.data.materials) == 0 and not use_image_search: mat = createMaterial('Specular', use_shadeless, viz_normals) mat.specular_color = specular_list[0] ob.data.materials.append(mat) else: #ob.data.materials[0] = specular_list[0] ob.data.materials[0].specular_color = specular_list[0] print(ob.data.materials[0].specular_color) if viz_blendweights: setVertexBlendweightColors(me, ob.data.tessfaces, vertex_blendweights1) # if no materials exist, create one+ if len(ob.data.materials) == 0 and not use_image_search: mat = createMaterial('BlendweightMat', use_shadeless, True) ob.data.materials.append(mat) me.update(calc_tessface=True, calc_edges=True) new_objects.append(ob) # end loop 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 for obj in new_objects: base = scene.objects.link(obj) base.select = True # we could apply this anywhere before scaling. obj.matrix_world = global_matrix 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 create_blender_object(self, ac_matlist, str_pre, bLevelLinked): if self.type == 'world': self.name = self.import_config.ac_name self.rotation = self.import_config.global_matrix me = None if self.type == 'group': # Create an empty object self.bl_obj = bpy.data.objects.new(self.name, None) if self.type == 'poly': meshname = self.name if len(self.data)>0: meshname = self.data me = bpy.data.meshes.new(meshname) self.bl_obj = bpy.data.objects.new(self.name, me) # setup parent object if self.ac_parent: self.bl_obj.parent = self.ac_parent.bl_obj # make sure we have something to work with if self.vert_list and me: me.use_auto_smooth = self.import_config.use_auto_smooth me.auto_smooth_angle = radians(self.crease) for surf in self.surf_list: surf_edges = surf.get_edges() surf_face = surf.get_faces() for edge in surf_edges: self.edge_list.append(edge) if surf.flags.type == 0: # test for invalid face (ie, >4 vertices) if len(surf.refs) > 4 or len(surf.refs) < 3: # not bringing in faces (assumed that there are none in a poly-line) TRACE("Ignoring surface (vertex-count: {0})".format(len(surf.refs))) else: self.face_list.append(surf_face) # Material index is 1 based, the list we built is 0 based ac_material = ac_matlist[surf.mat_index] bl_material = ac_material.get_blender_material(self.tex_name) if bl_material == None: TRACE("Error getting material {0} '{1}'".format(surf.mat_index, self.tex_name)) fm_index = 0 if not bl_material.name in me.materials: me.materials.append(bl_material) fm_index = len(me.materials)-1 else: for mat in me.materials: if mat == bl_material: continue fm_index += 1 if fm_index > len(me.materials): TRACE("Failed to find material index") fm_index = 0 self.face_mat_list.append(fm_index) else: # treating as a polyline (nothing more to do) pass me.vertices.add(len(self.vert_list)) me.tessfaces.add(len(self.face_list)) # verts_loc is a list of (x, y, z) tuples me.vertices.foreach_set("co", unpack_list(self.vert_list)) # faces is a list of (vert_indices, texco_indices, ...) tuples me.tessfaces.foreach_set("vertices_raw", unpack_face_list(self.face_list)) # face_mat = [m for m in self.face_mat_list] # me.tessfaces.foreach_set("material_index", face_mat) # del face_mat if len(self.tex_name): me.tessface_uv_textures.new() # uv_tex.active = True # uv_tex.active_render = True else: uv_tex = None two_sided_lighting = False for i, face in enumerate(self.face_list): blender_face = me.tessfaces[i] surf = self.surf_list[i] blender_face.use_smooth = surf.flags.shaded # If one surface is twosided, they all will be... two_sided_lighting |= surf.flags.two_sided if len(self.tex_name) and len(surf.uv_refs) >= 3: blender_tface = me.tessface_uv_textures[0].data[i] blender_tface.uv1 = surf.uv_refs[0] blender_tface.uv2 = surf.uv_refs[1] blender_tface.uv3 = surf.uv_refs[2] if len(surf.uv_refs) > 3: blender_tface.uv4 = surf.uv_refs[3] surf_material = me.materials[self.face_mat_list[i]] blender_tface.image = surf_material.texture_slots[0].texture.image # uv_tex.data[f_index].use_image = True me.show_double_sided = two_sided_lighting self.bl_obj.show_transparent = self.import_config.display_transparency if self.bl_obj: self.bl_obj.rotation_euler = self.rotation.to_euler() self.bl_obj.location = self.location self.import_config.context.scene.objects.link(self.bl_obj) # There's a bug somewhere - this ought to work.... self.import_config.context.scene.objects.active = self.bl_obj # bpy.ops.object.origin_set('ORIGIN_GEOMETRY', 'MEDIAN') TRACE("{0}+-{1} ({2})".format(str_pre, self.name, self.data)) # Add any children str_pre_new = "" bUseLink = True for obj in self.children: if bLevelLinked: str_pre_new = str_pre + "| " else: str_pre_new = str_pre + " " if self.children.index(obj) == len(self.children)-1: bUseLink = False obj.create_blender_object(ac_matlist, str_pre_new, bUseLink) if me: # me.calc_normals() me.validate() me.update(calc_edges=True)
def FLDSMDFR(self, file_gpu): file_gpu.seek(self.mesh_header.mesh_dataStart, 0) self.byte_count = self.mesh_header.vertexCount * self.m0.stride ti_0 = np.fromfile(file_gpu, dtype='B', count=self.byte_count).reshape( (self.mesh_header.vertexCount, self.m0.stride)) for x in cat_list: cat(self.m0.data, x) for p in self.m0.data: g = self.m0.data[p] chunc = data_paver(g["start"], g["end"], self.mesh_header.vertexCount, g["item_subCount"], g["d_type"], ti_0) if p == "POSITION0": chunc[:, [1, 2]] = chunc[:, [2, 1]] self.VA = chunc.tolist() elif p == "BLENDINDICES": self.bone_ids = chunc.tolist() elif p == "BLENDWEIGHTS": self.weights = chunc.tolist() chunk2_start = self.mesh_header.mesh_dataStart + self.m1.offset byteCount2 = self.mesh_header.vertexCount * self.m1.stride file_gpu.seek(chunk2_start, 0) ti_1 = np.fromfile(file_gpu, dtype='B', count=byteCount2).reshape( (self.mesh_header.vertexCount, self.m1.stride)) uv_count = 0 for j in self.m1.data: z = self.m1.data[j] chunc = data_paver(z["start"], z["end"], self.mesh_header.vertexCount, z["item_subCount"], z["d_type"], ti_1) if j == "NORMAL0": Normal_Array0 = chunc[:, 0:3].reshape( (self.mesh_header.vertexCount, 3)) Normal_Array0[:, [1, 2]] = Normal_Array0[:, [2, 1]] Normal_Array = Normal_Array0.tolist() elif j == "TANGENT0": pass elif j == "TEXCOORD0": uv_count += 1 chunc[:, 1:2] *= -1 chunc[:, 1:2] += 1 uvData0 = chunc.tolist() self.UVs0 = [mu.Vector(x) for x in uvData0] elif j == "TEXCOORD1": uv_count += 1 chunc[:, 1:2] *= -1 chunc[:, 1:2] += 1 uvData1 = chunc.tolist() self.UVs1 = [mu.Vector(x) for x in uvData1] elif j == "TEXCOORD2": uv_count += 1 chunc[:, 1:2] *= -1 chunc[:, 1:2] += 1 uvData2 = chunc.tolist() self.UVs2 = [mu.Vector(x) for x in uvData2] elif j == "TEXCOORD3": uv_count += 1 chunc[:, 1:2] *= -1 chunc[:, 1:2] += 1 uvData3 = chunc.tolist() self.UVs3 = [mu.Vector(x) for x in uvData3] elif j == "NORMAL4FACTORS0": pass elif j == "NORMAL2FACTORS0": pass mesh = bpy.data.meshes.new(self.name) mesh.vertices.add(len(self.VA)) mesh.tessfaces.add(len(self.faces)) mesh.vertices.foreach_set("co", unpack_list(self.VA)) mesh.tessfaces.foreach_set("vertices_raw", unpack_face_list(self.faces)) for g in range(uv_count): mesh.tessface_uv_textures.new() me_faces = mesh.tessfaces ''' for f, g in enumerate(mesh.vertices): g.normal = Normal_Array[f] ''' # UVs UVS = 0 for g in range(uv_count): if g == 0: UVS = self.UVs0 elif g == 1: UVS = self.UVs1 elif g == 2: UVS = self.UVs2 elif g == 3: UVS = self.UVs3 for i, face in enumerate(self.faces): idx = self.faces[i] blender_tface = mesh.tessface_uv_textures[g].data[i] blender_tface.uv1 = UVS[face[0]] blender_tface.uv2 = UVS[face[1]] blender_tface.uv3 = UVS[face[2]] mesh.validate() mesh.update() self.meshObject = bpy.data.objects.new(self.name, mesh) if self.V_28: bpy.context.scene.collection.objects.link(self.meshObject) self.meshObject.select_set("SELECT") else: bpy.context.scene.objects.link(self.meshObject) self.meshObject.select = True mesh.polygons.foreach_set("use_smooth", [True] * len(mesh.polygons)) bpy.context.scene.update()
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 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 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 create_blender_object(self, ac_matlist, str_pre, bLevelLinked): if self.type == 'world': self.name = self.import_config.ac_name self.rotation = self.import_config.global_matrix me = None if self.type == 'group': # Create an empty object self.bl_obj = bpy.data.objects.new(self.name, None) if self.type == 'poly': meshname = self.name if len(self.data) > 0: meshname = self.data me = bpy.data.meshes.new(meshname) self.bl_obj = bpy.data.objects.new(self.name, me) # setup parent object if self.ac_parent: self.bl_obj.parent = self.ac_parent.bl_obj # make sure we have something to work with if self.vert_list and me: me.use_auto_smooth = self.import_config.use_auto_smooth me.auto_smooth_angle = radians(self.crease) for surf in self.surf_list: surf_edges = surf.get_edges() surf_face = surf.get_faces() for edge in surf_edges: self.edge_list.append(edge) if surf.flags.type == 0: # test for invalid face (ie, >4 vertices) if len(surf.refs) > 4 or len(surf.refs) < 3: # not bringing in faces (assumed that there are none in a poly-line) TRACE("Ignoring surface (vertex-count: {0})".format( len(surf.refs))) else: self.face_list.append(surf_face) # Material index is 1 based, the list we built is 0 based ac_material = ac_matlist[surf.mat_index] bl_material = ac_material.get_blender_material( self.tex_name) if bl_material == None: TRACE("Error getting material {0} '{1}'".format( surf.mat_index, self.tex_name)) fm_index = 0 if not bl_material.name in me.materials: me.materials.append(bl_material) fm_index = len(me.materials) - 1 else: for mat in me.materials: if mat == bl_material: continue fm_index += 1 if fm_index > len(me.materials): TRACE("Failed to find material index") fm_index = 0 self.face_mat_list.append(fm_index) else: # treating as a polyline (nothing more to do) pass me.vertices.add(len(self.vert_list)) me.tessfaces.add(len(self.face_list)) # verts_loc is a list of (x, y, z) tuples me.vertices.foreach_set("co", unpack_list(self.vert_list)) # faces is a list of (vert_indices, texco_indices, ...) tuples me.tessfaces.foreach_set("vertices_raw", unpack_face_list(self.face_list)) # face_mat = [m for m in self.face_mat_list] # me.tessfaces.foreach_set("material_index", face_mat) # del face_mat if len(self.tex_name): me.tessface_uv_textures.new() # uv_tex.active = True # uv_tex.active_render = True else: uv_tex = None two_sided_lighting = False for i, face in enumerate(self.face_list): blender_face = me.tessfaces[i] surf = self.surf_list[i] blender_face.use_smooth = surf.flags.shaded # If one surface is twosided, they all will be... two_sided_lighting |= surf.flags.two_sided if len(self.tex_name) and len(surf.uv_refs) >= 3: blender_tface = me.tessface_uv_textures[0].data[i] blender_tface.uv1 = surf.uv_refs[0] blender_tface.uv2 = surf.uv_refs[1] blender_tface.uv3 = surf.uv_refs[2] if len(surf.uv_refs) > 3: blender_tface.uv4 = surf.uv_refs[3] surf_material = me.materials[self.face_mat_list[i]] blender_tface.image = surf_material.texture_slots[ 0].texture.image # uv_tex.data[f_index].use_image = True me.show_double_sided = two_sided_lighting self.bl_obj.show_transparent = self.import_config.display_transparency if self.bl_obj: self.bl_obj.rotation_euler = self.rotation.to_euler() self.bl_obj.location = self.location self.import_config.context.scene.objects.link(self.bl_obj) # There's a bug somewhere - this ought to work.... self.import_config.context.scene.objects.active = self.bl_obj # bpy.ops.object.origin_set('ORIGIN_GEOMETRY', 'MEDIAN') TRACE("{0}+-{1} ({2})".format(str_pre, self.name, self.data)) # Add any children str_pre_new = "" bUseLink = True for obj in self.children: if bLevelLinked: str_pre_new = str_pre + "| " else: str_pre_new = str_pre + " " if self.children.index(obj) == len(self.children) - 1: bUseLink = False obj.create_blender_object(ac_matlist, str_pre_new, bUseLink) if me: # me.calc_normals() me.validate() me.update(calc_edges=True)
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 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_vg = [], [], [], [] 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 = [] vg, vg_names = gather_vg(model.vertexarrays, m) 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 g = tuple([g[i][0] for g in vg]) if len(vg) > 0 else None key = p, n, b, g if not key in weld: weld[key] = len(out_vp) out_vp.append(p) out_vn.append(n) out_vb.append(b) out_vg.append(g) out_from_in.append(weld[key]) vt, vt_names = gather_vt(model.vertexarrays, m) vc, vc_names = gather_vc(model.vertexarrays, m) print("texcoords:", vt_names) print("colors:", vc_names) print("groups:", vg_names) 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]) # Non-skinning vertex groups for k, name in enumerate(vg_names): vgroup = obj.vertex_groups.new(name) for i, g in enumerate(out_vg): vgroup.add([i], g[k], 'REPLACE') # Vertex groups and armature modifier for skinning if amtobj: for iqbone in model.bones: obj.vertex_groups.new(iqbone[0]) for vgroup in obj.vertex_groups: for i, b in enumerate(out_vb): idx, wgt = b[0] if idx == vgroup.index: vgroup.add([i], wgt, '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 load_ply_mesh(filepath, ply_name): from bpy_extras.io_utils import unpack_face_list # from bpy_extras.image_utils import load_image # UNUSED obj_spec, obj, texture = read(filepath) if obj is None: print('Invalid file') return uvindices = colindices = None colmultiply = None # noindices = None # Ignore normals for el in obj_spec.specs: if el.name == b'vertex': vindices_x, vindices_y, vindices_z = el.index(b'x'), el.index(b'y'), el.index(b'z') # noindices = (el.index('nx'), el.index('ny'), el.index('nz')) # if -1 in noindices: noindices = None uvindices = (el.index(b's'), el.index(b't')) if -1 in uvindices: uvindices = None colindices = el.index(b'red'), el.index(b'green'), el.index(b'blue') if -1 in colindices: colindices = None else: # if not a float assume uchar colmultiply = [1.0 if el.properties[i].numeric_type in {'f', 'd'} else (1.0 / 256.0) for i in colindices] elif el.name == b'face': findex = el.index(b'vertex_indices') mesh_faces = [] mesh_uvs = [] mesh_colors = [] def add_face(vertices, indices, uvindices, colindices): mesh_faces.append(indices) if uvindices: mesh_uvs.append([(vertices[index][uvindices[0]], vertices[index][uvindices[1]]) for index in indices]) if colindices: mesh_colors.append([(vertices[index][colindices[0]] * colmultiply[0], vertices[index][colindices[1]] * colmultiply[1], vertices[index][colindices[2]] * colmultiply[2], ) for index in indices]) if uvindices or colindices: # If we have Cols or UVs then we need to check the face order. add_face_simple = add_face # EVIL EEKADOODLE - face order annoyance. def add_face(vertices, indices, uvindices, colindices): if len(indices) == 4: if indices[2] == 0 or indices[3] == 0: indices = indices[2], indices[3], indices[0], indices[1] elif len(indices) == 3: if indices[2] == 0: indices = indices[1], indices[2], indices[0] add_face_simple(vertices, indices, uvindices, colindices) verts = obj[b'vertex'] if b'face' in obj: for f in obj[b'face']: ind = f[findex] len_ind = len(ind) if len_ind <= 4: add_face(verts, ind, uvindices, colindices) else: # Fan fill the face for j in range(len_ind - 2): add_face(verts, (ind[0], ind[j + 1], ind[j + 2]), uvindices, colindices) mesh = bpy.data.meshes.new(name=ply_name) mesh.vertices.add(len(obj[b'vertex'])) mesh.vertices.foreach_set("co", [a for v in obj[b'vertex'] for a in (v[vindices_x], v[vindices_y], v[vindices_z])]) if mesh_faces: mesh.tessfaces.add(len(mesh_faces)) mesh.tessfaces.foreach_set("vertices_raw", unpack_face_list(mesh_faces)) if uvindices or colindices: if uvindices: uvlay = mesh.tessface_uv_textures.new() if colindices: vcol_lay = mesh.tessface_vertex_colors.new() if uvindices: for i, f in enumerate(uvlay.data): ply_uv = mesh_uvs[i] for j, uv in enumerate(f.uv): uv[0], uv[1] = ply_uv[j] if colindices: for i, f in enumerate(vcol_lay.data): # XXX, colors dont come in right, needs further investigation. ply_col = mesh_colors[i] if len(ply_col) == 4: f_col = f.color1, f.color2, f.color3, f.color4 else: f_col = f.color1, f.color2, f.color3 for j, col in enumerate(f_col): col.r, col.g, col.b = ply_col[j] mesh.validate() mesh.update() if texture and uvindices: import os import sys from bpy_extras.image_utils import load_image encoding = sys.getfilesystemencoding() encoded_texture = texture.decode(encoding=encoding) name = bpy.path.display_name_from_filepath(texture) image = load_image(encoded_texture, os.path.dirname(filepath), recursive=True, place_holder=True) if image: texture = bpy.data.textures.new(name=name, type='IMAGE') texture.image = image material = bpy.data.materials.new(name=name) material.use_shadeless = True mtex = material.texture_slots.add() mtex.texture = texture mtex.texture_coords = 'UV' mtex.use_map_color_diffuse = True mesh.materials.append(material) for face in mesh.uv_textures[0].data: face.image = image return mesh
def write_mesh_data(self, obj, name): ''' Convert maxwell object into blender mesh datablock precond: check that obj != null and that it is actually a mesh ''' uv_layer_count = obj.getNumChannelsUVW() verts = [] faces = [] normals = [] vert_norm = {} mats = {} mat_index = [] uvs = [] max_vertex = 0 max_normal = 0 for i in range(obj.getNumTriangles()): triangle = obj.getTriangle(i) (v1, v2, v3, n1, n2, n3) = triangle max_vertex = max(max_vertex, v1, v2, v3) max_normal = max(max_normal, n1, n2, n3) mat = obj.getTriangleMaterial(i) if not mat.isNull(): mat_name = mat.name if not mat_name in mats: mats[mat_name] = len(mats) mat_index.append(mats[mat_name]) else: mat_index.append(0) if v3 == 0: # eeekadoodle dance faces.append((v2, v3, v1)) zero_face_start = True else: faces.append((v1, v2, v3)) zero_face_start = False vert_norm[v1] = n1 vert_norm[v2] = n2 vert_norm[v3] = n3 if uv_layer_count > 0: u1, v1, w1, u2, v2, w2, u3, v3, w3 = obj.getTriangleUVW(i, 0) if not zero_face_start: uvs.append(( u1, -1.0 * v1, u2, -1.0 * v2, u3, -1.0 * v3, 0.0, 0.0 )) else: uvs.append(( u2, -1.0 * v2, u3, -1.0 * v3, u1, -1.0 * v1, 0.0, 0.0 )) else: uvs.append((0.0, 0.0, 0.0, 0.0, 0.0 ,0.0 ,0.0, 0.0)) for i in range(max_vertex + 1): vert = obj.getVertex(i, 0) verts.append((vert.x, vert.y, vert.z)) for i in range(max_vertex + 1): n = obj.getNormal(vert_norm[i],0) normals.append((n.x, n.y, n.z)) 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(): me.materials.append(self.materials[k]) else: MaxwellLog("WARNING OBJECT {} HAS NO MATERIAL".format(obj.getName())) me.vertices.foreach_set("co", unpack_list(verts)) me.vertices.foreach_set("normal", unpack_list(normals)) me.tessfaces.foreach_set("vertices_raw", unpack_face_list(faces)) me.tessfaces.foreach_set("material_index", mat_index) if len(uvs) > 0: me.tessface_uv_textures.new() for i in range(len(faces)): me.tessface_uv_textures[0].data[i].uv_raw = uvs[i] me.update(calc_edges=True) # Update mesh with new data me.validate() return me, len(verts)
def write_mesh_data(self, obj, name): ''' Convert maxwell object into blender mesh datablock precond: check that obj != null and that it is actually a mesh ''' uv_layer_count = obj.getNumChannelsUVW() verts = [] faces = [] normals = [] vert_norm = {} mats = {} mat_index = [] uvs = [] max_vertex = 0 max_normal = 0 for i in range(obj.getNumTriangles()): triangle = obj.getTriangle(i) (v1, v2, v3, n1, n2, n3) = triangle max_vertex = max(max_vertex, v1, v2, v3) max_normal = max(max_normal, n1, n2, n3) mat = obj.getTriangleMaterial(i) if not mat.isNull(): mat_name = mat.name if not mat_name in mats: mats[mat_name] = len(mats) mat_index.append(mats[mat_name]) else: mat_index.append(0) if v3 == 0: # eeekadoodle dance faces.append((v2, v3, v1)) zero_face_start = True else: faces.append((v1, v2, v3)) zero_face_start = False vert_norm[v1] = n1 vert_norm[v2] = n2 vert_norm[v3] = n3 if uv_layer_count > 0: u1, v1, w1, u2, v2, w2, u3, v3, w3 = obj.getTriangleUVW(i, 0) if not zero_face_start: uvs.append((u1, -1.0 * v1, u2, -1.0 * v2, u3, -1.0 * v3, 0.0, 0.0)) else: uvs.append((u2, -1.0 * v2, u3, -1.0 * v3, u1, -1.0 * v1, 0.0, 0.0)) else: uvs.append((0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)) for i in range(max_vertex + 1): vert = obj.getVertex(i, 0) verts.append((vert.x, vert.y, vert.z)) for i in range(max_vertex + 1): n = obj.getNormal(vert_norm[i], 0) normals.append((n.x, n.y, n.z)) 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(): me.materials.append(self.materials[k]) else: MaxwellLog("WARNING OBJECT {} HAS NO MATERIAL".format( obj.getName())) me.vertices.foreach_set("co", unpack_list(verts)) me.vertices.foreach_set("normal", unpack_list(normals)) me.tessfaces.foreach_set("vertices_raw", unpack_face_list(faces)) me.tessfaces.foreach_set("material_index", mat_index) if len(uvs) > 0: me.tessface_uv_textures.new() for i in range(len(faces)): me.tessface_uv_textures[0].data[i].uv_raw = uvs[i] me.update(calc_edges=True) # Update mesh with new data me.validate() return me, len(verts)
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 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 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 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 read_mesh(data): read_bounds(data) n_surfaces, = struct.unpack("<L",data.read(4)) print ("found ",n_surfaces," surfaces") surface_names = [] for i in range(n_surfaces): surface_name = read_string(data) surface_names.append(surface_name) print ("surface_name ",surface_name) read_bounds(data) for j in range(n_surfaces): n_vertices, = struct.unpack("<L",data.read(4)) verts = [] norms = [] print(n_vertices," vertices") for i in range(n_vertices): x,y,z = struct.unpack("<fff",data.read(12)) nx,ny,nz = struct.unpack("<hhh",data.read(6)) verts.append((x,y,z)) norms.append((float(nx)/33268.0,float(ny)/33268.0,float(nz)/33268.0)) #print ("verts: ",verts) n_uvcoords0, = struct.unpack("<L",data.read(4)) uvs0 = [] for i in range(n_uvcoords0): (u,v) = struct.unpack("<ff",data.read(8)) uvs0.append((u,v)) n_uvcoords1, = struct.unpack("<L",data.read(4)) uvs1 = [] for i in range(n_uvcoords1): (u,v) = struct.unpack("<ff",data.read(8)) uvs1.append((u,v)) n_triangles, = struct.unpack("<L",data.read(4)) faces = [] if(n_vertices < 66536): for i in range(n_triangles): v0,v1,v2 = struct.unpack("<HHH",data.read(6)) faces.append((v0,v1,v2)) else: for i in range(n_triangles): v0,v1,v2 = struct.unpack("<LLL",data.read(12)) faces.append((v0,v1,v2)) surface_name = surface_names[j] me = bpy.data.meshes.new(surface_name) ob = bpy.data.objects.new(surface_name,me) bpy.context.scene.objects.link(ob) me.vertices.add(len(verts)) me.vertices.foreach_set("co",unpack_list(verts)) me.faces.add(len(faces)) me.faces.foreach_set("vertices_raw",unpack_face_list(faces)) for i in range(n_vertices): me.vertices[i].normal = norms[i] me.validate() me.update(calc_edges=True) if n_uvcoords0 > 0: b_uvs0 = me.uv_textures.new() for i in range(len(faces)): (v0,v1,v2) = faces[i] b_uvface = b_uvs0.data[i] b_uvface.uv1 = uvs0[v0] b_uvface.uv2 = uvs0[v1] b_uvface.uv3 = uvs0[v2] if n_uvcoords1 > 0: b_uvs1 = me.uv_textures.new() for i in range(len(faces)): (v0,v1,v2) = faces[i] b_uvface = b_uvs1.data[i] b_uvface.uv1 = uvs1[v0] b_uvface.uv2 = uvs1[v1] b_uvface.uv3 = uvs1[v2]
def load_ply_mesh(filepath, ply_name): from bpy_extras.io_utils import unpack_face_list # from bpy_extras.image_utils import load_image # UNUSED obj_spec, obj, texture = read(filepath) if obj is None: print('Invalid file') return uvindices = colindices = None colmultiply = None # noindices = None # Ignore normals for el in obj_spec.specs: if el.name == b'vertex': vindices_x, vindices_y, vindices_z = el.index(b'x'), el.index( b'y'), el.index(b'z') # noindices = (el.index('nx'), el.index('ny'), el.index('nz')) # if -1 in noindices: noindices = None uvindices = (el.index(b's'), el.index(b't')) if -1 in uvindices: uvindices = None colindices = el.index(b'red'), el.index(b'green'), el.index( b'blue') if -1 in colindices: colindices = None else: # if not a float assume uchar colmultiply = [ 1.0 if el.properties[i].numeric_type in {'f', 'd'} else (1.0 / 255.0) for i in colindices ] elif el.name == b'face': findex = el.index(b'vertex_indices') elif el.name == b'tristrips': trindex = el.index(b'vertex_indices') elif el.name == b'edge': eindex1, eindex2 = el.index(b'vertex1'), el.index(b'vertex2') mesh_faces = [] mesh_uvs = [] mesh_colors = [] def add_face(vertices, indices, uvindices, colindices): mesh_faces.append(indices) if uvindices: mesh_uvs.append([(vertices[index][uvindices[0]], vertices[index][uvindices[1]]) for index in indices]) if colindices: mesh_colors.append([( vertices[index][colindices[0]] * colmultiply[0], vertices[index][colindices[1]] * colmultiply[1], vertices[index][colindices[2]] * colmultiply[2], ) for index in indices]) if uvindices or colindices: # If we have Cols or UVs then we need to check the face order. add_face_simple = add_face # EVIL EEKADOODLE - face order annoyance. def add_face(vertices, indices, uvindices, colindices): if len(indices) == 4: if indices[2] == 0 or indices[3] == 0: indices = indices[2], indices[3], indices[0], indices[1] elif len(indices) == 3: if indices[2] == 0: indices = indices[1], indices[2], indices[0] add_face_simple(vertices, indices, uvindices, colindices) verts = obj[b'vertex'] if b'face' in obj: for f in obj[b'face']: ind = f[findex] len_ind = len(ind) if len_ind <= 4: add_face(verts, ind, uvindices, colindices) else: # Fan fill the face for j in range(len_ind - 2): add_face(verts, (ind[0], ind[j + 1], ind[j + 2]), uvindices, colindices) if b'tristrips' in obj: for t in obj[b'tristrips']: ind = t[trindex] len_ind = len(ind) for j in range(len_ind - 2): add_face(verts, (ind[j], ind[j + 1], ind[j + 2]), uvindices, colindices) mesh = bpy.data.meshes.new(name=ply_name) mesh.vertices.add(len(obj[b'vertex'])) mesh.vertices.foreach_set("co", [ a for v in obj[b'vertex'] for a in (v[vindices_x], v[vindices_y], v[vindices_z]) ]) if b'edge' in obj: mesh.edges.add(len(obj[b'edge'])) mesh.edges.foreach_set( "vertices", [a for e in obj[b'edge'] for a in (e[eindex1], e[eindex2])]) if mesh_faces: mesh.tessfaces.add(len(mesh_faces)) mesh.tessfaces.foreach_set("vertices_raw", unpack_face_list(mesh_faces)) if uvindices or colindices: if uvindices: uvlay = mesh.tessface_uv_textures.new() if colindices: vcol_lay = mesh.tessface_vertex_colors.new() if uvindices: for i, f in enumerate(uvlay.data): ply_uv = mesh_uvs[i] for j, uv in enumerate(f.uv): uv[0], uv[1] = ply_uv[j] if colindices: for i, f in enumerate(vcol_lay.data): # XXX, colors dont come in right, needs further investigation. ply_col = mesh_colors[i] if len(ply_col) == 4: f_col = f.color1, f.color2, f.color3, f.color4 else: f_col = f.color1, f.color2, f.color3 for j, col in enumerate(f_col): col.r, col.g, col.b = ply_col[j] mesh.validate() mesh.update() if texture and uvindices: import os import sys from bpy_extras.image_utils import load_image encoding = sys.getfilesystemencoding() encoded_texture = texture.decode(encoding=encoding) name = bpy.path.display_name_from_filepath(texture) image = load_image(encoded_texture, os.path.dirname(filepath), recursive=True, place_holder=True) if image: texture = bpy.data.textures.new(name=name, type='IMAGE') texture.image = image material = bpy.data.materials.new(name=name) material.use_shadeless = True mtex = material.texture_slots.add() mtex.texture = texture mtex.texture_coords = 'UV' mtex.use_map_color_diffuse = True mesh.materials.append(material) for face in mesh.uv_textures[0].data: face.image = image return mesh
def create_mesh(self): global material_list global current_ac_file global xml_extra_position global xml_extra_rotation if not self.parent_name: return debug_info("ac_manager::MESH.create_mesh() %s" % self.mesh_name) obj_name = self.mesh_name context = CONTEXT mesh = bpy.data.meshes.new(obj_name + ".mesh") if self.crease != -1.0: mesh.use_auto_smooth = True mesh.auto_smooth_angle = radians(self.crease) mesh.vertices.add(len(self.vertices)) mesh.tessfaces.add(len(self.faces)) mesh.vertices.foreach_set("co", unpack_list(self.vertices)) mesh.tessfaces.foreach_set("vertices_raw", unpack_face_list(self.faces)) mesh.tessfaces.foreach_set("use_smooth", [(True)] * len(self.faces)) mesh.update() sc = bpy.context.scene obj_new = bpy.data.objects.new(obj_name, mesh) current_ac_file.meshs.append(obj_new.name) current_ac_file.dic_name_meshs[obj_name] = obj_new.name obj_new.data.fg.name_ac = obj_name obj_new.location = self.location compute_extra_transforme(obj_new, xml_extra_position, xml_extra_rotation) self.mesh_name_bl = obj_new.name o = sc.objects.link(obj_new) if self.parent_name[-1] != 'WORLD': str_print = "create_mesh() %s parent = %s" % ( self.mesh_name_bl, self.parent_name[-1]) obj_new.parent = bpy.data.objects[self.parent_name[-1]] else: str_print = "create_mesh() %s" % (self.mesh_name_bl) str_print += ' mat no = %d texture="%s" image="%s"' % ( self.mat_no, self.tex_name_bl, self.img_name_bl) debug_info(str_print) self.create_uv(mesh) self.assign_material(obj_new) #mesh.update(calc_edges=True) mesh.validate() mesh.update(calc_edges=True) obj_new.data.fg.ac_file = "" + self.filename self.edge_split(obj_new)
def ReadMesh(self, mesh): print("Name: {}".format(mesh["name"])) print("Num Verts: {}".format(len(mesh["vertices"]))) print("Num Indices: {}".format(len(mesh["indices"][0]))) scn = bpy.context.scene for o in scn.objects: o.select = False blenmesh = bpy.data.meshes.new(mesh["name"]) blenmesh.vertices.add(len(mesh["vertices"])) blenmesh.vertices.foreach_set("co", unpack_list(mesh["vertices"])) blenmesh.tessfaces.add(len(mesh["indices"][0])) # Add faces blenmesh.tessfaces.foreach_set("vertices_raw", unpack_face_list(mesh["indices"][0])) uvlay = blenmesh.tessface_uv_textures.new() for i, f in enumerate(uvlay.data): index = mesh["indices"][0][i] for j, uv in enumerate(f.uv): uv[0] = mesh["uvs"][index[j]][0] uv[1] = mesh["uvs"][index[j]][1] #add object to scene blenmesh.update() blenmesh.validate() nobj = bpy.data.objects.new(mesh["name"], blenmesh) scn.objects.link(nobj) #print("Skel: {}".format(mesh["skeleton"])) # Create Armature and Object bpy.ops.object.add(type='ARMATURE', enter_editmode=True) object = bpy.context.object object.name = 'armguy' armature = object.data armature.name = 'armguy' #create bones for the_bone in mesh["skeleton"]: nobj.vertex_groups.new(name=the_bone["name"]) bone = armature.edit_bones.new(the_bone["name"]) bone.tail = Vector( [0, 0, 0.1] ) # if you won't do it, the bone will have zero lenghtand will be removed immediately by Blender #map parents for the_bone in mesh["skeleton"]: if 'parent' in the_bone: armature.edit_bones[the_bone[ 'name']].parent = armature.edit_bones[the_bone['parent']] parent = self.FindBoneByName(mesh["skeleton"], the_bone['parent']) for the_bone in mesh["skeleton"]: matrix = Matrix(the_bone["matrix"]) matrix.transpose() matrix = matrix.inverted() armature.edit_bones[the_bone['name']].transform(matrix) for vidx in range(0, len(mesh["vertices"])): bones = mesh["bone_indices"][0][vidx] weights = mesh["weights"][0][vidx] print("Vertex: {}".format(vidx)) print("Data: {} {}".format(bones, weights)) for widx in range(0, len(weights)): bone_idx = bones[widx] if bone_idx == 0: break weight = weights[widx] nobj.vertex_groups[bone_idx].add([vidx], weight, 'ADD') # for vwidx, wval in enumerate(mesh["weights"][0]): # bones = mesh["bone_indices"][0][vwidx] # print("Vertex: {}".format(vwidx)) # print("Data: {} {}".format(bones, wval)) # for vwsidx, vwsval in enumerate(wval): # bone_idx = bones[vwsidx] # the_bone = mesh["skeleton"][bone_idx] # print("Bone: {} ({}): {}".format(bone_idx, the_bone["name"], vwsval)) # nobj.vertex_groups[bone_idx].add([vwidx], vwsval, 'ADD') return nobj
def processLambert(f, blocks): verts = [] faces = [] uvs = [] texs = [] #Get Version version = struct.unpack('<B', f.read(1))[0] type = struct.unpack('<I', f.read(4))[0] #skip f.read(40) #Get Textures for i in range(8): length = struct.unpack('<I', f.read(4))[0] texStr = '<%ds' % length tex = struct.unpack(texStr, f.read(length))[0].decode() texs.append(tex) print("Texture: %s" % tex) #skip unknown data f.read(4) print("Type: %d" % (type)) if(type == 1): vertCount = struct.unpack('<I', f.read(4))[0] print("Vertices: %d" % vertCount) for vert in range(vertCount): extra1 = struct.unpack('<H', f.read(2))[0] extra2 = struct.unpack('<H', f.read(2))[0] extra3 = struct.unpack('<H', f.read(2))[0] extra4 = struct.unpack('<H', f.read(2))[0] extra5 = struct.unpack('<f', f.read(4))[0] extra6 = struct.unpack('<f', f.read(4))[0] extra7 = struct.unpack('<f', f.read(4))[0] x = struct.unpack('<H', f.read(2))[0] y = struct.unpack('<H', f.read(2))[0] z = struct.unpack('<H', f.read(2))[0] extra8 = struct.unpack('<H', f.read(2))[0] print("Data: %d %d %d" % (x, y, z)) verts.append((x/65550, z/65550, y/65550)) faceCount = struct.unpack('<I', f.read(4))[0] print("Faces: %d" % faceCount) for face in range(int(faceCount/3)): vert1 = struct.unpack('<H', f.read(2))[0] vert2 = struct.unpack('<H', f.read(2))[0] vert3 = struct.unpack('<H', f.read(2))[0] faces.append((vert1, vert2, vert3)) #Read Check check = struct.unpack('<I', f.read(4))[0] #Add object data mesh = bpy.data.meshes.new("Mesh") mesh.vertices.add(vertCount) mesh.tessfaces.add(faceCount/3) mesh.vertices.foreach_set("co", unpack_list(verts)) mesh.tessfaces.foreach_set("vertices_raw", unpack_face_list(faces)) mesh.tessface_uv_textures.new() for face in range(int(faceCount/3)): uv = mesh.tessface_uv_textures[0].data[face] #uv.uv1 = uvs[faces[face][0]] #uv.uv2 = uvs[faces[face][1]] #uv.uv3 = uvs[faces[face][2]] mesh.validate() mesh.update() obj = bpy.data.objects.new("Mesh_Lambert_0", mesh) blocks.append(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 = [] smooth = [] 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': try: f.st_scale = self.materials_scales[default_material] except KeyError as e: pass 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) smooth_edge = False for edge in f.edges: if edge.GetSmooth() == True: smooth_edge = True break 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 ) ) smooth.append(smooth_edge) 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(): try: bmat = self.materials[k] except KeyError as e: bmat = self.materials["Material"] me.materials.append(bmat) if bmat.alpha < 1.0: alpha = True try: if self.render_engine == 'CYCLES': if 'Image Texture' in bmat.node_tree.nodes.keys(): uvs_used = True else: for ts in bmat.texture_slots: if ts is not None and ts.texture_coords is not None: 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) me.tessfaces.foreach_set("use_smooth", smooth) print('tessfaces: %i smoothie %i' % (len(faces), len(smooth))) 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