mirror of
https://github.com/sampletext32/ParkanPlayground.git
synced 2026-08-15 02:57:49 +04:00
msh reverse
This commit is contained in:
@@ -67,7 +67,7 @@ public static class Msh0x07
|
|||||||
/// <param name="PackedNormalX">[0x08..0x0A] Packed normal X, int16, scale = 1 / 32767.</param>
|
/// <param name="PackedNormalX">[0x08..0x0A] Packed normal X, int16, scale = 1 / 32767.</param>
|
||||||
/// <param name="PackedNormalY">[0x0A..0x0C] Packed normal Y, int16, scale = 1 / 32767.</param>
|
/// <param name="PackedNormalY">[0x0A..0x0C] Packed normal Y, int16, scale = 1 / 32767.</param>
|
||||||
/// <param name="PackedNormalZ">[0x0C..0x0E] Packed normal Z, int16, scale = 1 / 32767.</param>
|
/// <param name="PackedNormalZ">[0x0C..0x0E] Packed normal Z, int16, scale = 1 / 32767.</param>
|
||||||
/// <param name="SelectorPacked">[0x0E..0x10] Packed selectors. Старое наблюдение: 3 трактуется как 0xFFFF.</param>
|
/// <param name="SelectorPacked">[0x0E..0x10] Packed selectors. 3 трактуется как 0xFFFF.</param>
|
||||||
public readonly record struct TriangleDescriptor(
|
public readonly record struct TriangleDescriptor(
|
||||||
TriangleFlags Flags,
|
TriangleFlags Flags,
|
||||||
ushort Link0,
|
ushort Link0,
|
||||||
|
|||||||
@@ -54,19 +54,19 @@ public static class Msh0x0D
|
|||||||
/// <param name="MaterialIndex">[0x02..0x04] Индекс material slot. Может быть overridden CAniMesh::forced_material_index.</param>
|
/// <param name="MaterialIndex">[0x02..0x04] Индекс material slot. Может быть overridden CAniMesh::forced_material_index.</param>
|
||||||
/// <param name="Opaque04">[0x04..0x06] Opaque. В GetBatchRenderData попадает в packed field вместе с material/lightmap данными.</param>
|
/// <param name="Opaque04">[0x04..0x06] Opaque. В GetBatchRenderData попадает в packed field вместе с material/lightmap данными.</param>
|
||||||
/// <param name="LocalBatchIndex">[0x06..0x08] Локальный batch index. В GetBatchRenderData складывается с MSH_piece.local_index_base / batch base.</param>
|
/// <param name="LocalBatchIndex">[0x06..0x08] Локальный batch index. В GetBatchRenderData складывается с MSH_piece.local_index_base / batch base.</param>
|
||||||
/// <param name="IndexCount">[0x08..0x0A] Количество индексов из component 0x06.</param>
|
/// <param name="IndexCount0x06">[0x08..0x0A] Количество индексов из component 0x06.</param>
|
||||||
/// <param name="IndexStart">[0x0A..0x0E] Первый индекс в component 0x06.</param>
|
/// <param name="IndexStart0x06">[0x0A..0x0E] Первый индекс в component 0x06.</param>
|
||||||
/// <param name="VertexCount">[0x0E..0x10] Количество вершин для render primitive.</param>
|
/// <param name="VertexCount0x03">[0x0E..0x10] Количество вершин для render primitive.</param>
|
||||||
/// <param name="BaseVertex">[0x10..0x14] Base vertex в vertex streams, включая position stream 0x03.</param>
|
/// <param name="BaseVertex0x03">[0x10..0x14] Base vertex в vertex streams, включая position stream 0x03.</param>
|
||||||
public readonly record struct Batch(
|
public readonly record struct Batch(
|
||||||
BatchFlags Flags,
|
BatchFlags Flags,
|
||||||
ushort MaterialIndex,
|
ushort MaterialIndex,
|
||||||
ushort Opaque04,
|
ushort Opaque04,
|
||||||
ushort LocalBatchIndex,
|
ushort LocalBatchIndex,
|
||||||
ushort IndexCount,
|
ushort IndexCount0x06,
|
||||||
uint IndexStart,
|
uint IndexStart0x06,
|
||||||
ushort VertexCount,
|
ushort VertexCount0x03,
|
||||||
uint BaseVertex);
|
uint BaseVertex0x03);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
|
|||||||
@@ -58,23 +58,6 @@ public static class Msh0x14
|
|||||||
return elements;
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Component 0x14 is optional in the game reader.
|
|
||||||
/// This helper mirrors that behavior and returns an empty list when absent.
|
|
||||||
/// </summary>
|
|
||||||
public static List<LightProbe> ReadComponentOrEmpty(
|
|
||||||
FileStream mshFs, NResArchive archive)
|
|
||||||
{
|
|
||||||
var entry = archive.Files.FirstOrDefault(x => x.FileType == "14 00 00 00");
|
|
||||||
|
|
||||||
if (entry is null)
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
return ReadComponent(mshFs, archive);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Light/probe entry 0x14.</summary>
|
/// <summary>Light/probe entry 0x14.</summary>
|
||||||
/// <param name="PieceIndex">[0x00..0x04] Индекс MSH_piece, чью world matrix используют для transform position/direction.</param>
|
/// <param name="PieceIndex">[0x00..0x04] Индекс MSH_piece, чью world matrix используют для transform position/direction.</param>
|
||||||
/// <param name="LocalPosition">[0x04..0x10] Локальная позиция источника/probe относительно PieceIndex.</param>
|
/// <param name="LocalPosition">[0x04..0x10] Локальная позиция источника/probe относительно PieceIndex.</param>
|
||||||
|
|||||||
@@ -82,7 +82,8 @@ public static class Msh0x15
|
|||||||
ushort PackedEdgeOrSelector);
|
ushort PackedEdgeOrSelector);
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum TerrainTriangleFlags {
|
public enum TerrainTriangleFlags : uint
|
||||||
|
{
|
||||||
MSH15_FLAG_REFLECTIVE_SURFACE = 0x20000,
|
MSH15_FLAG_REFLECTIVE_SURFACE = 0x20000,
|
||||||
MSH15_FLAG_HAS_MICROTEXTURE = 0x400,
|
MSH15_FLAG_HAS_MICROTEXTURE = 0x400,
|
||||||
MSH15_FLAG_DISABLE_BACKFACE_TEST = 0x8
|
MSH15_FLAG_DISABLE_BACKFACE_TEST = 0x8
|
||||||
|
|||||||
@@ -151,22 +151,22 @@ public sealed class MshConverter
|
|||||||
{
|
{
|
||||||
var batch = batches[batchIndex];
|
var batch = batches[batchIndex];
|
||||||
|
|
||||||
if (batch.IndexStart + batch.IndexCount > indices.Count)
|
if (batch.IndexStart0x06 + batch.IndexCount0x06 > indices.Count)
|
||||||
{
|
{
|
||||||
Warn($"Piece {pieceIndex}, batch {batchIndex}: index range {batch.IndexStart}:{batch.IndexCount} out of range");
|
Warn($"Piece {pieceIndex}, batch {batchIndex}: index range {batch.IndexStart0x06}:{batch.IndexCount0x06} out of range");
|
||||||
skippedBatches++;
|
skippedBatches++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.WriteLine($"# batch {batchIndex}, material {batch.MaterialIndex}, flags {batch.Flags}");
|
writer.WriteLine($"# batch {batchIndex}, material {batch.MaterialIndex}, flags {batch.Flags}");
|
||||||
|
|
||||||
for (var i = 0; i + 2 < batch.IndexCount; i += 3)
|
for (var i = 0; i + 2 < batch.IndexCount0x06; i += 3)
|
||||||
{
|
{
|
||||||
var indexBase = (int)batch.IndexStart + i;
|
var indexBase = (int)batch.IndexStart0x06 + i;
|
||||||
|
|
||||||
var v1 = checked((int)batch.BaseVertex + indices[indexBase + 0]);
|
var v1 = checked((int)batch.BaseVertex0x03 + indices[indexBase + 0]);
|
||||||
var v2 = checked((int)batch.BaseVertex + indices[indexBase + 1]);
|
var v2 = checked((int)batch.BaseVertex0x03 + indices[indexBase + 1]);
|
||||||
var v3 = checked((int)batch.BaseVertex + indices[indexBase + 2]);
|
var v3 = checked((int)batch.BaseVertex0x03 + indices[indexBase + 2]);
|
||||||
|
|
||||||
if (!IsValidTriangle(vertices.Count, v1, v2, v3))
|
if (!IsValidTriangle(vertices.Count, v1, v2, v3))
|
||||||
{
|
{
|
||||||
@@ -178,9 +178,9 @@ public sealed class MshConverter
|
|||||||
exportedFaces++;
|
exportedFaces++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (batch.IndexCount % 3 != 0)
|
if (batch.IndexCount0x06 % 3 != 0)
|
||||||
{
|
{
|
||||||
Warn($"Piece {pieceIndex}, batch {batchIndex}: index count {batch.IndexCount} is not divisible by 3");
|
Warn($"Piece {pieceIndex}, batch {batchIndex}: index count {batch.IndexCount0x06} is not divisible by 3");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user