Compare commits

..

3 Commits

3 changed files with 57 additions and 13 deletions

View File

@ -332,7 +332,7 @@ public class WorldRep : IChunk
public LightmapInfo[] LightList { get; set; } public LightmapInfo[] LightList { get; set; }
public Lightmap[] Lightmaps { get; set; } public Lightmap[] Lightmaps { get; set; }
public int LightIndexCount { get; set; } public int LightIndexCount { get; set; }
public ushort[] LightIndices { get; set; } public List<ushort> LightIndices { get; set; }
public Cell(BinaryReader reader, int bpp) public Cell(BinaryReader reader, int bpp)
{ {
@ -392,10 +392,10 @@ public class WorldRep : IChunk
Lightmaps[i] = new Lightmap(reader, info.Width, info.Height, info.AnimLightBitmask, bpp); Lightmaps[i] = new Lightmap(reader, info.Width, info.Height, info.AnimLightBitmask, bpp);
} }
LightIndexCount = reader.ReadInt32(); LightIndexCount = reader.ReadInt32();
LightIndices = new ushort[LightIndexCount]; LightIndices = new List<ushort>(LightIndexCount);
for (var i = 0; i < LightIndexCount; i++) for (var i = 0; i < LightIndexCount; i++)
{ {
LightIndices[i] = reader.ReadUInt16(); LightIndices.Add(reader.ReadUInt16());
} }
} }

View File

@ -49,6 +49,12 @@ public static class MathUtils
return d2 < r2; return d2 < r2;
} }
public static bool Intersects(Sphere sphere, Sphere other)
{
var rsum = sphere.Radius + other.Radius;
return (sphere.Position - other.Position).Length() <= rsum;
}
public static float DistanceFromPlane(Plane plane, Vector3 point) public static float DistanceFromPlane(Plane plane, Vector3 point)
{ {
return Math.Abs(Vector3.Dot(plane.Normal, point) + plane.D) / plane.Normal.Length(); return Math.Abs(Vector3.Dot(plane.Normal, point) + plane.D) / plane.Normal.Length();

View File

@ -22,9 +22,9 @@ class Program
public float spotlightInnerAngle; public float spotlightInnerAngle;
public float spotlightOuterAngle; public float spotlightOuterAngle;
public int objId;
public int lightTableIndex;
public bool anim; public bool anim;
public int animObjId;
public int animLightTableIndex;
} }
static void Main(string[] args) static void Main(string[] args)
@ -36,9 +36,10 @@ class Program
var campaignName = "JAYRUDE_Tests"; var campaignName = "JAYRUDE_Tests";
var missionName = "lm_test.cow"; var missionName = "lm_test.cow";
// campaignName = "JAYRUDE_1MIL_Mages";
// campaignName = "TDP20AC_a_burrick_in_a_room"; // campaignName = "TDP20AC_a_burrick_in_a_room";
campaignName = "AtdV"; // campaignName = "AtdV";
missionName = "miss20.mis"; // missionName = "miss20.mis";
// Setup extract path // Setup extract path
var tmpDir = Directory.CreateTempSubdirectory("KCLightmapper"); var tmpDir = Directory.CreateTempSubdirectory("KCLightmapper");
@ -143,10 +144,10 @@ class Program
foreach (var (lightIdx, animCellMaps) in map) foreach (var (lightIdx, animCellMaps) in map)
{ {
// Get the appropriate property!! // Get the appropriate property!!
var light = lights.Find((l) => l.anim && l.animLightTableIndex == lightIdx); var light = lights.Find((l) => l.anim && l.lightTableIndex == lightIdx);
foreach (var prop in animLightChunk.properties) foreach (var prop in animLightChunk.properties)
{ {
if (prop.objectId == light.animObjId) if (prop.objectId == light.objId)
{ {
prop.LightTableLightIndex = lightIdx; prop.LightTableLightIndex = lightIdx;
prop.LightTableMapIndex = (ushort)worldRep.LightingTable.AnimMapCount; prop.LightTableMapIndex = (ushort)worldRep.LightingTable.AnimMapCount;
@ -195,6 +196,7 @@ class Program
color = HsbToRgb(sz.Y, sz.Z, Math.Min(sz.X, 255.0f)), color = HsbToRgb(sz.Y, sz.Z, Math.Min(sz.X, 255.0f)),
radius = float.MaxValue, radius = float.MaxValue,
r2 = float.MaxValue, r2 = float.MaxValue,
lightTableIndex = worldRep.LightingTable.LightCount,
}; };
lights.Add(light); lights.Add(light);
@ -272,6 +274,7 @@ class Program
spotlightDir = baseLight.spotlightDir, spotlightDir = baseLight.spotlightDir,
spotlightInnerAngle = baseLight.spotlightInnerAngle, spotlightInnerAngle = baseLight.spotlightInnerAngle,
spotlightOuterAngle = baseLight.spotlightOuterAngle, spotlightOuterAngle = baseLight.spotlightOuterAngle,
lightTableIndex = worldRep.LightingTable.LightCount,
}; };
if (propLight.Radius == 0) if (propLight.Radius == 0)
@ -309,8 +312,8 @@ class Program
spotlightInnerAngle = baseLight.spotlightInnerAngle, spotlightInnerAngle = baseLight.spotlightInnerAngle,
spotlightOuterAngle = baseLight.spotlightOuterAngle, spotlightOuterAngle = baseLight.spotlightOuterAngle,
anim = true, anim = true,
animObjId = id, objId = id,
animLightTableIndex = propAnimLight.LightTableLightIndex, lightTableIndex = propAnimLight.LightTableLightIndex,
}; };
if (propAnimLight.Radius == 0) if (propAnimLight.Radius == 0)
{ {
@ -411,6 +414,41 @@ class Program
{ {
var hdr = wr.DataHeader.LightmapFormat == 2; var hdr = wr.DataHeader.LightmapFormat == 2;
// We set up light indices in a separate loop because the actual lighting
// phase takes a lot of shortcuts that we don't want
Parallel.ForEach(wr.Cells, cell =>
{
cell.LightIndexCount = 0;
cell.LightIndices.Clear();
// The OG lightmapper uses the cell traversal to work out all the cells that
// are actually visited. We're a lot more coarse and just say if a cell is
// in range then we potentially affect the lighting in the cell and add it
// to the list. Cells already contain their sphere bounds so we just use
// that for now, but a tighter AABB is another option.
var cellSphere = new MathUtils.Sphere(cell.SphereCenter, cell.SphereRadius);
foreach (var light in lights)
{
// If the light had radius 0 (represented here with max float) then we
// always add it to the list
// TODO: Neaten this up
if (light.radius == float.MaxValue)
{
cell.LightIndexCount++;
cell.LightIndices.Add((ushort)light.lightTableIndex);
}
else
{
var lightSphere = new MathUtils.Sphere(light.position, light.radius);
if (MathUtils.Intersects(cellSphere, lightSphere))
{
cell.LightIndexCount++;
cell.LightIndices.Add((ushort)light.lightTableIndex);
}
}
}
});
Parallel.ForEach(wr.Cells, cell => Parallel.ForEach(wr.Cells, cell =>
{ {
// Reset cell AnimLight palette // Reset cell AnimLight palette
@ -549,12 +587,12 @@ class Program
if (light.anim) if (light.anim)
{ {
// TODO: Don't recalculate this for every point lol // TODO: Don't recalculate this for every point lol
var paletteIdx = cell.AnimLights.IndexOf((ushort)light.animLightTableIndex); var paletteIdx = cell.AnimLights.IndexOf((ushort)light.lightTableIndex);
if (paletteIdx == -1) if (paletteIdx == -1)
{ {
paletteIdx = cell.AnimLightCount; paletteIdx = cell.AnimLightCount;
cell.AnimLightCount++; cell.AnimLightCount++;
cell.AnimLights.Add((ushort)light.animLightTableIndex); cell.AnimLights.Add((ushort)light.lightTableIndex);
} }
info.AnimLightBitmask |= 1u << paletteIdx; info.AnimLightBitmask |= 1u << paletteIdx;