- return 0u;
-}
-
-void AtlasManager::CreateMesh( SizeType atlas,
- SizeType imageWidth,
- SizeType imageHeight,
- const Vector2& position,
- SizeType widthInBlocks,
- SizeType heightInBlocks,
- Toolkit::AtlasManager::Mesh2D& mesh,
- AtlasSlotDescriptor& desc )
-{
- Toolkit::AtlasManager::Vertex2D vertex;
- uint32_t faceIndex = 0; // TODO change to unsigned short when property type is available
-
- SizeType blockWidth = mAtlasList[ atlas ].mSize.mBlockWidth;
- SizeType blockHeight = mAtlasList[ atlas ].mSize.mBlockHeight;
-
- float vertexBlockWidth = static_cast< float >( blockWidth );
- float vertexBlockHeight = static_cast< float >( blockHeight );
-
- SizeType width = mAtlasList[ atlas ].mSize.mWidth;
- SizeType height = mAtlasList[ atlas ].mSize.mHeight;
-
- SizeType atlasWidthInBlocks = ( width - 1u ) / blockWidth;
-
- // Get the normalized size of a texel in both directions
- // TODO when texture resizing and passing texture size via uniforms is available,
- // we will encode pixel positions into the vertex data rather than normalized
- // meaning that geometry needn't be changed on an atlas resize
- float texelX = 1.0f / static_cast< float >( width );
- float texelY = 1.0f / static_cast< float >( height );
-
- float oneAndAHalfTexelX = texelX + ( texelX * 0.5f );
- float oneAndAHalfTexelY = texelY + ( texelY * 0.5f );
-
- // Get the normalized size of a block in texels
- float texelBlockWidth = texelX * vertexBlockWidth;
- float texelBlockHeight = texelY * vertexBlockHeight;
-
- // Get partial block space
- float vertexEdgeWidth = static_cast< float >( imageWidth % blockWidth );
- float vertexEdgeHeight = static_cast< float >( imageHeight % blockHeight );
-
- // And in texels
- float texelEdgeWidth = texelX * vertexEdgeWidth;
- float texelEdgeHeight = texelY * vertexEdgeHeight;
-
- // We're going to 'blit' half a pixel more on each edge
- vertexBlockWidth++;
- vertexEdgeWidth++;
- vertexBlockHeight++;
- vertexEdgeHeight++;
-
- // Block by block create the two triangles for the quad
- SizeType blockIndex = 0;
- float ndcWidth;
- float ndcHeight;
- float ndcVWidth;
- float ndcVHeight;
-
- // Move back half a pixel
- Vector2 topLeft = Vector2( position.x - 0.5f, position.y - 0.5f );
-
- for ( SizeType y = 0; y < heightInBlocks; ++y )
- {
-
- float currentX = position.x;
-
- if ( ( heightInBlocks - 1u ) == y && vertexEdgeHeight > 0.0f )
- {
- ndcHeight = texelEdgeHeight + texelY;
- ndcVHeight = vertexEdgeHeight;
- }
- else
- {
- ndcHeight = texelBlockHeight + texelY;
- ndcVHeight = vertexBlockHeight;
- }
-
- for ( SizeType x = 0; x < widthInBlocks; ++x )
- {
- SizeType block = desc.mBlocksList[ blockIndex++ ];
-
- float fBlockX = texelBlockWidth * static_cast< float >( block % atlasWidthInBlocks );
- float fBlockY = texelBlockHeight * static_cast< float >( block / atlasWidthInBlocks );
-
- // Add on texture filtering compensation ( half a texel plus compensation for filled pixel in top left corner )
- fBlockX += oneAndAHalfTexelX;
- fBlockY += oneAndAHalfTexelY;
-
- if ( ( widthInBlocks - 1u ) == x && vertexEdgeWidth > 0.0f )
- {
- ndcWidth = texelEdgeWidth + texelX;
- ndcVWidth = vertexEdgeWidth;
- }
- else
- {
- ndcWidth = texelBlockWidth + texelX;
- ndcVWidth = vertexBlockWidth;
- }
-
- // Top left
- vertex.mPosition.x = topLeft.x;
- vertex.mPosition.y = topLeft.y;
- vertex.mTexCoords.x = fBlockX;
- vertex.mTexCoords.y = fBlockY;
-
- mesh.mVertices.PushBack( vertex );
-
- // Top Right
- vertex.mPosition.x = topLeft.x + ndcVWidth;
- vertex.mPosition.y = topLeft.y;
- vertex.mTexCoords.x = fBlockX + ndcWidth;
- vertex.mTexCoords.y = fBlockY;
-
- mesh.mVertices.PushBack( vertex );
-
- // Bottom Left
- vertex.mPosition.x = topLeft.x;
- vertex.mPosition.y = topLeft.y + ndcVHeight;
- vertex.mTexCoords.x = fBlockX;
- vertex.mTexCoords.y = fBlockY + ndcHeight;
-
- mesh.mVertices.PushBack( vertex );
-
- // Bottom Right
- topLeft.x += ndcVWidth;
- vertex.mPosition.x = topLeft.x;
- vertex.mPosition.y = topLeft.y + ndcVHeight;
- vertex.mTexCoords.x = fBlockX + ndcWidth;
- vertex.mTexCoords.y = fBlockY + ndcHeight;
-
- mesh.mVertices.PushBack( vertex );
-
- // Six indices in counter clockwise winding
- mesh.mIndices.PushBack( faceIndex + 1u );
- mesh.mIndices.PushBack( faceIndex );
- mesh.mIndices.PushBack( faceIndex + 2u );
- mesh.mIndices.PushBack( faceIndex + 2u );
- mesh.mIndices.PushBack( faceIndex + 3u );
- mesh.mIndices.PushBack( faceIndex + 1u );
- faceIndex += 4;
- }
-
- // Move down a row
- topLeft.x = currentX;
- topLeft.y += vertexBlockHeight;
- }
-
- // If there's only one block then skip this next vertex optimisation
- if ( widthInBlocks * heightInBlocks > 1 )
- {
- Toolkit::AtlasManager::Mesh2D optimizedMesh;
- OptimizeMesh( mesh, optimizedMesh );
- }
-}
-
-void AtlasManager::PrintMeshData( const Toolkit::AtlasManager::Mesh2D& mesh )
-{
- uint32_t vertexCount = mesh.mVertices.Size();
- uint32_t indexCount = mesh.mIndices.Size();
- std::cout << "\nMesh Data for Image: VertexCount = " << vertexCount;
- std::cout << ", Triangles = " << indexCount / 3 << std::endl;
-
- for ( SizeType v = 0; v < vertexCount; ++v )
- {
- std::cout << " Vertex(" << v << ") x = " << mesh.mVertices[v].mPosition.x << ", ";
- std::cout << "y = " << mesh.mVertices[v].mPosition.y << ", ";
- std::cout << "u = " << mesh.mVertices[v].mTexCoords.x << ", ";
- std::cout << "v = " << mesh.mVertices[v].mTexCoords.y << std::endl;
- }
-
- std::cout << "\n Indices: ";
- for ( SizeType i = 0; i < indexCount; ++i )
- {
- std::cout << " " << mesh.mIndices[ i ];
- }
- std::cout << std::endl;
-}
-
-void AtlasManager::OptimizeMesh( const Toolkit::AtlasManager::Mesh2D& in,
- Toolkit::AtlasManager::Mesh2D& out )
-{
- unsigned short vertexIndex = 0;
-
- // We could check to see if blocks are next to each other, but it's probably just as quick to compare verts
- for ( SizeType i = 0; i < in.mIndices.Size(); ++i )
- {
- // Fetch a vertex, has it already been assigned?
- bool foundVertex = false;
- Toolkit::AtlasManager::Vertex2D v = in.mVertices[ in.mIndices[ i ] ];
- for ( SizeType j = 0; j < out.mVertices.Size(); ++j )
- {
- if ( ( fabsf( v.mPosition.x - out.mVertices[ j ].mPosition.x ) < Math::MACHINE_EPSILON_1000 ) &&
- ( fabsf( v.mPosition.y - out.mVertices[ j ].mPosition.y ) < Math::MACHINE_EPSILON_1000 ) &&
- ( fabsf( v.mTexCoords.x - out.mVertices[ j ].mTexCoords.x ) < Math::MACHINE_EPSILON_1000 ) &&
- ( fabsf( v.mTexCoords.y - out.mVertices[ j ].mTexCoords.y ) < Math::MACHINE_EPSILON_1000 ) )
- {
- // Yes, so store this down as the vertex to use
- out.mIndices.PushBack( j );
- foundVertex = true;
- break;
- }
- }
-
- // Did we find a vertex ?
- if ( !foundVertex )
- {
- // No so add a new one
- out.mVertices.PushBack( v );
- vertexIndex++;
- }
- }
-}
-
-void AtlasManager::StitchMesh( Toolkit::AtlasManager::Mesh2D& first,
- const Toolkit::AtlasManager::Mesh2D& second,
- bool optimize )
-{
- const uint32_t verticesCount = first.mVertices.Size();
- first.mVertices.Insert( first.mVertices.End(),
- second.mVertices.Begin(),
- second.mVertices.End() );
-
- const uint32_t indicesCount = first.mIndices.Size();
- first.mIndices.Insert( first.mIndices.End(),
- second.mIndices.Begin(),
- second.mIndices.End() );
-
- for( Vector<unsigned int>::Iterator it = first.mIndices.Begin() + indicesCount,
- endIt = first.mIndices.End();
- it != endIt;
- ++it )
- {
- *it += verticesCount;
- }
-
- if ( optimize )
- {
- Toolkit::AtlasManager::Mesh2D optimizedMesh;
- OptimizeMesh( first, optimizedMesh );
- first = optimizedMesh;
- }