Below is a script I wrote to export models from blender into a *.h file that contains two static GLfloat arrays. It requires that the model be already triangulated in Blender (maybe later I’ll add code to go ahead and triangulate the mesh if it needs it… oh yeah, and to manually triangulate a mesh in Blender’s edit mode hit ‘Ctrl+T’) and that the mesh already have UV texture coordinates. Also, it only uses GL_TRIANGLES mode right now. Later I am going to update it to use GL_TRIANGLE_STRIPS instead of GL_TRIANGLES. Finally it doesn’t apply Object rotations and scale. You should apply them in Object Mode Transform->Clear/Apply->Apply Scale/Rotation (or Ctrl+A).

Note: Just in case you didn’t catch it above the mesh you are exporting needs to be triangulated (via ‘Ctrl+T’) and have UV texture coordinates (in UV Face Select mode hit ‘U’ and choose some sort of UV unwrapping, if it doesn’t the script will crash instead of exiting gracefully).

To install this python script save it to the /.blender/scripts/ directory (on Mac OS X this is Blender.app/Contents/MacOS/.blender/scripts/). I called it export_objc.py. Also, if you make any modifications to the script, (say add some logic to only add UV texturing if it has been set, or to automatically triangulate the mesh please let me know, I’d love to update this code).

#!BPY

"""
Name: 'OpenGL ES/ObjC export (.h)...'
Blender: 245
Group: 'Export'
Tooltip: 'Export selected mesh to an OpenGL|ES ObjC static array (*.h)'
"""

__author__ = "John Bowers (quadelirus)"
__url__ = ("blender", "Author's homepage, http://www.espressosoft.com")
__version__ = "1.0"

__bpydoc__ = """\
This script exports meshes into two static GLfloat arrays
that can be used to render the model in an OpenGL|ES application.

I designed it as a helper script for some code I am writing for the
iPhone.
"""

# $Id:
#
# Copyright (c) 2008 John Bowers
# http://www.espressosoft.com
# July 13, 2008

# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****

import Blender
import BPyMessages

def write_header(filename):
     file = open(filename, 'wb')
     scn = Blender.Scene.GetCurrent()
     object = scn.objects.active
     if not object or object.type != 'Mesh':
          BPyMessages.Error_NoMeshActive()
          return
     mesh = object.getData(mesh=1)
     file.write("/*********************************************************\n")
     file.write(" * Exported using the ObjC exporter from espressoSoft.com\n")
     file.write(" * Written by: John Bowers\n")
     file.write(" * \n")
     file.write(" * Model: " + object.name)
     file.write("********************************************************/\n")
     #write the faces:
     file.write("static GLfloat " + object.name + "_vertData[] = {\n”)
     for face in mesh.faces:
          file.write(”\t” + str(face.verts[0].co.x) + “, ” + str(face.verts[0].co.y) + “, ” + str(face.verts[0].co.z) + “, “)
          file.write(str(face.verts[1].co.x) + “, ” + str(face.verts[1].co.y) + “, ” + str(face.verts[1].co.z) + “, “)
          file.write(str(face.verts[2].co.x) + “, ” + str(face.verts[2].co.y) + “, ” + str(face.verts[2].co.z) + “,\n”)
     file.write(”};\n”)
     file.write(”static GLfloat ” + object.name + “_texData[] = {\n”)
     for face in mesh.faces:
          file.write(”\t” + str(face.uv[0][0]) + “, ” + str(face.uv[0][1]) + “, “)
          file.write(str(face.uv[1][0]) + “, ” + str(face.uv[1][1]) + “, “)
          file.write(str(face.uv[2][0]) + “, ” + str(face.uv[2][1]) + “,\n”)
     file.write(”};\n”)
     file.write(”int ” + object.name + “_facesCount = ” + str(len(mesh.faces)) + “;\n”)
     file.close()

def fs_callback(filename):
     if not filename.lower().endswith(’.h’): filename += ‘.h’
     write_header(filename)

Blender.Window.FileSelector(fs_callback, “Export ObjC *.h File”, Blender.sys.makename(ext=’.h’))

Posted on July 14th, 2008 | filed under blender, code:: | Trackback |

