开发者

Mesh creation in openGL iphone sdk

I am using this source code as my base and trying to change the code as per my requirements. I have included the following code to create a mesh on image.

-(void)populateMesh{

verticalDivisions = kVerticalDivisions;
horizontalDivisions = kHorisontalDivisions; 
unsigned int verticesArrsize = (kVerticalDivisions * ((2 + kHorisontalDivisions * 2) * 3));
unsigned int textureCoordsArraySize = kVerticalDivisions * ((2 + kHorisontalDivisions * 2) * 2);
verticesArr = (GLfloat *)malloc(verticesArrsize * sizeof(GLfloat));
textureCoordsArr = (GLfloat*)malloc(textureCoordsArraySize * sizeof(GLfloat));
if (verticesArr == NULL) {
    NSLog(@"verticesArr = NULL!");
}   
float height = kWindowHeight/verticalDivisions;
float width = kWindowWidth/horizontalDivisions;
int i,j, count;
count = 0;
for (j=0; j<verticalDivisions; j++) {
    for (i=0; i<=horizontalDivisions; i++, count+=6) { //2 vertices each time...
        float currX = i * width;
        float currY = j * height;
        verticesArr[count] = currX;
        verticesArr[count+1] = currY + height;
        verticesArr[count+2] = 0.0f;            
        verticesArr[count+3] = currX;
        verticesArr[count+4] = currY;
        verticesArr[count+5] = 0.0f;
    } 
}
float xIncrease = 1.0f/horizontalDivisions;
float yIncrease = 1.0f/verticalDivisions;   
int x,y;
//int elements;
count = 0;  
for (y=0; y<verticalDivisions; y++) {
    for (x=0; x<horizontalDivisions+1; x++, count+=4) {
        float currX = x *xIncrease; 
        float currY = y * yIncrease;
        textureCoordsArr[count] = (float)currX;
        textureCoordsArr[count+1] 开发者_StackOverflow中文版= (float)currY + yIncrease;
        textureCoordsArr[count+2] = (float)currX;
        textureCoordsArr[count+3] = (float)currY;
    }
}
//  int cnt;
//  int cnt = 0;
    NSLog(@"expected %i vertices, and %i vertices were done",(verticalDivisions * ((2 + horizontalDivisions*2 ) * 2) ) , count );
}

Following is the drawView code.

- (void)drawView:(GLView*)view;
{
static GLfloat rot = 0.0;
glBindTexture(GL_TEXTURE_2D, texture[0]);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

glEnableClientState(GL_VERTEX_ARRAY);
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, textureCoordsArr);
glVertexPointer(3, GL_FLOAT, 0, verticesArr);
glPushMatrix();{
    int i;
    for (i=0; i<verticalDivisions; i++) {
        glDrawArrays(GL_TRIANGLE_STRIP, i*(horizontalDivisions*2+2), horizontalDivisions*2+2);
    }
}glPopMatrix();
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}

In the setup view I have called [self populateMesh]; at the end of the function. My problem is after changing the code, a blank rather say black view is appeared on the screen. Can anyone figure out where I am doing some mistake. I am newbie for openGL and trying to manipulate images through mesh. Please help asap. Thanks in advance.

Following is the setup view code.

-(void)setupView:(GLView*)view {    

 const GLfloat zNear = 0.01, zFar = 1000.0, fieldOfView = 45.0; 
 GLfloat size;   
 glEnable(GL_DEPTH_TEST);
 glMatrixMode(GL_PROJECTION);
 size = zNear *  tanf(DEGREES_TO_RADIANS(fieldOfView) / 2.0);
 CGRect rect =  view.bounds; 
 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_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:@"texture" 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 );

 CGContextTranslateCTM (context, 0, height);

 CGContextScaleCTM (context, 1.0, -1.0);

 CGColorSpaceRelease( colorSpace );

 CGContextClearRect( context, CGRectMake( 0, 0, width, 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];
 [self populateMesh]; 
}

EDIT This is what I am getting as an out put. While expected is regular grid...

Mesh creation in openGL iphone sdk


Guessing the mesh is cut out with zNear value. Try to change z value to -2.

verticesArr[count+2] = -2.0f; 
verticesArr[count+5] = -2.0f;

By default, the camera is situated at the origin, points down the negative z-axis, and has an up-vector of (0, 1, 0).

Notice that your mesh is out of view frustum (pyramid). Check it out in OpenGL red book:

http://glprogramming.com/red/chapter03.html


The grid is not regular because of the way how vertices are ordered. Also are you sure that GL_TRIANGLE_STRIP is desired option. Maybe, GL_TRIANGLES is that what you need.

I propose simpler solution with using indices array. For example in initialization code make vertices and texture array for your grid in normal order as:

0 1 2
3 4 5
6 7 8

Update:

- (void) setup
{
  vertices = (GLfloat*)malloc(rows*colums*3*sizeof(GLfloat));
  texCoords = (GLfloat*)malloc(rows*columns*2*sizeof(GLfloat));
  indices = (GLubyte*)malloc((rows-1)*(columns-1)*6*sizeof(GLubyte));

  float xDelta = horizontalDivisions/columns;
  float yDelta = verticalDivisions/rows;

  for (int i=0;i<columns;i++) {
    for(int j=0;j<rows; j++) {
      int index = j*columns+i;
      vertices[3*index+0] = i*xDelta; //x
      vertices[3*index+1] = j*yDelta; //y
      vertices[3*index+2] = -10; //z

      texCoords[2*index+0] = i/(float)(columns-1); //x texture coordinate
      texCoords[2*index+1] = j/(float)(rows-1); //y tex coordinate
    }
  }

  for (int i=0;i<columns-1;i++) {
   for(int j=0;j<rows-1; j++) {

     indices[6*(j*columns+i)+0] = j*columns+i;
     indices[6*(j*columns+i)+1] = j*columns+i+1;
     indices[6*(j*columns+i)+2] = (j+1)*columns+i;

     indices[6*(j*columns+i)+3] = j*columns+i+1;
     indices[6*(j*columns+i)+4] = (j+1)*columns+i+1;
     indices[6*(j*columns+i)+5] = (j+1)*columns+i;
   }
 }
}

- (void) dealloc {
  free(vertices); free(texCoords); free(indices);
}

Practically this indices order means that tringles are rendered as following:

(013)(143)(124)(254)(346)(476)... and so on.

In render method use the following lines:

glVertexPointer(3, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
glDrawElements(GL_TRIANGLES, 6*(columns-1)*(rows-1), GL_UNSIGNED_BYTE, indices);

Hope that will help.


This is a great tutorial on drawing a grid in 3D. It should have the code necessary to help you. I'm not sure if you are working in 3D or 2D, but even if it is 2D, it should be fairly easy to adapt to your needs. Hope that helps!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