import os def stl_to_gltf(binary_stl_path, out_path, is_binary): import struct gltf2 = ''' { "scenes" : [ { "nodes" : [ 0 ] } ], "nodes" : [ { "mesh" : 0 } ], "meshes" : [ { "primitives" : [ { "attributes" : { "POSITION" : 1 }, "indices" : 0 } ] } ], "buffers" : [ { %s "byteLength" : %d } ], "bufferViews" : [ { "buffer" : 0, "byteOffset" : 0, "byteLength" : %d, "target" : 34963 }, { "buffer" : 0, "byteOffset" : %d, "byteLength" : %d, "target" : 34962 } ], "accessors" : [ { "bufferView" : 0, "byteOffset" : 0, "componentType" : 5125, "count" : %d, "type" : "SCALAR", "max" : [ %d ], "min" : [ 0 ] }, { "bufferView" : 1, "byteOffset" : 0, "componentType" : 5126, "count" : %d, "type" : "VEC3", "min" : [%f, %f, %f], "max" : [%f, %f, %f] } ], "asset" : { "version" : "2.0" } } ''' header_bytes = 80 unsigned_long_int_bytes = 4 float_bytes = 4 vec3_bytes = 4 * 3 spacer_bytes = 2 num_vertices_in_face = 3 vertices = {} indices = [] if not is_binary: out_bin = os.path.join(out_path, "out.bin") out_gltf = os.path.join(out_path, "out.gltf") else: out_bin = out_path unpack_face = struct.Struct("<12fH").unpack face_bytes = float_bytes*12 + 2 with open(path_to_stl, "rb") as f: f.seek(header_bytes) # skip 80 bytes headers num_faces_bytes = f.read(unsigned_long_int_bytes) number_faces = struct.unpack(" maxx: maxx = x if y < miny: miny = y if y > maxy: maxy = y if z < minz: minz = z if z > maxz: maxz = z # f.seek(spacer_bytes, 1) # skip the spacer number_vertices = len(vertices) vertices_bytelength = number_vertices * vec3_bytes # each vec3 has 3 floats, each float is 4 bytes unpadded_indices_bytelength = number_vertices * unsigned_long_int_bytes out_number_vertices = len(vertices) out_number_indices = len(indices) unpadded_indices_bytelength = out_number_indices * unsigned_long_int_bytes indices_bytelength = (unpadded_indices_bytelength + 3) & ~3 out_bin_bytelength = vertices_bytelength + indices_bytelength if is_binary: out_bin_uir = "" else: out_bin_uir = '"uri": "out.bin",' gltf2 = gltf2 % ( out_bin_uir, #buffer out_bin_bytelength, # bufferViews[0] indices_bytelength, # bufferViews[1] indices_bytelength, vertices_bytelength, # accessors[0] out_number_indices, out_number_vertices - 1, # accessors[1] out_number_vertices, minx, miny, minz, maxx, maxy, maxz ) glb_out = bytearray() if is_binary: gltf2 = gltf2.replace(" ", "") gltf2 = gltf2.replace("\n", "") scene = bytearray(gltf2.encode()) scene_len = len(scene) padded_scene_len = (scene_len + 3) & ~3 body_offset = padded_scene_len + 12 + 8 file_len = body_offset + out_bin_bytelength + 8 # 12-byte header glb_out.extend(struct.pack(' 3: is_binary = True else: is_binary = False if out_path.lower().endswith(".glb"): print("Use binary mode since output file has glb extension") is_binary = True else: if is_binary: print("output file should have glb extension but not %s", out_path) if not os.path.exists(path_to_stl): print("stl file does not exists %s" % path_to_stl) if not is_binary: if not os.path.isdir(out_path): os.mkdir(out_path) stl_to_gltf(path_to_stl, out_path, is_binary)