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

 Most View
 -  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