Cocoa Design Patterns
Learning OpenGL ES for iOS
Presentations
Buy at Amazon Now
  • Cocoa Design Patterns
    Cocoa Design Patterns
    by Erik M. Buck, Donald A. Yacktman
  • Learning OpenGL ES for iOS: A Hands-on Guide to Modern 3D Graphics Programming
    Learning OpenGL ES for iOS: A Hands-on Guide to Modern 3D Graphics Programming
    by Erik M. Buck
« Let it go, Let it go | Main | Green-Screen Video Effects for iOS: Video Processing with OpenGL ES »
Saturday
Oct062012

Loading and Displaying COLLADA Models

COLLADA is a royalty-free XML schema that enables digital asset exchange within the interactive 3D industry. COLLADA is the best way to import complex 3D models into your own applications. Almost every popular 3D modeling tool these days supports export to COLLADA format. As you may suspect, the COLLADA format specification (pdf) is huge and complex to support just about every kind of information 3D modeling tools might generate.

Apple introduced the new Scene Kit framework in OS X 10.8, "Mountain Lion." Scene Kit is an Objective-C framework for building 3D scenes composed of imported COLLADA 3D models, cameras, lights, and meshes. I highly recommend playing with the new framework including its integration with Xcode 4.2+.

Scene Kit doesn't exist for iOS as of version 6.0, and the framework is probably too "heavyweight" for mobile devices at this time. Apple recommends using off-line tools to convert "heavyweight" data types such as COLLADA models into compact binary representations for use with iOS. Unfortunately, Scene Kit neither provides a conversion capability nor supplies source code you could use as the basis of your own conversion tool. [Update: SceneKit exists for iOS 7+]

The "Learning OpenGL ES for iOS" sample code at this site includes a rudimentary Mac OS X COLLADAViewer.app application with source code in the Chapter 7 examples. COLLADAViewer.app reads and displays a subset of COLLADA models and saves them in a compact binary representation suited for the book's examples. COLLADAViewer.app implements a small portion of the overall COLLADA Specification, but even with COLLADAViewer.app's numerous constraints, it still operates as a handy conversion tool to achieve the desirable "compact binary representation" for use in iOS applications.

After the publication of "Learning OpenGL ES for iOS", the limits of COLLADAViewer.app started to become a bit too constraining for my own projects. I started work on a COLLADAViewer2.app application that I'm excited to provide as a new "alpha" version sample with source code hosted at Github.

COLLADAViewer2 contains an Xcode project with source code to parse COLLADA XML files and supports a much greater subset of the COLLADA Specification than COLLADAViewer.app. The sample is useful as a demonstration of Apple's Objective-C XML parsing classes in general as well as the specific challenges of COLLADA. The alpha version of COLLADAViewer2 should correctly display almost any COLLADA model that Apple's Preview application can display. Exporting compact binary "modelplist" files from COLLADAViewer2 produces the same result as COLLADAViewer and suffers the same limitations. The next planned improvement to COLLADAViewer2 introduces a new more flexible "compact binary representation" for use in iOS applications.

The following entity relationship diagram shows the major COLLADA schema features supported by COLLADAViewer2.app.

The schema for the subset supported is actually more complex than shown, for example, there are typically five more sub-entities that combine to form a MeshGeometry and each sub-entity can be represented as multiple data types with optional features. It would take an entire book to explain the range of features supported by the Effect entity.

In the process of building COLLADAViewer2, I realized that almost every COLLADA model I can find is reducible to the following simplified schema without changing the appearance of the models.

Two entities, Resource and Instance, cover almost every feature of interest. Most Resources are global and may be referenced by Instances any number of times as needed. For example, the same MeshGeometry Resource can be referenced and combined with different Material Resources and coordinate systems. Nodes are Resources that together with Instances form a data structure called a scene graph. Nodes can have sub-nodes, and each Node can specify its own coordinate system transformations relative to its parent Node.

The schema can be further reduced by observing that most Instance entities exist to replicate entity relationships supported intrinsically by Apple's Core Data framework. Keep an eye on this site to see how COLLADAViewer2 progresses.

 

References (1)

References allow you to track sources for this article, as well as articles that were written in response to this article.
  • Response
    COLLADA is a very well known name in the 3d world. I see the bright future of this company.

Reader Comments (23)

Hi Erik,

Thanks for your hard work in creating this COLLADA viewer; I'm sure it will be very useful.

