Inspired by the idea behind iDevBlogADay I have decided to continue to blog more, as I enjoy writing and sharing useful (and not so useful) information.
Today I’m going to talk about adapting Blender for use in game development, specifically for exporting textured 3D models from Blender for use in our games.
I am assuming you know how to make Blender work and have created a mesh with a UV texture map. The problem you’re having specifically is getting that mesh out of Blender. You could of course use one of the built in exporters, but this way is more educational, also sometimes it is good to have control over the format your mesh data is stored in. The file described here is pretty basic, but hopefully this gives you enough working knowledge of Blender’s guts to use this as a springboard to create awesomer things. Another thing to take into consideration is that Blender and OpenGL use slightly different coordinate spaces, but it is not hard to work around.
Anyway, the language of choice for Blender is Python. If you like tabs, you will like Python. Much like how LISP was invented by parenthesis fetishists, I suspect that Guido van Rossum has a thing for tabs.
So, let’s get crackin’! Fire up your favorite text editor and do the following:
#!BPY """ Name: 'MyMeshExport' Blender: 248 Group: 'Export' Tooltip: 'Export a MyMesh File' """ import Blender import bpy
What this does is tells Blender that it’s a Blender Python script named “MyMeshExport”, runs on at least Blender 2.48 (you can change this as you see fit), and goes in the “Export” group. The imports hook into a bunch of Blender specific stuff including the scene.
Next, we’re going to specify the “write” function for the script. This is what is run automatically when you choose this script to export it.
def write(filename): out = file(filename, "w") sce = bpy.data.scenes.active ob = sce.objects.active mesh = ob.getData(mesh=1)
What this does is opens a file for writing, and hooks it to out, takes the currently active scene assigning it to sce, the currently active object and assigns it to ob, and then assigns the first mesh in ob to mesh. This assumes you have selected your object before you exported, and that object only has one mesh.
Next we’ll put in how many vertexes and faces there are in our mesh into the file. This will make life easier for our file loader:
out.write('%i Vertexes\n' % (len(mesh.verts))) out.write('%i Faces\n' % (len(mesh.faces)))
Next we insert vertex co-ordinates:
for vert in mesh.verts: out.write('v %f %f %f\n' % (vert.co.x, vert.co.y, vert.co.z))
This goes through each vertex in the mesh and inserts “v x y z” where x, y, and z represent the co-ordinates of the vertex.
Finally we write in information for each face in the mesh, including what vertexes make up the face, the vertex normals for that face, and the UV coordinates.
for face in mesh.faces: out.write('f') for vert in face.v: out.write(' %i' % (vert.index)) out.write('\n') out.write('n %f %f %f\n' %(face.no, face.no, face.no) out.write('n %f %f %f\n' %(face.no, face.no, face.no) out.write('n %f %f %f\n' %(face.no, face.no, face.no) for uv in face.uv: out.write('uv %f %f\n' % (uv, uv) out.close() Blender.Window.FileSelector(write, "Export")
This is where the per-polygon information is spat out into your file. For each face it outputs “f v1 v2 v3” where v1, v2, and v3 are the indexes of the vertexes we exported previously.
Next we output the normals. In this simple example we’re going to assign the face normals to each of the vertex normals. This is because whatever Blender thinks the “smooth” per-vertex normals are has no basis in reality what-so-ever. If you want to get smooth normals, you will have to compute them yourselves. The normals are encoded as “n fn1 fn2 fn3” on 3-separate lines (one per vertex) where fn1, fn2, and fn3 is the face normal.
Finally we output the UV coordinates of the texture map. For each vertex in the face we get “uv uv1 uv2” where uv1 and uv2 are the UV coordinates of that vertex.
The last line in the file tells Blender to open it’s File Selector window and call ‘write’.
Once you save your file with an imaginative name like ‘myfileexport.py’ you can copy it to wherever Python keeps its scripts. This is different under different platforms obviously, though you can get that information here, which incidentally I discovered after writing all this is practically identical to my post, except I cover exporting UV coordinates. Possibly because this is where I learned this over a year ago and subsequently forgot. Mea Culpa.
Anyway, let’s finish this up. So you’ve put your script into your scripts folder. Now you need to update the menus in Blender to tell it that it’s there. So you go to the Python pane and go to Scripts > Update Menus. Then you can go to your scene, select your object then go to File > Export > MyMeshExport to save your new mesh for inclusion in your game.