Compare commits

..

No commits in common. "196e97a8fdfed3c3bfbeefcd7573c3a651b1efdb" and "ce7002477e94451bda3434984a4ab87a4beebbc7" have entirely different histories.

2 changed files with 56 additions and 90 deletions

View File

@ -4,8 +4,6 @@ namespace KeepersCompound.Lightmapper;
public static class MathUtils public static class MathUtils
{ {
public const float Epsilon = 0.001f;
public readonly struct Aabb public readonly struct Aabb
{ {
public readonly Vector3 Min; public readonly Vector3 Min;
@ -54,76 +52,64 @@ public static class MathUtils
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();
} }
public record PlanePointMapper /// <summary>
/// Expects poly to be convex. Given a point
/// </summary>
public static Vector3 ClipPointToPoly3d(Vector3 point, Vector3[] vertices, Plane projectionPlane)
{ {
Vector3 _origin; // Shouldn't need to pass 3d. We can just pass the luxel coord, and then we only need the
Vector3 _xAxis;
Vector3 _yAxis;
public PlanePointMapper(Vector3 normal, Vector3 p0, Vector3 p1) var (p2d, v2ds) = LocalPlaneCoords(point, vertices, projectionPlane);
// !HACK: Replace this shit
var origin = vertices[0];
var locX = vertices[1] - origin;
var locY = Vector3.Cross(projectionPlane.Normal, locX);
locX = Vector3.Normalize(locX);
locY = Vector3.Normalize(locY);
var inside = true;
for (var i = 0; i < v2ds.Length; i++)
{ {
_origin = p0; var a = v2ds[i];
_xAxis = p1 - _origin; var b = v2ds[(i + 1) % v2ds.Length];
_yAxis = Vector3.Cross(normal, _xAxis);
_xAxis = Vector3.Normalize(_xAxis);
_yAxis = Vector3.Normalize(_yAxis);
}
public Vector2 MapTo2d(Vector3 point)
{
var offset = point - _origin;
var x = Vector3.Dot(offset, _xAxis);
var y = Vector3.Dot(offset, _yAxis);
return new Vector2(x, y);
}
public Vector2[] MapTo2d(Vector3[] points)
{
var points2d = new Vector2[points.Length];
for (var i = 0; i < points.Length; i++)
{
points2d[i] = MapTo2d(points[i]);
}
return points2d;
}
public Vector3 MapTo3d(Vector2 point)
{
return _origin + point.X * _xAxis + point.Y * _yAxis;
}
public Vector3[] MapTo3d(Vector2[] points)
{
var points3d = new Vector3[points.Length];
for (var i = 0; i < points.Length; i++)
{
points3d[i] = MapTo3d(points[i]);
}
return points3d;
}
}
public static Vector2 ClipPointToPoly2d(Vector2 point, Vector2[] vertices)
{
var vertexCount = vertices.Length;
for (var i = 0; i < vertexCount; i++)
{
var a = vertices[i];
var b = vertices[(i + 1) % vertexCount];
var segment = b - a; var segment = b - a;
var offset = point - a; var offset = p2d - a;
var norm = Vector2.Normalize(new Vector2(-segment.Y, segment.X)); var norm = Vector2.Normalize(new Vector2(-segment.Y, segment.X));
var side = Vector2.Dot(norm, offset); var side = Vector2.Dot(norm, offset);
if (side >= -Epsilon) if (side >= -0.001)
{ {
// We apply epsilon so that we push slightly into the poly. If we only p2d -= norm * (side + 0.0015f);
// push to the edge then Embree sometimes misses casts. The reason inside = false;
// it's 2 epsilon is so Side == -Epsilon still gets pushed in properly
point -= norm * (side + 2 * Epsilon);
} }
} }
return point; // return p2d;
return origin + p2d.X * locX + p2d.Y * locY;
// return Vector3.One;
}
// TODO: Only do this once per poly
public static (Vector2, Vector2[]) LocalPlaneCoords(Vector3 point, Vector3[] ps, Plane plane)
{
var origin = ps[0];
var locX = ps[1] - origin;
var locY = Vector3.Cross(plane.Normal, locX);
locX = Vector3.Normalize(locX);
locY = Vector3.Normalize(locY);
var offset = point - origin;
var p2d = new Vector2(Vector3.Dot(offset, locX), Vector3.Dot(offset, locY));
var p2ds = new Vector2[ps.Length];
for (var i = 0; i < ps.Length; i++)
{
var p = ps[i] - origin;
p2ds[i] = new Vector2(Vector3.Dot(p, locX), Vector3.Dot(p, locY));
}
return (p2d, p2ds);
} }
} }

View File

