caching: MessagePack and JSON shapes for SpanPath and SpanStage
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
0a1b49a231
commit
52d25740ac
4 changed files with 79 additions and 3 deletions
|
|
@ -14,7 +14,7 @@ namespace GameCult.Caching.MessagePack;
|
|||
/// The canonical System.Text.Json shape of every public CultMath value type, the JSON twin of
|
||||
/// <see cref="CultMathResolver"/>. Vectors, quaternions and colors are objects keyed by their
|
||||
/// field names (<c>{"x":1,"y":2}</c>), matrices are arrays of row objects, <c>rect</c> is
|
||||
/// <c>{"min":..,"max":..}</c>, <c>CultCellular</c> is <c>{"nearest":..,"edge":..,"id":..}</c>, <c>CultPhasor</c> is <c>{"cos":..,"sin":..}</c>, and <c>SpanNoise</c> is <c>{"field":..,"curvature":..,"fold":..}</c>.
|
||||
/// <c>{"min":..,"max":..}</c>, <c>CultCellular</c> is <c>{"nearest":..,"edge":..,"id":..}</c>, <c>CultPhasor</c> is <c>{"cos":..,"sin":..}</c>, <c>SpanNoise</c> is <c>{"field":..,"curvature":..,"fold":..}</c>, <c>SpanPath</c> is <c>{"midpoint":..,"velocity":..,"speed":..,"acceleration":..,"halfLength":..}</c>, and <c>SpanStage</c> is <c>{"frequency":..,"stretch":..,"axis":..,"shift":..,"offset":..,"octaveStep":..}</c>.
|
||||
/// Property names are fixed: <c>PropertyNamingPolicy</c> does not rename them, and
|
||||
/// <c>PropertyNameCaseInsensitive</c> makes reading case-insensitive.
|
||||
/// <para>
|
||||
|
|
@ -481,7 +481,7 @@ public static class CultMathJson
|
|||
Add<Random, uint>(UIntScalar.Instance, new Fields<uint>(("state", Val<uint>())),
|
||||
a => new Random { state = a[0] }, (v, a) => a[0] = v.state),
|
||||
|
||||
// Compositions: matrices are arrays of row objects, rect is {min, max}, CultCellular is {nearest, edge, id}, CultPhasor is {cos, sin}, SpanNoise is {field, curvature, fold}.
|
||||
// Compositions: matrices are arrays of row objects, rect is {min, max}, CultCellular is {nearest, edge, id}, CultPhasor is {cos, sin}, SpanNoise is {field, curvature, fold}, SpanPath is {midpoint, velocity, speed, acceleration, halfLength}, SpanStage is {frequency, stretch, axis, shift, offset, octaveStep}.
|
||||
Add<float2x2, float>(f, new Rows<float>(2, Xy<float>()),
|
||||
a => new float2x2(a[0], a[1], a[2], a[3]),
|
||||
(v, a) => { a[0] = v[0].x; a[1] = v[0].y; a[2] = v[1].x; a[3] = v[1].y; }),
|
||||
|
|
@ -521,6 +521,24 @@ public static class CultMathJson
|
|||
a[0] = v.field.x; a[1] = v.field.y; a[2] = v.field.z; a[3] = v.field.w;
|
||||
a[4] = v.curvature; a[5] = v.fold;
|
||||
}),
|
||||
Add<SpanPath, float>(f, new Fields<float>(("midpoint", Xyz<float>()), ("velocity", Xyz<float>()), ("speed", Val<float>()), ("acceleration", Val<float>()), ("halfLength", Val<float>())),
|
||||
a => new SpanPath { midpoint = new float3(a[0], a[1], a[2]), velocity = new float3(a[3], a[4], a[5]), speed = a[6], acceleration = a[7], halfLength = a[8] },
|
||||
(v, a) =>
|
||||
{
|
||||
a[0] = v.midpoint.x; a[1] = v.midpoint.y; a[2] = v.midpoint.z;
|
||||
a[3] = v.velocity.x; a[4] = v.velocity.y; a[5] = v.velocity.z;
|
||||
a[6] = v.speed; a[7] = v.acceleration; a[8] = v.halfLength;
|
||||
}),
|
||||
Add<SpanStage, float>(f, new Fields<float>(("frequency", Val<float>()), ("stretch", Val<float>()), ("axis", Xyz<float>()), ("shift", Xyz<float>()), ("offset", Xyz<float>()), ("octaveStep", Xyz<float>())),
|
||||
a => new SpanStage { frequency = a[0], stretch = a[1], axis = new float3(a[2], a[3], a[4]), shift = new float3(a[5], a[6], a[7]), offset = new float3(a[8], a[9], a[10]), octaveStep = new float3(a[11], a[12], a[13]) },
|
||||
(v, a) =>
|
||||
{
|
||||
a[0] = v.frequency; a[1] = v.stretch;
|
||||
a[2] = v.axis.x; a[3] = v.axis.y; a[4] = v.axis.z;
|
||||
a[5] = v.shift.x; a[6] = v.shift.y; a[7] = v.shift.z;
|
||||
a[8] = v.offset.x; a[9] = v.offset.y; a[10] = v.offset.z;
|
||||
a[11] = v.octaveStep.x; a[12] = v.octaveStep.y; a[13] = v.octaveStep.z;
|
||||
}),
|
||||
};
|
||||
|
||||
var map = new Dictionary<Type, JsonConverter>();
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ public sealed class CultMathResolver : IFormatterResolver
|
|||
return value;
|
||||
}),
|
||||
|
||||
// Compositions: matrices are rows, rect is [min, max], CultCellular is [nearest, edge, id], CultPhasor is [cos, sin], SpanNoise is [field, curvature, fold].
|
||||
// Compositions: matrices are rows, rect is [min, max], CultCellular is [nearest, edge, id], CultPhasor is [cos, sin], SpanNoise is [field, curvature, fold], SpanPath is [midpoint, velocity, speed, acceleration, halfLength], SpanStage is [frequency, stretch, axis, shift, offset, octaveStep].
|
||||
Shape<float2x2>((ref MessagePackWriter w, float2x2 v) => { w.WriteArrayHeader(2); PutFloat2(ref w, v[0]); PutFloat2(ref w, v[1]); },
|
||||
(ref MessagePackReader r) =>
|
||||
{
|
||||
|
|
@ -252,6 +252,43 @@ public sealed class CultMathResolver : IFormatterResolver
|
|||
}
|
||||
return value;
|
||||
}),
|
||||
Shape<SpanPath>((ref MessagePackWriter w, SpanPath v) => { w.WriteArrayHeader(5); PutFloat3(ref w, v.midpoint); PutFloat3(ref w, v.velocity); w.Write(v.speed); w.Write(v.acceleration); w.Write(v.halfLength); },
|
||||
(ref MessagePackReader r) =>
|
||||
{
|
||||
var value = default(SpanPath);
|
||||
for (int i = 0, n = r.ReadArrayHeader(); i < n; i++)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: value.midpoint = GetFloat3(ref r); break;
|
||||
case 1: value.velocity = GetFloat3(ref r); break;
|
||||
case 2: value.speed = r.ReadSingle(); break;
|
||||
case 3: value.acceleration = r.ReadSingle(); break;
|
||||
case 4: value.halfLength = r.ReadSingle(); break;
|
||||
default: r.Skip(); break;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}),
|
||||
Shape<SpanStage>((ref MessagePackWriter w, SpanStage v) => { w.WriteArrayHeader(6); w.Write(v.frequency); w.Write(v.stretch); PutFloat3(ref w, v.axis); PutFloat3(ref w, v.shift); PutFloat3(ref w, v.offset); PutFloat3(ref w, v.octaveStep); },
|
||||
(ref MessagePackReader r) =>
|
||||
{
|
||||
var value = default(SpanStage);
|
||||
for (int i = 0, n = r.ReadArrayHeader(); i < n; i++)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: value.frequency = r.ReadSingle(); break;
|
||||
case 1: value.stretch = r.ReadSingle(); break;
|
||||
case 2: value.axis = GetFloat3(ref r); break;
|
||||
case 3: value.shift = GetFloat3(ref r); break;
|
||||
case 4: value.offset = GetFloat3(ref r); break;
|
||||
case 5: value.octaveStep = GetFloat3(ref r); break;
|
||||
default: r.Skip(); break;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}),
|
||||
};
|
||||
|
||||
var map = new Dictionary<Type, object>();
|
||||
|
|
|
|||
|
|
@ -47,6 +47,10 @@ namespace GameCult.Caching.Tests
|
|||
"""{"cos":{"x":1,"y":2,"z":3,"w":4},"sin":{"x":5,"y":6,"z":7,"w":8}}""");
|
||||
Json(new SpanNoise(new float4(1f, 2f, 3f, 4f), 0.25f, 0.5f)).Should().Be(
|
||||
"""{"field":{"x":1,"y":2,"z":3,"w":4},"curvature":0.25,"fold":0.5}""");
|
||||
Json(new SpanPath { midpoint = new float3(1f, 2f, 3f), velocity = new float3(4f, 5f, 6f), speed = 7f, acceleration = 8f, halfLength = 9f }).Should().Be(
|
||||
"""{"midpoint":{"x":1,"y":2,"z":3},"velocity":{"x":4,"y":5,"z":6},"speed":7,"acceleration":8,"halfLength":9}""");
|
||||
Json(new SpanStage { frequency = 1f, stretch = 2f, axis = new float3(3f, 4f, 5f), shift = new float3(6f, 7f, 8f), offset = new float3(9f, 10f, 11f), octaveStep = new float3(12f, 13f, 14f) }).Should().Be(
|
||||
"""{"frequency":1,"stretch":2,"axis":{"x":3,"y":4,"z":5},"shift":{"x":6,"y":7,"z":8},"offset":{"x":9,"y":10,"z":11},"octaveStep":{"x":12,"y":13,"z":14}}""");
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
@ -72,6 +76,8 @@ namespace GameCult.Caching.Tests
|
|||
RoundTrip(new CultCellular(new float4(1, 2, 3, 4), new float4(5, 6, 7, 8), 0.25f));
|
||||
RoundTrip(new CultPhasor(new float4(1, 2, 3, 4), new float4(5, 6, 7, 8)));
|
||||
RoundTrip(new SpanNoise(new float4(1, 2, 3, 4), 0.25f, 0.5f));
|
||||
RoundTrip(new SpanPath { midpoint = new float3(1f, 2f, 3f), velocity = new float3(4f, 5f, 6f), speed = 7f, acceleration = 8f, halfLength = 9f });
|
||||
RoundTrip(new SpanStage { frequency = 1f, stretch = 2f, axis = new float3(3f, 4f, 5f), shift = new float3(6f, 7f, 8f), offset = new float3(9f, 10f, 11f), octaveStep = new float3(12f, 13f, 14f) });
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
|
|||
|
|
@ -103,6 +103,8 @@ namespace GameCult.Caching.Tests
|
|||
RoundTrip(new CultCellular(new float4(1, 2, 3, 4), new float4(5, 6, 7, 8), 0.25f));
|
||||
RoundTrip(new CultPhasor(new float4(1, 2, 3, 4), new float4(5, 6, 7, 8)));
|
||||
RoundTrip(new SpanNoise(new float4(1, 2, 3, 4), 0.25f, 0.5f));
|
||||
RoundTrip(new SpanPath { midpoint = new float3(1f, 2f, 3f), velocity = new float3(4f, 5f, 6f), speed = 7f, acceleration = 8f, halfLength = 9f });
|
||||
RoundTrip(new SpanStage { frequency = 1f, stretch = 2f, axis = new float3(3f, 4f, 5f), shift = new float3(6f, 7f, 8f), offset = new float3(9f, 10f, 11f), octaveStep = new float3(12f, 13f, 14f) });
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
@ -143,6 +145,19 @@ namespace GameCult.Caching.Tests
|
|||
"94CA3F800000CA40000000CA40400000CA40800000" +
|
||||
"CA3E800000" +
|
||||
"CA3F000000");
|
||||
Hex(new SpanPath { midpoint = new float3(1f, 2f, 3f), velocity = new float3(4f, 5f, 6f), speed = 7f, acceleration = 8f, halfLength = 9f }).Should().Be(
|
||||
"95" +
|
||||
"93CA3F800000CA40000000CA40400000" +
|
||||
"93CA40800000CA40A00000CA40C00000" +
|
||||
"CA40E00000CA41000000CA41100000");
|
||||
Hex(new SpanStage { frequency = 1f, stretch = 2f, axis = new float3(3f, 4f, 5f), shift = new float3(6f, 7f, 8f), offset = new float3(9f, 10f, 11f), octaveStep = new float3(12f, 13f, 14f) }).Should().Be(
|
||||
"96" +
|
||||
"CA3F800000" +
|
||||
"CA40000000" +
|
||||
"93CA40400000CA40800000CA40A00000" +
|
||||
"93CA40C00000CA40E00000CA41000000" +
|
||||
"93CA41100000CA41200000CA41300000" +
|
||||
"93CA41400000CA41500000CA41600000");
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
|
|||
Loading…
Reference in a new issue