I used Cheetah3D to generate a simple model (just a cylinder & a box) that causes problems - No "library_images" found: No texture image has been identified.Mesh has niether <triangles> nor <polylist>. COLLADAInstanceGeometry reports "instance_geometry references unknown material" in - (COLLADAImagePath *)imagePathForMaterialBinding:(COLLADAInstance *)bindMaterial root:(COLLADARoot *)aRoot; I suspect the problem arises because the node <polygons> in <mesh> is not being processed.

If you would like a copy of the .dae I am happy to provide it.
In the meantime, I hope to work out what code needs adding to work with this (or other cheetah3D files) that generate polygons, rather than triangles.

Regards,
Mark
October 22, 2012 | Unregistered CommenterMark Brindle
Ah, your detective work has been very thorough. The thing about OpenGL ES is that it can only render points, lines, and triangles. With <polygons>, you will need to "triangulate" them before they can be displayed with OpenGL ES.

With luck, Cheetah3D has an option to convert polygons into triangles during export or during edit. Using the editing tool to convert to triangles will save you a lot of effort when loading the resulting models for display with OpenGL ES. Another option is to load your Cheetah3D .dae models in blender and re-export as COLLADA. I may be mistaken, but I think blender always triangulates upon export or there is an options in blender that I have always used.
October 22, 2012 | Registered CommenterErik Buck
Hi Erik!
Love your book. Only one problem:
So far, I can't get COLLADAViewer to correctly render any .dae I make. I use Cheetah3D for modeling and animating. The Cheeta3D guys claim to support the Collada spec and their .dae files open in Preview, but I wouldn't be surprised if they're doing something quirky since every 3D app seems to handle Collada differently.

I zipped up a triangulated cube as an example. I'd appreciated it if you could look at the XML in it and tell me if there's anything that jumps out at you as being odd: https://dl.dropbox.com/u/14340439/TriCubeTest.zip

Thanks for your time, and thanks again for writing a great book.
October 28, 2012 | Unregistered CommenterJim
Thank you for the sample COLLADA file. There was indeed a bug that I have just corrected in the gitHub repository. The sample provided now loads and displays correctly in COLLADAViewer2.app.

The bug was the assumption in code that the number or vertex input source indices per vertex equals the number of vertex input sources for the vertex. The provided sample model proves that assumption unwarranted. In the sample, there are three input sources, (position, normal, texCoord), for every vertex, but only 2 vertex input source indices are provided per vertex because the normal input source and the texCoord input source always use (share) the same index.

The affected code is constrained to one file. A property has been renamed from "numberOfSources" to "indexStridePerVertex" to more correctly describe the property. indexStridePerVertex is now calculated independent of the number of sources.

Update: I also just committed rudimentary support for COLLADA <polygons> elements using the assumption that polygons are actually all triangles. The current implementation will likely break badly if non-triangular <polygons> elements are parsed. However, it seems to now work well with triangulated Cheetah3D models that use the COLLADA <polygons> element.
October 28, 2012 | Registered CommenterErik Buck
Thank you so much for taking time to check this out. I'll download the update and give it a spin!
October 30, 2012 | Unregistered CommenterJim
Erik,

In COLLADAViewer2, does the texture still need to be one file? I didn't see it in the ReadMe.

Thanks for the work in making this possible.

Jim Hillhouse
November 4, 2012 | Unregistered CommenterJim Hillhouse
The modelplist format used in "Learning OpenGL ES for iOS: A Hands-on Guide to Modern 3D Graphics Programming" only stores one texture although it could be modified to store multiple textures.

The COLLADAViewer2 application uses multiple textures by default and tries to condense all textures into a single texture atlas when exporting to modelplist format. In your own applications that load modelplist files, the texture mapping parameters should be set to GL_CLAMP_TO_EDGE. Using a "wrapping" wrapping mode would wrap the entire texture which won't look right. Not all of the book's examples set GL_CLAMP_TO_EDGE, so keep an eye out for that if/when modifying the examples.

glTexParameteri(
GL_TEXTURE_2D,
GL_TEXTURE_WRAP_S,
GL_CLAMP_TO_EDGE);
glTexParameteri(
GL_TEXTURE_2D,
GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE);

Note: if you write your own texture coordinate calculation in a fragment shader, you can achieve an effect similar to the built-in "wrapping" wrapping mode even when using a texture atlas.

