mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-17 11:35:08 -04:00
Cleanup in TextureAtlas2D, rename TextureAtlas2D to TerrainAtlas2D, move Vector3I to own file.
This commit is contained in:
parent
e2289b1a92
commit
d65ba5b226
@ -31,7 +31,7 @@ namespace ClassicalSharp {
|
|||||||
|
|
||||||
public override void Render( double delta ) {
|
public override void Render( double delta ) {
|
||||||
GraphicsApi.Texturing = true;
|
GraphicsApi.Texturing = true;
|
||||||
GraphicsApi.Bind2DTexture( Window.TerrainAtlasTexId );
|
GraphicsApi.Bind2DTexture( Window.TerrainAtlas.TexId );
|
||||||
|
|
||||||
for( int i = 0; i < blocksTable.Length; i++ ) {
|
for( int i = 0; i < blocksTable.Length; i++ ) {
|
||||||
Texture texture = blocksTable[i].Texture;
|
Texture texture = blocksTable[i].Texture;
|
||||||
@ -146,7 +146,7 @@ namespace ClassicalSharp {
|
|||||||
float height = Window.BlockInfo.BlockHeight( (byte)block );
|
float height = Window.BlockInfo.BlockHeight( (byte)block );
|
||||||
int blockY = y;
|
int blockY = y;
|
||||||
if( height != 1 ) {
|
if( height != 1 ) {
|
||||||
rec.V1 = rec.V1 + Window.TerrainAtlas.invVerElementSize * height;
|
rec.V1 = rec.V1 + TerrainAtlas2D.invElementSize * height;
|
||||||
verSize = (int)( blockSize * height );
|
verSize = (int)( blockSize * height );
|
||||||
blockY = y + blockSize - verSize;
|
blockY = y + blockSize - verSize;
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ namespace ClassicalSharp {
|
|||||||
public override void Render( double delta ) {
|
public override void Render( double delta ) {
|
||||||
GraphicsApi.Texturing = true;
|
GraphicsApi.Texturing = true;
|
||||||
// TODO: Maybe redesign this so we don't have to bind the whole atlas. Not cheap.
|
// 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;
|
int selectedX = 0;
|
||||||
for( int i = 0; i < barTextures.Length; i++ ) {
|
for( int i = 0; i < barTextures.Length; i++ ) {
|
||||||
barTextures[i].RenderNoBind( GraphicsApi );
|
barTextures[i].RenderNoBind( GraphicsApi );
|
||||||
@ -83,7 +83,7 @@ namespace ClassicalSharp {
|
|||||||
float height = Window.BlockInfo.BlockHeight( (byte)block );
|
float height = Window.BlockInfo.BlockHeight( (byte)block );
|
||||||
int blockY = y;
|
int blockY = y;
|
||||||
if( height != 1 ) {
|
if( height != 1 ) {
|
||||||
rec.V1 = rec.V1 + Window.TerrainAtlas.invVerElementSize * height;
|
rec.V1 = rec.V1 + TerrainAtlas2D.invElementSize * height;
|
||||||
verSize = (int)( blockSize * height );
|
verSize = (int)( blockSize * height );
|
||||||
blockY = y + blockSize - verSize;
|
blockY = y + blockSize - verSize;
|
||||||
}
|
}
|
||||||
|
@ -131,46 +131,5 @@ namespace ClassicalSharp {
|
|||||||
public int GetOptimTextureLoc( byte block, int face ) {
|
public int GetOptimTextureLoc( byte block, int face ) {
|
||||||
return optimTextures[block * 6 + 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\FastBitmap.cs" />
|
||||||
<Compile Include="Utils\FastColour.cs" />
|
<Compile Include="Utils\FastColour.cs" />
|
||||||
<Compile Include="Utils\TextureAtlas1D.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\UnsafeString.cs" />
|
||||||
<Compile Include="Utils\Utils.cs" />
|
<Compile Include="Utils\Utils.cs" />
|
||||||
|
<Compile Include="Utils\Vector3I.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<BootstrapperPackage Include=".NETFramework,Version=v4.0">
|
<BootstrapperPackage Include=".NETFramework,Version=v4.0">
|
||||||
|
@ -30,7 +30,7 @@ namespace ClassicalSharp.Particles {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Graphics.Texturing = true;
|
Graphics.Texturing = true;
|
||||||
Graphics.Bind2DTexture( Window.TerrainAtlasTexId );
|
Graphics.Bind2DTexture( Window.TerrainAtlas.TexId );
|
||||||
Graphics.AlphaTest = true;
|
Graphics.AlphaTest = true;
|
||||||
Graphics.DrawVertices( DrawMode.Triangles, vertices, count );
|
Graphics.DrawVertices( DrawMode.Triangles, vertices, count );
|
||||||
Graphics.AlphaTest = false;
|
Graphics.AlphaTest = false;
|
||||||
@ -54,8 +54,8 @@ namespace ClassicalSharp.Particles {
|
|||||||
int texLoc = Window.BlockInfo.GetOptimTextureLoc( block, TileSide.Left );
|
int texLoc = Window.BlockInfo.GetOptimTextureLoc( block, TileSide.Left );
|
||||||
TextureRectangle rec = Window.TerrainAtlas.GetTexRec( texLoc );
|
TextureRectangle rec = Window.TerrainAtlas.GetTexRec( texLoc );
|
||||||
|
|
||||||
float invHorSize = Window.TerrainAtlas.invHorElementSize;
|
float invHorSize = TerrainAtlas2D.invElementSize;
|
||||||
float invVerSize = Window.TerrainAtlas.invVerElementSize;
|
float invVerSize = TerrainAtlas2D.invElementSize;
|
||||||
int cellsCountX = (int)( 0.25f / invHorSize );
|
int cellsCountX = (int)( 0.25f / invHorSize );
|
||||||
int cellsCountY = (int)( 0.25f / invVerSize );
|
int cellsCountY = (int)( 0.25f / invVerSize );
|
||||||
float elementXSize = invHorSize * 0.25f;
|
float elementXSize = invHorSize * 0.25f;
|
||||||
|
19
Game/Game.cs
19
Game/Game.cs
@ -28,8 +28,7 @@ namespace ClassicalSharp {
|
|||||||
Camera firstPersonCam, thirdPersonCam;
|
Camera firstPersonCam, thirdPersonCam;
|
||||||
public BlockInfo BlockInfo;
|
public BlockInfo BlockInfo;
|
||||||
public double accumulator;
|
public double accumulator;
|
||||||
public TextureAtlas2D TerrainAtlas;
|
public TerrainAtlas2D TerrainAtlas;
|
||||||
public int TerrainAtlasTexId = -1;
|
|
||||||
public TextureAtlas1D TerrainAtlas1D;
|
public TextureAtlas1D TerrainAtlas1D;
|
||||||
public int[] TerrainAtlas1DTexIds;
|
public int[] TerrainAtlas1DTexIds;
|
||||||
public SkinType DefaultPlayerSkinType;
|
public SkinType DefaultPlayerSkinType;
|
||||||
@ -97,21 +96,14 @@ namespace ClassicalSharp {
|
|||||||
|
|
||||||
void LoadAtlas( Bitmap bmp ) {
|
void LoadAtlas( Bitmap bmp ) {
|
||||||
// Cleanup old atlas if applicable.
|
// Cleanup old atlas if applicable.
|
||||||
Graphics.DeleteTexture( ref TerrainAtlasTexId );
|
|
||||||
if( TerrainAtlas1DTexIds != null ) {
|
if( TerrainAtlas1DTexIds != null ) {
|
||||||
for( int i = 0; i < TerrainAtlas1DTexIds.Length; i++ ) {
|
for( int i = 0; i < TerrainAtlas1DTexIds.Length; i++ ) {
|
||||||
Graphics.DeleteTexture( ref TerrainAtlas1DTexIds[i] );
|
Graphics.DeleteTexture( ref TerrainAtlas1DTexIds[i] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( TerrainAtlas != null ) {
|
TerrainAtlas.GraphicsApi = Graphics;
|
||||||
TerrainAtlas.AtlasBitmap.Dispose();
|
TerrainAtlas.Dispose();
|
||||||
}
|
TerrainAtlas.UpdateState( bmp );
|
||||||
|
|
||||||
TerrainAtlas = new TextureAtlas2D( Graphics, bmp, 16, 16, 5 );
|
|
||||||
using( FastBitmap fastBmp = new FastBitmap( bmp, true ) ) {
|
|
||||||
BlockInfo.MakeOptimisedTexture( fastBmp );
|
|
||||||
TerrainAtlasTexId = Graphics.LoadTexture( fastBmp );
|
|
||||||
}
|
|
||||||
int size = Math.Min( 2048, Graphics.MaxTextureDimensions );
|
int size = Math.Min( 2048, Graphics.MaxTextureDimensions );
|
||||||
TerrainAtlas1DTexIds = TerrainAtlas1D.CreateFrom2DAtlas( Graphics, TerrainAtlas, size );
|
TerrainAtlas1DTexIds = TerrainAtlas1D.CreateFrom2DAtlas( Graphics, TerrainAtlas, size );
|
||||||
}
|
}
|
||||||
@ -136,6 +128,7 @@ namespace ClassicalSharp {
|
|||||||
PrintGraphicsInfo();
|
PrintGraphicsInfo();
|
||||||
Bitmap terrainBmp = new Bitmap( "terrain.png" );
|
Bitmap terrainBmp = new Bitmap( "terrain.png" );
|
||||||
TerrainAtlas1D = new TextureAtlas1D();
|
TerrainAtlas1D = new TextureAtlas1D();
|
||||||
|
TerrainAtlas = new TerrainAtlas2D();
|
||||||
LoadAtlas( terrainBmp );
|
LoadAtlas( terrainBmp );
|
||||||
BlockInfo = new BlockInfo();
|
BlockInfo = new BlockInfo();
|
||||||
BlockInfo.Init();
|
BlockInfo.Init();
|
||||||
@ -290,7 +283,7 @@ namespace ClassicalSharp {
|
|||||||
SetNewScreen( null );
|
SetNewScreen( null );
|
||||||
fpsScreen.Dispose();
|
fpsScreen.Dispose();
|
||||||
SelectionManager.Dispose();
|
SelectionManager.Dispose();
|
||||||
Graphics.DeleteTexture( ref TerrainAtlasTexId );
|
TerrainAtlas.Dispose();
|
||||||
for( int i = 0; i < TerrainAtlas1DTexIds.Length; i++ ) {
|
for( int i = 0; i < TerrainAtlas1DTexIds.Length; i++ ) {
|
||||||
Graphics.DeleteTexture( ref TerrainAtlas1DTexIds[i] );
|
Graphics.DeleteTexture( ref TerrainAtlas1DTexIds[i] );
|
||||||
}
|
}
|
||||||
|
@ -201,8 +201,7 @@ namespace ClassicalSharp {
|
|||||||
void DrawTopFace( int count ) {
|
void DrawTopFace( int count ) {
|
||||||
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Top );
|
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Top );
|
||||||
int drawInfoIndex;
|
int drawInfoIndex;
|
||||||
TextureRectangle rec = atlas.GetTexRec( texId, out drawInfoIndex );
|
TextureRectangle rec = atlas.GetTexRec( texId, count, out drawInfoIndex );
|
||||||
rec.U2 = count;
|
|
||||||
FastColour col = GetColour( X, Y + 1, Z, ref map.Sunlight, ref map.Shadowlight );
|
FastColour col = GetColour( X, Y + 1, Z, ref map.Sunlight, ref map.Shadowlight );
|
||||||
if( blockHeight == -1 ) {
|
if( blockHeight == -1 ) {
|
||||||
blockHeight = BlockInfo.BlockHeight( tile );
|
blockHeight = BlockInfo.BlockHeight( tile );
|
||||||
@ -221,8 +220,7 @@ namespace ClassicalSharp {
|
|||||||
void DrawBottomFace( int count ) {
|
void DrawBottomFace( int count ) {
|
||||||
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Bottom );
|
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Bottom );
|
||||||
int drawInfoIndex;
|
int drawInfoIndex;
|
||||||
TextureRectangle rec = atlas.GetTexRec( texId, out drawInfoIndex );
|
TextureRectangle rec = atlas.GetTexRec( texId, count, out drawInfoIndex );
|
||||||
rec.U2 = count;
|
|
||||||
FastColour col = GetColour( X, Y - 1, Z, ref map.SunlightYBottom, ref map.ShadowlightYBottom );
|
FastColour col = GetColour( X, Y - 1, Z, ref map.SunlightYBottom, ref map.ShadowlightYBottom );
|
||||||
if( blockHeight == -1 ) {
|
if( blockHeight == -1 ) {
|
||||||
blockHeight = BlockInfo.BlockHeight( tile );
|
blockHeight = BlockInfo.BlockHeight( tile );
|
||||||
@ -241,8 +239,7 @@ namespace ClassicalSharp {
|
|||||||
void DrawBackFace( int count ) {
|
void DrawBackFace( int count ) {
|
||||||
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Back );
|
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Back );
|
||||||
int drawInfoIndex;
|
int drawInfoIndex;
|
||||||
TextureRectangle rec = atlas.GetTexRec( texId, out drawInfoIndex );
|
TextureRectangle rec = atlas.GetTexRec( texId, count, out drawInfoIndex );
|
||||||
rec.U2 = count;
|
|
||||||
FastColour col = GetColourAdj( X, Y, Z + 1, ref map.SunlightZSide, ref map.ShadowlightZSide );
|
FastColour col = GetColourAdj( X, Y, Z + 1, ref map.SunlightZSide, ref map.ShadowlightZSide );
|
||||||
if( blockHeight == -1 ) {
|
if( blockHeight == -1 ) {
|
||||||
blockHeight = BlockInfo.BlockHeight( tile );
|
blockHeight = BlockInfo.BlockHeight( tile );
|
||||||
@ -264,8 +261,7 @@ namespace ClassicalSharp {
|
|||||||
void DrawFrontFace( int count ) {
|
void DrawFrontFace( int count ) {
|
||||||
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Front );
|
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Front );
|
||||||
int drawInfoIndex;
|
int drawInfoIndex;
|
||||||
TextureRectangle rec = atlas.GetTexRec( texId, out drawInfoIndex );
|
TextureRectangle rec = atlas.GetTexRec( texId, count, out drawInfoIndex );
|
||||||
rec.U2 = count;
|
|
||||||
FastColour col = GetColourAdj( X, Y, Z - 1, ref map.SunlightZSide, ref map.ShadowlightZSide );
|
FastColour col = GetColourAdj( X, Y, Z - 1, ref map.SunlightZSide, ref map.ShadowlightZSide );
|
||||||
if( blockHeight == -1 ) {
|
if( blockHeight == -1 ) {
|
||||||
blockHeight = BlockInfo.BlockHeight( tile );
|
blockHeight = BlockInfo.BlockHeight( tile );
|
||||||
@ -287,8 +283,7 @@ namespace ClassicalSharp {
|
|||||||
void DrawLeftFace( int count ) {
|
void DrawLeftFace( int count ) {
|
||||||
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Left );
|
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Left );
|
||||||
int drawInfoIndex;
|
int drawInfoIndex;
|
||||||
TextureRectangle rec = atlas.GetTexRec( texId, out drawInfoIndex );
|
TextureRectangle rec = atlas.GetTexRec( texId, count, out drawInfoIndex );
|
||||||
rec.U2 = count;
|
|
||||||
FastColour col = GetColourAdj( X - 1, Y, Z, ref map.SunlightXSide, ref map.ShadowlightXSide );
|
FastColour col = GetColourAdj( X - 1, Y, Z, ref map.SunlightXSide, ref map.ShadowlightXSide );
|
||||||
if( blockHeight == -1 ) {
|
if( blockHeight == -1 ) {
|
||||||
blockHeight = BlockInfo.BlockHeight( tile );
|
blockHeight = BlockInfo.BlockHeight( tile );
|
||||||
@ -310,8 +305,7 @@ namespace ClassicalSharp {
|
|||||||
void DrawRightFace( int count ) {
|
void DrawRightFace( int count ) {
|
||||||
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Right );
|
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Right );
|
||||||
int drawInfoIndex;
|
int drawInfoIndex;
|
||||||
TextureRectangle rec = atlas.GetTexRec( texId, out drawInfoIndex );
|
TextureRectangle rec = atlas.GetTexRec( texId, count, out drawInfoIndex );
|
||||||
rec.U2 = count;
|
|
||||||
FastColour col = GetColourAdj( X + 1, Y, Z, ref map.SunlightXSide, ref map.ShadowlightXSide );
|
FastColour col = GetColourAdj( X + 1, Y, Z, ref map.SunlightXSide, ref map.ShadowlightXSide );
|
||||||
if( blockHeight == -1 ) {
|
if( blockHeight == -1 ) {
|
||||||
blockHeight = BlockInfo.BlockHeight( tile );
|
blockHeight = BlockInfo.BlockHeight( tile );
|
||||||
@ -333,8 +327,7 @@ namespace ClassicalSharp {
|
|||||||
void DrawSprite( int count ) {
|
void DrawSprite( int count ) {
|
||||||
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Right );
|
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Right );
|
||||||
int drawInfoIndex;
|
int drawInfoIndex;
|
||||||
TextureRectangle rec = atlas.GetTexRec( texId, out drawInfoIndex );
|
TextureRectangle rec = atlas.GetTexRec( texId, count, out drawInfoIndex );
|
||||||
rec.U2 = count;
|
|
||||||
FastColour col = GetColour( X, Y + 1, Z, ref map.Sunlight, ref map.Shadowlight );
|
FastColour col = GetColour( X, Y + 1, Z, ref map.Sunlight, ref map.Shadowlight );
|
||||||
if( blockHeight == -1 ) {
|
if( blockHeight == -1 ) {
|
||||||
blockHeight = BlockInfo.BlockHeight( tile );
|
blockHeight = BlockInfo.BlockHeight( tile );
|
||||||
|
@ -26,7 +26,7 @@ namespace ClassicalSharp.Model {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
graphics.Bind2DTexture( window.TerrainAtlasTexId );
|
graphics.Bind2DTexture( window.TerrainAtlas.TexId );
|
||||||
blockHeight = window.BlockInfo.BlockHeight( block );
|
blockHeight = window.BlockInfo.BlockHeight( block );
|
||||||
atlas = window.TerrainAtlas;
|
atlas = window.TerrainAtlas;
|
||||||
BlockInfo = window.BlockInfo;
|
BlockInfo = window.BlockInfo;
|
||||||
@ -46,7 +46,7 @@ namespace ClassicalSharp.Model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
float blockHeight;
|
float blockHeight;
|
||||||
TextureAtlas2D atlas;
|
TerrainAtlas2D atlas;
|
||||||
BlockInfo BlockInfo;
|
BlockInfo BlockInfo;
|
||||||
|
|
||||||
public override void Dispose() {
|
public override void Dispose() {
|
||||||
@ -69,7 +69,7 @@ namespace ClassicalSharp.Model {
|
|||||||
int texId = BlockInfo.GetOptimTextureLoc( block, side );
|
int texId = BlockInfo.GetOptimTextureLoc( block, side );
|
||||||
TextureRectangle rec = atlas.GetTexRec( texId );
|
TextureRectangle rec = atlas.GetTexRec( texId );
|
||||||
if( blockHeight != 1 ) {
|
if( blockHeight != 1 ) {
|
||||||
rec.V2 = rec.V1 + blockHeight * atlas.invVerElementSize;
|
rec.V2 = rec.V1 + blockHeight * TerrainAtlas2D.invElementSize;
|
||||||
}
|
}
|
||||||
if( swapU ) rec.SwapU();
|
if( swapU ) rec.SwapU();
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ namespace ClassicalSharp.Model {
|
|||||||
int texId = BlockInfo.GetOptimTextureLoc( block, side );
|
int texId = BlockInfo.GetOptimTextureLoc( block, side );
|
||||||
TextureRectangle rec = atlas.GetTexRec( texId );
|
TextureRectangle rec = atlas.GetTexRec( texId );
|
||||||
if( blockHeight != 1 ) {
|
if( blockHeight != 1 ) {
|
||||||
rec.V2 = rec.V1 + blockHeight * atlas.invVerElementSize;
|
rec.V2 = rec.V1 + blockHeight * TerrainAtlas2D.invElementSize;
|
||||||
}
|
}
|
||||||
if( swapU ) rec.SwapU();
|
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;
|
internal int elementsPerBitmap;
|
||||||
public float invElementSize;
|
public float invElementSize;
|
||||||
|
|
||||||
public TextureRectangle GetTexRec( int texId, out int index ) {
|
public TextureRectangle GetTexRec( int texId, int uCount, out int index ) {
|
||||||
index = texId / usedElementsPerAtlas1D;
|
index = texId / usedElementsPerAtlas1D;
|
||||||
int y = 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 ) {
|
public int Get1DIndex( int texId ) {
|
||||||
@ -24,34 +24,35 @@ namespace ClassicalSharp {
|
|||||||
return texId % usedElementsPerAtlas1D;
|
return texId % usedElementsPerAtlas1D;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int[] CreateFrom2DAtlas( IGraphicsApi graphics, TextureAtlas2D atlas2D, int maxVerSize ) {
|
public int[] CreateFrom2DAtlas( IGraphicsApi graphics, TerrainAtlas2D atlas2D, int maxVerSize ) {
|
||||||
int verElements = maxVerSize / atlas2D.verElementSize;
|
int verElements = maxVerSize / atlas2D.elementSize;
|
||||||
int totalElements = atlas2D.UsedRowsCount * atlas2D.ElementsPerRow;
|
int totalElements = atlas2D.UsedRowsCount * TerrainAtlas2D.ElementsPerRow;
|
||||||
|
int elemSize = atlas2D.elementSize;
|
||||||
|
|
||||||
int atlasesCount = totalElements / verElements + ( totalElements % verElements != 0 ? 1 : 0 );
|
int atlasesCount = totalElements / verElements + ( totalElements % verElements != 0 ? 1 : 0 );
|
||||||
usedElementsPerAtlas1D = Math.Min( verElements, totalElements ); // in case verElements > totalElements
|
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 index = 0;
|
||||||
int x = 0, y = 0;
|
|
||||||
int[] texIds = new int[atlasesCount];
|
int[] texIds = new int[atlasesCount];
|
||||||
Utils.LogDebug( "Loaded new atlas: {0} bmps, {1} per bmp", atlasesCount, usedElementsPerAtlas1D );
|
Utils.LogDebug( "Loaded new atlas: {0} bmps, {1} per bmp", atlasesCount, usedElementsPerAtlas1D );
|
||||||
|
|
||||||
using( FastBitmap atlas = new FastBitmap( atlas2D.AtlasBitmap, true ) ) {
|
using( FastBitmap atlas = new FastBitmap( atlas2D.AtlasBitmap, true ) ) {
|
||||||
for( int i = 0; i < texIds.Length; i++ ) {
|
for( int i = 0; i < texIds.Length; i++ ) {
|
||||||
Bitmap atlas1d = new Bitmap( atlas2D.horElementSize, atlas1DHeight );
|
Bitmap atlas1d = new Bitmap( atlas2D.elementSize, atlas1DHeight );
|
||||||
using( FastBitmap dest = new FastBitmap( atlas1d, true ) ) {
|
using( FastBitmap dst = new FastBitmap( atlas1d, true ) ) {
|
||||||
for( int j = 0; j < usedElementsPerAtlas1D; j++ ) {
|
for( int y_1D = 0; y_1D < usedElementsPerAtlas1D; y_1D++ ) {
|
||||||
atlas2D.GetCoords( index, ref x, ref y );
|
int x = index & 0x0F;
|
||||||
atlas2D.CopyPortion( x, y, 0, j * atlas2D.verElementSize, atlas, dest );
|
int y = index >> 4;
|
||||||
|
Utils.MovePortion( x * elemSize, y * elemSize, 0, y_1D * elemSize, atlas, dst, elemSize );
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
texIds[i] = graphics.LoadTexture( dest );
|
texIds[i] = graphics.LoadTexture( dst );
|
||||||
}
|
}
|
||||||
atlas1d.Dispose();
|
atlas1d.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elementsPerBitmap = atlas1DHeight / atlas2D.verElementSize;
|
elementsPerBitmap = atlas1DHeight / atlas2D.elementSize;
|
||||||
invElementSize = 1f / elementsPerBitmap;
|
invElementSize = 1f / elementsPerBitmap;
|
||||||
return texIds;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
121
Utils/Utils.cs
121
Utils/Utils.cs
@ -1,8 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using ClassicalSharp.GraphicsAPI;
|
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
|
|
||||||
namespace ClassicalSharp {
|
namespace ClassicalSharp {
|
||||||
@ -230,118 +228,15 @@ namespace ClassicalSharp {
|
|||||||
throw new NotSupportedException( "unsupported skin: " + bmp.Width + ", " + bmp.Height );
|
throw new NotSupportedException( "unsupported skin: " + bmp.Width + ", " + bmp.Height );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public struct Vector3I {
|
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++ ) {
|
||||||
public static Vector3I Zero = new Vector3I( 0, 0, 0 );
|
int* srcRow = src.GetRowPtr( srcY + y );
|
||||||
public static Vector3I UnitX = new Vector3I( 1, 0, 0 );
|
int* dstRow = dst.GetRowPtr( dstY + y );
|
||||||
public static Vector3I UnitY = new Vector3I( 0, 1, 0 );
|
for( int x = 0; x < size; x++ ) {
|
||||||
public static Vector3I UnitZ = new Vector3I( 0, 0, 1 );
|
dstRow[dstX + x] = srcRow[srcX + x];
|
||||||
|
}
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
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…
x
Reference in New Issue
Block a user