Skip to content

Instantly share code, notes, and snippets.

@kaadmy
Created August 20, 2018 18:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kaadmy/837e68112ae60005d74d80b2dc610e55 to your computer and use it in GitHub Desktop.
Save kaadmy/837e68112ae60005d74d80b2dc610e55 to your computer and use it in GitHub Desktop.
# Meshes are a big endian binary blob.
# Format:
# {header: "LMM"}
# [int:vertcount]
# ([float*3:position], [float*3:normal], [float*2:texcoord]) * vertcount
#
# Limitations:
# Max vertices: 2147483648
# Vertex count MUST be a multiple of 3, may cause fatal errors otherwise
# Imports
import bpy
import bpy.props
from bpy_extras.io_utils import ExportHelper
import bmesh
import mathutils
import os
import struct
import time
# Constants
MODEL_HEADER = "LMM001" # Must be 6 characters long
# Addon info
bl_info = {
"name": "LMM model exporter",
"author": "KaadmY",
"version": (0, 1, 0),
"blender": (2, 79, 0),
"location": "File > Import-Export",
"description": "Export LMM model",
"warning": "Expect stability issues",
"category": "Import-Export"
}
# Generate a triangulated mesh
def mesh_triangulate(me):
bm = bmesh.new()
bm.from_mesh(me)
bmesh.ops.triangulate(bm, faces=bm.faces)
bm.to_mesh(me)
bm.free()
# Export mesh object
def export_mesh(scene, obj):
# Temporary triangulated mesh
mesh = obj.to_mesh(scene, True, "PREVIEW", calc_tessface = False)
mesh_triangulate(mesh)
# Make a copy of the vertex array
vertices = mesh.vertices[:]
# Reformat texture coordinate list
texcoords = None
if mesh.uv_layers.active != None:
texcoords = mesh.uv_layers.active.data[:]
out_vertices = []
# Write vertices
for poly in mesh.polygons:
uv = []
if texcoords == None: # Fallback if no valid UV layers are present
uv = [mathutils.Vector((0.0, 0.0)), mathutils.Vector((0.0, 0.0)), mathutils.Vector((0.0, 0.0))]
else:
for _, i in enumerate(poly.loop_indices):
uv.append(texcoords[i].uv)
# Write all 3 vertices of the triangle
for i in range(3):
co = vertices[poly.vertices[i]].co
co2 = mathutils.Vector((co.x, co.y, co.z)) # Can swizzle axes here if needed
out_vertices.append(struct.pack(">ffffffff", co2.x, co2.y, co2.z, *vertices[poly.vertices[i]].normal, *uv[i]))
# Remove temp mesh
bpy.data.meshes.remove(mesh)
# Export stats
print("Vertex count: %d" % len(out_vertices))
# Return value
return struct.pack(">i", len(out_vertices)) + bytes().join(out_vertices)
# Export all objects, if applicable
def export(context, options):
time_start = time.time()
file = open(options["filepath"], "wb")
# Header
out = bytes(MODEL_HEADER, "utf-8")
# Export selectede mesh
if context.active_object.type == "MESH":
out += export_mesh(context.scene, context.active_object)
else:
raise ValueError("Active object not a mesh")
# Write out
file.write(out)
file.close()
# Export stats
print("Export took a total of %0.4f seconds" % (time.time() - time_start))
# Primary export class
class ExportLMM(bpy.types.Operator, ExportHelper):
"""Export LMM mesh"""
bl_idname = "export_object.lmm"
bl_label = "Export LMM model"
bl_options = {"PRESET"}
filename_ext = ".lmm"
filter_glob = bpy.props.StringProperty(
default = "*.lmm",
options = {"HIDDEN"},
)
def execute(self, context):
export(context, self.as_keywords())
return {"FINISHED"}
# Export callbacks
def menu_func_export(self, context):
self.layout.operator(ExportLMM.bl_idname, text = "Lux Minima model (.lmm)")
def register():
bpy.utils.register_module(__name__)
bpy.types.INFO_MT_file_export.append(menu_func_export)
def unregister():
bpy.utils.unregister_module(__name__)
bpy.types.INFO_MT_file_export.remove(menu_func_export)
# Register addon
if __name__ == "__main__":
register()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment