Add PVS flag

This commit is contained in:
Jarrod Doyle 2025-01-26 17:54:09 +00:00
parent 392c7b24b5
commit 65c248de84
Signed by: Jayrude
GPG Key ID: 38B57B16E7C0ADF7
2 changed files with 73 additions and 62 deletions

View File

@ -27,6 +27,7 @@ public class LightMapper
public bool LightmappedWater; public bool LightmappedWater;
public SunSettings Sunlight; public SunSettings Sunlight;
public uint AnimLightCutoff; public uint AnimLightCutoff;
public bool UsePvs;
} }
private ResourcePathManager.CampaignResources _campaign; private ResourcePathManager.CampaignResources _campaign;
@ -75,7 +76,7 @@ public class LightMapper
}); });
} }
public void Light() public void Light(bool pvs)
{ {
// TODO: Throw? // TODO: Throw?
if (!_mission.TryGetChunk<RendParams>("RENDPARAMS", out var rendParams) || if (!_mission.TryGetChunk<RendParams>("RENDPARAMS", out var rendParams) ||
@ -110,6 +111,7 @@ public class LightMapper
LightmappedWater = lmParams.LightmappedWater, LightmappedWater = lmParams.LightmappedWater,
Sunlight = sunlightSettings, Sunlight = sunlightSettings,
AnimLightCutoff = lmParams.AnimLightCutoff, AnimLightCutoff = lmParams.AnimLightCutoff,
UsePvs = pvs,
}; };
Timing.TimeStage("Gather Lights", BuildLightList); Timing.TimeStage("Gather Lights", BuildLightList);
@ -437,61 +439,67 @@ public class LightMapper
if (!_mission.TryGetChunk<WorldRep>("WREXT", out var worldRep)) if (!_mission.TryGetChunk<WorldRep>("WREXT", out var worldRep))
return; return;
// var lightVisibleCells = Timing.TimeStage("Light PVS", () =>
// { var lightVisibleCells = new List<int[]>();
// var cellCount = worldRep.Cells.Length; if (settings.UsePvs)
// var aabbs = new MathUtils.Aabb[worldRep.Cells.Length]; {
// Parallel.For(0, cellCount, i => aabbs[i] = new MathUtils.Aabb(worldRep.Cells[i].Vertices)); lightVisibleCells = Timing.TimeStage("Light PVS", () =>
// {
// var lightCellMap = new int[_lights.Count]; var cellCount = worldRep.Cells.Length;
// Parallel.For(0, _lights.Count, i => var aabbs = new MathUtils.Aabb[worldRep.Cells.Length];
// { Parallel.For(0, cellCount, i => aabbs[i] = new MathUtils.Aabb(worldRep.Cells[i].Vertices));
// lightCellMap[i] = -1;
// var light = _lights[i]; var lightCellMap = new int[_lights.Count];
// for (var j = 0; j < cellCount; j++) Parallel.For(0, _lights.Count, i =>
// { {
// if (!MathUtils.Intersects(aabbs[j], light.Position)) lightCellMap[i] = -1;
// { var light = _lights[i];
// continue; for (var j = 0; j < cellCount; j++)
// } {
// if (!MathUtils.Intersects(aabbs[j], light.Position))
// // Half-space contained {
// var cell = worldRep.Cells[j]; continue;
// var contained = true; }
// for (var k = 0; k < cell.PlaneCount; k++)
// { // Half-space contained
// var plane = cell.Planes[k]; var cell = worldRep.Cells[j];
// if (MathUtils.DistanceFromPlane(plane, light.Position) < -MathUtils.Epsilon) var contained = true;
// { for (var k = 0; k < cell.PlaneCount; k++)
// contained = false; {
// break; var plane = cell.Planes[k];
// } if (MathUtils.DistanceFromPlane(plane, light.Position) < -MathUtils.Epsilon)
// } {
// contained = false;
// if (contained) break;
// { }
// lightCellMap[i] = j; }
// break;
// } if (contained)
// } {
// }); lightCellMap[i] = j;
// break;
// var lightVisibleCells = new List<int[]>(_lights.Count); }
// var pvs = new PotentiallyVisibleSet(worldRep.Cells); }
// for (var i = 0; i < _lights.Count; i++) });
// {
// var cellIdx = lightCellMap[i]; var visibleCellMap = new List<int[]>(_lights.Count);
// if (cellIdx == -1) var pvs = new PotentiallyVisibleSet(worldRep.Cells);
// { for (var i = 0; i < _lights.Count; i++)
// lightVisibleCells.Add([]); {
// continue; var cellIdx = lightCellMap[i];
// } if (cellIdx == -1)
// var visibleSet = pvs.GetVisible(lightCellMap[i]); {
// lightVisibleCells.Add(visibleSet); visibleCellMap.Add([]);
// } continue;
// }
// return lightVisibleCells;
// }); var visibleSet = pvs.GetVisible(lightCellMap[i]);
visibleCellMap.Add(visibleSet);
}
return visibleCellMap;
});
}
// TODO: Move this functionality to the LGS library // TODO: Move this functionality to the LGS library
// We set up light indices in separately from lighting because the actual // We set up light indices in separately from lighting because the actual
@ -535,10 +543,10 @@ public class LightMapper
continue; continue;
} }
// if (!lightVisibleCells[j].Contains(i)) if (settings.UsePvs && !lightVisibleCells[j].Contains(i))
// { {
// continue; continue;
// } }
cell.LightIndexCount++; cell.LightIndexCount++;
cell.LightIndices.Add((ushort)light.LightTableIndex); cell.LightIndices.Add((ushort)light.LightTableIndex);
@ -569,7 +577,7 @@ public class LightMapper
if (overLit > 0) if (overLit > 0)
{ {
Log.Warning("{Count}/{CellCount} cells are overlit. Overlit cells can cause Object/Light Gem lighting issues.", overLit, worldRep.Cells.Length); Log.Warning("{Count}/{CellCount} cells are overlit. Overlit cells can cause Object/Light Gem lighting issues. Try running with the --pvs flag.", overLit, worldRep.Cells.Length);
} }
Log.Information("Max cell lights found ({Count}/96)", maxLights); Log.Information("Max cell lights found ({Count}/96)", maxLights);

View File

@ -40,6 +40,9 @@ public class LightCommand
[CliArgument(Description = "The name of the mission file including extension.")] [CliArgument(Description = "The name of the mission file including extension.")]
public required string MissionName { get; set; } public required string MissionName { get; set; }
[CliOption(Description = "Use a coarse PVS for tighter cell light indices.")]
public bool Pvs { get; set; } = false;
[CliOption(Description = "Name of output file excluding extension.")] [CliOption(Description = "Name of output file excluding extension.")]
public string OutputName { get; set; } = "kc_lit"; public string OutputName { get; set; } = "kc_lit";
@ -48,7 +51,7 @@ public class LightCommand
Timing.Reset(); Timing.Reset();
var lightMapper = new LightMapper(InstallPath, CampaignName, MissionName); var lightMapper = new LightMapper(InstallPath, CampaignName, MissionName);
lightMapper.Light(); lightMapper.Light(Pvs);
lightMapper.Save(OutputName); lightMapper.Save(OutputName);
Timing.LogAll(); Timing.LogAll();