Blender Mesh Export Script
This vacation week was nice for me. Gained some knowledge from the community so tonight I'm giving back.
When I'm playing with my toy 3D frameworks, I like to have mesh data in an easy to read format. When I load, all I want to see are two integers at the start for how many vertices to read and how many face indices tightly follow, and do the bulk read. Easy fast data in engine side.
Generating that data I use Blender as my modeler of choice and this export file format has worked well. I'd like to share my custom export script supporting vertex position, texture coordinates and face indices as an export add-on. It's a nice jumping off point for your own custom export requirements. Currently it's sensitive to the object mode selection, triangulates mesh data, flips or not the v texture coordinate and writes optionally a binary or ascii format mesh file with a .geo file extension..
Use as you wish.
bl_info = {
"name": "Geo Format Exporter",
"description": "Writes geometry format to disk",
"author": "Mark Kughler (GoliathForgeOnline)",
"version": (1, 0),
"blender": (2, 79, 0),
"location": "File > Export > GEO",
"warning": "",
"wiki_url": "",
"tracker_url": "",
"support": 'COMMUNITY',
"category": "Import-Export"
}
import bpy
import bmesh
import struct #https://docs.python.org/3/library/struct.html
from bpy import context
def triangulateObject(obj):
me = obj.data
bm = bmesh.new()
bm.from_mesh(me)
bmesh.ops.triangulate(bm, faces=bm.faces[:], quad_method=0, ngon_method=0)
bm.to_mesh(me)
bm.free()
def writeObject(self, context):
ob = context.object
uv_layer = ob.data.uv_layers.active.data
vertBuff = []
uvBuff = []
faceBuff = []
#rebuild vertex, uv and face indices excluding duplicates
for poly in ob.data.polygons:
for index in poly.loop_indices:
thisVertex = ob.data.vertices[ob.data.loops[index].vertex_index].co
thisUV = uv_layer[index].uv
#check if already in the list
i = 0
found = 0
for v in vertBuff:
if(abs(v.x-thisVertex.x) <= max(1e-09 * max(abs(v.x), abs(thisVertex.x)), 0.0)):
if(abs(v.y-thisVertex.y) <= max(1e-09 * max(abs(v.y), abs(thisVertex.y)), 0.0)):
if(abs(v.z-thisVertex.z) <= max(1e-09 * max(abs(v.z), abs(thisVertex.z)), 0.0)):
if(abs(uvBuff[i].x-thisUV.x) <= max(1e-09 * max(abs(uvBuff[i].x), abs(thisUV.x)), 0.0)):
if(abs(uvBuff[i].y-thisUV.y) <= max(1e-09 * max(abs(uvBuff[i].y), abs(thisUV.y)), 0.0)):
faceBuff.append(int(i))
found = 1
break
i+=1
#otherwise stash a new vertex
if(found==0):
faceBuff.append(len(vertBuff)) #index
vertBuff.append(thisVertex) #float, float, float
uvBuff.append(thisUV) #float, float
#write to file
if(self.format == "OPT_A"):
with open(self.filepath, 'w') as ofile:
ofile.write("%d " % len(vertBuff)) #num unique vertex/uv pairs
ofile.write("%d " % len(faceBuff)) #num indices
for v in vertBuff:
ofile.write("%f %f %f " % v[:])
for t in uvBuff:
ofile.write("%f %f " % t[:])
for p in faceBuff:
ofile.write("%d " % p)
ofile.close()
return {'FINISHED'}
else:
with open(self.filepath, 'wb') as ofile:
ofile.write(struct.pack('H', len(vertBuff)))
ofile.write(struct.pack('H', len(faceBuff)))
for v in vertBuff:
ofile.write(struct.pack('3f', v.x, v.y, v.z)) #v[:])) #"%f %f %f " % v[:])
for t in uvBuff:
ofile.write(struct.pack('2f', t.x, t.y)) #t[:])) #"%f %f " % t[:])
for p in faceBuff:
ofile.write(struct.pack('H', p)) #"%d " % p)
ofile.close()
return {'FINISHED'}
class ObjectExport(bpy.types.Operator):
"""My object export script"""
bl_idname = "object.export_geo"
bl_label = "Geo Format Export"
bl_options = {'REGISTER', 'UNDO'}
filename_ext = ".geo"
total = bpy.props.IntProperty(name="Steps", default=2, min=1, max=100)
filter_glob = bpy.props.StringProperty(default="*.geo", options={'HIDDEN'}, maxlen=255)
use_setting = bpy.props.BoolProperty(name="Selected only", description="Export selected mesh items only", default=True)
use_triangulate = bpy.props.BoolProperty(name="Triangulate", description="Triangulate object", default=True)
format = bpy.props.EnumProperty(name="Format", description="Choose between two items", items=(('OPT_A', "ASCII ", "Text file format"), ('OPT_B', "Binary", "Binary file format")), default='OPT_A')
filepath = bpy.props.StringProperty(subtype='FILE_PATH')
def execute(self, context):
if(context.active_object.mode == 'EDIT'):
bpy.ops.object.mode_set(mode='OBJECT')
if(self.use_triangulate):
triangulateObject(context.active_object)
writeObject(self, context);
return {'FINISHED'}
def invoke(self, context, event):
context.window_manager.fileselect_add(self)
return {'RUNNING_MODAL'}
# Add trigger into a dynamic menu
def menu_func_export(self, context):
self.layout.operator(ObjectExport.bl_idname, text="Geometry Export (.geo)")
def register():
bpy.utils.register_class(ObjectExport)
bpy.types.INFO_MT_file_export.append(menu_func_export)
def unregister():
bpy.utils.unregister_class(ObjectExport)
bpy.types.INFO_MT_file_export.remove(menu_func_export)
if __name__ == "__main__":
register() Recommended resources
3D Art
3D Environment Design with Blender 5
Amazon · Book
Based on Blender 5, this updated second edition simplifies the complexities by guiding you through clear, practical workflows to overcome those challenges. You’ll start by addressing common modeling and proportion mistakes, then move on to realistic texturing and unwrapping to create stunning scenes based on actual references.
GameDev.net may earn a commission if you purchase through these links. This helps fund the site at no extra cost to you.
Low Poly 3D Modeling in Blender
Amazon · Book
Step into the world of low poly 3D art with Low Poly 3D Modeling in Blender—your entry point into Blender and mastering the fundamentals of 3D art. This beginner-friendly guide ensures that you’re fully prepared for the creative adventure that follows. Through a step-by-step learning process starting with the principles of low poly art, this book gradually immerses you in the intricacies of modeling. As you progress, you’ll gain hands-on experience creating diverse projects ranging from designing a simple 3D crate to rendering complete low poly scenes. The book covers a wide spectrum of topics as you navigate Blender's interface, mastering essential modeling tools and exploring both basic and advanced modeling techniques. Advancing to the final chapters, you’ll find ways to breathe life into your models with material creation and gain practical insights into modeling a variety of low poly objects. From end-to-end scene construction to configuring Blender for rendering high-quality images, you’ll be equipped with the foundational skills to propel your career in 3D modeling and explore the boundless creative possibilities that Blender offers. By the end of this book, you'll have a solid understanding of Blender, 3D modeling, low poly methodologies, material design, 3D rendering techniques, and the broader world of 3D art.
GameDev.net may earn a commission if you purchase through these links. This helps fund the site at no extra cost to you.
Discussion