2010-03-03 45 views
5

Tener muchos problemas para hacer que los mapas de texturas funcionen en openGL ES (iphone).¿Cómo se textura un cubo en OpenGL ES?

Esto es lo que he hecho:

  • construyeron una serie de vértices
  • construyeron una serie de caras que hacen referencia a los índices de la matriz de vértices para cada cara
  • construyeron una serie de colores entonces puedo estar seguro de saber qué vértice en el cubo es cual.

Todo esto siguiendo Jeff Lamarche's tutorials. Conseguir que los objetos se rindan y se muevan no es un problema.

Ahora estoy tratando de obtener el cubo (en realidad un azulejo, más angosto en Z que X o Y) para pegar una textura en dos caras opuestas (los otros pueden venir más adelante). He podido obtener una cara para trabajar, pero no obtengo resultados viables en ninguna otra cara.

¿Cuál es la forma más sistemática de mapear textura de un objeto en OpenGL ES, y puede alguien ver dónde están los errores en mi código?

#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 
+0

¿Los colores se muestran correctamente? –

+0

+1 para un enlace al tutorial de Jeff Lamarche. Es justo lo que necesitaba. – Bogatyr

Respuesta

2

También reinicié OpenGL ES usando los tutoriales de Jeff.

Sugiero simplificar lo que estás tratando de hacer.Por ejemplo:

  • se olvide de las Normales
  • Forget los colores
  • Forget los índices
  • Crear una estructura que une los vértices de sus atributos

Jeff proporciona una útil TexturedVertexData3D Struct que Haz esto. No es necesario que complete la parte normal si no lo desea.

A continuación, configurar sus pasos apropiadamente:

glVertexPointer(3, GL_FLOAT, sizeof(TexturedVertexData3D), &vertices[0]); 
glTexCoordPointer(2, GL_FLOAT, sizeof(TexturedVertexData3D), &vertices[0].texCoords); 

Y el uso de glDrawArrays llamar su objeto:

glDrawArrays(GL_TRIANGLES, 0, nVertices); 

vez que tenga este trabajo, seguir adelante y añadir las normales y colores en el TexturedVertexData3D struct, y configure sus punteros de textura y color de manera apropiada. Luego, vuelva a probar o publique una actualización si las cosas no funcionan.

En este punto puede comenzar a pensar en cómo usar índices. Los índices realmente no tienen sentido hasta que estés renderizando miles de vértices. Pero, cuando llegue el momento, puede obtener un buen aumento de rendimiento al usarlos.

+0

OK --- eso es bueno saberlo. Reconstruí el proyecto usando vértices explícitos de fuerza bruta, y las cosas funcionan bien, como sugirió usar GLDrawArrays. Los mapas de texturas funcionan de manera sensata, y ahora siento que puedo, como usted dice, mejorar gradualmente lo que funciona. – omnivore

0

He estado viendo esta pregunta como estoy aprendiendo OpenGL en el momento y va a pasar a OpenGL ES. Como nadie ha respondido aún, le diré lo que pienso, pero no considere esto como una opinión experta.

Algo a considerar es que tal como está, su Vertex, Color & Las matrices normales contienen 8 'elementos', sin embargo, su matriz TexCoord tiene 36 'elementos'. Estoy bastante seguro de que cuando usa glDrawElements con una lista de índices, usa esos índices para elegir elementos de TODAS las matrices activadas. Por lo tanto, los últimos 28 elementos de su matriz TexCoord nunca se usarán, se seleccionarán según los índices especificados en cubeFaces. En el tutorial que vinculó, hay cuatro elementos en todas las matrices, que funcionan muy bien para una sola cara de un objeto.

Sin embargo, esto es un problema con el uso de índices para objetos 3D, porque aunque varios vértices se vuelven a usar en un cubo, sus coordenadas de textura no serán necesariamente las mismas para los diferentes triángulos para los que se utilizan . De hecho, tampoco sus normales, por lo que puede ser otro problema con su código cuando se trata de iluminar el objeto.

No sé cuál es la mejor solución para esto, por lo que estoy interesado en otras respuestas a esta pregunta ... dibujar el vértice del cubo por vértice es una opción. También me pregunto si es posible dibujar cada cara del cubo por separado, y cambiar la matriz TexCoord cada vez. ¡O tal vez hay alguna manera más fácil o estándar de hacer este tipo de cosas de las que aún no soy consciente!

+0

Estoy llegando a conclusiones similares. El problema principal puede surgir cuando utilizas un índice en una matriz de vértices: no me queda claro si los mismos índices se usan para obtener valores en la matriz de vértices de textura. No puedo encontrar ninguna documentación sobre esto. Estoy considerando ahora volver a los triángulos básicos. Solo estoy lidiando con la geometría simple, por lo que el ahorro de espacio con una matriz de puntero vértice tal vez no valga la pena. Además: lo que estoy haciendo requiere que pueda mapear la textura de las caras de los objetos de diferentes maneras: el uso de triángulos puede ser la única forma de hacerlo. – omnivore

Cuestiones relacionadas