mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-01-24 01:52:24 -05:00
219 lines
No EOL
8.9 KiB
C#
219 lines
No EOL
8.9 KiB
C#
// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT
|
|
using System;
|
|
using ClassicalSharp.GraphicsAPI;
|
|
using ClassicalSharp.Model;
|
|
using ClassicalSharp.TexturePack;
|
|
using OpenTK;
|
|
|
|
namespace ClassicalSharp {
|
|
|
|
public sealed class IsometricBlockDrawer {
|
|
|
|
Game game;
|
|
TerrainAtlas1D atlas;
|
|
int index;
|
|
float scale;
|
|
Vector3 minBB, maxBB;
|
|
const float invElemSize = TerrainAtlas2D.invElementSize;
|
|
bool fullBright;
|
|
VertexP3fT2fC4b[] vertices;
|
|
int vb;
|
|
|
|
public void BeginBatch( Game game, VertexP3fT2fC4b[] vertices, int vb ) {
|
|
this.game = game;
|
|
lastIndex = -1;
|
|
index = 0;
|
|
this.vertices = vertices;
|
|
this.vb = vb;
|
|
}
|
|
|
|
static FastColour colNormal, colXSide, colZSide, colYBottom;
|
|
static float cosX, sinX, cosY, sinY;
|
|
static IsometricBlockDrawer() {
|
|
colNormal = FastColour.White;
|
|
FastColour.GetShaded( colNormal, ref colXSide, ref colZSide, ref colYBottom );
|
|
|
|
cosX = (float)Math.Cos( 26.565f * Utils.Deg2Rad );
|
|
sinX = (float)Math.Sin( 26.565f * Utils.Deg2Rad );
|
|
cosY = (float)Math.Cos( -45f * Utils.Deg2Rad );
|
|
sinY = (float)Math.Sin( -45f * Utils.Deg2Rad );
|
|
}
|
|
|
|
public void DrawBatch( byte block, float size, float x, float y ) {
|
|
BlockInfo info = game.BlockInfo;
|
|
atlas = game.TerrainAtlas1D;
|
|
minBB = info.MinBB[block];
|
|
maxBB = info.MaxBB[block];
|
|
fullBright = info.FullBright[block];
|
|
if( info.IsSprite[block] ) { minBB = Vector3.Zero; maxBB = Vector3.One; }
|
|
if( info.IsAir[block] ) return;
|
|
|
|
// isometric coords size: cosY * -scale - sinY * scale
|
|
// we need to divide by (2 * cosY), as the calling function expects size to be in pixels.
|
|
scale = size / (2 * cosY);
|
|
// screen to isometric coords (cos(-x) = cos(x), sin(-x) = -sin(x))
|
|
pos.X = x; pos.Y = y; pos.Z = 0;
|
|
Utils.RotateX( ref pos.Y, ref pos.Z, cosX, -sinX );
|
|
Utils.RotateY( ref pos.X, ref pos.Z, cosY, -sinY );
|
|
|
|
if( info.IsSprite[block] ) {
|
|
SpriteXQuad( block, Side.Right, false );
|
|
SpriteZQuad( block, Side.Back, false );
|
|
|
|
SpriteZQuad( block, Side.Back, true );
|
|
SpriteXQuad( block, Side.Right, true );
|
|
} else {
|
|
XQuad( block, maxBB.X, Side.Left );
|
|
ZQuad( block, minBB.Z, Side.Back );
|
|
YQuad( block, maxBB.Y, Side.Top );
|
|
}
|
|
}
|
|
|
|
public void EndBatch() {
|
|
if( index == 0 ) return;
|
|
if( texIndex != lastIndex )
|
|
game.Graphics.BindTexture( atlas.TexIds[texIndex] );
|
|
game.Graphics.UpdateDynamicIndexedVb( DrawMode.Triangles,
|
|
vb, vertices, index, index * 6 / 4 );
|
|
index = 0;
|
|
lastIndex = -1;
|
|
}
|
|
|
|
static Vector3 pos = Vector3.Zero;
|
|
void YQuad( byte block, float y, int side ) {
|
|
int texLoc = game.BlockInfo.GetTextureLoc( block, side );
|
|
texIndex = texLoc / atlas.elementsPerAtlas1D;
|
|
if( lastIndex != texIndex ) Flush();
|
|
|
|
VertexP3fT2fC4b v = default(VertexP3fT2fC4b);
|
|
FastColour col = colNormal;
|
|
v.A = col.A; v.R = col.R; v.G = col.G; v.B = col.B;
|
|
|
|
TextureRec rec;
|
|
float vOrigin = (texLoc % atlas.elementsPerAtlas1D) * atlas.invElementSize;
|
|
rec.U1 = minBB.X; rec.U2 = maxBB.X;
|
|
rec.V1 = vOrigin + minBB.Z * atlas.invElementSize;
|
|
rec.V2 = vOrigin + maxBB.Z * atlas.invElementSize * (15.99f/16f);
|
|
|
|
y = scale * (1 - y * 2);
|
|
float minX = scale * (1 - minBB.X * 2), maxX = scale * (1 - maxBB.X * 2);
|
|
float minZ = scale * (1 - minBB.Z * 2), maxZ = scale * (1 - maxBB.Z * 2);
|
|
v.X = minX; v.Y = y; v.Z = minZ; v.U = rec.U2; v.V = rec.V2; Transform( ref v );
|
|
v.X = maxX; v.Y = y; v.Z = minZ; v.U = rec.U1; v.V = rec.V2; Transform( ref v );
|
|
v.X = maxX; v.Y = y; v.Z = maxZ; v.U = rec.U1; v.V = rec.V1; Transform( ref v );
|
|
v.X = minX; v.Y = y; v.Z = maxZ; v.U = rec.U2; v.V = rec.V1; Transform( ref v );
|
|
}
|
|
|
|
void ZQuad( byte block, float z, int side ) {
|
|
int texLoc = game.BlockInfo.GetTextureLoc( block, side );
|
|
texIndex = texLoc / atlas.elementsPerAtlas1D;
|
|
if( lastIndex != texIndex ) Flush();
|
|
|
|
VertexP3fT2fC4b v = default(VertexP3fT2fC4b);
|
|
FastColour col = fullBright ? colNormal : colZSide;
|
|
v.A = col.A; v.R = col.R; v.G = col.G; v.B = col.B;
|
|
|
|
TextureRec rec;
|
|
float vOrigin = (texLoc % atlas.elementsPerAtlas1D) * atlas.invElementSize;
|
|
rec.U1 = minBB.X; rec.U2 = maxBB.X;
|
|
rec.V1 = vOrigin + (1 - minBB.Y) * atlas.invElementSize;
|
|
rec.V2 = vOrigin + (1 - maxBB.Y) * atlas.invElementSize * (15.99f/16f);
|
|
|
|
z = scale * (1 - z * 2);
|
|
float minX = scale * (1 - minBB.X * 2), maxX = scale * (1 - maxBB.X * 2);
|
|
float minY = scale * (1 - minBB.Y * 2), maxY = scale * (1 - maxBB.Y * 2);
|
|
v.X = minX; v.Y = maxY; v.Z = z; v.U = rec.U2; v.V = rec.V2; Transform( ref v );
|
|
v.X = minX; v.Y = minY; v.Z = z; v.U = rec.U2; v.V = rec.V1; Transform( ref v );
|
|
v.X = maxX; v.Y = minY; v.Z = z; v.U = rec.U1; v.V = rec.V1; Transform( ref v );
|
|
v.X = maxX; v.Y = maxY; v.Z = z; v.U = rec.U1; v.V = rec.V2; Transform( ref v );
|
|
}
|
|
|
|
void XQuad( byte block, float x, int side ) {
|
|
int texLoc = game.BlockInfo.GetTextureLoc( block, side );
|
|
texIndex = texLoc / atlas.elementsPerAtlas1D;
|
|
if( lastIndex != texIndex ) Flush();
|
|
|
|
VertexP3fT2fC4b v = default(VertexP3fT2fC4b);
|
|
FastColour col = fullBright ? colNormal : colXSide;
|
|
v.A = col.A; v.R = col.R; v.G = col.G; v.B = col.B;
|
|
|
|
TextureRec rec;
|
|
float vOrigin = (texLoc % atlas.elementsPerAtlas1D) * atlas.invElementSize;
|
|
rec.U1 = minBB.Z; rec.U2 = maxBB.Z;
|
|
rec.V1 = vOrigin + (1 - minBB.Y) * atlas.invElementSize;
|
|
rec.V2 = vOrigin + (1 - maxBB.Y) * atlas.invElementSize * (15.99f/16f);
|
|
|
|
x = scale * (1 - x * 2);
|
|
float minY = scale * (1 - minBB.Y * 2), maxY = scale * (1 - maxBB.Y * 2);
|
|
float minZ = scale * (1 - minBB.Z * 2), maxZ = scale * (1 - maxBB.Z * 2);
|
|
v.X = x; v.Y = maxY; v.Z = minZ; v.U = rec.U2; v.V = rec.V2; Transform( ref v );
|
|
v.X = x; v.Y = minY; v.Z = minZ; v.U = rec.U2; v.V = rec.V1; Transform( ref v );
|
|
v.X = x; v.Y = minY; v.Z = maxZ; v.U = rec.U1; v.V = rec.V1; Transform( ref v );
|
|
v.X = x; v.Y = maxY; v.Z = maxZ; v.U = rec.U1; v.V = rec.V2; Transform( ref v );
|
|
}
|
|
|
|
void SpriteZQuad( byte block, int side, bool firstPart ) {
|
|
int texLoc = game.BlockInfo.GetTextureLoc( block, side );
|
|
TextureRec rec = atlas.GetTexRec( texLoc, 1, out texIndex );
|
|
if( lastIndex != texIndex ) Flush();
|
|
|
|
VertexP3fT2fC4b v = default(VertexP3fT2fC4b);
|
|
FastColour col = colNormal;
|
|
v.A = col.A; v.R = col.R; v.G = col.G; v.B = col.B;
|
|
|
|
float x1 = firstPart ? -0.1f : 0.5f, x2 = firstPart ? 0.5f : 1.1f;
|
|
rec.U1 = firstPart ? 0.0f : 0.5f; rec.U2 = (firstPart ? 0.5f : 1.0f) * (15.99f/16f);
|
|
float minX = scale * (1 - x1 * 2), maxX = scale * (1 - x2 * 2);
|
|
float minY = scale * (1 - 0 * 2), maxY = scale * (1 - 1.1f * 2);
|
|
|
|
v.X = minX; v.Y = minY; v.Z = 0; v.U = rec.U1; v.V = rec.V2; Transform( ref v );
|
|
v.X = minX; v.Y = maxY; v.Z = 0; v.U = rec.U1; v.V = rec.V1; Transform( ref v );
|
|
v.X = maxX; v.Y = maxY; v.Z = 0; v.U = rec.U2; v.V = rec.V1; Transform( ref v );
|
|
v.X = maxX; v.Y = minY; v.Z = 0; v.U = rec.U2; v.V = rec.V2; Transform( ref v );
|
|
}
|
|
|
|
void SpriteXQuad( byte block, int side, bool firstPart ) {
|
|
int texLoc = game.BlockInfo.GetTextureLoc( block, side );
|
|
TextureRec rec = atlas.GetTexRec( texLoc, 1, out texIndex );
|
|
if( lastIndex != texIndex ) Flush();
|
|
|
|
VertexP3fT2fC4b v = default(VertexP3fT2fC4b);
|
|
FastColour col = colNormal;
|
|
v.A = col.A; v.R = col.R; v.G = col.G; v.B = col.B;
|
|
|
|
float z1 = firstPart ? -0.1f : 0.5f, z2 = firstPart ? 0.5f : 1.1f;
|
|
rec.U1 = firstPart ? 0.0f : 0.5f; rec.U2 = (firstPart ? 0.5f : 1.0f) * (15.99f/16f);
|
|
float minY = scale * (1 - 0 * 2), maxY = scale * (1 - 1.1f * 2);
|
|
float minZ = scale * (1 - z1 * 2), maxZ = scale * (1 - z2 * 2);
|
|
|
|
v.X = 0; v.Y = minY; v.Z = minZ; v.U = rec.U1; v.V = rec.V2; Transform( ref v );
|
|
v.X = 0; v.Y = maxY; v.Z = minZ; v.U = rec.U1; v.V = rec.V1; Transform( ref v );
|
|
v.X = 0; v.Y = maxY; v.Z = maxZ; v.U = rec.U2; v.V = rec.V1; Transform( ref v );
|
|
v.X = 0; v.Y = minY; v.Z = maxZ; v.U = rec.U2; v.V = rec.V2; Transform( ref v );
|
|
}
|
|
|
|
int lastIndex, texIndex;
|
|
void Flush() {
|
|
if( lastIndex != -1 ) {
|
|
game.Graphics.UpdateDynamicIndexedVb( DrawMode.Triangles,
|
|
vb, vertices, index, index * 6 / 4 );
|
|
index = 0;
|
|
}
|
|
lastIndex = texIndex;
|
|
game.Graphics.BindTexture( atlas.TexIds[texIndex] );
|
|
}
|
|
|
|
void Transform( ref VertexP3fT2fC4b v ) {
|
|
v.X += pos.X; v.Y += pos.Y; v.Z += pos.Z;
|
|
//Vector3 p = new Vector3( v.X, v.Y, v.Z ) + pos;
|
|
//p = Utils.RotateY( p - pos, time ) + pos;
|
|
//v coords = p
|
|
|
|
// See comment in IGraphicsApi.Draw2DTexture()
|
|
v.X -= 0.5f; v.Y -= 0.5f;
|
|
float t = cosY * v.X - sinY * v.Z; v.Z = sinY * v.X + cosY * v.Z; v.X = t; // Inlined RotY
|
|
t = cosX * v.Y + sinX * v.Z; v.Z = -sinX * v.Y + cosX * v.Z; v.Y = t; // Inlined RotX
|
|
vertices[index++] = v;
|
|
}
|
|
}
|
|
} |