MULTIMEDIA

iPhone 3D Programming : Adding Textures to ModelViewer (part 1) - Enhancing IResourceManager

1/21/2011 7:40:23 PM
Our final enhancement to ModelViewer wraps a simple grid texture around each of the surfaces in the parametric gallery, as shown in Figure 1. We need to store only one cell of the grid in an image file; OpenGL can repeat the source pattern as many times as desired.
Figure 1. Textured ModelViewer


The image file can be in a number of different file formats, but we’ll go with PNG for now. It’s popular because it supports an optional alpha channel, lossless compression, and variable color precision.

To keep things simple, the first step is rewinding a bit and using parametric surfaces exclusively. Simply revert the ApplicationEngine::Initialize method so that it uses the sphere and cone shapes. To do this, find the following code:

string path = m_resourceManager->GetResourcePath();
surfaces[0] = new ObjSurface(path + "/micronapalmv2.obj");
surfaces[1] = new ObjSurface(path + "/Ninja.obj");

And replace it with the following:

surfaces[0] = new Cone(3, 1);
surfaces[1] = new Sphere(1.4f);

Keep everything else the same. We’ll enhance the IResourceManager interface later to support image loading.

Next you need to add the actual image file to your Xcode project. Xcode automatically deploys these resources to your iPhone. Even though this example has only a single image file, I recommend creating a dedicated group anyway. Right-click the ModelViewer root in the OverviewAddNew Group, and call it Textures. Right-click the new group, and choose Get Info. To the right of the Path label on the General tab, click Choose, and create a new folder called Textures. Click Choose, and close the group info window. pane, choose

Right-click the new group, and choose AddExisting Files. Select the PNG file, click Add, and in the next dialog box, make sure the “Copy items” checkbox is checked; then click Add.

1. Enhancing IResourceManager

Unlike OBJ files, it’s a bit nontrivial to decode the PNG file format by hand since it uses a lossless compression algorithm. Rather than manually decoding the PNG file in the application code, it makes more sense to leverage the infrastructure that Apple provides for reading image files. Recall that the ResourceManager implementation is a mix of Objective-C and C++; so, it’s an ideal place for calling Apple-specific APIs. Let’s make the resource manager responsible for decoding the PNG file. The first step is to open Interfaces.hpp and make the changes shown in Example 1. New lines are in bold (the changes to the last two lines, which you’ll find at the end of the file, are needed to support a change we’ll be making to the rendering engine).

Example 1. Enhanced IResourceManager
struct IResourceManager {
virtual string GetResourcePath() const = 0;
virtual void LoadPngImage(const string& filename) = 0;
virtual void* GetImageData() = 0;
virtual ivec2 GetImageSize() = 0;
virtual void UnloadImage() = 0;
virtual ~IResourceManager() {}
};

// ...
namespace ES1 { IRenderingEngine*
CreateRenderingEngine(IResourceManager* resourceManager); }
namespace ES2 { IRenderingEngine*
CreateRenderingEngine(IResourceManager* resourceManager); }


Now let’s open ResourceManager.mm and update the actual implementation class (don’t delete the #imports, the using statement, or the CreateResourceManager definition). It needs two additional items to maintain state: the decoded memory buffer (m_imageData) and the size of the image (m_imageSize). Apple provides several ways of loading PNG files; Example 2 is the simplest way of doing this.

Example 2. ResourceManager with PNG loading
class ResourceManager : public IResourceManager {
public:
string GetResourcePath() const
{
NSString* bundlePath =[[NSBundle mainBundle] resourcePath];
return [bundlePath UTF8String];
}
void LoadPngImage(const string& name)
{
NSString* basePath = [NSString stringWithUTF8String:name.c_str()];
NSString* resourcePath = [[NSBundle mainBundle] resourcePath];
NSString* fullPath = [resourcePath stringByAppendingPathComponent:basePath];
UIImage* uiImage = [UIImage imageWithContentsOfFile:fullPath];
CGImageRef cgImage = uiImage.CGImage;
m_imageSize.x = CGImageGetWidth(cgImage);
m_imageSize.y = CGImageGetHeight(cgImage);
m_imageData = CGDataProviderCopyData(CGImageGetDataProvider(cgImage));
}
void* GetImageData()
{
return (void*) CFDataGetBytePtr(m_imageData);
}
ivec2 GetImageSize()
{
return m_imageSize;
}
void UnloadImage()
{
CFRelease(m_imageData);
}
private:
CFDataRef m_imageData;
ivec2 m_imageSize;
};



Most of Example 2 is straightforward, but LoadPngImage deserves some extra explanation:


Next we need to make sure that the resource manager can be accessed from the right places. It’s already instanced in the GLView class and passed to the application engine; now we need to pass it to the rendering engine as well. The OpenGL code needs it to retrieve the raw image data.

Go ahead and change GLView.mm so that the resource manager gets passed to the rendering engine during construction. Example 3 shows the relevant section of code (additions are shown in bold).

Example 3. Creation of ResourceManager, RenderingEngine, and ApplicationEngine
m_resourceManager = CreateResourceManager();

if (api == kEAGLRenderingAPIOpenGLES1) {
NSLog(@"Using OpenGL ES 1.1");
m_renderingEngine = ES1::CreateRenderingEngine(m_resourceManager);
} else {
NSLog(@"Using OpenGL ES 2.0");
m_renderingEngine = ES2::CreateRenderingEngine(m_resourceManager);
}

m_applicationEngine = CreateApplicationEngine(m_renderingEngine,
m_resourceManager);
Other  
  •  Programming with DirectX : Shading and Surfaces - Implementing Texture Mapping (part 2) - Multi Texture Demo
  •  Programming with DirectX : Shading and Surfaces - Implementing Texture Mapping (part 1) - 2D Texture Mapping Demo
  •  Building Out Of Browser Silverlight Applications - Using COM Interoperability and File System Access
  •  Building Out Of Browser Silverlight Applications - Controlling the Application Window
  •  iPhone 3D Programming : Adding Depth and Realism - Loading Geometry from OBJ Files
  •  iPhone 3D Programming : Adding Depth and Realism - Better Wireframes Using Polygon Offset
  •  Programming with DirectX : Textures in Direct3D 10 (part 2)
  •  Programming with DirectX : Textures in Direct3D 10 (part 1) - Textures Coordinates
  •  Programming with DirectX : Shading and Surfaces - Types of Textures
  •  iPhone 3D Programming : Adding Shaders to ModelViewer (part 2)
  •  iPhone 3D Programming : Adding Shaders to ModelViewer (part 1) - New Rendering Engine
  •  iPhone 3D Programming : Adding Depth and Realism - Shaders Demystified
  •  Programming with DirectX : Transformation Demo
  •  Programming with DirectX : View Transformations
  •  Programming with DirectX : World Transformations
  •  Programming with DirectX : Projection Transformations
  •  iPhone 3D Programming : Adding Depth and Realism - Lighting Up (part 2)
  •  iPhone 3D Programming : Adding Depth and Realism - Lighting Up (part 1)
  •  iPhone 3D Programming : Adding Depth and Realism - Surface Normals (part 2)
  •  iPhone 3D Programming : Adding Depth and Realism - Surface Normals (part 1)
  •  
    Most View
    Installing HP-UX : Loading Patches
    LG LM9600 47” Smart TV - A New Direction
    HP Photosmart 7520 e-All-in-One
    Acer CloudMobile - Ambitious Android Phone (Part 2)
    What To Do With An Old Mac (Part 1)
    Deploying to an iPhone, Debugging, and Testing : Distributing Your Application
    How To Choose A Printer (Part 2)
    Nvidia GeForce GTX Titan 6 GB Graphics Card Review (Part 1)
    Appetizing Art - The Complete Picture (Part 2)
    How To Deal With Windows And Network-Related Problems (Part 2)
    Top 10
    The NZXT Kraken X40 Compact Liquid Cooler Review (Part 3)
    The NZXT Kraken X40 Compact Liquid Cooler Review (Part 2)
    T-Mobile’s Samsung Galaxy Note II Review (Part 6)
    T-Mobile’s Samsung Galaxy Note II Review (Part 5)
    T-Mobile’s Samsung Galaxy Note II Review (Part 4)
    T-Mobile’s Samsung Galaxy Note II Review (Part 3)
    T-Mobile’s Samsung Galaxy Note II Review (Part 2)
    T-Mobile’s Samsung Galaxy Note II Review (Part 1)
    Sony Cybershot DSC-TF1 - Affordable Water-Resistant Camera
    Buffalo MiniStation Slim 500GB External Hard Drive