mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-18 03:55:19 -04:00
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:
parent
25ac8e28b5
commit
30c4384d66
@ -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>
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
@ -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.
|
||||
@ -38,87 +46,145 @@ namespace ClassicalSharp.Model {
|
||||
col = FastColour.Scale( baseCol, 0.8f );
|
||||
block = ((FakePlayer)p).Block;
|
||||
} else {
|
||||
block = Byte.Parse( p.ModelName );
|
||||
block = Byte.Parse( p.ModelName );
|
||||
}
|
||||
if( block == 0 ) {
|
||||
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 );
|
||||
}
|
||||
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 );
|
||||
|
||||
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 );
|
||||
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( -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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; }
|
||||
}
|
||||
|
@ -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; }
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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; }
|
||||
}
|
||||
|
@ -39,6 +39,10 @@ namespace ClassicalSharp.Model {
|
||||
.SetTexOrigin( 40, 16 ) );
|
||||
SetSlim.Hat = Set.Hat;
|
||||
}
|
||||
|
||||
public override bool Bobbing {
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public override float NameYOffset {
|
||||
get { return 2.1375f; }
|
||||
|
@ -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; }
|
||||
}
|
||||
|
@ -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; }
|
||||
}
|
||||
|
@ -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; }
|
||||
}
|
||||
|
@ -21,6 +21,10 @@ namespace ClassicalSharp.Model {
|
||||
RightArm = BuildBox( MakeBoxBounds( 4, 12, -2, 8, 24, 2 )
|
||||
.SetTexOrigin( 40, 16 ) );
|
||||
}
|
||||
|
||||
public override bool Bobbing {
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public override float NameYOffset {
|
||||
get { return 2.075f; }
|
||||
|
@ -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() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user