Skip to content

How To Replace The Teapot

matthewcburke edited this page Oct 14, 2012 · 1 revision

One of our first goals with the Vuforia sample applications is to replace the given objects (typically teapots) with our own images. We have mostly succeeded at this goal. We are able to replace the mesh, but are still working on fine tuning applying a texture to that mesh. This page provides a list of external resources, and a step by step guide of how to do this.

External Resources

  1. https://ar.qualcomm.at/content/replace-3d-model-different-3d-model - This is a developer forum on the Qualcomm site. Comment # 36 essentially sums up the discussion and provides the step by step guide. A couple of comments above Comment 36 also have relevant information.

  2. http://heikobehrens.net/2009/08/27/obj2opengl/ - This blog posting provides a Perl script for converting Wavefront OBJ files to header (.h) files. It also provides the banana example, including a banana.obj, a banana.h and a banana.jpg file.

  3. http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Bake - This page is referenced in the above developer forum, and gives an overview of baking in Blender. In short baking is the process of pre-computing something to speed up another process. In the case of render baking, we are creating a 2-D image that will be UV mapped to the mesh at rendering. It has some drawbacks, (e.g. fixed lighting) so maybe we can look into other options, but it looks like this is how the sample apps apply texture to the teapots.

Step by Step Guide to Replacing the Teapot in the ImageTargets Sample

This guide was compiled from the above resources.

Acquire or Create the Required Resource Files

Get an OBJ file of an object to display. Get an associated image file that is a UV map of the texture of the object. In the case of the banana, download these resources from link # 2 above.

Download the Perl script 'obj2opengl' from link # 2 above. ensuring that the script and the OBJ file are in the same directory, go to that directory in the command line and run:

$ ./obj2opengl banana.obj

You should now have a .h file with the appropriate arrays.

Place banana.h in ImageTargets/

Note: The online instructions said the above, but I was thinking that banana.h should go in ImageTargets/jni/ where Teapot.h is, so I put it in both locations.

Place the texture map, banana.jpg, in ImageTargets/assets/

In order to put a texture on our own models (i.e. anything other than the banana), we'll have to figure out how to make these UV maps in Blender. From my reading, I believe this process is called baking. See link # 3 above.

Modify ImageTargets.cpp

Include the newly created file at ~line 45:

#include "banana.h"

Modify renderFrame method:

Replace lines 389-394:

glVertexAttribPointer(vertexHandle, 3, GL_FLOAT, GL_FALSE, 0,
                      (const GLvoid*) &teapotVertices[0]);
glVertexAttribPointer(normalHandle, 3, GL_FLOAT, GL_FALSE, 0,
                      (const GLvoid*) &teapotNormals[0]);
glVertexAttribPointer(textureCoordHandle, 2, GL_FLOAT, GL_FALSE, 0,
                      (const GLvoid*) &teapotTexCoords[0]);

with

glVertexAttribPointer(vertexHandle, 3, GL_FLOAT, GL_FALSE, 0, 
                      (const GLvoid*) &bananaVerts[0]);
glVertexAttribPointer(normalHandle, 3, GL_FLOAT, GL_FALSE, 0, 
                      (const GLvoid*) &bananaNormals[0]);
glVertexAttribPointer(textureCoordHandle, 2, GL_FLOAT, GL_FALSE, 0, 
                      (const GLvoid*) &bananaTexCoords[0]);

Note that 'teapotVertices' becomes 'bananaVerts' but otherwise teapot is replaced by banana. I suppose it is a peculiarity of the 'obj2opengl' script.

Also replace line 404:

glDrawElements(GL_TRIANGLES, NUM_TEAPOT_OBJECT_INDEX, GL_UNSIGNED_SHORT, 
               (const GLvoid*) &teapotIndices[0]);

with

glDrawArrays(GL_TRIANGLES, 0, bananaNumVerts);

Lastly, for the banana example at least, in order to see the model clearly, you have to set change the kObjectScale on line 73 from 3 to 120:

static const float kObjectScale = 120.f;

Modify ImageTargets.java

Modify the loadTextures() method (line 293) by including this line:

mTextures.add(Texture.loadTextureFromApk("banana.jpg", getAssets()));

There was some discussion on the forum about whether to add banana.jpg before the other textures, or in the second position. I believe that the difference is simply which Image Target the banana texture will be associated with. That is, the application displays different color teapots by using different textures for different Image Targets. Texture is assigned in ImageTargets.cpp at line 355:

const Texture* const thisTexture = textures[textureIndex];

Clean and Build

Run ndk-build from the command line.

From the Project menu in Eclipse, Clean your project. Load the app, and hopefully you're looking at a banana or something other than a teapot.

Last time I was playing with the banana example, the program was definitely loading the banana texture with one of the Image Targets, but it looked like the UV mapping from the JPG to the mesh was off. We'll have to see how it works out once we figure out how to do our own baking in Blender (see link # 3 above).

Clone this wiki locally