Add RendParams and writers for each chunk
This commit is contained in:
parent
cf7ad880fb
commit
4bc55b9130
|
@ -46,6 +46,15 @@ public class BrList : IChunk
|
||||||
x = reader.ReadUInt16();
|
x = reader.ReadUInt16();
|
||||||
y = reader.ReadUInt16();
|
y = reader.ReadUInt16();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
writer.Write(id);
|
||||||
|
writer.Write(rot);
|
||||||
|
writer.Write(scale);
|
||||||
|
writer.Write(x);
|
||||||
|
writer.Write(y);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public short id;
|
public short id;
|
||||||
|
@ -104,6 +113,34 @@ public class BrList : IChunk
|
||||||
txs = Array.Empty<TexInfo>();
|
txs = Array.Empty<TexInfo>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
writer.Write(id);
|
||||||
|
writer.Write(time);
|
||||||
|
writer.Write(brushInfo);
|
||||||
|
writer.Write(textureId);
|
||||||
|
writer.Write((byte)media);
|
||||||
|
writer.Write(flags);
|
||||||
|
writer.WriteVec3(position);
|
||||||
|
writer.WriteVec3(size);
|
||||||
|
writer.WriteRotation(angle);
|
||||||
|
writer.Write(currentFaceIndex);
|
||||||
|
writer.Write(gridLineSpacing);
|
||||||
|
writer.WriteVec3(gridPhaseShift);
|
||||||
|
writer.WriteRotation(gridOrientation);
|
||||||
|
writer.Write(gridEnabled);
|
||||||
|
writer.Write(numFaces);
|
||||||
|
writer.Write(edgeSelected);
|
||||||
|
writer.Write(pointSelected);
|
||||||
|
writer.Write(useFlag);
|
||||||
|
writer.Write(groupId);
|
||||||
|
writer.Write(new byte[4]);
|
||||||
|
foreach (var info in txs)
|
||||||
|
{
|
||||||
|
info.Write(writer);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChunkHeader Header { get; set; }
|
public ChunkHeader Header { get; set; }
|
||||||
|
@ -120,6 +157,9 @@ public class BrList : IChunk
|
||||||
|
|
||||||
public void WriteData(BinaryWriter writer)
|
public void WriteData(BinaryWriter writer)
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
foreach (var brush in Brushes)
|
||||||
|
{
|
||||||
|
brush.Write(writer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,3 @@
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace KeepersCompound.LGS.Database.Chunks;
|
namespace KeepersCompound.LGS.Database.Chunks;
|
||||||
|
|
||||||
public class GamFile : IChunk
|
public class GamFile : IChunk
|
||||||
|
@ -16,6 +12,6 @@ public class GamFile : IChunk
|
||||||
|
|
||||||
public void WriteData(BinaryWriter writer)
|
public void WriteData(BinaryWriter writer)
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
writer.WriteNullString(fileName, 256);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -32,6 +32,11 @@ public record LinkId
|
||||||
{
|
{
|
||||||
return _data;
|
return _data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
writer.Write(_data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LinkChunk : IChunk, IMergable
|
public class LinkChunk : IChunk, IMergable
|
||||||
|
@ -50,6 +55,14 @@ public class LinkChunk : IChunk, IMergable
|
||||||
destination = reader.ReadInt32();
|
destination = reader.ReadInt32();
|
||||||
relation = reader.ReadUInt16();
|
relation = reader.ReadUInt16();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
linkId.Write(writer);
|
||||||
|
writer.Write(source);
|
||||||
|
writer.Write(destination);
|
||||||
|
writer.Write(relation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChunkHeader Header { get; set; }
|
public ChunkHeader Header { get; set; }
|
||||||
|
@ -66,7 +79,10 @@ public class LinkChunk : IChunk, IMergable
|
||||||
|
|
||||||
public void WriteData(BinaryWriter writer)
|
public void WriteData(BinaryWriter writer)
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
foreach (var link in links)
|
||||||
|
{
|
||||||
|
link.Write(writer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Merge(IMergable other)
|
public void Merge(IMergable other)
|
||||||
|
@ -88,6 +104,12 @@ public class LinkDataMetaProp : IChunk, IMergable
|
||||||
linkId = new LinkId(reader.ReadUInt32());
|
linkId = new LinkId(reader.ReadUInt32());
|
||||||
priority = reader.ReadInt32();
|
priority = reader.ReadInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
linkId.Write(writer);
|
||||||
|
writer.Write(priority);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChunkHeader Header { get; set; }
|
public ChunkHeader Header { get; set; }
|
||||||
|
@ -106,7 +128,11 @@ public class LinkDataMetaProp : IChunk, IMergable
|
||||||
|
|
||||||
public void WriteData(BinaryWriter writer)
|
public void WriteData(BinaryWriter writer)
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
writer.Write(DataSize);
|
||||||
|
foreach (var data in linkData)
|
||||||
|
{
|
||||||
|
data.Write(writer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Merge(IMergable other)
|
public void Merge(IMergable other)
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
namespace KeepersCompound.LGS.Database.Chunks;
|
namespace KeepersCompound.LGS.Database.Chunks;
|
||||||
|
@ -14,6 +12,12 @@ public class Property
|
||||||
objectId = reader.ReadInt32();
|
objectId = reader.ReadInt32();
|
||||||
length = (int)reader.ReadUInt32();
|
length = (int)reader.ReadUInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
writer.Write(objectId);
|
||||||
|
writer.Write((uint)length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PropertyChunk<T> : IChunk, IMergable where T : Property, new()
|
public class PropertyChunk<T> : IChunk, IMergable where T : Property, new()
|
||||||
|
@ -34,7 +38,10 @@ public class PropertyChunk<T> : IChunk, IMergable where T : Property, new()
|
||||||
|
|
||||||
public void WriteData(BinaryWriter writer)
|
public void WriteData(BinaryWriter writer)
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
foreach (var prop in properties)
|
||||||
|
{
|
||||||
|
prop.Write(writer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Merge(IMergable other)
|
public void Merge(IMergable other)
|
||||||
|
@ -52,6 +59,12 @@ public class PropGeneric : Property
|
||||||
base.Read(reader);
|
base.Read(reader);
|
||||||
data = reader.ReadBytes(length);
|
data = reader.ReadBytes(length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
base.Write(writer);
|
||||||
|
writer.Write(data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PropBool : Property
|
public class PropBool : Property
|
||||||
|
@ -63,6 +76,12 @@ public class PropBool : Property
|
||||||
base.Read(reader);
|
base.Read(reader);
|
||||||
value = reader.ReadInt32() != 0;
|
value = reader.ReadInt32() != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
base.Write(writer);
|
||||||
|
writer.Write(value ? 1 : 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PropInt : Property
|
public class PropInt : Property
|
||||||
|
@ -74,6 +93,12 @@ public class PropInt : Property
|
||||||
base.Read(reader);
|
base.Read(reader);
|
||||||
value = reader.ReadInt32();
|
value = reader.ReadInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
base.Write(writer);
|
||||||
|
writer.Write(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PropLabel : Property
|
public class PropLabel : Property
|
||||||
|
@ -85,6 +110,12 @@ public class PropLabel : Property
|
||||||
base.Read(reader);
|
base.Read(reader);
|
||||||
value = reader.ReadNullString(length);
|
value = reader.ReadNullString(length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
base.Write(writer);
|
||||||
|
writer.WriteNullString(value, length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PropString : Property
|
public class PropString : Property
|
||||||
|
@ -98,6 +129,13 @@ public class PropString : Property
|
||||||
stringLength = reader.ReadInt32();
|
stringLength = reader.ReadInt32();
|
||||||
value = reader.ReadNullString(stringLength);
|
value = reader.ReadNullString(stringLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
base.Write(writer);
|
||||||
|
writer.Write(stringLength);
|
||||||
|
writer.WriteNullString(value, stringLength);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PropFloat : Property
|
public class PropFloat : Property
|
||||||
|
@ -109,6 +147,12 @@ public class PropFloat : Property
|
||||||
base.Read(reader);
|
base.Read(reader);
|
||||||
value = reader.ReadSingle();
|
value = reader.ReadSingle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
base.Write(writer);
|
||||||
|
writer.Write(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PropVector : Property
|
public class PropVector : Property
|
||||||
|
@ -120,6 +164,12 @@ public class PropVector : Property
|
||||||
base.Read(reader);
|
base.Read(reader);
|
||||||
value = reader.ReadVec3();
|
value = reader.ReadVec3();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
base.Write(writer);
|
||||||
|
writer.WriteVec3(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PropRenderType : Property
|
public class PropRenderType : Property
|
||||||
|
@ -140,6 +190,12 @@ public class PropRenderType : Property
|
||||||
base.Read(reader);
|
base.Read(reader);
|
||||||
mode = (Mode)reader.ReadUInt32();
|
mode = (Mode)reader.ReadUInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
base.Write(writer);
|
||||||
|
writer.Write((uint)mode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PropSlayResult : Property
|
public class PropSlayResult : Property
|
||||||
|
@ -156,6 +212,12 @@ public class PropSlayResult : Property
|
||||||
base.Read(reader);
|
base.Read(reader);
|
||||||
effect = (Effect)reader.ReadUInt32();
|
effect = (Effect)reader.ReadUInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
base.Write(writer);
|
||||||
|
writer.Write((uint)effect);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PropInventoryType : Property
|
public class PropInventoryType : Property
|
||||||
|
@ -172,6 +234,12 @@ public class PropInventoryType : Property
|
||||||
base.Read(reader);
|
base.Read(reader);
|
||||||
type = (Slot)reader.ReadUInt32();
|
type = (Slot)reader.ReadUInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
base.Write(writer);
|
||||||
|
writer.Write((uint)type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PropCollisionType : Property
|
public class PropCollisionType : Property
|
||||||
|
@ -194,6 +262,19 @@ public class PropCollisionType : Property
|
||||||
NoResult = (flags & (0x1 << 4)) != 0;
|
NoResult = (flags & (0x1 << 4)) != 0;
|
||||||
FullCollisionSound = (flags & (0x1 << 5)) != 0;
|
FullCollisionSound = (flags & (0x1 << 5)) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
base.Write(writer);
|
||||||
|
var flags = 0u;
|
||||||
|
if (Bounce) flags += 1;
|
||||||
|
if (DestroyOnImpact) flags += 2;
|
||||||
|
if (SlayOnImpact) flags += 4;
|
||||||
|
if (NoCollisionSound) flags += 8;
|
||||||
|
if (NoResult) flags += 16;
|
||||||
|
if (FullCollisionSound) flags += 32;
|
||||||
|
writer.Write(flags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PropPosition : Property
|
public class PropPosition : Property
|
||||||
|
@ -208,6 +289,14 @@ public class PropPosition : Property
|
||||||
reader.ReadBytes(4); // Runtime Cell/Hint in editor
|
reader.ReadBytes(4); // Runtime Cell/Hint in editor
|
||||||
Rotation = reader.ReadRotation();
|
Rotation = reader.ReadRotation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
base.Write(writer);
|
||||||
|
writer.WriteVec3(Location);
|
||||||
|
writer.Write(new byte[4]);
|
||||||
|
writer.WriteRotation(Rotation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PropLight : Property
|
public class PropLight : Property
|
||||||
|
@ -228,6 +317,17 @@ public class PropLight : Property
|
||||||
reader.ReadBytes(3);
|
reader.ReadBytes(3);
|
||||||
InnerRadius = reader.ReadSingle();
|
InnerRadius = reader.ReadSingle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
base.Write(writer);
|
||||||
|
writer.Write(Brightness);
|
||||||
|
writer.WriteVec3(Offset);
|
||||||
|
writer.Write(Radius);
|
||||||
|
writer.Write(QuadLit);
|
||||||
|
writer.Write(new byte[3]);
|
||||||
|
writer.Write(InnerRadius);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PropLightColor : Property
|
public class PropLightColor : Property
|
||||||
|
@ -241,6 +341,13 @@ public class PropLightColor : Property
|
||||||
Hue = reader.ReadSingle();
|
Hue = reader.ReadSingle();
|
||||||
Saturation = reader.ReadSingle();
|
Saturation = reader.ReadSingle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
base.Write(writer);
|
||||||
|
writer.Write(Hue);
|
||||||
|
writer.Write(Saturation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PropSpotlight : Property
|
public class PropSpotlight : Property
|
||||||
|
@ -255,6 +362,14 @@ public class PropSpotlight : Property
|
||||||
OuterAngle = reader.ReadSingle();
|
OuterAngle = reader.ReadSingle();
|
||||||
reader.ReadBytes(4); // Z is unused
|
reader.ReadBytes(4); // Z is unused
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
base.Write(writer);
|
||||||
|
writer.Write(InnerAngle);
|
||||||
|
writer.Write(OuterAngle);
|
||||||
|
writer.Write(new byte[4]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PropSpotlightAndAmbient : Property
|
public class PropSpotlightAndAmbient : Property
|
||||||
|
@ -270,21 +385,12 @@ public class PropSpotlightAndAmbient : Property
|
||||||
OuterAngle = reader.ReadSingle();
|
OuterAngle = reader.ReadSingle();
|
||||||
SpotBrightness = reader.ReadSingle();
|
SpotBrightness = reader.ReadSingle();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Work out what this property actually does
|
public override void Write(BinaryWriter writer)
|
||||||
public class PropLightBasedAlpha : Property
|
|
||||||
{
|
{
|
||||||
public bool Enabled;
|
base.Write(writer);
|
||||||
public Vector2 AlphaRange;
|
writer.Write(InnerAngle);
|
||||||
public Vector2 LightRange;
|
writer.Write(OuterAngle);
|
||||||
|
writer.Write(SpotBrightness);
|
||||||
public override void Read(BinaryReader reader)
|
|
||||||
{
|
|
||||||
base.Read(reader);
|
|
||||||
Enabled = reader.ReadBoolean();
|
|
||||||
reader.ReadBytes(3);
|
|
||||||
AlphaRange = reader.ReadVec2();
|
|
||||||
LightRange = new Vector2(reader.ReadInt32(), reader.ReadInt32());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
namespace KeepersCompound.LGS.Database.Chunks;
|
||||||
|
|
||||||
|
public class RendParams : IChunk
|
||||||
|
{
|
||||||
|
public enum SunlightMode
|
||||||
|
{
|
||||||
|
SingleUnshadowed,
|
||||||
|
QuadObjcastShadows,
|
||||||
|
QuadUnshadowed,
|
||||||
|
SingleObjcastShadows,
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChunkHeader Header { get; set; }
|
||||||
|
|
||||||
|
public string palette;
|
||||||
|
public Vector3 ambientLight;
|
||||||
|
public int useSunlight;
|
||||||
|
public SunlightMode sunlightMode;
|
||||||
|
public Vector3 sunlightDirection;
|
||||||
|
public float sunlightHue;
|
||||||
|
public float sunlightSaturation;
|
||||||
|
public float sunlightBrightness;
|
||||||
|
public float viewDistance;
|
||||||
|
public Vector3[] ambientLightZones;
|
||||||
|
public float globalAiVisBias;
|
||||||
|
public float[] ambientZoneAiVisBiases;
|
||||||
|
|
||||||
|
public void ReadData(BinaryReader reader, DbFile.TableOfContents.Entry entry)
|
||||||
|
{
|
||||||
|
palette = reader.ReadNullString(16);
|
||||||
|
ambientLight = reader.ReadVec3();
|
||||||
|
useSunlight = reader.ReadInt32();
|
||||||
|
sunlightMode = (SunlightMode)reader.ReadUInt32();
|
||||||
|
sunlightDirection = reader.ReadVec3();
|
||||||
|
sunlightHue = reader.ReadSingle();
|
||||||
|
sunlightSaturation = reader.ReadSingle();
|
||||||
|
sunlightBrightness = reader.ReadSingle();
|
||||||
|
reader.ReadBytes(24);
|
||||||
|
viewDistance = reader.ReadSingle();
|
||||||
|
reader.ReadBytes(12);
|
||||||
|
ambientLightZones = new Vector3[8];
|
||||||
|
for (var i = 0; i < ambientLightZones.Length; i++)
|
||||||
|
{
|
||||||
|
ambientLightZones[i] = reader.ReadVec3();
|
||||||
|
}
|
||||||
|
globalAiVisBias = reader.ReadSingle();
|
||||||
|
ambientZoneAiVisBiases = new float[8];
|
||||||
|
for (var i = 0; i < ambientZoneAiVisBiases.Length; i++)
|
||||||
|
{
|
||||||
|
ambientZoneAiVisBiases[i] = reader.ReadSingle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteData(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
writer.WriteNullString(palette, 16);
|
||||||
|
writer.WriteVec3(ambientLight);
|
||||||
|
writer.Write(useSunlight);
|
||||||
|
writer.Write((uint)sunlightMode);
|
||||||
|
writer.WriteVec3(sunlightDirection);
|
||||||
|
writer.Write(sunlightHue);
|
||||||
|
writer.Write(sunlightSaturation);
|
||||||
|
writer.Write(sunlightBrightness);
|
||||||
|
writer.Write(new byte[24]);
|
||||||
|
writer.Write(viewDistance);
|
||||||
|
writer.Write(new byte[12]);
|
||||||
|
foreach (var lightZone in ambientLightZones)
|
||||||
|
{
|
||||||
|
writer.WriteVec3(lightZone);
|
||||||
|
}
|
||||||
|
writer.Write(globalAiVisBias);
|
||||||
|
foreach (var visBias in ambientZoneAiVisBiases)
|
||||||
|
{
|
||||||
|
writer.Write(visBias);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,3 @@
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace KeepersCompound.LGS.Database.Chunks;
|
namespace KeepersCompound.LGS.Database.Chunks;
|
||||||
|
|
||||||
public class TxList : IChunk
|
public class TxList : IChunk
|
||||||
|
@ -16,6 +12,12 @@ public class TxList : IChunk
|
||||||
Tokens = reader.ReadBytes(4);
|
Tokens = reader.ReadBytes(4);
|
||||||
Name = reader.ReadNullString(16);
|
Name = reader.ReadNullString(16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public readonly void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
writer.Write(Tokens);
|
||||||
|
writer.WriteNullString(Name, 16);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,7 +29,6 @@ public class TxList : IChunk
|
||||||
public string[] Tokens { get; set; }
|
public string[] Tokens { get; set; }
|
||||||
public Item[] Items { get; set; }
|
public Item[] Items { get; set; }
|
||||||
|
|
||||||
|
|
||||||
public void ReadData(BinaryReader reader, DbFile.TableOfContents.Entry entry)
|
public void ReadData(BinaryReader reader, DbFile.TableOfContents.Entry entry)
|
||||||
{
|
{
|
||||||
BlockSize = reader.ReadInt32();
|
BlockSize = reader.ReadInt32();
|
||||||
|
@ -47,6 +48,16 @@ public class TxList : IChunk
|
||||||
|
|
||||||
public void WriteData(BinaryWriter writer)
|
public void WriteData(BinaryWriter writer)
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
writer.Write(BlockSize);
|
||||||
|
writer.Write(ItemCount);
|
||||||
|
writer.Write(TokenCount);
|
||||||
|
foreach (var token in Tokens)
|
||||||
|
{
|
||||||
|
writer.WriteNullString(token, 16);
|
||||||
|
}
|
||||||
|
foreach (var item in Items)
|
||||||
|
{
|
||||||
|
item.Write(writer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -39,6 +39,17 @@ public class WorldRep : IChunk
|
||||||
_ => 1.0f,
|
_ => 1.0f,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public readonly void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
writer.Write(Size);
|
||||||
|
writer.Write(Version);
|
||||||
|
writer.Write(Flags);
|
||||||
|
writer.Write(LightmapFormat);
|
||||||
|
writer.Write(LightmapScale);
|
||||||
|
writer.Write(DataSize);
|
||||||
|
writer.Write(CellCount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Cell
|
public struct Cell
|
||||||
|
@ -62,6 +73,17 @@ public class WorldRep : IChunk
|
||||||
MotionIndex = reader.ReadByte();
|
MotionIndex = reader.ReadByte();
|
||||||
reader.ReadByte();
|
reader.ReadByte();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public readonly void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
writer.Write(Flags);
|
||||||
|
writer.Write(VertexCount);
|
||||||
|
writer.Write(PlaneId);
|
||||||
|
writer.Write(ClutId);
|
||||||
|
writer.Write(Destination);
|
||||||
|
writer.Write(MotionIndex);
|
||||||
|
writer.Write((byte)0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct RenderPoly
|
public struct RenderPoly
|
||||||
|
@ -82,6 +104,18 @@ public class WorldRep : IChunk
|
||||||
TextureMagnitude = reader.ReadSingle();
|
TextureMagnitude = reader.ReadSingle();
|
||||||
Center = reader.ReadVec3();
|
Center = reader.ReadVec3();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public readonly void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
writer.WriteVec3(TextureVectors.Item1);
|
||||||
|
writer.WriteVec3(TextureVectors.Item2);
|
||||||
|
writer.Write(TextureBases.Item1);
|
||||||
|
writer.Write(TextureBases.Item2);
|
||||||
|
writer.Write(TextureId);
|
||||||
|
writer.Write(CachedSurface);
|
||||||
|
writer.Write(TextureMagnitude);
|
||||||
|
writer.WriteVec3(Center);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct LightmapInfo
|
public struct LightmapInfo
|
||||||
|
@ -104,6 +138,18 @@ public class WorldRep : IChunk
|
||||||
DynamicLightPtr = reader.ReadUInt32();
|
DynamicLightPtr = reader.ReadUInt32();
|
||||||
AnimLightBitmask = reader.ReadUInt32();
|
AnimLightBitmask = reader.ReadUInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public readonly void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
writer.Write(Bases.Item1);
|
||||||
|
writer.Write(Bases.Item2);
|
||||||
|
writer.Write(PaddedWidth);
|
||||||
|
writer.Write(Height);
|
||||||
|
writer.Write(Width);
|
||||||
|
writer.Write(DataPtr);
|
||||||
|
writer.Write(DynamicLightPtr);
|
||||||
|
writer.Write(AnimLightBitmask);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Lightmap
|
public struct Lightmap
|
||||||
|
@ -186,6 +232,21 @@ public class WorldRep : IChunk
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: This ONLY works for rgba (bpp = 4)!!!
|
||||||
|
public void AddLight(int layer, int x, int y, byte r, byte g, byte b)
|
||||||
|
{
|
||||||
|
var idx = (x + y * Width + layer * Width * Height) * Bpp;
|
||||||
|
Pixels[idx] = (byte)Math.Min(Pixels[idx] + b, 255);
|
||||||
|
Pixels[idx + 1] = (byte)Math.Min(Pixels[idx + 1] + g, 255);
|
||||||
|
Pixels[idx + 2] = (byte)Math.Min(Pixels[idx + 2] + r, 255);
|
||||||
|
Pixels[idx + 3] = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
writer.Write(Pixels);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte VertexCount { get; set; }
|
public byte VertexCount { get; set; }
|
||||||
|
@ -277,11 +338,65 @@ public class WorldRep : IChunk
|
||||||
LightIndices[i] = reader.ReadUInt16();
|
LightIndices[i] = reader.ReadUInt16();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public readonly void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
writer.Write(VertexCount);
|
||||||
|
writer.Write(PolyCount);
|
||||||
|
writer.Write(RenderPolyCount);
|
||||||
|
writer.Write(PortalPolyCount);
|
||||||
|
writer.Write(PlaneCount);
|
||||||
|
writer.Write(Medium);
|
||||||
|
writer.Write(Flags);
|
||||||
|
writer.Write(PortalVertices);
|
||||||
|
writer.Write(NumVList);
|
||||||
|
writer.Write(AnimLightCount);
|
||||||
|
writer.Write(MotionIndex);
|
||||||
|
writer.WriteVec3(SphereCenter);
|
||||||
|
writer.Write(SphereRadius);
|
||||||
|
foreach (var vertex in Vertices)
|
||||||
|
{
|
||||||
|
writer.WriteVec3(vertex);
|
||||||
|
}
|
||||||
|
foreach (var poly in Polys)
|
||||||
|
{
|
||||||
|
poly.Write(writer);
|
||||||
|
}
|
||||||
|
foreach (var renderPoly in RenderPolys)
|
||||||
|
{
|
||||||
|
renderPoly.Write(writer);
|
||||||
|
}
|
||||||
|
writer.Write(IndexCount);
|
||||||
|
writer.Write(Indices);
|
||||||
|
foreach (var plane in Planes)
|
||||||
|
{
|
||||||
|
writer.WriteVec3(plane.Normal);
|
||||||
|
writer.Write(plane.D);
|
||||||
|
}
|
||||||
|
foreach (var animLight in AnimLights)
|
||||||
|
{
|
||||||
|
writer.Write(animLight);
|
||||||
|
}
|
||||||
|
foreach (var lightmapInfo in LightList)
|
||||||
|
{
|
||||||
|
lightmapInfo.Write(writer);
|
||||||
|
}
|
||||||
|
foreach (var lightmap in Lightmaps)
|
||||||
|
{
|
||||||
|
lightmap.Write(writer);
|
||||||
|
}
|
||||||
|
writer.Write(LightIndexCount);
|
||||||
|
foreach (var lightIndex in LightIndices)
|
||||||
|
{
|
||||||
|
writer.Write(lightIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChunkHeader Header { get; set; }
|
public ChunkHeader Header { get; set; }
|
||||||
public WrHeader DataHeader { get; set; }
|
public WrHeader DataHeader { get; set; }
|
||||||
public Cell[] Cells { get; set; }
|
public Cell[] Cells { get; set; }
|
||||||
|
private byte[] _unreadData;
|
||||||
|
|
||||||
public void ReadData(BinaryReader reader, DbFile.TableOfContents.Entry entry)
|
public void ReadData(BinaryReader reader, DbFile.TableOfContents.Entry entry)
|
||||||
{
|
{
|
||||||
|
@ -295,10 +410,17 @@ public class WorldRep : IChunk
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: All the other info lol
|
// TODO: All the other info lol
|
||||||
|
var length = entry.Offset + entry.Size + 24 - reader.BaseStream.Position;
|
||||||
|
_unreadData = reader.ReadBytes((int)length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteData(BinaryWriter writer)
|
public void WriteData(BinaryWriter writer)
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
DataHeader.Write(writer);
|
||||||
|
foreach (var cell in Cells)
|
||||||
|
{
|
||||||
|
cell.Write(writer);
|
||||||
|
}
|
||||||
|
writer.Write(_unreadData);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -52,6 +52,13 @@ public class DbFile
|
||||||
// return $"Name: {Name}, Offset: {O}"
|
// return $"Name: {Name}, Offset: {O}"
|
||||||
return base.ToString();
|
return base.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public readonly void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
writer.WriteNullString(Name, 12);
|
||||||
|
writer.Write(Offset);
|
||||||
|
writer.Write(Size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint ItemCount { get; }
|
public uint ItemCount { get; }
|
||||||
|
@ -65,6 +72,15 @@ public class DbFile
|
||||||
Items.Add(new Entry(reader));
|
Items.Add(new Entry(reader));
|
||||||
Items.Sort((a, b) => a.Offset.CompareTo(b.Offset));
|
Items.Sort((a, b) => a.Offset.CompareTo(b.Offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public readonly void Write(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
writer.Write(ItemCount);
|
||||||
|
foreach (var entry in Items)
|
||||||
|
{
|
||||||
|
entry.Write(writer);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public FHeader Header { get; private set; }
|
public FHeader Header { get; private set; }
|
||||||
|
@ -73,6 +89,7 @@ public class DbFile
|
||||||
|
|
||||||
public DbFile(string filename)
|
public DbFile(string filename)
|
||||||
{
|
{
|
||||||
|
// TODO: Throw rather than return
|
||||||
if (!File.Exists(filename)) return;
|
if (!File.Exists(filename)) return;
|
||||||
|
|
||||||
using MemoryStream stream = new(File.ReadAllBytes(filename));
|
using MemoryStream stream = new(File.ReadAllBytes(filename));
|
||||||
|
@ -91,6 +108,22 @@ public class DbFile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Save(string filename)
|
||||||
|
{
|
||||||
|
// !HACK: Right now we don't need to adjust TOC offset or anything because we're only
|
||||||
|
// overwriting data, not writing new lengths of data
|
||||||
|
|
||||||
|
using var stream = File.Open(filename, FileMode.Create);
|
||||||
|
using var writer = new BinaryWriter(stream, Encoding.UTF8, false);
|
||||||
|
|
||||||
|
Header.Write(writer);
|
||||||
|
foreach (var (name, chunk) in Chunks)
|
||||||
|
{
|
||||||
|
chunk.Write(writer);
|
||||||
|
}
|
||||||
|
Toc.Write(writer);
|
||||||
|
}
|
||||||
|
|
||||||
private static IChunk NewChunk(string entryName)
|
private static IChunk NewChunk(string entryName)
|
||||||
{
|
{
|
||||||
return entryName switch
|
return entryName switch
|
||||||
|
@ -101,6 +134,7 @@ public class DbFile
|
||||||
"TXLIST" => new TxList(),
|
"TXLIST" => new TxList(),
|
||||||
"WREXT" => new WorldRep(),
|
"WREXT" => new WorldRep(),
|
||||||
"BRLIST" => new BrList(),
|
"BRLIST" => new BrList(),
|
||||||
|
"RENDPARAMS" => new RendParams(),
|
||||||
"P$ModelName" => new PropertyChunk<PropLabel>(),
|
"P$ModelName" => new PropertyChunk<PropLabel>(),
|
||||||
"P$Scale" => new PropertyChunk<PropVector>(),
|
"P$Scale" => new PropertyChunk<PropVector>(),
|
||||||
"P$RenderTyp" => new PropertyChunk<PropRenderType>(),
|
"P$RenderTyp" => new PropertyChunk<PropRenderType>(),
|
||||||
|
|
|
@ -1,2 +1,243 @@
|
||||||
// See https://aka.ms/new-console-template for more information
|
using System.Numerics;
|
||||||
Console.WriteLine("Hello, World!");
|
using KeepersCompound.LGS.Database;
|
||||||
|
using KeepersCompound.LGS.Database.Chunks;
|
||||||
|
using TinyEmbree;
|
||||||
|
|
||||||
|
namespace KeepersCompound.Lightmapper;
|
||||||
|
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
// Super simple for now
|
||||||
|
private record Light
|
||||||
|
{
|
||||||
|
public Vector3 position;
|
||||||
|
public Vector3 color;
|
||||||
|
public float radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
var misPath = "/stuff/Games/thief/drive_c/GOG Games/TG ND 1.27 (MAPPING)/FMs/JAYRUDE_Tests/lm_test.cow";
|
||||||
|
var mis = new DbFile(misPath);
|
||||||
|
var hierarchy = BuildHierarchy(misPath, mis);
|
||||||
|
|
||||||
|
// Get list of brush lights, and object lights (ignore anim lights for now)
|
||||||
|
var lights = new List<Light>();
|
||||||
|
if (mis.Chunks.TryGetValue("BRLIST", out var brListRaw))
|
||||||
|
{
|
||||||
|
var brList = (BrList)brListRaw;
|
||||||
|
foreach (var brush in brList.Brushes)
|
||||||
|
{
|
||||||
|
if (brush.media == BrList.Brush.Media.Light)
|
||||||
|
{
|
||||||
|
var sz = brush.size;
|
||||||
|
lights.Add(new Light
|
||||||
|
{
|
||||||
|
position = brush.position,
|
||||||
|
color = HsbToRgb(360 * sz.Y, sz.Z, Math.Min(sz.X, 255.0f)),
|
||||||
|
radius = float.MaxValue
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: object lights
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build embree mesh
|
||||||
|
if (!mis.Chunks.TryGetValue("WREXT", out var wrRaw))
|
||||||
|
return;
|
||||||
|
var worldRep = (WorldRep)wrRaw;
|
||||||
|
var scene = new Raytracer();
|
||||||
|
scene.AddMesh(BuildWrMesh(worldRep));
|
||||||
|
scene.CommitScene();
|
||||||
|
|
||||||
|
// For each lightmap pixel cast against all the brush and object lights
|
||||||
|
if (!mis.Chunks.TryGetValue("RENDPARAMS", out var rendParamsRaw))
|
||||||
|
return;
|
||||||
|
var ambient = ((RendParams)rendParamsRaw).ambientLight * 255;
|
||||||
|
CastScene(scene, worldRep, [.. lights], ambient);
|
||||||
|
|
||||||
|
var dir = Path.GetDirectoryName(misPath);
|
||||||
|
var filename = Path.GetFileNameWithoutExtension(misPath);
|
||||||
|
mis.Save(Path.Join(dir, $"{filename}-lit.cow"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expects Hue to be 0-360, saturation 0-1, brightness 0-255
|
||||||
|
// https://en.wikipedia.org/wiki/HSL_and_HSV#HSV_to_RGB
|
||||||
|
private static Vector3 HsbToRgb(float hue, float saturation, float brightness)
|
||||||
|
{
|
||||||
|
var hi = Convert.ToInt32(Math.Floor(hue / 60)) % 6;
|
||||||
|
var f = hue / 60 - Math.Floor(hue / 60);
|
||||||
|
|
||||||
|
var v = Convert.ToInt32(brightness);
|
||||||
|
var p = Convert.ToInt32(brightness * (1 - saturation));
|
||||||
|
var q = Convert.ToInt32(brightness * (1 - f * saturation));
|
||||||
|
var t = Convert.ToInt32(brightness * (1 - (1 - f) * saturation));
|
||||||
|
|
||||||
|
return hi switch
|
||||||
|
{
|
||||||
|
0 => new Vector3(v, t, p),
|
||||||
|
1 => new Vector3(q, v, p),
|
||||||
|
2 => new Vector3(p, v, t),
|
||||||
|
3 => new Vector3(p, q, v),
|
||||||
|
4 => new Vector3(t, p, v),
|
||||||
|
_ => new Vector3(v, p, q),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ObjectHierarchy BuildHierarchy(string misPath, DbFile misFile)
|
||||||
|
{
|
||||||
|
ObjectHierarchy objHierarchy;
|
||||||
|
if (misFile.Chunks.TryGetValue("GAM_FILE", out var gamFileChunk))
|
||||||
|
{
|
||||||
|
var dir = Path.GetDirectoryName(misPath);
|
||||||
|
var options = new EnumerationOptions { MatchCasing = MatchCasing.CaseInsensitive };
|
||||||
|
var name = ((GamFile)gamFileChunk).fileName;
|
||||||
|
var paths = Directory.GetFiles(dir!, name, options);
|
||||||
|
if (paths.Length > 0)
|
||||||
|
{
|
||||||
|
objHierarchy = new ObjectHierarchy(misFile, new DbFile(paths[0]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
objHierarchy = new ObjectHierarchy(misFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
objHierarchy = new ObjectHierarchy(misFile);
|
||||||
|
}
|
||||||
|
return objHierarchy;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TriangleMesh BuildWrMesh(WorldRep worldRep)
|
||||||
|
{
|
||||||
|
var vertices = new List<Vector3>();
|
||||||
|
var indices = new List<int>();
|
||||||
|
|
||||||
|
var cells = worldRep.Cells;
|
||||||
|
for (var cellIdx = 0; cellIdx < cells.Length; cellIdx++)
|
||||||
|
{
|
||||||
|
var cell = cells[cellIdx];
|
||||||
|
var numPolys = cell.PolyCount;
|
||||||
|
var numRenderPolys = cell.RenderPolyCount;
|
||||||
|
var numPortalPolys = cell.PortalPolyCount;
|
||||||
|
|
||||||
|
// There's nothing to render
|
||||||
|
if (numRenderPolys == 0 || numPortalPolys >= numPolys)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var maxPolyIdx = Math.Min(numRenderPolys, numPolys - numPortalPolys);
|
||||||
|
var cellIdxOffset = 0;
|
||||||
|
for (int polyIdx = 0; polyIdx < maxPolyIdx; polyIdx++)
|
||||||
|
{
|
||||||
|
var poly = cell.Polys[polyIdx];
|
||||||
|
|
||||||
|
var meshIndexOffset = vertices.Count;
|
||||||
|
var numPolyVertices = poly.VertexCount;
|
||||||
|
for (var j = 0; j < numPolyVertices; j++)
|
||||||
|
{
|
||||||
|
var vertex = cell.Vertices[cell.Indices[cellIdxOffset + j]];
|
||||||
|
// Console.WriteLine($"Cell: {cellIdx}, Poly: {polyIdx}, V: {j}, Vert: {vertex}");
|
||||||
|
vertices.Add(vertex);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 1; j < numPolyVertices - 1; j++)
|
||||||
|
{
|
||||||
|
indices.Add(meshIndexOffset);
|
||||||
|
indices.Add(meshIndexOffset + j);
|
||||||
|
indices.Add(meshIndexOffset + j + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
cellIdxOffset += cell.Polys[polyIdx].VertexCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TriangleMesh([.. vertices], [.. indices]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CastScene(Raytracer scene, WorldRep wr, Light[] lights, Vector3 ambientLight)
|
||||||
|
{
|
||||||
|
var cells = wr.Cells;
|
||||||
|
for (var cellIdx = 0; cellIdx < cells.Length; cellIdx++)
|
||||||
|
{
|
||||||
|
var cell = cells[cellIdx];
|
||||||
|
var numPolys = cell.PolyCount;
|
||||||
|
var numRenderPolys = cell.RenderPolyCount;
|
||||||
|
var numPortalPolys = cell.PortalPolyCount;
|
||||||
|
|
||||||
|
// There's nothing to render
|
||||||
|
if (numRenderPolys == 0 || numPortalPolys >= numPolys)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var maxPolyIdx = Math.Min(numRenderPolys, numPolys - numPortalPolys);
|
||||||
|
for (int polyIdx = 0; polyIdx < maxPolyIdx; polyIdx++)
|
||||||
|
{
|
||||||
|
var poly = cell.Polys[polyIdx];
|
||||||
|
var plane = cell.Planes[poly.PlaneId];
|
||||||
|
var renderPoly = cell.RenderPolys[polyIdx];
|
||||||
|
var info = cell.LightList[polyIdx];
|
||||||
|
var lightmap = cell.Lightmaps[polyIdx];
|
||||||
|
|
||||||
|
// Clear existing lightmap data
|
||||||
|
for (var i = 0; i < lightmap.Pixels.Length; i++)
|
||||||
|
{
|
||||||
|
lightmap.Pixels[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var y = 0; y < lightmap.Height; y++)
|
||||||
|
{
|
||||||
|
for (var x = 0; x < lightmap.Width; x++)
|
||||||
|
{
|
||||||
|
lightmap.AddLight(0, x, y, (byte)ambientLight.X, (byte)ambientLight.Y, (byte)ambientLight.Z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var light in lights)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Doing a light...");
|
||||||
|
// Check if plane normal is facing towards the light
|
||||||
|
var direction = renderPoly.Center - light.position;
|
||||||
|
Console.WriteLine($"Light Pos: {light.position}, poly center: {renderPoly.Center}");
|
||||||
|
Console.WriteLine($"Dir: {direction}");
|
||||||
|
// if (Vector3.Dot(plane.Normal, direction) < 0)
|
||||||
|
{
|
||||||
|
// Cast from the light to the center (later each pixel)
|
||||||
|
var hit = scene.Trace(new Ray
|
||||||
|
{
|
||||||
|
Origin = light.position,
|
||||||
|
Direction = Vector3.Normalize(direction)
|
||||||
|
});
|
||||||
|
|
||||||
|
// cheeky epsilon
|
||||||
|
var goodHit = hit && Math.Abs(hit.Distance - direction.Length()) < 0.001;
|
||||||
|
Console.WriteLine($"Did we hit? {goodHit}");
|
||||||
|
Console.WriteLine($"Distance: {hit.Distance}, target dist: {direction.Length()}");
|
||||||
|
Console.WriteLine($"Pos: {hit.Position}, Target Pos: {renderPoly.Center}");
|
||||||
|
|
||||||
|
// Iterate all pixels
|
||||||
|
var color = goodHit ? light.color : ambientLight;
|
||||||
|
for (var y = 0; y < lightmap.Height; y++)
|
||||||
|
{
|
||||||
|
for (var x = 0; x < lightmap.Width; x++)
|
||||||
|
{
|
||||||
|
lightmap.AddLight(0, x, y, (byte)color.X, (byte)color.Y, (byte)color.Z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// // TODO: Get world position of each pixel?
|
||||||
|
|
||||||
|
// var poly = cell.Polys[polyIdx];
|
||||||
|
|
||||||
|
// poly.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue