diff --git a/Directory.Packages.props b/Directory.Packages.props
index 785906a..b81cd74 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -2,8 +2,8 @@
true
false
- 10.0.7
- 12.0.2
+ 10.0.8
+ 12.0.4
diff --git a/src/010 Templates/clm.bt b/src/010 Templates/clm.bt
new file mode 100644
index 0000000..6c7ff6d
--- /dev/null
+++ b/src/010 Templates/clm.bt
@@ -0,0 +1,35 @@
+//--------------------------------------
+//--- 010 Editor v15.0.1 Binary Template
+//
+// File: clm.bt
+// Author: Petar Tasev
+// Revision: 1
+// Purpose: Label Ego Engine clm files
+//--------------------------------------
+LittleEndian();
+SetBackColor(cLtGray);
+// Compressed Light Map
+// Supports RD:G and D2 for now
+
+// MapHeader
+float offsetX;
+float offsetZ;
+float scaleX;
+float scaleZ;
+uint32 mapSize;
+uint32 tileWidth;
+
+struct MapCell {
+ uint32 subOffset;
+ int8 cellData[100];
+
+ local int32 i = 0;
+ local int32 val ;
+ for (i = 0; i < 100; ++i) {
+ val = cellData[i];
+ if (val < 0) {
+ FSeek(~val * 0x68 + subOffset);
+ struct MapCell subCell;
+ }
+ }
+} firstCell;
diff --git a/src/010 Templates/ornaments.bt b/src/010 Templates/ornaments.bt
index 0bbe993..bd01acd 100644
--- a/src/010 Templates/ornaments.bt
+++ b/src/010 Templates/ornaments.bt
@@ -10,12 +10,12 @@
// ID Bytes:
// History:
//------------------------------------------------
-local ubyte isDirt2 = 0; // D2, F1 2011 - 2014
+local ubyte isDirt2 = 1; // D2, F1 2011 - 2014
local ubyte isF12010 = 0;
local ubyte isDirt3 = 0;
local ubyte isDirtShowdown = 0;
local ubyte isGrid2 = 0;
-local ubyte isGridAutosport = 1; // GA, Dirt Rally
+local ubyte isGridAutosport = 0; // GA, Dirt Rally
SetBackColor(cLtGray);
int32 version;
diff --git a/src/010 Templates/pssg.bt b/src/010 Templates/pssg.bt
index d169abd..2cf60a9 100644
--- a/src/010 Templates/pssg.bt
+++ b/src/010 Templates/pssg.bt
@@ -81,6 +81,7 @@ struct NODE {
case "SHADERINPUT":
case "TEXTUREIMAGEBLOCKDATA":
case "TRANSFORM":
+ case "SHADERPROGRAMCODEBLOCK":
char data[end - FTell()] ;
break;
default:
diff --git a/src/010 Templates/trees.bt b/src/010 Templates/trees.bt
new file mode 100644
index 0000000..2b7510d
--- /dev/null
+++ b/src/010 Templates/trees.bt
@@ -0,0 +1,103 @@
+//------------------------------------------------
+//--- 010 Editor v12.0.1 Binary Template
+//
+// File:
+// Authors:
+// Version:
+// Purpose: trees.bin in tracks
+// Category:
+// File Mask:
+// ID Bytes:
+// History:
+//------------------------------------------------
+local ubyte isDirt2 = 0; // D2, F1 2010 - 2014
+local ubyte isDirt3 = 0; // D3, DShowdown, G2
+local ubyte isGridAutosport = 0; // GA, DRally
+SetBackColor(cLtGray);
+
+if (isDirt3 || isGridAutosport) {
+ int32 version;
+ int32 instanceListOffset;
+ int32 numInstanceList;
+}
+else
+{
+ local int32 instanceListOffset = 0;
+ local int32 numInstanceList = 1;
+}
+
+FSeek(instanceListOffset);
+struct InstanceList {
+float boundsMin[3];
+float boundsMax[3];
+if (isDirt3 || isGridAutosport) {
+ int32 referenceNum;
+}
+int32 totalInstances; // aka instanceNum
+if (isDirt2 || isDirt3 || isGridAutosport)
+{
+ int32 totalLandmarks; // does not exist in RD: Grid
+}
+int32 instanceRefOffset;
+int32 numInstanceRef;
+if (isDirt3 || isGridAutosport) {
+ int32 instanceOffset;
+ int32 numInstance;
+}
+
+FSeek(instanceRefOffset);
+struct InstanceRef {
+ int32 fileNameOffset;
+ if (isDirt3 || isGridAutosport) {
+ int32 referenceId;
+ }
+ float boundsMin[3];
+ float boundsMax[3];
+ if (isDirt3 || isGridAutosport) {
+ int32 distant;
+ int32 maxInstances;
+ local int32 numInstances = 0;
+ }
+ else {
+ int32 maxInstances;
+ int32 offset; // index offset into total instance list
+ int32 instancesOffset;
+ int32 numInstances;
+ int32 distant;
+ }
+
+ if (numInstances <= 0) {
+ return;
+ }
+
+ local int64 pos = FTell();
+ FSeek(instancesOffset);
+ struct Instance {
+ float transform[12];
+ ubyte color[4];
+ if (isDirt2) {
+ float shadowFactor;
+ int32 dynamic;
+ int32 landmark;
+ }
+ } instances[numInstances] ;
+ FSeek(pos);
+} instanceRefs[numInstanceRef] ;
+
+if (isDirt3 || isGridAutosport) {
+FSeek(instanceOffset);
+struct Instance2 {
+ int32 referenceId;
+ int32 instanceId;
+ float transform[12];
+ ubyte color[4];
+ float shadowFactor;
+ int32 dynamic;
+ int32 landmark;
+ int32 instanceTag;
+ if (isGridAutosport) {
+ int32 todSpecificOffset;
+ }
+} instances[numInstance] ;
+}
+} instanceLists[numInstanceList] ;
diff --git a/src/EgoEngineLibrary/Formats/Pssg/RenderDataSourceReader.cs b/src/EgoEngineLibrary/Formats/Pssg/RenderDataSourceReader.cs
index 94e5a07..63d34c2 100644
--- a/src/EgoEngineLibrary/Formats/Pssg/RenderDataSourceReader.cs
+++ b/src/EgoEngineLibrary/Formats/Pssg/RenderDataSourceReader.cs
@@ -231,6 +231,8 @@ public Vector3 GetNormal(uint index)
return ReadVector3(data);
case "half4": // just read Vec3, pretty sure 4th item is just 1.0
return ReadVectorHalf3(data);
+ case "hend3n":
+ return ReadHend3N(data);
default:
throw new NotImplementedException($"Support for {attribute.Name} data type {attribute.DataType} is not implemented.");
}
@@ -256,6 +258,8 @@ public Vector4 GetTangent(uint index)
return ReadVectorHalf4(data);
case "float3":
return new Vector4(ReadVector3(data), 0);
+ case "hend3n":
+ return new Vector4(ReadHend3N(data), 0);
default:
throw new NotImplementedException($"Support for {attribute.Name} data type {attribute.DataType} is not implemented.");
}
@@ -281,6 +285,8 @@ public Vector4 GetBinormal(uint index)
return ReadVectorHalf4(data);
case "float3":
return new Vector4(ReadVector3(data), 0);
+ case "hend3n":
+ return new Vector4(ReadHend3N(data), 0);
default:
throw new NotImplementedException($"Support for {attribute.Name} data type {attribute.DataType} is not implemented.");
}
@@ -339,6 +345,8 @@ public Vector4 GetColor(uint index)
{
case "uint_color_argb":
return UnpackArgbColor(BinaryPrimitives.ReadUInt32BigEndian(data));
+ case "uchar4":
+ return UnpackRgbaColor(BinaryPrimitives.ReadUInt32BigEndian(data));
default:
throw new NotImplementedException($"Support for {attribute.Name} data type {attribute.DataType} is not implemented.");
}
@@ -356,6 +364,15 @@ static Vector4 UnpackArgbColor(uint color)
((color >> 24) & 0xFF) / (float)byte.MaxValue,
((color >> 0) & 0xFF) / (float)byte.MaxValue);
}
+
+ static Vector4 UnpackRgbaColor(uint color)
+ {
+ return new Vector4(
+ ((color >> 0) & 0xFF) / (float)byte.MaxValue,
+ ((color >> 8) & 0xFF) / (float)byte.MaxValue,
+ ((color >> 16) & 0xFF) / (float)byte.MaxValue,
+ ((color >> 24) & 0xFF) / (float)byte.MaxValue);
+ }
}
private static Vector3 ReadVector3(ReadOnlySpan data)
@@ -378,37 +395,45 @@ private static Vector2 ReadVector2(ReadOnlySpan data)
private static Vector4 ReadVectorHalf4(ReadOnlySpan data)
{
var vec = new Vector4();
- vec.X = (float)BigToHalf(data);
- vec.Y = (float)BigToHalf(data.Slice(2));
- vec.Z = (float)BigToHalf(data.Slice(4));
- vec.W = (float)BigToHalf(data.Slice(6));
+ vec.X = (float)BinaryPrimitives.ReadHalfBigEndian(data);
+ vec.Y = (float)BinaryPrimitives.ReadHalfBigEndian(data[2..]);
+ vec.Z = (float)BinaryPrimitives.ReadHalfBigEndian(data[4..]);
+ vec.W = (float)BinaryPrimitives.ReadHalfBigEndian(data[6..]);
return vec;
}
private static Vector3 ReadVectorHalf3(ReadOnlySpan data)
{
var vec = new Vector3();
- vec.X = (float)BigToHalf(data);
- vec.Y = (float)BigToHalf(data.Slice(2));
- vec.Z = (float)BigToHalf(data.Slice(4));
+ vec.X = (float)BinaryPrimitives.ReadHalfBigEndian(data);
+ vec.Y = (float)BinaryPrimitives.ReadHalfBigEndian(data[2..]);
+ vec.Z = (float)BinaryPrimitives.ReadHalfBigEndian(data[4..]);
return vec;
}
private static Vector2 ReadVectorHalf2(ReadOnlySpan data)
{
var vec = new Vector2();
- vec.X = (float)BigToHalf(data);
- vec.Y = (float)BigToHalf(data.Slice(2));
+ vec.X = (float)BinaryPrimitives.ReadHalfBigEndian(data);
+ vec.Y = (float)BinaryPrimitives.ReadHalfBigEndian(data[2..]);
return vec;
}
-
- static Half BigToHalf(ReadOnlySpan source)
+
+ private static Vector3 ReadHend3N(ReadOnlySpan data)
{
- return Int16BitsToHalf(BinaryPrimitives.ReadInt16BigEndian(source));
- }
- static unsafe Half Int16BitsToHalf(short value)
- {
- return *(Half*)&value;
+ // 11 11 10 bit signed values
+ var i = BinaryPrimitives.ReadUInt32BigEndian(data);
+ var y = i >> 11;
+ var z = i >> 22;
+
+ // use shift to sign extend
+ var vec = new Vector3
+ {
+ X = (((int)(i & 0x7FF)) << 21 >> 21) / (float)0x3FF,
+ Y = (((int)(y & 0x7FF)) << 21 >> 21) / (float)0x3FF,
+ Z = (((int)(z & 0x3FF)) << 22 >> 22) / (float)0x1FF
+ };
+ return vec;
}
}
}
diff --git a/src/EgoEngineLibrary/Formats/Pssg/RenderDataSourceWriter.cs b/src/EgoEngineLibrary/Formats/Pssg/RenderDataSourceWriter.cs
index cd1c85d..33010a5 100644
--- a/src/EgoEngineLibrary/Formats/Pssg/RenderDataSourceWriter.cs
+++ b/src/EgoEngineLibrary/Formats/Pssg/RenderDataSourceWriter.cs
@@ -245,6 +245,9 @@ private void WriteNormal(ShaderVertexInputInfo vi, uint elementIndex, Span
case "half4":
WriteVectorHalf4(destination, new Vector4(value, 1));
break;
+ case "hend3n":
+ WriteHend3N(destination, value);
+ break;
default:
throw new NotImplementedException($"Support for {vi.Name} data type {vi.DataType} is not implemented.");
}
@@ -262,6 +265,9 @@ private void WriteTangent(ShaderVertexInputInfo vi, uint elementIndex, Span
case "uint_color_argb":
BinaryPrimitives.WriteUInt32BigEndian(destination, PackArgbColor(value));
break;
+ case "uchar4":
+ BinaryPrimitives.WriteUInt32BigEndian(destination, PackRgbaColor(value));
+ break;
default:
throw new NotImplementedException($"Support for {vi.Name} data type {vi.DataType} is not implemented.");
}
+ return;
+
static uint PackArgbColor(Vector4 vector)
{
Vector4 MaxBytes = new Vector4(byte.MaxValue);
@@ -346,6 +360,17 @@ static uint PackArgbColor(Vector4 vector)
return (uint)((((byte)vector.W) << 0) | (((byte)vector.X) << 8) | (((byte)vector.Y) << 16) | (((byte)vector.Z) << 24));
}
+
+ static uint PackRgbaColor(Vector4 vector)
+ {
+ Vector4 MaxBytes = new Vector4(byte.MaxValue);
+ Vector4 Half = new Vector4(0.5f);
+ vector *= MaxBytes;
+ vector += Half;
+ vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
+
+ return (uint)((((byte)vector.X) << 0) | (((byte)vector.Y) << 8) | (((byte)vector.Z) << 16) | (((byte)vector.W) << 24));
+ }
}
private void WriteSkinIndex(ShaderVertexInputInfo vi, uint elementIndex, Span destination)
@@ -377,25 +402,27 @@ private static void WriteVector2(Span destination, Vector2 value)
private static void WriteVectorHalf2(Span destination, Vector2 value)
{
- WriteHalfBigEndian(destination, (Half)value.X);
- WriteHalfBigEndian(destination.Slice(2), (Half)value.Y);
+ BinaryPrimitives.WriteHalfBigEndian(destination, (Half)value.X);
+ BinaryPrimitives.WriteHalfBigEndian(destination.Slice(2), (Half)value.Y);
}
private static void WriteVectorHalf4(Span destination, Vector4 value)
{
- WriteHalfBigEndian(destination, (Half)value.X);
- WriteHalfBigEndian(destination.Slice(2), (Half)value.Y);
- WriteHalfBigEndian(destination.Slice(4), (Half)value.Z);
- WriteHalfBigEndian(destination.Slice(6), (Half)value.W);
+ BinaryPrimitives.WriteHalfBigEndian(destination, (Half)value.X);
+ BinaryPrimitives.WriteHalfBigEndian(destination.Slice(2), (Half)value.Y);
+ BinaryPrimitives.WriteHalfBigEndian(destination.Slice(4), (Half)value.Z);
+ BinaryPrimitives.WriteHalfBigEndian(destination.Slice(6), (Half)value.W);
}
- private static void WriteHalfBigEndian(Span destination, Half value)
- {
- BinaryPrimitives.WriteInt16BigEndian(destination, HalfToInt16Bits(value));
- }
- private static unsafe short HalfToInt16Bits(Half value)
+ private static void WriteHend3N(Span destination, Vector3 value)
{
- return *(short*)&value;
+ // 11 11 10 bit signed values
+ // Shift up to capture sign bit, then unsigned shift back
+ var x = ((int)(float.Clamp(value.X, -1, 1) * 0x3FF)) << 21 >>> 21;
+ var y = ((int)(float.Clamp(value.Y, -1, 1) * 0x3FF)) << 21 >>> 21;
+ var z = ((int)(float.Clamp(value.Z, -1, 1) * 0x1FF)) << 22 >>> 22;
+ uint val = (uint)x | ((uint)y << 11) | ((uint)z << 22);
+ BinaryPrimitives.WriteUInt32BigEndian(destination, val);
}
}
}
diff --git a/src/EgoEngineLibrary/Graphics/Pssg/Elements/PssgShaderProgramCode.cs b/src/EgoEngineLibrary/Graphics/Pssg/Elements/PssgShaderProgramCode.cs
index 5aa3bdf..3a42ea1 100644
--- a/src/EgoEngineLibrary/Graphics/Pssg/Elements/PssgShaderProgramCode.cs
+++ b/src/EgoEngineLibrary/Graphics/Pssg/Elements/PssgShaderProgramCode.cs
@@ -11,7 +11,7 @@ public class PssgShaderProgramCode : PssgElement
new PssgSchemaAttribute("codeType", PssgAttributeType.String),
new PssgSchemaAttribute("profileType", PssgAttributeType.Int),
new PssgSchemaAttribute("profile", PssgAttributeType.Int),
- new PssgSchemaAttribute("codeEntry", PssgAttributeType.Int),
+ new PssgSchemaAttribute("codeEntry", PssgAttributeType.String),
new PssgSchemaAttribute("parameterCount", PssgAttributeType.Int),
new PssgSchemaAttribute("streamCount", PssgAttributeType.Int),
}
@@ -41,9 +41,9 @@ public uint Profile
set => AddAttribute(Schema.Attributes[3].Name, value);
}
- public byte CodeEntry
+ public string CodeEntry
{
- get => GetAttributeValue(Schema.Attributes[4].Name);
+ get => GetAttributeValue(Schema.Attributes[4].Name);
set => AddAttribute(Schema.Attributes[4].Name, value);
}
diff --git a/src/EgoEngineLibrary/Graphics/Pssg/PssgBinaryReader.cs b/src/EgoEngineLibrary/Graphics/Pssg/PssgBinaryReader.cs
index fc6e563..2eb6a57 100644
--- a/src/EgoEngineLibrary/Graphics/Pssg/PssgBinaryReader.cs
+++ b/src/EgoEngineLibrary/Graphics/Pssg/PssgBinaryReader.cs
@@ -1,6 +1,4 @@
using System.Numerics;
-using System.Text;
-using EgoEngineLibrary.Collections;
using EgoEngineLibrary.Conversion;
using EgoEngineLibrary.IO;
@@ -8,8 +6,8 @@ namespace EgoEngineLibrary.Graphics.Pssg
{
public class PssgBinaryReader : EndianBinaryReader
{
- public OrderedSet ElementTable { get; set; }
- public OrderedSet AttributeTable { get; set; }
+ public List ElementTable { get; set; }
+ public List AttributeTable { get; set; }
internal bool UseDataElementCheck { get; set; }
public PssgBinaryReader(EndianBitConverter bitConvertor, Stream stream, bool leaveOpen)
diff --git a/src/EgoEngineLibrary/Graphics/Pssg/PssgFile.cs b/src/EgoEngineLibrary/Graphics/Pssg/PssgFile.cs
index 8901bdb..95dae6d 100644
--- a/src/EgoEngineLibrary/Graphics/Pssg/PssgFile.cs
+++ b/src/EgoEngineLibrary/Graphics/Pssg/PssgFile.cs
@@ -132,8 +132,8 @@ public static PssgFile ReadPssg(Stream fileStream, PssgFileType fileType)
}
}
- file._elementTable = reader.ElementTable;
- file._attributeTable = reader.AttributeTable;
+ file._elementTable = new OrderedSet(reader.ElementTable);
+ file._attributeTable = new OrderedSet(reader.AttributeTable);
}
return file;
diff --git a/src/EgoPssgEditor/App.axaml b/src/EgoPssgEditor/App.axaml
index bcafe07..306222b 100644
--- a/src/EgoPssgEditor/App.axaml
+++ b/src/EgoPssgEditor/App.axaml
@@ -10,6 +10,13 @@
+
+