Minor optimisations in ChunkMeshBuilder, store (y - 1) in heightmap so we don't have to also check against block height.

This commit is contained in:
UnknownShadow200 2015-08-28 06:13:18 +10:00
parent 2ffa078e75
commit fece6e6da0
3 changed files with 67 additions and 130 deletions

View File

@ -40,10 +40,13 @@ namespace ClassicalSharp {
for( int y = y1, yy = 0; y < yMax; y++, yy++ ) {
for( int z = z1, zz = 0; z < zMax; z++, zz++ ) {
int chunkIndex = ( yy + 1 ) * extChunkSize2 + ( zz + 1 ) * extChunkSize + ( -1 + 1 );
int chunkIndex = ( yy + 1 ) * extChunkSize2 + ( zz + 1 ) * extChunkSize + ( 0 + 1 ) - 1;
for( int x = x1, xx = 0; x < xMax; x++, xx++ ) {
chunkIndex++;
RenderTile( chunkIndex, xx, yy, zz, x, y, z );
tile = chunk[chunkIndex];
if( tile != 0 ) {
RenderTile( chunkIndex, xx, yy, zz, x, y, z );
}
}
}
}
@ -55,7 +58,7 @@ namespace ClassicalSharp {
fixed( byte* chunkPtr = chunk, mapPtr = map.mapData ) {
int* chunkIntPtr = (int*)chunkPtr;
for( int i = 0; i < extChunkSize3 / 4; i++ ) {
for( int i = 0; i < extChunkSize3 / sizeof( int ); i++ ) {
*chunkIntPtr++ = 0;
}
@ -107,11 +110,7 @@ namespace ClassicalSharp {
}
public void RenderTile( int chunkIndex, int xx, int yy, int zz, int x, int y, int z ) {
tile = chunk[chunkIndex];
if( tile == 0 ) return;
X = x;
Y = y;
Z = z;
X = x; Y = y; Z = z;
blockHeight = -1;
int index = ( ( yy << 8 ) + ( zz << 4 ) + xx ) * 6;
int count = 0;
@ -148,7 +147,7 @@ namespace ClassicalSharp {
if( count != 0 ) {
DrawTopFace( count );
}
}
}
void Stretch( int x1, int y1, int z1 ) {
for( int i = 0; i < counts.Length; i++ ) {
@ -172,100 +171,49 @@ namespace ClassicalSharp {
// Note that sprites are not drawn with any of the DrawXFace, they are drawn using DrawSprite.
if( BlockInfo.IsSprite( tile ) ) {
if( counts[countIndex + TileSide.Top] != 0 ) {
startX = x;
startY = y;
startZ = z;
X = x; Y = y; Z = z;
int count = StretchX( xx, countIndex, x, y, z, chunkIndex, tile, TileSide.Top );
AddSpriteVertices( tile, count );
counts[countIndex + TileSide.Top] = (byte)count;
}
} else { // Do the full calculation for all six faces.
DoStretchTerrain( xx, yy, zz, x, y, z, countIndex, tile, chunkIndex );
} else {
X = x; Y = y; Z = z;
TestAndStretchZ( zz, countIndex, tile, chunkIndex, x, 0, TileSide.Left, -1 );
TestAndStretchZ( zz, countIndex, tile, chunkIndex, x, maxX, TileSide.Right, 1 );
TestAndStretchX( xx, countIndex, tile, chunkIndex, z, 0, TileSide.Front, -18 );
TestAndStretchX( xx, countIndex, tile, chunkIndex, z, maxZ, TileSide.Back, 18 );
TestAndStretchX( xx, countIndex, tile, chunkIndex, y, 0, TileSide.Bottom, -324 );
TestAndStretchX( xx, countIndex, tile, chunkIndex, y, maxY + 2, TileSide.Top, 324 );
}
}
}
}
}
int startX, startY, startZ;
void DoStretchTerrain( int xx, int yy, int zz, int x, int y, int z, int index, byte tile, int chunkIndex ) {
startX = x;
startY = y;
startZ = z;
if( x == 0 ) {
counts[index + TileSide.Left] = 0;
} else if( counts[index + TileSide.Left] != 0 ) {
byte left = chunk[chunkIndex - 1]; // x - 1
if( BlockInfo.IsFaceHidden( tile, left, TileSide.Left ) ) {
counts[index + TileSide.Left] = 0;
void TestAndStretchX( int xx, int index, byte tile, int chunkIndex, int value, int test, int tileSide, int offset ) {
if( value == test ) {
counts[index + tileSide] = 0;
} else if( counts[index + tileSide] != 0 ) {
if( BlockInfo.IsFaceHidden( tile, chunk[chunkIndex + offset], tileSide ) ) {
counts[index + tileSide] = 0;
} else {
int count = StretchZ( zz, index, x, y, z, chunkIndex, tile, TileSide.Left );
AddVertices( tile, count, TileSide.Left );
counts[index + TileSide.Left] = (byte)count;
int count = StretchX( xx, index, X, Y, Z, chunkIndex, tile, tileSide );
AddVertices( tile, count, tileSide );
counts[index + tileSide] = (byte)count;
}
}
if( x == maxX ) {
counts[index + TileSide.Right] = 0;
} else if( counts[index + TileSide.Right] != 0 ) {
byte right = chunk[chunkIndex + 1]; // x + 1
if( BlockInfo.IsFaceHidden( tile, right, TileSide.Right ) ) {
counts[index + TileSide.Right] = 0;
}
void TestAndStretchZ( int zz, int index, byte tile, int chunkIndex, int value, int test, int tileSide, int offset ) {
if( value == test ) {
counts[index + tileSide] = 0;
} else if( counts[index + tileSide] != 0 ) {
if( BlockInfo.IsFaceHidden( tile, chunk[chunkIndex + offset], tileSide ) ) {
counts[index + tileSide] = 0;
} else {
int count = StretchZ( zz, index, x, y, z, chunkIndex, tile, TileSide.Right );
AddVertices( tile, count, TileSide.Right );
counts[index + TileSide.Right] = (byte)count;
}
}
if( z == 0 ) {
counts[index + TileSide.Front] = 0;
} else if( counts[index + TileSide.Front] != 0 ) {
byte front = chunk[chunkIndex - 18]; // z - 1
if( BlockInfo.IsFaceHidden( tile, front, TileSide.Front ) ) {
counts[index + TileSide.Front] = 0;
} else {
int count = StretchX( xx, index, x, y, z, chunkIndex, tile, TileSide.Front );
AddVertices( tile, count, TileSide.Front );
counts[index + TileSide.Front] = (byte)count;
}
}
if( z == maxZ ) {
counts[index + TileSide.Back] = 0;
} else if( counts[index + TileSide.Back] != 0 ) {
byte back = chunk[chunkIndex + 18]; // z + 1
if( BlockInfo.IsFaceHidden( tile, back, TileSide.Right ) ) {
counts[index + TileSide.Back] = 0;
} else {
int count = StretchX( xx, index, x, y, z, chunkIndex, tile, TileSide.Back );
AddVertices( tile, count, TileSide.Back );
counts[index + TileSide.Back] = (byte)count;
}
}
if( y == 0 ) {
counts[index + TileSide.Bottom] = 0;
} else if( counts[index + TileSide.Bottom] != 0 ) {
byte below = chunk[chunkIndex - 324]; // y - 1
if( BlockInfo.IsFaceHidden( tile, below, TileSide.Bottom ) ) {
counts[index + TileSide.Bottom] = 0;
} else {
int count = StretchX( xx, index, x, y, z, chunkIndex, tile, TileSide.Bottom );
AddVertices( tile, count, TileSide.Bottom );
counts[index + TileSide.Bottom] = (byte)count;
}
}
if( counts[index + TileSide.Top] != 0 ) {
byte above = chunk[chunkIndex + 324]; // y + 1
if( BlockInfo.IsFaceHidden( tile, above, TileSide.Top ) ) {
counts[index + TileSide.Top] = 0;
} else {
int count = StretchX( xx, index, x, y, z, chunkIndex, tile, TileSide.Top );
AddVertices( tile, count, TileSide.Top );
counts[index + TileSide.Top] = (byte)count;
int count = StretchZ( zz, index, X, Y, Z, chunkIndex, tile, tileSide );
AddVertices( tile, count, tileSide );
counts[index + tileSide] = (byte)count;
}
}
}
@ -342,7 +290,7 @@ namespace ClassicalSharp {
public struct ChunkPartInfo {
public int VbId, IndicesCount;
public int leftIndex, rightIndex, frontIndex,
public int leftIndex, rightIndex, frontIndex,
backIndex, bottomIndex, topIndex;
public ushort leftCount, rightCount, frontCount,
backCount, bottomCount, topCount, spriteCount;

View File

@ -64,48 +64,32 @@ namespace ClassicalSharp {
bool CanStretch( byte initialTile, int chunkIndex, int x, int y, int z, int face ) {
byte tile = chunk[chunkIndex];
return tile == initialTile && !BlockInfo.IsFaceHidden( tile, GetNeighbour( chunkIndex, face ), face ) &&
( IsLit( startX, startY, startZ, face ) == IsLit( x, y, z, face ) );
( IsLit( X, Y, Z, face ) == IsLit( x, y, z, face ) );
}
bool IsLit( int x, int y, int z, int face ) {
switch( face ) {
case TileSide.Left:
return x <= 0 || y > GetLightHeightAdj( x - 1, z );
return x <= 0 || y > map.heightmap[( z * width ) + (x - 1)];
case TileSide.Right:
return x >= maxX || y > GetLightHeightAdj( x + 1, z );
return x >= maxX || y > map.heightmap[( z * width ) + (x + 1)];
case TileSide.Front:
return z <= 0 || y > GetLightHeightAdj( x, z - 1 );
return z <= 0 || y > map.heightmap[( (z - 1) * width ) + x];
case TileSide.Back:
return z >= maxZ || y > GetLightHeightAdj( x, z + 1 );
return z >= maxZ || y > map.heightmap[( (z + 1) * width ) + x];
case TileSide.Bottom:
return y <= 0 || ( y - 1 ) > map.heightmap[( z * width ) + x];
return y <= 0 || (y - 1) > map.heightmap[( z * width ) + x];
case TileSide.Top:
return y >= maxY || ( y + 1 ) > map.heightmap[( z * width ) + x];
return y >= maxY || (y + 1) > map.heightmap[( z * width ) + x];
}
return true;
}
FastColour GetColour( int x, int y, int z, ref FastColour sunlight, ref FastColour shadow ) {
if( !map.IsValidPos( x, y, z ) ) return sunlight;
return y > map.heightmap[( z * width ) + x] ? sunlight : shadow;
}
FastColour GetColourAdj( int x, int y, int z, ref FastColour sunlight, ref FastColour shadow ) {
if( !map.IsValidPos( x, y, z ) ) return sunlight;
return y > GetLightHeightAdj( x, z ) ? sunlight : shadow;
}
int GetLightHeightAdj( int x, int z ) {
int y = map.heightmap[( z * width ) + x];
return y == -1 ? -1 :
( BlockInfo.BlockHeight( map.GetBlock( x, y, z ) ) == 1 ? y : y - 1 );
}
void SetPartInfo( DrawInfo part, int i, ref ChunkPartInfo[] parts ) {
if( part.iCount == 0 ) return;
@ -174,9 +158,7 @@ namespace ClassicalSharp {
part.iCount += 6;
DrawInfoFaceData counts = part.Count;
int* ptr = &counts.left;
ptr += face;
*ptr += 6;
*( &counts.left + face ) += 6;
part.Count = counts;
}
@ -184,7 +166,8 @@ namespace ClassicalSharp {
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Left );
int i;
TextureRectangle rec = atlas.GetTexRec( texId, count, out i );
FastColour col = GetColourAdj( X - 1, Y, Z, ref map.SunlightXSide, ref map.ShadowlightXSide );
FastColour col = X > 0 ? ( Y > map.heightmap[( Z * width ) + (X - 1)] ? map.SunlightXSide : map.ShadowlightXSide )
: map.SunlightXSide;
if( blockHeight == -1 ) {
blockHeight = BlockInfo.BlockHeight( tile );
isTranslucent = BlockInfo.IsTranslucent( tile );
@ -204,7 +187,8 @@ namespace ClassicalSharp {
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Right );
int i;
TextureRectangle rec = atlas.GetTexRec( texId, count, out i );
FastColour col = GetColourAdj( X + 1, Y, Z, ref map.SunlightXSide, ref map.ShadowlightXSide );
FastColour col = X < maxX ? ( Y > map.heightmap[( Z * width ) + (X + 1)] ? map.SunlightXSide : map.ShadowlightXSide )
: map.SunlightXSide;
if( blockHeight == -1 ) {
blockHeight = BlockInfo.BlockHeight( tile );
isTranslucent = BlockInfo.IsTranslucent( tile );
@ -224,7 +208,8 @@ namespace ClassicalSharp {
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Back );
int i;
TextureRectangle rec = atlas.GetTexRec( texId, count, out i );
FastColour col = GetColourAdj( X, Y, Z + 1, ref map.SunlightZSide, ref map.ShadowlightZSide );
FastColour col = Z < maxZ ? ( Y > map.heightmap[( (Z + 1) * width ) + X] ? map.SunlightZSide : map.ShadowlightZSide )
: map.SunlightZSide;
if( blockHeight == -1 ) {
blockHeight = BlockInfo.BlockHeight( tile );
isTranslucent = BlockInfo.IsTranslucent( tile );
@ -244,7 +229,8 @@ namespace ClassicalSharp {
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Front );
int i;
TextureRectangle rec = atlas.GetTexRec( texId, count, out i );
FastColour col = GetColourAdj( X, Y, Z - 1, ref map.SunlightZSide, ref map.ShadowlightZSide );
FastColour col = Z > 0 ? ( Y > map.heightmap[( (Z - 1) * width ) + X] ? map.SunlightZSide : map.ShadowlightZSide )
: map.SunlightZSide;
if( blockHeight == -1 ) {
blockHeight = BlockInfo.BlockHeight( tile );
isTranslucent = BlockInfo.IsTranslucent( tile );
@ -264,7 +250,8 @@ namespace ClassicalSharp {
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Bottom );
int i;
TextureRectangle rec = atlas.GetTexRec( texId, count, out i );
FastColour col = GetColour( X, Y - 1, Z, ref map.SunlightYBottom, ref map.ShadowlightYBottom );
FastColour col = Y > 0 ? ( (Y - 1) > map.heightmap[( Z * width ) + X] ? map.SunlightYBottom : map.ShadowlightYBottom )
: map.SunlightYBottom;
if( blockHeight == -1 ) {
blockHeight = BlockInfo.BlockHeight( tile );
isTranslucent = BlockInfo.IsTranslucent( tile );
@ -281,7 +268,8 @@ namespace ClassicalSharp {
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Top );
int i;
TextureRectangle rec = atlas.GetTexRec( texId, count, out i );
FastColour col = GetColour( X, Y + 1, Z, ref map.Sunlight, ref map.Shadowlight );
FastColour col = Y < maxY ? ( (Y + 1) > map.heightmap[( Z * width ) + X] ? map.Sunlight : map.Shadowlight )
: map.Sunlight;
if( blockHeight == -1 ) {
blockHeight = BlockInfo.BlockHeight( tile );
isTranslucent = BlockInfo.IsTranslucent( tile );
@ -298,7 +286,8 @@ namespace ClassicalSharp {
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Right );
int i;
TextureRectangle rec = atlas.GetTexRec( texId, count, out i );
FastColour col = GetColour( X, Y + 1, Z, ref map.Sunlight, ref map.Shadowlight );
FastColour col = Y < maxY ? ( (Y + 1) > map.heightmap[( Z * width ) + X] ? map.Sunlight : map.Shadowlight )
: map.Sunlight;
if( blockHeight == -1 ) {
blockHeight = BlockInfo.BlockHeight( tile );
}

View File

@ -119,14 +119,14 @@ namespace ClassicalSharp {
for( int y = maxY; y >= 0; y-- ) {
byte block = mapData[mapIndex];
if( info.BlocksLight( block ) ) {
heightmap[index] = (short)y;
heightmap[index] = (short)( y - 1 );
return y;
}
mapIndex -= oneY;
}
heightmap[index] = -1;
return -1;
heightmap[index] = -10;
return -10;
}
void UpdateHeight( int x, int y, int z, byte oldBlock, byte newBlock ) {
@ -140,9 +140,9 @@ namespace ClassicalSharp {
// We have to calculate the entire column for visibility, because the old/new block info is
// useless if there is another block higher than block.y that stops rain.
CalcHeightAt( x, maxY, z, index );
} else if( y >= height ) {
} else if( y > height ) {
if( nowBlocks ) {
heightmap[index] = (short)y;
heightmap[index] = (short)( y - 1 );
} else {
// Part of the column is now visible to light, we don't know how exactly how high it should be though.
// However, we know that if the old block was above or equal to light height, then the new light height must be <= old block.y
@ -255,7 +255,7 @@ namespace ClassicalSharp {
x += curRunCount; mapIndex += curRunCount; index += curRunCount;
if( x < xCount && info.blocksLight[mapPtr[mapIndex]] ) {
heightmap[heightmapIndex + x] = (short)y;
heightmap[heightmapIndex + x] = (short)( y - 1 );
elemsLeft--;
skip[index] = 0;
int offset = prevRunCount + curRunCount;
@ -290,7 +290,7 @@ namespace ClassicalSharp {
for( int x = 0; x < xCount; x++ ) {
int height = heightmap[heightmapIndex];
if( height == short.MaxValue )
heightmap[heightmapIndex] = -1;
heightmap[heightmapIndex] = -10;
heightmapIndex++;
}
}