@ -22,7 +22,7 @@ class Program
Timing.Reset(); Timing.Reset();
var misPath = "/stuff/Games/thief/drive_c/GOG Games/TG ND 1.27 (MAPPING)/FMs/JAYRUDE_Tests/lm_test.cow"; var misPath = "/stuff/Games/thief/drive_c/GOG Games/TG ND 1.27 (MAPPING)/FMs/JAYRUDE_Tests/lm_test.cow";
// misPath = "/stuff/Games/thief/drive_c/GOG Games/TG ND 1.27 (MAPPING)/FMs/AtdV/miss20.mis"; misPath = "/stuff/Games/thief/drive_c/GOG Games/TG ND 1.27 (MAPPING)/FMs/AtdV/miss20.mis";
misPath = "/stuff/Games/thief/drive_c/GOG Games/TG ND 1.27 (MAPPING)/FMs/TDP20AC_a_burrick_in_a_room/miss20.mis"; misPath = "/stuff/Games/thief/drive_c/GOG Games/TG ND 1.27 (MAPPING)/FMs/TDP20AC_a_burrick_in_a_room/miss20.mis";
Timing.TimeStage("Total", () => LightmapMission(misPath)); Timing.TimeStage("Total", () => LightmapMission(misPath));
@ -117,11 +117,9 @@ class Program
{ {
propLightColor ??= new PropLightColor { Hue = 0, Saturation = 0 }; propLightColor ??= new PropLightColor { Hue = 0, Saturation = 0 };
// TODO: There's still some lights that aren't positioned right such as Streetlamp.
// Perhaps there's a light point specified in model files?
var light = new Light var light = new Light
{ {
position = brush.position + propLight.Offset, position = brush.position,
color = HsbToRgb(propLightColor.Hue, propLightColor.Saturation, propLight.Brightness), color = HsbToRgb(propLightColor.Hue, propLightColor.Saturation, propLight.Brightness),
radius = propLight.Radius, radius = propLight.Radius,
r2 = propLight.Radius * propLight.Radius, r2 = propLight.Radius * propLight.Radius,
@ -245,7 +243,7 @@ class Program
var info = cell.LightList[polyIdx]; var info = cell.LightList[polyIdx];
var lightmap = cell.Lightmaps[polyIdx]; var lightmap = cell.Lightmaps[polyIdx];
ResetLightmap(ambientLight, lightmap, hdr); ResetLightmap(ambientLight, lightmap);
// 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)
var topLeft = cell.Vertices[cell.Indices[cellIdxOffset]]; var topLeft = cell.Vertices[cell.Indices[cellIdxOffset]];
@ -267,8 +265,6 @@ class Program
{ {
vs[i] = cell.Vertices[cell.Indices[cellIdxOffset + i]]; vs[i] = cell.Vertices[cell.Indices[cellIdxOffset + i]];
} }
var planeMapper = new MathUtils.PlanePointMapper(plane.Normal, vs[0], vs[1]);
var v2ds = planeMapper.MapTo2d(vs);
foreach (var light in lights) foreach (var light in lights)
{ {
@ -305,17 +301,7 @@ class Program
pos += x * 0.25f * renderPoly.TextureVectors.Item1; pos += x * 0.25f * renderPoly.TextureVectors.Item1;
pos += y * 0.25f * renderPoly.TextureVectors.Item2; pos += y * 0.25f * renderPoly.TextureVectors.Item2;
// We need to clip the point to slightly inside of the poly pos = MathUtils.ClipPointToPoly3d(pos, vs, plane);
// to avoid three problems:
// 1. Darkened spots from lightmap pixels who's center is outside
// of the polygon but is partially contained in the polygon
// 2. Darkened spots from linear filtering of points outside of the
// polygon which have missed
// 3. Darkened spots where centers are on the exact edge of a poly
// which can sometimes cause Embree to miss casts
var p2d = planeMapper.MapTo2d(pos);
p2d = MathUtils.ClipPointToPoly2d(p2d, v2ds);
pos = planeMapper.MapTo3d(p2d);
// If we're out of range there's no point casting a ray // If we're out of range there's no point casting a ray
// There's probably a better way to discard the entire lightmap // There's probably a better way to discard the entire lightmap
@ -336,7 +322,7 @@ class Program
// cheeky epsilon // cheeky epsilon
// TODO: Some pixels aren't hitting and I'm not sure why // TODO: Some pixels aren't hitting and I'm not sure why
var hit = hitResult && Math.Abs(hitResult.Distance - direction.Length()) < MathUtils.Epsilon; var hit = hitResult && Math.Abs(hitResult.Distance - direction.Length()) < 0.001;
if (hit) if (hit)
{ {
// Calculate light strength at a given point. As far as I can tell // Calculate light strength at a given point. As far as I can tell
@ -381,24 +367,18 @@ class Program
Console.Write("\n"); Console.Write("\n");
} }
private static void ResetLightmap(Vector3 ambientLight, WorldRep.Cell.Lightmap lightmap, bool hdr) private static void ResetLightmap(Vector3 ambientLight, WorldRep.Cell.Lightmap lightmap)
{ {
for (var i = 0; i < lightmap.Pixels.Length; i++) for (var i = 0; i < lightmap.Pixels.Length; i++)
{ {
lightmap.Pixels[i] = 0; lightmap.Pixels[i] = 0;
} }
var c = ambientLight;
if (hdr)
{
c /= 2.0f;
}
for (var y = 0; y < lightmap.Height; y++) for (var y = 0; y < lightmap.Height; y++)
{ {
for (var x = 0; x < lightmap.Width; x++) for (var x = 0; x < lightmap.Width; x++)
{ {
lightmap.AddLight(0, x, y, (byte)c.X, (byte)c.Y, (byte)c.Z); lightmap.AddLight(0, x, y, (byte)ambientLight.X, (byte)ambientLight.Y, (byte)ambientLight.Z);
} }
} }
} }