diff --git a/ClassicalSharp/Blocks/BlockInfo.BoundingBox.cs b/ClassicalSharp/Blocks/BlockInfo.BoundsBox.cs
similarity index 82%
rename from ClassicalSharp/Blocks/BlockInfo.BoundingBox.cs
rename to ClassicalSharp/Blocks/BlockInfo.BoundsBox.cs
index e75919962..df2eea218 100644
--- a/ClassicalSharp/Blocks/BlockInfo.BoundingBox.cs
+++ b/ClassicalSharp/Blocks/BlockInfo.BoundsBox.cs
@@ -11,7 +11,7 @@ namespace ClassicalSharp {
public Vector3[] MaxBB = new Vector3[BlocksCount];
void InitBoundingBoxes() {
- for( int i = 0; i < 256; i++ ) {
+ for( int i = 0; i < BlocksCount; i++ ) {
if( IsSprite[i] ) {
MinBB[i] = new Vector3( 2.50f/16f, 0, 2.50f/16f );
MaxBB[i] = new Vector3( 13.5f/16f, 1, 13.5f/16f );
@@ -22,8 +22,20 @@ namespace ClassicalSharp {
}
}
+ internal void InitLightOffsets() {
+ for( int tile = 0; tile < BlocksCount; tile++ ) {
+ int flags = 0xFF;
+ Vector3 min = MinBB[tile], max = MaxBB[tile];
+ if( min.X != 0 ) flags &= ~(1 << TileSide.Left);
+ if( max.X != 1 ) flags &= ~(1 << TileSide.Right);
+ if( min.Z != 0 ) flags &= ~(1 << TileSide.Front);
+ if( max.Z != 1 ) flags &= ~(1 << TileSide.Back);
+ LightOffset[tile] = (byte)flags;
+ }
+ }
+
public void RecalculateSpriteBB( FastBitmap fastBmp ) {
- for( int i = 0; i < 256; i++ ) {
+ for( int i = 0; i < BlocksCount; i++ ) {
if( IsSprite[i] ) RecalculateBB( i, fastBmp );
}
}
diff --git a/ClassicalSharp/Blocks/BlockInfo.cs b/ClassicalSharp/Blocks/BlockInfo.cs
index 98e672360..7509d67f0 100644
--- a/ClassicalSharp/Blocks/BlockInfo.cs
+++ b/ClassicalSharp/Blocks/BlockInfo.cs
@@ -46,6 +46,8 @@ namespace ClassicalSharp {
public bool[] CullWithNeighbours = new bool[BlocksCount];
+ public byte[] LightOffset = new byte[BlocksCount];
+
public const byte MaxDefinedCpeBlock = (byte)Block.StoneBrick;
public const int CpeBlocksCount = MaxDefinedCpeBlock + 1;
public const byte MaxDefinedBlock = byte.MaxValue;
@@ -97,9 +99,10 @@ namespace ClassicalSharp {
IsOpaqueY[(byte)Block.Slab] = true;
IsOpaqueY[(byte)Block.CobblestoneSlab] = true;
IsOpaqueY[(byte)Block.Snow] = true;
-
+
InitBoundingBoxes();
InitSounds();
+ InitLightOffsets();
SetupCullingCache();
}
diff --git a/ClassicalSharp/ClassicalSharp.csproj b/ClassicalSharp/ClassicalSharp.csproj
index ef93b1e0a..8d4ba54c2 100644
--- a/ClassicalSharp/ClassicalSharp.csproj
+++ b/ClassicalSharp/ClassicalSharp.csproj
@@ -140,7 +140,7 @@
-
+
diff --git a/ClassicalSharp/Map/ChunkMeshBuilder.cs b/ClassicalSharp/Map/ChunkMeshBuilder.cs
index 38da282fa..0808df556 100644
--- a/ClassicalSharp/Map/ChunkMeshBuilder.cs
+++ b/ClassicalSharp/Map/ChunkMeshBuilder.cs
@@ -144,6 +144,7 @@ namespace ClassicalSharp {
fullBright = info.FullBright[tile];
isTranslucent = info.IsTranslucent[tile];
+ lightFlags = info.LightOffset[tile];
if( leftCount != 0 )
DrawLeftFace( leftCount );
@@ -274,7 +275,9 @@ namespace ClassicalSharp {
chunkIndex++;
countIndex += TileSide.Sides;
int max = chunkSize - xx;
- while( count < max && x < width && CanStretch( tile, chunkIndex, x, y, z, face ) ) {
+ bool stretchTile = info.CanStretch[tile * TileSide.Sides + face];
+
+ while( count < max && x < width && stretchTile && CanStretch( tile, chunkIndex, x, y, z, face ) ) {
counts[countIndex] = 0;
count++;
x++;
@@ -290,7 +293,9 @@ namespace ClassicalSharp {
chunkIndex += extChunkSize;
countIndex += chunkSize * TileSide.Sides;
int max = chunkSize - zz;
- while( count < max && z < length && CanStretch( tile, chunkIndex, x, y, z, face ) ) {
+ bool stretchTile = info.CanStretch[tile * TileSide.Sides + face];
+
+ while( count < max && z < length && stretchTile && CanStretch( tile, chunkIndex, x, y, z, face ) ) {
counts[countIndex] = 0;
count++;
z++;
diff --git a/ClassicalSharp/Map/ChunkMeshBuilderTex2Col4.cs b/ClassicalSharp/Map/ChunkMeshBuilderTex2Col4.cs
index c3ad14cef..15811773f 100644
--- a/ClassicalSharp/Map/ChunkMeshBuilderTex2Col4.cs
+++ b/ClassicalSharp/Map/ChunkMeshBuilderTex2Col4.cs
@@ -10,6 +10,7 @@ namespace ClassicalSharp {
TerrainAtlas1D atlas;
int arraysCount = 0;
bool fullBright;
+ int lightFlags;
void TerrainAtlasChanged( object sender, EventArgs e ) {
int newArraysCount = game.TerrainAtlas1D.TexIds.Length;
@@ -64,30 +65,25 @@ namespace ClassicalSharp {
bool CanStretch( byte initialTile, int chunkIndex, int x, int y, int z, int face ) {
byte tile = chunk[chunkIndex];
- return tile == initialTile && info.CanStretch[tile * TileSide.Sides + face] &&
- !info.IsFaceHidden( tile, GetNeighbour( chunkIndex, face ), face ) &&
- ( IsLit( X, Y, Z, face ) == IsLit( x, y, z, face ) );
+ return tile == initialTile && !info.IsFaceHidden( tile, GetNeighbour( chunkIndex, face ), face )
+ && (fullBright || IsLit( X, Y, Z, face, initialTile ) == IsLit( x, y, z, face, tile ) );
}
- bool IsLit( int x, int y, int z, int face ) {
+ bool IsLit( int x, int y, int z, int face, byte type ) {
+ int offset = (info.LightOffset[type] >> face) & 1;
switch( face ) {
case TileSide.Left:
- return fullBright || x <= 0 || y > map.heightmap[(z * width) + (x - 1)];
-
+ return x < offset || y > map.heightmap[(z * width) + (x - offset)];
case TileSide.Right:
- return fullBright || x >= maxX || y > map.heightmap[(z * width) + (x + 1)];
-
+ return x > (maxX - offset) || y > map.heightmap[(z * width) + (x + offset)];
case TileSide.Front:
- return fullBright || z <= 0 || y > map.heightmap[((z - 1) * width) + x];
-
+ return z < offset || y > map.heightmap[((z - offset) * width) + x];
case TileSide.Back:
- return fullBright || z >= maxZ || y > map.heightmap[((z + 1) * width) + x];
-
+ return z > (maxZ - offset) || y > map.heightmap[((z + offset) * width) + x];
case TileSide.Bottom:
- return fullBright || y <= 0 || (y - 1) > map.heightmap[(z * width) + x];
-
+ return y <= 0 || (y - 1) > map.heightmap[(z * width) + x];
case TileSide.Top:
- return fullBright || y >= maxY || y > map.heightmap[(z * width) + x];
+ return y >= maxY || y > map.heightmap[(z * width) + x];
}
return true;
}
@@ -169,13 +165,14 @@ namespace ClassicalSharp {
int texId = info.textures[tile * TileSide.Sides + TileSide.Left];
int i = texId / elementsPerAtlas1D;
float vOrigin = (texId % elementsPerAtlas1D) * invVerElementSize;
+ int offset = (lightFlags >> TileSide.Left) & 1;
float u1 = minBB.Z, u2 = (maxBB.Z + (count - 1)) * 15.99f/16f;
float v1 = vOrigin + minBB.Y * invVerElementSize;
float v2 = vOrigin + maxBB.Y * invVerElementSize * 15.99f/16f;
DrawInfo part = isTranslucent ? drawInfoTranslucent[i] : drawInfoNormal[i];
FastColour col = fullBright ? FastColour.White :
- X > 0 ? (Y > map.heightmap[(Z * width) + (X - 1)] ? map.SunlightXSide : map.ShadowlightXSide) : map.SunlightXSide;
+ X >= offset ? (Y > map.heightmap[(Z * width) + (X - offset)] ? map.SunlightXSide : map.ShadowlightXSide) : map.SunlightXSide;
part.vertices[part.vIndex.left++] = new VertexPos3fTex2fCol4b( x1, y2, z2 + (count - 1), u2, v1, col );
part.vertices[part.vIndex.left++] = new VertexPos3fTex2fCol4b( x1, y2, z1, u1, v1, col );
@@ -187,49 +184,33 @@ namespace ClassicalSharp {
int texId = info.textures[tile * TileSide.Sides + TileSide.Right];
int i = texId / elementsPerAtlas1D;
float vOrigin = (texId % elementsPerAtlas1D) * invVerElementSize;
+ int offset = (lightFlags >> TileSide.Right) & 1;
float u1 = minBB.Z, u2 = (maxBB.Z + (count - 1)) * 15.99f/16f;
float v1 = vOrigin + minBB.Y * invVerElementSize;
float v2 = vOrigin + maxBB.Y * invVerElementSize * 15.99f/16f;
DrawInfo part = isTranslucent ? drawInfoTranslucent[i] : drawInfoNormal[i];
FastColour col = fullBright ? FastColour.White :
- X < maxX ? (Y > map.heightmap[(Z * width) + (X + 1)] ? map.SunlightXSide : map.ShadowlightXSide) : map.SunlightXSide;
+ X <= (maxX - offset) ? (Y > map.heightmap[(Z * width) + (X + offset)] ? map.SunlightXSide : map.ShadowlightXSide) : map.SunlightXSide;
part.vertices[part.vIndex.right++] = new VertexPos3fTex2fCol4b( x2, y2, z1, u2, v1, col );
part.vertices[part.vIndex.right++] = new VertexPos3fTex2fCol4b( x2, y2, z2 + (count - 1), u1, v1, col );
part.vertices[part.vIndex.right++] = new VertexPos3fTex2fCol4b( x2, y1, z2 + (count - 1), u1, v2, col );
part.vertices[part.vIndex.right++] = new VertexPos3fTex2fCol4b( x2, y1, z1, u2, v2, col );
}
-
- void DrawBackFace( int count ) {
- int texId = info.textures[tile * TileSide.Sides + TileSide.Back];
- int i = texId / elementsPerAtlas1D;
- float vOrigin = (texId % elementsPerAtlas1D) * invVerElementSize;
-
- float u1 = minBB.X, u2 = (maxBB.X + (count - 1)) * 15.99f/16f;
- float v1 = vOrigin + minBB.Y * invVerElementSize;
- float v2 = vOrigin + maxBB.Y * invVerElementSize * 15.99f/16f;
- DrawInfo part = isTranslucent ? drawInfoTranslucent[i] : drawInfoNormal[i];
- FastColour col = fullBright ? FastColour.White :
- Z < maxZ ? (Y > map.heightmap[((Z + 1) * width) + X] ? map.SunlightZSide : map.ShadowlightZSide) : map.SunlightZSide;
-
- part.vertices[part.vIndex.back++] = new VertexPos3fTex2fCol4b( x2 + (count - 1), y2, z2, u2, v1, col );
- part.vertices[part.vIndex.back++] = new VertexPos3fTex2fCol4b( x1, y2, z2, u1, v1, col );
- part.vertices[part.vIndex.back++] = new VertexPos3fTex2fCol4b( x1, y1, z2, u1, v2, col );
- part.vertices[part.vIndex.back++] = new VertexPos3fTex2fCol4b( x2 + (count - 1), y1, z2, u2, v2, col );
- }
void DrawFrontFace( int count ) {
int texId = info.textures[tile * TileSide.Sides + TileSide.Front];
int i = texId / elementsPerAtlas1D;
float vOrigin = (texId % elementsPerAtlas1D) * invVerElementSize;
+ int offset = (lightFlags >> TileSide.Front) & 1;
float u1 = minBB.X, u2 = (maxBB.X + (count - 1)) * 15.99f/16f;
float v1 = vOrigin + minBB.Y * invVerElementSize;
float v2 = vOrigin + maxBB.Y * invVerElementSize * 15.99f/16f;
DrawInfo part = isTranslucent ? drawInfoTranslucent[i] : drawInfoNormal[i];
FastColour col = fullBright ? FastColour.White :
- Z > 0 ? (Y > map.heightmap[((Z - 1) * width) + X] ? map.SunlightZSide : map.ShadowlightZSide) : map.SunlightZSide;
+ Z >= offset ? (Y > map.heightmap[((Z - offset) * width) + X] ? map.SunlightZSide : map.ShadowlightZSide) : map.SunlightZSide;
part.vertices[part.vIndex.front++] = new VertexPos3fTex2fCol4b( x2 + (count - 1), y1, z1, u1, v2, col );
part.vertices[part.vIndex.front++] = new VertexPos3fTex2fCol4b( x1, y1, z1, u2, v2, col );
@@ -237,6 +218,25 @@ namespace ClassicalSharp {
part.vertices[part.vIndex.front++] = new VertexPos3fTex2fCol4b( x2 + (count - 1), y2, z1, u1, v1, col );
}
+ void DrawBackFace( int count ) {
+ int texId = info.textures[tile * TileSide.Sides + TileSide.Back];
+ int i = texId / elementsPerAtlas1D;
+ float vOrigin = (texId % elementsPerAtlas1D) * invVerElementSize;
+ int offset = (lightFlags >> TileSide.Back) & 1;
+
+ float u1 = minBB.X, u2 = (maxBB.X + (count - 1)) * 15.99f/16f;
+ float v1 = vOrigin + minBB.Y * invVerElementSize;
+ float v2 = vOrigin + maxBB.Y * invVerElementSize * 15.99f/16f;
+ DrawInfo part = isTranslucent ? drawInfoTranslucent[i] : drawInfoNormal[i];
+ FastColour col = fullBright ? FastColour.White :
+ Z <= (maxZ - offset) ? (Y > map.heightmap[((Z + offset) * width) + X] ? map.SunlightZSide : map.ShadowlightZSide) : map.SunlightZSide;
+
+ part.vertices[part.vIndex.back++] = new VertexPos3fTex2fCol4b( x2 + (count - 1), y2, z2, u2, v1, col );
+ part.vertices[part.vIndex.back++] = new VertexPos3fTex2fCol4b( x1, y2, z2, u1, v1, col );
+ part.vertices[part.vIndex.back++] = new VertexPos3fTex2fCol4b( x1, y1, z2, u1, v2, col );
+ part.vertices[part.vIndex.back++] = new VertexPos3fTex2fCol4b( x2 + (count - 1), y1, z2, u2, v2, col );
+ }
+
void DrawBottomFace( int count ) {
int texId = info.textures[tile * TileSide.Sides + TileSide.Bottom];
int i = texId / elementsPerAtlas1D;