MULTIMEDIA

iPhone 3D Programming : Adding Textures to ModelViewer (part 2) - Generating Texture Coordinates

1/21/2011 7:41:25 PM

2. Generating Texture Coordinates

To control how the texture gets applied to the models, we need to add a 2D texture coordinate attribute to the vertices. The natural place to generate texture coordinates is in the ParametricSurface class. Each subclass should specify how many repetitions of the texture get tiled across each axis of domain. Consider the torus: its outer circumference is much longer than the circumference of its cross section. Since the x-axis in the domain follows the outer circumference and the y-axis circumscribes the cross section, it follows that more copies of the texture need to be tiled across the x-axis than the y-axis. This prevents the grid pattern from being stretched along one axis.

Recall that each parametric surface describes its domain using the ParametricInterval structure, so that’s a natural place to store the number of repetitions; see Example 4. Note that the repetition counts for each axis are stored in a vec2.

Example 4. Texture support in ParametricSurface.hpp
#include "Interfaces.hpp"

struct ParametricInterval {
ivec2 Divisions;
vec2 UpperBound;
vec2 TextureCount;
};

class ParametricSurface : public ISurface {
...
private:
vec2 ComputeDomain(float i, float j) const;
ivec2 m_slices;
ivec2 m_divisions;
vec2 m_upperBound;
vec2 m_textureCount;
};

The texture counts that I chose for the cone and sphere are shown in bold in Example 5.

Example 5. Texture support in ParametricEquations.hpp
#include "ParametricSurface.hpp"

class Cone : public ParametricSurface {
public:
Cone(float height, float radius) : m_height(height), m_radius(radius)
{
ParametricInterval interval = { ivec2(20, 20), vec2(TwoPi, 1), vec2(30,20) };
SetInterval(interval);
}
...
};

class Sphere : public ParametricSurface {
public:
Sphere(float radius) : m_radius(radius)
{
ParametricInterval interval = { ivec2(20, 20), vec2(Pi, TwoPi), vec2(20, 35) };
SetInterval(interval);
}
...
};



Next we need to flesh out a couple methods in ParametericSurface (Example 6). Recall that we’re passing in a set of flags to GenerateVertices to request a set of vertex attributes; until now, we’ve been ignoring the VertexFlagsTexCoords flag.

Example 6. Texture support in ParametricSurface.cpp
void ParametricSurface::SetInterval(const ParametricInterval& interval)
{
m_divisions = interval.Divisions;
m_slices = m_divisions - ivec2(1, 1);
m_upperBound = interval.UpperBound;
m_textureCount = interval.TextureCount;
}

...

void ParametricSurface::GenerateVertices(vector<float>& vertices,
unsigned char flags) const
{
int floatsPerVertex = 3;
if (flags & VertexFlagsNormals)
floatsPerVertex += 3;
if (flags & VertexFlagsTexCoords)
floatsPerVertex += 2;

vertices.resize(GetVertexCount() * floatsPerVertex);
float* attribute = &vertices[0];

for (int j = 0; j < m_divisions.y; j++) {
for (int i = 0; i < m_divisions.x; i++) {

// Compute Position
vec2 domain = ComputeDomain(i, j);
vec3 range = Evaluate(domain);
attribute = range.Write(attribute);

// Compute Normal
if (flags & VertexFlagsNormals) {
...
}

// Compute Texture Coordinates
if (flags & VertexFlagsTexCoords) {
float s = m_textureCount.x * i / m_slices.x;
float t = m_textureCount.y * j / m_slices.y;
attribute = vec2(s, t).Write(attribute);
}
}
}
}



In OpenGL, texture coordinates are normalized such that (0,0) maps to one corner of the image and (1, 1) maps to the other corner, regardless of its size. The inner loop in Example 6 computes the texture coordinates like this:

float s = m_textureCount.x * i / m_slices.x;
float t = m_textureCount.y * j / m_slices.y;

Since the s coordinate ranges from zero up to m_textureCount.x (inclusive), OpenGL horizontally tiles m_textureCount.x repetitions of the texture across the surface.

Note that if you were loading the model data from an OBJ file or other 3D format, you’d probably obtain the texture coordinates directly from the model file rather than computing them like we’re doing here.
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
    The Best iPad Cases
    Asus P8Z68-V Pro
    Asus Zenbook UX31A : In The Prime Of Zen
    Nikon 1 V2 - Still Fast and Handles Better
    Building Applications with Visual Studio 2010 : Getting Smart about Smart Clients - Using the Properties Window
    Windows 9 : What to expect - 32-bit support , WinRT & XNA
    The Revolution Of Visual Resolution (Part 2) - BenQ XL2420T, Dell UltraSharp U2412M, Edge10 EF240a
    AOC e2752Vq – Basic Monitor With Excellent Image Quality
    Primer – Choosing And Using Peripheral Buses (Part 1)
    ASP.NET 4 and WPF Content (part 2) - WPF Content and Web Applications
    Top 10
    Windows Phone 8 In-Depth Review (Part 6)
    Windows Phone 8 In-Depth Review (Part 5)
    Windows Phone 8 In-Depth Review (Part 4)
    Windows Phone 8 In-Depth Review (Part 3)
    Windows Phone 8 In-Depth Review (Part 2)
    Windows Phone 8 In-Depth Review (Part 1)
    Xiaomi Phone 2 - High-End Specifications In A Surprisingly Cheap Package (Part 5)
    Xiaomi Phone 2 - High-End Specifications In A Surprisingly Cheap Package (Part 4)
    Xiaomi Phone 2 - High-End Specifications In A Surprisingly Cheap Package (Part 3)
    Xiaomi Phone 2 - High-End Specifications In A Surprisingly Cheap Package (Part 2)