Skip to content

Instantly share code, notes, and snippets.

@milasudril
Created February 13, 2021 14:22
Show Gist options
  • Save milasudril/e31e2c9fe91a99f5becaa1d624b1e115 to your computer and use it in GitHub Desktop.
Save milasudril/e31e2c9fe91a99f5becaa1d624b1e115 to your computer and use it in GitHub Desktop.
Helper for exporting blender meshes
import bmesh
import bpy
import json
def debug_print(data):
for window in bpy.context.window_manager.windows:
screen = window.screen
for area in screen.areas:
if area.type == 'CONSOLE':
override = {'window': window, 'screen': screen, 'area': area}
bpy.ops.console.scrollback_append(override, text=str(data), type="OUTPUT")
def collect_meshes(collection):
meshes = []
depsgraph = bpy.context.evaluated_depsgraph_get()
for object in collection:
if object.type == 'MESH':
object_eval = object.evaluated_get(depsgraph)
tmp = object.copy()
tmp.data = object_eval.data.copy()
meshes.append(tmp)
return meshes
def join_meshes(mesh_array):
if len(mesh_array) > 1:
context = bpy.context.copy()
context['active_object'] = mesh_array[0]
context['selected_editable_objects'] = mesh_array
bpy.ops.object.join(context)
return context['active_object']
else:
return mesh_array[0]
def triangulate(mesh):
bm = bmesh.new()
bm.from_mesh(mesh)
bmesh.ops.triangulate(bm, faces = bm.faces[:])
bm.to_mesh(mesh)
def get_verts(mesh):
verts = []
for v in mesh.vertices:
verts.extend([v.co.x, v.co.y, v.co.z, 1.0])
return verts
def get_normals(mesh):
normals = []
for v in mesh.vertices:
normals.extend([v.normal.x, v.normal.y, v.normal.z, 0.0])
return normals
def get_faces(mesh):
faces = []
for f in mesh.polygons:
if len(f.vertices) > 3:
raise(Exception('Mesh must be triangulated'))
for v in f.vertices:
faces.append(v)
faces.append(f.material_index)
return faces
def get_uvs(mesh):
if mesh.uv_layers.active is None:
raise(Exception('No acttive uv layer'))
uvs = []
uvs_dict = dict()
for f in mesh.polygons:
if not f.use_smooth:
raise(Exception('At least one face use non-smooth shadig'))
for vert, loop in zip(f.vertices, f.loop_indices):
uvs_dict[vert] = mesh.uv_layers.active.data[loop].uv
for key, value in sorted(uvs_dict.items()):
uvs.extend([value.x, value.y])
return uvs
def get_materials(obj):
materials = []
for material in obj.material_slots:
if material is None:
raise(Exception('Empty material slot'))
materials.append(material.name)
return materials
def make_data_arrays(obj):
arrays = dict();
arrays['verts'] = get_verts(obj.data)
arrays['uvs'] = get_uvs(obj.data)
arrays['normals'] = get_normals(obj.data)
arrays['faces'] = get_faces(obj.data)
arrays['materials'] = get_materials(obj)
if len(arrays['verts']) % 4 != 0:
raise(Exception('Length of verts should be divisible by 4'))
if len(arrays['uvs']) % 2 != 0:
raise(Exception('Length of verts should be divisible by 2'))
if len(arrays['verts'])/4 != len(arrays['uvs'])/2:
raise(Exception('uv/vertex count mismatch %d vs %d'%(len(arrays['uvs'])/2, len(arrays['verts'])/4)))
return arrays
class MeshCopy:
def __init__(self, mesh):
self.__mesh = mesh
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
self.__mesh.user_clear()
bpy.data.objects.remove(self.__mesh)
def get(self):
return self.__mesh
meshes = collect_meshes(bpy.context.collection.objects)
with MeshCopy(join_meshes(meshes)) as obj:
triangulate(obj.get().data)
arrays = make_data_arrays(obj.get())
print(json.dumps(arrays))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment