Fix propegation of light through leaves/etc

This commit is contained in:
Drew DeVault 2015-06-26 19:22:07 -06:00
parent 61310e6bbb
commit edf7205050
6 changed files with 111 additions and 11 deletions

View File

@ -232,6 +232,94 @@ namespace TrueCraft.Core.Test.Lighting
expected--; expected--;
} }
} }
[Test]
public void TestLeavesAndEtc()
{
var repository = new BlockRepository();
repository.RegisterBlockProvider(new GrassBlock());
repository.RegisterBlockProvider(new DirtBlock());
repository.RegisterBlockProvider(new AirBlock());
repository.RegisterBlockProvider(new BedrockBlock());
repository.RegisterBlockProvider(new LeavesBlock());
var world = new TrueCraft.Core.World.World("TEST", new FlatlandGenerator());
world.BlockRepository = repository;
var lighter = new WorldLighter(world, repository);
world.GetBlockID(Coordinates3D.Zero); // Generate a chunk
for (int y = 1; y <= 16; y++)
{
var coords = new Coordinates3D(5, y, 5);
world.SetBlockID(coords, 0);
world.SetBlockID(coords + Coordinates3D.East, DirtBlock.BlockID);
world.SetBlockID(coords + Coordinates3D.West, DirtBlock.BlockID);
world.SetBlockID(coords + Coordinates3D.North, DirtBlock.BlockID);
world.SetBlockID(coords + Coordinates3D.South, DirtBlock.BlockID);
}
world.GetChunk(Coordinates2D.Zero).UpdateHeightMap();
lighter.EnqueueOperation(new BoundingBox(
new Vector3(0, 0, 0),
new Vector3(16, 128, 16)), true, true);
while (lighter.TryLightNext()) // Initial lighting
{
}
// Test this layout:
// xox o == leaves
// x x
// xox
// x x
// xox ...
for (int y = 1; y <= 16; y++)
{
if (y % 2 == 1)
world.SetBlockID(new Coordinates3D(5, y, 5), LeavesBlock.BlockID);
}
world.GetChunk(Coordinates2D.Zero).UpdateHeightMap();
lighter.EnqueueOperation(new BoundingBox(new Vector3(5, 0, 5),
new Vector3(6, 16, 6)), true);
while (lighter.TryLightNext()) // Test lighting
{
}
// Output lighting
for (int y = 16; y >= 0; y--)
{
Console.Write(world.GetBlockID(new Coordinates3D(5, y, 5)).ToString("D2"));
Console.Write(" " + world.GetSkyLight(new Coordinates3D(5, y, 5)).ToString("D2"));
Console.WriteLine(" Y={0}", y);
}
var expected = new byte[]
{
15, // air
15, // leaves
13, // air
11, // leaves
9, // air
7, // leaves
5, // air
3, // leaves
1, // air
0, // leaves
0, // air
0, // leaves
};
for (int y = 16, i = 0; y >= 0; y--, i++)
{
byte ex;
if (i < expected.Length)
ex = expected[i];
else
ex = 0;
Assert.AreEqual(ex, world.GetSkyLight(new Coordinates3D(5, y, 5)));
}
}
} }
} }

View File

