Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>false</CentralPackageTransitivePinningEnabled>
<BclVersion>10.0.7</BclVersion>
<AvaloniaVersion>12.0.2</AvaloniaVersion>
<BclVersion>10.0.8</BclVersion>
<AvaloniaVersion>12.0.4</AvaloniaVersion>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Avalonia" Version="$(AvaloniaVersion)" />
Expand Down
35 changes: 35 additions & 0 deletions src/010 Templates/clm.bt
Original file line number Diff line number Diff line change
@@ -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 <hidden=true> = 0;
local int32 val <hidden=true>;
for (i = 0; i < 100; ++i) {
val = cellData[i];
if (val < 0) {
FSeek(~val * 0x68 + subOffset);
struct MapCell subCell;
}
}
} firstCell;
4 changes: 2 additions & 2 deletions src/010 Templates/ornaments.bt
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
// ID Bytes:
// History:
//------------------------------------------------
local ubyte isDirt2 <hidden=true> = 0; // D2, F1 2011 - 2014
local ubyte isDirt2 <hidden=true> = 1; // D2, F1 2011 - 2014
local ubyte isF12010 <hidden=true> = 0;
local ubyte isDirt3 <hidden=true> = 0;
local ubyte isDirtShowdown <hidden=true> = 0;
local ubyte isGrid2 <hidden=true> = 0;
local ubyte isGridAutosport <hidden=true> = 1; // GA, Dirt Rally
local ubyte isGridAutosport <hidden=true> = 0; // GA, Dirt Rally
SetBackColor(cLtGray);

int32 version;
Expand Down
1 change: 1 addition & 0 deletions src/010 Templates/pssg.bt
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ struct NODE {
case "SHADERINPUT":
case "TEXTUREIMAGEBLOCKDATA":
case "TRANSFORM":
case "SHADERPROGRAMCODEBLOCK":
char data[end - FTell()] <bgcolor=cRed>;
break;
default:
Expand Down
103 changes: 103 additions & 0 deletions src/010 Templates/trees.bt
Original file line number Diff line number Diff line change
@@ -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 <hidden=true> = 0; // D2, F1 2010 - 2014
local ubyte isDirt3 <hidden=true> = 0; // D3, DShowdown, G2
local ubyte isGridAutosport <hidden=true> = 0; // GA, DRally
SetBackColor(cLtGray);

if (isDirt3 || isGridAutosport) {
int32 version;
int32 instanceListOffset;
int32 numInstanceList;
}
else
{
local int32 instanceListOffset <hidden=true> = 0;
local int32 numInstanceList <hidden=true> = 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 <hidden=true> = FTell();
FSeek(instancesOffset);
struct Instance {
float transform[12];
ubyte color[4];
if (isDirt2) {
float shadowFactor;
int32 dynamic;
int32 landmark;
}
} instances[numInstances] <optimize=false>;
FSeek(pos);
} instanceRefs[numInstanceRef] <optimize=false,read=ReadString(fileNameOffset)>;

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] <optimize=false>;
}
} instanceLists[numInstanceList] <optimize=false>;
57 changes: 41 additions & 16 deletions src/EgoEngineLibrary/Formats/Pssg/RenderDataSourceReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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.");
}
Expand All @@ -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.");
}
Expand All @@ -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.");
}
Expand Down Expand Up @@ -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.");
}
Expand All @@ -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<byte> data)
Expand All @@ -378,37 +395,45 @@ private static Vector2 ReadVector2(ReadOnlySpan<byte> data)
private static Vector4 ReadVectorHalf4(ReadOnlySpan<byte> 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<byte> 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<byte> 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<byte> source)
private static Vector3 ReadHend3N(ReadOnlySpan<byte> 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;
}
}
}
51 changes: 39 additions & 12 deletions src/EgoEngineLibrary/Formats/Pssg/RenderDataSourceWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,9 @@ private void WriteNormal(ShaderVertexInputInfo vi, uint elementIndex, Span<byte>
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.");
}
Expand All @@ -262,6 +265,9 @@ private void WriteTangent(ShaderVertexInputInfo vi, uint elementIndex, Span<byte
case "float3":
WriteVector3(destination, new Vector3(value.X, value.Y, value.Z));
break;
case "hend3n":
WriteHend3N(destination, value.AsVector3());
break;
default:
throw new NotImplementedException($"Support for {vi.Name} data type {vi.DataType} is not implemented.");
}
Expand All @@ -282,6 +288,9 @@ private void WriteBinormal(ShaderVertexInputInfo vi, uint elementIndex, Span<byt
case "float3":
WriteVector3(destination, new Vector3(value.X, value.Y, value.Z));
break;
case "hend3n":
WriteHend3N(destination, value.AsVector3());
break;
default:
throw new NotImplementedException($"Support for {vi.Name} data type {vi.DataType} is not implemented.");
}
Expand Down Expand Up @@ -332,10 +341,15 @@ private void WriteColor(ShaderVertexInputInfo vi, uint elementIndex, Span<byte>
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);
Expand All @@ -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<byte> destination)
Expand Down Expand Up @@ -377,25 +402,27 @@ private static void WriteVector2(Span<byte> destination, Vector2 value)

private static void WriteVectorHalf2(Span<byte> 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<byte> 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<byte> destination, Half value)
{
BinaryPrimitives.WriteInt16BigEndian(destination, HalfToInt16Bits(value));
}
private static unsafe short HalfToInt16Bits(Half value)
private static void WriteHend3N(Span<byte> 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);
}
}
}
Loading