Client now rescales non-power of two skins, fixes crashing and closes #177. (Thanks MarsBarsFood)

This commit is contained in:
UnknownShadow200 2016-04-27 18:17:03 +10:00
parent 2bb67cd2f1
commit 544f80a2f5
4 changed files with 42 additions and 13 deletions

View File

@ -67,6 +67,12 @@ namespace ClassicalSharp {
}
}
public static void CopyRow( int srcY, int dstY, FastBitmap src, FastBitmap dst, int width ) {
int* srcRow = src.GetRowPtr( srcY ), dstRow = dst.GetRowPtr( dstY);
for( int x = 0; x < width; x++ )
dstRow[x] = srcRow[x];
}
public void Dispose() { UnlockBits(); }
#if !ANDROID

View File

@ -17,6 +17,7 @@ namespace ClassicalSharp.Entities {
public SkinType SkinType;
internal AnimatedComponent anim;
internal ShadowComponent shadow;
internal float uScale = 1, vScale = 1;
public Player( Game game ) : base( game ) {
this.game = game;
@ -81,6 +82,8 @@ namespace ClassicalSharp.Entities {
game.Graphics.DeleteTexture( ref TextureId );
if( !FastBitmap.CheckFormat( bmp.PixelFormat ) )
game.Drawer2D.ConvertTo32Bpp( ref bmp );
uScale = 1; vScale = 1;
EnsurePow2( ref bmp );
try {
SkinType = Utils.GetSkinType( bmp );
@ -91,7 +94,7 @@ namespace ClassicalSharp.Entities {
// Custom mob textures.
if( Utils.IsUrlPrefix( SkinName, 0 ) && item.TimeAdded > lastModelChange )
MobTextureId = TextureId;
MobTextureId = TextureId;
} catch( NotSupportedException ) {
ResetSkin( bmp );
}
@ -136,5 +139,24 @@ namespace ClassicalSharp.Entities {
}
}
}
void EnsurePow2( ref Bitmap bmp ) {
int width = Utils.NextPowerOf2( bmp.Width );
int height = Utils.NextPowerOf2( bmp.Height );
if( width == bmp.Width && height == bmp.Height ) return;
Bitmap scaled = Platform.CreateBmp( width, height );
using( FastBitmap src = new FastBitmap( bmp, true, true ) )
using( FastBitmap dst = new FastBitmap( scaled, true, false ) )
{
for( int y = 0; y < src.Height; y++ )
FastBitmap.CopyRow( y, y, src, dst, src.Width );
}
uScale = (float)bmp.Width / width;
vScale = (float)bmp.Height / height;
bmp.Dispose();
bmp = scaled;
}
}
}

View File

@ -90,9 +90,12 @@ namespace ClassicalSharp.Model {
graphics.AlphaTest = false;
SkinType skinType = p.SkinType;
_64x64 = skinType != SkinType.Type64x32;
bool _64x64 = skinType != SkinType.Type64x32;
uScale = p.uScale / 64f;
vScale = p.vScale / (_64x64 ? 64 : 32);
ModelSet model = skinType == SkinType.Type64x64Slim ? SetSlim :
(skinType == SkinType.Type64x64 ? Set64 : Set);
DrawHeadRotate( -p.PitchRadians, 0, 0, model.Head );
DrawPart( model.Torso );

View File

@ -47,15 +47,16 @@ namespace ClassicalSharp.Model {
protected Vector3 pos;
protected float cosYaw, sinYaw, cosHead, sinHead;
protected float uScale, vScale;
/// <summary> Renders the model based on the given entity's position and orientation. </summary>
public void Render( Player p ) {
index = 0;
pos = p.Position;
if( Bobbing )
pos.Y += p.anim.bobYOffset;
if( Bobbing ) pos.Y += p.anim.bobYOffset;
World map = game.World;
col = game.World.IsLit( Vector3I.Floor( p.EyePosition ) ) ? map.Sunlight : map.Shadowlight;
uScale = 1 / 64f; vScale = 1 / 32f;
cols[0] = col;
cols[1] = FastColour.Scale( col, FastColour.ShadeYBottom );
@ -96,9 +97,7 @@ namespace ClassicalSharp.Model {
return ModelBuilder.BuildRotatedBox( this, desc );
}
protected bool _64x64 = false;
protected void DrawPart( ModelPart part ) {
float vScale = _64x64 ? 64f : 32f;
for( int i = 0; i < part.Count; i++ ) {
ModelVertex v = vertices[part.Offset + i];
float t = cosYaw * v.X - sinYaw * v.Z; v.Z = sinYaw * v.X + cosYaw * v.Z; v.X = t; // Inlined RotY
@ -110,10 +109,10 @@ namespace ClassicalSharp.Model {
vertex.X = v.X; vertex.Y = v.Y; vertex.Z = v.Z;
vertex.R = col.R; vertex.G = col.G; vertex.B = col.B; vertex.A = 255;
vertex.U = v.U / 64f; vertex.V = v.V / vScale;
vertex.U = v.U * uScale; vertex.V = v.V * vScale;
int quadI = i % 4;
if( quadI == 0 || quadI == 3 ) vertex.V -= 0.01f / vScale;
if( quadI == 2 || quadI == 3 ) vertex.U -= 0.01f / 64f;
if( quadI == 0 || quadI == 3 ) vertex.V -= 0.01f * vScale;
if( quadI == 2 || quadI == 3 ) vertex.U -= 0.01f * uScale;
cache.vertices[index++] = vertex;
}
}
@ -131,7 +130,6 @@ namespace ClassicalSharp.Model {
float cosX = (float)Math.Cos( -angleX ), sinX = (float)Math.Sin( -angleX );
float cosY = (float)Math.Cos( -angleY ), sinY = (float)Math.Sin( -angleY );
float cosZ = (float)Math.Cos( -angleZ ), sinZ = (float)Math.Sin( -angleZ );
float vScale = _64x64 ? 64f : 32f;
for( int i = 0; i < part.Count; i++ ) {
ModelVertex v = vertices[part.Offset + i];
@ -167,10 +165,10 @@ namespace ClassicalSharp.Model {
vertex.X = v.X; vertex.Y = v.Y; vertex.Z = v.Z;
vertex.R = col.R; vertex.G = col.G; vertex.B = col.B; vertex.A = 255;
vertex.U = v.U / 64f; vertex.V = v.V / vScale;
vertex.U = v.U * uScale; vertex.V = v.V * vScale;
int quadI = i % 4;
if( quadI == 0 || quadI == 3 ) vertex.V -= 0.01f / vScale;
if( quadI == 2 || quadI == 3 ) vertex.U -= 0.01f / 64f;
if( quadI == 0 || quadI == 3 ) vertex.V -= 0.01f * vScale;
if( quadI == 2 || quadI == 3 ) vertex.U -= 0.01f * vScale;
cache.vertices[index++] = vertex;
}
}