2D engine done. Advice on optimisation, please?
Here's mine...
And here's where it's called from:
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);
}
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 |
|

