Last active
December 23, 2021 21:15
-
-
Save blm768/6059892 to your computer and use it in GitHub Desktop.
A Blender mesh export script for the game Oolite
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!BPY | |
""" | |
Name 'Oolite DAT' | |
Blender: 263 | |
Group: 'Export' | |
Tooltip 'Oolite mesh exporter' | |
""" | |
bl_info = { | |
"name": "Oolite (.dat)", | |
"author": "Ben Merritt", | |
"blender": (2,6,3), | |
"version": (0,0,1), | |
"location": "File > Import-Export", | |
"description": "Exports the selected mesh to an Oolite .dat file", | |
"category": "Import-Export", | |
} | |
import os.path | |
#from types import * | |
import bpy | |
import mathutils | |
def convertCoords(vec): | |
return mathutils.Vector((vec.x, vec.z, -vec.y)) | |
def formatVector(vec): | |
return "{},{},{}".format(vec.x, vec.y, vec.z) | |
def formatTex(tc): | |
return "{} {}".format(vec.x, vec.y) | |
def write(filename): | |
object = bpy.context.active_object | |
if object.type != "MESH": | |
raise Exception("Invalid active object; must be a mesh") | |
#Apply modifiers. | |
mesh = object.to_mesh(bpy.context.scene, True, "PREVIEW") | |
#Write mesh data. | |
verts = [] | |
normals = [] | |
writtenSmoothVerts = {} | |
vertsOut = [] | |
normsOut = [] | |
facesOut = [] | |
uvsOut = [] | |
for v in mesh.vertices: | |
verts.append(convertCoords(v.co)) | |
normals.append(convertCoords(v.normal)) | |
uvs = None | |
if len(mesh.tessface_uv_textures) > 0: | |
uvs = mesh.tessface_uv_textures[0] | |
for face in mesh.tessfaces: | |
faceOut = [] | |
texName = None | |
if uvs is not None: | |
texName = os.path.basename(uvs.data[face.index].image.filepath) | |
if texName is None: | |
raise Exception("Face with missing texture") | |
def writeTri(vertexNumbers): | |
triOut = ",".join((str(faceOut[vn]) for vn in vertexNumbers)) | |
facesOut.append("0,0,0 {} 3,{}\n".format(formatVector(convertCoords(face.normal)), triOut)) | |
if uvs is not None: | |
faceUvs = uvs.data[face.index].uv | |
uvOut = " ".join(",".join((str(val) for val in (faceUvs[vn]))) for vn in vertexNumbers) | |
uvsOut.append("{} 1.0,1.0 {}\n".format(texName, uvOut)) | |
for v in face.vertices: | |
vOut = None | |
if(face.use_smooth): | |
if v in writtenSmoothVerts: | |
vOut = writtenSmoothVerts[v] | |
else: | |
vOut = len(vertsOut) | |
writtenSmoothVerts[v] = vOut | |
vertsOut.append(formatVector(verts[v]) + "\n") | |
normsOut.append(formatVector(normals[v]) + "\n") | |
else: | |
vOut = len(vertsOut) | |
vertsOut.append(formatVector(verts[v]) + "\n") | |
normsOut.append(formatVector(convertCoords(face.normal)) + "\n") | |
faceOut.append(vOut) | |
writeTri(range(2, -1, -1)) | |
#If this is a quad, add another triangle to fill it out. | |
print(faceOut) | |
if len(faceOut) == 4: | |
writeTri([0, 3, 2]) | |
#Remove the temporary mesh. | |
bpy.data.meshes.remove(mesh) | |
out = open(filename, "w") | |
out.write("NVERTS %d\n" % len(vertsOut)) | |
out.write("NFACES %d\n" % len(facesOut)) | |
out.write("VERTEX\n") | |
out.writelines(vertsOut) | |
out.write("FACES\n") | |
out.writelines(facesOut) | |
if uvs is not None: | |
out.write("TEXTURES\n") | |
out.writelines(uvsOut) | |
out.write("NORMALS\n") | |
out.writelines(normsOut) | |
out.write("END\n") | |
out.close() | |
class Exporter(bpy.types.Operator): | |
"""Exporter for Oolite .dat meshes""" | |
bl_idname = "export.oolite_dat" | |
bl_label = "Export Oolite .dat mesh" | |
bl_options = {'PRESET'} | |
filename_ext = ".dat" | |
filepath = bpy.props.StringProperty(subtype="FILE_PATH") | |
@classmethod | |
def poll(cls, context): | |
return True | |
def execute(self, context): | |
write(self.filepath) | |
return {'FINISHED'} | |
def invoke(self, context, event): | |
context.window_manager.fileselect_add(self) | |
return {'RUNNING_MODAL'} | |
def menu_func(self, context): | |
self.layout.operator_context = 'INVOKE_DEFAULT' | |
self.layout.operator(Exporter.bl_idname, text="Oolite (.dat)") | |
def register(): | |
bpy.utils.register_class(Exporter) | |
bpy.types.INFO_MT_file_export.append(menu_func) | |
def unregister(): | |
bpy.utils.unregister_class(Exporter) | |
bpy.types.INFO_MT_file_export.remove(menu_func) | |
if __name__ == "__main__": | |
register() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Linked to Oolite Converters page on Oolite wiki http://wiki.alioth.net/index.php/Oolite_Converters