Home > OpenGL ES > Using 3D Models from Blender in OpenGL ES
Using 3D Models from Blender in OpenGL ES
Posted on Wednesday, June 24, 2009 by android apps market for tablests
One question I get asked a lot is "how do I load 3D models into OpenGL ES?".
Of course, the answer to that isn't a simple one. If you followed my my earlier posts on importing Wavefront OBJ files, you're probably aware of that already. There are many file formats, and none of them are ideal for loading into a resource-constrained device like the iPhone.
Apple recommends that 3D objects be stored in header files as static arrays. This obviates the need to do any loading or transforming or conversion at all. But� there's not really any easy way to create those header files from within 3D software packages.
Well, there is one way now. The open source 3D program called Blender has a very extensible architecture, making it relatively easy to write custom export modules. Blender's scripting architecture is based on Python, a language that I'm not particularly familiar with, but I hacked out something that works. So, let's say that you've got an object in Blender:

Click to see larger version
And you want to load it into a program you're writing for your iPhone:

Click to see larger version
Note, I know that the screenshots don't actually match - I cropped the texture after exporting from Blender to make it more iPhone sized - I didn't want to resize it for fear that the texture would get too small to see.
All you have to do is take this script and install it into the scripts folder in Blender.
There's a catch, however. The Mac OS X version of Blender doesn't follow the sames rules as it does for other platforms. If you look up how to install a script in Blender, it will tell you to add the script to ~/.blender/scripts/. That directory doesn't get created on the Mac, and if you manually create it, you will lose all the delivered scripts.
Instead, you have to actually install the script into the Blender.app bundle. To make things even more gnarley, the scripts are stored in an invisible folder inside of the Blender bundle. The easiest way to copy the script is to use Terminal.app and the unix cp command. The scripts folder is located at:
Every time you upgrade your Blender install, you'll have to reinstall this script. The next time you start Blender after copying the script, you will find an entry in the Export menu called Objective-C Header (.h). This is intended to be used with texture-mapped objects, and only exports the active object, not all selected objects or all objects. I am going to create a separate version for non-texture mapped objects. This script will create an inefficient version of non-texture-mapped objects because of the way OpenGL ES uses texture coordinates.
I've also created a sample project that shows how to use the exported header file. It's actually quite easy. You just pass the arrays from the header into the various OpenGL calls, like this:
You can then either use glDrawArrays() or glDrawElements() as you see fit. There are indices provided for glDrawElements(), but since the object is exported as triangles, glDrawArrays() works just fine too.
Before running the script, make sure you put the object into edit mode and select Mesh->Faces->Convert Quads to Triangles. This script will not convert to triangles for you, and OpenGL ES requires triangles. You also need to load and bind the texture you used in Blender, or one that you created based on Blender's exported UV template.
As I said before, I am not a very experienced Python programmer, so if you want to suggest improvements, I'm happy to hear those suggestions. You will not hurt my feelings one little bit. This is what I call a "brute force" script - it gets the job done, but perhaps not with the elegance it should have.
If you want to play around with the simple Blender project I used in the test Xcode project, you can find that right here (right-click and save to disk).
I hope to create a future version that interleaves the data as suggested by Apple, but for now, I was just thrilled to get something working.
Of course, the answer to that isn't a simple one. If you followed my my earlier posts on importing Wavefront OBJ files, you're probably aware of that already. There are many file formats, and none of them are ideal for loading into a resource-constrained device like the iPhone.
Apple recommends that 3D objects be stored in header files as static arrays. This obviates the need to do any loading or transforming or conversion at all. But� there's not really any easy way to create those header files from within 3D software packages.
Well, there is one way now. The open source 3D program called Blender has a very extensible architecture, making it relatively easy to write custom export modules. Blender's scripting architecture is based on Python, a language that I'm not particularly familiar with, but I hacked out something that works. So, let's say that you've got an object in Blender:

And you want to load it into a program you're writing for your iPhone:

