Compare commits

..

No commits in common. "3a445ef6d8a71252d6ed56b4d224091db5ce6dc3" and "4bc55b913097200655ff58efdd7a12b7469d7eaa" have entirely different histories.

3 changed files with 42 additions and 93 deletions

View File

@ -142,8 +142,6 @@ public class DbFile
"P$OTxtRepr1" => new PropertyChunk<PropString>(), "P$OTxtRepr1" => new PropertyChunk<PropString>(),
"P$OTxtRepr2" => new PropertyChunk<PropString>(), "P$OTxtRepr2" => new PropertyChunk<PropString>(),
"P$OTxtRepr3" => new PropertyChunk<PropString>(), "P$OTxtRepr3" => new PropertyChunk<PropString>(),
"P$Light" => new PropertyChunk<PropLight>(),
"P$LightColo" => new PropertyChunk<PropLightColor>(),
"P$RenderAlp" => new PropertyChunk<PropFloat>(), "P$RenderAlp" => new PropertyChunk<PropFloat>(),
"LD$MetaProp" => new LinkDataMetaProp(), "LD$MetaProp" => new LinkDataMetaProp(),
_ when entryName.StartsWith("L$") => new LinkChunk(), _ when entryName.StartsWith("L$") => new LinkChunk(),

View File

@ -99,8 +99,6 @@ public class ObjectHierarchy
AddProp<PropString>("P$OTxtRepr2"); AddProp<PropString>("P$OTxtRepr2");
AddProp<PropString>("P$OTxtRepr3"); AddProp<PropString>("P$OTxtRepr3");
AddProp<PropFloat>("P$RenderAlp"); AddProp<PropFloat>("P$RenderAlp");
AddProp<PropLight>("P$Light");
AddProp<PropLightColor>("P$LightColo");
} }
public T GetProperty<T>(int objectId, string propName) where T : Property public T GetProperty<T>(int objectId, string propName) where T : Property

View File

