Add model vhots and model light offset/dir
This commit is contained in:
parent
2420bbef4f
commit
d7fcf7a2d8
|
@ -153,6 +153,30 @@ public class ModelFile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum VhotId
|
||||||
|
{
|
||||||
|
LightPosition = 1,
|
||||||
|
LightDirection = 8,
|
||||||
|
Anchor = 2,
|
||||||
|
Particle1 = 3,
|
||||||
|
Particle2 = 4,
|
||||||
|
Particle3 = 5,
|
||||||
|
Particle4 = 6,
|
||||||
|
Particle5 = 7,
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct VHot
|
||||||
|
{
|
||||||
|
public int Id;
|
||||||
|
public Vector3 Position;
|
||||||
|
|
||||||
|
public VHot(BinaryReader reader)
|
||||||
|
{
|
||||||
|
Id = reader.ReadInt32();
|
||||||
|
Position = reader.ReadVec3();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public BHeader BinHeader { get; set; }
|
public BHeader BinHeader { get; set; }
|
||||||
public MHeader Header { get; set; }
|
public MHeader Header { get; set; }
|
||||||
public Vector3[] Vertices { get; }
|
public Vector3[] Vertices { get; }
|
||||||
|
@ -160,6 +184,7 @@ public class ModelFile
|
||||||
public Vector3[] Normals { get; }
|
public Vector3[] Normals { get; }
|
||||||
public Polygon[] Polygons { get; }
|
public Polygon[] Polygons { get; }
|
||||||
public Material[] Materials { get; }
|
public Material[] Materials { get; }
|
||||||
|
public VHot[] VHots { get; }
|
||||||
|
|
||||||
public ModelFile(string filename)
|
public ModelFile(string filename)
|
||||||
{
|
{
|
||||||
|
@ -202,5 +227,25 @@ public class ModelFile
|
||||||
{
|
{
|
||||||
Materials[i] = new Material(reader);
|
Materials[i] = new Material(reader);
|
||||||
}
|
}
|
||||||
|
stream.Seek(Header.VHotOffset, SeekOrigin.Begin);
|
||||||
|
VHots = new VHot[Header.VHotCount];
|
||||||
|
for (var i = 0; i < VHots.Length; i++)
|
||||||
|
{
|
||||||
|
VHots[i] = new VHot(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetVhot(VhotId id, out VHot vhot)
|
||||||
|
{
|
||||||
|
foreach (var v in VHots)
|
||||||
|
{
|
||||||
|
if (v.Id == (int)id)
|
||||||
|
{
|
||||||
|
vhot = v;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vhot = new VHot();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
using KeepersCompound.LGS;
|
||||||
using KeepersCompound.LGS.Database;
|
using KeepersCompound.LGS.Database;
|
||||||
using KeepersCompound.LGS.Database.Chunks;
|
using KeepersCompound.LGS.Database.Chunks;
|
||||||
using TinyEmbree;
|
using TinyEmbree;
|
||||||
|
@ -27,20 +28,34 @@ 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";
|
// TODO: Read this from args
|
||||||
|
var installPath = "/stuff/Games/thief/drive_c/GOG Games/TG ND 1.27 (MAPPING)/";
|
||||||
|
var campaignName = "JAYRUDE_Tests";
|
||||||
|
var missionName = "lm_test.cow";
|
||||||
|
|
||||||
|
// Setup extract path
|
||||||
|
var tmpDir = Directory.CreateTempSubdirectory("KCLightmapper");
|
||||||
|
Console.WriteLine(tmpDir.FullName);
|
||||||
|
var resPathManager = new ResourcePathManager(tmpDir.FullName);
|
||||||
|
resPathManager.Init(installPath);
|
||||||
|
|
||||||
|
var campaign = resPathManager.GetCampaign(campaignName);
|
||||||
|
var misPath = campaign.GetResourcePath(ResourceType.Mission, missionName);
|
||||||
|
|
||||||
|
// 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(campaign, misPath));
|
||||||
|
|
||||||
Timing.LogAll();
|
Timing.LogAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void LightmapMission(string misPath)
|
private static void LightmapMission(ResourcePathManager.CampaignResources campaign, string misPath)
|
||||||
{
|
{
|
||||||
var mis = Timing.TimeStage("Parse DB", () => new DbFile(misPath));
|
var mis = Timing.TimeStage("Parse DB", () => new DbFile(misPath));
|
||||||
var hierarchy = Timing.TimeStage("Build Hierarchy", () => BuildHierarchy(misPath, mis));
|
var hierarchy = Timing.TimeStage("Build Hierarchy", () => BuildHierarchy(misPath, mis));
|
||||||
|
|
||||||
var lights = Timing.TimeStage("Gather Lights", () => BuildLightList(mis, hierarchy));
|
var lights = Timing.TimeStage("Gather Lights", () => BuildLightList(mis, hierarchy, campaign));
|
||||||
|
|
||||||
// Build embree mesh
|
// Build embree mesh
|
||||||
if (!mis.Chunks.TryGetValue("WREXT", out var wrRaw))
|
if (!mis.Chunks.TryGetValue("WREXT", out var wrRaw))
|
||||||
|
@ -93,7 +108,7 @@ class Program
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get list of brush lights, and object lights (ignore anim lights for now)
|
// Get list of brush lights, and object lights (ignore anim lights for now)
|
||||||
private static List<Light> BuildLightList(DbFile mis, ObjectHierarchy hierarchy)
|
private static List<Light> BuildLightList(DbFile mis, ObjectHierarchy hierarchy, ResourcePathManager.CampaignResources campaign)
|
||||||
{
|
{
|
||||||
var lights = new List<Light>();
|
var lights = new List<Light>();
|
||||||
|
|
||||||
|
@ -120,6 +135,7 @@ class Program
|
||||||
var propLight = hierarchy.GetProperty<PropLight>(id, "P$Light");
|
var propLight = hierarchy.GetProperty<PropLight>(id, "P$Light");
|
||||||
var propLightColor = hierarchy.GetProperty<PropLightColor>(id, "P$LightColo");
|
var propLightColor = hierarchy.GetProperty<PropLightColor>(id, "P$LightColo");
|
||||||
var propSpotlight = hierarchy.GetProperty<PropSpotlight>(id, "P$Spotlight");
|
var propSpotlight = hierarchy.GetProperty<PropSpotlight>(id, "P$Spotlight");
|
||||||
|
var propModelname = hierarchy.GetProperty<PropLabel>(id, "P$ModelName");
|
||||||
|
|
||||||
if (propLight != null)
|
if (propLight != null)
|
||||||
{
|
{
|
||||||
|
@ -134,8 +150,24 @@ class Program
|
||||||
innerRadius = propLight.InnerRadius,
|
innerRadius = propLight.InnerRadius,
|
||||||
radius = propLight.Radius,
|
radius = propLight.Radius,
|
||||||
r2 = propLight.Radius * propLight.Radius,
|
r2 = propLight.Radius * propLight.Radius,
|
||||||
|
spotlightDir = -Vector3.UnitZ,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (propModelname != null)
|
||||||
|
{
|
||||||
|
var resName = $"{propModelname.value.ToLower()}.bin";
|
||||||
|
var modelPath = campaign.GetResourcePath(ResourceType.Object, resName);
|
||||||
|
var model = new ModelFile(modelPath);
|
||||||
|
if (model.TryGetVhot(ModelFile.VhotId.LightPosition, out var vhot))
|
||||||
|
{
|
||||||
|
light.position += vhot.Position;
|
||||||
|
}
|
||||||
|
if (model.TryGetVhot(ModelFile.VhotId.LightDirection, out vhot))
|
||||||
|
{
|
||||||
|
light.spotlightDir = vhot.Position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (propSpotlight != null)
|
if (propSpotlight != null)
|
||||||
{
|
{
|
||||||
// TODO: Some objects seem to have spotlight direction embedded in the model file
|
// TODO: Some objects seem to have spotlight direction embedded in the model file
|
||||||
|
@ -145,7 +177,7 @@ class Program
|
||||||
rot *= Matrix4x4.CreateRotationZ(float.DegreesToRadians(brush.angle.Z));
|
rot *= Matrix4x4.CreateRotationZ(float.DegreesToRadians(brush.angle.Z));
|
||||||
|
|
||||||
light.spotlight = true;
|
light.spotlight = true;
|
||||||
light.spotlightDir = Vector3.Transform(-Vector3.UnitZ, rot);
|
light.spotlightDir = Vector3.Transform(light.spotlightDir, rot);
|
||||||
light.spotlightInnerAngle = (float)Math.Cos(float.DegreesToRadians(propSpotlight.InnerAngle));
|
light.spotlightInnerAngle = (float)Math.Cos(float.DegreesToRadians(propSpotlight.InnerAngle));
|
||||||
light.spotlightOuterAngle = (float)Math.Cos(float.DegreesToRadians(propSpotlight.OuterAngle));
|
light.spotlightOuterAngle = (float)Math.Cos(float.DegreesToRadians(propSpotlight.OuterAngle));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue