2D engine done. Advice on optimisation, please?

Member
Posts: 110
Joined: 2009.07
Post: #21
Here's mine...

Code:
- (void) copyDrawDataWithCamera: (CCamera *) camera ToVertexDataArray: (GLfloat *) vertex_data_array
{
    if(atlasRect != nil)
    {        
        // Reset the local vertex array. Each object is centred at this point.
        memcpy(&vertex_data_array[TOTAL_VERTEX_DATA_ELEMENTS * 0], &atlasRect.vertexCoords[ENTRIES_PER_VERTEX_COORD * 0], sizeof(GLfloat) * ENTRIES_PER_VERTEX_COORD);
        memcpy(&vertex_data_array[TOTAL_VERTEX_DATA_ELEMENTS * 1], &atlasRect.vertexCoords[ENTRIES_PER_VERTEX_COORD * 1], sizeof(GLfloat) * ENTRIES_PER_VERTEX_COORD);
        memcpy(&vertex_data_array[TOTAL_VERTEX_DATA_ELEMENTS * 2], &atlasRect.vertexCoords[ENTRIES_PER_VERTEX_COORD * 2], sizeof(GLfloat) * ENTRIES_PER_VERTEX_COORD);            
        memcpy(&vertex_data_array[TOTAL_VERTEX_DATA_ELEMENTS * 3], &atlasRect.vertexCoords[ENTRIES_PER_VERTEX_COORD * 3], sizeof(GLfloat) * ENTRIES_PER_VERTEX_COORD);            
                    
        matrixInit(&spriteManipulationMatrix);
        matrixTranslate(&spriteManipulationMatrix, self.worldCoord.X, self.worldCoord.Y, self.worldCoord.Z);                

        if([axis angleZ])    matrixRotateZ(&spriteManipulationMatrix, [axis angleZ]);    //[self printMatrix];

        for(int i = 0; i < VERTICES_PER_SPRITE; i++)
        {    
            GLfloat *array = &vertex_data_array[TOTAL_VERTEX_DATA_ELEMENTS * i];
            [self applyMatrix: &spriteManipulationMatrix ToGLVertexArrayElement: array];
        }
        
        // Convert the GLfloat vertex_data_array pointer into a GLubyte pointer
        GLubyte *colour_array = ((GLubyte*)vertex_data_array) + COLOUR_INDEX_FLOAT_OFFSET * sizeof(GLfloat);

        for(int i = 0; i <  VERTICES_PER_SPRITE; i++)
        {        
            int index = i * STRIDE_SIZE;

            // Note - openGL for some reason expects all the colour information to be pre-multiplied.
            // Therefore, we're multiplying all of the RGB values by the Alpha value.
            colour_array[index + 0] = (GLubyte) (255.0f * red * alpha);        // R
            colour_array[index + 1] = (GLubyte) (255.0f * green * alpha);    // G
            colour_array[index + 2] = (GLubyte) (255.0f * blue * alpha);    // B
            colour_array[index + 3] = (GLubyte) (255.0f * alpha);            // A
        }        
    }    
}


And here's where it's called from:

Code:
- (void) drawWithCamera: (CCamera *)camera
{    
    NSArray *drawset        = [spriteDictionary allValues]; // create a nice, sortable array
    NSArray *sorted_objects = [drawset sortedArrayUsingSelector:@selector(compareByTextureID:)];    // Now sort based on the textureID of each sprite

    // Format per point is:
    // x,y,z, r,g,b,a, u,v    
    glEnable(GL_TEXTURE_2D);
    glEnableClientState(GL_COLOR_ARRAY);  
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glVertexPointer(ENTRIES_PER_VERTEX_COORD, GL_FLOAT, STRIDE_SIZE, &vertexDataArray[VERTEX_INDEX_FLOAT_OFFSET]);
    glTexCoordPointer(ENTRIES_PER_TEXTURE_COORD, GL_FLOAT, STRIDE_SIZE, &vertexDataArray[TEXTURE_INDEX_FLOAT_OFFSET]);           
    glColorPointer(ENTRIES_PER_COLOUR_ELEMENT, GL_UNSIGNED_BYTE, STRIDE_SIZE, &vertexDataArray[COLOUR_INDEX_FLOAT_OFFSET]);

    
    //------------------------------------------
    // Go through the sorted objects and find out when the texture changes occur
    // For each texture, store an index of which sprite it changes on,
    // and how many sprites in the list after that start point use this texture
    for(int i = 0; i < parentView.numberOfAtlasTextures; i++)
    {
        atlasToSortedSpriteIndexStart[i] = -1;    // But first, kill the index list completely
        atlasToSortedSpriteIndexCount[i] = -1;    
        
        int start = -1;
        int count = 0;
        
        int total_sprite_count = [sorted_objects count];
        for (int j = 0; j < total_sprite_count; j++)
        {
            CSprite *sprite = [sorted_objects objectAtIndex: j];
            
            if([sprite getTextureIndex] == i) // Check if the atlas's id matches the sprite's id
            {
                if(start == -1)
                    start = j;
                count++;
            }
        }
        atlasToSortedSpriteIndexStart[i] = start;
        atlasToSortedSpriteIndexCount[i] = count;        
    }    
    
    //------------------------------------------
    // Now draw all the sprites, sorting by texture-type
    // We use a single, long vertex buffer and use clever indexing, as opposed to constantly
    // creating and deleting new vertex buffers for each
    for(int c_atlas_index = 0; c_atlas_index < parentView.numberOfAtlasTextures; c_atlas_index++)
    {
        int vertex_data_array_index = 0; // Keeps track of where to write next. Reset for each texture
        
        int c_current_sprite_index = atlasToSortedSpriteIndexStart[c_atlas_index];        
        if(c_current_sprite_index < 0) // Skip this whole thing if there are no sprites using this atlas
            continue;
        
        glBindTexture(GL_TEXTURE_2D, [self getTextureIDWithIndex: c_atlas_index]);

        // For every sprite using this atlas...
        for (int h = 0; h < atlasToSortedSpriteIndexCount[c_atlas_index]; h++)
        {
            CSprite *sprite = [sorted_objects objectAtIndex: (c_current_sprite_index + h)];
    
            // Check if the texture page has changed. Only then change the texture bindings
            [sprite copyDrawDataWithCamera: camera ToVertexDataArray: &vertexDataArray[vertex_data_array_index]];
        
            // Now use this information to build the Vertex buffer
            for(int i = 0; i < VERTICES_PER_SPRITE; i++)
            {            
                vertex_data_array_index += ENTRIES_PER_VERTEX_COORD; // skip the already copied vertex information
                vertex_data_array_index += FLOATS_PER_COLOUR_ELEMENT; // skip the already copied colour information

                // Create uv texture info
                for(int j = 0; j < ENTRIES_PER_TEXTURE_COORD; j++)
                {
                    vertexDataArray[vertex_data_array_index] = sprite.atlasRect.textureCoords[i * ENTRIES_PER_TEXTURE_COORD + j];
                    vertex_data_array_index++;
                }            
            }    
        }
        
        // Here's the magic.
        int size = atlasToSortedSpriteIndexCount[c_atlas_index] * VERTEX_INDICES_PER_SPRITE;
        glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_SHORT,indexArray);
    }
    
    // And now turn it all off again
    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisable(GL_TEXTURE_2D);
}
Quote this message in a reply
Post Reply 


Messages In This Thread
2D engine done. Advice on optimisation, please? - Madrayken - Jul 28, 2009 12:26 PM
Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  new engine in works. advice? godexsoft 4 3,774 Apr 7, 2012 07:25 AM
Last Post: godexsoft
  Advice on 3D Room engine? devGamer 4 3,405 Mar 21, 2010 10:05 AM
Last Post: Skorche