diff --git a/ClassicalSharp/2D/IsometricBlockDrawer.cs b/ClassicalSharp/2D/IsometricBlockDrawer.cs index 3f00b39a6..d809af467 100644 --- a/ClassicalSharp/2D/IsometricBlockDrawer.cs +++ b/ClassicalSharp/2D/IsometricBlockDrawer.cs @@ -7,17 +7,25 @@ using OpenTK; namespace ClassicalSharp { - public static class IsometricBlockDrawer { + public sealed class IsometricBlockDrawer { - static BlockInfo info; - static ModelCache cache; - static IGraphicsApi api; - static TerrainAtlas1D atlas; - static int index; - static float scale; - static Vector3 minBB, maxBB; + Game game; + TerrainAtlas1D atlas; + int index; + float scale; + Vector3 minBB, maxBB; const float invElemSize = TerrainAtlas2D.invElementSize; - static bool fullBright; + bool fullBright; + VertexP3fT2fC4b[] vertices; + int vb; + + public void BeginBatch( Game game, VertexP3fT2fC4b[] vertices, int vb ) { + this.game = game; + lastIndex = -1; + index = 0; + this.vertices = vertices; + this.vb = vb; + } static FastColour colNormal, colXSide, colZSide, colYBottom; static float cosX, sinX, cosY, sinY; @@ -31,19 +39,14 @@ namespace ClassicalSharp { sinY = (float)Math.Sin( -45f * Utils.Deg2Rad ); } - public static void Draw( Game game, byte block, float size, float x, float y ) { - info = game.BlockInfo; - cache = game.ModelCache; + public void DrawBatch( byte block, float size, float x, float y ) { + BlockInfo info = game.BlockInfo; atlas = game.TerrainAtlas1D; minBB = info.MinBB[block]; maxBB = info.MaxBB[block]; fullBright = info.FullBright[block]; - if( info.IsSprite[block] ) { - minBB = Vector3.Zero; maxBB = Vector3.One; - } + if( info.IsSprite[block] ) { minBB = Vector3.Zero; maxBB = Vector3.One; } if( info.IsAir[block] ) return; - index = 0; - api = game.Graphics; // isometric coords size: cosY * -scale - sinY * scale // we need to divide by (2 * cosY), as the calling function expects size to be in pixels. @@ -64,22 +67,23 @@ namespace ClassicalSharp { ZQuad( block, Make( minBB.Z ), Side.Back ); YQuad( block, Make( maxBB.Y ), Side.Top ); } - + } + + public void EndBatch() { if( index == 0 ) return; - if( atlas.TexIds[texIndex] != lastTexId ) { - lastTexId = atlas.TexIds[texIndex]; - api.BindTexture( lastTexId ); - } - for( int i = 0; i < index; i++ ) - TransformVertex( ref cache.vertices[i] ); - api.UpdateDynamicIndexedVb( DrawMode.Triangles, cache.vb, cache.vertices, index, index * 6 / 4 ); + if( texIndex != lastIndex ) + game.Graphics.BindTexture( atlas.TexIds[texIndex] ); + game.Graphics.UpdateDynamicIndexedVb( DrawMode.Triangles, + vb, vertices, index, index * 6 / 4 ); + index = 0; + lastIndex = -1; } static Vector3 pos = Vector3.Zero; - static void YQuad( byte block, float y, int side ) { - int texLoc = info.GetTextureLoc( block, side ); + void YQuad( byte block, float y, int side ) { + int texLoc = game.BlockInfo.GetTextureLoc( block, side ); TextureRec rec = atlas.GetTexRec( texLoc, 1, out texIndex ); - FlushIfNotSame(); + if( lastIndex != texIndex ) Flush(); FastColour col = colNormal; float vOrigin = (texLoc % atlas.elementsPerAtlas1D) * atlas.invElementSize; @@ -87,16 +91,20 @@ namespace ClassicalSharp { rec.V1 = vOrigin + minBB.Z * atlas.invElementSize; rec.V2 = vOrigin + maxBB.Z * atlas.invElementSize * (15.99f/16f); - cache.vertices[index++] = new VertexP3fT2fC4b( Make( minBB.X ), y, Make( minBB.Z ), rec.U2, rec.V2, col ); - cache.vertices[index++] = new VertexP3fT2fC4b( Make( maxBB.X ), y, Make( minBB.Z ), rec.U1, rec.V2, col ); - cache.vertices[index++] = new VertexP3fT2fC4b( Make( maxBB.X ), y, Make( maxBB.Z ), rec.U1, rec.V1, col ); - cache.vertices[index++] = new VertexP3fT2fC4b( Make( minBB.X ), y, Make( maxBB.Z ), rec.U2, rec.V1, col ); + vertices[index] = new VertexP3fT2fC4b( Make( minBB.X ), y, Make( minBB.Z ), rec.U2, rec.V2, col ); + Transform( ref vertices[index] ); + vertices[index] = new VertexP3fT2fC4b( Make( maxBB.X ), y, Make( minBB.Z ), rec.U1, rec.V2, col ); + Transform( ref vertices[index] ); + vertices[index] = new VertexP3fT2fC4b( Make( maxBB.X ), y, Make( maxBB.Z ), rec.U1, rec.V1, col ); + Transform( ref vertices[index] ); + vertices[index] = new VertexP3fT2fC4b( Make( minBB.X ), y, Make( maxBB.Z ), rec.U2, rec.V1, col ); + Transform( ref vertices[index] ); } - static void ZQuad( byte block, float z, int side ) { - int texLoc = info.GetTextureLoc( block, side ); + void ZQuad( byte block, float z, int side ) { + int texLoc = game.BlockInfo.GetTextureLoc( block, side ); TextureRec rec = atlas.GetTexRec( texLoc, 1, out texIndex ); - FlushIfNotSame(); + if( lastIndex != texIndex ) Flush(); FastColour col = fullBright ? colNormal : colZSide; float vOrigin = (texLoc % atlas.elementsPerAtlas1D) * atlas.invElementSize; @@ -104,16 +112,20 @@ namespace ClassicalSharp { rec.V1 = vOrigin + (1 - minBB.Y) * atlas.invElementSize; rec.V2 = vOrigin + (1 - maxBB.Y) * atlas.invElementSize * (15.99f/16f); - cache.vertices[index++] = new VertexP3fT2fC4b( Make( minBB.X ), Make( maxBB.Y ), z, rec.U2, rec.V2, col ); - cache.vertices[index++] = new VertexP3fT2fC4b( Make( minBB.X ), Make( minBB.Y ), z, rec.U2, rec.V1, col ); - cache.vertices[index++] = new VertexP3fT2fC4b( Make( maxBB.X ), Make( minBB.Y ), z, rec.U1, rec.V1, col ); - cache.vertices[index++] = new VertexP3fT2fC4b( Make( maxBB.X ), Make( maxBB.Y ), z, rec.U1, rec.V2, col ); + vertices[index] = new VertexP3fT2fC4b( Make( minBB.X ), Make( maxBB.Y ), z, rec.U2, rec.V2, col ); + Transform( ref vertices[index] ); + vertices[index] = new VertexP3fT2fC4b( Make( minBB.X ), Make( minBB.Y ), z, rec.U2, rec.V1, col ); + Transform( ref vertices[index] ); + vertices[index] = new VertexP3fT2fC4b( Make( maxBB.X ), Make( minBB.Y ), z, rec.U1, rec.V1, col ); + Transform( ref vertices[index] ); + vertices[index] = new VertexP3fT2fC4b( Make( maxBB.X ), Make( maxBB.Y ), z, rec.U1, rec.V2, col ); + Transform( ref vertices[index] ); } - static void XQuad( byte block, float x, int side ) { - int texLoc = info.GetTextureLoc( block, side ); + void XQuad( byte block, float x, int side ) { + int texLoc = game.BlockInfo.GetTextureLoc( block, side ); TextureRec rec = atlas.GetTexRec( texLoc, 1, out texIndex ); - FlushIfNotSame(); + if( lastIndex != texIndex ) Flush(); FastColour col = fullBright ? colNormal : colXSide; float vOrigin = (texLoc % atlas.elementsPerAtlas1D) * atlas.invElementSize; @@ -121,61 +133,68 @@ namespace ClassicalSharp { rec.V1 = vOrigin + (1 - minBB.Y) * atlas.invElementSize; rec.V2 = vOrigin + (1 - maxBB.Y) * atlas.invElementSize * (15.99f/16f); - cache.vertices[index++] = new VertexP3fT2fC4b( x, Make( maxBB.Y ), Make( minBB.Z ), rec.U2, rec.V2, col ); - cache.vertices[index++] = new VertexP3fT2fC4b( x, Make( minBB.Y ), Make( minBB.Z ), rec.U2, rec.V1, col ); - cache.vertices[index++] = new VertexP3fT2fC4b( x, Make( minBB.Y ), Make( maxBB.Z ), rec.U1, rec.V1, col ); - cache.vertices[index++] = new VertexP3fT2fC4b( x, Make( maxBB.Y ), Make( maxBB.Z ), rec.U1, rec.V2, col ); + vertices[index] = new VertexP3fT2fC4b( x, Make( maxBB.Y ), Make( minBB.Z ), rec.U2, rec.V2, col ); + Transform( ref vertices[index] ); + vertices[index] = new VertexP3fT2fC4b( x, Make( minBB.Y ), Make( minBB.Z ), rec.U2, rec.V1, col ); + Transform( ref vertices[index] ); + vertices[index] = new VertexP3fT2fC4b( x, Make( minBB.Y ), Make( maxBB.Z ), rec.U1, rec.V1, col ); + Transform( ref vertices[index] ); + vertices[index] = new VertexP3fT2fC4b( x, Make( maxBB.Y ), Make( maxBB.Z ), rec.U1, rec.V2, col ); + Transform( ref vertices[index] ); } - static void SpriteZQuad( byte block, int side, bool firstPart ) { - int texLoc = info.GetTextureLoc( block, side ); + void SpriteZQuad( byte block, int side, bool firstPart ) { + int texLoc = game.BlockInfo.GetTextureLoc( block, side ); TextureRec rec = atlas.GetTexRec( texLoc, 1, out texIndex ); - FlushIfNotSame(); + if( lastIndex != texIndex ) Flush(); FastColour col = colNormal; float x1 = firstPart ? -0.1f : 0.5f, x2 = firstPart ? 0.5f : 1.1f; rec.U1 = firstPart ? 0.0f : 0.5f; rec.U2 = (firstPart ? 0.5f : 1.0f) * (15.99f/16f); - cache.vertices[index++] = new VertexP3fT2fC4b( Make( x1 ), Make( 0.0f ), Make( 0.5f ), rec.U1, rec.V2, col ); - cache.vertices[index++] = new VertexP3fT2fC4b( Make( x1 ), Make( 1.1f ), Make( 0.5f ), rec.U1, rec.V1, col ); - cache.vertices[index++] = new VertexP3fT2fC4b( Make( x2 ), Make( 1.1f ), Make( 0.5f ), rec.U2, rec.V1, col ); - cache.vertices[index++] = new VertexP3fT2fC4b( Make( x2 ), Make( 0.0f ), Make( 0.5f ), rec.U2, rec.V2, col ); + vertices[index] = new VertexP3fT2fC4b( Make( x1 ), Make( 0.0f ), Make( 0.5f ), rec.U1, rec.V2, col ); + Transform( ref vertices[index] ); + vertices[index] = new VertexP3fT2fC4b( Make( x1 ), Make( 1.1f ), Make( 0.5f ), rec.U1, rec.V1, col ); + Transform( ref vertices[index] ); + vertices[index] = new VertexP3fT2fC4b( Make( x2 ), Make( 1.1f ), Make( 0.5f ), rec.U2, rec.V1, col ); + Transform( ref vertices[index] ); + vertices[index] = new VertexP3fT2fC4b( Make( x2 ), Make( 0.0f ), Make( 0.5f ), rec.U2, rec.V2, col ); + Transform( ref vertices[index] ); } - static void SpriteXQuad( byte block, int side, bool firstPart ) { - int texLoc = info.GetTextureLoc( block, side ); + void SpriteXQuad( byte block, int side, bool firstPart ) { + int texLoc = game.BlockInfo.GetTextureLoc( block, side ); TextureRec rec = atlas.GetTexRec( texLoc, 1, out texIndex ); - FlushIfNotSame(); + if( lastIndex != texIndex ) Flush(); FastColour col = colNormal; float z1 = firstPart ? -0.1f : 0.5f, z2 = firstPart ? 0.5f : 1.1f; rec.U1 = firstPart ? 0.0f : 0.5f; rec.U2 = (firstPart ? 0.5f : 1.0f) * (15.99f/16f); - cache.vertices[index++] = new VertexP3fT2fC4b( Make( 0.5f ), Make( 0.0f ), Make( z1 ), rec.U1, rec.V2, col ); - cache.vertices[index++] = new VertexP3fT2fC4b( Make( 0.5f ), Make( 1.1f ), Make( z1 ), rec.U1, rec.V1, col ); - cache.vertices[index++] = new VertexP3fT2fC4b( Make( 0.5f ), Make( 1.1f ), Make( z2 ), rec.U2, rec.V1, col ); - cache.vertices[index++] = new VertexP3fT2fC4b( Make( 0.5f ), Make( 0.0f ), Make( z2 ), rec.U2, rec.V2, col ); + vertices[index] = new VertexP3fT2fC4b( Make( 0.5f ), Make( 0.0f ), Make( z1 ), rec.U1, rec.V2, col ); + Transform( ref vertices[index] ); + vertices[index] = new VertexP3fT2fC4b( Make( 0.5f ), Make( 1.1f ), Make( z1 ), rec.U1, rec.V1, col ); + Transform( ref vertices[index] ); + vertices[index] = new VertexP3fT2fC4b( Make( 0.5f ), Make( 1.1f ), Make( z2 ), rec.U2, rec.V1, col ); + Transform( ref vertices[index] ); + vertices[index] = new VertexP3fT2fC4b( Make( 0.5f ), Make( 0.0f ), Make( z2 ), rec.U2, rec.V2, col ); + Transform( ref vertices[index] ); } - static float Make( float value ) { return scale - (scale * value * 2); } + float Make( float value ) { return scale - (scale * value * 2); } - internal static int lastTexId, texIndex; - static void FlushIfNotSame() { - int texId = atlas.TexIds[texIndex]; - if( texId == lastTexId ) return; - - if( lastTexId != -1 ) { - for( int i = 0; i < index; i++ ) - TransformVertex( ref cache.vertices[i] ); - api.UpdateDynamicIndexedVb( DrawMode.Triangles, cache.vb, - cache.vertices, index, index * 6 / 4 ); + int lastIndex, texIndex; + void Flush() { + if( lastIndex != -1 ) { + game.Graphics.UpdateDynamicIndexedVb( DrawMode.Triangles, + vb, vertices, index, index * 6 / 4 ); index = 0; } - lastTexId = texId; - api.BindTexture( texId ); + lastIndex = texIndex; + game.Graphics.BindTexture( atlas.TexIds[texIndex] ); } - static void TransformVertex( ref VertexP3fT2fC4b v ) { + void Transform( ref VertexP3fT2fC4b v ) { v.X += pos.X; v.Y += pos.Y; v.Z += pos.Z; //Vector3 p = new Vector3( v.X, v.Y, v.Z ) + pos; //p = Utils.RotateY( p - pos, time ) + pos; @@ -185,6 +204,7 @@ namespace ClassicalSharp { v.X -= 0.5f; v.Y -= 0.5f; float t = cosY * v.X - sinY * v.Z; v.Z = sinY * v.X + cosY * v.Z; v.X = t; // Inlined RotY t = cosX * v.Y + sinX * v.Z; v.Z = -sinX * v.Y + cosX * v.Z; v.Y = t; // Inlined RotX + index++; } } } \ No newline at end of file diff --git a/ClassicalSharp/2D/Screens/Inventory/InventoryScreen.cs b/ClassicalSharp/2D/Screens/Inventory/InventoryScreen.cs index 732ed3887..371bba152 100644 --- a/ClassicalSharp/2D/Screens/Inventory/InventoryScreen.cs +++ b/ClassicalSharp/2D/Screens/Inventory/InventoryScreen.cs @@ -20,6 +20,7 @@ namespace ClassicalSharp.Gui { float selBlockExpand; readonly Font font; StringBuffer buffer = new StringBuffer( 128 ); + IsometricBlockDrawer drawer = new IsometricBlockDrawer(); int TableX { get { return startX - 5 - 10; } } int TableY { get { return startY - 5 - 30; } } @@ -28,6 +29,9 @@ namespace ClassicalSharp.Gui { static FastColour normBackCol = new FastColour( 30, 30, 30, 200 ); static FastColour classicBackCol = new FastColour( 48, 48, 96, 192 ); + static VertexP3fT2fC4b[] vertices = new VertexP3fT2fC4b[8 * 10 * (4 * 4)]; + int vb; + public override void Render( double delta ) { FastColour backCol = game.ClassicMode ? classicBackCol : normBackCol; api.Draw2DQuad( TableX, TableY, TableWidth, TableHeight, backCol ); @@ -36,24 +40,24 @@ namespace ClassicalSharp.Gui { api.Texturing = true; api.SetBatchFormat( VertexFormat.P3fT2fC4b ); - IsometricBlockDrawer.lastTexId = -1; + drawer.BeginBatch( game, vertices, vb ); for( int i = 0; i < blocksTable.Length; i++ ) { int x, y; if( !GetCoords( i, out x, out y ) ) continue; // We want to always draw the selected block on top of others if( i == selIndex ) continue; - IsometricBlockDrawer.Draw( game, (byte)blocksTable[i], blockSize * 0.7f / 2f, - x + blockSize / 2, y + blockSize / 2 ); + drawer.DrawBatch( (byte)blocksTable[i], blockSize * 0.7f / 2f, + x + blockSize / 2, y + blockSize / 2 ); } if( selIndex != -1 ) { int x, y; GetCoords( selIndex, out x, out y ); - IsometricBlockDrawer.lastTexId = -1; - IsometricBlockDrawer.Draw( game, (byte)blocksTable[selIndex], (blockSize + selBlockExpand) * 0.7f / 2, - x + blockSize / 2, y + blockSize / 2 ); + drawer.DrawBatch( (byte)blocksTable[selIndex], (blockSize + selBlockExpand) * 0.7f / 2, + x + blockSize / 2, y + blockSize / 2 ); } + drawer.EndBatch(); if( blockInfoTexture.IsValid ) blockInfoTexture.Render( api ); @@ -84,6 +88,7 @@ namespace ClassicalSharp.Gui { public override void Dispose() { font.Dispose(); api.DeleteTexture( ref blockInfoTexture ); + api.DeleteDynamicVb( vb ); game.Events.BlockPermissionsChanged -= BlockPermissionsChanged; game.Keyboard.KeyRepeat = false; } @@ -103,6 +108,7 @@ namespace ClassicalSharp.Gui { blockSize = (int)(50 * Math.Sqrt(game.GuiInventoryScale)); selBlockExpand = (float)(25 * Math.Sqrt(game.GuiInventoryScale)); game.Events.BlockPermissionsChanged += BlockPermissionsChanged; + vb = game.Graphics.CreateDynamicVb( VertexFormat.P3fT2fC4b, vertices.Length ); RecreateBlockTable(); SetBlockTo( game.Inventory.HeldBlock ); @@ -132,7 +138,7 @@ namespace ClassicalSharp.Gui { RecreateBlockInfoTexture(); } - void UpdateBlockInfoString( Block block ) { + void UpdateBlockInfoString( Block block ) { int index = 0; buffer.Clear(); buffer.Append( ref index, "&f" ); @@ -191,7 +197,7 @@ namespace ClassicalSharp.Gui { bool ShowTile( int tile ) { bool hackBlocks = !game.ClassicMode || game.ClassicHacks; - if( !hackBlocks && (tile == (byte)Block.Bedrock || + if( !hackBlocks && (tile == (byte)Block.Bedrock || tile >= (byte)Block.Water && tile <= (byte)Block.StillLava) ) return false; return tile < BlockInfo.CpeBlocksCount || game.BlockInfo.Name[tile] != "Invalid"; diff --git a/ClassicalSharp/2D/Widgets/BlockHotbarWidget.cs b/ClassicalSharp/2D/Widgets/BlockHotbarWidget.cs index cbb1a45a9..1d97fd7c6 100644 --- a/ClassicalSharp/2D/Widgets/BlockHotbarWidget.cs +++ b/ClassicalSharp/2D/Widgets/BlockHotbarWidget.cs @@ -18,6 +18,7 @@ namespace ClassicalSharp.Gui { Texture selTex, backTex; float barHeight, selBlockSize, elemSize; float barXOffset, borderSize; + IsometricBlockDrawer drawer = new IsometricBlockDrawer(); public override void Init() { float scale = 2 * game.GuiHotbarScale; @@ -39,7 +40,8 @@ namespace ClassicalSharp.Gui { public override void Render( double delta ) { api.Texturing = true; RenderHotbar(); - IsometricBlockDrawer.lastTexId = -1; + Model.ModelCache cache = game.ModelCache; + drawer.BeginBatch( game, cache.vertices, cache.vb ); for( int i = 0; i < hotbarCount; i++ ) { byte block = (byte)game.Inventory.Hotbar[i]; @@ -47,8 +49,9 @@ namespace ClassicalSharp.Gui { int y = (int)(game.Height - barHeight / 2); float scale = (elemSize * 13.5f/16f) / 2f; - IsometricBlockDrawer.Draw( game, block, scale, x, y ); + drawer.DrawBatch( block, scale, x, y ); } + drawer.EndBatch(); api.Texturing = false; } diff --git a/ClassicalSharp/Singleplayer/Server.cs b/ClassicalSharp/Singleplayer/Server.cs index 13ccaec4a..4ca513aba 100644 --- a/ClassicalSharp/Singleplayer/Server.cs +++ b/ClassicalSharp/Singleplayer/Server.cs @@ -36,7 +36,7 @@ namespace ClassicalSharp.Singleplayer { game.LocalPlayer.SkinName ); game.Events.RaiseBlockPermissionsChanged(); - int seed = new Random().Next(); + int seed = new Random(200).Next(); GenMap( 128, 64, 128, seed, new NotchyGenerator() ); }