24 Comments

  1. Ben Smith:

    Hey, thanks for the script. I too am using it for iPhone/iPod touch programming. I added another for loop to export normals. That way I can use models before I have textured them. I’m also thinking about writing some functions that will load 3D objects without having them included as .h files. The format could be something easily loaded w/ cocoa (plist or similar) and all of the arrays and any useful data could be stored in the structure, even data such as the object’s location and rotation in whatever world is being built. It would end up with some object being the 3d object with subarrays:

    object.verts
    object.norms
    object.uv
    object.textureName
    object.co
    object.rot

    I’d love to hear back from you,
    Ben Smith

  2. tim:

    Thanks for the helpful script. I added normals output too. I don’t particularly like python cause of the indention syntax. This code may be useful to others:

    file.write(”static GLfloat ” + object.name + “_normData[] = {\n”)
    for face in mesh.faces:
    file.write(”\t” + str(face.verts[0].no.x) + “, ” + str(face.verts[0].no.y) + “, ” + str(face.verts[0].no.z) + “, “)
    file.write(str(face.verts[1].no.x) + “, ” + str(face.verts[1].no.y) + “, ” + str(face.verts[1].no.z) + “, “)
    file.write(str(face.verts[2].no.x) + “, ” + str(face.verts[2].no.y) + “, ” + str(face.verts[2].no.z) + “,\n”)
    file.write(”};\n”)

  3. admin:

    @tim

    Awesome! Definitely a necessary addition to the script. I’m learning OpenGL as I go and surface normals are a must have for the lighting effects.

  4. pete:

    This exporter is great, but I think i’m doing something wrong. How are you guys displaying the models once exported? Mine have all kinds of holes in them, especially if i add normals(you can see the triangles appear and dissappear as the object rotates)…

  5. admin:

    @pete

    Did you triangulate your mesh with CTRL+T? The script only works with triangular meshes, no square faces allowed!

  6. pete:

    that fixed it… Thanks, this is a lifesaver.

  7. tim:

    To cut back on the floating pt precision you could (python’s version of sprintf):

    file.write(”\t” + ‘%.6f’ % face.verts[0].co.x + “, ” + ‘%.6f’ % face.verts[0].co.y + “, ” + ‘%.6f’ % face.verts[0].co.z + “, “)
    file.write( ‘%.6f’ % face.verts[1].co.x + “, ” + ‘%.6f’ % face.verts[1].co.y + “, ” + ‘%.6f’ % face.verts[1].co.z + “, “)
    file.write( ‘%.6f’ % face.verts[2].co.x + “, ” + ‘%.6f’ % face.verts[2].co.y + “, ” + ‘%.6f’ % face.verts[2].co.z + “,\n”)

  8. N00bSC:

    Hi,

    Thank you all for this great script. I am a n00b to Blender (some Maya), but I think this will be very useful in Objective-C.

    One quick question, I am used to dealing with vertData array and indices array (drawing order). Again, I’m new to these concepts, but would anyone mind lending a little more explanation on implementing this script and using this vertices data using the glDrawElements() ? (I’m using indices array here. Am I missing a step?)

    Thanks for your time and knowledge

  9. Chris Griffin:

    I would love to here from Ben Smith if he was able to get the additions added he speaks about in his post. I’m very new to OpenGL and would also love some pointers on how to use the exported data. I can get the object to draw but don’t seem to know how to use the textures or what to do with the normals if I exported those as well.

  10. Keodark:

    Thanks for the script!

    I’m struggling with how to use the resulting arrays in OpenGL ES for iPhone - I’m using the vertex arrays generated by your script to replace the triangle strip cube in the default OpenGL ES project in XCode… but all I ever see on the simulator is a single triangle. Could you post some sample Objective C code showing how to use a blender-exported vertex array in GL_TRIANGLES mode?

  11. Mike:

    Hello,

    can you please write the acutal version of the export_objc.py file. I always receive an error while exporting.

    Did you have any example code to import the data to an iPhone or iPod simulator.

    Thanks a lot
    Mike

  12. Ron:

    Any chance you could post some example code that’s being used to draw the arrays of vert and texture pointers ?

  13. admin:

    @Ron

    Yes, I will write a post about how I do it and post it on the site. Sorry for the delay.

    @Mike

    What error do you receive? Python is white space sensitive and uses tabs to separate code blocks which aren’t translated via a copy/paste from this website. I will see about uploading a downloadable version of the script. My current problem is that I’m in Africa for 6 mos. and net access is spotty at best.

  14. admin:

    @Keodark,

    http://espressosoft.com/wordpress/?p=27

    I promise a more in depth treatment soon. I’m very busy at the moment and seeing as how accessing my website takes around 20 minutes (it feels like) I’m not doing it so often at the moment. I’ll work on it as I get settled in here in Uganda.

  15. Benji:

    I get this error when I try to export a triangled modle from blender with that script installed…any ideas/

    11/1/08 2:40:38 PM [0x0-0x1be1be].org.blenderfoundation.blender[10204] /Applications/blender/blender.app/Contents/MacOS/blender:1: DeprecationWarning: Non-ASCII character ‘\xe2′ in file /Applications/blender/blender.app/Contents/MacOS/.blender/scripts/export_objc.py on line 64, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details
    11/1/08 2:40:38 PM [0x0-0x1be1be].org.blenderfoundation.blender[10204] �?�?
    11/1/08 2:40:38 PM [0x0-0x1be1be].org.blenderfoundation.blender[10204] Compiled with Python version 2.3.5.
    11/1/08 2:40:38 PM [0x0-0x1be1be].org.blenderfoundation.blender[10204] Checking for installed Python… got it!
    11/1/08 2:40:38 PM [0x0-0x1be1be].org.blenderfoundation.blender[10204] Traceback (most recent call last):
    11/1/08 2:40:38 PM [0x0-0x1be1be].org.blenderfoundation.blender[10204] File “”, line 1, in ?
    11/1/08 2:40:38 PM [0x0-0x1be1be].org.blenderfoundation.blender[10204] File “/Applications/blender/blender.app/Contents/MacOS/.blender/scripts/export_objc.py”, line 64
    11/1/08 2:40:38 PM [0x0-0x1be1be].org.blenderfoundation.blender[10204] file.write(”static GLfloat ” + object.name + “_vertData[] = {\n”)
    11/1/08 2:40:38 PM [0x0-0x1be1be].org.blenderfoundation.blender[10204]
    11/1/08 2:40:38 PM [0x0-0x1be1be].org.blenderfoundation.blender[10204]
    11/1/08 2:40:38 PM [0x0-0x1be1be].org.blenderfoundation.blender[10204] ^

  16. Benji:

    sorry one last bit:

    11/1/08 2:40:38 PM [0x0-0x1be1be].org.blenderfoundation.blender[10204] SyntaxError: EOL while scanning single-quoted string

    Im a noob :)

  17. Benji:

    ah so I figured out my problem with the above code:

    If you copy and paste the code sometimes has weird quotes and apostrophes. I had to find replace all of them to be ‘ or ” not the weird curly ones.

  18. Tim Ocock:

    We’ve modified the script to also export all parts of the scene as separate headers. We can post it here and also would be happy to host a downloadable version (no more Python indentation encoding issues!) with your permission and permission of other contributors.

  19. admin:

    @Tim

    Fantastic! Send me a link =D

  20. Cesare:

    Hi,
    thanks for this.

    But there’s a problem.

    The blender Y axis is equivalent to opengl Z and vice versa. You should switch them in your code. You will notice this if you add the code to export and render vertex normals. They are screwed up.

  21. Biosopher:

    I wanted to pass on this link to everyone. I had been looking for a Blender to OpenGL converter for the iPhone and came across this blog:

    Wavefront OBJ Loader
    http://iphonedevelopment.blogspot.com/2008/12/wavefront-obj-loader-another-update.html

    This guy, Jeff Lamarche, is taking the approach of creating a utility to import a Wavefront OBJ file (you can get this from Blender by doing a simple export as a Wavefront OBJ file).

    He’s gotten pretty far with importing OBJ files and running them on the iPhone.

    Check it out.

    Anthony

  22. Tim:

    We’re in the process of adding a blog section to our website. In the meantime, you can find the page here http://www.symsource.com/index.php?option=com_wordpress - please let me know if the attribution and presentation is acceptable to you before we go live to the general public.

  23. Niels:

    Is there a direct link to the export_objc.py file somewhere?
    Had to find/replace some of the quotes for it to be able to run, but I still think I missed something, as it still gives errors. (I converted the quads to triangles already using ctrl-T)

    What I got up to this point is this:
    ###########################################################################

    #!BPY

    “”"
    Name: ‘OpenGL ES/ObjC export (.h)…’
    Blender: 245
    Group: ‘Export’
    Tooltip: ‘Export selected mesh to an OpenGL|ES ObjC static array (*.h)’
    “”"

    __author__ = “John Bowers (quadelirus)”
    __url__ = (”blender”, “Author’s homepage, http://www.espressosoft.com“)
    __version__ = “1.0″

    __bpydoc__ = “”"\
    This script exports meshes into two static GLfloat arrays
    that can be used to render the model in an OpenGL|ES application.

    I designed it as a helper script for some code I am writing for the
    iPhone.
    “”"

    # $Id:
    #
    # Copyright (c) 2008 John Bowers
    # http://www.espressosoft.com
    # July 13, 2008

    # ***** BEGIN GPL LICENSE BLOCK *****
    #
    # This program is free software; you can redistribute it and/or
    # modify it under the terms of the GNU General Public License
    # as published by the Free Software Foundation; either version 2
    # of the License, or (at your option) any later version.
    #
    # This program is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    # GNU General Public License for more details.
    #
    # You should have received a copy of the GNU General Public License
    # along with this program; if not, write to the Free Software Foundation,
    # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    #
    # ***** END GPL LICENCE BLOCK *****

    import Blender
    import BPyMessages

    def write_header(filename):
    file = open(filename, ‘wb’)
    scn = Blender.Scene.GetCurrent()
    object = scn.objects.active
    if not object or object.type != ‘Mesh’:
    BPyMessages.Error_NoMeshActive()
    return
    mesh = object.getData(mesh=1)
    file.write(”/*********************************************************\n”)
    file.write(” * Exported using the ObjC exporter from espressoSoft.com\n”)
    file.write(” * Written by: John Bowers\n”)
    file.write(” * \n”)
    file.write(” * Model: ” + object.name)
    file.write(”********************************************************/\n”)
    #write the faces:
    file.write(”static GLfloat ” + object.name + “_vertData[] = {\n”)
    for face in mesh.faces:
    file.write(”\t” + str(face.verts[0].co.x) + “, ” + str(face.verts[0].co.y) + “, ” + str(face.verts[0].co.z) + “, “)
    file.write(str(face.verts[1].co.x) + “, ” + str(face.verts[1].co.y) + “, ” + str(face.verts[1].co.z) + “, “)
    file.write(str(face.verts[2].co.x) + “, ” + str(face.verts[2].co.y) + “, ” + str(face.verts[2].co.z) + “,\n”)
    file.write(”};\n”)
    file.write(”static GLfloat ” + object.name + “_texData[] = {\n”)
    for face in mesh.faces:
    file.write(”\t” + str(face.uv[0][0]) + “, ” + str(face.uv[0][1]) + “, “)
    file.write(str(face.uv[1][0]) + “, ” + str(face.uv[1][1]) + “, “)
    file.write(str(face.uv[2][0]) + “, ” + str(face.uv[2][1]) + “,\n”)
    file.write(”};\n”)
    file.write(”int ” + object.name + “_facesCount = ” + str(len(mesh.faces)) + “;\n”)
    file.close()

    def fs_callback(filename):
    if not filename.lower().endswith(’.h’): filename += ‘.h’
    write_header(filename)

    Blender.Window.FileSelector(fs_callback, “Export ObjC *.h File”, Blender.sys.makename(ext=’.h’))

    ###############################################################################

    Console error output is this:
    ##############################################################################

    25-02-09 14:44:41 [0x0-0x69069].org.blenderfoundation.blender[1664] file.write(”\t” + str(face.uv[0][0]) + “, ” + str(face.uv[0][1]) + “, “)
    25-02-09 14:44:41 [0x0-0x69069].org.blenderfoundation.blender[1664] ValueError
    25-02-09 14:44:41 [0x0-0x69069].org.blenderfoundation.blender[1664] : face has no texture values
    25-02-09 14:45:28 [0x0-0x69069].org.blenderfoundation.blender[1664] Traceback (most recent call last):
    25-02-09 14:45:28 [0x0-0x69069].org.blenderfoundation.blender[1664] File “/Applications/blender/blender.app/Contents/MacOS/.blender/scripts/export_objc.py”, line 81, in fs_callback
    25-02-09 14:45:28 [0x0-0x69069].org.blenderfoundation.blender[1664] write_header(filename)
    25-02-09 14:45:28 [0x0-0x69069].org.blenderfoundation.blender[1664] File “/Applications/blender/blender.app/Contents/MacOS/.blender/scripts/export_objc.py”, line 72, in write_header
    ######################################################################################

    I’m probably doing something really stupid in the syntax or something, as I’m not used to a python enviroment.

    Anybody here that can help me out? I want to export an icosahedron/cylinder/sphere model to use for making a 360 pano-tool.
    Isn’t that much to find concerning OPENGL_ES/EAGL development on the web.

    Any help would be appriciated, tnx upfront

  24. Anup Jayapal Rao:

    Hi,

    You might want to have a look at my exporter at

    http://renegadepixels.in/carmine.html

    It is an add-on that generates C/C++ compliant structures that can be used with the provided rendering code to display 3D objects modelled in Blender using OpenGL (or modified slightly to work with OpenGL 2.0 ES)

    This should ease OpenGL programming for beginners.

    Regards,
    Anup

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>