mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-01-22 17:12:25 -05:00
Cleanup in TextureAtlas2D, rename TextureAtlas2D to TerrainAtlas2D, move Vector3I to own file.
This commit is contained in:
parent
e2289b1a92
commit
d65ba5b226
14 changed files with 286 additions and 339 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -153,9 +153,11 @@
|
|||
<Compile Include="Utils\FastBitmap.cs" />
|
||||
<Compile Include="Utils\FastColour.cs" />
|
||||
<Compile Include="Utils\TextureAtlas1D.cs" />
|
||||
<Compile Include="Utils\TextureAtlas2D.cs" />
|
||||
<Compile Include="Utils\TerrainAtlas2D.cs" />
|
||||
<Compile Include="Utils\TextureRectangle.cs" />
|
||||
<Compile Include="Utils\UnsafeString.cs" />
|
||||
<Compile Include="Utils\Utils.cs" />
|
||||
<Compile Include="Utils\Vector3I.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include=".NETFramework,Version=v4.0">
|
||||
|
|
|
@ -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;
|
||||
|
|
19
Game/Game.cs
19
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] );
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
80
Utils/TerrainAtlas2D.cs
Normal file
80
Utils/TerrainAtlas2D.cs
Normal file
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
34
Utils/TextureRectangle.cs
Normal file
34
Utils/TextureRectangle.cs
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
129
Utils/Utils.cs
129
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
118
Utils/Vector3I.cs
Normal file
118
Utils/Vector3I.cs
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue