Do not use our own special packed atlas, use the standard atlas in preparation for #42.

This commit is contained in:
UnknownShadow200 2015-09-06 08:13:21 +10:00
parent d95272f4a7
commit 03b21b62a7
11 changed files with 158 additions and 188 deletions

View file

@ -165,13 +165,13 @@ namespace ClassicalSharp {
for( int tile = 1; tile < BlockInfo.BlocksCount; tile++ ) {
if( game.CanPlace[tile] || game.CanDelete[tile] ) {
Block block = (Block)tile;
int texId = game.BlockInfo.GetOptimTextureLoc( (byte)block, TileSide.Left );
int texId = game.BlockInfo.GetTextureLoc( (byte)block, TileSide.Left );
TextureRectangle rec = game.TerrainAtlas.GetTexRec( texId );
int verSize = blockSize;
float height = game.BlockInfo.BlockHeight( (byte)block );
int blockY = y;
if( height != 1 ) {
rec.V1 = rec.V1 + TerrainAtlas2D.usedInvVerElemSize * height;
rec.V1 = rec.V1 + TerrainAtlas2D.invElementSize * height;
verSize = (int)( blockSize * height );
blockY = y + blockSize - verSize;
}

View file

@ -76,14 +76,14 @@ namespace ClassicalSharp {
}
Texture MakeTexture( int x, int y, Block block ) {
int texId = game.BlockInfo.GetOptimTextureLoc( (byte)block, TileSide.Left );
int texId = game.BlockInfo.GetTextureLoc( (byte)block, TileSide.Left );
TextureRectangle rec = game.TerrainAtlas.GetTexRec( texId );
int verSize = blockSize;
float height = game.BlockInfo.BlockHeight( (byte)block );
int blockY = y;
if( height != 1 ) {
rec.V1 = rec.V1 + TerrainAtlas2D.usedInvVerElemSize * height;
rec.V1 = rec.V1 + TerrainAtlas2D.invElementSize * height;
verSize = (int)( blockSize * height );
blockY = y + blockSize - verSize;
}

View file

@ -0,0 +1,126 @@
using System;
namespace ClassicalSharp {
public partial class BlockInfo {
int[] textures = new int[BlocksCount * TileSide.Sides];
const int Row1 = 0, Row2 = 16, Row3 = 32, Row4 = 48,
Row5 = 64, Row6 = 80, Row7 = 96, Row8 = 112, Row9 = 128;
void SetupOptimTextures() {
// Row 1
SetAll( Block.Grass, Block.Stone, Block.Dirt );
SetSide( Block.Grass );
SetBottom( 0 + 2, Block.Grass );
SetAll( Block.WoodenPlanks );
SetSide( Block.DoubleSlab );
SetSide( 0 + 5, Block.Slab );
SetTopAndBottom( Block.DoubleSlab );
SetTopAndBottom( 0 + 6, Block.Slab );
SetAll( Block.Brick );
SetSide( Block.TNT );
SetTop( Block.TNT );
SetBottom( Block.TNT );
SetAll( Block.Rope, Block.Rose, Block.Dandelion, Block.Water, Block.Sapling );
SetAll( 0 + 14, Block.StillWater );
// Row 2
SetAll( Block.Cobblestone, Block.Bedrock, Block.Sand, Block.Gravel );
SetAll( 16 + 0, Block.CobblestoneSlab );
SetSide( Block.Wood );
SetTopAndBottom( Block.Wood );
SetAll( Block.Leaves );
SetTop( Block.IronBlock, Block.GoldBlock, Block.Sandstone, Block.Pillar );
texId += 1;
SetAll( Block.RedMushroom, Block.BrownMushroom, Block.Lava );
SetAll( 16 + 14, Block.StillLava );
texId += 1;
// Row 3
SetAll( Block.GoldOre, Block.IronOre, Block.CoalOre, Block.Bookshelf,
Block.MossyCobblestone, Block.Obsidian, Block.Fire );
SetTopAndBottom( 0 + 4, Block.Bookshelf );
SetSide( Block.IronBlock, Block.GoldBlock, Block.Sandstone, Block.Pillar );
texId += 5;
// Row 4
SetAll( Block.Sponge, Block.Glass, Block.Snow, Block.Ice, Block.StoneBrick,
Block.Crate, Block.CeramicTile );
SetBottom( Block.IronBlock, Block.GoldBlock, Block.Sandstone, Block.Pillar );
texId += 5;
// Row 5
SetAll( Block.RedCloth, Block.OrangeCloth, Block.YellowCloth, Block.LimeCloth,
Block.GreenCloth, Block.AquaCloth, Block.CyanCloth, Block.BlueCloth,
Block.PurpleCloth, Block.IndigoCloth, Block.VioletCloth, Block.MagentaCloth,
Block.PinkCloth, Block.BlackCloth, Block.GrayCloth, Block.WhiteCloth );
// Row 6
SetAll( Block.LightPinkWool, Block.ForestGreenWool, Block.BrownWool,
Block.DeepBlueWool, Block.TurquoiseWool );
texId += 1;
SetAll( Block.Magma );
}
void SetAll( int textureId, Block blockId ) {
int index = (byte)blockId * TileSide.Sides;
for( int i = index; i < index + TileSide.Sides; i++ ) {
textures[i] = textureId;
}
}
void SetSide( int textureId, Block blockId ) {
int index = (byte)blockId * TileSide.Sides;
for( int i = index; i < index + TileSide.Bottom; i++ ) {
textures[i] = textureId;
}
}
int texId;
void SetTopAndBottom( int textureId, Block blockId ) {
textures[(byte)blockId * TileSide.Sides + TileSide.Bottom] = textureId;
textures[(byte)blockId * TileSide.Sides + TileSide.Top] = textureId;
}
void SetTop( int textureId, Block blockId ) {
textures[(byte)blockId * TileSide.Sides + TileSide.Top] = textureId;
}
void SetBottom( int textureId, Block blockId ) {
textures[(byte)blockId * TileSide.Sides + TileSide.Bottom] = textureId;
}
void SetAll( params Block[] blocks ) {
for( int i = 0; i < blocks.Length; i++ ) {
SetAll( texId, blocks[i] );
texId++;
}
}
void SetSide( params Block[] blocks ) {
for( int i = 0; i < blocks.Length; i++ ) {
SetSide( texId, blocks[i] ); texId++;
}
}
void SetTopAndBottom( params Block[] blocks ) {
for( int i = 0; i < blocks.Length; i++ ) {
SetTopAndBottom( texId, blocks[i] ); texId++;
}
}
void SetTop( params Block[] blocks ) {
for( int i = 0; i < blocks.Length; i++ ) {
SetTop( texId, blocks[i] ); texId++;
}
}
void SetBottom( params Block[] blocks ) {
for( int i = 0; i < blocks.Length; i++ ) {
SetBottom( texId, blocks[i] ); texId++;
}
}
/// <summary> Gets the index in the terrain atlas for the texture of the face of the given block. </summary>
/// <param name="face"> Face of the given block, see TileSide constants. </param>
public int GetTextureLoc( byte block, int face ) {
return textures[block * TileSide.Sides + face];
}
}
}

View file

@ -1,132 +0,0 @@
using System;
namespace ClassicalSharp {
public partial class BlockInfo {
int[] textures = new int[BlocksCount * TileSide.Sides];
const int Row1 = 0, Row2 = 16, Row3 = 32, Row4 = 48,
Row5 = 64, Row6 = 80, Row7 = 96, Row8 = 112, Row9 = 128;
void SetupOptimTextures() {
SetOptimAll( Block.Stone, Row1 + 1 );
SetOptimTop( Block.Grass, Row1 );
SetOptimSide( Block.Grass, Row1 + 3 );
SetOptimBottom( Block.Grass, Row1 + 2 );
SetOptimAll( Block.Dirt, Row1 + 2 );
SetOptimAll( Block.Cobblestone, Row2 );
SetOptimAll( Block.WoodenPlanks, Row1 + 4 );
SetOptimAll( Block.Sapling, Row1 + 15 );
SetOptimAll( Block.Bedrock, Row2 + 1 );
SetOptimAll( Block.Water, Row1 + 14 );
SetOptimAll( Block.StillWater, Row1 + 14 );
SetOptimAll( Block.Lava, Row2 + 13 );
SetOptimAll( Block.StillLava, Row2 + 13 );
SetOptimAll( Block.Sand, Row2 + 2 );
SetOptimAll( Block.Gravel, Row2 + 3 );
SetOptimAll( Block.GoldOre, Row2 + 14 );
SetOptimAll( Block.IronOre, Row2 + 15 );
SetOptimAll( Block.CoalOre, Row3 );
SetOptimSide( Block.Wood, Row2 + 4 );
SetOptimTop( Block.Wood, Row2 + 5 );
SetOptimBottom( Block.Wood, Row2 + 5 );
SetOptimAll( Block.Leaves, Row2 + 6 );
SetOptimAll( Block.Sponge, Row3 + 9);
SetOptimAll( Block.Glass, Row3 + 10 );
SetOptimAll( Block.RedCloth, Row4 + 4 );
SetOptimAll( Block.OrangeCloth, Row4 + 5 );
SetOptimAll( Block.YellowCloth, Row4 + 6 );
SetOptimAll( Block.LimeCloth, Row4 + 7 );
SetOptimAll( Block.GreenCloth, Row4 + 8 );
SetOptimAll( Block.AquaCloth, Row4 + 9 );
SetOptimAll( Block.CyanCloth, Row4 + 10 );
SetOptimAll( Block.BlueCloth, Row4 + 11 );
SetOptimAll( Block.PurpleCloth, Row4 + 12 );
SetOptimAll( Block.IndigoCloth, Row4 + 13 );
SetOptimAll( Block.VioletCloth, Row4 + 14 );
SetOptimAll( Block.MagentaCloth, Row4 + 15 );
SetOptimAll( Block.PinkCloth, Row5 );
SetOptimAll( Block.BlackCloth, Row5 + 1 );
SetOptimAll( Block.GrayCloth, Row5 + 2 );
SetOptimAll( Block.WhiteCloth, Row5 + 3 );
SetOptimAll( Block.Dandelion, Row1 + 13 );
SetOptimAll( Block.Rose, Row1 + 12 );
SetOptimAll( Block.BrownMushroom, Row2 + 12 );
SetOptimAll( Block.RedMushroom, Row2 + 11 );
SetOptimTop( Block.GoldBlock, Row2 + 8 );
SetOptimSide( Block.GoldBlock, Row3 + 6 );
SetOptimBottom( Block.GoldBlock, Row4 + 1 );
SetOptimTop( Block.IronBlock, Row2 + 7 );
SetOptimSide( Block.IronBlock, Row3 + 5 );
SetOptimBottom( Block.IronBlock, Row4 );
SetOptimTop( Block.DoubleSlab, Row1 + 6 );
SetOptimSide( Block.DoubleSlab, Row1 + 5 );
SetOptimBottom( Block.DoubleSlab, Row1 + 6 );
SetOptimTop( Block.Slab, Row1 + 6 );
SetOptimSide( Block.Slab, Row1 + 5 );
SetOptimBottom( Block.Slab, Row1 + 6 );
SetOptimAll( Block.Brick, Row1 + 7 );
SetOptimTop( Block.TNT, Row1 + 9 );
SetOptimSide( Block.TNT, Row1 + 8 );
SetOptimBottom( Block.TNT, Row1 + 10 );
SetOptimTop( Block.Bookshelf, Row1 + 4 );
SetOptimBottom( Block.Bookshelf, Row1 + 4 );
SetOptimSide( Block.Bookshelf, Row3 + 1 );
SetOptimAll( Block.MossyCobblestone, Row3 + 2 );
SetOptimAll( Block.Obsidian, Row3 + 3 );
// CPE blocks
SetOptimAll( Block.CobblestoneSlab, Row2 + 0 );
SetOptimAll( Block.Rope, Row1 + 11 );
SetOptimTop( Block.Sandstone, Row2 + 9 );
SetOptimSide( Block.Sandstone, Row3 + 7 );
SetOptimBottom( Block.Sandstone, Row4 + 2 );
SetOptimAll( Block.Snow, Row3 + 11 );
SetOptimAll( Block.Fire, Row3 + 4 );
SetOptimAll( Block.LightPinkWool, Row5 + 4 );
SetOptimAll( Block.ForestGreenWool, Row5 + 5 );
SetOptimAll( Block.BrownWool, Row5 + 6 );
SetOptimAll( Block.DeepBlueWool, Row5 + 7 );
SetOptimAll( Block.TurquoiseWool, Row5 + 8 );
SetOptimAll( Block.Ice, Row3 + 12 );
SetOptimAll( Block.CeramicTile, Row3 + 15 );
SetOptimAll( Block.Magma, Row5 + 9 );
SetOptimTop( Block.Pillar, Row2 + 10 );
SetOptimSide( Block.Pillar, Row3 + 8 );
SetOptimBottom( Block.Pillar, Row4 + 3 );
SetOptimAll( Block.Crate, Row3 + 14 );
SetOptimAll( Block.StoneBrick, Row3 + 13 );
}
void SetOptimAll( Block blockId, int textureId ) {
int index = (byte)blockId * TileSide.Sides;
for( int i = index; i < index + TileSide.Sides; i++ ) {
textures[i] = textureId;
}
}
void SetOptimSide( Block blockId, int textureId ) {
int index = (byte)blockId * TileSide.Sides;
for( int i = index; i < index + TileSide.Bottom; i++ ) {
textures[i] = textureId;
}
}
void SetOptimTop( Block blockId, int textureId ) {
textures[(byte)blockId * TileSide.Sides + TileSide.Top] = textureId;
}
void SetOptimBottom( Block blockId, int textureId ) {
textures[(byte)blockId * TileSide.Sides + TileSide.Bottom] = textureId;
}
/// <summary> Gets the index in the ***optimised*** 2D terrain atlas for the
/// texture of the face of the given block. </summary>
/// <param name="block"> Block ID. </param>
/// <param name="face">Face of the given block, see TileSide constants. </param>
/// <returns>The index of the texture within the terrain atlas.</returns>
public int GetOptimTextureLoc( byte block, int face ) {
return textures[block * TileSide.Sides + face];
}
}
}

View file

@ -87,7 +87,7 @@
<Compile Include="Blocks\Block.cs" />
<Compile Include="Blocks\BlockInfo.cs" />
<Compile Include="Blocks\BlockInfo.Culling.cs" />
<Compile Include="Blocks\BlockInfo.Optimised.cs" />
<Compile Include="Blocks\BlockInfo.Atlas.cs" />
<Compile Include="Entities\Entity.cs" />
<Compile Include="Entities\EntityList.cs" />
<Compile Include="Entities\LocalPlayer.cs" />

View file

@ -59,15 +59,14 @@ namespace ClassicalSharp.Particles {
public void BreakBlockEffect( Vector3I position, byte block ) {
Vector3 startPos = new Vector3( position.X, position.Y, position.Z );
int texLoc = game.BlockInfo.GetOptimTextureLoc( block, TileSide.Left );
int texLoc = game.BlockInfo.GetTextureLoc( block, TileSide.Left );
TextureRectangle rec = game.TerrainAtlas.GetTexRec( texLoc );
float invHorSize = TerrainAtlas2D.invElementSize;
float invVerSize = TerrainAtlas2D.usedInvVerElemSize;
int cellsCountX = (int)( 0.25f / invHorSize );
int cellsCountY = (int)( 0.25f / invVerSize );
float elementXSize = invHorSize * 0.25f;
float elementYSize = invVerSize * 0.25f;
float invSize = TerrainAtlas2D.invElementSize;
int cellsCountX = (int)( 0.25f / invSize );
int cellsCountY = (int)( 0.25f / invSize );
float elementXSize = invSize * 0.25f;
float elementYSize = invSize * 0.25f;
Random rnd = new Random();
for( int i = 0; i < 25; i++ ) {

View file

@ -147,14 +147,14 @@ namespace ClassicalSharp {
}
void AddSpriteVertices( byte tile, int count ) {
int i = atlas.Get1DIndex( info.GetOptimTextureLoc( tile, TileSide.Left ) );
int i = atlas.Get1DIndex( info.GetTextureLoc( tile, TileSide.Left ) );
DrawInfo part = drawInfoNormal[i];
part.spriteCount += 6 + 6 * count;
part.iCount += 6 + 6 * count;
}
unsafe void AddVertices( byte tile, int count, int face ) {
int i = atlas.Get1DIndex( info.GetOptimTextureLoc( tile, face ) );
int i = atlas.Get1DIndex( info.GetTextureLoc( tile, face ) );
DrawInfo part = info.IsTranslucent( tile ) ? drawInfoTranslucent[i] : drawInfoNormal[i];
part.iCount += 6;
@ -164,7 +164,7 @@ namespace ClassicalSharp {
}
void DrawLeftFace( int count ) {
int texId = info.GetOptimTextureLoc( tile, TileSide.Left );
int texId = info.GetTextureLoc( tile, TileSide.Left );
int i;
TextureRectangle rec = atlas.GetTexRec( texId, count, out i );
FastColour col = X > 0 ? ( emitsLight || Y > map.heightmap[( Z * width ) + (X - 1)] ? map.SunlightXSide : map.ShadowlightXSide )
@ -181,7 +181,7 @@ namespace ClassicalSharp {
}
void DrawRightFace( int count ) {
int texId = info.GetOptimTextureLoc( tile, TileSide.Right );
int texId = info.GetTextureLoc( tile, TileSide.Right );
int i;
TextureRectangle rec = atlas.GetTexRec( texId, count, out i );
FastColour col = X < maxX ? ( emitsLight || Y > map.heightmap[( Z * width ) + (X + 1)] ? map.SunlightXSide : map.ShadowlightXSide )
@ -198,7 +198,7 @@ namespace ClassicalSharp {
}
void DrawBackFace( int count ) {
int texId = info.GetOptimTextureLoc( tile, TileSide.Back );
int texId = info.GetTextureLoc( tile, TileSide.Back );
int i;
TextureRectangle rec = atlas.GetTexRec( texId, count, out i );
FastColour col = Z < maxZ ? ( emitsLight || Y > map.heightmap[( (Z + 1) * width ) + X] ? map.SunlightZSide : map.ShadowlightZSide )
@ -215,7 +215,7 @@ namespace ClassicalSharp {
}
void DrawFrontFace( int count ) {
int texId = info.GetOptimTextureLoc( tile, TileSide.Front );
int texId = info.GetTextureLoc( tile, TileSide.Front );
int i;
TextureRectangle rec = atlas.GetTexRec( texId, count, out i );
FastColour col = Z > 0 ? ( emitsLight || Y > map.heightmap[( (Z - 1) * width ) + X] ? map.SunlightZSide : map.ShadowlightZSide )
@ -232,7 +232,7 @@ namespace ClassicalSharp {
}
void DrawBottomFace( int count ) {
int texId = info.GetOptimTextureLoc( tile, TileSide.Bottom );
int texId = info.GetTextureLoc( tile, TileSide.Bottom );
int i;
TextureRectangle rec = atlas.GetTexRec( texId, count, out i );
FastColour col = Y > 0 ? ( emitsLight || (Y - 1) > map.heightmap[( Z * width ) + X] ? map.SunlightYBottom : map.ShadowlightYBottom )
@ -246,7 +246,7 @@ namespace ClassicalSharp {
}
void DrawTopFace( int count ) {
int texId = info.GetOptimTextureLoc( tile, TileSide.Top );
int texId = info.GetTextureLoc( tile, TileSide.Top );
int i;
TextureRectangle rec = atlas.GetTexRec( texId, count, out i );
FastColour col = Y < maxY ? ( emitsLight || (Y + 1) > map.heightmap[( Z * width ) + X] ? map.Sunlight : map.Shadowlight )
@ -260,7 +260,7 @@ namespace ClassicalSharp {
}
void DrawSprite( int count ) {
int texId = info.GetOptimTextureLoc( tile, TileSide.Right );
int texId = info.GetTextureLoc( tile, TileSide.Right );
int i;
TextureRectangle rec = atlas.GetTexRec( texId, count, out i );
FastColour col = Y < maxY ? ( emitsLight || (Y + 1) > map.heightmap[( Z * width ) + X] ? map.Sunlight : map.Shadowlight )

View file

@ -57,7 +57,7 @@ namespace ClassicalSharp.Model {
}
void DrawYFace( float y, int side ) {
int texId = BlockInfo.GetOptimTextureLoc( block, side );
int texId = BlockInfo.GetTextureLoc( block, side );
TextureRectangle rec = atlas.GetTexRec( texId );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( -0.5f, y, -0.5f, rec.U1, rec.V1, col );
@ -67,10 +67,10 @@ namespace ClassicalSharp.Model {
}
void DrawZFace( float z, int side, bool swapU ) {
int texId = BlockInfo.GetOptimTextureLoc( block, side );
int texId = BlockInfo.GetTextureLoc( block, side );
TextureRectangle rec = atlas.GetTexRec( texId );
if( blockHeight != 1 ) {
rec.V2 = rec.V1 + blockHeight * TerrainAtlas2D.usedInvVerElemSize;
rec.V2 = rec.V1 + blockHeight * TerrainAtlas2D.invElementSize;
}
if( swapU ) rec.SwapU();
@ -81,10 +81,10 @@ namespace ClassicalSharp.Model {
}
void DrawXFace( float x, int side, bool swapU ) {
int texId = BlockInfo.GetOptimTextureLoc( block, side );
int texId = BlockInfo.GetTextureLoc( block, side );
TextureRectangle rec = atlas.GetTexRec( texId );
if( blockHeight != 1 ) {
rec.V2 = rec.V1 + blockHeight * TerrainAtlas2D.usedInvVerElemSize;
rec.V2 = rec.V1 + blockHeight * TerrainAtlas2D.invElementSize;
}
if( swapU ) rec.SwapU();

View file

@ -217,7 +217,7 @@ namespace ClassicalSharp {
int lastEdgeTexLoc, lastSideTexLoc;
void MakeTexture( ref int texId, ref int lastTexLoc, Block block ) {
int texLoc = game.BlockInfo.GetOptimTextureLoc( (byte)block, TileSide.Top );
int texLoc = game.BlockInfo.GetTextureLoc( (byte)block, TileSide.Top );
if( texLoc != lastTexLoc ) {
lastTexLoc = texLoc;
game.Graphics.DeleteTexture( ref texId );

View file

@ -12,7 +12,7 @@ namespace ClassicalSharp {
public float invElementSize;
public int[] TexIds;
IGraphicsApi graphics;
public readonly int UsedRows1D = 5;
public const int UsedRows1D = 6;
public TerrainAtlas1D( IGraphicsApi graphics ) {
this.graphics = graphics;
@ -33,7 +33,7 @@ namespace ClassicalSharp {
}
public void UpdateState( TerrainAtlas2D atlas2D ) {
int maxVerSize = Math.Min( 2048, graphics.MaxTextureDimensions );
int maxVerSize = Math.Min( 4096, graphics.MaxTextureDimensions );
int verElements = maxVerSize / atlas2D.elementSize;
int totalElements = UsedRows1D * TerrainAtlas2D.ElementsPerRow;
int elemSize = atlas2D.elementSize;

View file

@ -18,8 +18,7 @@ namespace ClassicalSharp {
public class TerrainAtlas2D : IDisposable {
public const int ElementsPerRow = 16, RowsCount = 16;
public const float invElementSize = 0.0625f;
public const float usedInvVerElemSize = 0.125f;
public const float invElementSize = 1 / 16f;
public Bitmap AtlasBitmap;
public int elementSize;
public int TexId;
@ -33,8 +32,7 @@ namespace ClassicalSharp {
AtlasBitmap = bmp;
elementSize = bmp.Width >> 4;
using( FastBitmap fastBmp = new FastBitmap( bmp, true ) ) {
MakeOptimisedTexture( fastBmp );
TexId = graphics.CreateTexture( fastBmp.Width, fastBmp.Height / 2, fastBmp.Scan0 );
TexId = graphics.CreateTexture( fastBmp );
}
}
@ -56,8 +54,8 @@ namespace ClassicalSharp {
public TextureRectangle GetTexRec( int index ) {
int x = index & 0x0F;
int y = index >> 4;
return new TextureRectangle( x * invElementSize, y * usedInvVerElemSize,
invElementSize, usedInvVerElemSize );
return new TextureRectangle( x * invElementSize, y * invElementSize,
invElementSize, invElementSize );
}
public void Dispose() {
@ -66,26 +64,5 @@ namespace ClassicalSharp {
}
graphics.DeleteTexture( ref TexId );
}
static ushort[] rowFlags = { 0xFFFF, 0xFFEE, 0xFFE0, 0xFFE0, 0xFFFF, 0xFA00 };
void MakeOptimisedTexture( FastBitmap atlas ) {
int srcIndex = 0, destIndex = 0;
int size = elementSize;
for( int y = 0; y < 6; y++ ) {
int flags = rowFlags[y];
for( int x = 0; x < ElementsPerRow; x++ ) {
bool isUsed = ( flags & 1 << ( 15 - x ) ) != 0;
if( isUsed && srcIndex != destIndex ) {
int dstX = ( destIndex & 0x0F ) * size;
int dstY = ( destIndex >> 4 ) * size;
FastBitmap.MovePortion( x * size, y * size, dstX, dstY, atlas, atlas, size );
}
srcIndex++;
if( isUsed ) destIndex++;
}
}
}
}
}