Having a lot of trouble getting texture maps to work in openGL ES (iphone).
Here's what I've done:
- built an array of vertexes
- built an array of faces that reference the indices of the array of vertexes for each face
- built an array of colors so I can be sure I know which vertex on the cube is which.
All of this following Jeff Lamarche's tutorials. Getting the objects rendering and moving is not a problem.
Now I'm trying to get the cube (actually a tile, narrower in Z that X or Y) to stick a texture on two opposite faces (the others can come later). I have been able to get one face to work, but I am not getting workable results on any other face.
What is the most systematic way to texture map an object in OpenGL ES, and can anyone see where the errors in my code are?
#import "GLViewController.h"
#import "ConstantsAndMacros.h"
#import "OpenGLCommon.h"
#import "Cube.h"
@implementation GLViewController
@synthesize initDone;
@synthesize tileArray;
@synthesize tileRows;
@synthesize tileCols;
@synthesize cubes;
@synthesize gridOffsetX;
@synthesize gridOffsetY;
@synthesize gridOffsetZ;
@synthesize tileSpacing;
- (void)drawView:(UIView *)theView
{
static GLfloat rot = 0.0;
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// This is the same result as using Vertex3D, just faster to type and
// can be made const this way
static const Vertex3D vertices[]= {
{1.0f, -1.0f, 0.2f},
{1.0f, -1.0f, -0.2f},
{1.0f, 1.0f, -0.2f},
{1.0f, 1.0f, 0.2f},
{-1.0f, -1.0f, 0.2f},
{-1.0f, -1.0f, -0.2f},
{-1.0f, 1.0f, -0.2f},
{-1.0f, 1.0f, 0.2f}
};
static const Color3D colors[] = {
{1.0, 0.0, 0.0, 20.0},
{1.0, 1.0, 1.0, 20.0},
{1.0, 1.0, 1.0, 20.0},
{0.0, 0.0, 1.0, 20.0},
{0.0, 1.0, 0.0, 20.0},
{1.0, 1.0, 1.0, 20.0},
{1.0, 1.0, 1.0, 20.0},
{1.0, 1.0, 1.0, 20.0},
};
static const GLubyte cubeFaces[] = {
0, 1, 3,
2, 3, 1,
0, 3, 4,
3, 4, 7, // first main face
2, 1, 6, // second main face
1, 6, 5,
5, 6, 7,
5, 4, 7,
7, 6, 3,
6, 3, 2,
4, 0, 5,
1, 0, 5,
};
static const Vector3D normals[] = {
{0.200000, -0.400000, 0.000000},
{0.400000, -0.200000, -0.400000},
{0.333333, 0.333333, -0.333333},
{0.400000, 0.400000, -0.200000},
{-0.333333, -0.333333, 0.333333},
{-0.400000, -0.400000, -0.200000},
{-0.200000, 0.400000, -0.400000},
{-0.400000, 0.200000, 0.000000},
};
static const GLfloat texCoords[] = {
0.0, 0.0, // texture face
1.0, 1.0,
0.0, 1.0,
1.0, 1.0,
0.0, 0.0,
1.0, 0.0,
0.0, 0.0, // texture face
1.0, 1.0,
1.0, 0.0,
1.0, 0.0,
0.0, 1.0,
1.0, 1.0,
0.0, 0.0, // texture face
1.0, 1.0,
0.0, 1.0,
1.0, 1.0,
0.0, 0.0,
1.0, 0.0,
0.0, 0.0, // texture face
1.0, 1.0,
0.0, 1.0,
1.0, 1.0,
0.0, 0.0,
1.0, 0.0,
0.0, 0.0, // texture face
1.0, 1.0,
0.0, 1.0,
1.0, 1.0,
0.0, 0.0,
1.0, 0.0,
0.0, 0.0, //
1.0, 1.0,
0.0, 1.0,
1.0, 1.0,
0.0, 0.0,
1.0, 0.0,
};
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
glLoadIdentity();
glClearColor(0.7, 0.7, 0.7, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glColorPointer(4, GL_FLOAT, 0, colors);
glNormalPointer(GL_FLOAT, 0, normals);
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
NSMutableArray *tempRow;
Cube *tempCube;
for (int i = 1; i <= cubes.tileRows; i++)
{
tempRow = [cubes rowAtIndex:i-1];
for (int j = 1; j <= cubes.tileCols; j++)
{
tempCube = [tempRow objectAtIndex:j-1];
glLoadIdentity();
glTranslatef(gridOffsetX + (tileSpacing * (GLfloat)i), gridOffsetY + (tileSpacing * (GLfloat)j), gridOffsetZ);
glRotatef(rot, 1.0, 0.0, 0);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, cubeFaces);
}
}
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
static NSTimeInterval lastDrawTime;
if (lastDrawTime)
{
NSTimeInterval timeSinceLastDraw = [NSDate timeIntervalSinceReferenceDate] - lastDrawTime;
rot+=30 * timeSinceLastDraw;
}
//NSLog(@"rot is %f", rot);
lastDrawTime = [NSDate timeIntervalSinceReferenceDate];
}
-(void)setupView:(GLView*)view
{
initDone = NO;
tileRows = 5;
tileCols = 7;
gridOffsetX = 5.2f;
gridOffsetY = 6.9f;
gridOffsetZ = -14.0;
tileSpacing = -2.15f;
cubes = [[Cubes alloc] initWithRowCount:tileRows colCount: tileCols ];
const GLfloat zNear = 0.01, zFar = 1000.0, fieldOfView = 50.0;
GLfloat size;
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
size = zNear * tanf(DEGREES_TO_RADIANS(fieldOfView) / 2.0);
CGRect rect = view.bounds;
// glOrthof(-5.0, // Left
// 5.0, // Right
// -5.0 / (rect.size.width / rect.size.height), // Bottom
// 5.0 / (rect.size.width / rect.size.height), // Top
// 0.01, // Near
// 10000.0); // Far
glFrustumf(-size, size, -size / (rect.size.width / rect.size.height), size /
(rect.size.width / rect.size.height), zNear, zFar);
glViewport(0, 0, rect.size.width, rect.size.height);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_COLOR_MATERIAL);
// Enable lighting
glEnable(GL_LIGHTING);
// Turn the first light on
glEnable(GL_LIGHT0);
// Define the ambient component of the first light
const GLfloat light0Ambient[] = {0.5, 0.5, 0.5, 1.0};
glLightfv(GL_LIGHT0, GL_AMBIENT, light0Ambient);
// Define the diffuse component of the first light
const GLfloat light0Diffuse[] = {0.7, 0.7, 0.7, 1.0};
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0Diffuse);
// Define the specular component and shininess of the first light
const GLfloat light0Specular[] = {0.7, 0.7, 0.7, 1.0};
const GLfloat light0Shininess = 0.4;
glLightfv(GL_LIGHT0, GL_SPECULAR, light0Specular);
// Define the position of the first light
const GLfloat light0Position[] = {0.0, 10.0, 10.0, 0.0};
glLightfv(GL_LIGHT0, GL_POSITION, light0Position);
// Define a direction vector for the light, this one points right down the Z axis
const GLfloat light0Direction[] = {0.0, 0.0, -1.0};
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light0Direction);
// Define a cutoff angle. This defines a 90° field of vision, since the cutoff
// is number of degrees to each side of an imaginary line drawn from the light's
// position along the vector supplied in GL_SPOT_DIRECTION above
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 45.0);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_SRC_COLOR);
glGenTextures(1, &texture[0]);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
NSString *path = [[NSBundle mainBundle] pathForResource:@"a-tile-64" ofType:@"png"];
NSData *texData = [[NSData alloc] initWithContentsOfFile:path];
UIImage *image = [[UIImage alloc] initWithData:texData];
if (image == nil)
NSLog(@"Do real error checking here");
GLuint width = CGImageGetWidth(image.CGImage);
GLuint height = CGImageGetHeight(image.CGImage);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
void *imageData = malloc( height * width * 4 );
CGContextRef context = CGBitmapContextCreate( imageData, width, height, 8, 4 * width, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big );
CGColorSpaceRelease( colorSpace );
CGContextClearRect( context, CGRectMake( 0, 0, width, height ) );
CGContextTranslateCTM( context, 0, height - height );
CGContextDrawImage( context, CGRectMake( 0, 0, width, height ), image.CGImage );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
CGContextRelease(context);
free(imageData);
[image release];
[texData release];
glLoadIdentity();
};
- (void)dealloc
{
[tileArray release];
[cubes release];
[super dealloc];
}
@end