bit of refactoring with the TileMapLighter classes

This commit is contained in:
Gered 2013-07-22 18:25:06 -04:00
parent 2cc12276f0
commit 9ba2a0a142
3 changed files with 102 additions and 88 deletions

View file

@ -0,0 +1,61 @@
package com.blarg.gdx.tilemap3d.lighting;
import com.blarg.gdx.Bitfield;
import com.blarg.gdx.tilemap3d.Tile;
import com.blarg.gdx.tilemap3d.TileMap;
import com.blarg.gdx.tilemap3d.tilemesh.TileMesh;
public abstract class BaseTileMapLighter implements TileMapLighter {
protected void resetLightValues(TileMap tileMap) {
for (int y = 0; y < tileMap.getHeight(); ++y)
{
for (int z = 0; z < tileMap.getDepth(); ++z)
{
for (int x = 0; x < tileMap.getWidth(); ++x)
{
Tile tile = tileMap.get(x, y, z);
// sky lighting will be recalculated, and other types of light sources
// info stays as they were
tile.flags = Bitfield.clear(Tile.FLAG_LIGHT_SKY, tile.flags);
tile.skyLight = 0;
tile.tileLight = tileMap.ambientLightValue;
}
}
}
}
protected void castSkyLightDown(TileMap tileMap) {
// go through each vertical column one at a time from top to bottom
for (int x = 0; x < tileMap.getWidth(); ++x)
{
for (int z = 0; z < tileMap.getDepth(); ++z)
{
boolean stillSkyLit = true;
byte currentSkyLightValue = tileMap.skyLightValue;
for (int y = tileMap.getHeight() - 1; y >= 0 && stillSkyLit; --y)
{
Tile tile = tileMap.get(x, y, z);
TileMesh mesh = tileMap.tileMeshes.get(tile);
if (mesh == null || (mesh != null && !mesh.isOpaque(TileMesh.SIDE_TOP) && !mesh.isOpaque(TileMesh.SIDE_BOTTOM)))
{
// tile is partially transparent or this tile is empty space
tile.flags = Bitfield.set(Tile.FLAG_LIGHT_SKY, tile.flags);
if (mesh != null)
currentSkyLightValue = Tile.adjustLightForTranslucency(currentSkyLightValue, mesh.translucency);
tile.skyLight = currentSkyLightValue;
}
else
{
// tile is present and is fully solid, sky lighting stops
// at the tile above this one
stillSkyLit = false;
}
}
}
}
}
}

View file