The current COLLADAViewer2 version in Github contains debug code to store the generated texture atlas in your home directory as well as within the saved modelplist file when exporting in modelplist format. You can view the saved texture atlas in Preview and quickly gauge what COLLADAViewer2 has done.

Note: When importing COLLADA files into COLLADAViewer2, there is a check box specifying whether to preserve the texture coordinates in the loaded model or convert the texture coordinates to the values that will be in an exported modelplist. Leaving the box unchecked provides a better preview of the way the model will look in your application. Checking the box attempts to make the loaded model look the same as it does in the Preview app.
November 5, 2012 | Registered CommenterErik Buck
Hi Erik,

Thank you for writing this book it is extremely informative!

I am using Cheetah 3D as well and am attempting to make an earth model with one sphere and a an earth flat map image mapped to the sphere. I use Cheetah's 'spherical' option in the UV Mapping tool to get the texture to look correct on my sphere. I then export the file as a .DAE type and can view it with the Mac Preview app just fine, texture and all.

I pulled your latest changes for COLLADAViewer2 and when I open the .DAE file I see my sphere, but the entire surface is dark blue, there are no green continents. I tried checking the box for 'preserving texture coordinates', but seem to be getting the same results. I must be doing something wrong here.

I would really appreciate if you could shed some light on this. I've placed a zip file on my website at www.ptrackapp.com/EARTH.zip containing the Cheetah3d file, image, earth.DAE file, and screenshots of what I am seeing. Please take a look if you get a chance -

Thank you very much,

Phil
December 9, 2012 | Unregistered CommenterPhil Class
I loaded your Earth.dae file using the "preserve texture coordinates" option and see the model as expected with continents. http://cocoadesignpatterns.squarespace.com/storage/Earth.png I'm unsure why it isn't working for you.
December 10, 2012 | Registered CommenterErik Buck
Hi Erik,

Busy reading your book, and it is the best source out there, but in chapter 7, you use the .modelplist with the GLKit. I'm trying to create a class that will use shaders, but i can't seem to get the fragment shader to work with the "bumper.modelplist". How would i go about making it work? This is the code in the fragment shader so far:
"uniform sampler2D textureSampler;

varying lowp vec4 vColour;
varying lowp vec2 textureCoord;

void main() {
gl_FragColor = texture2D(textureSampler, textureCoord) * vColour;
}"

Thanks,
Justin Guedes
December 13, 2012 | Unregistered CommenterJustin Guedes
What's not working?

Has texturing been enabled? Is textureSampler valid? is vColour non-black? Multiplying any color with zero produces zero.

Also, for fun and debugging, you can check the validity of the texture coordinates via
gl_FragColor = vec4(textureCoord.x, textureCoord.y, 0.0, 1.0);
You should see red, green, and yellow on your geometry indicating the corresponding texture coordinates.

Example 3_6 contains a simple shader similar to yours for comparison.
December 13, 2012 | Registered CommenterErik Buck
Hi again,

My texturing is enabled, and it is even valid, as i see red, green and yellow when I use the following line:
"gl_FragColor = vec4(textureCoord.x, textureCoord.y, 0.0, 1.0);"
The vColour is non-black, and I have set textureSampler to a zero value.

The example on 3_6 is helpful, but its not so helpful with this example, or so I think.

Thanks again,
Justin Guedes
December 13, 2012 | Unregistered CommenterJustin Guedes
Sorry,

The problem is that I can't see anything on the screen, it just appears black.

Thanks
December 13, 2012 | Unregistered CommenterJustin Guedes
Hi Erik,

Does COLLADAViewer2 support 'spherical' UV texture mapping? I am using Cheetah3d to map a rectangular Globe image to a simple sphere. If I use 'cubic' UV texture mapping, the exported modelplist render looks identical to the dae file when viewed in Preview App, but if I use 'spherical' mapping, which obviously looks the most like earth, then my dae and rendered modelplist in the iPad simulator looks wrong. Please see the following images. Any suggestions here? Thank you for your help.

.dae in Preview App:
http://i45.tinypic.com/4zxm4p.png

iPad simulator render:
http://i48.tinypic.com/2mn2grn.png
December 30, 2012 | Unregistered CommenterPhil
Phil,

There's obviously a bug in COLLADAViewer2 when it renders a model so badly compared to Preview. However, the problem shouldn't be related to the texture mapping approach used in a 3D modeling tool. Cubic UV mapping and spherical UV mapping within the 3D modeling tool are just two different algorithms for calculating the UV coordinates stored for each vertex in a model's mesh. In the end, only the calculated UV coordinates are stored in the COLLADA file. To my knowledge, the algorithm used to calculate UV coordinates is neither stored in the COLLADA file nor reasonably discernible when reading a COLLADA file.

