OpenGLES2 iOS: What's the best streaming vertex animation for dynamic terrain?

I am writing an application that creates a 640 * 480 dynamic landscape (changes every frame). Each terrain is stored in a raw data file that represents a string of float values. So far, I could read files sequentially in memory and dynamically create a grid based on the height values ​​of each frame (and the frame rate is actually reasonable), but I max out at about 20 frames before my application exits without error or stack footprint.

I suspect I am approaching this in the wrong way. How do I pass this data so that I can't keep every frame in memory?

Here is a section from my data class that contains a collection of landscapes:

- (void)addModelWithID:(int)modelID;
{
    NSString* resourcePath  = [[NSBundle mainBundle] resourcePath];
    NSString* fileName      = [NSString stringWithFormat:@"depth_%i.raw", modelID];
    NSString* fullPath = [resourcePath stringByAppendingPathComponent:fileName];

    NSData *myData = [NSData dataWithContentsOfFile:fullPath];
    if (!myData)
      return;

    const float *data = [myData bytes];

    int meshWidth               = 640;
    int meshHeight              = 480;

    Model *kModel = [[Model alloc] init];

    int indicesPtr  = 0;
    int depthPtr = 2;

    for (int y=0;y<meshHeight;y++)    // Loop through y pixels
        {
            for (int x=0;x<meshWidth;x++)   // Loop through x pixels
            {
                // Set up vertex positions
                int index  = y*meshWidth+x;
                float xpos = ((float)x/(float)(meshWidth-1)) - 0.5f;
                float ypos = ((float)y/(float)(meshHeight-1)) - 0.5f;
                float zpos = (float)data[index];

                kModel.vertices1[index*3+0] = xpos;
                kModel.vertices1[index*3+1] = ypos;
                kModel.vertices1[index*3+2] = zpos;

                // Create a new index based on whether the current line is even or odd (flipped horizontally if odd)
                int _index = (y%2==0) ? index : (y*meshWidth) + ((meshWidth-1)-x); 

                //Create the first index
                kModel.indices[indicesPtr++] = _index;

                // Create the second index
                if ((x<meshWidth-1) || (x==meshWidth-1 && y==meshHeight-2))
                    kModel.indices[indicesPtr++] = _index+meshWidth;
            }
        }
    }

    // Add the model to the data object
    [Models addObject:kModel];
    [kModel release];
}

      

And my drawing code (each frame I call a different terrain, hopefully up to 500 or so, but I maximize at ~ 20:

{
    ...
        Model *kModel = [kData.kinectModels objectAtIndex:sequenceCurrentFrame];

        glVertexAttribPointer(vertexHandle, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)kModel.vertices1);

        glEnableVertexAttribArray(vertexHandle);

        glUniformMatrix4fv(mvpMatrixHandle, 1, GL_FALSE, (const GLfloat*)&modelViewProjection.data[0]);
        glDrawElements(GL_TRIANGLE_STRIP, kModel.numIndices, GL_UNSIGNED_SHORT, (const GLvoid*)kModel.indices);
    ...
}

      

Thanks a million for your help,

Josh

+3


source to share


1 answer


You can store the height data in a texture and then use a function texture2D

in the vertex shader to change the current vertex height.

With this setting, you can have a single mesh and simply adjust the height of each vertex to the value stored in the texture.



If you are confident that you are GPU bound, the texture format used to find height data can also be further optimized. Say your height range is from 0-255

, given the format GL_RGBA

, you can use the same texture to render up to 4 frames (the first frame reads the height from the red component, the next frame from the blue component, etc.). Creating a support texture twice as large (1280x960) will allow you to save up to 16 frames within a single texture. Another thing worth mentioning in regards to textures is that using a native format for your GPU can also improve performance in both GUI and IO scenarios. For iDevices, this format is PVRTC .

I really believe the problem is only the allocation of 300k + vertices for each frame separately ... which adds up to 640 * 480 * 3 * 4 = 3,686,400 bytes allocated for each frame and you did not mention after that how many frames will you stop allocating memory (wait ... won't you?). This is too much for such a resource-limited environment.

+3


source







All Articles