def write(filename): start = Blender.sys.time() if not filename.lower().endswith('.raw'): filename += '.raw' scn= Blender.Scene.GetCurrent() ob= scn.objects.active if not ob: Blender.Draw.PupMenu('Error%t|Select 1 active object') return file = open(filename, 'wb') mesh = BPyMesh.getMeshFromObject(ob, None, True, False, scn) if not mesh: Blender.Draw.PupMenu('Error%t|Could not get mesh data from active object') return mesh.transform(ob.matrixWorld) file = open(filename, "wb") for f in mesh.faces: for v in f: file.write('%.6f %.6f %.6f ' % tuple(v.co)) file.write('\n') file.close() end = Blender.sys.time() message = 'Successfully exported "%s" in %.4f seconds' % ( Blender.sys.basename(filename), end-start) print message
def write(filename): start = Blender.sys.time() if not filename.lower().endswith('.raw'): filename += '.raw' scn = Blender.Scene.GetCurrent() ob = scn.objects.active if not ob: Blender.Draw.PupMenu('Error%t|Select 1 active object') return file = open(filename, 'wb') mesh = BPyMesh.getMeshFromObject(ob, None, True, False, scn) if not mesh: Blender.Draw.PupMenu( 'Error%t|Could not get mesh data from active object') return mesh.transform(ob.matrixWorld) file = open(filename, "wb") for f in mesh.faces: for v in f: file.write('%.6f %.6f %.6f ' % tuple(v.co)) file.write('\n') file.close() end = Blender.sys.time() message = 'Successfully exported "%s" in %.4f seconds' % ( Blender.sys.basename(filename), end - start) print message
def load_objs(parent, group): group.obj_count = 0 for o in objs: if o.getParent() == parent: new = Obj() try: new.name = o.getName().split('-')[1] + '-' + o.getName().split( '-')[2] except: Blender.Draw.PupMenu( "ERROR:%t| Object name \"" + o.getName() + "\"not valid.|%l|Name should look like OBJECT_NAME-XX-XX") return -1 me = BPyMesh.getMeshFromObject(o, None, True, False, tp) #me = NMesh.GetRaw(o.data.name) if len(me.materials) > 0: new.tex = add_mat(me.materials[0], o) else: print "No Material: %s\n" % o.getName() new.tex = 'FFFF' if load_meshes(me, new, o.matrix) == -1: Blender.Draw.PupMenu('ERROR:%t| Unexpected Error. ') return -1 group.obj_list.append(new) group.obj_count += 1 return 1
def write(filename): Blender.Window.WaitCursor(1) if not filename.lower().endswith('.begc'): filename += '.begc' out = file(filename, "w") objects = Blender.Object.GetSelected() num_objects = 0 for object in objects: if object.type == 'Mesh': num_objects = num_objects + 1 out.write('%d\n' % num_objects) node_offset = 0 for object in objects: if object.type == 'Mesh': out.write(object.name) out.write('\n') for object in objects: if object.type == 'Mesh': mesh = BPyMesh.getMeshFromObject(object, None, True, False, bpy.data.scenes.active) #mesh = object.getData(0,1) mesh.transform(object.matrixWorld) faces = mesh.faces nodes = mesh.verts out.write('%d' % len(nodes)) out.write(' %d\n' % len(faces)) for n in nodes: #out.write("%e " % n.co[0]) #out.write("%e " % n.co[1]) #out.write("%e\n" % n.co[2]) out.write("%e " % n.co[0]) out.write("%e " % n.co[1]) out.write("%e\n" % n.co[2]) for f in faces: N = len(f.verts) if N < 3 and N > 4: Blender.Draw.PupMenu( 'Error%t|Only triangles and quads allowed') return out.write("%d" % N) for v in f.verts: out.write(' %d' % (v.index + node_offset)) out.write('\n') node_offset = node_offset + len(nodes) Blender.Window.WaitCursor(0)
def write(filename): Blender.Window.WaitCursor(1) if not filename.lower().endswith('.begc'): filename += '.begc' out = file(filename, "w") objects = Blender.Object.GetSelected() num_objects = 0 for object in objects: if object.type == 'Mesh': num_objects = num_objects + 1 out.write('%d\n' % num_objects) node_offset = 0 for object in objects: if object.type == 'Mesh': out.write(object.name) out.write('\n') for object in objects: if object.type == 'Mesh': mesh = BPyMesh.getMeshFromObject(object, None, True, False, bpy.data.scenes.active) #mesh = object.getData(0,1) mesh.transform(object.matrixWorld) faces = mesh.faces nodes = mesh.verts out.write('%d' % len(nodes)) out.write(' %d\n' % len(faces)) for n in nodes: #out.write("%e " % n.co[0]) #out.write("%e " % n.co[1]) #out.write("%e\n" % n.co[2]) out.write("%e " % n.co[0]) out.write("%e " % n.co[1]) out.write("%e\n" % n.co[2]) for f in faces: N = len(f.verts) if N < 3 and N > 4: Blender.Draw.PupMenu('Error%t|Only triangles and quads allowed') return out.write("%d" % N) for v in f.verts: out.write(' %d' % (v.index + node_offset)) out.write('\n') node_offset = node_offset + len(nodes) Blender.Window.WaitCursor(0)
def exportPath(curve, filename): print "Exporting curve "+curve.name+" to "+filename mesh = BPyMesh.getMeshFromObject(curve) mesh.transform(curve.matrixWorld) numVertices = len(mesh.verts) file = open(filename, "w") for i in range(0, numVertices): vertex = mesh.verts[i] file.write("%g %g %g\n" % (vertex.co[0], vertex.co[1], vertex.co[2])) if curve.data.isCyclic(): vertex = mesh.verts[0] file.write("%g %g %g\n" % (vertex.co[0], vertex.co[1], vertex.co[2])) file.close()
def write(filename): start = Blender.sys.time() if not filename.lower().endswith('.ml.txt'): filename += '.ml.txt' scn= Blender.Scene.GetCurrent() ob= scn.objects.active if not ob: Blender.Draw.PupMenu('Error%t|Select 1 active object') return file = open(filename, 'wb') mesh = BPyMesh.getMeshFromObject(ob, None, True, False, scn) if not mesh: Blender.Draw.PupMenu('Error%t|Could not get mesh data from active object') return mesh.transform(ob.matrixWorld) with open(filename, "w") as ml_file: ml_file.write('#MiniLight\n') ml_file.write('%d\n' % DEFAULT_ITERATIONS) ml_file.write('%d %d\n' % DEFAULT_RESOLUTION) ml_file.write('(%.2f %.2f %.2f) (%.2f %.2f %.2f) %.2f\n' % DEFAULT_CAMERA) ml_file.write('(%.2f %.2f %.2f) (%.2f %.2f %.2f)\n' % DEFAULT_SKY_AND_GROUND) for f in mesh.faces: if len(f) != 3: Blender.Draw.PupMenu('Error%t|Non-triangular face found in mesh') return for v in f: ml_file.write('(%.6f %.6f %.6f) ' % tuple(v.co)) ml_file.write('(%.6f %.6f %.6f) ' % DEFAULT_COLOR) ml_file.write('(%.6f %.6f %.6f)\n' % DEFAULT_REFLECTIVITY) end = Blender.sys.time() message = 'Successfully exported "%s" in %.4f seconds' % ( Blender.sys.basename(filename), end-start) print message
def writeMeshData(self, parent, mesh, obj): aMesh = BPyMesh.getMeshFromObject(obj, self.getContainerMesh(), True, scn=self.scene) if len(aMesh.faces) == 0: return print("Writing mesh %s" % mesh.name) materials = aMesh.materials has_quads = False for f in aMesh.faces: if len(f) == 4: has_quads = True break if has_quads: oldmode = Mesh.Mode() Mesh.Mode(Mesh.SelectModes['FACE']) aMesh.sel = True tempob = self.scene.objects.new(aMesh) aMesh.quadToTriangle(0) # more=0 shortest length oldmode = Mesh.Mode(oldmode) self.scene.objects.unlink(tempob) Mesh.Mode(oldmode) data = self.doc.createDataElement(mesh.name+"_data", None, None, None, None) parent.appendChild(data) # Mesh indices matCount = len(materials) if matCount == 0: matCount = 1 indices = [[] for m in range(matCount)] #@UnusedVariable vertices = [] vertex_dict = {} print("Faces: %i" % len(aMesh.faces)) i = 0 for face in aMesh.faces: mv = None for i, v in enumerate(face): if face.smooth: if aMesh.faceUV: mv = vertex(v.index, None, face.uv[i]) else: mv = vertex(v.index, None, None) else: if aMesh.faceUV: mv = vertex(v.index, face.no, face.uv[i]) else: mv = vertex(v.index, face.no) index, added = appendUnique(vertex_dict, mv) indices[face.mat].append(index) if added: vertices.append(mv) # Single or no material: write all in one data block if not matCount > 1: valueElement = self.doc.createIntElement(None, "index") valueElement.setValue(' '.join(map(str, indices[0]))) data.appendChild(valueElement) print("Vertices: %i" % len(vertex_dict)) # Vertex positions value_list = [] for v in vertices: value_list.append("%.6f %.6f %.6f" % tuple(aMesh.verts[v.index].co)) valueElement = self.doc.createFloat3Element(None, "position") valueElement.setValue(' '.join(value_list)) data.appendChild(valueElement) # Vertex normals value_list = [] for v in vertices: if v.normal == None: value_list.append("%.6f %.6f %.6f" % tuple(aMesh.verts[v.index].no)) else: value_list.append("%.6f %.6f %.6f" % tuple(v.normal)) valueElement = self.doc.createFloat3Element(None, "normal") valueElement.setValue(' '.join(value_list)) data.appendChild(valueElement) # Vertex texCoord if aMesh.faceUV: value_list = [] for v in vertices: value_list.append("%.6f %.6f" % tuple(v.texcoord)) valueElement =self. doc.createFloat2Element(None, "texcoord") valueElement.setValue(' '.join(value_list)) data.appendChild(valueElement); if len(materials) > 1: for i, material in enumerate(materials): if len(indices[i]) == 0: continue data = self.doc.createDataElement(mesh.name+"_data_" + material.name, None, None, None, None) parent.appendChild(data) refdata = self.doc.createDataElement(src_="#"+mesh.name+"_data") data.appendChild(refdata) valueElement = self.doc.createIntElement(None, "index") valueElement.setValue(' '.join(map(str, indices[i]))) data.appendChild(valueElement) aMesh.verts = None
def file_callback(filename): if not filename.lower().endswith('.ply'): filename += '.ply' scn= bpy.data.scenes.active ob= scn.objects.active if not ob: Blender.Draw.PupMenu('Error%t|Select 1 active object') return file = open(filename, 'wb') EXPORT_APPLY_MODIFIERS = Draw.Create(1) EXPORT_NORMALS = Draw.Create(1) EXPORT_UV = Draw.Create(1) EXPORT_COLORS = Draw.Create(1) #EXPORT_EDGES = Draw.Create(0) pup_block = [\ ('Apply Modifiers', EXPORT_APPLY_MODIFIERS, 'Use transformed mesh data.'),\ ('Normals', EXPORT_NORMALS, 'Export vertex normal data.'),\ ('UVs', EXPORT_UV, 'Export texface UV coords.'),\ ('Colors', EXPORT_COLORS, 'Export vertex Colors.'),\ #('Edges', EXPORT_EDGES, 'Edges not connected to faces.'),\ ] if not Draw.PupBlock('Export...', pup_block): return is_editmode = Blender.Window.EditMode() if is_editmode: Blender.Window.EditMode(0, '', 0) Window.WaitCursor(1) EXPORT_APPLY_MODIFIERS = EXPORT_APPLY_MODIFIERS.val EXPORT_NORMALS = EXPORT_NORMALS.val EXPORT_UV = EXPORT_UV.val EXPORT_COLORS = EXPORT_COLORS.val #EXPORT_EDGES = EXPORT_EDGES.val mesh = BPyMesh.getMeshFromObject(ob, None, EXPORT_APPLY_MODIFIERS, False, scn) if not mesh: Blender.Draw.PupMenu('Error%t|Could not get mesh data from active object') return mesh.transform(ob.matrixWorld) faceUV = mesh.faceUV vertexUV = mesh.vertexUV vertexColors = mesh.vertexColors if (not faceUV) and (not vertexUV): EXPORT_UV = False if not vertexColors: EXPORT_COLORS = False if not EXPORT_UV: faceUV = vertexUV = False if not EXPORT_COLORS: vertexColors = False # incase color = uvcoord = uvcoord_key = normal = normal_key = None verts = [] # list of dictionaries # vdict = {} # (index, normal, uv) -> new index vdict = [{} for i in xrange(len(mesh.verts))] vert_count = 0 for i, f in enumerate(mesh.faces): smooth = f.smooth if not smooth: normal = tuple(f.no) normal_key = rvec3d(normal) if faceUV: uv = f.uv if vertexColors: col = f.col for j, v in enumerate(f): if smooth: normal= tuple(v.no) normal_key = rvec3d(normal) if faceUV: uvcoord= uv[j][0], 1.0-uv[j][1] uvcoord_key = rvec2d(uvcoord) elif vertexUV: uvcoord= v.uvco[0], 1.0-v.uvco[1] uvcoord_key = rvec2d(uvcoord) if vertexColors: color= col[j].r, col[j].g, col[j].b key = normal_key, uvcoord_key, color vdict_local = vdict[v.index] if (not vdict_local) or (not vdict_local.has_key(key)): vdict_local[key] = vert_count; verts.append( (tuple(v.co), normal, uvcoord, color) ) vert_count += 1 file.write('ply\n') file.write('format ascii 1.0\n') file.write('comment Created by Blender3D %s - www.blender.org, source file: %s\n' % (Blender.Get('version'), Blender.Get('filename').split('/')[-1].split('\\')[-1] )) file.write('element vertex %d\n' % len(verts)) file.write('property float x\n') file.write('property float y\n') file.write('property float z\n') if EXPORT_NORMALS: file.write('property float nx\n') file.write('property float ny\n') file.write('property float nz\n') if EXPORT_UV: file.write('property float s\n') file.write('property float t\n') if EXPORT_COLORS: file.write('property uchar red\n') file.write('property uchar green\n') file.write('property uchar blue\n') file.write('element face %d\n' % len(mesh.faces)) file.write('property list uchar uint vertex_indices\n') file.write('end_header\n') for i, v in enumerate(verts): file.write('%.6f %.6f %.6f ' % v[0]) # co if EXPORT_NORMALS: file.write('%.6f %.6f %.6f ' % v[1]) # no if EXPORT_UV: file.write('%.6f %.6f ' % v[2]) # uv if EXPORT_COLORS: file.write('%u %u %u' % v[3]) # col file.write('\n') for (i, f) in enumerate(mesh.faces): file.write('%d ' % len(f)) smooth = f.smooth if not smooth: no = rvec3d(f.no) if faceUV: uv = f.uv if vertexColors: col = f.col for j, v in enumerate(f): if f.smooth: normal= rvec3d(v.no) else: normal= no if faceUV: uvcoord= rvec2d((uv[j][0], 1.0-uv[j][1])) elif vertexUV: uvcoord= rvec2d((v.uvco[0], 1.0-v.uvco[1])) if vertexColors: color= col[j].r, col[j].g, col[j].b file.write('%d ' % vdict[v.index][normal, uvcoord, color]) file.write('\n') file.close() if is_editmode: Blender.Window.EditMode(1, '', 0)
def write(filename): start = Blender.sys.time() if not filename.lower().endswith('.js'): filename += '.js' scn= Blender.Scene.GetCurrent() ob= scn.objects.active if not ob: Blender.Draw.PupMenu('Error%t|Select 1 active object') return file = open(filename, 'wb') mesh = BPyMesh.getMeshFromObject(ob, None, True, False, scn) if not mesh: Blender.Draw.PupMenu('Error%t|Could not get mesh data from active object') return mesh.transform(ob.matrixWorld) #classname = clean(ob.name) classname = filename.split('/')[-1].replace('.js','') file = open(filename, "wb") file.write('var %s = function () {\n\n' % classname) file.write('\tvar scope = this;\n\n') file.write('\tTHREE.Geometry.call(this);\n\n') for v in mesh.verts: file.write('\tv( %.6f, %.6f, %.6f );\n' % (v.co.x, v.co.z, -v.co.y)) # co file.write('\n') for f in mesh.faces: if len(f.verts) == 3: file.write('\tf3( %d, %d, %d, %.6f, %.6f, %.6f );\n' % (f.verts[0].index, f.verts[1].index, f.verts[2].index, f.verts[0].no.x, f.verts[0].no.z, -f.verts[0].no.y)) else: file.write('\tf4( %d, %d, %d, %d, %.6f, %.6f, %.6f );\n' % (f.verts[0].index, f.verts[1].index, f.verts[2].index, f.verts[3].index, f.verts[0].no.x, f.verts[0].no.z, -f.verts[0].no.y)) face_index_pairs = [ (face, index) for index, face in enumerate(mesh.faces)] file.write('\n') ''' for f in me.faces: if me.faceUV: if len(f.verts) == 3: file.write('\tuv( %.6f, %.6f, %.6f, %.6f, %.6f, %.6f );\n' % (f.uv[0][0], 1.0-f.uv[0][1], f.uv[1][0], 1.0-f.uv[1][1], f.uv[2][0], 1.0-f.uv[2][1]) ''' for f in mesh.faces: if mesh.faceUV: if len(f.verts) == 3: file.write('\tuv( %.6f, %.6f, %.6f, %.6f, %.6f, %.6f );\n' % (f.uv[0].x, 1.0 - f.uv[0].y, f.uv[1].x, 1.0 - f.uv[1].y, f.uv[2].x, 1.0 - f.uv[2].y)) else: file.write('\tuv( %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f);\n' % (f.uv[0].x, 1.0 - f.uv[0].y, f.uv[1].x, 1.0 - f.uv[1].y, f.uv[2].x, 1.0 - f.uv[2].y, f.uv[3].x, 1.0 - f.uv[3].y)) file.write('\n') file.write('\tfunction v( x, y, z ) {\n\n') file.write('\t\tscope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) );\n\n') file.write('\t}\n\n') file.write('\tfunction f3( a, b, c, nx, ny, nz ) {\n\n') file.write('\t\tscope.faces.push( new THREE.Face3( a, b, c, nx && ny && nz ? new THREE.Vector3( nx, ny, nz ) : null ) );\n\n') file.write('\t}\n\n') file.write('\tfunction f4( a, b, c, d, nx, ny, nz ) {\n\n') file.write('\t\tscope.faces.push( new THREE.Face4( a, b, c, d, nx && ny && nz ? new THREE.Vector3( nx, ny, nz ) : null ) );\n\n') file.write('\t}\n\n') file.write('\tfunction uv( u1, v1, u2, v2, u3, v3, u4, v4 ) {\n\n') file.write('\t\tvar uv = [];\n') file.write('\t\tuv.push( new THREE.UV( u1, v1 ) );\n') file.write('\t\tuv.push( new THREE.UV( u2, v2 ) );\n') file.write('\t\tuv.push( new THREE.UV( u3, v3 ) );\n') file.write('\t\tif ( u4 && v4 ) uv.push( new THREE.UV( u4, v4 ) );\n') file.write('\t\tscope.uvs.push( uv );\n') file.write('\t}\n\n') file.write('}\n\n') file.write('%s.prototype = new THREE.Geometry();\n' % classname) file.write('%s.prototype.constructor = %s;' % (classname, classname)) file.close()
def write(filename): start = Blender.sys.time() file = open(filename, "wb") scn = Blender.Scene.GetCurrent() objects = list(scn.objects.context) if not objects: Blender.Draw.PupMenu("Error%t|No Objects selected") return try: objects.sort(key=lambda a: a.name) except: objects.sort(lambda a, b: cmp(a.name, b.name)) text = generate_text() desc = generate_desc() icon = "" # generate_icon() meshes = [] mesh_object_name_lookup = {} # for name lookups only for obj in objects: mesh = BPyMesh.getMeshFromObject(obj, None, True, False, scn) if mesh: mesh.transform(obj.matrixWorld) meshes.append(mesh) mesh_object_name_lookup[mesh] = obj.name del obj material_names = get_used_material_names(meshes) tags = generate_tags(material_names) surfs = generate_surfs(material_names) chunks = [text, desc, icon, tags] meshdata = cStringIO.StringIO() layer_index = 0 for mesh in meshes: layr = generate_layr(mesh_object_name_lookup[mesh], layer_index) pnts = generate_pnts(mesh) bbox = generate_bbox(mesh) pols = generate_pols(mesh) ptag = generate_ptag(mesh, material_names) clip = generate_clip(mesh, material_names) if mesh.faceUV: vmad_uv = generate_vmad_uv(mesh) # per face if mesh.vertexColors: # if meshtools.average_vcols: # vmap_vc = generate_vmap_vc(mesh) # per vert # else: vmad_vc = generate_vmad_vc(mesh) # per face write_chunk(meshdata, "LAYR", layr) chunks.append(layr) write_chunk(meshdata, "PNTS", pnts) chunks.append(pnts) write_chunk(meshdata, "BBOX", bbox) chunks.append(bbox) write_chunk(meshdata, "POLS", pols) chunks.append(pols) write_chunk(meshdata, "PTAG", ptag) chunks.append(ptag) if mesh.vertexColors: # if meshtools.average_vcols: # write_chunk(meshdata, "VMAP", vmap_vc) # chunks.append(vmap_vc) # else: write_chunk(meshdata, "VMAD", vmad_vc) chunks.append(vmad_vc) if mesh.faceUV: write_chunk(meshdata, "VMAD", vmad_uv) chunks.append(vmad_uv) write_chunk(meshdata, "CLIP", clip) chunks.append(clip) layer_index += 1 mesh.verts = None # save some ram del mesh_object_name_lookup for surf in surfs: chunks.append(surf) write_header(file, chunks) write_chunk(file, "ICON", icon) write_chunk(file, "TEXT", text) write_chunk(file, "DESC", desc) write_chunk(file, "TAGS", tags) file.write(meshdata.getvalue()) meshdata.close() for surf in surfs: write_chunk(file, "SURF", surf) write_chunk(file, "DATE", "August 19, 2005") Blender.Window.DrawProgressBar(1.0, "") # clear progressbar file.close() print "\a\r", print "Successfully exported %s in %.3f seconds" % ( filename.split("\\")[-1].split("/")[-1], Blender.sys.time() - start, )
def file_callback(filename): if not filename.lower().endswith('.submesh'): filename += '.submesh' scn = bpy.data.scenes.active ob = scn.objects.active if not ob: Blender.Draw.PupMenu('Error%t|Select 1 active object') return file = open(filename, 'wb') EXPORT_APPLY_MODIFIERS = Draw.Create(1) EXPORT_NORMALS = Draw.Create(1) EXPORT_UV = Draw.Create(1) EXPORT_COLORS = Draw.Create(1) #EXPORT_EDGES = Draw.Create(0) pup_block = [\ ('Apply Modifiers', EXPORT_APPLY_MODIFIERS, 'Use transformed mesh data.'),\ ('Normals', EXPORT_NORMALS, 'Export vertex normal data.'),\ ('UVs', EXPORT_UV, 'Export texface UV coords.'),\ ('Colors', EXPORT_COLORS, 'Export vertex Colors.'),\ #('Edges', EXPORT_EDGES, 'Edges not connected to faces.'),\ ] if not Draw.PupBlock('Export...', pup_block): return is_editmode = Blender.Window.EditMode() if is_editmode: Blender.Window.EditMode(0, '', 0) Window.WaitCursor(1) EXPORT_APPLY_MODIFIERS = EXPORT_APPLY_MODIFIERS.val EXPORT_NORMALS = EXPORT_NORMALS.val EXPORT_UV = EXPORT_UV.val EXPORT_COLORS = EXPORT_COLORS.val #EXPORT_EDGES = EXPORT_EDGES.val mesh = BPyMesh.getMeshFromObject(ob, None, EXPORT_APPLY_MODIFIERS, False, scn) if not mesh: Blender.Draw.PupMenu( 'Error%t|Could not get mesh data from active object') return mesh.transform(ob.matrixWorld) faceUV = mesh.faceUV vertexUV = mesh.vertexUV vertexColors = mesh.vertexColors if (not faceUV) and (not vertexUV): EXPORT_UV = False if not vertexColors: EXPORT_COLORS = False if not EXPORT_UV: faceUV = vertexUV = False if not EXPORT_COLORS: vertexColors = False # incase color = uvcoord = uvcoord_key = normal = normal_key = None verts = [] # list of dictionaries # vdict = {} # (index, normal, uv) -> new index vdict = [{} for i in xrange(len(mesh.verts))] vert_count = 0 for i, f in enumerate(mesh.faces): smooth = f.smooth if not smooth: normal = tuple(f.no) normal_key = rvec3d(normal) if faceUV: uv = f.uv if vertexColors: col = f.col for j, v in enumerate(f): if smooth: normal = tuple(v.no) normal_key = rvec3d(normal) if faceUV: uvcoord = uv[j][0], 1.0 - uv[j][1] uvcoord_key = rvec2d(uvcoord) elif vertexUV: uvcoord = v.uvco[0], 1.0 - v.uvco[1] uvcoord_key = rvec2d(uvcoord) if vertexColors: color = col[j].r, col[j].g, col[j].b key = normal_key, uvcoord_key, color vdict_local = vdict[v.index] if (not vdict_local) or (not vdict_local.has_key(key)): vdict_local[key] = vert_count verts.append((tuple(v.co), normal, uvcoord, color)) vert_count += 1 file.write('SUBMESHTEXT0001\n') file.write( '#Created by Blender3D %s - www.blender.org, source file: %s\n' % (Blender.Get('version'), Blender.Get('filename').split('/')[-1].split('\\')[-1])) #file.write('element vertex %d\n' % len(verts)) file.write('vertex format: position:3,texture0:2,normal:3\n') file.write('vertex count: %d\n' % len(verts)) for i, v in enumerate(verts): file.write('[%.6f,%.6f,%.6f]' % v[0]) # co #if EXPORT_UV: file.write(' [%.6f,%.6f]' % v[2]) # uv #if EXPORT_NORMALS: file.write(' [%.6f,%.6f,%.6f]' % v[1]) # no #if EXPORT_COLORS: # file.write('%u %u %u' % v[3]) # col file.write('\n') triangles = [] for (i, f) in enumerate(mesh.faces): #file.write('%d ' % len(f)) smooth = f.smooth if not smooth: no = rvec3d(f.no) if faceUV: uv = f.uv if vertexColors: col = f.col if (len(f) == 3): triangle = [] for j, v in enumerate(f): if f.smooth: normal = rvec3d(v.no) else: normal = no if faceUV: uvcoord = rvec2d((uv[j][0], 1.0 - uv[j][1])) elif vertexUV: uvcoord = rvec2d((v.uvco[0], 1.0 - v.uvco[1])) if vertexColors: color = col[j].r, col[j].g, col[j].b triangle += [vdict[v.index][normal, uvcoord, color]] triangles += [triangle] #file.write('%d ' % vdict[v.index][normal, uvcoord, color]) #file.write('\n') else: x = [] for j, v in enumerate(f): if f.smooth: normal = rvec3d(v.no) else: normal = no if faceUV: uvcoord = rvec2d((uv[j][0], 1.0 - uv[j][1])) elif vertexUV: uvcoord = rvec2d((v.uvco[0], 1.0 - v.uvco[1])) if vertexColors: color = col[j].r, col[j].g, col[j].b #file.write('%d ' % vdict[v.index][normal, uvcoord, color]) x += [vdict[v.index][normal, uvcoord, color]] triangles += [[x[1], x[2], x[0]]] triangles += [[x[2], x[3], x[0]]] #file.write('[%d,%d,%d]\n'%()) #file.write('[%d,%d,%d]\n'%(x[1],x[2],x[3])) file.write('triangle count: %d\n' % len(triangles)) for (i, f) in enumerate(triangles): file.write('[%d,' % f[0]) file.write('%d,' % f[1]) file.write('%d]\n' % f[2]) file.close() if is_editmode: Blender.Window.EditMode(1, '', 0)
def write(directory, filename, objects): def v_n_uv_key(v, n, uv): return round(v.x, 6), round(v.y, 6), round(v.z, 6), round(n.x, 6), round( n.y, 6), round(n.z, 6), round(uv[0], 6), round(uv[1], 6) def v_n_key(v, n): return round(v.x, 6), round(v.y, 6), round(v.z, 6), round(n.x, 6), round(n.y, 6), round(n.z, 6) def adjust_key(key, obCenter): keyList = list(key) keyList[0] -= obCenter[0] keyList[1] -= obCenter[1] keyList[2] -= obCenter[2] return tuple(keyList) temp_mesh_name = '~tmp-mesh' scn = Scene.GetCurrent() # Get the container mesh. - used for applying modifiers and non mesh objects. containerMesh = meshName = tempMesh = None for meshName in Blender.NMesh.GetNames(): if meshName.startswith(temp_mesh_name): tempMesh = Mesh.Get(meshName) if not tempMesh.users: containerMesh = tempMesh if not containerMesh: containerMesh = Mesh.New(temp_mesh_name) del meshName del tempMesh try: armature = Blender.Object.Get("Armature") write_armature(directory + filename, armature) except: armature = None # Get all meshs for ob_main in objects: for ob, ob_mat in BPyObject.getDerivedObjects(ob_main): me = BPyMesh.getMeshFromObject(ob, containerMesh, True, False, scn) if not me: continue # Initialize globalVertices and globalMaterials dictionaries vertIndex = 0 matIndex = 0 globalVertices = {} globalMaterials = {} # Dictionary of materials: (material.name, image.name):matname_imagename # matname_imagename has fixed names. materialDict = {} # We have a valid mesh if me.faces: # Add a dummy object to it. has_quads = False for f in me.faces: if len(f) == 4: has_quads = True break if has_quads: oldmode = Mesh.Mode() Mesh.Mode(Mesh.SelectModes['FACE']) me.sel = True tempob = scn.objects.new(me) me.quadToTriangle(0) # more=0 shortest length oldmode = Mesh.Mode(oldmode) scn.objects.unlink(tempob) Mesh.Mode(oldmode) else: continue # High Quality Normals BPyMesh.meshCalcNormals(me) # Make our own list so it can be sorted to reduce context switching faces = [f for f in me.faces] faceuv = me.faceUV edges = me.edges materials = me.materials materialNames = [] materialItems = materials[:] if materials: for mat in materials: if mat: materialNames.append(mat.name) else: materialNames.append(None) # Possible there null materials, will mess up indicies # but at least it will export, wait until Blender gets fixed. materialNames.extend((16 - len(materialNames)) * [None]) materialItems.extend((16 - len(materialItems)) * [None]) # Sort by Material, then images # so we dont over context switch in the obj file. if faceuv: try: faces.sort(key=lambda a: (a.mat, a.image, a.smooth)) except: faces.sort(lambda a, b: cmp((a.mat, a.image, a.smooth), (b.mat, b.image, b.smooth))) elif len(materials) > 1: try: faces.sort(key=lambda a: (a.mat, a.smooth)) except: faces.sort(lambda a, b: cmp((a.mat, a.smooth), (b.mat, b.smooth))) else: # no materials try: faces.sort(key=lambda a: a.smooth) except: faces.sort(lambda a, b: cmp(a.smooth, b.smooth)) # Set the default mat to no material and no image. contextMat = ( 0, 0 ) # Can never be this, so we will label a new material the first chance we get. contextSmooth = None # Will either be true or false, set bad to force initialization switch. name1 = ob.name name2 = ob.getData(1) obnamestring = fixName(name1) file = open(directory + obnamestring + ".drkMesh", "w") # Fill globalVertices dictionary by creating (vert, normal, uv) tuple for all vertices of all faces vertString = "" obCenter = ob.getLocation() if faceuv: vOutputFormat = 'v %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f\n' else: vOutputFormat = 'v %.6f %.6f %.6f %.6f %.6f %.6f\n' f_image = None #Loop through all faces submeshCount = 0 faceCount = 0 faceCounts = [] for face in faces: if faceuv: faceUVs = list(face.uv) faceUVindex = 0 faceIndices = [] for v in face: if face.smooth: vno = v.no else: vno = face.no if faceuv: key = v_n_uv_key(v.co, v.no, faceUVs[faceUVindex]) faceUVindex += 1 else: key = v_n_key(v.co, v.no) if not globalVertices.has_key(key): globalVertices[key] = vertIndex vertString += vOutputFormat % key faceIndices.append(vertIndex) vertIndex += 1 else: faceIndices.append(globalVertices[key]) # Make material,texture key f_mat = min(face.mat, len(materialNames) - 1) if faceuv: f_image = face.image if faceuv and f_image: matKey = materialNames[f_mat], f_image.name else: matKey = materialNames[f_mat], None # Check for context switch if matKey != contextMat: submeshCount += 1 if matKey[0] == None and matKey[1] == None: # Write a null material, since we know the context has changed. faceString += 'use (null)\n' # mat, image else: mat_data = materialDict.get(matKey) if not mat_data: mat_data = materialDict[matKey] = fixName( matKey[0]), materialItems[f_mat], f_image vertString += 'use %d\n' % matIndex globalMaterials[mat_data[0]] = matIndex matIndex += 1 if faceCount != 0: faceCounts.append(faceCount) faceCount = 0 contextMat = matKey vertString += 'face %d %d %d\n' % tuple(faceIndices) faceCount += 1 faceCounts.append(faceCount) file.write('count %d\n' % vertIndex) if faceuv: file.write('uvs\n') file.write('submeshes %d\n' % submeshCount) for faceCount in faceCounts: file.write('faces %d\n' % faceCount) file.write(vertString) me.verts = None write_mtl(file, materialDict, globalMaterials) file.close()
def main(): PREF_Z_LOC= Blender.Draw.PupMenu('Cut Z Location%t|Original Faces|Cutting Polyline') if PREF_Z_LOC==-1: return PREF_Z_LOC-=1 Blender.Window.WaitCursor(1) print '\nRunning Cookie Cutter' time= Blender.sys.time() scn = Blender.Scene.GetCurrent() obs= [ob for ob in scn.objects.context if ob.type in ('Mesh', 'Curve')] MULTIRES_ERROR = False # Divide into 2 lists- 1 with faces, one with only edges terrains= [] #[me for me in mes if me.faces] cutters= [] #[me for me in mes if not me.faces] terrain_type= auto_class(['mesh', 'bounds', 'face_bounds', 'edge_bounds', 'edge_dict', 'cutters', 'matrix']) for ob in obs: if ob.type == 'Mesh': me= ob.getData(mesh=1) elif ob.data.flag & 1: # Is the curve 3D? else don't use. me= BPyMesh.getMeshFromObject(ob) # get the curve else: continue # a new terrain instance if me.multires: MULTIRES_ERROR = True else: t= terrain_type() t.matrix= ob.matrixWorld * Blender.Window.GetViewMatrix() # Transform the object by its matrix me.transform(t.matrix) # Set the terrain bounds t.bounds= bounds_xy(me.verts) t.edge_bounds= [bounds_xy(ed) for ed in me.edges] t.mesh= me if me.faces: # Terrain. t.edge_dict= mesh_edge_dict(me) t.face_bounds= [bounds_xy(f) for f in me.faces] t.cutters= [] # Store cutting objects that cut us here terrains.append(t) elif len(me.edges)>2: # Cutter cutters.append(t) totcuts= len(terrains)*len(cutters) if not totcuts: Blender.Window.WaitCursor(0) Blender.Draw.PupMenu('ERROR%t|Select at least 1 closed loop mesh (edges only)|as the cutter...|and 1 or more meshes to cut into') crazy_point= Vector(100000, 100000) for t in terrains: for c in cutters: # Main curring function terrain_cut_2d(t, c, PREF_Z_LOC) # Was the terrain touched? if len(t.face_bounds) != len(t.mesh.faces): t.edge_dict= mesh_edge_dict(t.mesh) # remake the bounds t.edge_bounds= [bounds_xy(ed) for ed in t.mesh.edges] t.face_bounds= [bounds_xy(f) for f in t.mesh.faces] t.cutters.append(c) print '\t%i remaining' % totcuts totcuts-=1 # SELECT INTERNAL FACES ONCE THIS TERRAIN IS CUT Blender.Mesh.Mode(Blender.Mesh.SelectModes['FACE']) t.mesh.sel= 0 for c in t.cutters: edge_verts_c= [(ed_c.v1.co, ed_c.v2.co) for ed_c in c.mesh.edges] for f in t.mesh.faces: # How many edges do we intersect on our way to the faces center if not f.hide and not f.sel: # Not alredy selected c= f.cent if point_in_bounds(c, t.bounds): isect_count= 0 for edv1, edv2 in edge_verts_c: isect_count += (LineIntersect2D(c, crazy_point, edv1, edv2) != None) if isect_count%2: f.sel= 1 Blender.Mesh.Mode(Blender.Mesh.SelectModes['FACE']) # Restore the transformation for data in (terrains, cutters): for t in data: if t.mesh.users: # it may have been a temp mesh from a curve. t.mesh.transform(t.matrix.copy().invert()) Blender.Window.WaitCursor(0) if MULTIRES_ERROR: Blender.Draw.PupMenu('Error%t|One or more meshes meshes not cut because they are multires.') print 'terrains:%i cutters %i %.2f secs taken' % (len(terrains), len(cutters), Blender.sys.time()-time)
def write(filename, objects,\ EXPORT_APPLY_MODIFIERS=True, EXPORT_ROTX90=True): ''' Basic write function. The context and options must be alredy set This can be accessed externaly eg. write( 'c:\\test\\foobar.obj', Blender.Object.GetSelected() ) # Using default options. ''' def veckey3d(v): return round(v.x, 6), round(v.y, 6), round(v.z, 6) def veckey2d(v): return round(v.x, 6), round(v.y, 6) print 'EOL MESH Export path: "%s"' % filename temp_mesh_name = '~tmp-mesh' time1 = sys.time() scn = Scene.GetCurrent() file = open(filename, "w") # Write Header file.write('# Blender3D v%s EOL MESH File: %s\n' % (Blender.Get('version'), Blender.Get('filename').split('/')[-1].split('\\')[-1])) file.write('# www.blender3d.org\n') # Get the container mesh. - used for applying modifiers and non mesh objects. containerMesh = meshName = tempMesh = None for meshName in Blender.NMesh.GetNames(): if meshName.startswith(temp_mesh_name): tempMesh = Mesh.Get(meshName) if not tempMesh.users: containerMesh = tempMesh if not containerMesh: containerMesh = Mesh.New(temp_mesh_name) if EXPORT_ROTX90: mat_xrot90 = Blender.Mathutils.RotationMatrix(-90, 4, 'x') del meshName del tempMesh # Initialize totals, these are updated each object totverts = totuvco = totno = 1 face_vert_index = 1 globalNormals = {} # Get all meshs for ob_main in objects: for ob, ob_mat in BPyObject.getDerivedObjects(ob_main): # Will work for non meshes now! :) # getMeshFromObject(ob, container_mesh=None, apply_modifiers=True, vgroups=True, scn=None) me = BPyMesh.getMeshFromObject(ob, containerMesh, EXPORT_APPLY_MODIFIERS, False, scn) if not me: continue faceuv = me.faceUV has_quads = False for f in me.faces: if len(f) == 4: has_quads = True break if has_quads: oldmode = Mesh.Mode() Mesh.Mode(Mesh.SelectModes['FACE']) me.sel = True tempob = scn.objects.new(me) me.quadToTriangle(0) # more=0 shortest length oldmode = Mesh.Mode(oldmode) scn.objects.unlink(tempob) Mesh.Mode(oldmode) edges = me.edges faces = [f for f in me.faces] if EXPORT_ROTX90: me.transform(ob_mat * mat_xrot90) else: me.transform(ob_mat) # Vert mesh = ob.getData() objmat = ob.getMatrix() for i in objmat: file.write('obm: %.6f %.6f %.6f %.6f\n' % tuple(i)) vgrouplist = mesh.getVertGroupNames() file.write('vgroupcount: %i\n' % len(vgrouplist)) for vgname in vgrouplist: file.write('vgroup: %s\n' % vgname) file.write('vertexcount: %i\n' % len(mesh.verts)) for v in mesh.verts: file.write('v %.6f %.6f %.6f\n' % tuple(v.co)) influences = mesh.getVertexInfluences(v.index) file.write('influence: %i\n' % len(influences)) for name, weight in influences: file.write('groupname: %s\n' % name) file.write('weight: %f\n' % weight) # UV if faceuv: uv_face_mapping = [[0, 0, 0, 0] for f in faces ] # a bit of a waste for tri's :/ uv_dict = {} # could use a set() here for f_index, f in enumerate(faces): for uv_index, uv in enumerate(f.uv): uvkey = veckey2d(uv) try: uv_face_mapping[f_index][uv_index] = uv_dict[uvkey] except: uv_face_mapping[f_index][uv_index] = uv_dict[ uvkey] = len(uv_dict) file.write('vt %.6f %.6f\n' % tuple(uv)) uv_unique_count = len(uv_dict) del uv, uvkey, uv_dict, f_index, uv_index # Only need uv_unique_count and uv_face_mapping file.write('uvcount: %i\n' % uv_unique_count) # NORMAL, Smooth/Non smoothed. for f in faces: if f.smooth: for v in f: noKey = veckey3d(v.no) if not globalNormals.has_key(noKey): globalNormals[noKey] = totno totno += 1 file.write('vn %.6f %.6f %.6f\n' % noKey) else: # Hard, 1 normal from the face. noKey = veckey3d(f.no) if not globalNormals.has_key(noKey): globalNormals[noKey] = totno totno += 1 file.write('vn %.6f %.6f %.6f\n' % noKey) file.write('normalcount: %i\n' % len(globalNormals)) if not faceuv: f_image = None file.write('facecount: %i\n' % len(faces)) for f_index, f in enumerate(faces): f_v = f.v f_smooth = f.smooth if faceuv: f_uv = f.uv file.write('f') if faceuv: if f_smooth: # Smoothed, use vertex normals for vi, v in enumerate(f_v): file.write( ' %d/%d/%d' % (\ v.index+totverts,\ totuvco + uv_face_mapping[f_index][vi],\ globalNormals[ veckey3d(v.no) ])) # vert, uv, normal else: # No smoothing, face normals no = globalNormals[veckey3d(f.no)] for vi, v in enumerate(f_v): file.write( ' %d/%d/%d' % (\ v.index+totverts,\ totuvco + uv_face_mapping[f_index][vi],\ no)) # vert, uv, normal face_vert_index += len(f_v) else: # No UV's if f_smooth: # Smoothed, use vertex normals for v in f_v: file.write( ' %d//%d' % (\ v.index+totverts,\ globalNormals[ veckey3d(v.no) ])) else: # No smoothing, face normals no = globalNormals[veckey3d(f.no)] for v in f_v: file.write( ' %d//%d' % (\ v.index+totverts,\ no)) file.write('\n') # Write edges. LOOSE = Mesh.EdgeFlags.LOOSE for ed in edges: if ed.flag & LOOSE: file.write( 'f %d %d\n' % (ed.v1.index + totverts, ed.v2.index + totverts)) # Make the indicies global rather then per mesh totverts += len(me.verts) if faceuv: totuvco += uv_unique_count me.verts = None file.close() # Now we have all our materials, save them print "MESH Export time: %.2f" % (sys.time() - time1)
def write(filename): start = Blender.sys.time() if not filename.lower().endswith('.js'): filename += '.js' scn = Blender.Scene.GetCurrent() ob = scn.objects.active if not ob: Blender.Draw.PupMenu('Error%t|Select 1 active object') return file = open(filename, 'wb') mesh = BPyMesh.getMeshFromObject(ob, None, True, False, scn) if not mesh: Blender.Draw.PupMenu( 'Error%t|Could not get mesh data from active object') return mesh.transform(ob.matrixWorld) #classname = clean(ob.name) classname = filename.split('/')[-1].replace('.js', '') file = open(filename, "wb") file.write('var %s = function () {\n\n' % classname) file.write('\tvar scope = this;\n\n') file.write('\tTHREE.Geometry.call(this);\n\n') for v in mesh.verts: file.write('\tv( %.6f, %.6f, %.6f );\n' % (v.co.x, v.co.z, -v.co.y)) # co file.write('\n') for f in mesh.faces: if len(f.verts) == 3: file.write('\tf3( %d, %d, %d, %.6f, %.6f, %.6f );\n' % (f.verts[0].index, f.verts[1].index, f.verts[2].index, f.verts[0].no.x, f.verts[0].no.z, -f.verts[0].no.y)) else: file.write('\tf4( %d, %d, %d, %d, %.6f, %.6f, %.6f );\n' % (f.verts[0].index, f.verts[1].index, f.verts[2].index, f.verts[3].index, f.verts[0].no.x, f.verts[0].no.z, -f.verts[0].no.y)) face_index_pairs = [(face, index) for index, face in enumerate(mesh.faces)] file.write('\n') ''' for f in me.faces: if me.faceUV: if len(f.verts) == 3: file.write('\tuv( %.6f, %.6f, %.6f, %.6f, %.6f, %.6f );\n' % (f.uv[0][0], 1.0-f.uv[0][1], f.uv[1][0], 1.0-f.uv[1][1], f.uv[2][0], 1.0-f.uv[2][1]) ''' for f in mesh.faces: if mesh.faceUV: if len(f.verts) == 3: file.write('\tuv( %.6f, %.6f, %.6f, %.6f, %.6f, %.6f );\n' % (f.uv[0].x, 1.0 - f.uv[0].y, f.uv[1].x, 1.0 - f.uv[1].y, f.uv[2].x, 1.0 - f.uv[2].y)) else: file.write( '\tuv( %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f);\n' % (f.uv[0].x, 1.0 - f.uv[0].y, f.uv[1].x, 1.0 - f.uv[1].y, f.uv[2].x, 1.0 - f.uv[2].y, f.uv[3].x, 1.0 - f.uv[3].y)) file.write('\n') file.write('\tfunction v( x, y, z ) {\n\n') file.write( '\t\tscope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) );\n\n' ) file.write('\t}\n\n') file.write('\tfunction f3( a, b, c, nx, ny, nz ) {\n\n') file.write( '\t\tscope.faces.push( new THREE.Face3( a, b, c, nx && ny && nz ? new THREE.Vector3( nx, ny, nz ) : null ) );\n\n' ) file.write('\t}\n\n') file.write('\tfunction f4( a, b, c, d, nx, ny, nz ) {\n\n') file.write( '\t\tscope.faces.push( new THREE.Face4( a, b, c, d, nx && ny && nz ? new THREE.Vector3( nx, ny, nz ) : null ) );\n\n' ) file.write('\t}\n\n') file.write('\tfunction uv( u1, v1, u2, v2, u3, v3, u4, v4 ) {\n\n') file.write('\t\tvar uv = [];\n') file.write('\t\tuv.push( new THREE.UV( u1, v1 ) );\n') file.write('\t\tuv.push( new THREE.UV( u2, v2 ) );\n') file.write('\t\tuv.push( new THREE.UV( u3, v3 ) );\n') file.write('\t\tif ( u4 && v4 ) uv.push( new THREE.UV( u4, v4 ) );\n') file.write('\t\tscope.uvs.push( uv );\n') file.write('\t}\n\n') file.write('}\n\n') file.write('%s.prototype = new THREE.Geometry();\n' % classname) file.write('%s.prototype.constructor = %s;' % (classname, classname)) file.close()
def file_callback(filename): if not filename.lower().endswith('.ply'): filename += '.ply' scn = bpy.data.scenes.active ob = scn.objects.active if not ob: Blender.Draw.PupMenu('Error%t|Select 1 active object') return file = open(filename, 'wb') EXPORT_APPLY_MODIFIERS = Draw.Create(1) EXPORT_NORMALS = Draw.Create(1) EXPORT_UV = Draw.Create(1) EXPORT_COLORS = Draw.Create(1) #EXPORT_EDGES = Draw.Create(0) pup_block = [\ ('Apply Modifiers', EXPORT_APPLY_MODIFIERS, 'Use transformed mesh data.'),\ ('Normals', EXPORT_NORMALS, 'Export vertex normal data.'),\ ('UVs', EXPORT_UV, 'Export texface UV coords.'),\ ('Colors', EXPORT_COLORS, 'Export vertex Colors.'),\ #('Edges', EXPORT_EDGES, 'Edges not connected to faces.'),\ ] if not Draw.PupBlock('Export...', pup_block): return is_editmode = Blender.Window.EditMode() if is_editmode: Blender.Window.EditMode(0, '', 0) Window.WaitCursor(1) EXPORT_APPLY_MODIFIERS = EXPORT_APPLY_MODIFIERS.val EXPORT_NORMALS = EXPORT_NORMALS.val EXPORT_UV = EXPORT_UV.val EXPORT_COLORS = EXPORT_COLORS.val #EXPORT_EDGES = EXPORT_EDGES.val mesh = BPyMesh.getMeshFromObject(ob, None, EXPORT_APPLY_MODIFIERS, False, scn) if not mesh: Blender.Draw.PupMenu( 'Error%t|Could not get mesh data from active object') return mesh.transform(ob.matrixWorld) faceUV = mesh.faceUV vertexUV = mesh.vertexUV vertexColors = mesh.vertexColors if (not faceUV) and (not vertexUV): EXPORT_UV = False if not vertexColors: EXPORT_COLORS = False if not EXPORT_UV: faceUV = vertexUV = False if not EXPORT_COLORS: vertexColors = False # incase color = uvcoord = uvcoord_key = normal = normal_key = None verts = [] # list of dictionaries # vdict = {} # (index, normal, uv) -> new index vdict = [{} for i in xrange(len(mesh.verts))] vert_count = 0 for i, f in enumerate(mesh.faces): smooth = f.smooth if not smooth: normal = tuple(f.no) normal_key = rvec3d(normal) if faceUV: uv = f.uv if vertexColors: col = f.col for j, v in enumerate(f): if smooth: normal = tuple(v.no) normal_key = rvec3d(normal) if faceUV: uvcoord = uv[j][0], 1.0 - uv[j][1] uvcoord_key = rvec2d(uvcoord) elif vertexUV: uvcoord = v.uvco[0], 1.0 - v.uvco[1] uvcoord_key = rvec2d(uvcoord) if vertexColors: color = col[j].r, col[j].g, col[j].b key = normal_key, uvcoord_key, color vdict_local = vdict[v.index] if (not vdict_local) or (not vdict_local.has_key(key)): vdict_local[key] = vert_count verts.append((tuple(v.co), normal, uvcoord, color)) vert_count += 1 file.write('ply\n') file.write('format ascii 1.0\n') file.write( 'comment Created by Blender3D %s - www.blender.org, source file: %s\n' % (Blender.Get('version'), Blender.Get('filename').split('/')[-1].split('\\')[-1])) file.write('element vertex %d\n' % len(verts)) file.write('property float x\n') file.write('property float y\n') file.write('property float z\n') if EXPORT_NORMALS: file.write('property float nx\n') file.write('property float ny\n') file.write('property float nz\n') if EXPORT_UV: file.write('property float s\n') file.write('property float t\n') if EXPORT_COLORS: file.write('property uchar red\n') file.write('property uchar green\n') file.write('property uchar blue\n') file.write('element face %d\n' % len(mesh.faces)) file.write('property list uchar uint vertex_indices\n') file.write('end_header\n') for i, v in enumerate(verts): file.write('%.6f %.6f %.6f ' % v[0]) # co if EXPORT_NORMALS: file.write('%.6f %.6f %.6f ' % v[1]) # no if EXPORT_UV: file.write('%.6f %.6f ' % v[2]) # uv if EXPORT_COLORS: file.write('%u %u %u' % v[3]) # col file.write('\n') for (i, f) in enumerate(mesh.faces): file.write('%d ' % len(f)) smooth = f.smooth if not smooth: no = rvec3d(f.no) if faceUV: uv = f.uv if vertexColors: col = f.col for j, v in enumerate(f): if f.smooth: normal = rvec3d(v.no) else: normal = no if faceUV: uvcoord = rvec2d((uv[j][0], 1.0 - uv[j][1])) elif vertexUV: uvcoord = rvec2d((v.uvco[0], 1.0 - v.uvco[1])) if vertexColors: color = col[j].r, col[j].g, col[j].b file.write('%d ' % vdict[v.index][normal, uvcoord, color]) file.write('\n') file.close() if is_editmode: Blender.Window.EditMode(1, '', 0)
def apply_deform(): scn = bpy.data.scenes.active #Blender.Window.EditMode(0) NAME_LENGTH = 19 SUFFIX = "_def" SUFFIX_LENGTH = len(SUFFIX) # Get all object and mesh names ob_list = list(scn.objects.context) ob_act = scn.objects.active # Assume no soft body has_sb = False # reverse loop so we can remove objects (metaballs in this case) for ob_idx in xrange(len(ob_list) - 1, -1, -1): ob = ob_list[ob_idx] ob.sel = 0 # deselect while where checking the metaballs # Test for a softbody if not has_sb and ob.isSB(): has_sb = True # Remove all numbered metaballs because their disp list is only on the main metaball (un numbered) if ob.type == 'MBall': name = ob.name # is this metaball numbered? dot_idx = name.rfind('.') + 1 if name[dot_idx:].isdigit(): # Not the motherball, ignore it. del ob_list[ob_idx] if not ob_list: Blender.Draw.PupMenu('No objects selected, nothing to do.') return if has_sb: curframe = Blender.Get('curframe') for f in xrange(curframe): Blender.Set('curframe', f + 1) Blender.Window.RedrawAll() used_names = [ob.name for ob in Blender.Object.Get()] used_names.extend(Blender.NMesh.GetNames()) deformedList = [] for ob in ob_list: # Get the mesh data new_me = BPyMesh.getMeshFromObject(ob, vgroups=False) if not new_me: continue # Object has no display list name = ob.name new_name = "%s_def" % name[:NAME_LENGTH - SUFFIX_LENGTH] num = 0 while new_name in used_names: new_name = "%s_def.%.3i" % (name[:NAME_LENGTH - (SUFFIX_LENGTH + SUFFIX_LENGTH)], num) num += 1 used_names.append(new_name) new_me.name = new_name new_ob = scn.objects.new(new_me) new_ob.setMatrix(ob.matrixWorld) # Make the active duplicate also active if ob == ob_act: scn.objects.active = new_ob # Original object was a mesh? see if we can copy any vert groups. if ob.type == 'Mesh': copy_vgroups(ob, new_ob) Blender.Window.RedrawAll()
def save_3ds(filename): print " " print "starting 3ds export" global CS_GLOBALOPTIONS_OBJ '''Save the Blender scene to a 3ds file.''' # Time the export if not filename.lower().endswith('.3ds'): filename += '.3ds' if not BPyMessages.Warning_SaveOver(filename): return time1= Blender.sys.time() Blender.Window.WaitCursor(1) sce= bpy.data.scenes.active # Initialize the main chunk (primary): primary = _3ds_chunk(PRIMARY) # Add version chunk: version_chunk = _3ds_chunk(VERSION) version_chunk.add_variable("version", _3ds_int(3)) primary.add_subchunk(version_chunk) # init main object info chunk: object_info = _3ds_chunk(OBJECTINFO) ''' # COMMENTED OUT FOR 2.42 RELEASE!! CRASHES 3DS MAX ''' # 4KEX: Enabled kfdata with changes. Hopefully will not crash 3DS MAX (not tested) # init main key frame data chunk: kfdata = make_kfdata() # Get all the supported objects selected in this scene: ob_sel= list(sce.objects.context) for ob in ob_sel: if ob.name.upper() == '~CS_GLOBALOPTIONS': ob_sel.remove(ob) CS_GLOBALOPTIONS_OBJ = ob break mesh_objects = [ (ob, me) for ob in ob_sel for me in (BPyMesh.getMeshFromObject(ob, None, True, False, sce),) if me ] empty_objects = [ ob for ob in ob_sel if ob.type == 'Empty' ] # Make a list of all materials used in the selected meshes (use a dictionary, # each material is added once): materialDict = {} mesh_objects = [] for ob in ob_sel: for ob_derived, mat in getDerivedObjects(ob, False): data = getMeshFromObject(ob_derived, None, True, False, sce) if data: # 4KEX: Removed mesh transformation. Will do this later based on parenting and other factors. #zzz so vertices are in local coordinates #zzz orig was the next line commented out data.transform(mat, recalc_normals=False) mesh_objects.append((ob_derived, data)) mat_ls = data.materials mat_ls_len = len(mat_ls) # get material/image tuples. if data.faceUV: if not mat_ls: mat = mat_name = None for f in data.faces: if mat_ls: mat_index = f.mat if mat_index >= mat_ls_len: mat_index = f.mat = 0 mat = mat_ls[mat_index] if mat: mat_name = mat.name else: mat_name = None # else there alredy set to none img = f.image if img: img_name = img.name else: img_name = None materialDict.setdefault((mat_name, img_name), (mat, img) ) else: for mat in mat_ls: if mat: # material may be None so check its not. materialDict.setdefault((mat.name, None), (mat, None) ) # Why 0 Why! for f in data.faces: if f.mat >= mat_ls_len: f.mat = 0 # Make material chunks for all materials used in the meshes: for mat_and_image in materialDict.itervalues(): object_info.add_subchunk(make_material_chunk(mat_and_image[0], mat_and_image[1])) # 4KEX: Added MASTERSCALE element mscale = _3ds_chunk(MASTERSCALE) mscale.add_variable("scale", _3ds_float(1)) object_info.add_subchunk(mscale) # Give all objects a unique ID and build a dictionary from object name to object id: name_to_id = {} name_to_scale = {} name_to_pos = {} name_to_rot = {} name_to_rotzzz = {} #zzz my copy of name_to_rot for my debug use for ob, data in mesh_objects: name_to_id[ob.name]= len(name_to_id) name_to_scale[ob.name] = ob.getSize('worldspace') name_to_pos[ob.name] = ob.getLocation('worldspace') name_to_rot[ob.name] = ob.getEuler('worldspace') name_to_rot[ob.name] = name_to_rot[ob.name].toQuat().inverse() #applying toquat() produces angle and axis properties but blender rotates the other way so need to inverse this too for ob in empty_objects: name_to_id[ob.name]= len(name_to_id) name_to_scale[ob.name] = ob.getSize('worldspace') name_to_pos[ob.name] = ob.getLocation('worldspace') name_to_rot[ob.name] = ob.getEuler('worldspace') name_to_rot[ob.name] = name_to_rot[ob.name].toQuat().inverse() # Create object chunks for all meshes: i = 0 for ob, blender_mesh in mesh_objects: # create a new object chunk object_chunk = _3ds_chunk(OBJECT) # set the object name object_chunk.add_variable("name", _3ds_string(sane_name(ob.name, "object", False))) # make a mesh chunk out of the mesh: object_chunk.add_subchunk(make_mesh_chunk(blender_mesh, materialDict, ob, name_to_id, name_to_scale, name_to_pos, name_to_rot)) object_info.add_subchunk(object_chunk) # 4KEX: export kfdata node kfdata.add_subchunk(make_kf_obj_node(ob, name_to_id, name_to_scale, name_to_pos, name_to_rot)) blender_mesh.verts = None i+=i # Create chunks for all empties: # 4KEX: Re-enabled kfdata. Empty objects not tested yet. for ob in empty_objects: # Empties only require a kf object node: kfdata.add_subchunk(make_kf_obj_node(ob, name_to_id, name_to_scale, name_to_pos, name_to_rot)) # Add main object info chunk to primary chunk: primary.add_subchunk(object_info) # 4KEX: Export kfdata primary.add_subchunk(kfdata) # At this point, the chunk hierarchy is completely built. # Check the size: primary.get_size() # Open the file for writing: file = open( filename, 'wb' ) # Recursively write the chunks to file: primary.write(file) # Close the file: file.close() # Check if SUP file is requested global ENABLE_SUP if ENABLE_SUP: # Open the SUP file file = open( filename[:-4]+'.sup', 'w' ) # Write the RootFrame object if ENABLE_BETA: file.write( '[RootFrame]\r\nIsPivot=BOOL:No\r\nName=STRING:RootFrame\r\nParent=STRING:\r\nPivot=STRING:\r\n\r\n' ) else: file.write( '[RootFrame]\r\nIsPivot=No\r\nName=RootFrame\r\nParent=\r\nPivot=\r\n\r\n' ) read_globaloptions() for ob, blender_mesh in mesh_objects: write_sup( file, ob, False ) for ob in empty_objects: write_sup( file, ob, True ) # Close the SUP file file.close() global ENABLE_KEX if ENABLE_KEX: global KEX_FILE cmd_line = '""' + KEX_FILE + '" -s -v3 \"' + filename + '\""' os.system(cmd_line) # Debugging only: report the exporting time: Blender.Window.WaitCursor(0) print "3ds export time: %.2f" % (Blender.sys.time() - time1)
def export(self, scene, world, alltextures,\ EXPORT_APPLY_MODIFIERS = False,\ EXPORT_TRI= False,\ ): print "Info: starting X3D export to " + self.filename + "..." self.writeHeader() # self.writeScript() self.writeNavigationInfo(scene) self.writeBackground(world, alltextures) self.writeFog(world) self.proto = 0 # COPIED FROM OBJ EXPORTER if EXPORT_APPLY_MODIFIERS: temp_mesh_name = '~tmp-mesh' # Get the container mesh. - used for applying modifiers and non mesh objects. containerMesh = meshName = tempMesh = None for meshName in Blender.NMesh.GetNames(): if meshName.startswith(temp_mesh_name): tempMesh = Mesh.Get(meshName) if not tempMesh.users: containerMesh = tempMesh if not containerMesh: containerMesh = Mesh.New(temp_mesh_name) # -------------------------- for ob_main in scene.objects.context: for ob, ob_mat in BPyObject.getDerivedObjects(ob_main): objType = ob.type objName = ob.name self.matonly = 0 if objType == "Camera": self.writeViewpoint(ob, ob_mat, scene) elif objType in ("Mesh", "Curve", "Surf", "Text"): if EXPORT_APPLY_MODIFIERS or objType != 'Mesh': me = BPyMesh.getMeshFromObject(ob, containerMesh, EXPORT_APPLY_MODIFIERS, False, scene) else: me = ob.getData(mesh=1) self.writeIndexedFaceSet(ob, me, ob_mat, world, EXPORT_TRI=EXPORT_TRI) elif objType == "Lamp": data = ob.data datatype = data.type if datatype == Lamp.Types.Lamp: self.writePointLight(ob, ob_mat, data, world) elif datatype == Lamp.Types.Spot: self.writeSpotLight(ob, ob_mat, data, world) elif datatype == Lamp.Types.Sun: self.writeDirectionalLight(ob, ob_mat, data, world) else: self.writeDirectionalLight(ob, ob_mat, data, world) # do you think x3d could document what to do with dummy objects? #elif objType == "Empty" and objName != "Empty": # self.writeNode(ob, ob_mat) else: #print "Info: Ignoring [%s], object type [%s] not handle yet" % (object.name,object.getType) pass self.file.write("\n</Scene>\n</X3D>") if EXPORT_APPLY_MODIFIERS: if containerMesh: containerMesh.verts = None self.cleanup()
def export(self, scene, world, alltextures,\ EXPORT_APPLY_MODIFIERS = False,\ EXPORT_TRI= False,\ ): print "Info: starting X3D export to " + self.filename + "..." self.writeHeader() # self.writeScript() self.writeNavigationInfo(scene) self.writeBackground(world, alltextures) self.writeFog(world) self.proto = 0 # COPIED FROM OBJ EXPORTER if EXPORT_APPLY_MODIFIERS: temp_mesh_name = '~tmp-mesh' # Get the container mesh. - used for applying modifiers and non mesh objects. containerMesh = meshName = tempMesh = None for meshName in Blender.NMesh.GetNames(): if meshName.startswith(temp_mesh_name): tempMesh = Mesh.Get(meshName) if not tempMesh.users: containerMesh = tempMesh if not containerMesh: containerMesh = Mesh.New(temp_mesh_name) # -------------------------- for ob_main in scene.objects.context: for ob, ob_mat in BPyObject.getDerivedObjects(ob_main): objType=ob.type objName=ob.name self.matonly = 0 if objType == "Camera": self.writeViewpoint(ob, ob_mat, scene) elif objType in ("Mesh", "Curve", "Surf", "Text") : if EXPORT_APPLY_MODIFIERS or objType != 'Mesh': me= BPyMesh.getMeshFromObject(ob, containerMesh, EXPORT_APPLY_MODIFIERS, False, scene) else: me = ob.getData(mesh=1) self.writeIndexedFaceSet(ob, me, ob_mat, world, EXPORT_TRI = EXPORT_TRI) elif objType == "Lamp": data= ob.data datatype=data.type if datatype == Lamp.Types.Lamp: self.writePointLight(ob, ob_mat, data, world) elif datatype == Lamp.Types.Spot: self.writeSpotLight(ob, ob_mat, data, world) elif datatype == Lamp.Types.Sun: self.writeDirectionalLight(ob, ob_mat, data, world) else: self.writeDirectionalLight(ob, ob_mat, data, world) # do you think x3d could document what to do with dummy objects? #elif objType == "Empty" and objName != "Empty": # self.writeNode(ob, ob_mat) else: #print "Info: Ignoring [%s], object type [%s] not handle yet" % (object.name,object.getType) pass self.file.write("\n</Scene>\n</X3D>") if EXPORT_APPLY_MODIFIERS: if containerMesh: containerMesh.verts = None self.cleanup()
def write(filename, objects,\ EXPORT_NORMALS_HQ=False,\ EXPORT_MTL=True, EXPORT_COPY_IMAGES=False,\ EXPORT_APPLY_MODIFIERS=True, EXPORT_BLEN_OBS=True,\ EXPORT_GROUP_BY_OB=False): ''' Basic write function. The context and options must be alredy set This can be accessed externaly eg. write( 'c:\\test\\foobar.obj', Blender.Object.GetSelected() ) # Using default options. ''' def veckey3d(v): return round(v.x, 6), round(v.y, 6), round(v.z, 6) def veckey2d(v): return round(v.x, 6), round(v.y, 6) print 'WTF Export path: "%s"' % filename temp_mesh_name = '~tmp-mesh' time1 = sys.time() scn = Scene.GetCurrent() file = open(filename, "w") file.write('<?xml version="1.0"?>\n') file.write('<OPEN_TRACK>\n') # Write Header # file.write('\n<!--\n' # + ' Blender3D v%s WTF File: %s\n' % (Blender.Get('version'), Blender.Get('filename').split('/')[-1].split('\\')[-1] ) # + ' www.blender3d.org\n' # + '-->\n\n') # Get the container mesh. - used for applying modifiers and non mesh objects. containerMesh = meshName = tempMesh = None for meshName in Blender.NMesh.GetNames(): if meshName.startswith(temp_mesh_name): tempMesh = Mesh.Get(meshName) if not tempMesh.users: containerMesh = tempMesh if not containerMesh: containerMesh = Mesh.New(temp_mesh_name) del meshName del tempMesh # Initialize totals, these are updated each object totverts = totuvco = totno = 0 face_vert_index = 0 globalNormals = {} file.write('\n<library_objects>\n') # Get all meshs for ob_main in objects: obnamestring = fixName(ob_main.name) file.write('\t<object id="%s">\n' % obnamestring) # Write Object name for ob, ob_mat in BPyObject.getDerivedObjects(ob_main): # Will work for non meshes now! :) # getMeshFromObject(ob, container_mesh=None, apply_modifiers=True, vgroups=True, scn=None) me = BPyMesh.getMeshFromObject(ob, containerMesh, EXPORT_APPLY_MODIFIERS, False, scn) if not me: file.write('\t\t<loc>%.6f %.6f %.6f</loc>\n' % tuple(ob_main.loc)) # Write Object name file.write('\t\t<rot>%.6f %.6f %.6f</rot>\n' % tuple(ob_main.rot)) # Write Object name continue faceuv = me.faceUV # We have a valid mesh if me.faces: # Add a dummy object to it. has_quads = False for f in me.faces: if len(f) == 4: has_quads = True break if has_quads: oldmode = Mesh.Mode() Mesh.Mode(Mesh.SelectModes['FACE']) me.sel = True tempob = scn.objects.new(me) me.quadToTriangle(0) # more=0 shortest length oldmode = Mesh.Mode(oldmode) scn.objects.unlink(tempob) Mesh.Mode(oldmode) # Make our own list so it can be sorted to reduce context switching faces = [ f for f in me.faces ] edges = me.edges if not (len(faces)+len(edges)+len(me.verts)): # Make sure there is somthing to write continue # dont bother with this mesh. me.transform(ob_mat) # High Quality Normals if faces: if EXPORT_NORMALS_HQ: BPyMesh.meshCalcNormals(me) else: # transforming normals is incorrect # when the matrix is scaled, # better to recalculate them me.calcNormals() # # Crash Blender #materials = me.getMaterials(1) # 1 == will return None in the list. materials = me.materials materialNames = [] materialItems = materials[:] if materials: for mat in materials: if mat: # !=None materialNames.append(mat.name) else: materialNames.append(None) # Cant use LC because some materials are None. # materialNames = map(lambda mat: mat.name, materials) # Bug Blender, dosent account for null materials, still broken. # Possible there null materials, will mess up indicies # but at least it will export, wait until Blender gets fixed. materialNames.extend((16-len(materialNames)) * [None]) materialItems.extend((16-len(materialItems)) * [None]) # Sort by Material, then images # so we dont over context switch in the obj file. if faceuv: try: faces.sort(key = lambda a: (a.mat, a.image, a.smooth)) except: faces.sort(lambda a,b: cmp((a.mat, a.image, a.smooth), (b.mat, b.image, b.smooth))) elif len(materials) > 1: try: faces.sort(key = lambda a: (a.mat, a.smooth)) except: faces.sort(lambda a,b: cmp((a.mat, a.smooth), (b.mat, b.smooth))) else: # no materials try: faces.sort(key = lambda a: a.smooth) except: faces.sort(lambda a,b: cmp(a.smooth, b.smooth)) # Set the default mat to no material and no image. contextMat = (0, 0) # Can never be this, so we will label a new material teh first chance we get. contextSmooth = None # Will either be true or false, set bad to force initialization switch. if len(faces) > 0: file.write('\t\t<mesh>\n') else: file.write('\t\t<curve>\n') vertname = "%s-Vertices" % obnamestring vertarrayname = "%s-Array" % vertname normname = "%s-Normals" % obnamestring normarrayname = "%s-Array" % normname texname = "%s-TexCoord" % obnamestring texarrayname = "%s-Array" % texname # Vert file.write('\t\t\t<float_array count="%d" id="%s">' % (len(me.verts), vertarrayname)) for v in me.verts: file.write(' %.6f %.6f %.6f' % tuple(v.co)) file.write('</float_array>\n') file.write('\t\t\t<vertices id="%s" source="#%s" />\n' % (vertname, vertarrayname)) # UV if faceuv: file.write('\t\t\t<float_array id="%s">' % texarrayname) uv_face_mapping = [[0,0,0,0] for f in faces] # a bit of a waste for tri's :/ uv_dict = {} # could use a set() here for f_index, f in enumerate(faces): for uv_index, uv in enumerate(f.uv): uvkey = veckey2d(uv) try: uv_face_mapping[f_index][uv_index] = uv_dict[uvkey] except: uv_face_mapping[f_index][uv_index] = uv_dict[uvkey] = len(uv_dict) file.write(' %.6f %.6f' % tuple(uv)) uv_unique_count = len(uv_dict) del uv, uvkey, uv_dict, f_index, uv_index # Only need uv_unique_count and uv_face_mapping file.write('</float_array>\n') file.write('\t\t\t<texcoords id="%s" source="#%s" />\n' % (texname, texarrayname)) # NORMAL, Smooth/Non smoothed. if len(faces) > 0: file.write('\t\t\t<float_array id="%s">' % normarrayname) for f in faces: if f.smooth: for v in f: noKey = veckey3d(v.no) if not globalNormals.has_key( noKey ): globalNormals[noKey] = totno totno +=1 file.write(' %.6f %.6f %.6f' % noKey) else: # Hard, 1 normal from the face. noKey = veckey3d(f.no) if not globalNormals.has_key( noKey ): globalNormals[noKey] = totno totno +=1 file.write(' %.6f %.6f %.6f' % noKey) file.write('</float_array>\n') file.write('\t\t\t<normals id="%s" source="#%s" />\n' % (normname, normarrayname)) if not faceuv: f_image = None in_triangles = False for f_index, f in enumerate(faces): f_v= f.v f_smooth= f.smooth f_mat = min(f.mat, len(materialNames)-1) if faceuv: f_image = f.image f_uv= f.uv # MAKE KEY if faceuv and f_image: # Object is always true. key = materialNames[f_mat], f_image.name else: key = materialNames[f_mat], None # No image, use None instead. # CHECK FOR CONTEXT SWITCH if key == contextMat: pass # Context alredy switched, dont do anythoing else: if key[0] == None and key[1] == None: # Write a null material, since we know the context has changed. if in_triangles: file.write('</p>\n') file.write('\t\t\t</triangles>\n') file.write('\t\t\t<triangles id="%s_%s">\n' % (fixName(ob.name), fixName(ob.getData(1)))) in_triangles = True else: mat_data= MTL_DICT.get(key) if not mat_data: # First add to global dict so we can export to mtl # Then write mtl # Make a new names from the mat and image name, # converting any spaces to underscores with fixName. # If none image dont bother adding it to the name if key[1] == None: mat_data = MTL_DICT[key] = ('%s'%fixName(key[0])), materialItems[f_mat], f_image else: mat_data = MTL_DICT[key] = ('%s_%s' % (fixName(key[0]), fixName(key[1]))), materialItems[f_mat], f_image if in_triangles: file.write('</p>\n') file.write('\t\t\t</triangles>\n') file.write('\t\t\t<triangles id="%s_%s_%s" material="#%s">\n' % (fixName(ob.name), fixName(ob.getData(1)), mat_data[0], mat_data[0]) ) in_triangles = True file.write('\t\t\t\t<input offset="0" semantic="VERTEX" source="#%s" />\n' % vertname) file.write('\t\t\t\t<input offset="1" semantic="NORMAL" source="#%s" />\n' % normname) if faceuv: file.write('\t\t\t\t<input offset="2" semantic="TEXCOORD" source="#%s" />\n' % texname) file.write('\t\t\t\t<p>') contextMat = key if f_smooth != contextSmooth: if f_smooth: # on now off # file.write('s 1\n') contextSmooth = f_smooth else: # was off now on # file.write('s off\n') contextSmooth = f_smooth if faceuv: if f_smooth: # Smoothed, use vertex normals for vi, v in enumerate(f_v): file.write( ' %d %d %d' % (\ v.index+totverts,\ totuvco + uv_face_mapping[f_index][vi],\ globalNormals[ veckey3d(v.no) ])) # vert, uv, normal else: # No smoothing, face normals no = globalNormals[ veckey3d(f.no) ] for vi, v in enumerate(f_v): file.write( ' %d %d %d' % (\ v.index+totverts,\ totuvco + uv_face_mapping[f_index][vi],\ no)) # vert, uv, normal face_vert_index += len(f_v) else: # No UV's if f_smooth: # Smoothed, use vertex normals for v in f_v: file.write( ' %d %d' % (\ v.index+totverts,\ globalNormals[ veckey3d(v.no) ])) else: # No smoothing, face normals no = globalNormals[ veckey3d(f.no) ] for v in f_v: file.write( ' %d %d' % (\ v.index+totverts,\ no)) if in_triangles: file.write('</p>\n') file.write('\t\t\t</triangles>\n') # Write edges. LOOSE = Mesh.EdgeFlags.LOOSE has_edge = False for ed in edges: if ed.flag & LOOSE: has_edge = True if has_edge: file.write('\t\t\t<edges>\n') file.write('\t\t\t\t<input offset="0" semantic="VERTEX" source="#%s" />\n' % vertname) file.write('\t\t\t\t<p>') for ed in edges: if ed.flag & LOOSE: file.write(' %d %d' % (ed.v1.index+totverts, ed.v2.index+totverts)) file.write('</p>\n') file.write('\t\t\t</edges>\n') # Make the indicies global rather then per mesh # totverts += len(me.verts) # if faceuv: # totuvco += uv_unique_count me.verts= None if len(faces) > 0: file.write('\t\t</mesh>\n') else: file.write('\t\t</curve>\n') file.write('\t</object>\n') file.write('</library_objects>\n\n') # Now we have all our materials, save them if EXPORT_MTL: write_library_materials(file) # Save the groups write_library_groups(file) file.write('</OPEN_TRACK>\n') file.close() if EXPORT_COPY_IMAGES: dest_dir = filename # Remove chars until we are just the path. while dest_dir and dest_dir[-1] not in '\\/': dest_dir = dest_dir[:-1] if dest_dir: copy_images(dest_dir) else: print '\tError: "%s" could not be used as a base for an image path.' % filename print "WTF Export time: %.2f" % (sys.time() - time1)
def write(filename, objects,\ EXPORT_TRI=False, EXPORT_EDGES=False, EXPORT_NORMALS=False, EXPORT_NORMALS_HQ=False,\ EXPORT_UV=True, EXPORT_MTL=True, EXPORT_COPY_IMAGES=False,\ EXPORT_APPLY_MODIFIERS=True, EXPORT_ROTX90=True, EXPORT_BLEN_OBS=True,\ EXPORT_GROUP_BY_OB=False, EXPORT_GROUP_BY_MAT=False, EXPORT_MORPH_TARGET=False, EXPORT_ARMATURE=False): ''' Basic write function. The context and options must be alredy set This can be accessed externaly eg. write( 'c:\\test\\foobar.obj', Blender.Object.GetSelected() ) # Using default options. ''' def veckey3d(v): return round(v.x, 6), round(v.y, 6), round(v.z, 6) def veckey2d(v): return round(v.x, 6), round(v.y, 6) print 'OBJ Export path: "%s"' % filename temp_mesh_name = '~tmp-mesh' time1 = sys.time() scn = Scene.GetCurrent() file = open(filename, "w") # Write Header file.write('# Blender3D v%s OBJ File: %s\n' % (Blender.Get('version'), Blender.Get('filename').split('/')[-1].split('\\')[-1] )) file.write('# www.blender3d.org\n') # Tell the obj file what material file to use. if EXPORT_MTL: mtlfilename = '%s.mtl' % '.'.join(filename.split('.')[:-1]) file.write('mtllib %s\n' % ( mtlfilename.split('\\')[-1].split('/')[-1] )) # Get the container mesh. - used for applying modifiers and non mesh objects. containerMesh = meshName = tempMesh = None for meshName in Blender.NMesh.GetNames(): if meshName.startswith(temp_mesh_name): tempMesh = Mesh.Get(meshName) if not tempMesh.users: containerMesh = tempMesh if not containerMesh: containerMesh = Mesh.New(temp_mesh_name) if EXPORT_ROTX90: mat_xrot90= Blender.Mathutils.RotationMatrix(-90, 4, 'x') del meshName del tempMesh # Initialize totals, these are updated each object totverts = totuvco = totno = 1 face_vert_index = 1 globalNormals = {} # Get all meshs for ob_main in objects: for ob, ob_mat in BPyObject.getDerivedObjects(ob_main): # Will work for non meshes now! :) # getMeshFromObject(ob, container_mesh=None, apply_modifiers=True, vgroups=True, scn=None) if EXPORT_ARMATURE: write_armature(file,ob) write_poses(file,ob) me= BPyMesh.getMeshFromObject(ob, containerMesh, EXPORT_APPLY_MODIFIERS, False, scn) if not me: continue if EXPORT_UV: faceuv= me.faceUV else: faceuv = False # We have a valid mesh if EXPORT_TRI and me.faces: # Add a dummy object to it. has_quads = False for f in me.faces: if len(f) == 4: has_quads = True break if has_quads: oldmode = Mesh.Mode() Mesh.Mode(Mesh.SelectModes['FACE']) me.sel = True tempob = scn.objects.new(me) me.quadToTriangle(0) # more=0 shortest length oldmode = Mesh.Mode(oldmode) scn.objects.unlink(tempob) Mesh.Mode(oldmode) faces = [ f for f in me.faces ] if EXPORT_EDGES: edges = me.edges else: edges = [] if not (len(faces)+len(edges)+len(me.verts)): # Make sure there is somthing to write continue # dont bother with this mesh. if EXPORT_ROTX90: me.transform(ob_mat*mat_xrot90) else: me.transform(ob_mat) # High Quality Normals if EXPORT_NORMALS and faces: if EXPORT_NORMALS_HQ: BPyMesh.meshCalcNormals(me) else: # transforming normals is incorrect # when the matrix is scaled, # better to recalculate them me.calcNormals() # # Crash Blender #materials = me.getMaterials(1) # 1 == will return None in the list. materials = me.materials materialNames = [] materialItems = materials[:] if materials: for mat in materials: if mat: # !=None materialNames.append(mat.name) else: materialNames.append(None) # Cant use LC because some materials are None. # materialNames = map(lambda mat: mat.name, materials) # Bug Blender, dosent account for null materials, still broken. # Possible there null materials, will mess up indicies # but at least it will export, wait until Blender gets fixed. materialNames.extend((16-len(materialNames)) * [None]) materialItems.extend((16-len(materialItems)) * [None]) # Sort by Material, then images # so we dont over context switch in the obj file. if EXPORT_MORPH_TARGET: pass elif faceuv: try: faces.sort(key = lambda a: (a.mat, a.image, a.smooth)) except: faces.sort(lambda a,b: cmp((a.mat, a.image, a.smooth), (b.mat, b.image, b.smooth))) elif len(materials) > 1: try: faces.sort(key = lambda a: (a.mat, a.smooth)) except: faces.sort(lambda a,b: cmp((a.mat, a.smooth), (b.mat, b.smooth))) else: # no materials try: faces.sort(key = lambda a: a.smooth) except: faces.sort(lambda a,b: cmp(a.smooth, b.smooth)) # Set the default mat to no material and no image. contextMat = (0, 0) # Can never be this, so we will label a new material teh first chance we get. contextSmooth = None # Will either be true or false, set bad to force initialization switch. if EXPORT_BLEN_OBS or EXPORT_GROUP_BY_OB: name1 = ob.name name2 = ob.getData(1) if name1 == name2: obnamestring = fixName(name1) else: obnamestring = '%s_%s' % (fixName(name1), fixName(name2)) if EXPORT_BLEN_OBS: file.write('o %s\n' % obnamestring) # Write Object name else: # if EXPORT_GROUP_BY_OB: file.write('g %s\n' % obnamestring) # Vert mesh = ob.getData() objmat = ob.getMatrix() for i in objmat: file.write('obm: %.6f %.6f %.6f %.6f\n' % tuple(i)) vgrouplist = mesh.getVertGroupNames() file.write('vgroupcount: %i\n' % len(vgrouplist)) for vgname in vgrouplist: file.write('vgroup: %s\n' % vgname) for v in mesh.verts: file.write('v %.6f %.6f %.6f\n' % tuple(v.co)) influences = mesh.getVertexInfluences(v.index) file.write('influence: %i\n' % len(influences)) for name,weight in influences: file.write('GroupName: %s\n' % name) file.write('Weight: %f\n' % weight) # UV if faceuv: uv_face_mapping = [[0,0,0,0] for f in faces] # a bit of a waste for tri's :/ uv_dict = {} # could use a set() here for f_index, f in enumerate(faces): for uv_index, uv in enumerate(f.uv): uvkey = veckey2d(uv) try: uv_face_mapping[f_index][uv_index] = uv_dict[uvkey] except: uv_face_mapping[f_index][uv_index] = uv_dict[uvkey] = len(uv_dict) file.write('vt %.6f %.6f\n' % tuple(uv)) uv_unique_count = len(uv_dict) del uv, uvkey, uv_dict, f_index, uv_index # Only need uv_unique_count and uv_face_mapping # NORMAL, Smooth/Non smoothed. if EXPORT_NORMALS: for f in faces: if f.smooth: for v in f: noKey = veckey3d(v.no) if not globalNormals.has_key( noKey ): globalNormals[noKey] = totno totno +=1 file.write('vn %.6f %.6f %.6f\n' % noKey) else: # Hard, 1 normal from the face. noKey = veckey3d(f.no) if not globalNormals.has_key( noKey ): globalNormals[noKey] = totno totno +=1 file.write('vn %.6f %.6f %.6f\n' % noKey) if not faceuv: f_image = None for f_index, f in enumerate(faces): f_v= f.v f_smooth= f.smooth f_mat = min(f.mat, len(materialNames)-1) if faceuv: f_image = f.image f_uv= f.uv # MAKE KEY if faceuv and f_image: # Object is always true. key = materialNames[f_mat], f_image.name else: key = materialNames[f_mat], None # No image, use None instead. # CHECK FOR CONTEXT SWITCH if key == contextMat: pass # Context alredy switched, dont do anythoing else: if key[0] == None and key[1] == None: # Write a null material, since we know the context has changed. if EXPORT_GROUP_BY_MAT: file.write('g %s_%s\n' % (fixName(ob.name), fixName(ob.getData(1))) ) # can be mat_image or (null) file.write('usemtl (null)\n') # mat, image else: mat_data= MTL_DICT.get(key) if not mat_data: # First add to global dict so we can export to mtl # Then write mtl # Make a new names from the mat and image name, # converting any spaces to underscores with fixName. # If none image dont bother adding it to the name if key[1] == None: mat_data = MTL_DICT[key] = ('%s'%fixName(key[0])), materialItems[f_mat], f_image else: mat_data = MTL_DICT[key] = ('%s_%s' % (fixName(key[0]), fixName(key[1]))), materialItems[f_mat], f_image if EXPORT_GROUP_BY_MAT: file.write('g %s_%s_%s\n' % (fixName(ob.name), fixName(ob.getData(1)), mat_data[0]) ) # can be mat_image or (null) file.write('usemtl %s\n' % mat_data[0]) # can be mat_image or (null) contextMat = key if f_smooth != contextSmooth: if f_smooth: # on now off file.write('s 1\n') contextSmooth = f_smooth else: # was off now on file.write('s off\n') contextSmooth = f_smooth file.write('f') if faceuv: if EXPORT_NORMALS: if f_smooth: # Smoothed, use vertex normals for vi, v in enumerate(f_v): file.write( ' %d/%d/%d' % (\ v.index+totverts,\ totuvco + uv_face_mapping[f_index][vi],\ globalNormals[ veckey3d(v.no) ])) # vert, uv, normal else: # No smoothing, face normals no = globalNormals[ veckey3d(f.no) ] for vi, v in enumerate(f_v): file.write( ' %d/%d/%d' % (\ v.index+totverts,\ totuvco + uv_face_mapping[f_index][vi],\ no)) # vert, uv, normal else: # No Normals for vi, v in enumerate(f_v): file.write( ' %d/%d' % (\ v.index+totverts,\ totuvco + uv_face_mapping[f_index][vi])) # vert, uv face_vert_index += len(f_v) else: # No UV's if EXPORT_NORMALS: if f_smooth: # Smoothed, use vertex normals for v in f_v: file.write( ' %d//%d' % (\ v.index+totverts,\ globalNormals[ veckey3d(v.no) ])) else: # No smoothing, face normals no = globalNormals[ veckey3d(f.no) ] for v in f_v: file.write( ' %d//%d' % (\ v.index+totverts,\ no)) else: # No Normals for v in f_v: file.write( ' %d' % (\ v.index+totverts)) file.write('\n') # Write edges. if EXPORT_EDGES: LOOSE= Mesh.EdgeFlags.LOOSE for ed in edges: if ed.flag & LOOSE: file.write('f %d %d\n' % (ed.v1.index+totverts, ed.v2.index+totverts)) # Make the indicies global rather then per mesh totverts += len(me.verts) if faceuv: totuvco += uv_unique_count me.verts= None file.close() # Now we have all our materials, save them if EXPORT_MTL: write_mtl(mtlfilename) if EXPORT_COPY_IMAGES: dest_dir = filename # Remove chars until we are just the path. while dest_dir and dest_dir[-1] not in '\\/': dest_dir = dest_dir[:-1] if dest_dir: copy_images(dest_dir) else: print '\tError: "%s" could not be used as a base for an image path.' % filename print "OBJ Export time: %.2f" % (sys.time() - time1)
def write(filename, objects,\ EXPORT_TRI=False, EXPORT_EDGES=False, EXPORT_NORMALS=False, EXPORT_NORMALS_HQ=False,\ EXPORT_UV=True, EXPORT_MTL=True, EXPORT_COPY_IMAGES=False,\ EXPORT_APPLY_MODIFIERS=True, EXPORT_ROTX90=True, EXPORT_BLEN_OBS=True,\ EXPORT_GROUP_BY_OB=False, EXPORT_GROUP_BY_MAT=False, EXPORT_KEEP_VERT_ORDER=False,\ EXPORT_POLYGROUPS=False, EXPORT_CURVE_AS_NURBS=True): ''' Basic write function. The context and options must be alredy set This can be accessed externaly eg. write( 'c:\\test\\foobar.obj', Blender.Object.GetSelected() ) # Using default options. ''' def veckey3d(v): return round(v.x, 6), round(v.y, 6), round(v.z, 6) def veckey2d(v): return round(v.x, 6), round(v.y, 6) def findVertexGroupName(face, vWeightMap): """ Searches the vertexDict to see what groups is assigned to a given face. We use a frequency system in order to sort out the name because a given vetex can belong to two or more groups at the same time. To find the right name for the face we list all the possible vertex group names with their frequency and then sort by frequency in descend order. The top element is the one shared by the highest number of vertices is the face's group """ weightDict = {} for vert in face: vWeights = vWeightMap[vert.index] for vGroupName, weight in vWeights: weightDict[vGroupName] = weightDict.get(vGroupName, 0) + weight if weightDict: alist = [(weight,vGroupName) for vGroupName, weight in weightDict.iteritems()] # sort least to greatest amount of weight alist.sort() return(alist[-1][1]) # highest value last else: return '(null)' print 'OBJ Export path: "%s"' % filename temp_mesh_name = '~tmp-mesh' time1 = sys.time() scn = Scene.GetCurrent() file = open(filename, "w") # Write Header file.write('# Blender3D v%s OBJ File: %s\n' % (Blender.Get('version'), Blender.Get('filename').split('/')[-1].split('\\')[-1] )) file.write('# www.blender3d.org\n') # Tell the obj file what material file to use. if EXPORT_MTL: mtlfilename = '%s.mtl' % '.'.join(filename.split('.')[:-1]) file.write('mtllib %s\n' % ( mtlfilename.split('\\')[-1].split('/')[-1] )) # Get the container mesh. - used for applying modifiers and non mesh objects. containerMesh = meshName = tempMesh = None for meshName in Blender.NMesh.GetNames(): if meshName.startswith(temp_mesh_name): tempMesh = Mesh.Get(meshName) if not tempMesh.users: containerMesh = tempMesh if not containerMesh: containerMesh = Mesh.New(temp_mesh_name) if EXPORT_ROTX90: mat_xrot90= Blender.Mathutils.RotationMatrix(-90, 4, 'x') del meshName del tempMesh # Initialize totals, these are updated each object totverts = totuvco = totno = 1 face_vert_index = 1 globalNormals = {} # Get all meshes for ob_main in objects: for ob, ob_mat in BPyObject.getDerivedObjects(ob_main): # Nurbs curve support if EXPORT_CURVE_AS_NURBS and test_nurbs_compat(ob): if EXPORT_ROTX90: ob_mat = ob_mat * mat_xrot90 totverts += write_nurb(file, ob, ob_mat) continue # end nurbs # Will work for non meshes now! :) # getMeshFromObject(ob, container_mesh=None, apply_modifiers=True, vgroups=True, scn=None) me= BPyMesh.getMeshFromObject(ob, containerMesh, EXPORT_APPLY_MODIFIERS, EXPORT_POLYGROUPS, scn) if not me: continue if EXPORT_UV: faceuv= me.faceUV else: faceuv = False # We have a valid mesh if EXPORT_TRI and me.faces: # Add a dummy object to it. has_quads = False for f in me.faces: if len(f) == 4: has_quads = True break if has_quads: oldmode = Mesh.Mode() Mesh.Mode(Mesh.SelectModes['FACE']) me.sel = True tempob = scn.objects.new(me) me.quadToTriangle(0) # more=0 shortest length oldmode = Mesh.Mode(oldmode) scn.objects.unlink(tempob) Mesh.Mode(oldmode) # Make our own list so it can be sorted to reduce context switching faces = [ f for f in me.faces ] if EXPORT_EDGES: edges = me.edges else: edges = [] if not (len(faces)+len(edges)+len(me.verts)): # Make sure there is somthing to write continue # dont bother with this mesh. if EXPORT_ROTX90: me.transform(ob_mat*mat_xrot90) else: me.transform(ob_mat) # High Quality Normals if EXPORT_NORMALS and faces: if EXPORT_NORMALS_HQ: BPyMesh.meshCalcNormals(me) else: # transforming normals is incorrect # when the matrix is scaled, # better to recalculate them me.calcNormals() # # Crash Blender #materials = me.getMaterials(1) # 1 == will return None in the list. materials = me.materials materialNames = [] materialItems = materials[:] if materials: for mat in materials: if mat: # !=None materialNames.append(mat.name) else: materialNames.append(None) # Cant use LC because some materials are None. # materialNames = map(lambda mat: mat.name, materials) # Bug Blender, dosent account for null materials, still broken. # Possible there null materials, will mess up indicies # but at least it will export, wait until Blender gets fixed. materialNames.extend((16-len(materialNames)) * [None]) materialItems.extend((16-len(materialItems)) * [None]) # Sort by Material, then images # so we dont over context switch in the obj file. if EXPORT_KEEP_VERT_ORDER: pass elif faceuv: try: faces.sort(key = lambda a: (a.mat, a.image, a.smooth)) except: faces.sort(lambda a,b: cmp((a.mat, a.image, a.smooth), (b.mat, b.image, b.smooth))) elif len(materials) > 1: try: faces.sort(key = lambda a: (a.mat, a.smooth)) except: faces.sort(lambda a,b: cmp((a.mat, a.smooth), (b.mat, b.smooth))) else: # no materials try: faces.sort(key = lambda a: a.smooth) except: faces.sort(lambda a,b: cmp(a.smooth, b.smooth)) # Set the default mat to no material and no image. contextMat = (0, 0) # Can never be this, so we will label a new material teh first chance we get. contextSmooth = None # Will either be true or false, set bad to force initialization switch. if EXPORT_BLEN_OBS or EXPORT_GROUP_BY_OB: name1 = ob.name name2 = ob.getData(1) if name1 == name2: obnamestring = fixName(name1) else: obnamestring = '%s_%s' % (fixName(name1), fixName(name2)) if EXPORT_BLEN_OBS: file.write('o %s\n' % obnamestring) # Write Object name else: # if EXPORT_GROUP_BY_OB: file.write('g %s\n' % obnamestring) # Vert for v in me.verts: file.write('v %.6f %.6f %.6f\n' % tuple(v.co)) # UV if faceuv: uv_face_mapping = [[0,0,0,0] for f in faces] # a bit of a waste for tri's :/ uv_dict = {} # could use a set() here for f_index, f in enumerate(faces): for uv_index, uv in enumerate(f.uv): uvkey = veckey2d(uv) try: uv_face_mapping[f_index][uv_index] = uv_dict[uvkey] except: uv_face_mapping[f_index][uv_index] = uv_dict[uvkey] = len(uv_dict) file.write('vt %.6f %.6f\n' % tuple(uv)) uv_unique_count = len(uv_dict) del uv, uvkey, uv_dict, f_index, uv_index # Only need uv_unique_count and uv_face_mapping # NORMAL, Smooth/Non smoothed. if EXPORT_NORMALS: for f in faces: if f.smooth: for v in f: noKey = veckey3d(v.no) if not globalNormals.has_key( noKey ): globalNormals[noKey] = totno totno +=1 file.write('vn %.6f %.6f %.6f\n' % noKey) else: # Hard, 1 normal from the face. noKey = veckey3d(f.no) if not globalNormals.has_key( noKey ): globalNormals[noKey] = totno totno +=1 file.write('vn %.6f %.6f %.6f\n' % noKey) if not faceuv: f_image = None if EXPORT_POLYGROUPS: # Retrieve the list of vertex groups vertGroupNames = me.getVertGroupNames() currentVGroup = '' # Create a dictionary keyed by face id and listing, for each vertex, the vertex groups it belongs to vgroupsMap = [[] for _i in xrange(len(me.verts))] for vertexGroupName in vertGroupNames: for vIdx, vWeight in me.getVertsFromGroup(vertexGroupName, 1): vgroupsMap[vIdx].append((vertexGroupName, vWeight)) for f_index, f in enumerate(faces): f_v= f.v f_smooth= f.smooth f_mat = min(f.mat, len(materialNames)-1) if faceuv: f_image = f.image f_uv= f.uv # MAKE KEY if faceuv and f_image: # Object is always true. key = materialNames[f_mat], f_image.name else: key = materialNames[f_mat], None # No image, use None instead. # Write the vertex group if EXPORT_POLYGROUPS: if vertGroupNames: # find what vertext group the face belongs to theVGroup = findVertexGroupName(f,vgroupsMap) if theVGroup != currentVGroup: currentVGroup = theVGroup file.write('g %s\n' % theVGroup) # CHECK FOR CONTEXT SWITCH if key == contextMat: pass # Context alredy switched, dont do anything else: if key[0] == None and key[1] == None: # Write a null material, since we know the context has changed. if EXPORT_GROUP_BY_MAT: file.write('g %s_%s\n' % (fixName(ob.name), fixName(ob.getData(1))) ) # can be mat_image or (null) file.write('usemtl (null)\n') # mat, image else: mat_data= MTL_DICT.get(key) if not mat_data: # First add to global dict so we can export to mtl # Then write mtl # Make a new names from the mat and image name, # converting any spaces to underscores with fixName. # If none image dont bother adding it to the name if key[1] == None: mat_data = MTL_DICT[key] = ('%s'%fixName(key[0])), materialItems[f_mat], f_image else: mat_data = MTL_DICT[key] = ('%s_%s' % (fixName(key[0]), fixName(key[1]))), materialItems[f_mat], f_image if EXPORT_GROUP_BY_MAT: file.write('g %s_%s_%s\n' % (fixName(ob.name), fixName(ob.getData(1)), mat_data[0]) ) # can be mat_image or (null) file.write('usemtl %s\n' % mat_data[0]) # can be mat_image or (null) contextMat = key if f_smooth != contextSmooth: if f_smooth: # on now off file.write('s 1\n') contextSmooth = f_smooth else: # was off now on file.write('s off\n') contextSmooth = f_smooth file.write('f') if faceuv: if EXPORT_NORMALS: if f_smooth: # Smoothed, use vertex normals for vi, v in enumerate(f_v): file.write( ' %d/%d/%d' % (\ v.index+totverts,\ totuvco + uv_face_mapping[f_index][vi],\ globalNormals[ veckey3d(v.no) ])) # vert, uv, normal else: # No smoothing, face normals no = globalNormals[ veckey3d(f.no) ] for vi, v in enumerate(f_v): file.write( ' %d/%d/%d' % (\ v.index+totverts,\ totuvco + uv_face_mapping[f_index][vi],\ no)) # vert, uv, normal else: # No Normals for vi, v in enumerate(f_v): file.write( ' %d/%d' % (\ v.index+totverts,\ totuvco + uv_face_mapping[f_index][vi])) # vert, uv face_vert_index += len(f_v) else: # No UV's if EXPORT_NORMALS: if f_smooth: # Smoothed, use vertex normals for v in f_v: file.write( ' %d//%d' % (\ v.index+totverts,\ globalNormals[ veckey3d(v.no) ])) else: # No smoothing, face normals no = globalNormals[ veckey3d(f.no) ] for v in f_v: file.write( ' %d//%d' % (\ v.index+totverts,\ no)) else: # No Normals for v in f_v: file.write( ' %d' % (\ v.index+totverts)) file.write('\n') # Write edges. if EXPORT_EDGES: LOOSE= Mesh.EdgeFlags.LOOSE for ed in edges: if ed.flag & LOOSE: file.write('f %d %d\n' % (ed.v1.index+totverts, ed.v2.index+totverts)) # Make the indicies global rather then per mesh totverts += len(me.verts) if faceuv: totuvco += uv_unique_count me.verts= None file.close() # Now we have all our materials, save them if EXPORT_MTL: write_mtl(mtlfilename) if EXPORT_COPY_IMAGES: dest_dir = filename # Remove chars until we are just the path. while dest_dir and dest_dir[-1] not in '\\/': dest_dir = dest_dir[:-1] if dest_dir: copy_images(dest_dir) else: print '\tError: "%s" could not be used as a base for an image path.' % filename print "OBJ Export time: %.2f" % (sys.time() - time1)
def file_callback(filename): if not filename.lower().endswith(".ctm"): filename += ".ctm" # Get object mesh from the selected object scn = bpy.data.scenes.active ob = scn.objects.active if not ob: Blender.Draw.PupMenu("Error%t|Select 1 active object") return mesh = BPyMesh.getMeshFromObject(ob, None, False, False, scn) if not mesh: Blender.Draw.PupMenu("Error%t|Could not get mesh data from active object") return # Check which mesh properties are present... hasVertexUV = mesh.vertexUV or mesh.faceUV hasVertexColors = mesh.vertexColors # Show a GUI for the export settings pupBlock = [] EXPORT_APPLY_MODIFIERS = Draw.Create(1) pupBlock.append(("Apply Modifiers", EXPORT_APPLY_MODIFIERS, "Use transformed mesh data.")) EXPORT_NORMALS = Draw.Create(1) pupBlock.append(("Normals", EXPORT_NORMALS, "Export vertex normal data.")) if hasVertexUV: EXPORT_UV = Draw.Create(1) pupBlock.append(("UVs", EXPORT_UV, "Export texface UV coords.")) if hasVertexColors: EXPORT_COLORS = Draw.Create(1) pupBlock.append(("Colors", EXPORT_COLORS, "Export vertex Colors.")) EXPORT_MG2 = Draw.Create(0) pupBlock.append(("Fixed Point", EXPORT_MG2, "Use limited precision algorithm (MG2 method = better compression).")) if not Draw.PupBlock("Export...", pupBlock): return # Adjust export settings according to GUI selections EXPORT_APPLY_MODIFIERS = EXPORT_APPLY_MODIFIERS.val EXPORT_NORMALS = EXPORT_NORMALS.val if hasVertexUV: EXPORT_UV = EXPORT_UV.val else: EXPORT_UV = False if hasVertexColors: EXPORT_COLORS = EXPORT_COLORS.val else: EXPORT_COLORS = False EXPORT_MG2 = EXPORT_MG2.val # If the user wants to export MG2, then show another GUI... if EXPORT_MG2: pupBlock = [] EXPORT_VPREC = Draw.Create(0.01) pupBlock.append(("Vertex", EXPORT_VPREC, 0.0001, 1.0, "Relative vertex precision (fixed point).")) if EXPORT_NORMALS: EXPORT_NPREC = Draw.Create(1.0 / 256.0) pupBlock.append(("Normal", EXPORT_NPREC, 0.0001, 1.0, "Normal precision (fixed point).")) if EXPORT_UV: EXPORT_UVPREC = Draw.Create(1.0 / 1024.0) pupBlock.append(("UV", EXPORT_UVPREC, 0.0001, 1.0, "UV precision (fixed point).")) if EXPORT_COLORS: EXPORT_CPREC = Draw.Create(1.0 / 256.0) pupBlock.append(("Color", EXPORT_CPREC, 0.0001, 1.0, "Color precision (fixed point).")) if not Draw.PupBlock("Fixed point precision...", pupBlock): return # Adjust export settings according to GUI selections if EXPORT_MG2: EXPORT_VPREC = EXPORT_VPREC.val else: EXPORT_VPREC = 0.1 if EXPORT_MG2 and EXPORT_NORMALS: EXPORT_NPREC = EXPORT_NPREC.val else: EXPORT_NPREC = 0.1 if EXPORT_MG2 and EXPORT_UV: EXPORT_UVPREC = EXPORT_UVPREC.val else: EXPORT_UVPREC = 0.1 if EXPORT_MG2 and EXPORT_COLORS: EXPORT_CPREC = EXPORT_CPREC.val else: EXPORT_CPREC = 0.1 is_editmode = Blender.Window.EditMode() if is_editmode: Blender.Window.EditMode(0, "", 0) Window.WaitCursor(1) try: # Get the mesh, again, if we wanted modifiers (from GUI selection) if EXPORT_APPLY_MODIFIERS: mesh = BPyMesh.getMeshFromObject(ob, None, EXPORT_APPLY_MODIFIERS, False, scn) if not mesh: Blender.Draw.PupMenu("Error%t|Could not get mesh data from active object") return mesh.transform(ob.matrixWorld, True) # Count triangles (quads count as two triangles) triangleCount = 0 for f in mesh.faces: if len(f.v) == 4: triangleCount += 2 else: triangleCount += 1 # Extract indices from the Blender mesh (quads are split into two triangles) pindices = cast((c_int * 3 * triangleCount)(), POINTER(c_int)) i = 0 for f in mesh.faces: pindices[i] = c_int(f.v[0].index) pindices[i + 1] = c_int(f.v[1].index) pindices[i + 2] = c_int(f.v[2].index) i += 3 if len(f.v) == 4: pindices[i] = c_int(f.v[0].index) pindices[i + 1] = c_int(f.v[2].index) pindices[i + 2] = c_int(f.v[3].index) i += 3 # Extract vertex array from the Blender mesh vertexCount = len(mesh.verts) pvertices = cast((c_float * 3 * vertexCount)(), POINTER(c_float)) i = 0 for v in mesh.verts: pvertices[i] = c_float(v.co.x) pvertices[i + 1] = c_float(v.co.y) pvertices[i + 2] = c_float(v.co.z) i += 3 # Extract normals if EXPORT_NORMALS: pnormals = cast((c_float * 3 * vertexCount)(), POINTER(c_float)) i = 0 for v in mesh.verts: pnormals[i] = c_float(v.no.x) pnormals[i + 1] = c_float(v.no.y) pnormals[i + 2] = c_float(v.no.z) i += 3 else: pnormals = POINTER(c_float)() # Extract UVs if EXPORT_UV: ptexCoords = cast((c_float * 2 * vertexCount)(), POINTER(c_float)) if mesh.faceUV: for f in mesh.faces: for j, v in enumerate(f.v): k = v.index if k < vertexCount: uv = f.uv[j] ptexCoords[k * 2] = uv[0] ptexCoords[k * 2 + 1] = uv[1] else: i = 0 for v in mesh.verts: ptexCoords[i] = c_float(v.uvco[0]) ptexCoords[i + 1] = c_float(v.uvco[1]) i += 2 else: ptexCoords = POINTER(c_float)() # Extract colors if EXPORT_COLORS: pcolors = cast((c_float * 4 * vertexCount)(), POINTER(c_float)) for f in mesh.faces: for j, v in enumerate(f.v): k = v.index if k < vertexCount: col = f.col[j] pcolors[k * 4] = col.r / 255.0 pcolors[k * 4 + 1] = col.g / 255.0 pcolors[k * 4 + 2] = col.b / 255.0 pcolors[k * 4 + 3] = 1.0 else: pcolors = POINTER(c_float)() # Load the OpenCTM shared library if os.name == "nt": libHDL = WinDLL("openctm.dll") else: libName = find_library("openctm") if not libName: Blender.Draw.PupMenu("Could not find the OpenCTM shared library") return libHDL = CDLL(libName) if not libHDL: Blender.Draw.PupMenu("Could not open the OpenCTM shared library") return # Get all the functions from the shared library that we need ctmNewContext = libHDL.ctmNewContext ctmNewContext.argtypes = [c_int] ctmNewContext.restype = c_void_p ctmFreeContext = libHDL.ctmFreeContext ctmFreeContext.argtypes = [c_void_p] ctmGetError = libHDL.ctmGetError ctmGetError.argtypes = [c_void_p] ctmGetError.restype = c_int ctmErrorString = libHDL.ctmErrorString ctmErrorString.argtypes = [c_int] ctmErrorString.restype = c_char_p ctmFileComment = libHDL.ctmFileComment ctmFileComment.argtypes = [c_void_p, c_char_p] ctmDefineMesh = libHDL.ctmDefineMesh ctmDefineMesh.argtypes = [c_void_p, POINTER(c_float), c_int, POINTER(c_int), c_int, POINTER(c_float)] ctmSave = libHDL.ctmSave ctmSave.argtypes = [c_void_p, c_char_p] ctmAddUVMap = libHDL.ctmAddUVMap ctmAddUVMap.argtypes = [c_void_p, POINTER(c_float), c_char_p, c_char_p] ctmAddUVMap.restype = c_int ctmAddAttribMap = libHDL.ctmAddAttribMap ctmAddAttribMap.argtypes = [c_void_p, POINTER(c_float), c_char_p] ctmAddAttribMap.restype = c_int ctmCompressionMethod = libHDL.ctmCompressionMethod ctmCompressionMethod.argtypes = [c_void_p, c_int] ctmVertexPrecisionRel = libHDL.ctmVertexPrecisionRel ctmVertexPrecisionRel.argtypes = [c_void_p, c_float] ctmNormalPrecision = libHDL.ctmNormalPrecision ctmNormalPrecision.argtypes = [c_void_p, c_float] ctmUVCoordPrecision = libHDL.ctmUVCoordPrecision ctmUVCoordPrecision.argtypes = [c_void_p, c_int, c_float] ctmAttribPrecision = libHDL.ctmAttribPrecision ctmAttribPrecision.argtypes = [c_void_p, c_int, c_float] # Create an OpenCTM context ctm = ctmNewContext(0x0102) # CTM_EXPORT try: # Set the file comment ctmFileComment( ctm, c_char_p("%s - created by Blender %s (www.blender.org)" % (ob.getName(), Blender.Get("version"))) ) # Define the mesh ctmDefineMesh(ctm, pvertices, c_int(vertexCount), pindices, c_int(triangleCount), pnormals) # Add UV coordinates? if EXPORT_UV: tm = ctmAddUVMap(ctm, ptexCoords, c_char_p(), c_char_p()) if EXPORT_MG2: ctmUVCoordPrecision(ctm, tm, EXPORT_UVPREC) # Add colors? if EXPORT_COLORS: cm = ctmAddAttribMap(ctm, pcolors, c_char_p("Color")) if EXPORT_MG2: ctmAttribPrecision(ctm, cm, EXPORT_CPREC) # Set compression method if EXPORT_MG2: ctmCompressionMethod(ctm, 0x0203) # CTM_METHOD_MG2 ctmVertexPrecisionRel(ctm, EXPORT_VPREC) if EXPORT_NORMALS: ctmNormalPrecision(ctm, EXPORT_NPREC) else: ctmCompressionMethod(ctm, 0x0202) # CTM_METHOD_MG1 # Save the file ctmSave(ctm, c_char_p(filename)) # Check for errors e = ctmGetError(ctm) if e != 0: s = ctmErrorString(e) Blender.Draw.PupMenu("Error%t|Could not save the file: " + s) finally: # Free the OpenCTM context ctmFreeContext(ctm) finally: Window.WaitCursor(0) if is_editmode: Blender.Window.EditMode(1, "", 0)
def write(filename, objects,\ EXPORT_NORMALS_HQ=False,\ EXPORT_MTL=True, EXPORT_COPY_IMAGES=False,\ EXPORT_APPLY_MODIFIERS=True, EXPORT_BLEN_OBS=True,\ EXPORT_GROUP_BY_OB=False): ''' Basic write function. The context and options must be alredy set This can be accessed externaly eg. write( 'c:\\test\\foobar.obj', Blender.Object.GetSelected() ) # Using default options. ''' def veckey3d(v): return round(v.x, 6), round(v.y, 6), round(v.z, 6) def veckey2d(v): return round(v.x, 6), round(v.y, 6) print 'WTF Export path: "%s"' % filename temp_mesh_name = '~tmp-mesh' time1 = sys.time() scn = Scene.GetCurrent() file = open(filename, "w") file.write('<?xml version="1.0"?>\n') file.write('<OPEN_TRACK>\n') # Write Header # file.write('\n<!--\n' # + ' Blender3D v%s WTF File: %s\n' % (Blender.Get('version'), Blender.Get('filename').split('/')[-1].split('\\')[-1] ) # + ' www.blender3d.org\n' # + '-->\n\n') # Get the container mesh. - used for applying modifiers and non mesh objects. containerMesh = meshName = tempMesh = None for meshName in Blender.NMesh.GetNames(): if meshName.startswith(temp_mesh_name): tempMesh = Mesh.Get(meshName) if not tempMesh.users: containerMesh = tempMesh if not containerMesh: containerMesh = Mesh.New(temp_mesh_name) del meshName del tempMesh # Initialize totals, these are updated each object totverts = totuvco = totno = 0 face_vert_index = 0 globalNormals = {} file.write('\n<library_objects>\n') # Get all meshs for ob_main in objects: obnamestring = fixName(ob_main.name) file.write('\t<object id="%s">\n' % obnamestring) # Write Object name for ob, ob_mat in BPyObject.getDerivedObjects(ob_main): # Will work for non meshes now! :) # getMeshFromObject(ob, container_mesh=None, apply_modifiers=True, vgroups=True, scn=None) me = BPyMesh.getMeshFromObject(ob, containerMesh, EXPORT_APPLY_MODIFIERS, False, scn) if not me: file.write('\t\t<loc>%.6f %.6f %.6f</loc>\n' % tuple(ob_main.loc)) # Write Object name file.write('\t\t<rot>%.6f %.6f %.6f</rot>\n' % tuple(ob_main.rot)) # Write Object name continue faceuv = me.faceUV # We have a valid mesh if me.faces: # Add a dummy object to it. has_quads = False for f in me.faces: if len(f) == 4: has_quads = True break if has_quads: oldmode = Mesh.Mode() Mesh.Mode(Mesh.SelectModes['FACE']) me.sel = True tempob = scn.objects.new(me) me.quadToTriangle(0) # more=0 shortest length oldmode = Mesh.Mode(oldmode) scn.objects.unlink(tempob) Mesh.Mode(oldmode) # Make our own list so it can be sorted to reduce context switching faces = [f for f in me.faces] edges = me.edges if not (len(faces) + len(edges) + len(me.verts)): # Make sure there is somthing to write continue # dont bother with this mesh. me.transform(ob_mat) # High Quality Normals if faces: if EXPORT_NORMALS_HQ: BPyMesh.meshCalcNormals(me) else: # transforming normals is incorrect # when the matrix is scaled, # better to recalculate them me.calcNormals() # # Crash Blender #materials = me.getMaterials(1) # 1 == will return None in the list. materials = me.materials materialNames = [] materialItems = materials[:] if materials: for mat in materials: if mat: # !=None materialNames.append(mat.name) else: materialNames.append(None) # Cant use LC because some materials are None. # materialNames = map(lambda mat: mat.name, materials) # Bug Blender, dosent account for null materials, still broken. # Possible there null materials, will mess up indicies # but at least it will export, wait until Blender gets fixed. materialNames.extend((16 - len(materialNames)) * [None]) materialItems.extend((16 - len(materialItems)) * [None]) # Sort by Material, then images # so we dont over context switch in the obj file. if faceuv: try: faces.sort(key=lambda a: (a.mat, a.image, a.smooth)) except: faces.sort(lambda a, b: cmp((a.mat, a.image, a.smooth), (b.mat, b.image, b.smooth))) elif len(materials) > 1: try: faces.sort(key=lambda a: (a.mat, a.smooth)) except: faces.sort(lambda a, b: cmp((a.mat, a.smooth), (b.mat, b.smooth))) else: # no materials try: faces.sort(key=lambda a: a.smooth) except: faces.sort(lambda a, b: cmp(a.smooth, b.smooth)) # Set the default mat to no material and no image. contextMat = ( 0, 0 ) # Can never be this, so we will label a new material teh first chance we get. contextSmooth = None # Will either be true or false, set bad to force initialization switch. if len(faces) > 0: file.write('\t\t<mesh>\n') else: file.write('\t\t<curve>\n') vertname = "%s-Vertices" % obnamestring vertarrayname = "%s-Array" % vertname normname = "%s-Normals" % obnamestring normarrayname = "%s-Array" % normname texname = "%s-TexCoord" % obnamestring texarrayname = "%s-Array" % texname # Vert file.write('\t\t\t<float_array count="%d" id="%s">' % (len(me.verts), vertarrayname)) for v in me.verts: file.write(' %.6f %.6f %.6f' % tuple(v.co)) file.write('</float_array>\n') file.write('\t\t\t<vertices id="%s" source="#%s" />\n' % (vertname, vertarrayname)) # UV if faceuv: file.write('\t\t\t<float_array id="%s">' % texarrayname) uv_face_mapping = [[0, 0, 0, 0] for f in faces ] # a bit of a waste for tri's :/ uv_dict = {} # could use a set() here for f_index, f in enumerate(faces): for uv_index, uv in enumerate(f.uv): uvkey = veckey2d(uv) try: uv_face_mapping[f_index][uv_index] = uv_dict[uvkey] except: uv_face_mapping[f_index][uv_index] = uv_dict[ uvkey] = len(uv_dict) file.write(' %.6f %.6f' % tuple(uv)) uv_unique_count = len(uv_dict) del uv, uvkey, uv_dict, f_index, uv_index # Only need uv_unique_count and uv_face_mapping file.write('</float_array>\n') file.write('\t\t\t<texcoords id="%s" source="#%s" />\n' % (texname, texarrayname)) # NORMAL, Smooth/Non smoothed. if len(faces) > 0: file.write('\t\t\t<float_array id="%s">' % normarrayname) for f in faces: if f.smooth: for v in f: noKey = veckey3d(v.no) if not globalNormals.has_key(noKey): globalNormals[noKey] = totno totno += 1 file.write(' %.6f %.6f %.6f' % noKey) else: # Hard, 1 normal from the face. noKey = veckey3d(f.no) if not globalNormals.has_key(noKey): globalNormals[noKey] = totno totno += 1 file.write(' %.6f %.6f %.6f' % noKey) file.write('</float_array>\n') file.write('\t\t\t<normals id="%s" source="#%s" />\n' % (normname, normarrayname)) if not faceuv: f_image = None in_triangles = False for f_index, f in enumerate(faces): f_v = f.v f_smooth = f.smooth f_mat = min(f.mat, len(materialNames) - 1) if faceuv: f_image = f.image f_uv = f.uv # MAKE KEY if faceuv and f_image: # Object is always true. key = materialNames[f_mat], f_image.name else: key = materialNames[ f_mat], None # No image, use None instead. # CHECK FOR CONTEXT SWITCH if key == contextMat: pass # Context alredy switched, dont do anythoing else: if key[0] == None and key[1] == None: # Write a null material, since we know the context has changed. if in_triangles: file.write('</p>\n') file.write('\t\t\t</triangles>\n') file.write('\t\t\t<triangles id="%s_%s">\n' % (fixName(ob.name), fixName(ob.getData(1)))) in_triangles = True else: mat_data = MTL_DICT.get(key) if not mat_data: # First add to global dict so we can export to mtl # Then write mtl # Make a new names from the mat and image name, # converting any spaces to underscores with fixName. # If none image dont bother adding it to the name if key[1] == None: mat_data = MTL_DICT[key] = ('%s' % fixName( key[0])), materialItems[f_mat], f_image else: mat_data = MTL_DICT[key] = ( '%s_%s' % (fixName(key[0]), fixName(key[1])) ), materialItems[f_mat], f_image if in_triangles: file.write('</p>\n') file.write('\t\t\t</triangles>\n') file.write( '\t\t\t<triangles id="%s_%s_%s" material="#%s">\n' % (fixName(ob.name), fixName( ob.getData(1)), mat_data[0], mat_data[0])) in_triangles = True file.write( '\t\t\t\t<input offset="0" semantic="VERTEX" source="#%s" />\n' % vertname) file.write( '\t\t\t\t<input offset="1" semantic="NORMAL" source="#%s" />\n' % normname) if faceuv: file.write( '\t\t\t\t<input offset="2" semantic="TEXCOORD" source="#%s" />\n' % texname) file.write('\t\t\t\t<p>') contextMat = key if f_smooth != contextSmooth: if f_smooth: # on now off # file.write('s 1\n') contextSmooth = f_smooth else: # was off now on # file.write('s off\n') contextSmooth = f_smooth if faceuv: if f_smooth: # Smoothed, use vertex normals for vi, v in enumerate(f_v): file.write( ' %d %d %d' % (\ v.index+totverts,\ totuvco + uv_face_mapping[f_index][vi],\ globalNormals[ veckey3d(v.no) ])) # vert, uv, normal else: # No smoothing, face normals no = globalNormals[veckey3d(f.no)] for vi, v in enumerate(f_v): file.write( ' %d %d %d' % (\ v.index+totverts,\ totuvco + uv_face_mapping[f_index][vi],\ no)) # vert, uv, normal face_vert_index += len(f_v) else: # No UV's if f_smooth: # Smoothed, use vertex normals for v in f_v: file.write( ' %d %d' % (\ v.index+totverts,\ globalNormals[ veckey3d(v.no) ])) else: # No smoothing, face normals no = globalNormals[veckey3d(f.no)] for v in f_v: file.write( ' %d %d' % (\ v.index+totverts,\ no)) if in_triangles: file.write('</p>\n') file.write('\t\t\t</triangles>\n') # Write edges. LOOSE = Mesh.EdgeFlags.LOOSE has_edge = False for ed in edges: if ed.flag & LOOSE: has_edge = True if has_edge: file.write('\t\t\t<edges>\n') file.write( '\t\t\t\t<input offset="0" semantic="VERTEX" source="#%s" />\n' % vertname) file.write('\t\t\t\t<p>') for ed in edges: if ed.flag & LOOSE: file.write( ' %d %d' % (ed.v1.index + totverts, ed.v2.index + totverts)) file.write('</p>\n') file.write('\t\t\t</edges>\n') # Make the indicies global rather then per mesh # totverts += len(me.verts) # if faceuv: # totuvco += uv_unique_count me.verts = None if len(faces) > 0: file.write('\t\t</mesh>\n') else: file.write('\t\t</curve>\n') file.write('\t</object>\n') file.write('</library_objects>\n\n') # Now we have all our materials, save them if EXPORT_MTL: write_library_materials(file) # Save the groups write_library_groups(file) file.write('</OPEN_TRACK>\n') file.close() if EXPORT_COPY_IMAGES: dest_dir = filename # Remove chars until we are just the path. while dest_dir and dest_dir[-1] not in '\\/': dest_dir = dest_dir[:-1] if dest_dir: copy_images(dest_dir) else: print '\tError: "%s" could not be used as a base for an image path.' % filename print "WTF Export time: %.2f" % (sys.time() - time1)
def write(filename): start = Blender.sys.time() if not filename.lower().endswith(".tmf"): filename += ".tmf" scn = Blender.Scene.GetCurrent() ob = scn.objects.active if not ob: Blender.Draw.PupMenu("Error%t|Select 1 active object") return file = open(filename, "wb") mesh = BPyMesh.getMeshFromObject(ob, None, True, False, scn) if not mesh: Blender.Draw.PupMenu("Error%t|Could not get mesh data from active object") return mesh.transform(ob.matrixWorld) file = open(filename, "wb") # Write vertex coords and normals file.write("C " + ` len(mesh.verts) ` + "\n") for v in mesh.verts: file.write("%.6f %.6f %.6f " % tuple(v.co)) file.write("\n") file.write("N " + ` len(mesh.verts) ` + "\n") for v in mesh.verts: file.write("%.6f %.6f %.6f " % tuple(v.no)) file.write("\n") # Process faces faces = len(mesh.faces) data = "" uvdata = "" for face in mesh.faces: if face.v[2] < 0: # discard faces = faces - 1 elif face.v[2] < 0: # Already a triangle, add it to the data, do not change the count data = data + ` face.v[0].index ` + " " + ` face.v[1].index ` + " " + ` face.v[2].index ` + "\n" for v in face.uv: add_uvdata(uvdata, v) else: # this one is a quad # Break it up into two triangles # Hence one additional face faces = faces + 1 data = data + ` face.v[0].index ` + " " + ` face.v[1].index ` + " " + ` face.v[3].index ` + "\n" data = data + ` face.v[1].index ` + " " + ` face.v[2].index ` + " " + ` face.v[3].index ` + "\n" uvdata = add_uvdata(uvdata, face.uv[0]) uvdata = add_uvdata(uvdata, face.uv[1]) uvdata = add_uvdata(uvdata, face.uv[3]) uvdata = uvdata + "\n" uvdata = add_uvdata(uvdata, face.uv[1]) uvdata = add_uvdata(uvdata, face.uv[2]) uvdata = add_uvdata(uvdata, face.uv[3]) uvdata = uvdata + "\n" # Now I can write the header with the correct face count, and then the data file.write("F " + ` faces ` + "\n") file.write(data) uvs = faces * 3 file.write("T " + ` uvs ` + "\n") file.write(uvdata) file.close() end = Blender.sys.time() message = 'Successfully exported "%s" in %.4f seconds' % (Blender.sys.basename(filename), end - start) print message
def apply_deform(): scn= bpy.data.scenes.active #Blender.Window.EditMode(0) NAME_LENGTH = 19 SUFFIX = "_def" SUFFIX_LENGTH = len(SUFFIX) # Get all object and mesh names ob_list = list(scn.objects.context) ob_act = scn.objects.active # Assume no soft body has_sb= False # reverse loop so we can remove objects (metaballs in this case) for ob_idx in xrange(len(ob_list)-1, -1, -1): ob= ob_list[ob_idx] ob.sel = 0 # deselect while where checking the metaballs # Test for a softbody if not has_sb and ob.isSB(): has_sb= True # Remove all numbered metaballs because their disp list is only on the main metaball (un numbered) if ob.type == 'MBall': name= ob.name # is this metaball numbered? dot_idx= name.rfind('.') + 1 if name[dot_idx:].isdigit(): # Not the motherball, ignore it. del ob_list[ob_idx] if not ob_list: Blender.Draw.PupMenu('No objects selected, nothing to do.') return if has_sb: curframe=Blender.Get('curframe') for f in xrange(curframe): Blender.Set('curframe',f+1) Blender.Window.RedrawAll() used_names = [ob.name for ob in Blender.Object.Get()] used_names.extend(Blender.NMesh.GetNames()) deformedList = [] for ob in ob_list: # Get the mesh data new_me= BPyMesh.getMeshFromObject(ob, vgroups=False) if not new_me: continue # Object has no display list name = ob.name new_name = "%s_def" % name[:NAME_LENGTH-SUFFIX_LENGTH] num = 0 while new_name in used_names: new_name = "%s_def.%.3i" % (name[:NAME_LENGTH-(SUFFIX_LENGTH+SUFFIX_LENGTH)], num) num += 1 used_names.append(new_name) new_me.name= new_name new_ob= scn.objects.new(new_me) new_ob.setMatrix(ob.matrixWorld) # Make the active duplicate also active if ob == ob_act: scn.objects.active = new_ob # Original object was a mesh? see if we can copy any vert groups. if ob.type =='Mesh': copy_vgroups(ob, new_ob) Blender.Window.RedrawAll()
def setSinglePath(filename): base = os.path.dirname(filename) print('Base path: ' + base) print('Relative path: ' + relpath('.', base)) base = relpath('.', base) Blender.Window.EditMode(0, '', 0) print('Models count: %d' % len(bpy.data.scenes)) savescene = bpy.data.scenes.active # save current active scene Window.DrawProgressBar( 0.0, "Start exporting..." ) progress = 0.0 addProgress = 1.0 / len(bpy.data.scenes) USE_GZIP = True for scene in bpy.data.scenes: progress += addProgress Window.DrawProgressBar( progress, 'Exporting model "' + scene.name + '" %.0f %%...' % ( progress * 100.0 ) ) print('Model "' + scene.name + '":') scene.makeCurrent() try: import gzip file_model = gzip.open(base + "\\" + scene.name +".bdsm2.gz", "wb") except: print "Failed to compression modules, exporting uncompressed" USE_GZIP = False file_model = open(base + "\\" + scene.name +".bdsm2", "wb") file_info = open(base + "\\" + scene.name +".bdsi2", "w") file_model.write(MODEL_HEADER) file_info.write('Model name: "' + scene.name + '"\n') ANIMATION = False # Pass 1 - validate scene for animation required and collect meshes render = scene.render start = render.sFrame end = render.eFrame if end < start: start, end = end, start saveframe = Blender.Get('curframe') # save current active frame frame = start mesh_list = [] mesh_by_frame = [[] for i in xrange(end-start+1)] omeshes = [] link_omeshes_mesh = {} link_mesh_frame = {} while frame <= end: Blender.Set('curframe', frame) objects = [object for object in scene.objects if (object.type == 'Mesh') and (not object.restrictRender) and (1 in object.layers)] for object in objects: mesh = BPyMesh.getMeshFromObject(object, None, EXPORT_APPLY_MODIFIERS, False, scene) omesh = object.getData(True) if (mesh) and (len(mesh.faces)): try: ipo = object.ipo except: ipo = None if ipo: ANIMATION = True if omesh in omeshes: # file_info.write('+reusing mesh "' + omesh + '" for object "' + object.name + '\n') mesh_by_frame[frame-start].append((link_omeshes_mesh[omesh], object)) else: # file_info.write('+mesh "' + omesh + '" for object "' + object.name + '"\n') omeshes.append(omesh) link_omeshes_mesh[omesh] = mesh mesh_list.append(mesh) mesh_by_frame[frame-start].append((mesh, object)) link_mesh_frame[mesh] = frame materials = mesh.materials if materials: for material in materials: try: ipo = material.ipo except: ipo = None if ipo: ANIMATION = True #mesh.unlink() frame+=1 # file_info.write('Meshes used: %d\n' % len(omeshes)) # for omesh in omeshes: # file_info.write(' mesh ' + omesh + '\n') mesh_max = len(mesh_list) file_info.write(' meshes: %d\n' % mesh_max ) file_model.write(struct.pack("<I", mesh_max)) vert_data = ['' for i in xrange(len(mesh_list))]; index_data = ['' for i in xrange(len(mesh_list))]; for mi, mesh in enumerate(mesh_list): frame = link_mesh_frame[mesh] file_info.write(' [%d] mesh "'%(mi,) + mesh.name + '" (frame = %d)\n' % frame) Blender.Set('curframe', frame) # OpenGL 3.x GL_QUADS is deprecated # MESH_QUADS = True MESH_QUADS = False # Проверим состоит ли меш только из квадов # for face in mesh.faces: # if len(face) == 3: # MESH_QUADS = False # break if not MESH_QUADS: file_info.write(' convert to triangles\n') tempob = scene.objects.new(mesh) oldmode = Mesh.Mode() Mesh.Mode(Mesh.SelectModes['FACE']) mesh.sel = True mesh.quadToTriangle(0) # mesh.recalcNormals(0) scene.objects.unlink(tempob) Mesh.Mode(oldmode) # TBD!!! Нужно еще вставить контроль того что не осталось смешанных face EXPORT_UV = True EXPORT_COLORS = True # Генерируем списки вершин и списки индексов faceUV = mesh.faceUV vertexUV = mesh.vertexUV vertexColors = mesh.vertexColors if (not faceUV) and (not vertexUV): EXPORT_UV = False if not vertexColors: EXPORT_COLORS = False if not EXPORT_UV: faceUV = vertexUV = False if not EXPORT_COLORS: vertexColors = False color = uvcoord = uvcoord_key = normal = normal_key = None verts = [] # list of dictionaries # vdict = {} # (index, normal, uv) -> new index vdict = [{} for i in xrange(len(mesh.verts))] vert_count = 0 for i, f in enumerate(mesh.faces): smooth = f.smooth if not smooth: normal = tuple(f.no) normal_key = rvec3d(normal) if faceUV: uv = f.uv if vertexColors: col = f.col for j, v in enumerate(f): if smooth: normal = tuple(v.no) normal_key = rvec3d(normal) if faceUV: uvcoord = uv[j][0], 1.0-uv[j][1] uvcoord_key = rvec2d(uvcoord) elif vertexUV: uvcoord = v.uvco[0], 1.0-v.uvco[1] uvcoord_key = rvec2d(uvcoord) if vertexColors: color = col[j].r, col[j].g, col[j].b key = normal_key, uvcoord_key, color vdict_local = vdict[v.index] if (not vdict_local) or (not vdict_local.has_key(key)): vdict_local[key] = vert_count; verts.append( (tuple(v.co), normal, uvcoord, color) ) vert_count += 1 file_info.write(' Mesh attributes: ') vl = len(verts) if MESH_QUADS: il = len(mesh.faces)*4 else: il = len(mesh.faces)*3 bits = 0 if MESH_QUADS: bits |= 1 file_info.write(' [quads]') else: file_info.write(' [triangles]') if EXPORT_UV: bits |= 2 file_info.write(' [texture coordinates]') if EXPORT_COLORS: bits |= 4 file_info.write(' [vertex color]') if vl < 256: file_info.write(' [VB]') elif vl < 65536: bits |= 8 file_info.write(' [VS]') else: bits |= 16 file_info.write(' [VI]') if il < 256: file_info.write(' [IB]') elif il < 65536: bits |= 32 file_info.write(' [IS]') else: bits |= 64 file_info.write(' [II]') file_info.write('\n') file_model.write(struct.pack("<c", chr(bits))) file_info.write(' Mesh verts = %d\n' % vl); packwrite(file_model, vl); file_info.write(' Mesh indexes = %d\n' % il) packwrite(file_model, il); vind=0 for v in verts: # file_info.write(' [%d]:' % vind) vind += 1 # file_info.write(' v:(%.3f, %.3f, %.3f)' % (v[0][0], v[0][1], v[0][2])) vert_data[mi] += struct.pack('<3H', FloatToHalf(v[0][0]), FloatToHalf(v[0][1]), FloatToHalf(v[0][2])) # vertex # file_info.write(' n:(%.3f, %.3f, %.3f)' % (v[1][0], v[1][1], v[1][2])) vert_data[mi] += struct.pack('<3H', FloatToHalf(v[1][0]), FloatToHalf(v[1][1]), FloatToHalf(v[1][2])) # normals if EXPORT_UV: # file_info.write(' v:(%.3f, %.3f)' % (v[2][0], v[2][1])) vert_data[mi] += struct.pack('<2H', FloatToHalf(v[2][0]), FloatToHalf(v[2][1])) if EXPORT_COLORS: # file_info.write(' c:(%d, %d, %d, %d)' % (v[3][0], v[3][1], v[3][2], 255)) vert_data[mi] += struct.pack('<4c', chr(int(v[3][0])), chr(int(v[3][1])), chr(int(v[3][2])), chr(255) ) # file_info.write('\n') ri = 0 # file_info.write(' Indexes:\n') iind = 0 for (i, f) in enumerate(mesh.faces): # file.write('%d ' % len(f)) # file.write(struct.pack("<I", len(f))) smooth = f.smooth if not smooth: no = rvec3d(f.no) if faceUV: uv = f.uv if vertexColors: col = f.col for j, v in enumerate(f): if f.smooth: normal = rvec3d(v.no) else: normal = no if faceUV: uvcoord = rvec2d((uv[j][0], 1.0-uv[j][1])) elif vertexUV: uvcoord = rvec2d((v.uvco[0], 1.0-v.uvco[1])) if vertexColors: color = col[j].r, col[j].g, col[j].b # file.write(struct.pack("<I", vdict[v.index][normal, uvcoord, color])) ri += 1; # index_data[mi] += struct.pack("<I", vdict[v.index][normal, uvcoord, color]) # file_info.write(' [%d]: %d\n' % (iind, vdict[v.index][normal, uvcoord, color])) iind += 1 if vl < 256: index_data[mi] += struct.pack("<c", chr(vdict[v.index][normal, uvcoord, color])) elif vl < 65536: index_data[mi] += struct.pack("<H", vdict[v.index][normal, uvcoord, color]) else: index_data[mi] += struct.pack("<I", vdict[v.index][normal, uvcoord, color]) # file_info.write(' Real indexes = %d\n' % ri) if ANIMATION: file_info.write(' Animation frames: %d\n' %(end-start+1)) else: end = start file_info.write(' No animation (frames: 1)\n') file_model.write(ANIMATION_HEADER) file_model.write(struct.pack("<I", end-start+1)) frame = start while frame <= end: Blender.Set('curframe', frame) file_info.write(' frame: %d\n' % frame ) mif = len(mesh_by_frame[frame-start]) file_info.write(' meshes in frame: %d\n' % mif) packmwrite(file_model, mesh_max, mif); for mesh,mobject in mesh_by_frame[frame-start]: i = mesh_list.index(mesh) mcolor = [255, 255, 255, 255] materials = mobject.getMaterials() if not materials: materials = mesh.materials if materials: if materials[0]: mcolor = [int(materials[0].R*255), int(materials[0].G*255), int(materials[0].B*255), int(255) ] for x in xrange(4): if mcolor[x]<0: mcolor[x] = 0 if mcolor[x]>255: mcolor[x] = 255 file_info.write(' mesh "' + mesh.name + '"[%d] for object "'%(i,) + mobject.name + '"' ) packmwrite(file_model, mesh_max, i) file_info.write(' color: [%d,%d,%d,%d]\n' % tuple(mcolor) ) file_model.write(struct.pack("<4c", chr(mcolor[0]),chr(mcolor[1]),chr(mcolor[2]),chr(mcolor[3]))) file_info.write(' matrix:'); file_info.write(' [[%.2f,%.2f,%.2f,%.2f]' % tuple(mobject.matrixWorld[0])) file_info.write(' [%.2f,%.2f,%.2f,%.2f]' % tuple(mobject.matrixWorld[1])) file_info.write(' [%.2f,%.2f,%.2f,%.2f]' % tuple(mobject.matrixWorld[2])) file_info.write(' [%.2f,%.2f,%.2f,%.2f]]\n' % tuple(mobject.matrixWorld[3])) file_model.write(struct.pack("<4f", mobject.matrixWorld[0][0], mobject.matrixWorld[0][1], mobject.matrixWorld[0][2], mobject.matrixWorld[0][3])) file_model.write(struct.pack("<4f", mobject.matrixWorld[1][0], mobject.matrixWorld[1][1], mobject.matrixWorld[1][2], mobject.matrixWorld[1][3])) file_model.write(struct.pack("<4f", mobject.matrixWorld[2][0], mobject.matrixWorld[2][1], mobject.matrixWorld[2][2], mobject.matrixWorld[2][3])) file_model.write(struct.pack("<4f", mobject.matrixWorld[3][0], mobject.matrixWorld[3][1], mobject.matrixWorld[3][2], mobject.matrixWorld[3][3])) frame+=1 # Save vbo file_model.write(VBO_HEADER) for i in xrange(len(mesh_list)): file_info.write(' Mesh %d:\n' % i) file_model.write(vert_data[i]) file_model.write(index_data[i]) file_info.write(' Vertex data size = %d bytes\n' % len(vert_data[i])) file_info.write(' Index data size = %d bytes\n' % len(index_data[i])) Blender.Set('curframe', saveframe) # restore current active frame file_info.close(); file_model.close(); savescene.makeCurrent() # restore active scene Window.DrawProgressBar( 1.0, "Finished!" ) return
def file_callback(filename): if not filename.lower().endswith('.submesh'): filename += '.submesh' scn= bpy.data.scenes.active ob= scn.objects.active if not ob: Blender.Draw.PupMenu('Error%t|Select 1 active object') return file = open(filename, 'wb') EXPORT_APPLY_MODIFIERS = Draw.Create(1) EXPORT_NORMALS = Draw.Create(1) EXPORT_UV = Draw.Create(1) EXPORT_COLORS = Draw.Create(1) #EXPORT_EDGES = Draw.Create(0) pup_block = [\ ('Apply Modifiers', EXPORT_APPLY_MODIFIERS, 'Use transformed mesh data.'),\ ('Normals', EXPORT_NORMALS, 'Export vertex normal data.'),\ ('UVs', EXPORT_UV, 'Export texface UV coords.'),\ ('Colors', EXPORT_COLORS, 'Export vertex Colors.'),\ #('Edges', EXPORT_EDGES, 'Edges not connected to faces.'),\ ] if not Draw.PupBlock('Export...', pup_block): return is_editmode = Blender.Window.EditMode() if is_editmode: Blender.Window.EditMode(0, '', 0) Window.WaitCursor(1) EXPORT_APPLY_MODIFIERS = EXPORT_APPLY_MODIFIERS.val EXPORT_NORMALS = EXPORT_NORMALS.val EXPORT_UV = EXPORT_UV.val EXPORT_COLORS = EXPORT_COLORS.val #EXPORT_EDGES = EXPORT_EDGES.val mesh = BPyMesh.getMeshFromObject(ob, None, EXPORT_APPLY_MODIFIERS, False, scn) if not mesh: Blender.Draw.PupMenu('Error%t|Could not get mesh data from active object') return mesh.transform(ob.matrixWorld) faceUV = mesh.faceUV vertexUV = mesh.vertexUV vertexColors = mesh.vertexColors if (not faceUV) and (not vertexUV): EXPORT_UV = False if not vertexColors: EXPORT_COLORS = False if not EXPORT_UV: faceUV = vertexUV = False if not EXPORT_COLORS: vertexColors = False # incase color = uvcoord = uvcoord_key = normal = normal_key = None verts = [] # list of dictionaries # vdict = {} # (index, normal, uv) -> new index vdict = [{} for i in xrange(len(mesh.verts))] vert_count = 0 for i, f in enumerate(mesh.faces): smooth = f.smooth if not smooth: normal = tuple(f.no) normal_key = rvec3d(normal) if faceUV: uv = f.uv if vertexColors: col = f.col for j, v in enumerate(f): if smooth: normal= tuple(v.no) normal_key = rvec3d(normal) if faceUV: uvcoord= uv[j][0], 1.0-uv[j][1] uvcoord_key = rvec2d(uvcoord) elif vertexUV: uvcoord= v.uvco[0], 1.0-v.uvco[1] uvcoord_key = rvec2d(uvcoord) if vertexColors: color= col[j].r, col[j].g, col[j].b key = normal_key, uvcoord_key, color vdict_local = vdict[v.index] if (not vdict_local) or (not vdict_local.has_key(key)): vdict_local[key] = vert_count; verts.append( (tuple(v.co), normal, uvcoord, color) ) vert_count += 1 file.write('SUBMESHTEXT0001\n') file.write('#Created by Blender3D %s - www.blender.org, source file: %s\n' % (Blender.Get('version'), Blender.Get('filename').split('/')[-1].split('\\')[-1] )) #file.write('element vertex %d\n' % len(verts)) file.write('vertex format: position:3,texture0:2,normal:3\n') file.write('vertex count: %d\n'%len(verts)) for i, v in enumerate(verts): file.write('[%.6f,%.6f,%.6f]' % v[0]) # co #if EXPORT_UV: file.write(' [%.6f,%.6f]' % v[2]) # uv #if EXPORT_NORMALS: file.write(' [%.6f,%.6f,%.6f]' % v[1]) # no #if EXPORT_COLORS: # file.write('%u %u %u' % v[3]) # col file.write('\n') triangles=[] for (i, f) in enumerate(mesh.faces): #file.write('%d ' % len(f)) smooth = f.smooth if not smooth: no = rvec3d(f.no) if faceUV: uv = f.uv if vertexColors: col = f.col if(len(f)==3): triangle=[] for j, v in enumerate(f): if f.smooth: normal= rvec3d(v.no) else: normal= no if faceUV: uvcoord= rvec2d((uv[j][0], 1.0-uv[j][1])) elif vertexUV: uvcoord= rvec2d((v.uvco[0], 1.0-v.uvco[1])) if vertexColors: color= col[j].r, col[j].g, col[j].b triangle+=[vdict[v.index][normal, uvcoord, color]] triangles+=[triangle] #file.write('%d ' % vdict[v.index][normal, uvcoord, color]) #file.write('\n') else: x=[] for j, v in enumerate(f): if f.smooth: normal= rvec3d(v.no) else: normal= no if faceUV: uvcoord= rvec2d((uv[j][0], 1.0-uv[j][1])) elif vertexUV: uvcoord= rvec2d((v.uvco[0], 1.0-v.uvco[1])) if vertexColors: color= col[j].r, col[j].g, col[j].b #file.write('%d ' % vdict[v.index][normal, uvcoord, color]) x+=[vdict[v.index][normal, uvcoord, color]] triangles+=[[x[1],x[2],x[0]]] triangles+=[[x[2],x[3],x[0]]] #file.write('[%d,%d,%d]\n'%()) #file.write('[%d,%d,%d]\n'%(x[1],x[2],x[3])) file.write('triangle count: %d\n'%len(triangles)) for (i, f) in enumerate(triangles): file.write('[%d,'%f[0]) file.write('%d,'%f[1]) file.write('%d]\n'%f[2]) file.close() if is_editmode: Blender.Window.EditMode(1, '', 0)
def file_callback(filename): if not filename.lower().endswith('.ctm'): filename += '.ctm' # Get object mesh from the selected object scn = bpy.data.scenes.active ob = scn.objects.active if not ob: Blender.Draw.PupMenu('Error%t|Select 1 active object') return mesh = BPyMesh.getMeshFromObject(ob, None, False, False, scn) if not mesh: Blender.Draw.PupMenu( 'Error%t|Could not get mesh data from active object') return # Check which mesh properties are present... hasVertexUV = mesh.vertexUV or mesh.faceUV hasVertexColors = mesh.vertexColors # Show a GUI for the export settings pupBlock = [] EXPORT_APPLY_MODIFIERS = Draw.Create(1) pupBlock.append(('Apply Modifiers', EXPORT_APPLY_MODIFIERS, 'Use transformed mesh data.')) EXPORT_NORMALS = Draw.Create(1) pupBlock.append(('Normals', EXPORT_NORMALS, 'Export vertex normal data.')) if hasVertexUV: EXPORT_UV = Draw.Create(1) pupBlock.append(('UVs', EXPORT_UV, 'Export texface UV coords.')) if hasVertexColors: EXPORT_COLORS = Draw.Create(1) pupBlock.append(('Colors', EXPORT_COLORS, 'Export vertex Colors.')) EXPORT_MG2 = Draw.Create(0) pupBlock.append( ('Fixed Point', EXPORT_MG2, 'Use limited precision algorithm (MG2 method = better compression).')) if not Draw.PupBlock('Export...', pupBlock): return # Adjust export settings according to GUI selections EXPORT_APPLY_MODIFIERS = EXPORT_APPLY_MODIFIERS.val EXPORT_NORMALS = EXPORT_NORMALS.val if hasVertexUV: EXPORT_UV = EXPORT_UV.val else: EXPORT_UV = False if hasVertexColors: EXPORT_COLORS = EXPORT_COLORS.val else: EXPORT_COLORS = False EXPORT_MG2 = EXPORT_MG2.val # If the user wants to export MG2, then show another GUI... if EXPORT_MG2: pupBlock = [] EXPORT_VPREC = Draw.Create(0.01) pupBlock.append(('Vertex', EXPORT_VPREC, 0.0001, 1.0, 'Relative vertex precision (fixed point).')) if EXPORT_NORMALS: EXPORT_NPREC = Draw.Create(1.0 / 256.0) pupBlock.append(('Normal', EXPORT_NPREC, 0.0001, 1.0, 'Normal precision (fixed point).')) if EXPORT_UV: EXPORT_UVPREC = Draw.Create(1.0 / 1024.0) pupBlock.append(('UV', EXPORT_UVPREC, 0.0001, 1.0, 'UV precision (fixed point).')) if EXPORT_COLORS: EXPORT_CPREC = Draw.Create(1.0 / 256.0) pupBlock.append(('Color', EXPORT_CPREC, 0.0001, 1.0, 'Color precision (fixed point).')) if not Draw.PupBlock('Fixed point precision...', pupBlock): return # Adjust export settings according to GUI selections if EXPORT_MG2: EXPORT_VPREC = EXPORT_VPREC.val else: EXPORT_VPREC = 0.1 if EXPORT_MG2 and EXPORT_NORMALS: EXPORT_NPREC = EXPORT_NPREC.val else: EXPORT_NPREC = 0.1 if EXPORT_MG2 and EXPORT_UV: EXPORT_UVPREC = EXPORT_UVPREC.val else: EXPORT_UVPREC = 0.1 if EXPORT_MG2 and EXPORT_COLORS: EXPORT_CPREC = EXPORT_CPREC.val else: EXPORT_CPREC = 0.1 is_editmode = Blender.Window.EditMode() if is_editmode: Blender.Window.EditMode(0, '', 0) Window.WaitCursor(1) try: # Get the mesh, again, if we wanted modifiers (from GUI selection) if EXPORT_APPLY_MODIFIERS: mesh = BPyMesh.getMeshFromObject(ob, None, EXPORT_APPLY_MODIFIERS, False, scn) if not mesh: Blender.Draw.PupMenu( 'Error%t|Could not get mesh data from active object') return mesh.transform(ob.matrixWorld, True) # Count triangles (quads count as two triangles) triangleCount = 0 for f in mesh.faces: if len(f.v) == 4: triangleCount += 2 else: triangleCount += 1 # Extract indices from the Blender mesh (quads are split into two triangles) pindices = cast((c_int * 3 * triangleCount)(), POINTER(c_int)) i = 0 for f in mesh.faces: pindices[i] = c_int(f.v[0].index) pindices[i + 1] = c_int(f.v[1].index) pindices[i + 2] = c_int(f.v[2].index) i += 3 if len(f.v) == 4: pindices[i] = c_int(f.v[0].index) pindices[i + 1] = c_int(f.v[2].index) pindices[i + 2] = c_int(f.v[3].index) i += 3 # Extract vertex array from the Blender mesh vertexCount = len(mesh.verts) pvertices = cast((c_float * 3 * vertexCount)(), POINTER(c_float)) i = 0 for v in mesh.verts: pvertices[i] = c_float(v.co.x) pvertices[i + 1] = c_float(v.co.y) pvertices[i + 2] = c_float(v.co.z) i += 3 # Extract normals if EXPORT_NORMALS: pnormals = cast((c_float * 3 * vertexCount)(), POINTER(c_float)) i = 0 for v in mesh.verts: pnormals[i] = c_float(v.no.x) pnormals[i + 1] = c_float(v.no.y) pnormals[i + 2] = c_float(v.no.z) i += 3 else: pnormals = POINTER(c_float)() # Extract UVs if EXPORT_UV: ptexCoords = cast((c_float * 2 * vertexCount)(), POINTER(c_float)) if mesh.faceUV: for f in mesh.faces: for j, v in enumerate(f.v): k = v.index if k < vertexCount: uv = f.uv[j] ptexCoords[k * 2] = uv[0] ptexCoords[k * 2 + 1] = uv[1] else: i = 0 for v in mesh.verts: ptexCoords[i] = c_float(v.uvco[0]) ptexCoords[i + 1] = c_float(v.uvco[1]) i += 2 else: ptexCoords = POINTER(c_float)() # Extract colors if EXPORT_COLORS: pcolors = cast((c_float * 4 * vertexCount)(), POINTER(c_float)) for f in mesh.faces: for j, v in enumerate(f.v): k = v.index if k < vertexCount: col = f.col[j] pcolors[k * 4] = col.r / 255.0 pcolors[k * 4 + 1] = col.g / 255.0 pcolors[k * 4 + 2] = col.b / 255.0 pcolors[k * 4 + 3] = 1.0 else: pcolors = POINTER(c_float)() # Load the OpenCTM shared library if os.name == 'nt': libHDL = WinDLL('openctm.dll') else: libName = find_library('openctm') if not libName: Blender.Draw.PupMenu( 'Could not find the OpenCTM shared library') return libHDL = CDLL(libName) if not libHDL: Blender.Draw.PupMenu('Could not open the OpenCTM shared library') return # Get all the functions from the shared library that we need ctmNewContext = libHDL.ctmNewContext ctmNewContext.argtypes = [c_int] ctmNewContext.restype = c_void_p ctmFreeContext = libHDL.ctmFreeContext ctmFreeContext.argtypes = [c_void_p] ctmGetError = libHDL.ctmGetError ctmGetError.argtypes = [c_void_p] ctmGetError.restype = c_int ctmErrorString = libHDL.ctmErrorString ctmErrorString.argtypes = [c_int] ctmErrorString.restype = c_char_p ctmFileComment = libHDL.ctmFileComment ctmFileComment.argtypes = [c_void_p, c_char_p] ctmDefineMesh = libHDL.ctmDefineMesh ctmDefineMesh.argtypes = [ c_void_p, POINTER(c_float), c_int, POINTER(c_int), c_int, POINTER(c_float) ] ctmSave = libHDL.ctmSave ctmSave.argtypes = [c_void_p, c_char_p] ctmAddUVMap = libHDL.ctmAddUVMap ctmAddUVMap.argtypes = [c_void_p, POINTER(c_float), c_char_p, c_char_p] ctmAddUVMap.restype = c_int ctmAddAttribMap = libHDL.ctmAddAttribMap ctmAddAttribMap.argtypes = [c_void_p, POINTER(c_float), c_char_p] ctmAddAttribMap.restype = c_int ctmCompressionMethod = libHDL.ctmCompressionMethod ctmCompressionMethod.argtypes = [c_void_p, c_int] ctmVertexPrecisionRel = libHDL.ctmVertexPrecisionRel ctmVertexPrecisionRel.argtypes = [c_void_p, c_float] ctmNormalPrecision = libHDL.ctmNormalPrecision ctmNormalPrecision.argtypes = [c_void_p, c_float] ctmUVCoordPrecision = libHDL.ctmUVCoordPrecision ctmUVCoordPrecision.argtypes = [c_void_p, c_int, c_float] ctmAttribPrecision = libHDL.ctmAttribPrecision ctmAttribPrecision.argtypes = [c_void_p, c_int, c_float] # Create an OpenCTM context ctm = ctmNewContext(0x0102) # CTM_EXPORT try: # Set the file comment ctmFileComment( ctm, c_char_p('%s - created by Blender %s (www.blender.org)' % (ob.getName(), Blender.Get('version')))) # Define the mesh ctmDefineMesh(ctm, pvertices, c_int(vertexCount), pindices, c_int(triangleCount), pnormals) # Add UV coordinates? if EXPORT_UV: tm = ctmAddUVMap(ctm, ptexCoords, c_char_p(), c_char_p()) if EXPORT_MG2: ctmUVCoordPrecision(ctm, tm, EXPORT_UVPREC) # Add colors? if EXPORT_COLORS: cm = ctmAddAttribMap(ctm, pcolors, c_char_p('Color')) if EXPORT_MG2: ctmAttribPrecision(ctm, cm, EXPORT_CPREC) # Set compression method if EXPORT_MG2: ctmCompressionMethod(ctm, 0x0203) # CTM_METHOD_MG2 ctmVertexPrecisionRel(ctm, EXPORT_VPREC) if EXPORT_NORMALS: ctmNormalPrecision(ctm, EXPORT_NPREC) else: ctmCompressionMethod(ctm, 0x0202) # CTM_METHOD_MG1 # Save the file ctmSave(ctm, c_char_p(filename)) # Check for errors e = ctmGetError(ctm) if e != 0: s = ctmErrorString(e) Blender.Draw.PupMenu('Error%t|Could not save the file: ' + s) finally: # Free the OpenCTM context ctmFreeContext(ctm) finally: Window.WaitCursor(0) if is_editmode: Blender.Window.EditMode(1, '', 0)
def write(filename): start = Blender.sys.time() file = open(filename, "wb") scn = Blender.Scene.GetCurrent() objects = list(scn.objects.context) if not objects: Blender.Draw.PupMenu('Error%t|No Objects selected') return try: objects.sort(key=lambda a: a.name) except: objects.sort(lambda a, b: cmp(a.name, b.name)) text = generate_text() desc = generate_desc() icon = "" #generate_icon() meshes = [] for obj in objects: mesh = BPyMesh.getMeshFromObject(obj, None, True, False, scn) if mesh: mesh.transform(obj.matrixWorld) meshes.append(mesh) material_names = get_used_material_names(meshes) tags = generate_tags(material_names) surfs = generate_surfs(material_names) chunks = [text, desc, icon, tags] meshdata = cStringIO.StringIO() layer_index = 0 for mesh in meshes: layr = generate_layr(obj.name, layer_index) pnts = generate_pnts(mesh) bbox = generate_bbox(mesh) pols = generate_pols(mesh) ptag = generate_ptag(mesh, material_names) clip = generate_clip(mesh, material_names) if mesh.faceUV: vmad_uv = generate_vmad_uv(mesh) # per face if mesh.vertexColors: #if meshtools.average_vcols: # vmap_vc = generate_vmap_vc(mesh) # per vert #else: vmad_vc = generate_vmad_vc(mesh) # per face write_chunk(meshdata, "LAYR", layr) chunks.append(layr) write_chunk(meshdata, "PNTS", pnts) chunks.append(pnts) write_chunk(meshdata, "BBOX", bbox) chunks.append(bbox) write_chunk(meshdata, "POLS", pols) chunks.append(pols) write_chunk(meshdata, "PTAG", ptag) chunks.append(ptag) if mesh.vertexColors: #if meshtools.average_vcols: # write_chunk(meshdata, "VMAP", vmap_vc) # chunks.append(vmap_vc) #else: write_chunk(meshdata, "VMAD", vmad_vc) chunks.append(vmad_vc) if mesh.faceUV: write_chunk(meshdata, "VMAD", vmad_uv) chunks.append(vmad_uv) write_chunk(meshdata, "CLIP", clip) chunks.append(clip) layer_index += 1 mesh.verts = None # save some ram for surf in surfs: chunks.append(surf) write_header(file, chunks) write_chunk(file, "ICON", icon) write_chunk(file, "TEXT", text) write_chunk(file, "DESC", desc) write_chunk(file, "TAGS", tags) file.write(meshdata.getvalue()) meshdata.close() for surf in surfs: write_chunk(file, "SURF", surf) write_chunk(file, "DATE", "August 19, 2005") Blender.Window.DrawProgressBar(1.0, "") # clear progressbar file.close() print '\a\r', print "Successfully exported %s in %.3f seconds" % ( filename.split('\\')[-1].split('/')[-1], Blender.sys.time() - start)
def main(): PREF_Z_LOC = Blender.Draw.PupMenu( 'Cut Z Location%t|Original Faces|Cutting Polyline') if PREF_Z_LOC == -1: return PREF_Z_LOC -= 1 Blender.Window.WaitCursor(1) print '\nRunning Cookie Cutter' time = Blender.sys.time() scn = Blender.Scene.GetCurrent() obs = [ob for ob in scn.objects.context if ob.type in ('Mesh', 'Curve')] MULTIRES_ERROR = False # Divide into 2 lists- 1 with faces, one with only edges terrains = [] #[me for me in mes if me.faces] cutters = [] #[me for me in mes if not me.faces] terrain_type = auto_class([ 'mesh', 'bounds', 'face_bounds', 'edge_bounds', 'edge_dict', 'cutters', 'matrix' ]) for ob in obs: if ob.type == 'Mesh': me = ob.getData(mesh=1) elif ob.data.flag & 1: # Is the curve 3D? else dont use. me = BPyMesh.getMeshFromObject(ob) # get the curve else: continue # a new terrain instance if me.multires: MULTIRES_ERROR = True else: t = terrain_type() t.matrix = ob.matrixWorld * Blender.Window.GetViewMatrix() # Transform the object by its matrix me.transform(t.matrix) # Set the terrain bounds t.bounds = bounds_xy(me.verts) t.edge_bounds = [bounds_xy(ed) for ed in me.edges] t.mesh = me if me.faces: # Terrain. t.edge_dict = mesh_edge_dict(me) t.face_bounds = [bounds_xy(f) for f in me.faces] t.cutters = [] # Store cutting objects that cut us here terrains.append(t) elif len(me.edges) > 2: # Cutter cutters.append(t) totcuts = len(terrains) * len(cutters) if not totcuts: Blender.Window.WaitCursor(0) Blender.Draw.PupMenu( 'ERROR%t|Select at least 1 closed loop mesh (edges only)|as the cutter...|and 1 or more meshes to cut into' ) crazy_point = Vector(100000, 100000) for t in terrains: for c in cutters: # Main curring function terrain_cut_2d(t, c, PREF_Z_LOC) # Was the terrain touched? if len(t.face_bounds) != len(t.mesh.faces): t.edge_dict = mesh_edge_dict(t.mesh) # remake the bounds t.edge_bounds = [bounds_xy(ed) for ed in t.mesh.edges] t.face_bounds = [bounds_xy(f) for f in t.mesh.faces] t.cutters.append(c) print '\t%i remaining' % totcuts totcuts -= 1 # SELECT INTERNAL FACES ONCE THIS TERRAIN IS CUT Blender.Mesh.Mode(Blender.Mesh.SelectModes['FACE']) t.mesh.sel = 0 for c in t.cutters: edge_verts_c = [(ed_c.v1.co, ed_c.v2.co) for ed_c in c.mesh.edges] for f in t.mesh.faces: # How many edges do we intersect on our way to the faces center if not f.hide and not f.sel: # Not alredy selected c = f.cent if point_in_bounds(c, t.bounds): isect_count = 0 for edv1, edv2 in edge_verts_c: isect_count += (LineIntersect2D( c, crazy_point, edv1, edv2) != None) if isect_count % 2: f.sel = 1 Blender.Mesh.Mode(Blender.Mesh.SelectModes['FACE']) # Restore the transformation for data in (terrains, cutters): for t in data: if t.mesh.users: # it may have been a temp mesh from a curve. t.mesh.transform(t.matrix.copy().invert()) Blender.Window.WaitCursor(0) if MULTIRES_ERROR: Blender.Draw.PupMenu( 'Error%t|One or more meshes meshes not cut because they are multires.' ) print 'terrains:%i cutters %i %.2f secs taken' % ( len(terrains), len(cutters), Blender.sys.time() - time)
def write(filename, objects,\ EXPORT_APPLY_MODIFIERS=True, EXPORT_ROTX90=True): ''' Basic write function. The context and options must be alredy set This can be accessed externaly eg. write( 'c:\\test\\foobar.obj', Blender.Object.GetSelected() ) # Using default options. ''' def veckey3d(v): return round(v.x, 6), round(v.y, 6), round(v.z, 6) def veckey2d(v): return round(v.x, 6), round(v.y, 6) print 'EOL MESH Export path: "%s"' % filename temp_mesh_name = '~tmp-mesh' time1 = sys.time() scn = Scene.GetCurrent() file = open(filename, "w") # Write Header file.write('# Blender3D v%s EOL MESH File: %s\n' % (Blender.Get('version'), Blender.Get('filename').split('/')[-1].split('\\')[-1] )) file.write('# www.blender3d.org\n') # Get the container mesh. - used for applying modifiers and non mesh objects. containerMesh = meshName = tempMesh = None for meshName in Blender.NMesh.GetNames(): if meshName.startswith(temp_mesh_name): tempMesh = Mesh.Get(meshName) if not tempMesh.users: containerMesh = tempMesh if not containerMesh: containerMesh = Mesh.New(temp_mesh_name) if EXPORT_ROTX90: mat_xrot90= Blender.Mathutils.RotationMatrix(-90, 4, 'x') del meshName del tempMesh # Initialize totals, these are updated each object totverts = totuvco = totno = 1 face_vert_index = 1 globalNormals = {} # Get all meshs for ob_main in objects: for ob, ob_mat in BPyObject.getDerivedObjects(ob_main): # Will work for non meshes now! :) # getMeshFromObject(ob, container_mesh=None, apply_modifiers=True, vgroups=True, scn=None) me= BPyMesh.getMeshFromObject(ob, containerMesh, EXPORT_APPLY_MODIFIERS, False, scn) if not me: continue faceuv= me.faceUV has_quads = False for f in me.faces: if len(f) == 4: has_quads = True break if has_quads: oldmode = Mesh.Mode() Mesh.Mode(Mesh.SelectModes['FACE']) me.sel = True tempob = scn.objects.new(me) me.quadToTriangle(0) # more=0 shortest length oldmode = Mesh.Mode(oldmode) scn.objects.unlink(tempob) Mesh.Mode(oldmode) edges = me.edges faces = [ f for f in me.faces ] if EXPORT_ROTX90: me.transform(ob_mat*mat_xrot90) else: me.transform(ob_mat) # Vert mesh = ob.getData() objmat = ob.getMatrix() for i in objmat: file.write('obm: %.6f %.6f %.6f %.6f\n' % tuple(i)) vgrouplist = mesh.getVertGroupNames() file.write('vgroupcount: %i\n' % len(vgrouplist)) for vgname in vgrouplist: file.write('vgroup: %s\n' % vgname) file.write('vertexcount: %i\n' % len(mesh.verts)) for v in mesh.verts: file.write('v %.6f %.6f %.6f\n' % tuple(v.co)) influences = mesh.getVertexInfluences(v.index) file.write('influence: %i\n' % len(influences)) for name,weight in influences: file.write('groupname: %s\n' % name) file.write('weight: %f\n' % weight) # UV if faceuv: uv_face_mapping = [[0,0,0,0] for f in faces] # a bit of a waste for tri's :/ uv_dict = {} # could use a set() here for f_index, f in enumerate(faces): for uv_index, uv in enumerate(f.uv): uvkey = veckey2d(uv) try: uv_face_mapping[f_index][uv_index] = uv_dict[uvkey] except: uv_face_mapping[f_index][uv_index] = uv_dict[uvkey] = len(uv_dict) file.write('vt %.6f %.6f\n' % tuple(uv)) uv_unique_count = len(uv_dict) del uv, uvkey, uv_dict, f_index, uv_index # Only need uv_unique_count and uv_face_mapping file.write('uvcount: %i\n' % uv_unique_count) # NORMAL, Smooth/Non smoothed. for f in faces: if f.smooth: for v in f: noKey = veckey3d(v.no) if not globalNormals.has_key( noKey ): globalNormals[noKey] = totno totno +=1 file.write('vn %.6f %.6f %.6f\n' % noKey) else: # Hard, 1 normal from the face. noKey = veckey3d(f.no) if not globalNormals.has_key( noKey ): globalNormals[noKey] = totno totno +=1 file.write('vn %.6f %.6f %.6f\n' % noKey) file.write('normalcount: %i\n' % len(globalNormals)) if not faceuv: f_image = None file.write('facecount: %i\n' % len(faces)) for f_index, f in enumerate(faces): f_v= f.v f_smooth= f.smooth if faceuv: f_uv= f.uv file.write('f') if faceuv: if f_smooth: # Smoothed, use vertex normals for vi, v in enumerate(f_v): file.write( ' %d/%d/%d' % (\ v.index+totverts,\ totuvco + uv_face_mapping[f_index][vi],\ globalNormals[ veckey3d(v.no) ])) # vert, uv, normal else: # No smoothing, face normals no = globalNormals[ veckey3d(f.no) ] for vi, v in enumerate(f_v): file.write( ' %d/%d/%d' % (\ v.index+totverts,\ totuvco + uv_face_mapping[f_index][vi],\ no)) # vert, uv, normal face_vert_index += len(f_v) else: # No UV's if f_smooth: # Smoothed, use vertex normals for v in f_v: file.write( ' %d//%d' % (\ v.index+totverts,\ globalNormals[ veckey3d(v.no) ])) else: # No smoothing, face normals no = globalNormals[ veckey3d(f.no) ] for v in f_v: file.write( ' %d//%d' % (\ v.index+totverts,\ no)) file.write('\n') # Write edges. LOOSE= Mesh.EdgeFlags.LOOSE for ed in edges: if ed.flag & LOOSE: file.write('f %d %d\n' % (ed.v1.index+totverts, ed.v2.index+totverts)) # Make the indicies global rather then per mesh totverts += len(me.verts) if faceuv: totuvco += uv_unique_count me.verts= None file.close() # Now we have all our materials, save them print "MESH Export time: %.2f" % (sys.time() - time1)