Compare commits
4 Commits
fe100bb938
...
b3a71e6827
Author | SHA1 | Date |
---|---|---|
Jarrod Doyle | b3a71e6827 | |
Jarrod Doyle | 1d96c06032 | |
Jarrod Doyle | b47a7536c4 | |
Jarrod Doyle | e6ca952962 |
|
@ -8,12 +8,20 @@ namespace KeepersCompound.Lightmapper;
|
||||||
|
|
||||||
public class LightMapper
|
public class LightMapper
|
||||||
{
|
{
|
||||||
|
private enum SurfaceType
|
||||||
|
{
|
||||||
|
Solid,
|
||||||
|
Sky,
|
||||||
|
Water,
|
||||||
|
}
|
||||||
|
|
||||||
private class Settings
|
private class Settings
|
||||||
{
|
{
|
||||||
public Vector3 AmbientLight;
|
public Vector3 AmbientLight;
|
||||||
public bool Hdr;
|
public bool Hdr;
|
||||||
public SoftnessMode MultiSampling;
|
public SoftnessMode MultiSampling;
|
||||||
public float MultiSamplingCenterWeight;
|
public float MultiSamplingCenterWeight;
|
||||||
|
public bool LightmappedWater;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResourcePathManager.CampaignResources _campaign;
|
private ResourcePathManager.CampaignResources _campaign;
|
||||||
|
@ -22,6 +30,7 @@ public class LightMapper
|
||||||
private ObjectHierarchy _hierarchy;
|
private ObjectHierarchy _hierarchy;
|
||||||
private Raytracer _scene;
|
private Raytracer _scene;
|
||||||
private List<Light> _lights;
|
private List<Light> _lights;
|
||||||
|
private List<SurfaceType> _triangleTypeMap;
|
||||||
|
|
||||||
public LightMapper(
|
public LightMapper(
|
||||||
string installPath,
|
string installPath,
|
||||||
|
@ -33,6 +42,7 @@ public class LightMapper
|
||||||
_misPath = _campaign.GetResourcePath(ResourceType.Mission, missionName);
|
_misPath = _campaign.GetResourcePath(ResourceType.Mission, missionName);
|
||||||
_mission = Timing.TimeStage("Parse DB", () => new DbFile(_misPath));
|
_mission = Timing.TimeStage("Parse DB", () => new DbFile(_misPath));
|
||||||
_hierarchy = Timing.TimeStage("Build Hierarchy", BuildHierarchy);
|
_hierarchy = Timing.TimeStage("Build Hierarchy", BuildHierarchy);
|
||||||
|
_triangleTypeMap = [];
|
||||||
_scene = Timing.TimeStage("Build Scene", BuildRaytracingScene);
|
_scene = Timing.TimeStage("Build Scene", BuildRaytracingScene);
|
||||||
_lights = [];
|
_lights = [];
|
||||||
}
|
}
|
||||||
|
@ -47,14 +57,16 @@ public class LightMapper
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: lmParams LightmappedWater doesn't mean the game will actually *use* the lightmapped water hmm
|
||||||
var settings = new Settings
|
var settings = new Settings
|
||||||
{
|
{
|
||||||
Hdr = worldRep.DataHeader.LightmapFormat == 2,
|
Hdr = worldRep.DataHeader.LightmapFormat == 2,
|
||||||
AmbientLight = rendParams.ambientLight * 255,
|
AmbientLight = rendParams.ambientLight * 255,
|
||||||
MultiSampling = lmParams.ShadowSoftness,
|
MultiSampling = lmParams.ShadowSoftness,
|
||||||
MultiSamplingCenterWeight = lmParams.CenterWeight,
|
MultiSamplingCenterWeight = lmParams.CenterWeight,
|
||||||
|
LightmappedWater = lmParams.LightmappedWater,
|
||||||
};
|
};
|
||||||
|
|
||||||
Timing.TimeStage("Gather Lights", BuildLightList);
|
Timing.TimeStage("Gather Lights", BuildLightList);
|
||||||
Timing.TimeStage("Set Light Indices", SetCellLightIndices);
|
Timing.TimeStage("Set Light Indices", SetCellLightIndices);
|
||||||
Timing.TimeStage("Trace Scene", () => TraceScene(settings));
|
Timing.TimeStage("Trace Scene", () => TraceScene(settings));
|
||||||
|
@ -119,9 +131,9 @@ public class LightMapper
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var maxPolyIdx = Math.Min(numRenderPolys, numPolys - numPortalPolys);
|
var solidPolys = numPolys - numPortalPolys;
|
||||||
var cellIdxOffset = 0;
|
var cellIdxOffset = 0;
|
||||||
for (var polyIdx = 0; polyIdx < maxPolyIdx; polyIdx++)
|
for (var polyIdx = 0; polyIdx < numRenderPolys; polyIdx++)
|
||||||
{
|
{
|
||||||
var poly = cell.Polys[polyIdx];
|
var poly = cell.Polys[polyIdx];
|
||||||
var meshIndexOffset = vertices.Count;
|
var meshIndexOffset = vertices.Count;
|
||||||
|
@ -132,12 +144,25 @@ public class LightMapper
|
||||||
vertices.Add(vertex);
|
vertices.Add(vertex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We need to know what type of surface this poly is so we can map Embree primitive IDs to surface
|
||||||
|
// types
|
||||||
|
var renderPoly = cell.RenderPolys[polyIdx];
|
||||||
|
var primType = SurfaceType.Solid;
|
||||||
|
if (renderPoly.TextureId == 249)
|
||||||
|
{
|
||||||
|
primType = SurfaceType.Sky;
|
||||||
|
} else if (polyIdx >= solidPolys)
|
||||||
|
{
|
||||||
|
primType = SurfaceType.Water;
|
||||||
|
}
|
||||||
|
|
||||||
// Cell polygons are n-sided, but fortunately they're convex so we can just do a fan triangulation
|
// Cell polygons are n-sided, but fortunately they're convex so we can just do a fan triangulation
|
||||||
for (var j = 1; j < numPolyVertices - 1; j++)
|
for (var j = 1; j < numPolyVertices - 1; j++)
|
||||||
{
|
{
|
||||||
indices.Add(meshIndexOffset);
|
indices.Add(meshIndexOffset);
|
||||||
indices.Add(meshIndexOffset + j);
|
indices.Add(meshIndexOffset + j);
|
||||||
indices.Add(meshIndexOffset + j + 1);
|
indices.Add(meshIndexOffset + j + 1);
|
||||||
|
_triangleTypeMap.Add(primType);
|
||||||
}
|
}
|
||||||
|
|
||||||
cellIdxOffset += cell.Polys[polyIdx].VertexCount;
|
cellIdxOffset += cell.Polys[polyIdx].VertexCount;
|
||||||
|
@ -368,9 +393,9 @@ public class LightMapper
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var maxPolyIdx = Math.Min(numRenderPolys, numPolys - numPortalPolys);
|
var solidPolys = numPolys - numPortalPolys;
|
||||||
var cellIdxOffset = 0;
|
var cellIdxOffset = 0;
|
||||||
for (var polyIdx = 0; polyIdx < maxPolyIdx; polyIdx++)
|
for (var polyIdx = 0; polyIdx < numRenderPolys; polyIdx++)
|
||||||
{
|
{
|
||||||
var poly = cell.Polys[polyIdx];
|
var poly = cell.Polys[polyIdx];
|
||||||
var plane = cell.Planes[poly.PlaneId];
|
var plane = cell.Planes[poly.PlaneId];
|
||||||
|
@ -379,6 +404,14 @@ public class LightMapper
|
||||||
var lightmap = cell.Lightmaps[polyIdx];
|
var lightmap = cell.Lightmaps[polyIdx];
|
||||||
|
|
||||||
info.AnimLightBitmask = 0;
|
info.AnimLightBitmask = 0;
|
||||||
|
|
||||||
|
// We have to reset the lightmaps for water, but we don't want to do anything else
|
||||||
|
var waterPoly = polyIdx >= solidPolys;
|
||||||
|
if (!settings.LightmappedWater && waterPoly)
|
||||||
|
{
|
||||||
|
lightmap.Reset(Vector3.One * 255f, settings.Hdr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
lightmap.Reset(settings.AmbientLight, settings.Hdr);
|
lightmap.Reset(settings.AmbientLight, settings.Hdr);
|
||||||
|
|
||||||
// Get world position of lightmap (0, 0) (+0.5 so we cast from the center of a pixel)
|
// Get world position of lightmap (0, 0) (+0.5 so we cast from the center of a pixel)
|
||||||
|
@ -598,13 +631,23 @@ public class LightMapper
|
||||||
|
|
||||||
private bool TraceRay(Vector3 origin, Vector3 target)
|
private bool TraceRay(Vector3 origin, Vector3 target)
|
||||||
{
|
{
|
||||||
var direction = target - origin;
|
var hitDistanceFromTarget = float.MinValue;
|
||||||
var hitResult = _scene.Trace(new Ray
|
var hitSurfaceType = SurfaceType.Water;
|
||||||
|
while (hitDistanceFromTarget < -MathUtils.Epsilon && hitSurfaceType == SurfaceType.Water)
|
||||||
{
|
{
|
||||||
Origin = origin,
|
var direction = target - origin;
|
||||||
Direction = Vector3.Normalize(direction),
|
var hitResult = _scene.Trace(new Ray
|
||||||
});
|
{
|
||||||
return hitResult && Math.Abs(hitResult.Distance - direction.Length()) < MathUtils.Epsilon;
|
Origin = origin,
|
||||||
|
Direction = Vector3.Normalize(direction),
|
||||||
|
});
|
||||||
|
|
||||||
|
hitDistanceFromTarget = hitResult.Distance - direction.Length();
|
||||||
|
hitSurfaceType = _triangleTypeMap[(int)hitResult.PrimId];
|
||||||
|
origin = hitResult.Position += direction * MathUtils.Epsilon;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.Abs(hitDistanceFromTarget) < MathUtils.Epsilon;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetAnimLightCellMaps()
|
private void SetAnimLightCellMaps()
|
||||||
|
|
Loading…
Reference in New Issue