@ -2,37 +2,20 @@ package com.blarg.gdx.tilemap3d.lighting;
import com.blarg.gdx.tilemap3d.Tile; import com.blarg.gdx.tilemap3d.Tile;
import com.blarg.gdx.tilemap3d.TileMap; import com.blarg.gdx.tilemap3d.TileMap;
import com.blarg.gdx.tilemap3d.lighting.SimpleTileMapLighter;
import com.blarg.gdx.tilemap3d.tilemesh.TileMesh; import com.blarg.gdx.tilemap3d.tilemesh.TileMesh;
public class PositionAndSkyTileMapLighter extends SimpleTileMapLighter { public class LightSpreadingTileMapLighter extends BaseTileMapLighter {
public PositionAndSkyTileMapLighter() { private boolean doSkyLight;
private boolean doTileLight;
public LightSpreadingTileMapLighter(boolean doSkyLight, boolean doTileLight) {
this.doSkyLight = doSkyLight;
this.doTileLight = doTileLight;
} }
private void applyLighting(TileMap tileMap) { public LightSpreadingTileMapLighter() {
// for each light source (sky or not), recursively go through and set this(true, true);
// appropriate lighting for each adjacent tile
for (int y = 0; y < tileMap.getHeight(); ++y)
{
for (int z = 0; z < tileMap.getDepth(); ++z)
{
for (int x = 0; x < tileMap.getWidth(); ++x)
{
Tile tile = tileMap.get(x, y, z);
if (tile.isEmptySpace())
{
if (tile.isSkyLit())
spreadSkyLight(x, y, z, tile, tile.skyLight, tileMap);
} }
else
{
TileMesh mesh = tileMap.tileMeshes.get(tile);
if (mesh.isLightSource())
spreadTileLight(x, y, z, tile, mesh.lightValue, tileMap);
}
}
}
} }
private void spreadSkyLight(int x, int y, int z, Tile tile, byte light, TileMap tileMap) { private void spreadSkyLight(int x, int y, int z, Tile tile, byte light, TileMap tileMap) {
if (light > 0) if (light > 0)
@ -153,7 +136,33 @@ public class PositionAndSkyTileMapLighter extends SimpleTileMapLighter {
@Override @Override
public void light(TileMap tileMap) { public void light(TileMap tileMap) {
resetLightValues(tileMap); resetLightValues(tileMap);
applySkyLight(tileMap);
applyLighting(tileMap); if (doSkyLight)
castSkyLightDown(tileMap);
// for each light source (sky or not), recursively go through and set
// appropriate lighting for each adjacent tile
for (int y = 0; y < tileMap.getHeight(); ++y)
{
for (int z = 0; z < tileMap.getDepth(); ++z)
{
for (int x = 0; x < tileMap.getWidth(); ++x)
{
Tile tile = tileMap.get(x, y, z);
if (tile.isEmptySpace())
{
if (doSkyLight && tile.isSkyLit())
spreadSkyLight(x, y, z, tile, tile.skyLight, tileMap);
} }
else
{
if (doTileLight) {
TileMesh mesh = tileMap.tileMeshes.get(tile);
if (mesh.isLightSource())
spreadTileLight(x, y, z, tile, mesh.lightValue, tileMap);
}
}
}
}
} }
} }

View file

@ -6,69 +6,13 @@ import com.blarg.gdx.tilemap3d.TileMap;
import com.blarg.gdx.tilemap3d.lighting.TileMapLighter; import com.blarg.gdx.tilemap3d.lighting.TileMapLighter;
import com.blarg.gdx.tilemap3d.tilemesh.TileMesh; import com.blarg.gdx.tilemap3d.tilemesh.TileMesh;
public class SimpleTileMapLighter implements TileMapLighter { public class SimpleTileMapLighter extends BaseTileMapLighter {
public SimpleTileMapLighter() { public SimpleTileMapLighter() {
} }
protected void resetLightValues(TileMap tileMap) {
for (int y = 0; y < tileMap.getHeight(); ++y)
{
for (int z = 0; z < tileMap.getDepth(); ++z)
{
for (int x = 0; x < tileMap.getWidth(); ++x)
{
Tile tile = tileMap.get(x, y, z);
// sky lighting will be recalculated, and other types of light sources
// info stays as they were
tile.flags = Bitfield.clear(Tile.FLAG_LIGHT_SKY, tile.flags);
tile.skyLight = 0;
tile.tileLight = tileMap.ambientLightValue;
}
}
}
}
protected void applySkyLight(TileMap tileMap) {
// NOTE: resetLightValues() clears sky light data in such a way that
// doesn't require us to flood-fill 0 light values here for everything
// that isn't sky-lit
// go through each vertical column one at a time from top to bottom
for (int x = 0; x < tileMap.getWidth(); ++x)
{
for (int z = 0; z < tileMap.getDepth(); ++z)
{
boolean stillSkyLit = true;
byte currentSkyLightValue = tileMap.skyLightValue;
for (int y = tileMap.getHeight() - 1; y >= 0 && stillSkyLit; --y)
{
Tile tile = tileMap.get(x, y, z);
TileMesh mesh = tileMap.tileMeshes.get(tile);
if (mesh == null || (mesh != null && !mesh.isOpaque(TileMesh.SIDE_TOP) && !mesh.isOpaque(TileMesh.SIDE_BOTTOM)))
{
// tile is partially transparent or this tile is empty space
tile.flags = Bitfield.set(Tile.FLAG_LIGHT_SKY, tile.flags);
if (mesh != null)
currentSkyLightValue = Tile.adjustLightForTranslucency(currentSkyLightValue, mesh.translucency);
tile.skyLight = currentSkyLightValue;
}
else
{
// tile is present and is fully solid, sky lighting stops
// at the tile above this one
stillSkyLit = false;
}
}
}
}
}
@Override @Override
public void light(TileMap tileMap) { public void light(TileMap tileMap) {
resetLightValues(tileMap); resetLightValues(tileMap);
applySkyLight(tileMap); castSkyLightDown(tileMap);
} }
} }