@ -93,12 +93,14 @@ namespace TrueCraft.Core.Lighting
byte current = op.SkyLight ? data.SkyLight : data.BlockLight; byte current = op.SkyLight ? data.SkyLight : data.BlockLight;
byte newLight = 0; byte newLight = 0;
byte opacity = Math.Max(provider.LightModifier, (byte)1); byte opacity = Math.Max(provider.LightModifier, (byte)1);
byte emissiveness = Math.Max(provider.Luminance, op.SkyLight ? data.SkyLight : data.BlockLight); byte emissiveness = provider.Luminance;
if (op.SkyLight) if (op.SkyLight)
{ {
if (chunk.GetHeight((byte)adjustedCoords.X, (byte)adjustedCoords.Z) <= y) if (y >= chunk.GetHeight((byte)adjustedCoords.X, (byte)adjustedCoords.Z))
emissiveness = 15; emissiveness = 15;
} }
else
emissiveness = provider.Luminance;
if (opacity < 15 || emissiveness != 0) if (opacity < 15 || emissiveness != 0)
{ {
byte max = 0; byte max = 0;
@ -116,7 +118,7 @@ namespace TrueCraft.Core.Lighting
else else
val = c.GetBlockLight(adjusted); val = c.GetBlockLight(adjusted);
var p = BlockRepository.GetBlockProvider(c.GetBlockID(adjusted)); var p = BlockRepository.GetBlockProvider(c.GetBlockID(adjusted));
val -= p.LightModifier; val -= Math.Max(0, p.LightModifier - 1);
max = (byte)Math.Max(max, val); max = (byte)Math.Max(max, val);
} }
} }
@ -171,9 +173,9 @@ namespace TrueCraft.Core.Lighting
if (op.Box.Min.DistanceTo(box.Min) <= 2 && op.Box.Max.DistanceTo(box.Max) <= 2 if (op.Box.Min.DistanceTo(box.Min) <= 2 && op.Box.Max.DistanceTo(box.Max) <= 2
&& op.Box.Volume - box.Volume <= 2) && op.Box.Volume - box.Volume <= 2)
{ {
// Merge // TODO: Merge
op.Box = new BoundingBox(Vector3.Min(op.Box.Min, box.Min), Vector3.Max(op.Box.Max, box.Max)); //op.Box = new BoundingBox(Vector3.Min(op.Box.Min, box.Min), Vector3.Max(op.Box.Max, box.Max));
return; //return;
} }
} }
PendingOperations.Add(new LightingOperation { SkyLight = skyLight, Box = box, Initial = initial }); PendingOperations.Add(new LightingOperation { SkyLight = skyLight, Box = box, Initial = initial });

View File

@ -208,7 +208,16 @@ namespace TrueCraft.Core.Logic
/// - This isn't needed for opaque blocks /// - This isn't needed for opaque blocks
/// - This is needed since some "partial" transparent blocks remove more than 1 level from light passing through such as Ice. /// - This is needed since some "partial" transparent blocks remove more than 1 level from light passing through such as Ice.
/// </summary> /// </summary>
public virtual byte LightModifier { get { return 255; } } public virtual byte LightModifier
{
get
{
if (Opaque)
return 255;
else
return 0;
}
}
public virtual bool DiffuseSkyLight { get { return false; } } public virtual bool DiffuseSkyLight { get { return false; } }

View File

@ -16,8 +16,6 @@ namespace TrueCraft.Core.Logic.Blocks
public override bool Opaque { get { return false; } } public override bool Opaque { get { return false; } }
public override byte LightModifier { get { return 0; } }
public override byte Luminance { get { return 0; } } public override byte Luminance { get { return 0; } }
public override string DisplayName { get { return "Air"; } } public override string DisplayName { get { return "Air"; } }

View File

@ -20,7 +20,9 @@ namespace TrueCraft.Core.Logic.Blocks
public override bool Opaque { get { return false; } } public override bool Opaque { get { return false; } }
//TODO: Mark this as a block that diffuses sun light. public override bool DiffuseSkyLight { get { return true; } }
public override byte LightModifier { get { return 2; } }
public override string DisplayName { get { return "Leaves"; } } public override string DisplayName { get { return "Leaves"; } }

View File

@ -89,6 +89,7 @@ namespace TrueCraft
Server.Log(LogCategory.Notice, "{0}% complete", progress + 10); Server.Log(LogCategory.Notice, "{0}% complete", progress + 10);
} }
} }
world.Save();
CommandManager = new CommandManager(); CommandManager = new CommandManager();
Server.ChatMessageReceived += HandleChatMessageReceived; Server.ChatMessageReceived += HandleChatMessageReceived;
Server.Start(new IPEndPoint(IPAddress.Parse(ServerConfiguration.ServerAddress), ServerConfiguration.ServerPort)); Server.Start(new IPEndPoint(IPAddress.Parse(ServerConfiguration.ServerAddress), ServerConfiguration.ServerPort));