Without seeing the COLLADA files in question, my guess is that Cheetah 3D is storing vertex data differently as a side effect of the way UV coordinates are calculated. For example, one approach may cause generation of an equal number of UV coordinates and XYZ position coordinates. The other approach may cause generation of coordinates for one quarter of the sphere and then use transformation matrices to produce all the radially symmetrical UV coordinates for the other 3/4 of the sphere. It's still a bug when COLLADAViewer doesn't render the model correctly though.

Note: OpenGL and most hardware Graphics Processing Units (GPUs) include multiple texture mapping modes including cubic texture mapping. In the context of OpenGL, the mapping mode determines how texels are sampled based on UV coordinates. The mapping mode applies implicit transforms as textures are sampled. I don't THINK the 3D modeling tool is using the terms cubic and spherical in the same context as a GPU. I THINK the terms describe the way the 3D modeling tool calculates UV coordinates and not the way the coordinates are meant to be transformed when sampling a texture at runtime. I could be wrong, and that would certainly explain the bug you are seeing.
December 30, 2012 | Registered CommenterErik Buck
Erik,

Thanks for the information. If you would like to see it, I placed an archive of the images and my Cheetah 3D.dae file here --> http://ptrackapp.com/dae_earth.zip

I did download a pre-made Sketchup 8 model of the earth as well and saw the same rendering results after exporting it as a modelplist file.

Thanks again -

Phil
December 30, 2012 | Unregistered CommenterPhil
Erik,

Please note that in the second image in my first post ( the distorted image ) is actually a screenshot of the iPad simulator from within XCode. It is not a render of the .dae file from within COLLADAViewer2. Using spherical UV mapping, the render shown in the COLLADAViewer App looks correct ( and matches Preview ), but not the OpenGL render in XCode. I think I didn't communicate that clearly.

There seems to be an issue rendering the exported modelplist file using GLKit. If I use cubic texture mapping from Cheetah 3D, then the image is discernable from withing XCode on the simulator and matches what I see in the Preview App and COLLADAViewer2.

Just wanted to clarify -

Phil
December 30, 2012 | Unregistered CommenterPhil
Hi,

The zoom looks broken. On my system (OS X 10.8.3), when I scroll up or down, it changes the zoom level, but it is very chaotic. I'm not even sure that changing the zoom level is a feature of the collada viewer.
May 10, 2013 | Unregistered CommenterLucy
The book is wonderful but I have been having a problem with textures using ColladaViewer 1 & 2. A Sphere Model with texture created in Blend and exported using built in Collada exporter. ColladaViewer 2 shows 1 in the 'textures' column. Imported .modelplist file into example program 8.1 to replace boat.modelplist. Sphere shows up as it should but texture does not show. The same Blend model with texture worked fine when exported as a .h file and imported into example program 5.6.
I am fairly sure the problem is all my fault. I am not an expert and am probably a bit old for this. I am trying to add 3d satellite orbit visualization to my existing 'Satellite Explorer Pro' educational app.
November 1, 2013 | Unregistered CommenterTom Doyle
Hi Erik,

Thanks for your hard work in creating this COLLADA viewer; I'm sure it will be very useful.
but I don't know how to use it .I did not find any information about how to use this tool in the book , so I hope you can give me a tutorials about how to load the .dae file and get the export file.
thank you very much

Just wanted to clarify

luo
February 26, 2014 | Unregistered Commenterluo
Hi, thanks for the good book and the programs like ColladaViewr. I have a problem with second one (the first it's ok) : the build failed. Several errors like GL_CLAMP undeclared (and others GL_TRIANGLES, GL_LIGHTNING,...) If you can help me it will be fantastic

thanks in advance
March 11, 2014 | Unregistered CommenterCurro Bellas
What version of OS X are you using. What version of Xcode?
March 17, 2014 | Registered CommenterErik Buck
I have updated ColladaViewer2 at GitHub. Apple updated the the gl3.h header file with OS X 10.9 to make it more standard compliant. Apple's changes necessitated changes to ColladaViewer2.
March 17, 2014 | Registered CommenterErik Buck

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
All HTML will be escaped. Hyperlinks will be created for URLs automatically.