Refactor block models - they rotate and use shading, also orient sprite block models correctly. Add slight bobbing up/down of in-game entities.

This commit is contained in:
UnknownShadow200 2015-11-24 09:17:16 +11:00
parent 25ac8e28b5
commit 30c4384d66
13 changed files with 176 additions and 66 deletions

View File

@ -35,6 +35,7 @@
<DefineConstants>DEBUG;TRACE;</DefineConstants>
<StartAction>Project</StartAction>
<BaseIntermediateOutputPath>obj\</BaseIntermediateOutputPath>
<StartArguments>wwwf df 127.0.0.1 25564</StartArguments>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<OutputPath>..\output\release\</OutputPath>

View File

@ -10,6 +10,7 @@ namespace ClassicalSharp {
}
public float leftLegXRot, leftArmXRot, leftArmZRot;
public float rightLegXRot, rightArmXRot, rightArmZRot;
public float bobYOffset;
protected float walkTimeO, walkTimeN, swingO, swingN;
/// <summary> Calculates the next animation state based on old and new position. </summary>
@ -49,6 +50,8 @@ namespace ClassicalSharp {
leftLegXRot = -rightLegXRot;
rightArmZRot = idleZRot;
leftArmZRot = -idleZRot;
bobYOffset = -(float)(Math.Abs( Math.Cos( walkTime ) ) * swing * (2/16f));
}
}
}

View File

@ -8,9 +8,17 @@ namespace ClassicalSharp.Model {
public class BlockModel : IModel {
byte block = (byte)Block.Air;
float blockHeight;
TerrainAtlas1D atlas;
const float adjust = 0.1f, extent = 0.5f;
public BlockModel( Game game ) : base( game ) {
}
public override bool Bobbing {
get { return false; }
}
public override float NameYOffset {
get { return blockHeight + 0.075f; }
}
@ -20,15 +28,15 @@ namespace ClassicalSharp.Model {
return block == 0 ? 1 : game.BlockInfo.Height[block];
}
const float adjust = 0.1f;
public override Vector3 CollisionSize {
get { return new Vector3( 1 - adjust, blockHeight - adjust, 1 - adjust ); }
}
public override BoundingBox PickingBounds {
get { return new BoundingBox( -scale, 0f, -scale, scale, blockHeight, scale ); }
get { return new BoundingBox( -extent, 0f, -extent, extent, blockHeight, extent ); }
}
int lastTexId = -1;
protected override void DrawPlayerModel( Player p ) {
// TODO: using 'is' is ugly, but means we can avoid creating
// a string every single time held block changes.
@ -44,81 +52,139 @@ namespace ClassicalSharp.Model {
blockHeight = 1;
return;
}
graphics.BindTexture( game.TerrainAtlas.TexId );
lastTexId = -1;
blockHeight = game.BlockInfo.Height[block];
atlas = game.TerrainAtlas;
BlockInfo = game.BlockInfo;
atlas = game.TerrainAtlas1D;
if( BlockInfo.IsSprite[block] ) {
float offset = TerrainAtlas2D.invElementSize / 2;
XQuad( 0f, TileSide.Right, -scale, 0, 0, -offset, false );
ZQuad( 0f, TileSide.Back, 0, scale, offset, 0, false );
if( game.BlockInfo.IsSprite[block] ) {
SpriteXQuad( TileSide.Right, true );
SpriteZQuad( TileSide.Back, false );
XQuad( 0f, TileSide.Right, 0, scale, offset, 0, false );
ZQuad( 0f, TileSide.Back, -scale, 0, 0, -offset, false );
SpriteXQuad( TileSide.Right, false );
SpriteZQuad( TileSide.Back, true );
} else {
YQuad( 0f, TileSide.Bottom );
XQuad( scale, TileSide.Left, -scale, scale, 0, 0, true );
ZQuad( -scale, TileSide.Front, -scale, scale, 0, 0, true );
YQuad( 0f, TileSide.Bottom, FastColour.ShadeYBottom );
XQuad( extent, TileSide.Left, -extent, extent, true, FastColour.ShadeX );
ZQuad( -extent, TileSide.Front, -extent, extent, true, FastColour.ShadeZ );
ZQuad( scale, TileSide.Back, -scale, scale, 0, 0, true );
YQuad( blockHeight, TileSide.Top );
XQuad( -scale, TileSide.Right, -scale, scale, 0, 0, true );
ZQuad( extent, TileSide.Back, -extent, extent, true, FastColour.ShadeZ );
YQuad( blockHeight, TileSide.Top, 1.0f );
XQuad( -extent, TileSide.Right, -extent, extent, true, FastColour.ShadeX );
}
if( index > 0 ) {
graphics.BindTexture( lastTexId );
TransformVertices();
graphics.UpdateDynamicIndexedVb( DrawMode.Triangles, cache.vb, cache.vertices, index, index * 6 / 4 );
}
float blockHeight;
TerrainAtlas2D atlas;
BlockInfo BlockInfo;
float scale = 0.5f;
public override void Dispose() {
}
void YQuad( float y, int side ) {
int texId = BlockInfo.GetTextureLoc( block, side );
TextureRec rec = atlas.GetAdjTexRec( texId );
void YQuad( float y, int side, float shade ) {
int texId = game.BlockInfo.GetTextureLoc( block, side ), texIndex = 0;
TextureRec rec = atlas.GetTexRec( texId, 1, out texIndex );
FlushIfNotSame( texIndex );
FastColour col = FastColour.Scale( this.col, shade );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X - scale, pos.Y + y, pos.Z - scale, rec.U1, rec.V1, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + scale, pos.Y + y, pos.Z - scale, rec.U2, rec.V1, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + scale, pos.Y + y, pos.Z + scale, rec.U2, rec.V2, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X - scale, pos.Y + y, pos.Z + scale, rec.U1, rec.V2, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( -extent, y, -extent, rec.U1, rec.V1, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( extent, y, -extent, rec.U2, rec.V1, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( extent, y, extent, rec.U2, rec.V2, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( -extent, y, extent, rec.U1, rec.V2, col );
}
void ZQuad( float z, int side, float x1, float x2,
float u1Offset, float u2Offset, bool swapU ) {
int texId = BlockInfo.GetTextureLoc( block, side );
TextureRec rec = atlas.GetAdjTexRec( texId );
void ZQuad( float z, int side, float x1, float x2, bool swapU, float shade ) {
int texId = game.BlockInfo.GetTextureLoc( block, side ), texIndex = 0;
TextureRec rec = atlas.GetTexRec( texId, 1, out texIndex );
FlushIfNotSame( texIndex );
FastColour col = FastColour.Scale( this.col, shade );
if( blockHeight != 1 )
rec.V2 = rec.V1 + blockHeight * TerrainAtlas2D.invElementSize * (15.99f/16f);
// need to break into two quads when drawing a sprite model in hand.
rec.V2 = rec.V1 + blockHeight * atlas.invElementSize * (15.99f/16f);
if( swapU ) rec.SwapU();
rec.U1 += u1Offset;
rec.U2 += u2Offset;
cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + x1, pos.Y + 0f, pos.Z + z, rec.U1, rec.V2, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + x1, pos.Y + blockHeight, pos.Z + z, rec.U1, rec.V1, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + x2, pos.Y + blockHeight, pos.Z + z, rec.U2, rec.V1, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + x2, pos.Y + 0f, pos.Z + z, rec.U2, rec.V2, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( x1, 0f, z, rec.U1, rec.V2, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( x1, blockHeight, z, rec.U1, rec.V1, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( x2, blockHeight, z, rec.U2, rec.V1, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( x2, 0f, z, rec.U2, rec.V2, col );
}
void XQuad( float x, int side, float z1, float z2,
float u1Offset, float u2Offset, bool swapU ) {
int texId = BlockInfo.GetTextureLoc( block, side );
TextureRec rec = atlas.GetAdjTexRec( texId );
void XQuad( float x, int side, float z1, float z2, bool swapU, float shade ) {
int texId = game.BlockInfo.GetTextureLoc( block, side ), texIndex = 0;
TextureRec rec = atlas.GetTexRec( texId, 1, out texIndex );
FlushIfNotSame( texIndex );
FastColour col = FastColour.Scale( this.col, shade );
if( blockHeight != 1 )
rec.V2 = rec.V1 + blockHeight * TerrainAtlas2D.invElementSize * (15.99f/16f);
rec.V2 = rec.V1 + blockHeight * atlas.invElementSize * (15.99f/16f);
if( swapU ) rec.SwapU();
rec.U1 += u1Offset;
rec.U2 += u2Offset;
cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + x, pos.Y + 0f, pos.Z + z1, rec.U1, rec.V2, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + x, pos.Y + blockHeight, pos.Z + z1, rec.U1, rec.V1, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + x, pos.Y + blockHeight, pos.Z + z2, rec.U2, rec.V1, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( pos.X + x, pos.Y + 0f, pos.Z + z2, rec.U2, rec.V2, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( x, 0f, z1, rec.U1, rec.V2, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( x, blockHeight, z1, rec.U1, rec.V1, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( x, blockHeight, z2, rec.U2, rec.V1, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( x, 0f, z2, rec.U2, rec.V2, col );
}
void SpriteZQuad( int side, bool firstPart ) {
int texId = game.BlockInfo.GetTextureLoc( block, side ), texIndex = 0;
TextureRec rec = atlas.GetTexRec( texId, 1, out texIndex );
FlushIfNotSame( texIndex );
if( blockHeight != 1 )
rec.V2 = rec.V1 + blockHeight * atlas.invElementSize * (15.99f/16f);
float p1, p2;
if( firstPart ) { // Need to break into two quads for when drawing a sprite model in hand.
rec.U1 = 0.5f; p1 = -5.5f/16; p2 = 0.0f/16;
} else {
rec.U2 = 0.5f; p1 = 0.0f/16; p2 = 5.5f/16;
}
cache.vertices[index++] = new VertexPos3fTex2fCol4b( p1, 0f, p1, rec.U2, rec.V2, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( p1, blockHeight, p1, rec.U2, rec.V1, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( p2, blockHeight, p2, rec.U1, rec.V1, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( p2, 0f, p2, rec.U1, rec.V2, col );
}
void SpriteXQuad( int side, bool firstPart ) { // dis is broken
int texId = game.BlockInfo.GetTextureLoc( block, side ), texIndex = 0;
TextureRec rec = atlas.GetTexRec( texId, 1, out texIndex );
FlushIfNotSame( texIndex );
if( blockHeight != 1 )
rec.V2 = rec.V1 + blockHeight * atlas.invElementSize * (15.99f/16f);
float x1, x2, z1, z2;
if( firstPart ) {
rec.U1 = 0; rec.U2 = 0.5f; x1 = -5.5f/16;
x2 = 0.0f/16; z1 = 5.5f/16; z2 = 0.0f/16;
} else {
rec.U1 = 0.5f; rec.U2 = 1f; x1 = 0.0f/16;
x2 = 5.5f/16; z1 = 0.0f/16; z2 = -5.5f/16;
}
cache.vertices[index++] = new VertexPos3fTex2fCol4b( x1, 0f, z1, rec.U1, rec.V2, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( x1, blockHeight, z1, rec.U1, rec.V1, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( x2, blockHeight, z2, rec.U2, rec.V1, col );
cache.vertices[index++] = new VertexPos3fTex2fCol4b( x2, 0f, z2, rec.U2, rec.V2, col );
}
void FlushIfNotSame( int texIndex ) {
int texId = game.TerrainAtlas1D.TexIds[texIndex];
if( texId == lastTexId ) return;
if( lastTexId != -1 ) {
graphics.BindTexture( lastTexId );
TransformVertices();
graphics.UpdateDynamicIndexedVb( DrawMode.Triangles, cache.vb,
cache.vertices, index, index * 6 / 4 );
}
lastTexId = texId;
index = 0;
}
void TransformVertices() {
for( int i = 0; i < index; i++ ) {
VertexPos3fTex2fCol4b vertex = cache.vertices[i];
Vector3 newPos = Utils.RotateY( vertex.X, vertex.Y, vertex.Z, cosA, sinA ) + pos;
vertex.X = newPos.X; vertex.Y = newPos.Y; vertex.Z = newPos.Z;
cache.vertices[i] = vertex;
}
}
}
}

View File

@ -32,6 +32,10 @@ namespace ClassicalSharp.Model {
return new ModelPart( index - 2 * 4, 2 * 4 );
}
public override bool Bobbing {
get { return true; }
}
public override float NameYOffset {
get { return 1.0125f; }
}

View File

@ -23,6 +23,10 @@ namespace ClassicalSharp.Model {
.SetTexOrigin( 0, 16 ) );
}
public override bool Bobbing {
get { return false; }
}
public override float NameYOffset {
get { return 1.7f; }
}

View File

@ -22,6 +22,11 @@ namespace ClassicalSharp.Model {
cache = game.ModelCache;
}
/// <summary> Whether the entity should be slightly bobbed up and down when rendering. </summary>
/// <remarks> e.g. for players when their legs are at the peak of their swing,
/// the whole model will be moved slightly down. </remarks>
public abstract bool Bobbing { get; }
/// <summary> Vertical offset from the model's feet/base that the name texture should be drawn at. </summary>
public abstract float NameYOffset { get; }
@ -43,6 +48,8 @@ namespace ClassicalSharp.Model {
public void RenderModel( Player p ) {
index = 0;
pos = p.Position;
if( Bobbing )
pos.Y += p.bobYOffset;
cosA = (float)Math.Cos( p.YawRadians );
sinA = (float)Math.Sin( p.YawRadians );
Map map = game.Map;
@ -225,11 +232,11 @@ namespace ClassicalSharp.Model {
if( count != boxVertices )
return FastColour.Scale( col, 0.7f );
if( i >= 4 && i < 8 )
return FastColour.Scale( col, 0.5f ); // y bottom
return FastColour.Scale( col, FastColour.ShadeYBottom );
if( i >= 8 && i < 16 )
return FastColour.Scale( col, 0.8f ); // z sides
return FastColour.Scale( col, FastColour.ShadeZ );
if( i >= 16 && i < 24 )
return FastColour.Scale( col, 0.6f ); // x sides
return FastColour.Scale( col, FastColour.ShadeX );
return col;
}

View File

@ -22,6 +22,10 @@ namespace ClassicalSharp.Model {
.SetTexOrigin( 0, 16 ) );
}
public override bool Bobbing {
get { return true; }
}
public override float NameYOffset {
get { return 1.075f; }
}

View File

@ -40,6 +40,10 @@ namespace ClassicalSharp.Model {
SetSlim.Hat = Set.Hat;
}
public override bool Bobbing {
get { return true; }
}
public override float NameYOffset {
get { return 2.1375f; }
}

View File

@ -44,6 +44,10 @@ namespace ClassicalSharp.Model {
FurRightLegBack = BuildBox( legDesc.SetModelBounds( 0.5f, 5.5f, 4.5f, 5.5f, 12.5f, 9.5f ) );
}
public override bool Bobbing {
get { return true; }
}
public override float NameYOffset {
get { return Fur ? 1.48125f: 1.075f; }
}

View File

@ -22,6 +22,10 @@ namespace ClassicalSharp.Model {
.SetTexOrigin( 40, 16 ) );
}
public override bool Bobbing {
get { return true; }
}
public override float NameYOffset {
get { return 2.075f; }
}

View File

@ -20,6 +20,10 @@ namespace ClassicalSharp.Model {
.SetTexOrigin( 18, 0 ) );
}
public override bool Bobbing {
get { return false; }
}
public override float NameYOffset {
get { return 1.0125f; }
}

View File

@ -22,6 +22,10 @@ namespace ClassicalSharp.Model {
.SetTexOrigin( 40, 16 ) );
}
public override bool Bobbing {
get { return true; }
}
public override float NameYOffset {
get { return 2.075f; }
}

View File

@ -76,11 +76,12 @@ namespace ClassicalSharp {
191 * ((hex >> 0) & 1) + 64 * (hex >> 3) );
}
public const float ShadeX = 0.6f, ShadeZ = 0.8f, ShadeYBottom = 0.5f;
public static void GetShaded( FastColour normal, ref FastColour xSide,
ref FastColour zSide, ref FastColour yBottom ) {
xSide = FastColour.Scale( normal, 0.6f );
zSide = FastColour.Scale( normal, 0.8f );
yBottom = FastColour.Scale( normal, 0.5f );
xSide = FastColour.Scale( normal, ShadeX );
zSide = FastColour.Scale( normal, ShadeZ );
yBottom = FastColour.Scale( normal, ShadeYBottom );
}
public Color ToColor() {