<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mobile Perspectives &#187; paul</title>
	<atom:link href="http://www.BluMtnWerx.com/blog/author/paul/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.BluMtnWerx.com/blog</link>
	<description>Computing at the Edge!</description>
	<lastBuildDate>Tue, 27 Jul 2010 23:43:57 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Look Ma, No Stencil Buffer</title>
		<link>http://www.BluMtnWerx.com/blog/2009/07/look-ma-no-stencil-buffer/</link>
		<comments>http://www.BluMtnWerx.com/blog/2009/07/look-ma-no-stencil-buffer/#comments</comments>
		<pubDate>Fri, 31 Jul 2009 01:10:26 +0000</pubDate>
		<dc:creator>paul</dc:creator>
				<category><![CDATA[Resources]]></category>
		<category><![CDATA[coding example]]></category>
		<category><![CDATA[depth culling]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Oolong]]></category>
		<category><![CDATA[OpenGL]]></category>
		<category><![CDATA[stencil buffer]]></category>

		<guid isPermaLink="false">http://www.BluMtnWerx.com/blog/?p=235</guid>
		<description><![CDATA[Shows an example of using OpenGL depth culling and transparency to achieve a stencil effect in the absence of a stencil buffer on the iPhone.]]></description>
			<content:encoded><![CDATA[<p>OK, show of hands, who else was surprised to discover that there is no stencil buffer on the iPhone, even though it&#8217;s supported by OpenGL-ES 1.1?  Well, I was, but I&#8217;m a noob.  I&#8217;m also a bit of a hacker, so when I need something, I just go schlepping around the Internet until I find a way to do it.  When I needed a stencil-type behavior for <a title="iPunt iPhone game web page." href="http://www.blumtnwerx.com/iPunt.html" target="_blank" title="iPunt iPhone game web page.">iPunt</a> , I went googling and discovered this wonderful thing called a &quot;stencil buffer&quot;, and tried to use it.  Only it didn&#8217;t work.  I did some more homework and discovered that the iPhone doesn&#8217;t have a stencil buffer.  That left me scatching my head until I saw a brief comment somewhere that suggested that many applications for a stencil could be accomplished by depth culling and transparency.  Ah-Ha, I exclaimed, and came up with the following.  Pehaps this will help some other noob out there, or maybe some expert will show me a better way.</p>
<p>Here&#8217;s the effect I was trying to achieve:</p>
<p><img src="http://www.BluMtnWerx.com/blog/wp-content/finished.png" alt="Desired effect of playbox with mirrored floor suspended in mid-air." /></p>
<p>What we have here is the iPunt playing box suspended in mid-air.  The floor is a broken mirror (although that&#8217;s a little hard to see from this angle.)  The camera is allowed to move freely around the inside of the skybox.  When the camera is below the foor, the floor appears transparent (like broken glass.)  The walls of the playbox are fractured glass.</p>
<p>The problem, really, is the reflection.  Without any stenciling, you get this&#8230;</p>
<p><img src="http://www.BluMtnWerx.com/blog/wp-content/woutstencil.png" alt="The problem.  Scene drawn as a reflection is visible from some angles." /></p>
<p>We somehow need to prevent the reflected scene that is not viewed through the mirrored floor from showing.  A stencil buffer would have worked well for this purpose.  Without a stencil buffer, you have to rely on depth culling and transparency to achieve the desired result.</p>
<p>In brief, what I did was to create a stencil shape (a planar shape made up of triangles) that had a hole in the middle where the mirrored floor was going to be and was large enough to obscure the reflected scene from all camera angles above the plane of the floor.  This shape will be drawn transparent (alpha = 0) so that the skybox will show through, but the draw order and the depth culling will prevent the unwanted portions of the reflected scene from showing through.</p>
<p>Here&#8217;s a picture of the skybox, reflection, and stencil (with the alpha turned up so that it can be seen.)</p>
<p><img src="http://www.BluMtnWerx.com/blog/wp-content/stencil.png" alt="Skybox, reflection, and stencil." /></p>
<p>Because the draw order is skybox, then stencil, then reflected scene, those portions of the reflected scene that are occluded by the stencil are depth-culled and won&#8217;t be drawn.  The real scene and floor can then be drawn.</p>
<p>Here is the code, with comments, that does this&#8230;</p>
<p>First, the definition of the stencil and floor triangles.</p>
<pre>// The shape here is a large plane
// with a hole in it where the mirror will be.
const GLfloat stencilVerts[] = {
-100.0, -15.0, 100.0,
-10.0, -15.0, 10.0,
100.0, -15.0, 100.0,
10.0, -15.0, 10.0,
100.0, -15.0, -100.0,
10.0, -15.0, -10.0,
-100.0, -15.0, -100.0,
-10.0, -15.0, -10.0,
-100.0, -15.0, 100.0,
-10.0, -15.0, 10.0
};

const GLfloat floorVerts[] = {
-10.0, -15.0, 10.0,
10.0, -15.0, 10.0,
10.0, -15.0, -10.0,
-10.0, -15.0, -10.0,
};

const GLfloat floorUV[] = {
0.0, 0.0,
0.0, 1.0,
1.0, 1.0,
1.0, 0.0
};</pre>
<p>Then in my render() function&#8230;</p>
<pre>  glEnable(GL_DEPTH_TEST);
  glEnable(GL_TEXTURE_2D);
  glShadeModel(GL_SMOOTH);
  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  // Clear the space
  glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  CHECK_ERR

  // Draw the skybox
  _pSkyBox-&gt;draw();
  CHECK_ERR

  // Only draw the reflection if the view is above the plane of the floor.
  if (pWorld-&gt;camera()-&gt;location().y() &gt; -14.5) {

    // Draw the stencil.  Anything that is drawn after this that is occluded by the
    // stencil will not be drawn because it fails the depth test.  The skybox, which
    // has already been drawn, will show through everywhere because of the transparency.
    pWorld-&gt;material(&quot;StencilMaterial&quot;)-&gt;installMaterial();  // Sets the material properties, including alpha
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3, GL_FLOAT, 0, stencilVerts);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 10);
    glDisableClientState(GL_VERTEX_ARRAY);
    pWorld-&gt;material(&quot;StencilMaterial&quot;)-&gt;uninstallMaterial();

    // Draw reflection w/out floor -- Reflection will be depth culled everwhere but hole
    // Draw everything else normally (including the mirrored floor)
    glPushMatrix ();
    // Mirror lies in XZ plane, so scale by -1.0 in Y axis
    glScalef(1.0, -1.0, 1.0);
    // Mirror is 15.0 units from origin, so translate by 30.0 units
    glTranslatef(0.0, 30.0, 0.0);
    pWorld-&gt;draw();
    glPopMatrix();
  }
  CHECK_ERR

  // Draw the real scene
  pWorld-&gt;draw();
  CHECK_ERR

  // Draw the floor
  BMWLight::disableLighting();
  pWorld-&gt;material(&quot;Material_010&quot;)-&gt;installMaterial(); // Sets the material properties
  glEnableClientState(GL_VERTEX_ARRAY);
  glVertexPointer(3, GL_FLOAT, 0, floorVerts);
  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  glClientActiveTexture(GL_TEXTURE0);
  glTexCoordPointer(2, VERTTYPEENUM, 0, floorUV);
  glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  glDisableClientState(GL_VERTEX_ARRAY);
  pWorld-&gt;material(&quot;Material_010&quot;)-&gt;uninstallMaterial();
  BMWLight::enableLighting();</pre>
<p>Note that the BMW functions are functions in our framework that encapsulate OpenGL functionality.  You can pretty much treat them as pseudo-code in this example.</p>
<p>So, there you have it.  A use of depth culling and transparency to implement functionality that I originally though required a stencil buffer.  I&#8217;d be intereste in hearing about any examples you have of similar effects!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.BluMtnWerx.com/blog/2009/07/look-ma-no-stencil-buffer/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Taming SoundEngine Processor Utilization</title>
		<link>http://www.BluMtnWerx.com/blog/2009/07/taming-soundengine-processor-utilization/</link>
		<comments>http://www.BluMtnWerx.com/blog/2009/07/taming-soundengine-processor-utilization/#comments</comments>
		<pubDate>Wed, 22 Jul 2009 22:26:22 +0000</pubDate>
		<dc:creator>paul</dc:creator>
				<category><![CDATA[Resources]]></category>
		<category><![CDATA[iPhone SDK]]></category>
		<category><![CDATA[iPunt]]></category>
		<category><![CDATA[OpenAL]]></category>

		<guid isPermaLink="false">http://www.BluMtnWerx.com/blog/?p=224</guid>
		<description><![CDATA[Here's a simple modification to SoundEngine that cures performance problems with looping effects having long preambles (or attack buffers.)]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re using the SoundEngine example code from Apple for OpenAL sounds on iPhone, I have a tip for you.  I ran into a serious processor utilization problem when using SoundEngine_LoadLoopingEffect() to load a sound effect that had a long preamble and then transitioned into a steady-state loop.  At first glance, this function looks ideal for such a thing because it will allow you to load a sound to be played when the effect starts, then a sound that is looped, then a sound that is played when the effect is stopped.  What I found was that, while the preamble (called the <em>AttackBuffer</em> in SoundEngine) is playing, SoundEngineEffect::PlaybackProc() hogs the processor.  This led to serious frame rate issues in <a title="iPunt iPhone game web page." href="http://www.blumtnwerx.com/iPunt.html" target="_blank" title="iPunt iPhone game web page.">iPunt</a> .</p>
<p>The cause is the following code in SoundEngineEffect::PlaybackProc()</p>
<pre>  if (THIS-&gt;HasAttackBuffer())
  {
    ALint numBuffersProcessed = 0;
    while (numBuffersProcessed &lt; 1)
    {
       alGetSourcei(THIS-&gt;GetEffectID(), AL_BUFFERS_PROCESSED, &amp;numBuffersProcessed);
         AssertNoOALError(&quot;Error getting processed buffer number&quot;, end)
    }</pre>
<p>While the attack buffer is playing, you&#8217;re in a tight polling loop waiting for it to complete.  This is no problem if the preamble is really short, but for OpenGL games, it&#8217;s going to cause problems for any sound longer than a fraction of a frame.</p>
<p>The fix, fortunately, is simple.  Sleep this thread for a few milliseconds each iteration of the polling loop in order to give the rest of your application a chance to run.</p>
<p>The modified code is:</p>
<pre>  if (THIS-&gt;HasAttackBuffer())
  {
    ALint numBuffersProcessed = 0;
    while (numBuffersProcessed &lt; 1)
    {
       alGetSourcei(THIS-&gt;GetEffectID(), AL_BUFFERS_PROCESSED, &amp;numBuffersProcessed);
         AssertNoOALError(&quot;Error getting processed buffer number&quot;, end)
       usleep(5000);  // Sleep for 5 mS each polling loop
    }</pre>
<p>This little change makes all the difference for this bit of code and makes it suitable for long (&gt; 1second) preambles.</p>
<p>I&#8217;ve found SoundEngine to work pretty well, although I have had to make a number of modifications to it for my specific application.  However, I think I&#8217;m at the point where I need to write my own OpenAL sound processing class library.  I&#8217;d be interested to hear from some of you to see what you&#8217;re using for game sound.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.BluMtnWerx.com/blog/2009/07/taming-soundengine-processor-utilization/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OpenGL-ES Texture Mapping for iPhone / Oolong / PowerVR</title>
		<link>http://www.BluMtnWerx.com/blog/2009/06/opengl-es-texture-mapping-for-iphone-oolong-powervr/</link>
		<comments>http://www.BluMtnWerx.com/blog/2009/06/opengl-es-texture-mapping-for-iphone-oolong-powervr/#comments</comments>
		<pubDate>Fri, 12 Jun 2009 19:59:42 +0000</pubDate>
		<dc:creator>paul</dc:creator>
				<category><![CDATA[Resources]]></category>
		<category><![CDATA[Oolong]]></category>
		<category><![CDATA[OpenGL-ES]]></category>
		<category><![CDATA[PowerVR]]></category>
		<category><![CDATA[texturing]]></category>

		<guid isPermaLink="false">http://www.BluMtnWerx.com/blog/?p=84</guid>
		<description><![CDATA[Resources to help newbs like me get started with more advanced texturing in OpenGL-ES for the iPhone, particularly when using Blender as the modeling tool.]]></description>
			<content:encoded><![CDATA[<p>Sorry it&#8217;s been so long, but I&#8217;ve been busy learning and applying texture mapping for the upcoming iPunt update.  As the old saw goes, &quot;The more I learn, the more I realize I don&#8217;t know!&quot;  The learning process has been pretty fun, and I hope that what I share here helps keep it fun for someone else.</p>
<p>I want to apologize in advance for the lack of polish in this post.  It&#8217;s kind-of a hodge-podge of information, but it&#8217;s been in the womb too long.  Time to get it out, even if it&#8217;s rough!</p>
<p>I&#8217;ve had a lot of trouble getting my head around texturing.  I know what I want to do, and I understand the &quot;how to&quot; do it for OpenGL, but there are a bunch of issues that make translating the theory to practice on the iPhone challenging:</p>
<ul>
<li>The iPhone uses OpenGL-ES 1.x which is not OpenGL when it comes to texturing.  (News flash, the iPhone 3G S will support OpenGL-ES 2.0.)</li>
<li>The PowerVR MBX chipset doesn&#8217;t support all of the OpenGL-ES functionality (particularly the stencil buffer.)  It will be interesting to see what the new SGX chipset provides.</li>
<li>If you&#8217;re using Blender for your modeling, as I&#8217;m trying to do, making the translation from a texturing strategy in Blender to something that will work on the device may not be obvious.</li>
</ul>
<p>I found myself doing a lot of googling and reading books, then trying things out only to find that the methods provided required an API call or technique that doesn&#8217;t work on the platform.  So, I&#8217;ve compiled a little list of resources and hints that perhaps will make the going easier for those that are also trying to climb the mountain.</p>
<p><strong>The Basics of Texturing</strong></p>
<p>There are some great tutorials on OpenGL texturing out there.  Here are a few to get you started, but there are many more that are worth mentioning:</p>
<ul>
<li><a title="Zeus Texture Mapping Tutorial" href="http://www.zeuscmd.com/tutorials/opengles/17-TextureMapping.php" target="_blank" title="Zeus Texture Mapping Tutorial">Zeus Texture Mapping Tutorial</a></li>
<li><a title="OpenGL Texture Mapping Tutorial" href="http://www.flipcode.com/archives/Advanced_OpenGL_Texture_Mapping.shtml" target="_blank" title="OpenGL Texture Mapping Tutorial">Flipcode Advanced OpenGL Texture Mapping</a></li>
</ul>
<p>These and others will get you the basics.  Please don&#8217;t waste time writing loaders for different graphics file types, generating textures and so-on.  Oolong and PowerVR have a solution for that which is much quicker and better.  Simply load your texture bitmap (in whatever format is convenient) into the PowerVR TexTool and generate the PVRTC (.pvr) compressed texture file.  A few easy calls and the .pvr file is loaded into your app and ready to use.  I&#8217;ll provide a more complete recipe for this a little later in this post.</p>
<p>One of the things that I struggled with in a big way was understanding and generating texture coordinates.  This is something that all of the tutorials make short shrift of.  Most of them provide a static array of 0&#8217;s and 1&#8217;s and leave it at that.  Those that go a bit deeper (the Red Book and Super Bible go into more detail) rely heavily on glTexGen().  Well, guess what, there is no glTexGen() for OpenGL-ES and I have found very little  help in working around that.  The one bright light is this article on &quot;<a title="Mathematics of glTexGen article." href="http://www.opengl.org/wiki/Mathematics_of_glTexGen" target="_blank" title="Mathematics of glTexGen article.">The Mathematics of glTexGen()</a> &quot; from the OpenGL wiki.  With this information, you can write your own procedural texture coordinate generation code.  One of the best explanations of what each of these generation &quot;modes&quot; does is found <a title="SuperBible chapter on texcoord generation." href="http://www.informit.com/articles/article.aspx?p=770639&amp;seqNum=4" target="_blank" title="SuperBible chapter on texcoord generation.">here</a> , from the OpenGL Super Bible.</p>
<p>More than likely, the main reason that these resources don&#8217;t help much with procedural texture mapping is because most texture mapping is performed in a modeling tool.  The funny thing is that, with all my searching, it took a while before I discovered how to do this in Blender.  There is actually a very good, comprehensive tutorial in the Blender manual that explains all:  <a title="Link to Blender texture mapping documentation." href="http://wiki.blender.org/index.php/Doc:Manual/Textures/UV" target="_blank" title="Link to Blender texture mapping documentation.">Blender UV Texture Mapping</a> .  The relevant documentation is several web pages long, so stick with it to the end.  Note that in the currently available iPhones (the PowerVR MBX chip) there are only two texture units, so don&#8217;t plan on deep multi-texturing for this device.</p>
<p><strong>The Blender-&gt;PVR-&gt;Oolong Procedure At A Glance</strong></p>
<p>Here&#8217;s a high level overview of the entire procedure at a glance.  Note that I have left out many details that are covered in the Blender documentation, only including those steps that are either structural or I have additional details for.</p>
<p>In Blender:</p>
<ol>
<li>Create your mesh.</li>
<li>Select the <em>Material</em> window configuration which puts the <em>UV/Image Editor</em> and <em>3D View </em> up simultaneously (see image below.)</li>
<li>Put the 3D window in texture mapped mode so that you can see the effects of texturing in real-time.</li>
<li>Create or select a material for the object or faces.</li>
<li>Create a UVTex mapping for the object or faces.</li>
<li>Unwrap the mesh.  This will probably take some experimentation with the many unwrapping algorithms Blender provides, along with some manual editing of the faces in the UV window.</li>
<li>Export the face layout to a .tga file using the Blender script <em>UVs-&gt;Scripts-&gt;Save UV Face Layout</em> .  Be sure to set the size to the final size of the texture (for a 256&#215;256 texture, set the size to 256.)  Be sure size is a power of 2.</li>
</ol>
<p>In GIMP or the image editing / paint tool of your choice&#8230;</p>
<ol>
<li>Open the .tga file and copy the layout to a semi-transparent, top layer (overlay).</li>
<li>&quot;Color&quot; the texture on layers underneath it.</li>
<li>Turn off the overlay and export to .png format</li>
</ol>
<p>In Blender</p>
<ol>
<li>Load the texture image and assign to the mesh faces to which it applies.</li>
<li>Use texture paint to touch up any areas where appropriate.  (Be sure to load the changed version into your image editor if you go back!)</li>
<li>Adjust vertices and mapping as necessary and iterate.</li>
</ol>
<p>For the most part, the result on the device will look the same as in Blender, so you can just stay in Blender and GIMP until you have it looking right.  I noticed that I occasionally had to flip normals on some faces in Blender, particularly when I manually added faces or reduced the face count during optimization.  Faces with the normal facing in the wrong direction will look transparent in Blender.</p>
<p>Note that the mapping is extremely flexible.  It is not necessary for faces in the UV window to have proportional area to the actual faces on the mesh.  In fact, it is a monumental waste of pixels to map faces that are a solid color or have low resolution data to large UV areas.  Devote most of the area in your texture to the high resolution content and put low resolution faces in smaller areas.  Also, remember that it&#8217;s OK if UV faces overlap as long as the result is what you want.  I sometimes just create a color splotch and put all the faces that are that color higgledy-piggledy in the splotch.</p>
<p>When the object looks the way you want, use the PVRTexTool to convert the texture image to .pvr format&#8230;</p>
<ol>
<li>Open the texture image produced above in the PVRTexTool (comes with the PowerVR SDK.)</li>
<li>Generate all MipMaps.  They should automatically show up.  If they don&#8217;t, your texture may not be square and a power of 2.</li>
<li>Use Save As to save the texture as a .pvr</li>
<li>In the encoding dialog that pops up, select 2bpp or 4bpp as needed, turn YFlip OFF, and export all mipmaps.  Many other encodings are supported, but I have found that the PVRTC 2bpp and 4bpp encodings work very well with the Oolong kit.  Use 4bpp where you need better image quality, 2bpp where the quality is not as important.  Experiment to get what you need.</li>
</ol>
<p>You can now load the POD and texture, apply the texturing during rendering in Oolong and it should look the same as it did in Blender.  I used the Shadows example to get me started.</p>
<p>Here are some examples from iPunt:</p>
<p><a href="http://www.BluMtnWerx.com/blog/wp-content/blenderapache1.png"><img src="http://www.BluMtnWerx.com/blog/wp-content/blenderapache1-300x223.png" alt="Apache helicopter being textured in Blender." /> </a></p>
<p><img src="http://www.BluMtnWerx.com/blog/wp-content/apacheondevice.png" alt="Textured helicopter as rendered on device." width="300" /></p>
<p><strong>Procedural Texturing</strong></p>
<p>Once I figured out how to use Blender to map an image to an object by &quot;unwrapping&quot; it, I didn&#8217;t have as much need for procedural texturing, but for certain things (like cube mapping and projections) procedural texturing is still useful.  Here&#8217;s what I learned.</p>
<p>One of the conceptual things that I struggled with is that I kept trying to think of wrapping my texture around an object.  The way these algorithms work is backwards from that, and much easier.  They work backwards from the point on the object to be textured to the pixel in the texture bitmap to be used.  I don&#8217;t know if that helps anyone else, but it was an epiphany for me!</p>
<p>One little trick that you need to be aware of is that you&#8217;ll need to &quot;adjust&quot; your texture coordinates after the chosen glTexGen() algorithm has generated them.  The algorithm will generate values in some range, such as -n .. +n and you&#8217;ll want to re-map that range to 0..1 or 0..r (for repeated textures.)  Otherwise, you&#8217;ll get garbage.  I call this &quot;re-boxing&quot; the coordinates instead of &quot;normalization&quot; since normalization tends to refer to reducing vectors to unit-length in OpenGL.  Here are some code fragments that do all of the above in an Oolong environment:</p>
<p>Here&#8217;s an implementation of glTxGen() OBJECT_LINEAR:</p>
<pre>// Note that these algorithms come from:
// http://www.opengl.org/wiki/Mathematics_of_glTexGen

void texGenObjectLinear(GLfloat* buf, unsigned int stride, const btVector3 &amp;sPlane, const btVector3 &amp;tPlane) {
  // Loop through the vertices and operate on each one
  unsigned char* p = (unsigned char*)buf;

  for (unsigned int i=0; i &lt; numVertices(); i++, p+=stride) {
    buf = (GLfloat*)p;
    const btVector3 vtx(vertex(i)[0], vertex(i)[1], vertex(i)[2]);
    buf[0] = vtx.dot(sPlane);
    buf[1] = vtx.dot(tPlane);
  }
} // computeTexObjectLinear()</pre>
<p>As you can see, this is just a direct translation of the pseudo-code in the Mathematics of glTexGen() article, using the Bullet vector dot product.</p>
<p>Here is the implementation of the vertex() method for SPOD meshes:</p>
<pre>virtual GLfloat* vertex(unsigned int i) {
  if (_pMesh-&gt;pInterleaved != NULL)
    return (GLfloat*)(_pMesh-&gt;pInterleaved+(size_t)_pMesh-&gt;sVertex.pData+i*_pMesh-&gt;sVertex.nStride);
  else
    return &amp;((GLfloat*)(_pMesh-&gt;sVertex.pData))[i*_pMesh-&gt;sVertex.nStride];
} // vertex()</pre>
<p>If you&#8217;ve loaded your meshes from a POD file, you can just call this as below (note that _pMesh is an SPODMesh* and texGenObjectLinearInPlace() will compute the new texcoords in-place, over-writing the texture coords in the SPOD data structure.)</p>
<pre>GLfloat* uvArray() {
  if (_pMesh-&gt;pInterleaved != NULL)
    return (GLfloat*)(_pMesh-&gt;pInterleaved+(size_t)_pMesh-&gt;psUVW[0].pData);
  else
    return (GLfloat*)_pMesh-&gt;psUVW[0].pData;
} // uvArray()

// Recompute text coords in-place
void texGenObjectLinearInPlace(const btVector3 &amp;sPlane, const btVector3 &amp;tPlane) {
  this-&gt;texGenObjectLinear(uvArray(), _pMesh-&gt;psUVW[0].nStride, sPlane, tPlane);
} // texGenObjectLinearInPlace()</pre>
<p>I ended up writing a general-purpose routine to &quot;re-box&quot; vertices.  Not pretty, and my brain tells me that it could be more elegant, but I haven&#8217;t figured out how yet.  Perhaps after I&#8217;m rested up&#8230;</p>
<pre>void BMWDrawableObject::reBoxVertices(GLfloat* buf, unsigned int stride, unsigned int numVtx,
       unsigned int coordsPerVert, const btVector4 &amp;min, const btVector4 &amp;max) {
  // Calculate (in-place) the new vertices based on the min and max vertices passed in.
  GLfloat* pStart = buf;
  btVector4 minAccum(FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX);
  btVector4 maxAccum(FLT_MIN, FLT_MIN, FLT_MIN, FLT_MIN);

  // Compute the current nD bounding box
  unsigned char* p = (unsigned char*)pStart;
  for (unsigned int i=0; i &lt; numVtx; i++, p+=stride) {
    buf = (GLfloat*)p;
    for (unsigned int j=0; j &lt; coordsPerVert; j++) {
      minAccum[j] = (buf[j] &lt; minAccum[j]) ? buf[j] : minAccum[j];
      maxAccum[j] = (buf[j] &gt; maxAccum[j]) ? buf[j] : maxAccum[j];
    }
  }

  // Compute scale and offset to be used on each vertex.
  btVector4 offset(min[0]-minAccum[0], min[1]-minAccum[1], min[2]-minAccum[2], min[3]-minAccum[3]);
  btVector4 oD(maxAccum[0]-minAccum[0], maxAccum[1]-minAccum[1], maxAccum[2]-minAccum[2], maxAccum[3]-minAccum[3]);
  btVector4 nD(max[0]-min[0], max[1]-min[1], max[2]-min[2], max[3]-min[3]);
  btVector4 scale(nD[0]/oD[0], nD[1]/oD[1], nD[2]/oD[2], nD[3]/oD[3]);

  // Loop through and set the values.
  p = (unsigned char*)pStart;
  for (unsigned int i=0; i &lt; numVtx; i++, p+=stride) {
    buf = (GLfloat*)p;
    for (unsigned int j=0; j &lt; coordsPerVert; j++)
      buf[j] = (buf[j]+offset[j])*scale[j];
  }
} // reBoxVertices()</pre>
<p>Putting it all together, imagine that I want to map a texture to a hemisphere.  The texture is projected from the XY plan.  Here&#8217;s how I would call the above routines to accomplish that:</p>
<pre>    // Generate new texcoords based on OBJECT_LINEAR algorithm
    // We are going to put the data right back into the Mesh's UV array.
    // (pDef is a pointer to an object with the SPODMesh* _pMesh.)
    pDef-&gt;texGenObjectLinearInPlace(btVector3(1,0,0), btVector3(0,1,0));
    // Normalize the UV coords such that the texture wraps all the way around.
    reBoxVertices(pDef-&gt;uvArray(), pDef-&gt;mesh()-&gt;psUVW[0].nStride, pDef-&gt;numVertices(),
                                   pDef-&gt;mesh()-&gt;psUVW[0].n, btVector4(0,0,0,0), btVector4(1,1,1,1));
    // Re-load the VBO since we've changed the data
    pDef-&gt;loadVBO();</pre>
<h2>Additional Texturing Resources</h2>
<p><strong>Cube Mapping</strong></p>
<p><a title="Cube mapping description." href="http://developer.nvidia.com/object/cube_map_ogl_tutorial.html" target="_blank" title="Cube mapping description.">http://developer.nvidia.com/object/cube_map_ogl_tutorial.html</a> (Uses OpenGL extensions not available to us, but explains the process.)</p>
<p><a title="More cube mapping references." href="http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&amp;Number=247684" target="_blank" title="More cube mapping references.">http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&amp;Number=247684</a></p>
<p><strong>Spherical Mapping<br />
</strong></p>
<p><a title="Spherical mapping information." href="http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=23" target="_blank" title="Spherical mapping information.">http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=23</a></p>
<p><strong>Bump Mapping Tutorial</strong></p>
<p><a title="Bump mapping tutorial." href="http://www.paulsprojects.net/tutorials/simplebump/simplebump.html" target="_blank" title="Bump mapping tutorial.">http://www.paulsprojects.net/tutorials/simplebump/simplebump.html</a></p>
<p><strong>Sky Boxes in Blender</strong></p>
<p><a title="How to build a skybox in Blender." href="http://en.wikibooks.org/wiki/Blender_3D:_Noob_to_Pro/Build_a_skybox" target="_blank" title="How to build a skybox in Blender.">http://en.wikibooks.org/wiki/Blender_3D:_Noob_to_Pro/Build_a_skybox</a></p>
<p><strong>Texture Sources</strong></p>
<p><a title="A library of textures, most free." href="http://www.cgtextures.com/" target="_blank" title="A library of textures, most free.">http://www.cgtextures.com/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.BluMtnWerx.com/blog/2009/06/opengl-es-texture-mapping-for-iphone-oolong-powervr/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Oolong/Bullet Collision Detection</title>
		<link>http://www.BluMtnWerx.com/blog/2009/04/oolongbullet-collision-detection/</link>
		<comments>http://www.BluMtnWerx.com/blog/2009/04/oolongbullet-collision-detection/#comments</comments>
		<pubDate>Sun, 12 Apr 2009 04:03:19 +0000</pubDate>
		<dc:creator>paul</dc:creator>
				<category><![CDATA[Resources]]></category>
		<category><![CDATA[Bullet]]></category>
		<category><![CDATA[Collision Handling]]></category>
		<category><![CDATA[Oolong]]></category>

		<guid isPermaLink="false">http://www.BluMtnWerx.com/blog/?p=80</guid>
		<description><![CDATA[Collision handling in Oolong/Bullet was not obvious.  Here is a rundown on what I learned along with some sample code from my solution.]]></description>
			<content:encoded><![CDATA[<p>One of the things that I found incredibly attractive about Oolong and the Bullet physics package (which is embedded in Oolong) was that one could get a fantastic simulation of objects bouncing around and interacting with each other and fixed objects with very little code.  The &quot;Falling Boxes&quot; example in Oolong is really cool, even though the code is simple.  However, it&#8217;s pretty important to be able to &quot;react&quot; to these collisions, and it took me a bit to figure out the best way to accomplish that.</p>
<p>What I was hoping for was a way to register a call-back with a rigid body such that my function or method would get called whenever the body collided with something.  Further, after working with the ray testing functionality, I was hoping for the same kind of filtering capabilities that the ray testing interface provides. Unfortunately, that functionality doesn&#8217;t quite exist, so you have to &quot;roll your own&quot; from what is provided.</p>
<p>The best reference on collision detection in Bullet is, I believe, <a title="Link to bullet collision detection documentation." href="http://www.bulletphysics.com/mediawiki-1.5.8/index.php?title=Collision_Callbacks_and_Triggers" target="_blank" title="Link to bullet collision detection documentation.">this one</a> .  After reading through this carefully and considering the options, I decided to use the first strategy, which is to simply loop through the manifolds at the end of each simulation cycle.  I quickly discovered that there were several issues I needed to deal with:</p>
<ul>
<li>A manifold will appear in the list and contain objects when there are no points of collision (getNumContacts() == 0) between the objects.  This surprised me!  Therefore, even though I didn&#8217;t care about the actual points of contact in my application, I needed to check the number of points and only register a collision if there were one or more.</li>
<li>Objects may remain in contact for a number of cycles.  The behavior I wanted was to be notified when objects came into contact and again when they separated.  In order to achieve this, I had to implement some state in my objects that indicated what other objects they were in contact with.  I used STL sets for this purpose, as shown below&#8230;  <em>(4/24/2009 &#8212; I have noticed that the B-Tree implementation underlying the STL set is showing up in profiling with lots of calls for allocation.  While this is not hurting the performance of my app yet, I expect that it will at some point.  I will probably end up optimizing the set implementation, probably through the use of a custom allocator.)</em></li>
</ul>
<p>Here is the code for the collision detection method, which is called after each simulation cycle:</p>
<pre>void BMWWorld::_detectCollisions() {
  // For information on collision detection using Bullet, see:
  // http://www.bulletphysics.com/mediawiki-1.5.8/index.php?title=Collision_Callbacks_and_Triggers
  //
  // Detect collisions and notify the objects involved.
  int numManifolds = this-&gt;numManifolds();
  BMWObjectSet *pNewNotifications = NULL;
  for (int i=0; i &lt; numManifolds; i++) {
    btPersistentManifold* contactManifold = this-&gt;contactManifold(i);
    int numContacts = contactManifold-&gt;getNumContacts();
    if (numContacts &gt; 0) {
      // We only notify the collision if there is a point of contact.  I suppose it's possible
      // to have really rapid, transient collisions that occurred during the simulation but
      // are still not in contact when the simulation step comes to an end.  I think our system
      // is slow enough that we can ignore these safely, but might want to keep an eye on this
      // as a future enhancement.
      // Call collision handlers for each object.
      btCollisionObject* obA = static_cast&lt;btCollisionObject*&gt;(contactManifold-&gt;getBody0());
      BMWObject* pObA = static_cast&lt;BMWObject*&gt;(obA-&gt;getUserPointer());
      btCollisionObject* obB = static_cast&lt;btCollisionObject*&gt;(contactManifold-&gt;getBody1());
      BMWObject* pObB = static_cast&lt;BMWObject*&gt;(obB-&gt;getUserPointer());
      pObA-&gt;_notifyCollision(pObB);
      pObB-&gt;_notifyCollision(pObA);
      if (pNewNotifications == NULL)
        pNewNotifications = new BMWObjectSet;
      pNewNotifications-&gt;insert(pObA);
      pNewNotifications-&gt;insert(pObB);
    }

    // The following code allows you to find out where the objects are in contact
    // with other.
//    	for (int j=0; j &lt; numContacts; j++) {
//    		btManifoldPoint&amp; pt = contactManifold-&gt;getContactPoint(j);
//
//    		btVector3 ptA = pt.getPositionWorldOnA();
//    		btVector3 ptB = pt.getPositionWorldOnB();
//    	}
//
//	// Clear all contact points out of the manifold cache
//    	contactManifold-&gt;clearManifold();
  }

  // All collisions reported.  Notify all objects in the previous notification set that we're done with
  // collision processing.  That way they can notify any handlers that collisions are complete.
  if (_pLastNotifySet != NULL) {
    BMWObjectSet::iterator itr;
    for (itr=_pLastNotifySet-&gt;begin(); itr != _pLastNotifySet-&gt;end(); itr++)
      (*itr)-&gt;_collisionDetectionComplete();
    delete _pLastNotifySet;
  }

  // Replace the notification set with the new notification set.
  _pLastNotifySet = pNewNotifications;
} // _detectCollisions()</pre>
<p>I then simply created a pure virtual collision handler interface and implemented it for objects for which I need to be notified about collisions.  Here it is:</p>
<pre>// Objects that need to handle collisions should derive from this and set
// the handler in the BMWObject.
class BMWCollision {
public:
  BMWCollision() {};
  virtual ~BMWCollision() {};

  // pObj is the object with which the collision has occurred.  This is called when
  // contact is first detected with the other object.
  virtual void handleCollision(BMWObject* pOther) = 0;

  // Called with the set of objects that we were in contact with that we're no longer
  // in contact with.  May be null or empty!
  virtual void collisionComplete(BMWObjectSet* pCollSet) = 0;
}; // class BMWCollision</pre>
<p>This interface is used by the objects when they determine that a collision has occurred or been completed, as shown here:</p>
<pre>void BMWObject::_notifyCollision(BMWObject* pObj) {
  if (_pCollHandler == NULL)
    return;

  // No collision processing if there is not a handler defined.
  // Do screening of collision notifications.  The handler is
  // only called if the &quot;other&quot; object is not in the LastCollSet.
  // The &quot;other&quot; object is always added to the NewCollSet.  When
  // all notifications are complete (the collisionDetectionComplete()
  // method is called), the objects that are in the LastCollSet but
  // not in the NewCollSet are sent to the handler.  This way the
  // handler can be appropriately called for both the detection of a
  // collision and also when the collision is complete.
  if (_pNewCollSet == NULL)
    _pNewCollSet = new BMWObjectSet;
  _pNewCollSet-&gt;insert(pObj);

  if ((_pLastCollSet == NULL) || (_pLastCollSet-&gt;count(pObj) == 0))
    _pCollHandler-&gt;handleCollision(pObj);
} // notifyCollision()

void BMWObject::_collisionDetectionComplete() {
  if (_pCollHandler == NULL)
    return;

  // Remove objects in the new collision set from the last collision set
  BMWObjectSet::iterator itr;
  if ((_pNewCollSet != NULL) &amp;&amp; (_pLastCollSet != NULL)) {
    for (itr=_pNewCollSet-&gt;begin(); itr != _pNewCollSet-&gt;end(); itr++)
        _pLastCollSet-&gt;erase(*itr);
  }

  // Notify collision handler about objects we're no longer colliding with
  // (those remaining in the last set.)
  _pCollHandler-&gt;collisionComplete(_pLastCollSet);

  // Delete the old set and swap in the new set.
  delete _pLastCollSet;
  _pLastCollSet = _pNewCollSet;
  _pNewCollSet = NULL;
} // collisionDetectionComplete()</pre>
<p>Again, if you see problems or improvements, please share with the rest of us!  This is definitely a learning process on my part!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.BluMtnWerx.com/blog/2009/04/oolongbullet-collision-detection/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Xcode Workspace Setup for Oolong</title>
		<link>http://www.BluMtnWerx.com/blog/2009/04/xcode-workspace-setup-for-oolong/</link>
		<comments>http://www.BluMtnWerx.com/blog/2009/04/xcode-workspace-setup-for-oolong/#comments</comments>
		<pubDate>Sun, 05 Apr 2009 06:19:33 +0000</pubDate>
		<dc:creator>paul</dc:creator>
				<category><![CDATA[Resources]]></category>
		<category><![CDATA[Oolong]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://www.BluMtnWerx.com/blog/?p=61</guid>
		<description><![CDATA[Paul shares some tips / HOWTO information for using Oolong gracefully with Xcode.  (Well, somewhat more gracefully.)]]></description>
			<content:encoded><![CDATA[<p><strong><em><a title="Oolong Xcode project template download." href="http://www.blumtnwerx.com/Downloads/FallingCubes_Tmplt.tgz" target="_blank" title="Oolong Xcode project template download.">Download the current version of the template by clicking here.</a> </em> </strong> The rest of this is the &quot;what&quot; and &quot;why&quot; for first timers.</p>
<p>I&#8217;m having so much fun coding, I&#8217;m having trouble finding the time to blog.  I promised the folks over on the Oolong list that I&#8217;d post some info on setting up an Xcode workspace for an Oolong project, though, so here it is.  Keep in mind that I&#8217;m new to XCode, so you guys that have been around longer please straighten me out on anything that looks incorrect.</p>
<p>First, let me explain why this matters.  Oolong is currently organized as a source tree with the examples embedded.  The examples simply refer directly to the Oolong files of interest by relative paths.  One would naturally like to use the examples as templates for new projects, but it&#8217;s difficult to get it to work unless you embed your project within Oolong alongside the examples.  Further, we&#8217;d like to put Oolong into our own SCM system (this makes managing updates easier, especially when local changes to Oolong are required) and we might have other &quot;libraries&quot; that we want to use as well.  Ideally, we&#8217;d like to create a project organization that looks something like this:</p>
<ul>
<li>Sandbox
<ul>
<li>Oolong</li>
<li>MyLibrary</li>
<li>MyProj1</li>
<li>MyProj2</li>
<li>OtherLibrary</li>
</ul>
</li>
</ul>
<p>Where MyLibrary and MyProj1 &amp; 2 are dependent on the shared Oolong and possibly OtherLibrary, all of this managed in our SCM.</p>
<p>Here&#8217;s what I did, in a nutshell, with a few details to follow:</p>
<ul>
<li>First, I put Oolong and MyLibrary into our SCM alongside each other, as shown above.</li>
<li>I pointed Xcode to these two &quot;Source Trees&quot;, which effectively adds the equivalent of good old &quot;environment variables&quot; which can be referenced by your projects.  More on how to do this in a moment as it was not obvious.</li>
<li>I created a project template from one of the Oolong examples, modifying it such that Oolong and MyLibrary are referenced through the environment variables.</li>
</ul>
<p>There are several benefits to this approach.  First, my project isn&#8217;t in the Oolong tree, which is important to me.  Secondly, I can create any number of projects from my template and <em>put them anywhere on my system</em> and they&#8217;ll still be able to find Oolong and MyLibrary via the Source Tree references.  Thirdly, it makes setting up a new team member very easy.  They just check out the source to whatever folders they like, setup the Source Trees in Xcode, and away they go.</p>
<p>Here&#8217;s how to setup your Source Trees in Xcode.</p>
<ol>
<li>Open XCode-&gt;Preferences and then click on the <strong>Source Trees</strong> button at the top.</li>
<li>Add (&#8217;+&#8217; button under list box)</li>
<li>Choose a name for the tree (this name is a string that will be used an identifier, like an environment variable, I used &quot;OOLONG_ROOT&quot;), then &quot;Oolong Root&quot; as the Display Name (a human friendly name), then the path to your Oolong tree (/Users/paul/Sandbox/Oolong in my case.)  Note that these settings are available to all your projects as they&#8217;re part of the Xcode preferences, not project settings.  Each team member will have to set these up in their Xcode preferences as they are not shared.</li>
<li>Do the same thing for any other libraries (like MyLibrary in my example.)</li>
</ol>
<p>Now that you&#8217;ve set up your source trees, you can reference them from your project.  There are two places where you&#8217;ll want to do this.  The first is in the folders (Xcode calls them &quot;Groups&quot;) containing the sources.  The second is in the build settings where you&#8217;ll use them in header and, if necessary, library search paths.</p>
<p>Note that in the following, I&#8217;m assuming you&#8217;re starting with an Oolong example, such as &quot;skeleton.&quot;</p>
<ol>
<li>I would start by changing the Oolong folder name from &quot;Classes&quot; to &quot;Oolong&quot; or something.</li>
<li>Select the Oolong folder/group and click on the <strong>info</strong> button.  On the <strong>General</strong> tab, select the &quot;Relative to Oolong Root&quot; item from the <strong>Path Type</strong> chooser.</li>
<li>Click on &quot;Choose&quot; for the <strong>Path</strong> and select the folder where Oolong resides.  If everything is setup correctly, the path setting should change to &quot;None&quot; (because the path is relative to Oolong.)</li>
<li>The folders under the Oolong folder should be corrected as necessary.  I found that the &quot;group&quot; organization in the examples didn&#8217;t always match the organization on the file system, so I changed it to match the file system.  As a result, each folder and file path can be &quot;Relative to Enclosing Group&quot; and the <strong>Path</strong> will then match the file system folder name.  It just seems cleaner to me.</li>
</ol>
<p><em>Note that as an alternative to these steps, you could also just delete the Classes folder in the example and use Add Existing Files to re-add it (choose recurse and set the reference relative to the OOLONG_ROOT source tree.)  If you use this approach, you will need to go through the Oolong hierarchy and delete stuff you don&#8217;t want in there (the compiler will help you identify this&#8230;)</em></p>
<p>Now, change the header search path:</p>
<ol>
<li>From the Project menu select <strong>Edit Project Settings</strong> .</li>
<li>On the <strong>Build</strong> tab, select &quot;All Configurations&quot; and &quot;All Settings&quot;.</li>
<li>Scroll down to &quot;Search Paths&quot;</li>
<li>In the <strong>Header Search Path</strong> field, change all the search paths that reference the Oolong location (probably by relative path, like ../../..) to <strong>&quot;$(OOLONG_ROOT)&quot;</strong> .  Here&#8217;s what mine looks like <strong>&quot;$(OOLONG_ROOT)&quot; &quot;$(OOLONG_ROOT)/Bullet/src&quot; &quot;$(OOLONG_ROOT)/Math&quot; &quot;$(OOLONG_ROOT)/Include&quot;</strong></li>
<li>There really aren&#8217;t any libraries in Oolong that are used (currently everything&#8217;s just compiled together), but you could make similar changes to the <strong>Library Search Path.</strong></li>
<li>Note that you&#8217;ll need to do the same thing for the Target.  What I would recommend is to set these at the Project level (as described), and for the target, simply use the value $(inherited).</li>
</ol>
<p>Now, for the moment of truth: Build and see what smokes.  I would highly recommend starting with a project that you&#8217;ve already built successfully within Oolong (like one of the simpler examples.)  Build it and satisfy yourself that it works, then pull it out to the side and make the changes described above and build again.  (Be sure to do a Clean before you build so that there&#8217;s no old junk lying around.)  It&#8217;s hard for me to predict what kinds of problems you might run into, but hopefully you&#8217;ll be able to sort it out based on the error messages.  If not, leave a comment to this post with the question and I (or some other kind soul) will try to help.</p>
<p>Once you&#8217;ve got the project working, clean everything up and use it as a template from which to create other projects.  I&#8217;ve found that I can quickly create a new project from such a template by:</p>
<ul>
<li>Copying the template and renaming the copy to newProjName.</li>
<li>Rename the *.xcodeproj file to newProjName.xcodeproj.</li>
<li>In Xcode, open the new project, edit the build settings and for all configurations change the <strong>Product Name</strong> (under <strong>Packaging</strong> ) to newProjName.</li>
<li>Edit the build settings for the target and make the same change.</li>
<li>Under the <strong>Groups &amp; Files</strong> window, rename the Targets as appropriate.</li>
</ul>
<p><em>4/7/2009:  I have created a template from the FallingCubes example.  This template follows the rules above and can be used as a starting point for your projects.  The template also includes the necessary additional frameworks for audio.  Instructions for using the template are contained in the ReadMe.txt file.  I hope this will save you some time mucking with Xcode. </em></p>
<p><strong><em><a title="Oolong Xcode project template download." href="http://www.blumtnwerx.com/Downloads/FallingCubes_Tmplt.tgz" target="_blank" title="Oolong Xcode project template download.">Download the template by clicking here.</a> </em> </strong></p>
<p><em>4/27/2009: Updated template, removing the Graphics Services framework from the Frameworks group.  The Graphics Services framework is a private framework and may not be used in applications released to the AppStore.  Fortunately, it&#8217;s not needed!</em></p>
<p><em>4/30/2009: After some great discussion on performance tuning on the Oolong mailing list, I&#8217;ve updated the template with the &quot;right&quot; (or is it &quot;better&quot;?) compiler flags.  Be sure to check out the <a title="Link to Oolong Performance thread in the Oolong Archives." href="http://lists.oolongengine.com/private.cgi/oolong-oolongengine.com/2009-April/000726.html" target="_blank" title="Link to Oolong Performance thread in the Oolong Archives.">Oolong Performance thread</a> for the last two days.  Also, if you&#8217;re interested in iPhone performance, be sure to check out this <a title="Link to OpenGL performance issues on iPhone." href="https://devforums.apple.com/thread/6546?start=0&amp;tstart=0" target="_blank" title="Link to OpenGL performance issues on iPhone.">thread on the DevForum</a> .</em></p>
<p>It would be best if Oolong were built as a &quot;Framework&quot; (pre-compiled sources in .a files with accompanying header files like the Apple frameworks) but I haven&#8217;t gone that far yet.  For the moment, the approach above is sufficient for my needs.  However, if the internal source organization of upcoming Oolong releases change, we&#8217;re  toast.  We&#8217;ll have to monkey with the structure of all of the projects that use Oolong.  Therefore, a logical &quot;next step&quot; is to make Oolong a Framework.  In fact, it would be great if the next release of Oolong was setup to build itself as a framework.  I&#8217;m willing to help&#8230;</p>
<p>I feel like I&#8217;ve probably made some errors and left things out.  Please don&#8217;t hesitate to correct me or let me know when there&#8217;s yet a better way!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.BluMtnWerx.com/blog/2009/04/xcode-workspace-setup-for-oolong/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Blender to POD for Oolong</title>
		<link>http://www.BluMtnWerx.com/blog/2009/03/blender-to-pod-for-oolong/</link>
		<comments>http://www.BluMtnWerx.com/blog/2009/03/blender-to-pod-for-oolong/#comments</comments>
		<pubDate>Mon, 23 Mar 2009 17:21:23 +0000</pubDate>
		<dc:creator>paul</dc:creator>
				<category><![CDATA[Resources]]></category>
		<category><![CDATA[Blender]]></category>
		<category><![CDATA[Oolong]]></category>
		<category><![CDATA[OpenGL-ES]]></category>
		<category><![CDATA[PowerVR]]></category>

		<guid isPermaLink="false">http://www.BluMtnWerx.com/blog/?p=38</guid>
		<description><![CDATA[For those of you who, like me, are just getting started developing with OpenGL-ES for the iPhone, one of the challenges is building some meshes to work with.  This post gives some pointers on using the open source Blender tool for your 3D modeling.]]></description>
			<content:encoded><![CDATA[<p>For those of you who, like me, are just getting started developing with OpenGL-ES for the iPhone, one of the challenges is building some meshes to work with.  If you don&#8217;t have lots of money to spend on the real &quot;pro&quot; tools, you&#8217;ll want to check out <a title="Link to Blender web site." href="http://www.blender.org/" target="_blank" title="Link to Blender web site.">Blender</a> (<a title="Link to Blender web site." href="http://www.blender.org/" target="_blank" title="Link to Blender web site.">http://www.blender.org</a> ).  Blender is a feature-rich, but somewhat hard to learn, open-source 3D modeling and animation environment.  It even has integrated physics simulation and scripting.  To get up to speed on Blender, I highly recommend the <a title="Link to Wikibooks web site." href="http://www.wikibooks.org/" target="_blank" title="Link to Wikibooks web site.">Wikibooks</a> tutorial <a title="Link to Blender tutorial." href="http://en.wikibooks.org/wiki/Blender_3D/Noob_to_Pro" target="_blank" title="Link to Blender tutorial.">Blender 3D: Noob to Pro</a> .  Once you face the Blender GUI for the first time, you&#8217;ll be very thankful for this grand effort at a tutorial!</p>
<p>Before I go on, I need to state that I&#8217;m a real noob myself and my needs at this point only include the creation of some meshes that I&#8217;m going to import into my application and then manage entirely there.  I haven&#8217;t yet had a need or chance to try out boned meshes or any of the animation features.  That being said, here are a few guidelines for developing your meshes in Blender with the intenion of importing them into an <a title="Link to Oolong web site." href="http://oolongengine.com/" target="_blank" title="Link to Oolong web site.">Oolong</a> (<a title="Link to PowerVR SDK web site." href="http://www.imgtec.com/powervr/insider/powervr-sdk.asp" target="_blank" title="Link to PowerVR SDK web site.">PowerVR</a> ) application as POD files.</p>
<ul>
<li>Go ahead and create your meshes in Blender, but recognize that rendering is going to be performed in your application, so don&#8217;t spend a lot of time trying to get it to look &quot;just right&quot; in the Blender renderer.</li>
<li>You can set up initial light and camera locations in Blender.  These are imported in the POD file.</li>
<li>Create and apply your materials in Blender.  Materials will be imported in the POD file (although I can&#8217;t find the Emission component yet.)</li>
<li>Note that meshes with different materials on different faces will be split up into multiple meshes (with a single parent mesh.)  For instance, a cube with a different material on each face will be split up into 6 different meshes, one for each face.  Each of these &quot;child&quot; meshes will have a pointer to the parent node.  More on how to deal with this in Oolong later.</li>
<li>Right now, I&#8217;m applying textures to textured surfaces as place-holders only.  This ensures that the UV coordinates are included in the interleaved vertex data.  In Oolong, textures are imported from PVR files, and I haven&#8217;t yet figured out a path from Blender texture to PVR.  If you can help out with this, please chime in!  The result is that you will have to figure out the right texture settings through experimentation.</li>
</ul>
<p>Once you have your meshes built, you&#8217;ll want to do the export/import dance to get to POD.  Right now, it appears that the best path is from Blender to Collada 1.4 (via the Blender Export menu) then from Collada to POD via the PowerVR Collada2POD tool.  (Collada2POD is in the utilities folder of the PowerVR SDK distribution.)  Sorry, I couldn&#8217;t find a Mac OS-X version of the SDK, so I have to use a Windows PC for this step.  Here are the settings I&#8217;ve come up with for the export and import.</p>
<h2>Export to Collada 1.4 Settings</h2>
<ul>
<li>Set the geometry type to triangles.</li>
<li>Don&#8217;t set anything else.  I tried messing with the &quot;UV Image Materials&quot; but didn&#8217;t find that useful.</li>
</ul>
<p>That&#8217;s all.</p>
<h2>Collada2POD Settings</h2>
<ul>
<li>Under geometry options select (not all of these may be required, I didn&#8217;t experiment with dropping any out.):
<ul>
<li>Normals</li>
<li>Vertex Colors</li>
<li>Mapping Channels</li>
<li>Flip V</li>
<li>Interleave Vectors</li>
</ul>
</li>
<li>PowerVR documentation recommends sorted, indexed, triangle strips for performance, so I turned on
<ul>
<li>Sort vertices with PVRTTriStrip</li>
<li>Indexed Triangle List</li>
</ul>
</li>
<li>I haven&#8217;t selected anything special in the Vertex vector formats.</li>
<li>The resulting POD file can be automatically opened in PVR Shaman for examination by simply setting up the path on the Post-Export tab.</li>
</ul>
<p>I used the Shadowing example as the template for how to load POD and PVR texture files.  Here are a few notes on what I&#8217;ve discovered:</p>
<ul>
<li>A &quot;SPODNode&quot; is created for each instance of a mesh, the camera and light, and each parent node (for composite meshes.)  The Node has a link to it&#8217;s defining mesh, a transform, and a link to it&#8217;s SPODMaterial.</li>
<li>A &quot;SPODMesh&quot; is created for each mesh and contains the interleaved, indexed, vertex data.</li>
<li>You can draw the children of  &quot;composite&quot; nodes ad-hoc if you like, because the GetWorldMatrix( ) methods automatically multiply by the parent&#8217;s transform matrix.  However, if you&#8217;re doing physics, you&#8217;ll want to treat them as a unit (a single btCollisionShape for the composite node.)</li>
<li>As mentioned before the Emission component of materials doesn&#8217;t come through, so I&#8217;m having handle that manually in my application.</li>
<li>Again, I haven&#8217;t figured out how to get textures directly from Blender to PVR.  I&#8217;m handling them separately.  Create your texture externally, use it in Blender and convert it to PVR for use in your application and fiddle to get things right.  (If you&#8217;ve got a better way, please tell us noobs about it!)</li>
<li>April 24, 2009 &#8212; Discovered that if you have a material assigned to an object, and you have also assigned materials to faces, but the material assigned to the object is not used on any of the faces, the Collada exporter will crash.  Make sure that all materials assigned to an object in blender are actually used.  Delete any that are unused before attempting to export.</li>
</ul>
<p>Note that there has been some recent discussion of this same topic on the Oolong mailing list, so I really recommend getting hooked up to that.  In particular, there is someone there working on a direct Blender reader (into the ModelPOD structures), and mention of a blender reader in the Bullet physics toolkit.  So, there may be more direct methods of using your Blender models in Oolong soon.</p>
<p>I&#8217;d really like to thank Wolfgang Engel, the PowerVR folks, the Bullet Physics team, and the rest of the Oolong contributors.  My early efforts are showing excellent performance on the device and I&#8217;m having a blast with the programming.  I don&#8217;t know where things are headed next for Oolong, but it can only get better!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.BluMtnWerx.com/blog/2009/03/blender-to-pod-for-oolong/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Getting Started</title>
		<link>http://www.BluMtnWerx.com/blog/2009/03/getting-started/</link>
		<comments>http://www.BluMtnWerx.com/blog/2009/03/getting-started/#comments</comments>
		<pubDate>Sun, 01 Mar 2009 10:15:47 +0000</pubDate>
		<dc:creator>paul</dc:creator>
				<category><![CDATA[Resources]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Oolong]]></category>
		<category><![CDATA[OpenGL]]></category>

		<guid isPermaLink="false">http://www.BluMtnWerx.com/blog/?p=8</guid>
		<description><![CDATA[We're just getting started with iPhone application development.  Paul shares some experiences and resources that he's found over the first two weeks.]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been roughly two weeks since we&#8217;ve seriously embarked on this iPhone development project.  Along with about a million others, it seems.  It reminds me a bit of the &#8216;49ers and the gold rush.  A recession, tales of AppStore wealth, and the desire to be part of a very &quot;cool&quot; transition in computing have lured many of us to leave what we know for a brave new frontier.</p>
<p>It&#8217;s definitely been a new frontier for me.  After years and years of large application development in the computer aided engineering fields on *NIX and Windows platforms, much is new:</p>
<ul>
<li>The Mac development platform</li>
<li>Objective-C</li>
<li>3D Graphics</li>
<li>Small, lightweight programs</li>
<li>Touch UI</li>
<li>A different kind of user</li>
</ul>
<p>My bookshelves are full of books that are not relevant.  My office has 4 Windows machines and 2 Sun Ultra-Sparc Solaris computers.  I obviously have a major transition to make.  But, I know how to develop quality software.</p>
<p>To bootstrap ourselves, Dean and I did a lot of up-front reading.  There are many helpful blogs out there for newbs like ourselves.  One we found particularly useful is by <a title="Craig Hockenberry's bootstrap post." href="http://furbo.org/2009/02/19/bootstrap" target="_blank" title="Craig Hockenberry's bootstrap post.">Craig Hockenberry over on furbo.org</a> .</p>
<h2>Step 1 &#8212; Sign up on the Apple iPhone developer site and start reading.</h2>
<p>This step was easy.  There is a wealth of information on the Apple Developer Connection web site.  I spent some serious time with the materials on the web site relevant to the Cocoa SDK, the iPhone software architecture, Objective-C, and XCode.  I&#8217;ve spent 20 years with C++ so Objective-C looks pretty weird, but I can certainly understand the motivation for some of the differences.  Apple has definitely built themselves an island with this one!  (Later I learned that I can use Objective-C++ and I now feel right at home.)</p>
<h2>Step 2 &#8212; Buy a Mac.</h2>
<p>After spending some serious time on eBay, I found a Buy It Now Macbook with 13&quot; display, 2GHz, and 1GB of RAM for $650 with shipping.  I&#8217;m used to buying cheap Windows laptops, so the cost of a Macbook was a bit shocking (I saw a Macbook Pro that had had Gatorade spilled in it go at auction for over $700!) but $650 was certainly acceptable.  When I received the Macbook, it was nearly pristine.  In fact, I am so happy with the quality and rapid service that I want to put in a plug for <a title="Link to Beta Macs web site." href="http://www.betamacs.com/" target="_blank" title="Link to Beta Macs web site.">Beta Macs</a> in Denver.  Check out their <a title="Beta Macs eBay Store" href="http://stores.ebay.com/Betamacs-Sales-Wholesale" target="_blank" title="Beta Macs eBay Store">eBay store</a> as well if you&#8217;re looking for a Macbook to get started with.</p>
<p>I read that for development at least 2GB of memory was advised, so I picked up 4GB of RAM from Tiger Direct for $50 along with a 250GB 2.5&quot; USB drive for extra storage and backups.</p>
<p>The Macbook was instantly loved at our house.  My 12 year old daughter now wants one, even though she has a Gateway dual-core X64 Windows laptop that she uses.  My 16 yr old son thinks it&#8217;s cool and likes Garage Band.  I like it, and I especially like having the Bash command-line and *NIX functionality at my fingertips without loading CygWin.  In fact, I&#8217;m totally in love with Mac OS-X for that reason.  Basing it on UNIX was brilliant.</p>
<h2>Step 3 &#8212; Download the iPhone SDK and watch videos.</h2>
<p>Downloading and installing the iPhone SDK was a breeze.  I also spent most of a day watching the iPhone tutorial videos on iTunes.  This is time well spent just to learn all the new terminology.</p>
<h2>Step 4 &#8212; More Research.</h2>
<p>One of the first applications I want to develop is a game where I&#8217;ll be employing some 3D graphics.  As I looked at OpenGL-ES and the rest of the SDK, it became apparent that the graphics SDK was pretty primitive (Cocoa has lots of the stuff you need for UI programming, but OpenGL is just a &#8216;C&#8217; API and definitely needs some OO stuff around it.)  Before I tore off and re-invented the wheel, I did some research to see what others have done.  Here&#8217;s what I found:</p>
<ul>
<li><a title="OpenGL C++ Toolkit web site." href="http://www.nigels.com/glt/" target="_blank" title="OpenGL C++ Toolkit web site.">OpenGL C++ Toolkit</a> &#8211; A C++ library and toolkit for OpenGL.  Probably couldn&#8217;t be used &quot;out of the box&quot; but could probably be ported without too much trouble (if it hasn&#8217;t happened already).</li>
<li><a title="Open Scene Graph web site." href="http://www.openscenegraph.org/projects/osg" target="_blank" title="Open Scene Graph web site.">Open Scene Graph</a> &#8211; An Open Source scene graph SDK for OpenGL.  Looks very powerful and, again, could probably be ported in whole or in part.  Significant overkill for the applications I&#8217;m currently imagining.</li>
<li><a title="Oolong web site." href="http://oolongengine.com/" target="_blank" title="Oolong web site.">Oolong iPhone Game Engine</a> &#8212; Now we&#8217;re talking.  A 3D graphics toolkit over OpenGL ES, based on the <a title="PowerVR SDK web site." href="http://www.imgtec.com/powervr/insider/powervr-sdk.asp" target="_blank" title="PowerVR SDK web site.">PowerVR SDK</a> , with the <a title="Bullet Physics web site." href="http://www.bulletphysics.com/Bullet/wordpress/" target="_blank" title="Bullet Physics web site.">Bullet</a> physics library integrated.  (Note that this effort is still pretty young, so there isn&#8217;t a lot of documentation with the kit, but it is usable.  Be sure to also download the PowerVR SDK for both the tools and documentation.)  The jury is out as to the performance of this beast on the device, but it is a great starting point.  I hope to contribute to the project over time.</li>
</ul>
<p>With Oolong, I think I&#8217;ve found the giant I want to stand on.  I&#8217;d much rather contribute to an infant effort than re-invent the wheel.</p>
<h2>Step 5 &#8212; Setup a web site.</h2>
<p>This obviously doesn&#8217;t get us any closer to having an iPhone app, but Dean and I felt it important to get a blog, web site, and source code management system setup as early as possible.  We&#8217;re both most familiar with CVS (I&#8217;ve used it for over 15 years) but decided to go with Subversion for it&#8217;s features.  I can setup a CVS repository on a server in about 5 minutes.  Setting up Subversion took me a long time.  It seems to be working well, however, and we&#8217;ll see how things go long term.  We can always fall back to CVS if we need to.  If you need pointers on setting up Subversion on a Plesk managed server, maybe I can help.  It wasn&#8217;t as hard as I made it!  The XCode integration looks pretty good, and I dowloaded a trial copy of the <a title="SmartSVN web site." href="http://www.syntevo.com/smartsvn/features.html" target="_blank" title="SmartSVN web site.">SmartSVN</a> client as well for it&#8217;s tag and branch features.</p>
<p>The web site is simple at this point.  We&#8217;ll be expanding it as we have applications to push and things to share.  This blog will be our primary means of communication.</p>
<h2>Step 6 &#8212; Start coding.</h2>
<p>Yeah!  Finally.  After some serious coding, I&#8217;ve decided I really like XCode.  I haven&#8217;t poked into everything yet, but I&#8217;m getting the hang of it and it&#8217;s working really well.  Most of the coding I&#8217;m doing right now is in C++ around OpenGL and Oolong.  Results are coming fast now, although I still have a whole lot to learn before I&#8217;ve got a complete application.</p>
<h2>Next Step &#8212; Acquire a device.</h2>
<p>Yep, haven&#8217;t done that yet.  Right now I&#8217;m running in the simulator which works pretty well but doesn&#8217;t give you the feel of the device at all, especially for accelerometer stuff.  Even the touch interactions are very different.  I&#8217;m particularly concerned about the performance of Oolong given all the floating point computations.  I should have a device (I&#8217;m starting with an iPod Touch) next weekend, and then I&#8217;ve got to pay my $99 and get the provisioning stuff together.</p>
<p>Lots to do, but I&#8217;m having a lot of fun!  Makes me feel young again.</p>
<p>paul</p>
]]></content:encoded>
			<wfw:commentRss>http://www.BluMtnWerx.com/blog/2009/03/getting-started/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