Note, I know that the screenshots don't actually match - I cropped the texture after exporting from Blender to make it more iPhone sized - I didn't want to resize it for fear that the texture would get too small to see.
All you have to do is take this script and install it into the scripts folder in Blender.
There's a catch, however. The Mac OS X version of Blender doesn't follow the sames rules as it does for other platforms. If you look up how to install a script in Blender, it will tell you to add the script to ~/.blender/scripts/. That directory doesn't get created on the Mac, and if you manually create it, you will lose all the delivered scripts.
Instead, you have to actually install the script into the Blender.app bundle. To make things even more gnarley, the scripts are stored in an invisible folder inside of the Blender bundle. The easiest way to copy the script is to use Terminal.app and the unix cp command. The scripts folder is located at:
/path/to/Blender.app/Contents/MacOS/.blender/scriptsSo, if Blender is installed in your Applications folder inside of a folder called Blender, you could use the following command to copy the unzipped script into Blender:
cp objc.py /Applications/Blender/Blender.app/Contents/MacOS/.blender/scripts/
Every time you upgrade your Blender install, you'll have to reinstall this script. The next time you start Blender after copying the script, you will find an entry in the Export menu called Objective-C Header (.h). This is intended to be used with texture-mapped objects, and only exports the active object, not all selected objects or all objects. I am going to create a separate version for non-texture mapped objects. This script will create an inefficient version of non-texture-mapped objects because of the way OpenGL ES uses texture coordinates.
I've also created a sample project that shows how to use the exported header file. It's actually quite easy. You just pass the arrays from the header into the various OpenGL calls, like this:
glVertexPointer(3, GL_FLOAT, 0, CubeVertices);
glNormalPointer(GL_FLOAT, 0, CubeNormals);
glTexCoordPointer(2, GL_FLOAT, 0, CubeTexCoords);You can then either use glDrawArrays() or glDrawElements() as you see fit. There are indices provided for glDrawElements(), but since the object is exported as triangles, glDrawArrays() works just fine too.
Before running the script, make sure you put the object into edit mode and select Mesh->Faces->Convert Quads to Triangles. This script will not convert to triangles for you, and OpenGL ES requires triangles. You also need to load and bind the texture you used in Blender, or one that you created based on Blender's exported UV template.
As I said before, I am not a very experienced Python programmer, so if you want to suggest improvements, I'm happy to hear those suggestions. You will not hurt my feelings one little bit. This is what I call a "brute force" script - it gets the job done, but perhaps not with the elegance it should have.
If you want to play around with the simple Blender project I used in the test Xcode project, you can find that right here (right-click and save to disk).
I hope to create a future version that interleaves the data as suggested by Apple, but for now, I was just thrilled to get something working.
Category Article iPhone SDK, OpenGL ES
Powered by Blogger.
Blog Archive
-
▼
2009
(496)
-
▼
June
(48)
- OpenGL ES 2.0 Programming Guide has 3Gs Sample Code
- Beginning iPhone 3 Development
- Designing SMS apps for mobile Africa
- Designing SMS apps for mobile Africa
- YouTube: 400% Daily Increase in Mobile Uploads sin...
- Google Voice rolling out new invites
- Google Voice rolling out new invites
- Blender Export Script
- Empty OpenGL ES Application Project Template Updat...
- Using 3D Models from Blender in OpenGL ES
- Announcing the AdSense for Mobile Applications beta
- Announcing the AdSense for Mobile Applications beta
- The Iterative Web App: Swipe-to-Archive and Expand...
- The Iterative Web App: Swipe-to-Archive and Expand...
- YouTube Mobile Application in more languages
- YouTube Mobile Application in more languages
- Mobile Orchard Two Day iPhone Training Class
- A Weekend with the 3Gs
- Willpower Fail
- OpenGL ES 2 Shaders
- Upgrading etc.
- Search by voice and transit directions come to Goo...
- Search by voice and transit directions come to Goo...
- An Amazing WWDC
- Snack time with the new iGoogle for Android and iP...
- Snack time with the new iGoogle for Android and iP...
- Display your public Latitude location on your Goog...
- Display your public Latitude location on your Goog...
- The Iterative Web App - Faster Address Auto-comple...
- The Iterative Web App - Faster Address Auto-comple...
- OpenGL ES from the Ground Up Part 8: Interleaving ...
- Yet Another Post for WWDC First-Timer's
- T-Minus Sixteen Hours
- Mike Ash's Blog
- Beautydig Tutorial Gadget
- Palm Pre launching with Google Search, Google Maps...
- Palm Pre launching with Google Search, Google Maps...
- Introducing the orkut Mobile App
- Introducing the orkut Mobile App
- OpenGL ES From the Ground Up, Part 7: Transformati...
- WWDC Signage
- The importance of being immediate - Google Mobile ...
- The importance of being immediate - Google Mobile ...
- 2010 Pre-WWDC Pilgrimage Payment
- Places Directory app for Android
- Places Directory app for Android
- Runtime Madness
- WWDC Cocoaheads
-
▼
June
(48)