From d65ba5b226d4d8601090a1f752bff4722eb705b1 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 27 May 2015 17:57:39 +1000 Subject: [PATCH] Cleanup in TextureAtlas2D, rename TextureAtlas2D to TerrainAtlas2D, move Vector3I to own file. --- 2D/Screens/BlockSelectScreen.cs | 4 +- 2D/Widgets/BlockHotbarWidget.cs | 4 +- Blocks/BlockInfo.Optimised.cs | 41 ---------- ClassicalSharp.csproj | 4 +- Entities/ParticleManager.cs | 6 +- Game/Game.cs | 19 ++--- Map/ChunkMeshBuilderTex2Col4.cs | 21 ++---- Model/BlockModel.cs | 8 +- Utils/TerrainAtlas2D.cs | 80 ++++++++++++++++++++ Utils/TextureAtlas1D.cs | 29 +++---- Utils/TextureAtlas2D.cs | 128 ------------------------------- Utils/TextureRectangle.cs | 34 +++++++++ Utils/Utils.cs | 129 +++----------------------------- Utils/Vector3I.cs | 118 +++++++++++++++++++++++++++++ 14 files changed, 286 insertions(+), 339 deletions(-) create mode 100644 Utils/TerrainAtlas2D.cs delete mode 100644 Utils/TextureAtlas2D.cs create mode 100644 Utils/TextureRectangle.cs create mode 100644 Utils/Vector3I.cs diff --git a/2D/Screens/BlockSelectScreen.cs b/2D/Screens/BlockSelectScreen.cs index 7f550b040..de43f0e70 100644 --- a/2D/Screens/BlockSelectScreen.cs +++ b/2D/Screens/BlockSelectScreen.cs @@ -31,7 +31,7 @@ namespace ClassicalSharp { public override void Render( double delta ) { GraphicsApi.Texturing = true; - GraphicsApi.Bind2DTexture( Window.TerrainAtlasTexId ); + GraphicsApi.Bind2DTexture( Window.TerrainAtlas.TexId ); for( int i = 0; i < blocksTable.Length; i++ ) { Texture texture = blocksTable[i].Texture; @@ -146,7 +146,7 @@ namespace ClassicalSharp { float height = Window.BlockInfo.BlockHeight( (byte)block ); int blockY = y; if( height != 1 ) { - rec.V1 = rec.V1 + Window.TerrainAtlas.invVerElementSize * height; + rec.V1 = rec.V1 + TerrainAtlas2D.invElementSize * height; verSize = (int)( blockSize * height ); blockY = y + blockSize - verSize; } diff --git a/2D/Widgets/BlockHotbarWidget.cs b/2D/Widgets/BlockHotbarWidget.cs index 3394c75d2..3aec2a91e 100644 --- a/2D/Widgets/BlockHotbarWidget.cs +++ b/2D/Widgets/BlockHotbarWidget.cs @@ -50,7 +50,7 @@ namespace ClassicalSharp { public override void Render( double delta ) { GraphicsApi.Texturing = true; // TODO: Maybe redesign this so we don't have to bind the whole atlas. Not cheap. - GraphicsApi.Bind2DTexture( Window.TerrainAtlasTexId ); + GraphicsApi.Bind2DTexture( Window.TerrainAtlas.TexId ); int selectedX = 0; for( int i = 0; i < barTextures.Length; i++ ) { barTextures[i].RenderNoBind( GraphicsApi ); @@ -83,7 +83,7 @@ namespace ClassicalSharp { float height = Window.BlockInfo.BlockHeight( (byte)block ); int blockY = y; if( height != 1 ) { - rec.V1 = rec.V1 + Window.TerrainAtlas.invVerElementSize * height; + rec.V1 = rec.V1 + TerrainAtlas2D.invElementSize * height; verSize = (int)( blockSize * height ); blockY = y + blockSize - verSize; } diff --git a/Blocks/BlockInfo.Optimised.cs b/Blocks/BlockInfo.Optimised.cs index 4d3a7356d..37f88ff2c 100644 --- a/Blocks/BlockInfo.Optimised.cs +++ b/Blocks/BlockInfo.Optimised.cs @@ -131,46 +131,5 @@ namespace ClassicalSharp { public int GetOptimTextureLoc( byte block, int face ) { return optimTextures[block * 6 + face]; } - - static ushort[] RowFlags = new ushort[] { - 0xFFFF, // y y y y y y y y y y y y y y y y - 0xFFEE, // y y y y y y y y y y y n y y y n - 0xFFE0, // y y y y y y y y y y y n n n n n - 0xFFE0, // y y y y y y y y y y y n n n n n - 0xFFFF, // y y y y y y y y y y y y y y y y - 0xFA00, // y y y y y n y n n n n n n n n n - }; - - public static void MakeOptimisedTexture( FastBitmap atlas ) { - int tileSize = atlas.Width / 16; - int srcIndex = 0, destIndex = 0; - - for( int y = 0; y < 6; y++ ) { - int flags = RowFlags[y]; - for( int x = 0; x < 16; x++ ) { - bool isUsed = ( flags & 1 << ( 15 - x ) ) != 0; - if( isUsed && srcIndex != destIndex ) { - int srcX = x * tileSize; - int srcY = y * tileSize; - int destX = ( destIndex & 0x0F ) * tileSize; - int destY = ( destIndex >> 4 ) * tileSize; - MovePortion( srcX, srcY, destX, destY, atlas, tileSize ); - } - - srcIndex++; - if( isUsed ) destIndex++; - } - } - } - - unsafe static void MovePortion( int srcX, int srcY, int dstX, int dstY, FastBitmap src, int size ) { - for( int y = 0; y < size; y++ ) { - int* srcRow = src.GetRowPtr( srcY + y ); - int* dstRow = src.GetRowPtr( dstY + y ); - for( int x = 0; x < size; x++ ) { - dstRow[dstX + x] = srcRow[srcX + x]; - } - } - } } } \ No newline at end of file diff --git a/ClassicalSharp.csproj b/ClassicalSharp.csproj index 122719d7e..9d48a3981 100644 --- a/ClassicalSharp.csproj +++ b/ClassicalSharp.csproj @@ -153,9 +153,11 @@ - + + + diff --git a/Entities/ParticleManager.cs b/Entities/ParticleManager.cs index a7157fecb..53e6d2a8f 100644 --- a/Entities/ParticleManager.cs +++ b/Entities/ParticleManager.cs @@ -30,7 +30,7 @@ namespace ClassicalSharp.Particles { } Graphics.Texturing = true; - Graphics.Bind2DTexture( Window.TerrainAtlasTexId ); + Graphics.Bind2DTexture( Window.TerrainAtlas.TexId ); Graphics.AlphaTest = true; Graphics.DrawVertices( DrawMode.Triangles, vertices, count ); Graphics.AlphaTest = false; @@ -54,8 +54,8 @@ namespace ClassicalSharp.Particles { int texLoc = Window.BlockInfo.GetOptimTextureLoc( block, TileSide.Left ); TextureRectangle rec = Window.TerrainAtlas.GetTexRec( texLoc ); - float invHorSize = Window.TerrainAtlas.invHorElementSize; - float invVerSize = Window.TerrainAtlas.invVerElementSize; + float invHorSize = TerrainAtlas2D.invElementSize; + float invVerSize = TerrainAtlas2D.invElementSize; int cellsCountX = (int)( 0.25f / invHorSize ); int cellsCountY = (int)( 0.25f / invVerSize ); float elementXSize = invHorSize * 0.25f; diff --git a/Game/Game.cs b/Game/Game.cs index cbf0df2d3..b42c86da2 100644 --- a/Game/Game.cs +++ b/Game/Game.cs @@ -28,8 +28,7 @@ namespace ClassicalSharp { Camera firstPersonCam, thirdPersonCam; public BlockInfo BlockInfo; public double accumulator; - public TextureAtlas2D TerrainAtlas; - public int TerrainAtlasTexId = -1; + public TerrainAtlas2D TerrainAtlas; public TextureAtlas1D TerrainAtlas1D; public int[] TerrainAtlas1DTexIds; public SkinType DefaultPlayerSkinType; @@ -97,21 +96,14 @@ namespace ClassicalSharp { void LoadAtlas( Bitmap bmp ) { // Cleanup old atlas if applicable. - Graphics.DeleteTexture( ref TerrainAtlasTexId ); if( TerrainAtlas1DTexIds != null ) { for( int i = 0; i < TerrainAtlas1DTexIds.Length; i++ ) { Graphics.DeleteTexture( ref TerrainAtlas1DTexIds[i] ); } } - if( TerrainAtlas != null ) { - TerrainAtlas.AtlasBitmap.Dispose(); - } - - TerrainAtlas = new TextureAtlas2D( Graphics, bmp, 16, 16, 5 ); - using( FastBitmap fastBmp = new FastBitmap( bmp, true ) ) { - BlockInfo.MakeOptimisedTexture( fastBmp ); - TerrainAtlasTexId = Graphics.LoadTexture( fastBmp ); - } + TerrainAtlas.GraphicsApi = Graphics; + TerrainAtlas.Dispose(); + TerrainAtlas.UpdateState( bmp ); int size = Math.Min( 2048, Graphics.MaxTextureDimensions ); TerrainAtlas1DTexIds = TerrainAtlas1D.CreateFrom2DAtlas( Graphics, TerrainAtlas, size ); } @@ -136,6 +128,7 @@ namespace ClassicalSharp { PrintGraphicsInfo(); Bitmap terrainBmp = new Bitmap( "terrain.png" ); TerrainAtlas1D = new TextureAtlas1D(); + TerrainAtlas = new TerrainAtlas2D(); LoadAtlas( terrainBmp ); BlockInfo = new BlockInfo(); BlockInfo.Init(); @@ -290,7 +283,7 @@ namespace ClassicalSharp { SetNewScreen( null ); fpsScreen.Dispose(); SelectionManager.Dispose(); - Graphics.DeleteTexture( ref TerrainAtlasTexId ); + TerrainAtlas.Dispose(); for( int i = 0; i < TerrainAtlas1DTexIds.Length; i++ ) { Graphics.DeleteTexture( ref TerrainAtlas1DTexIds[i] ); } diff --git a/Map/ChunkMeshBuilderTex2Col4.cs b/Map/ChunkMeshBuilderTex2Col4.cs index 8e18fb36c..bd3a023fb 100644 --- a/Map/ChunkMeshBuilderTex2Col4.cs +++ b/Map/ChunkMeshBuilderTex2Col4.cs @@ -201,8 +201,7 @@ namespace ClassicalSharp { void DrawTopFace( int count ) { int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Top ); int drawInfoIndex; - TextureRectangle rec = atlas.GetTexRec( texId, out drawInfoIndex ); - rec.U2 = count; + TextureRectangle rec = atlas.GetTexRec( texId, count, out drawInfoIndex ); FastColour col = GetColour( X, Y + 1, Z, ref map.Sunlight, ref map.Shadowlight ); if( blockHeight == -1 ) { blockHeight = BlockInfo.BlockHeight( tile ); @@ -221,8 +220,7 @@ namespace ClassicalSharp { void DrawBottomFace( int count ) { int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Bottom ); int drawInfoIndex; - TextureRectangle rec = atlas.GetTexRec( texId, out drawInfoIndex ); - rec.U2 = count; + TextureRectangle rec = atlas.GetTexRec( texId, count, out drawInfoIndex ); FastColour col = GetColour( X, Y - 1, Z, ref map.SunlightYBottom, ref map.ShadowlightYBottom ); if( blockHeight == -1 ) { blockHeight = BlockInfo.BlockHeight( tile ); @@ -241,8 +239,7 @@ namespace ClassicalSharp { void DrawBackFace( int count ) { int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Back ); int drawInfoIndex; - TextureRectangle rec = atlas.GetTexRec( texId, out drawInfoIndex ); - rec.U2 = count; + TextureRectangle rec = atlas.GetTexRec( texId, count, out drawInfoIndex ); FastColour col = GetColourAdj( X, Y, Z + 1, ref map.SunlightZSide, ref map.ShadowlightZSide ); if( blockHeight == -1 ) { blockHeight = BlockInfo.BlockHeight( tile ); @@ -264,8 +261,7 @@ namespace ClassicalSharp { void DrawFrontFace( int count ) { int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Front ); int drawInfoIndex; - TextureRectangle rec = atlas.GetTexRec( texId, out drawInfoIndex ); - rec.U2 = count; + TextureRectangle rec = atlas.GetTexRec( texId, count, out drawInfoIndex ); FastColour col = GetColourAdj( X, Y, Z - 1, ref map.SunlightZSide, ref map.ShadowlightZSide ); if( blockHeight == -1 ) { blockHeight = BlockInfo.BlockHeight( tile ); @@ -287,8 +283,7 @@ namespace ClassicalSharp { void DrawLeftFace( int count ) { int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Left ); int drawInfoIndex; - TextureRectangle rec = atlas.GetTexRec( texId, out drawInfoIndex ); - rec.U2 = count; + TextureRectangle rec = atlas.GetTexRec( texId, count, out drawInfoIndex ); FastColour col = GetColourAdj( X - 1, Y, Z, ref map.SunlightXSide, ref map.ShadowlightXSide ); if( blockHeight == -1 ) { blockHeight = BlockInfo.BlockHeight( tile ); @@ -310,8 +305,7 @@ namespace ClassicalSharp { void DrawRightFace( int count ) { int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Right ); int drawInfoIndex; - TextureRectangle rec = atlas.GetTexRec( texId, out drawInfoIndex ); - rec.U2 = count; + TextureRectangle rec = atlas.GetTexRec( texId, count, out drawInfoIndex ); FastColour col = GetColourAdj( X + 1, Y, Z, ref map.SunlightXSide, ref map.ShadowlightXSide ); if( blockHeight == -1 ) { blockHeight = BlockInfo.BlockHeight( tile ); @@ -333,8 +327,7 @@ namespace ClassicalSharp { void DrawSprite( int count ) { int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Right ); int drawInfoIndex; - TextureRectangle rec = atlas.GetTexRec( texId, out drawInfoIndex ); - rec.U2 = count; + TextureRectangle rec = atlas.GetTexRec( texId, count, out drawInfoIndex ); FastColour col = GetColour( X, Y + 1, Z, ref map.Sunlight, ref map.Shadowlight ); if( blockHeight == -1 ) { blockHeight = BlockInfo.BlockHeight( tile ); diff --git a/Model/BlockModel.cs b/Model/BlockModel.cs index c11bd4808..1087b2615 100644 --- a/Model/BlockModel.cs +++ b/Model/BlockModel.cs @@ -26,7 +26,7 @@ namespace ClassicalSharp.Model { return; } - graphics.Bind2DTexture( window.TerrainAtlasTexId ); + graphics.Bind2DTexture( window.TerrainAtlas.TexId ); blockHeight = window.BlockInfo.BlockHeight( block ); atlas = window.TerrainAtlas; BlockInfo = window.BlockInfo; @@ -46,7 +46,7 @@ namespace ClassicalSharp.Model { } } float blockHeight; - TextureAtlas2D atlas; + TerrainAtlas2D atlas; BlockInfo BlockInfo; public override void Dispose() { @@ -69,7 +69,7 @@ namespace ClassicalSharp.Model { int texId = BlockInfo.GetOptimTextureLoc( block, side ); TextureRectangle rec = atlas.GetTexRec( texId ); if( blockHeight != 1 ) { - rec.V2 = rec.V1 + blockHeight * atlas.invVerElementSize; + rec.V2 = rec.V1 + blockHeight * TerrainAtlas2D.invElementSize; } if( swapU ) rec.SwapU(); @@ -86,7 +86,7 @@ namespace ClassicalSharp.Model { int texId = BlockInfo.GetOptimTextureLoc( block, side ); TextureRectangle rec = atlas.GetTexRec( texId ); if( blockHeight != 1 ) { - rec.V2 = rec.V1 + blockHeight * atlas.invVerElementSize; + rec.V2 = rec.V1 + blockHeight * TerrainAtlas2D.invElementSize; } if( swapU ) rec.SwapU(); diff --git a/Utils/TerrainAtlas2D.cs b/Utils/TerrainAtlas2D.cs new file mode 100644 index 000000000..570fe1523 --- /dev/null +++ b/Utils/TerrainAtlas2D.cs @@ -0,0 +1,80 @@ +using System; +using System.Drawing; +using ClassicalSharp.GraphicsAPI; + +namespace ClassicalSharp { + + public static class TileSide { + public const int Left = 0; + public const int Right = 1; + public const int Front = 2; + public const int Back = 3; + public const int Bottom = 4; + public const int Top = 5; + } + + public class TerrainAtlas2D : IDisposable { + + public const int ElementsPerRow = 16, RowsCount = 16; + public const float invElementSize = 0.0625f; + public readonly int UsedRowsCount = 5; + public Bitmap AtlasBitmap; + public int elementSize; + public IGraphicsApi GraphicsApi; + public int TexId; + + public void UpdateState( Bitmap bmp ) { + AtlasBitmap = bmp; + elementSize = bmp.Width >> 4; + using( FastBitmap fastBmp = new FastBitmap( bmp, true ) ) { + MakeOptimisedTexture( fastBmp ); + TexId = GraphicsApi.LoadTexture( fastBmp ); + } + } + + public int LoadTextureElement( int index ) { + int x = index & 0x0F; + int y = index >> 4; + using( FastBitmap atlas = new FastBitmap( AtlasBitmap, true ) ) { + Bitmap bmp = new Bitmap( elementSize, elementSize ); + using( FastBitmap dst = new FastBitmap( bmp, true ) ) { + Utils.MovePortion( x * elementSize, y * elementSize, 0, 0, atlas, dst, elementSize ); + return GraphicsApi.LoadTexture( dst ); + } + } + } + + public TextureRectangle GetTexRec( int index ) { + int x = index & 0x0F; + int y = index >> 4; + return new TextureRectangle( x * invElementSize, y * invElementSize, invElementSize, invElementSize ); + } + + public void Dispose() { + if( AtlasBitmap != null ) { + AtlasBitmap.Dispose(); + } + GraphicsApi.DeleteTexture( ref TexId ); + } + + static ushort[] rowFlags = { 0xFFFF, 0xFFEE, 0xFFE0, 0xFFE0, 0xFFFF, 0xFA00 }; + void MakeOptimisedTexture( FastBitmap atlas ) { + int srcIndex = 0, destIndex = 0; + + 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 ) * elementSize; + int dstY = ( destIndex >> 4 ) * elementSize; + Utils.MovePortion( x * elementSize, y * elementSize, dstX, dstY, atlas, atlas, elementSize ); + } + + srcIndex++; + if( isUsed ) destIndex++; + } + } + } + } +} \ No newline at end of file diff --git a/Utils/TextureAtlas1D.cs b/Utils/TextureAtlas1D.cs index c14f5483e..2b28a86d4 100644 --- a/Utils/TextureAtlas1D.cs +++ b/Utils/TextureAtlas1D.cs @@ -10,10 +10,10 @@ namespace ClassicalSharp { internal int elementsPerBitmap; public float invElementSize; - public TextureRectangle GetTexRec( int texId, out int index ) { + public TextureRectangle GetTexRec( int texId, int uCount, out int index ) { index = texId / usedElementsPerAtlas1D; int y = texId % usedElementsPerAtlas1D; - return new TextureRectangle( 0, y * invElementSize, 1, invElementSize ); + return new TextureRectangle( 0, y * invElementSize, uCount, invElementSize ); } public int Get1DIndex( int texId ) { @@ -24,34 +24,35 @@ namespace ClassicalSharp { return texId % usedElementsPerAtlas1D; } - public int[] CreateFrom2DAtlas( IGraphicsApi graphics, TextureAtlas2D atlas2D, int maxVerSize ) { - int verElements = maxVerSize / atlas2D.verElementSize; - int totalElements = atlas2D.UsedRowsCount * atlas2D.ElementsPerRow; + public int[] CreateFrom2DAtlas( IGraphicsApi graphics, TerrainAtlas2D atlas2D, int maxVerSize ) { + int verElements = maxVerSize / atlas2D.elementSize; + int totalElements = atlas2D.UsedRowsCount * TerrainAtlas2D.ElementsPerRow; + int elemSize = atlas2D.elementSize; int atlasesCount = totalElements / verElements + ( totalElements % verElements != 0 ? 1 : 0 ); usedElementsPerAtlas1D = Math.Min( verElements, totalElements ); // in case verElements > totalElements - int atlas1DHeight = Utils.NextPowerOf2( usedElementsPerAtlas1D * atlas2D.verElementSize ); + int atlas1DHeight = Utils.NextPowerOf2( usedElementsPerAtlas1D * atlas2D.elementSize ); int index = 0; - int x = 0, y = 0; int[] texIds = new int[atlasesCount]; Utils.LogDebug( "Loaded new atlas: {0} bmps, {1} per bmp", atlasesCount, usedElementsPerAtlas1D ); using( FastBitmap atlas = new FastBitmap( atlas2D.AtlasBitmap, true ) ) { for( int i = 0; i < texIds.Length; i++ ) { - Bitmap atlas1d = new Bitmap( atlas2D.horElementSize, atlas1DHeight ); - using( FastBitmap dest = new FastBitmap( atlas1d, true ) ) { - for( int j = 0; j < usedElementsPerAtlas1D; j++ ) { - atlas2D.GetCoords( index, ref x, ref y ); - atlas2D.CopyPortion( x, y, 0, j * atlas2D.verElementSize, atlas, dest ); + Bitmap atlas1d = new Bitmap( atlas2D.elementSize, atlas1DHeight ); + using( FastBitmap dst = new FastBitmap( atlas1d, true ) ) { + for( int y_1D = 0; y_1D < usedElementsPerAtlas1D; y_1D++ ) { + int x = index & 0x0F; + int y = index >> 4; + Utils.MovePortion( x * elemSize, y * elemSize, 0, y_1D * elemSize, atlas, dst, elemSize ); index++; } - texIds[i] = graphics.LoadTexture( dest ); + texIds[i] = graphics.LoadTexture( dst ); } atlas1d.Dispose(); } } - elementsPerBitmap = atlas1DHeight / atlas2D.verElementSize; + elementsPerBitmap = atlas1DHeight / atlas2D.elementSize; invElementSize = 1f / elementsPerBitmap; return texIds; } diff --git a/Utils/TextureAtlas2D.cs b/Utils/TextureAtlas2D.cs deleted file mode 100644 index 281ef3ab3..000000000 --- a/Utils/TextureAtlas2D.cs +++ /dev/null @@ -1,128 +0,0 @@ -using System; -using System.Drawing; -using ClassicalSharp.GraphicsAPI; - -namespace ClassicalSharp { - - public struct TextureRectangle { - public float U1, V1, U2, V2; - - public TextureRectangle( float u, float v, float uWidth, float vHeight ) { - U1 = u; - V1 = v; - U2 = u + uWidth; - V2 = v + vHeight; - } - - public static TextureRectangle FromPoints( float u1, float u2, float v1, float v2 ) { - TextureRectangle rec; - rec.U1 = u1; - rec.U2 = u2; - rec.V1 = v1; - rec.V2 = v2; - return rec; - } - - public override string ToString() { - return String.Format( "{0}, {1} : {2}, {3}", U1, V1, U2, V2 ); - } - - internal void SwapU() { - float u2 = U2; - U2 = U1; - U1 = u2; - } - } - - public static class TileSide { - public const int Left = 0; - public const int Right = 1; - public const int Front = 2; - public const int Back = 3; - public const int Bottom = 4; - public const int Top = 5; - } - - public class TextureAtlas2D : IDisposable { - - public int ElementsPerRow; - public int RowsCount; - public int UsedRowsCount; - public Bitmap AtlasBitmap; - public int horElementSize, verElementSize; - public float invHorElementSize, invVerElementSize; - public IGraphicsApi GraphicsApi; - - public TextureAtlas2D( IGraphicsApi graphics, string path, int elementsPerRow, int rows, int usedRows ) { - Bitmap bmp = new Bitmap( path ); - GraphicsApi = graphics; - Init( bmp, elementsPerRow, rows, usedRows ); - } - - public TextureAtlas2D( IGraphicsApi graphics, Bitmap bmp, int elementsPerRow, int rows, int usedRows ) { - GraphicsApi = graphics; - Init( bmp, elementsPerRow, rows, usedRows ); - } - - void Init( Bitmap bmp, int elementsPerRow, int rows, int usedRows ) { - AtlasBitmap = bmp; - ElementsPerRow = elementsPerRow; - RowsCount = rows; - horElementSize = bmp.Width / ElementsPerRow; - verElementSize = bmp.Height / RowsCount; - UsedRowsCount = usedRows; - invHorElementSize = (float)horElementSize / bmp.Width; - invVerElementSize = (float)verElementSize / bmp.Height; - } - - public int LoadTextureElement( int x, int y ) { - using( FastBitmap atlas = new FastBitmap( AtlasBitmap, true ) ) { - Bitmap bmp = new Bitmap( horElementSize, verElementSize ); - using( FastBitmap dest = new FastBitmap( bmp, true ) ) { - CopyPortion( x, y, 0, 0, atlas, dest ); - return GraphicsApi.LoadTexture( dest ); - } - } - } - - public int LoadTextureElement( int index ) { - int x = 0, y = 0; - GetCoords( index, ref x, ref y ); - return LoadTextureElement( x, y ); - } - - public TextureRectangle GetTexRec( int x, int y ) { - return new TextureRectangle( x * invHorElementSize, y * invVerElementSize, - invHorElementSize, invVerElementSize ); - } - - public TextureRectangle GetTexRec( int index ) { - int x = 0, y = 0; - GetCoords( index, ref x, ref y ); - return GetTexRec( x, y ); - } - - internal void GetCoords( int id, ref int x, ref int y ) { - x = id % ElementsPerRow; - y = id / ElementsPerRow; - } - - internal unsafe void CopyPortion( int tileX, int tileY, int dstX, int dstY, FastBitmap atlas, FastBitmap dst ) { - int atlasX = tileX * horElementSize; - int atlasY = tileY * verElementSize; - for( int y = 0; y < verElementSize; y++ ) { - int* srcRow = atlas.GetRowPtr( atlasY + y ); - int* dstRow = dst.GetRowPtr( dstY + y ); - for( int x = 0; x < horElementSize; x++ ) { - dstRow[dstX + x] = srcRow[atlasX + x]; - } - } - } - - public void Dispose() { - if( AtlasBitmap != null ) { - AtlasBitmap.Dispose(); - } - } - } -} \ No newline at end of file diff --git a/Utils/TextureRectangle.cs b/Utils/TextureRectangle.cs new file mode 100644 index 000000000..7320799fb --- /dev/null +++ b/Utils/TextureRectangle.cs @@ -0,0 +1,34 @@ +using System; + +namespace ClassicalSharp { + + public struct TextureRectangle { + public float U1, V1, U2, V2; + + public TextureRectangle( float u, float v, float uWidth, float vHeight ) { + U1 = u; + V1 = v; + U2 = u + uWidth; + V2 = v + vHeight; + } + + public static TextureRectangle FromPoints( float u1, float u2, float v1, float v2 ) { + TextureRectangle rec; + rec.U1 = u1; + rec.U2 = u2; + rec.V1 = v1; + rec.V2 = v2; + return rec; + } + + public override string ToString() { + return String.Format( "{0}, {1} : {2}, {3}", U1, V1, U2, V2 ); + } + + internal void SwapU() { + float u2 = U2; + U2 = U1; + U1 = u2; + } + } +} \ No newline at end of file diff --git a/Utils/Utils.cs b/Utils/Utils.cs index 420a61ecb..8b4baa0c8 100644 --- a/Utils/Utils.cs +++ b/Utils/Utils.cs @@ -1,9 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Text; -using ClassicalSharp.GraphicsAPI; -using OpenTK; +using System; +using System.Drawing; +using System.Text; +using OpenTK; namespace ClassicalSharp { @@ -230,118 +228,15 @@ namespace ClassicalSharp { throw new NotSupportedException( "unsupported skin: " + bmp.Width + ", " + bmp.Height ); } } - } - - public struct Vector3I { - public static Vector3I Zero = new Vector3I( 0, 0, 0 ); - public static Vector3I UnitX = new Vector3I( 1, 0, 0 ); - public static Vector3I UnitY = new Vector3I( 0, 1, 0 ); - public static Vector3I UnitZ = new Vector3I( 0, 0, 1 ); - - public int X, Y, Z; - - public float Length { - get { return (float)Math.Sqrt( X * X + Y * Y + Z + Z ); } - } - - public int LengthSquared { - get { return X * X + Y * Y + Z + Z; } - } - - public Vector3 Normalise() { - float len = Length; - return new Vector3( X / len, Y / len, Z / len ); - } - - public Vector3I( int x, int y, int z ) { - X = x; - Y = y; - Z = z; - } - - public Vector3I( int value ) { - X = value; - Y = value; - Z = value; - } - - public static Vector3I operator + ( Vector3I left, Vector3I right ) { - return new Vector3I( left.X + right.X, left.Y + right.Y, left.Z + right.Z ); - } - - public static Vector3I operator - ( Vector3I left, Vector3I right ) { - return new Vector3I( left.X - right.X, left.Y - right.Y, left.Z - right.Z ); - } - - public static Vector3I operator - ( Vector3I left ) { - return new Vector3I( -left.X, -left.Y, -left.Z ); - } - - public static explicit operator Vector3I( Vector3 value ) { - return Truncate( value ); - } - - public static explicit operator Vector3( Vector3I value ) { - return new Vector3( value.X, value.Y, value.Z ); - } - - public override bool Equals( object obj ) { - return obj is Vector3I && Equals( (Vector3I)obj ); - } - - public bool Equals( Vector3I other ) { - return X == other.X && Y == other.Y && Z == other.Z; - } - - public override int GetHashCode(){ - int hashCode = 1000000007 * X; - hashCode += 1000000009 * Y; - hashCode += 1000000021 * Z; - return hashCode; - } - - public static bool operator == ( Vector3I lhs, Vector3I rhs ) { - return lhs.X == rhs.X && lhs.Y == rhs.Y && lhs.Z == rhs.Z; - } - - public static bool operator != (Vector3I lhs, Vector3I rhs) { - return !( lhs.X == rhs.X && lhs.Y == rhs.Y && lhs.Z == rhs.Z ); - } - - public static Vector3I Truncate( Vector3 vector ) { - int x = (int)vector.X; - int y = (int)vector.Y; - int z = (int)vector.Z; - return new Vector3I( x, y, z ); - } - - public static Vector3I Floor( Vector3 value ) { - return new Vector3I( Utils.Floor( value.X ), Utils.Floor( value.Y ), Utils.Floor( value.Z ) ); - } - - public static Vector3I Floor( float x, float y, float z ) { - return new Vector3I( Utils.Floor( x ), Utils.Floor( y ), Utils.Floor( z ) ); - } - - public static Vector3I Min( Vector3I p1, Vector3I p2 ) { - return new Vector3I( Math.Min( p1.X, p2.X ), Math.Min( p1.Y, p2.Y ), Math.Min( p1.Z, p2.Z ) ); - } - - public static Vector3I Min( int x1, int y1, int z1, int x2, int y2, int z2 ) { - return new Vector3I( Math.Min( x1, x2 ), Math.Min( y1, y2 ), Math.Min( z1, z2 ) ); - } - - public static Vector3I Max( Vector3I p1, Vector3I p2 ) { - return new Vector3I( Math.Max( p1.X, p2.X ), Math.Max( p1.Y, p2.Y ), Math.Max( p1.Z, p2.Z ) ); - } - - public static Vector3I Max( int x1, int y1, int z1, int x2, int y2, int z2 ) { - return new Vector3I( Math.Max( x1, x2 ), Math.Max( y1, y2 ), Math.Max( z1, z2 ) ); - } - - public override string ToString() { - return X + "," + Y + "," + Z; + internal unsafe static void MovePortion( int srcX, int srcY, int dstX, int dstY, FastBitmap src, FastBitmap dst, int size ) { + for( int y = 0; y < size; y++ ) { + int* srcRow = src.GetRowPtr( srcY + y ); + int* dstRow = dst.GetRowPtr( dstY + y ); + for( int x = 0; x < size; x++ ) { + dstRow[dstX + x] = srcRow[srcX + x]; + } + } } } } \ No newline at end of file diff --git a/Utils/Vector3I.cs b/Utils/Vector3I.cs new file mode 100644 index 000000000..28aa1d619 --- /dev/null +++ b/Utils/Vector3I.cs @@ -0,0 +1,118 @@ +using System; +using OpenTK; + +namespace ClassicalSharp { + + public struct Vector3I { + + public static Vector3I Zero = new Vector3I( 0, 0, 0 ); + public static Vector3I UnitX = new Vector3I( 1, 0, 0 ); + public static Vector3I UnitY = new Vector3I( 0, 1, 0 ); + public static Vector3I UnitZ = new Vector3I( 0, 0, 1 ); + + public int X, Y, Z; + + public float Length { + get { return (float)Math.Sqrt( X * X + Y * Y + Z + Z ); } + } + + public int LengthSquared { + get { return X * X + Y * Y + Z + Z; } + } + + public Vector3 Normalise() { + float len = Length; + return new Vector3( X / len, Y / len, Z / len ); + } + + public Vector3I( int x, int y, int z ) { + X = x; + Y = y; + Z = z; + } + + public Vector3I( int value ) { + X = value; + Y = value; + Z = value; + } + + public static Vector3I operator + ( Vector3I left, Vector3I right ) { + return new Vector3I( left.X + right.X, left.Y + right.Y, left.Z + right.Z ); + } + + public static Vector3I operator - ( Vector3I left, Vector3I right ) { + return new Vector3I( left.X - right.X, left.Y - right.Y, left.Z - right.Z ); + } + + public static Vector3I operator - ( Vector3I left ) { + return new Vector3I( -left.X, -left.Y, -left.Z ); + } + + public static explicit operator Vector3I( Vector3 value ) { + return Truncate( value ); + } + + public static explicit operator Vector3( Vector3I value ) { + return new Vector3( value.X, value.Y, value.Z ); + } + + public override bool Equals( object obj ) { + return obj is Vector3I && Equals( (Vector3I)obj ); + } + + public bool Equals( Vector3I other ) { + return X == other.X && Y == other.Y && Z == other.Z; + } + + public override int GetHashCode(){ + int hashCode = 1000000007 * X; + hashCode += 1000000009 * Y; + hashCode += 1000000021 * Z; + return hashCode; + } + + public static bool operator == ( Vector3I lhs, Vector3I rhs ) { + return lhs.X == rhs.X && lhs.Y == rhs.Y && lhs.Z == rhs.Z; + } + + public static bool operator != (Vector3I lhs, Vector3I rhs) { + return !( lhs.X == rhs.X && lhs.Y == rhs.Y && lhs.Z == rhs.Z ); + } + + public static Vector3I Truncate( Vector3 vector ) { + int x = (int)vector.X; + int y = (int)vector.Y; + int z = (int)vector.Z; + return new Vector3I( x, y, z ); + } + + public static Vector3I Floor( Vector3 value ) { + return new Vector3I( Utils.Floor( value.X ), Utils.Floor( value.Y ), Utils.Floor( value.Z ) ); + } + + public static Vector3I Floor( float x, float y, float z ) { + return new Vector3I( Utils.Floor( x ), Utils.Floor( y ), Utils.Floor( z ) ); + } + + public static Vector3I Min( Vector3I p1, Vector3I p2 ) { + return new Vector3I( Math.Min( p1.X, p2.X ), Math.Min( p1.Y, p2.Y ), Math.Min( p1.Z, p2.Z ) ); + } + + public static Vector3I Min( int x1, int y1, int z1, int x2, int y2, int z2 ) { + return new Vector3I( Math.Min( x1, x2 ), Math.Min( y1, y2 ), Math.Min( z1, z2 ) ); + } + + public static Vector3I Max( Vector3I p1, Vector3I p2 ) { + return new Vector3I( Math.Max( p1.X, p2.X ), Math.Max( p1.Y, p2.Y ), Math.Max( p1.Z, p2.Z ) ); + } + + public static Vector3I Max( int x1, int y1, int z1, int x2, int y2, int z2 ) { + return new Vector3I( Math.Max( x1, x2 ), Math.Max( y1, y2 ), Math.Max( z1, z2 ) ); + } + + public override string ToString() { + return X + "," + Y + "," + Z; + } + } +} \ No newline at end of file