@ -13,7 +13,6 @@ class Program
public Vector3 position; public Vector3 position;
public Vector3 color; public Vector3 color;
public float radius; public float radius;
public float r2;
} }
static void Main(string[] args) static void Main(string[] args)
@ -35,35 +34,13 @@ class Program
lights.Add(new Light lights.Add(new Light
{ {
position = brush.position, position = brush.position,
color = HsbToRgb(sz.Y, sz.Z, Math.Min(sz.X, 255.0f)), color = HsbToRgb(360 * sz.Y, sz.Z, Math.Min(sz.X, 255.0f)),
radius = float.MaxValue, radius = float.MaxValue
r2 = float.MaxValue
}); });
} }
else if (brush.media == BrList.Brush.Media.Object)
{
var id = (int)brush.brushInfo;
var light = hierarchy.GetProperty<PropLight>(id, "P$Light");
var lightColor = hierarchy.GetProperty<PropLightColor>(id, "P$LightColo");
if (light != null)
{
lightColor ??= new PropLightColor { Hue = 0, Saturation = 0 };
lights.Add(new Light
{
position = brush.position,
color = HsbToRgb(lightColor.Hue, lightColor.Saturation, light.Brightness),
radius = light.Radius,
r2 = light.Radius * light.Radius,
});
}
else
{
Console.WriteLine($"no light prop apparently");
}
}
} }
// TODO: object lights
} }
// Build embree mesh // Build embree mesh
@ -83,15 +60,12 @@ class Program
var dir = Path.GetDirectoryName(misPath); var dir = Path.GetDirectoryName(misPath);
var filename = Path.GetFileNameWithoutExtension(misPath); var filename = Path.GetFileNameWithoutExtension(misPath);
mis.Save(Path.Join(dir, $"{filename}-lit.cow")); mis.Save(Path.Join(dir, $"{filename}-lit.cow"));
Console.WriteLine($"Lit {lights.Count} light");
} }
// Expects Hue and Saturation are 0-1, Brightness 0-255 // Expects Hue to be 0-360, saturation 0-1, brightness 0-255
// https://en.wikipedia.org/wiki/HSL_and_HSV#HSV_to_RGB // https://en.wikipedia.org/wiki/HSL_and_HSV#HSV_to_RGB
private static Vector3 HsbToRgb(float hue, float saturation, float brightness) private static Vector3 HsbToRgb(float hue, float saturation, float brightness)
{ {
hue *= 360;
var hi = Convert.ToInt32(Math.Floor(hue / 60)) % 6; var hi = Convert.ToInt32(Math.Floor(hue / 60)) % 6;
var f = hue / 60 - Math.Floor(hue / 60); var f = hue / 60 - Math.Floor(hue / 60);
@ -166,6 +140,7 @@ class Program
for (var j = 0; j < numPolyVertices; j++) for (var j = 0; j < numPolyVertices; j++)
{ {
var vertex = cell.Vertices[cell.Indices[cellIdxOffset + j]]; var vertex = cell.Vertices[cell.Indices[cellIdxOffset + j]];
// Console.WriteLine($"Cell: {cellIdx}, Poly: {polyIdx}, V: {j}, Vert: {vertex}");
vertices.Add(vertex); vertices.Add(vertex);
} }
@ -188,22 +163,18 @@ class Program
var cells = wr.Cells; var cells = wr.Cells;
for (var cellIdx = 0; cellIdx < cells.Length; cellIdx++) for (var cellIdx = 0; cellIdx < cells.Length; cellIdx++)
{ {
Console.Write($"\rLighting cell... {cellIdx + 1}/{cells.Length}\n");
var cell = cells[cellIdx]; var cell = cells[cellIdx];
var numPolys = cell.PolyCount; var numPolys = cell.PolyCount;
var numRenderPolys = cell.RenderPolyCount; var numRenderPolys = cell.RenderPolyCount;
var numPortalPolys = cell.PortalPolyCount; var numPortalPolys = cell.PortalPolyCount;
// There's nothing to render // There's nothing to render
// Portal polys can be render polys (e.g. water) but we're ignoring them for now
if (numRenderPolys == 0 || numPortalPolys >= numPolys) if (numRenderPolys == 0 || numPortalPolys >= numPolys)
{ {
continue; continue;
} }
var maxPolyIdx = Math.Min(numRenderPolys, numPolys - numPortalPolys); var maxPolyIdx = Math.Min(numRenderPolys, numPolys - numPortalPolys);
var cellIdxOffset = 0;
for (int polyIdx = 0; polyIdx < maxPolyIdx; polyIdx++) for (int polyIdx = 0; polyIdx < maxPolyIdx; polyIdx++)
{ {
var poly = cell.Polys[polyIdx]; var poly = cell.Polys[polyIdx];
@ -212,78 +183,60 @@ 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); // Clear existing lightmap data
for (var i = 0; i < lightmap.Pixels.Length; i++)
{
lightmap.Pixels[i] = 0;
}
// Get world position of lightmap (0, 0) (+0.5 so we cast from the center of a pixel) for (var y = 0; y < lightmap.Height; y++)
var topLeft = cell.Vertices[cell.Indices[cellIdxOffset]]; {
topLeft -= renderPoly.TextureVectors.Item1 * (renderPoly.TextureBases.Item1 - info.Bases.Item1 * 0.25f); for (var x = 0; x < lightmap.Width; x++)
topLeft -= renderPoly.TextureVectors.Item2 * (renderPoly.TextureBases.Item2 - info.Bases.Item2 * 0.25f); {
lightmap.AddLight(0, x, y, (byte)ambientLight.X, (byte)ambientLight.Y, (byte)ambientLight.Z);
}
}
foreach (var light in lights) foreach (var light in lights)
{ {
Console.WriteLine("Doing a light...");
// Check if plane normal is facing towards the light // Check if plane normal is facing towards the light
// If it's not then we're never going to be (directly) lit by this var direction = renderPoly.Center - light.position;
// light. Console.WriteLine($"Light Pos: {light.position}, poly center: {renderPoly.Center}");
var centerDirection = renderPoly.Center - light.position; Console.WriteLine($"Dir: {direction}");
if (Vector3.Dot(plane.Normal, centerDirection) >= 0) // if (Vector3.Dot(plane.Normal, direction) < 0)
{ {
continue; // Cast from the light to the center (later each pixel)
} var hit = scene.Trace(new Ray
for (var y = 0; y < lightmap.Height; y++)
{
for (var x = 0; x < lightmap.Width; x++)
{ {
var pos = topLeft; Origin = light.position,
pos += x * 0.25f * renderPoly.TextureVectors.Item1; Direction = Vector3.Normalize(direction)
pos += y * 0.25f * renderPoly.TextureVectors.Item2; });
// If we're out of range there's no point casting a ray // cheeky epsilon
// There's probably a better way to discard the entire lightmap var goodHit = hit && Math.Abs(hit.Distance - direction.Length()) < 0.001;
// if we're massively out of range Console.WriteLine($"Did we hit? {goodHit}");
var direction = pos - light.position; Console.WriteLine($"Distance: {hit.Distance}, target dist: {direction.Length()}");
if (direction.LengthSquared() > light.r2) Console.WriteLine($"Pos: {hit.Position}, Target Pos: {renderPoly.Center}");
{
continue;
}
// We cast from the light to the pixel because the light has // Iterate all pixels
// no mesh in the scene to hit var color = goodHit ? light.color : ambientLight;
var hitResult = scene.Trace(new Ray for (var y = 0; y < lightmap.Height; y++)
{
for (var x = 0; x < lightmap.Width; x++)
{ {
Origin = light.position, lightmap.AddLight(0, x, y, (byte)color.X, (byte)color.Y, (byte)color.Z);
Direction = Vector3.Normalize(direction),
});
// cheeky epsilon
var hit = hitResult && Math.Abs(hitResult.Distance - direction.Length()) < 0.001;
if (hit)
{
lightmap.AddLight(0, x, y, (byte)light.color.X, (byte)light.color.Y, (byte)light.color.Z);
} }
} }
} }
} }
cellIdxOffset += poly.VertexCount;
}
}
Console.Write("\n"); // // TODO: Get world position of each pixel?
}
private static void ResetLightmap(Vector3 ambientLight, WorldRep.Cell.Lightmap lightmap) // var poly = cell.Polys[polyIdx];
{
for (var i = 0; i < lightmap.Pixels.Length; i++)
{
lightmap.Pixels[i] = 0;
}
for (var y = 0; y < lightmap.Height; y++) // poly.
{
for (var x = 0; x < lightmap.Width; x++)
{
lightmap.AddLight(0, x, y, (byte)ambientLight.X, (byte)ambientLight.Y, (byte)ambientLight.Z);
} }
} }
} }