mirror of
				https://github.com/sampletext32/ParkanPlayground.git
				synced 2025-11-04 07:19:45 +03:00 
			
		
		
		
	Hack .msh
This commit is contained in:
		@@ -32,23 +32,24 @@ public static class Msh01
 | 
				
			|||||||
                OffsetIntoFile13 =
 | 
					                OffsetIntoFile13 =
 | 
				
			||||||
                    BinaryPrimitives.ReadInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 4)),
 | 
					                    BinaryPrimitives.ReadInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 4)),
 | 
				
			||||||
                IndexInFile08 =
 | 
					                IndexInFile08 =
 | 
				
			||||||
                    BinaryPrimitives.ReadInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 6)),
 | 
					                    BinaryPrimitives.ReadInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 6))
 | 
				
			||||||
                State00 = BinaryPrimitives.ReadUInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 8)),
 | 
					 | 
				
			||||||
                State01 = BinaryPrimitives.ReadUInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 10)),
 | 
					 | 
				
			||||||
                State10 = BinaryPrimitives.ReadUInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 12)),
 | 
					 | 
				
			||||||
                State11 = BinaryPrimitives.ReadUInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 14)),
 | 
					 | 
				
			||||||
                State20 = BinaryPrimitives.ReadUInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 16)),
 | 
					 | 
				
			||||||
                State21 = BinaryPrimitives.ReadUInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 18)),
 | 
					 | 
				
			||||||
                S20 = BinaryPrimitives.ReadInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 20)),
 | 
					 | 
				
			||||||
                S22 = BinaryPrimitives.ReadInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 22)),
 | 
					 | 
				
			||||||
                S24 = BinaryPrimitives.ReadInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 24)),
 | 
					 | 
				
			||||||
                S26 = BinaryPrimitives.ReadInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 26)),
 | 
					 | 
				
			||||||
                S28 = BinaryPrimitives.ReadInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 28)),
 | 
					 | 
				
			||||||
                S30 = BinaryPrimitives.ReadInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 30)),
 | 
					 | 
				
			||||||
                S32 = BinaryPrimitives.ReadInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 32)),
 | 
					 | 
				
			||||||
                S34 = BinaryPrimitives.ReadInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 34)),
 | 
					 | 
				
			||||||
                S36 = BinaryPrimitives.ReadInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 36))
 | 
					 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            element.Lod[0] = BinaryPrimitives.ReadUInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 8));
 | 
				
			||||||
 | 
					            element.Lod[1] = BinaryPrimitives.ReadUInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 10));
 | 
				
			||||||
 | 
					            element.Lod[2] = BinaryPrimitives.ReadUInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 12));
 | 
				
			||||||
 | 
					            element.Lod[3] = BinaryPrimitives.ReadUInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 14));
 | 
				
			||||||
 | 
					            element.Lod[4] = BinaryPrimitives.ReadUInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 16));
 | 
				
			||||||
 | 
					            element.Lod[5] = BinaryPrimitives.ReadUInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 18));
 | 
				
			||||||
 | 
					            element.Lod[6] = BinaryPrimitives.ReadUInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 20));
 | 
				
			||||||
 | 
					            element.Lod[7] = BinaryPrimitives.ReadUInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 22));
 | 
				
			||||||
 | 
					            element.Lod[8] = BinaryPrimitives.ReadUInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 24));
 | 
				
			||||||
 | 
					            element.Lod[9] = BinaryPrimitives.ReadUInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 26));
 | 
				
			||||||
 | 
					            element.Lod[10] = BinaryPrimitives.ReadUInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 28));
 | 
				
			||||||
 | 
					            element.Lod[11] = BinaryPrimitives.ReadUInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 30));
 | 
				
			||||||
 | 
					            element.Lod[12] = BinaryPrimitives.ReadUInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 32));
 | 
				
			||||||
 | 
					            element.Lod[13] = BinaryPrimitives.ReadUInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 34));
 | 
				
			||||||
 | 
					            element.Lod[14] = BinaryPrimitives.ReadUInt16LittleEndian(dataSpan.Slice(i * headerFileEntry.ElementSize + 36));
 | 
				
			||||||
            elements.Add(element);
 | 
					            elements.Add(element);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -71,20 +72,6 @@ public static class Msh01
 | 
				
			|||||||
        public short ParentIndex { get; set; }
 | 
					        public short ParentIndex { get; set; }
 | 
				
			||||||
        public short OffsetIntoFile13 { get; set; }
 | 
					        public short OffsetIntoFile13 { get; set; }
 | 
				
			||||||
        public short IndexInFile08 { get; set; }
 | 
					        public short IndexInFile08 { get; set; }
 | 
				
			||||||
        public ushort State00 { get; set; }
 | 
					        public ushort[] Lod { get; set; } = new ushort[15];
 | 
				
			||||||
        public ushort State01 { get; set; }
 | 
					 | 
				
			||||||
        public ushort State10 { get; set; }
 | 
					 | 
				
			||||||
        public ushort State11 { get; set; }
 | 
					 | 
				
			||||||
        public ushort State20 { get; set; }
 | 
					 | 
				
			||||||
        public ushort State21 { get; set; }
 | 
					 | 
				
			||||||
        public short S20 { get; set; }
 | 
					 | 
				
			||||||
        public short S22 { get; set; }
 | 
					 | 
				
			||||||
        public short S24 { get; set; }
 | 
					 | 
				
			||||||
        public short S26 { get; set; }
 | 
					 | 
				
			||||||
        public short S28 { get; set; }
 | 
					 | 
				
			||||||
        public short S30 { get; set; }
 | 
					 | 
				
			||||||
        public short S32 { get; set; }
 | 
					 | 
				
			||||||
        public short S34 { get; set; }
 | 
					 | 
				
			||||||
        public short S36 { get; set; }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -159,18 +159,6 @@ public static class Msh02
 | 
				
			|||||||
        public float XYRadius { get; set; }
 | 
					        public float XYRadius { get; set; }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public class BoundingBox
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        public Vector3 Vec1 { get; set; }
 | 
					 | 
				
			||||||
        public Vector3 Vec2 { get; set; }
 | 
					 | 
				
			||||||
        public Vector3 Vec3 { get; set; }
 | 
					 | 
				
			||||||
        public Vector3 Vec4 { get; set; }
 | 
					 | 
				
			||||||
        public Vector3 Vec5 { get; set; }
 | 
					 | 
				
			||||||
        public Vector3 Vec6 { get; set; }
 | 
					 | 
				
			||||||
        public Vector3 Vec7 { get; set; }
 | 
					 | 
				
			||||||
        public Vector3 Vec8 { get; set; }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public class Msh02Element
 | 
					    public class Msh02Element
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public ushort StartIndexIn07 { get; set; }
 | 
					        public ushort StartIndexIn07 { get; set; }
 | 
				
			||||||
@@ -183,4 +171,16 @@ public static class Msh02
 | 
				
			|||||||
        public Vector3 Vector4 { get; set; }
 | 
					        public Vector3 Vector4 { get; set; }
 | 
				
			||||||
        public Vector3 Vector5 { get; set; }
 | 
					        public Vector3 Vector5 { get; set; }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public class BoundingBox
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public Vector3 Vec1 { get; set; }
 | 
				
			||||||
 | 
					        public Vector3 Vec2 { get; set; }
 | 
				
			||||||
 | 
					        public Vector3 Vec3 { get; set; }
 | 
				
			||||||
 | 
					        public Vector3 Vec4 { get; set; }
 | 
				
			||||||
 | 
					        public Vector3 Vec5 { get; set; }
 | 
				
			||||||
 | 
					        public Vector3 Vec6 { get; set; }
 | 
				
			||||||
 | 
					        public Vector3 Vec7 { get; set; }
 | 
				
			||||||
 | 
					        public Vector3 Vec8 { get; set; }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										35
									
								
								ParkanPlayground/Msh03.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								ParkanPlayground/Msh03.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					using System.Buffers.Binary;
 | 
				
			||||||
 | 
					using Common;
 | 
				
			||||||
 | 
					using NResLib;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ParkanPlayground;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class Msh03
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public static List<Vector3> ReadComponent(FileStream mshFs, NResArchive mshNres)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        var verticesFileEntry = mshNres.Files.FirstOrDefault(x => x.FileType == "03 00 00 00");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (verticesFileEntry is null)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            throw new Exception("Archive doesn't contain vertices file (03)");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (verticesFileEntry.ElementSize != 12)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            throw new Exception("Vertices file (03) element size is not 12");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var verticesFile = new byte[verticesFileEntry.ElementCount * verticesFileEntry.ElementSize];
 | 
				
			||||||
 | 
					        mshFs.Seek(verticesFileEntry.OffsetInFile, SeekOrigin.Begin);
 | 
				
			||||||
 | 
					        mshFs.ReadExactly(verticesFile, 0, verticesFile.Length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var vertices = verticesFile.Chunk(12).Select(x => new Vector3(
 | 
				
			||||||
 | 
					                BinaryPrimitives.ReadSingleLittleEndian(x.AsSpan(0)),
 | 
				
			||||||
 | 
					                BinaryPrimitives.ReadSingleLittleEndian(x.AsSpan(4)),
 | 
				
			||||||
 | 
					                BinaryPrimitives.ReadSingleLittleEndian(x.AsSpan(8))
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        ).ToList();
 | 
				
			||||||
 | 
					        return vertices;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -25,7 +25,8 @@ public static class Msh07
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            Flags = BinaryPrimitives.ReadUInt16LittleEndian(x.AsSpan(0)),
 | 
					            Flags = BinaryPrimitives.ReadUInt16LittleEndian(x.AsSpan(0)),
 | 
				
			||||||
            Magic02 = BinaryPrimitives.ReadUInt16LittleEndian(x.AsSpan(2)),
 | 
					            Magic02 = BinaryPrimitives.ReadUInt16LittleEndian(x.AsSpan(2)),
 | 
				
			||||||
            Magic04 = BinaryPrimitives.ReadUInt32LittleEndian(x.AsSpan(4)),
 | 
					            Magic04 = BinaryPrimitives.ReadUInt16LittleEndian(x.AsSpan(4)),
 | 
				
			||||||
 | 
					            Magic06 = BinaryPrimitives.ReadUInt16LittleEndian(x.AsSpan(6)),
 | 
				
			||||||
            OffsetX = BinaryPrimitives.ReadInt16LittleEndian(x.AsSpan(8)),
 | 
					            OffsetX = BinaryPrimitives.ReadInt16LittleEndian(x.AsSpan(8)),
 | 
				
			||||||
            OffsetY = BinaryPrimitives.ReadInt16LittleEndian(x.AsSpan(10)),
 | 
					            OffsetY = BinaryPrimitives.ReadInt16LittleEndian(x.AsSpan(10)),
 | 
				
			||||||
            OffsetZ = BinaryPrimitives.ReadInt16LittleEndian(x.AsSpan(12)),
 | 
					            OffsetZ = BinaryPrimitives.ReadInt16LittleEndian(x.AsSpan(12)),
 | 
				
			||||||
@@ -39,7 +40,8 @@ public static class Msh07
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        public ushort Flags { get; set; }
 | 
					        public ushort Flags { get; set; }
 | 
				
			||||||
        public ushort Magic02 { get; set; }
 | 
					        public ushort Magic02 { get; set; }
 | 
				
			||||||
        public uint Magic04 { get; set; }
 | 
					        public ushort Magic04 { get; set; }
 | 
				
			||||||
 | 
					        public ushort Magic06 { get; set; }
 | 
				
			||||||
        // normalized vector X, need to divide by 32767 to get float in range -1..1
 | 
					        // normalized vector X, need to divide by 32767 to get float in range -1..1
 | 
				
			||||||
        public short OffsetX { get; set; }
 | 
					        public short OffsetX { get; set; }
 | 
				
			||||||
        // normalized vector Y, need to divide by 32767 to get float in range -1..1
 | 
					        // normalized vector Y, need to divide by 32767 to get float in range -1..1
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,11 +26,12 @@ public static class Msh0D
 | 
				
			|||||||
        var elements = elementBytes.Select(x => new Msh0DElement()
 | 
					        var elements = elementBytes.Select(x => new Msh0DElement()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Flags = BinaryPrimitives.ReadUInt16LittleEndian(x.AsSpan(0)),
 | 
					            Flags = BinaryPrimitives.ReadUInt16LittleEndian(x.AsSpan(0)),
 | 
				
			||||||
            Magic04 = BinaryPrimitives.ReadUInt32LittleEndian(x.AsSpan(4)),
 | 
					            Magic04 = BinaryPrimitives.ReadUInt16LittleEndian(x.AsSpan(4)),
 | 
				
			||||||
            number_of_triangles = BinaryPrimitives.ReadUInt16LittleEndian(x.AsSpan(8)),
 | 
					            Magic06 = BinaryPrimitives.ReadUInt16LittleEndian(x.AsSpan(6)),
 | 
				
			||||||
            IndexInto06 = BinaryPrimitives.ReadInt32LittleEndian(x.AsSpan(10)),
 | 
					            CountOf06 = BinaryPrimitives.ReadUInt16LittleEndian(x.AsSpan(8)),
 | 
				
			||||||
            Magic0C = BinaryPrimitives.ReadUInt16LittleEndian(x.AsSpan(14)),
 | 
					            IndexInto06 = BinaryPrimitives.ReadInt32LittleEndian(x.AsSpan(0xA)),
 | 
				
			||||||
            IndexInto03 = BinaryPrimitives.ReadInt32LittleEndian(x.AsSpan(16)),
 | 
					            CountOf03 = BinaryPrimitives.ReadUInt16LittleEndian(x.AsSpan(0xE)),
 | 
				
			||||||
 | 
					            IndexInto03 = BinaryPrimitives.ReadInt32LittleEndian(x.AsSpan(0x10)),
 | 
				
			||||||
        }).ToList();
 | 
					        }).ToList();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return elements;
 | 
					        return elements;
 | 
				
			||||||
@@ -39,10 +40,14 @@ public static class Msh0D
 | 
				
			|||||||
    public class Msh0DElement
 | 
					    public class Msh0DElement
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public uint Flags { get; set; }
 | 
					        public uint Flags { get; set; }
 | 
				
			||||||
        public uint Magic04 { get; set; }
 | 
					        
 | 
				
			||||||
        public ushort number_of_triangles { get; set; }
 | 
					        // Magic04 и Magic06 обрабатываются вместе
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public ushort Magic04 { get; set; }
 | 
				
			||||||
 | 
					        public ushort Magic06 { get; set; }
 | 
				
			||||||
 | 
					        public ushort CountOf06 { get; set; }
 | 
				
			||||||
        public int IndexInto06 { get; set; }
 | 
					        public int IndexInto06 { get; set; }
 | 
				
			||||||
        public ushort Magic0C { get; set; }
 | 
					        public ushort CountOf03 { get; set; }
 | 
				
			||||||
        public int IndexInto03 { get; set; }
 | 
					        public int IndexInto03 { get; set; }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
using System.Buffers.Binary;
 | 
					using System.Buffers.Binary;
 | 
				
			||||||
 | 
					using System.Globalization;
 | 
				
			||||||
using System.Text;
 | 
					using System.Text;
 | 
				
			||||||
using Common;
 | 
					using Common;
 | 
				
			||||||
using NResLib;
 | 
					using NResLib;
 | 
				
			||||||
@@ -19,11 +20,17 @@ public class MshConverter
 | 
				
			|||||||
        var component0A = Msh0A.ReadComponent(mshFs, mshNres);
 | 
					        var component0A = Msh0A.ReadComponent(mshFs, mshNres);
 | 
				
			||||||
        var component07 = Msh07.ReadComponent(mshFs, mshNres);
 | 
					        var component07 = Msh07.ReadComponent(mshFs, mshNres);
 | 
				
			||||||
        var component0D = Msh0D.ReadComponent(mshFs, mshNres);
 | 
					        var component0D = Msh0D.ReadComponent(mshFs, mshNres);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Triangle Vertex Indices
 | 
				
			||||||
        var component06 = Msh06.ReadComponent(mshFs, mshNres);
 | 
					        var component06 = Msh06.ReadComponent(mshFs, mshNres);
 | 
				
			||||||
        var component03 = Read03Component(mshFs, mshNres);
 | 
					
 | 
				
			||||||
 | 
					        // vertices
 | 
				
			||||||
 | 
					        var component03 = Msh03.ReadComponent(mshFs, mshNres);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _ = 5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // --- Write OBJ ---
 | 
					        // --- Write OBJ ---
 | 
				
			||||||
        using var sw = new StreamWriter("test.obj", false, Encoding.UTF8);
 | 
					        using var sw = new StreamWriter("test.obj", false, new UTF8Encoding(false));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach (var v in component03)
 | 
					        foreach (var v in component03)
 | 
				
			||||||
            sw.WriteLine($"v {v.X:F8} {v.Y:F8} {v.Z:F8}");
 | 
					            sw.WriteLine($"v {v.X:F8} {v.Y:F8} {v.Z:F8}");
 | 
				
			||||||
@@ -31,79 +38,168 @@ public class MshConverter
 | 
				
			|||||||
        var vertices = new List<Vector3>();
 | 
					        var vertices = new List<Vector3>();
 | 
				
			||||||
        var faces = new List<(int, int, int)>(); // store indices into vertices list
 | 
					        var faces = new List<(int, int, int)>(); // store indices into vertices list
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 01 - это части меша (Piece)
 | 
				
			||||||
        for (var pieceIndex = 0; pieceIndex < component01.Elements.Count; pieceIndex++)
 | 
					        for (var pieceIndex = 0; pieceIndex < component01.Elements.Count; pieceIndex++)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var piece = component01.Elements[pieceIndex];
 | 
					            var piece01 = component01.Elements[pieceIndex];
 | 
				
			||||||
            var state = (piece.State00 == 0xffff) ? 0 : piece.State00;
 | 
					            // var state = (piece.State00 == 0xffff) ? 0 : piece.State00;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var mesh02Element = component02.Elements[state];
 | 
					            for (var lodIndex = 0; lodIndex < piece01.Lod.Length; lodIndex++)
 | 
				
			||||||
 | 
					 | 
				
			||||||
            int indexInto07 = mesh02Element.StartIndexIn07;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            var element0Dstart = mesh02Element.StartOffsetIn0d;
 | 
					 | 
				
			||||||
            var element0Dcount = mesh02Element.ByteLengthIn0D;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            Console.WriteLine($"Started piece {pieceIndex}. State={state}. 0D start={element0Dstart}, count={element0Dcount}");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            for (var comp0Dindex = 0; comp0Dindex < element0Dcount; comp0Dindex++)
 | 
					 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var element0D = component0D[element0Dstart + comp0Dindex];
 | 
					                var lod = piece01.Lod[lodIndex];
 | 
				
			||||||
 | 
					                if (lod == 0xffff)
 | 
				
			||||||
                var indexInto03 = element0D.IndexInto03;
 | 
					 | 
				
			||||||
                var indexInto06 = element0D.IndexInto06;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                var count = (uint)element0D.number_of_triangles;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                // Convert IndexInto06 to ushort array index (3 ushorts per triangle)
 | 
					 | 
				
			||||||
                Console.WriteLine(
 | 
					 | 
				
			||||||
                    $"Processing 0D element[{element0Dstart + comp0Dindex}]. IndexInto03={indexInto03}, IndexInto06={indexInto06}. Number of triangles={count}");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if (count != 0)
 | 
					 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    sw.WriteLine($"o piece_{pieceIndex++}_of_mesh_{comp0Dindex}");
 | 
					                    Console.WriteLine($"Piece {pieceIndex} has lod -1 at {lodIndex}. Skipping");
 | 
				
			||||||
                    if (count % 3 != 0)
 | 
					                    continue;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                sw.WriteLine($"o piece_{pieceIndex}_lod_{lodIndex}");
 | 
				
			||||||
 | 
					                // 02 - Submesh
 | 
				
			||||||
 | 
					                var part02 = component02.Elements[lod];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                int indexInto07 = part02.StartIndexIn07;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                var element0Dstart = part02.StartOffsetIn0d;
 | 
				
			||||||
 | 
					                var element0Dcount = part02.ByteLengthIn0D;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // Console.WriteLine($"Started piece {pieceIndex}. LOD={lod}. 0D start={element0Dstart}, count={element0Dcount}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                for (var comp0Dindex = 0; comp0Dindex < element0Dcount; comp0Dindex++)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    var element0D = component0D[element0Dstart + comp0Dindex];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    var indexInto03 = element0D.IndexInto03;
 | 
				
			||||||
 | 
					                    var indexInto06 = element0D.IndexInto06; // indices
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    uint maxIndex = element0D.CountOf03;
 | 
				
			||||||
 | 
					                    uint indicesCount = element0D.CountOf06;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    // Convert IndexInto06 to ushort array index (3 ushorts per triangle)
 | 
				
			||||||
 | 
					                    // Console.WriteLine($"Processing 0D element[{element0Dstart + comp0Dindex}]. IndexInto03={indexInto03}, IndexInto06={indexInto06}. Number of triangles={indicesCount}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (indicesCount != 0)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        Console.WriteLine("Number of triangles is not multiple of 3");
 | 
					                        // sw.WriteLine($"o piece_{pieceIndex}_of_mesh_{comp0Dindex}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        for (int ind = 0; ind < indicesCount; ind += 3)
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            // Each triangle uses 3 consecutive ushorts in component06
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            // sw.WriteLine($"o piece_{pieceIndex}_of_mesh_{comp0Dindex}_tri_{ind}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            var comp07 = component07[indexInto07];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            var i1 = indexInto03 + component06[indexInto06];
 | 
				
			||||||
 | 
					                            var i2 = indexInto03 + component06[indexInto06 + 1];
 | 
				
			||||||
 | 
					                            var i3 = indexInto03 + component06[indexInto06 + 2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            var v1 = component03[i1];
 | 
				
			||||||
 | 
					                            var v2 = component03[i2];
 | 
				
			||||||
 | 
					                            var v3 = component03[i3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            sw.WriteLine($"f {i1 + 1} {i2 + 1} {i3 + 1}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            // push vertices to global list
 | 
				
			||||||
 | 
					                            vertices.Add(v1);
 | 
				
			||||||
 | 
					                            vertices.Add(v2);
 | 
				
			||||||
 | 
					                            vertices.Add(v3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            int baseIndex = vertices.Count;
 | 
				
			||||||
 | 
					                            // record face (OBJ is 1-based indexing!)
 | 
				
			||||||
 | 
					                            faces.Add((baseIndex - 2, baseIndex - 1, baseIndex));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            indexInto07++;
 | 
				
			||||||
 | 
					                            indexInto06 += 3; // step by 3 since each triangle uses 3 ushorts
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        _ = 5;
 | 
					                        _ = 5;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
                    count = (count + 2) / 3; // number of triangles
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    for (int tri = 0; tri < count; tri++)
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        // Each triangle uses 3 consecutive ushorts in component06
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        var comp07 = component07[indexInto07];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        var i1 = indexInto03 + component06[indexInto06];
 | 
					 | 
				
			||||||
                        var i2 = indexInto03 + component06[indexInto06 + 1];
 | 
					 | 
				
			||||||
                        var i3 = indexInto03 + component06[indexInto06 + 2];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        var v1 = component03[i1];
 | 
					 | 
				
			||||||
                        var v2 = component03[i2];
 | 
					 | 
				
			||||||
                        var v3 = component03[i3];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        sw.WriteLine($"f {i1 + 1} {i2 + 1} {i3 + 1}");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        // push vertices to global list
 | 
					 | 
				
			||||||
                        vertices.Add(v1);
 | 
					 | 
				
			||||||
                        vertices.Add(v2);
 | 
					 | 
				
			||||||
                        vertices.Add(v3);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        int baseIndex = vertices.Count;
 | 
					 | 
				
			||||||
                        // record face (OBJ is 1-based indexing!)
 | 
					 | 
				
			||||||
                        faces.Add((baseIndex - 2, baseIndex - 1, baseIndex));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        indexInto07++;
 | 
					 | 
				
			||||||
                        indexInto06 += 3; // step by 3 since each triangle uses 3 ushorts
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    _ = 5;
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void Convert2(string mshPath)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        var mshNresResult = NResParser.ReadFile(mshPath);
 | 
				
			||||||
 | 
					        var mshNres = mshNresResult.Archive!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        using var mshFs = new FileStream(mshPath, FileMode.Open, FileAccess.Read, FileShare.Read);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var component01 = Msh01.ReadComponent(mshFs, mshNres);
 | 
				
			||||||
 | 
					        var component02 = Msh02.ReadComponent(mshFs, mshNres);
 | 
				
			||||||
 | 
					        var component0A = Msh0A.ReadComponent(mshFs, mshNres);
 | 
				
			||||||
 | 
					        var component07 = Msh07.ReadComponent(mshFs, mshNres);
 | 
				
			||||||
 | 
					        var component0D = Msh0D.ReadComponent(mshFs, mshNres);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Triangle Vertex Indices
 | 
				
			||||||
 | 
					        var component06 = Msh06.ReadComponent(mshFs, mshNres);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // vertices
 | 
				
			||||||
 | 
					        var component03 = Msh03.ReadComponent(mshFs, mshNres);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var csv06 = new StreamWriter("06.csv", false, Encoding.UTF8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (var i = 0; i < component06.Count; i += 3)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // csv06.WriteLine($"{component06[i]}");
 | 
				
			||||||
 | 
					            csv06.WriteLine($"{component06[i]}, {component06[i + 1]}, {component06[i + 2]}");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        csv06.Dispose();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var csv03 = new StreamWriter("03.obj", false, Encoding.UTF8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        csv03.WriteLine();
 | 
				
			||||||
 | 
					        for (var i = 7525; i < component03.Count; i++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // csv06.WriteLine($"{component06[i]}");
 | 
				
			||||||
 | 
					            // csv03.WriteAsync($"o {i - 7525}");
 | 
				
			||||||
 | 
					            csv03.WriteLine(
 | 
				
			||||||
 | 
					                $"v {component03[i].X.ToString("F2", CultureInfo.InvariantCulture)} {component03[i].Y.ToString("F2", CultureInfo.InvariantCulture)} {component03[i].Z.ToString("F2", CultureInfo.InvariantCulture)}");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (var i = 10485; i < component06.Count; i += 3)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            csv03.WriteLine($"f {component06[i] + 1} {component06[i + 1] + 1} {component06[i + 2] + 1}");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        csv03.Dispose();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // --- Write OBJ ---
 | 
				
			||||||
 | 
					        using var sw = new StreamWriter("test.obj", false, Encoding.UTF8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (var index = 0; index < component03.Count; index++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var v = component03[index];
 | 
				
			||||||
 | 
					            sw.WriteLine($"v {v.X:F8} {v.Y:F8} {v.Z:F8}");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (var i = 0; i < 1; i++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            sw.WriteLine($"o elem_0d_{i}");
 | 
				
			||||||
 | 
					            var element0D = component0D[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Console.WriteLine($"Processing element 0D [{i}]:");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var elementsOf06 = component06
 | 
				
			||||||
 | 
					                .Skip(element0D.IndexInto06)
 | 
				
			||||||
 | 
					                .Take(element0D.CountOf06)
 | 
				
			||||||
 | 
					                .ToList();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Console.WriteLine($"\tCount of 06: {elementsOf06.Count}, starting from {element0D.IndexInto06}");
 | 
				
			||||||
 | 
					            var indexInto03 = element0D.IndexInto03;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Console.WriteLine($"\tIndexInto03: {indexInto03}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (elementsOf06.Count < 3)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                throw new Exception("Less than 3 points");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public record Face(Vector3 P1, Vector3 P2, Vector3 P3);
 | 
					    public record Face(Vector3 P1, Vector3 P2, Vector3 P3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static void ExportCube(string filePath, Vector3[] points)
 | 
					    public static void ExportCube(string filePath, Vector3[] points)
 | 
				
			||||||
@@ -189,34 +285,6 @@ public class MshConverter
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    private static List<Vector3> Read03Component(FileStream mshFs, NResArchive mshNres)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        var verticesFileEntry = mshNres.Files.FirstOrDefault(x => x.FileType == "03 00 00 00");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (verticesFileEntry is null)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            throw new Exception("Archive doesn't contain vertices file (03)");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (verticesFileEntry.ElementSize != 12)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            throw new Exception("Vertices file (03) element size is not 12");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        var verticesFile = new byte[verticesFileEntry.ElementCount * verticesFileEntry.ElementSize];
 | 
					 | 
				
			||||||
        mshFs.Seek(verticesFileEntry.OffsetInFile, SeekOrigin.Begin);
 | 
					 | 
				
			||||||
        mshFs.ReadExactly(verticesFile, 0, verticesFile.Length);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        var vertices = verticesFile.Chunk(12).Select(x => new Vector3(
 | 
					 | 
				
			||||||
                BinaryPrimitives.ReadSingleLittleEndian(x.AsSpan(0)),
 | 
					 | 
				
			||||||
                BinaryPrimitives.ReadSingleLittleEndian(x.AsSpan(4)),
 | 
					 | 
				
			||||||
                BinaryPrimitives.ReadSingleLittleEndian(x.AsSpan(8))
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
        ).ToList();
 | 
					 | 
				
			||||||
        return vertices;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void Export(string filePath, IEnumerable<Vector3> vertices, List<IndexedEdge> edges)
 | 
					    void Export(string filePath, IEnumerable<Vector3> vertices, List<IndexedEdge> edges)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        using (var writer = new StreamWriter(filePath))
 | 
					        using (var writer = new StreamWriter(filePath))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
using System.Buffers.Binary;
 | 
					using System.Buffers.Binary;
 | 
				
			||||||
using Common;
 | 
					using Common;
 | 
				
			||||||
using MissionTmaLib.Parsing;
 | 
					using MissionTmaLib.Parsing;
 | 
				
			||||||
using NResLib;
 | 
					using NResLib;
 | 
				
			||||||
@@ -10,6 +10,7 @@ using ParkanPlayground;
 | 
				
			|||||||
var converter = new MshConverter();
 | 
					var converter = new MshConverter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
converter.Convert("E:\\ParkanUnpacked\\fortif.rlb\\133_fr_m_bunker.msh");
 | 
					converter.Convert("E:\\ParkanUnpacked\\fortif.rlb\\133_fr_m_bunker.msh");
 | 
				
			||||||
 | 
					// converter.Convert("E:\\ParkanUnpacked\\fortif.rlb\\73_fr_m_brige.msh");
 | 
				
			||||||
// converter.Convert("E:\\ParkanUnpacked\\intsys.rlb\\277_MESH_o_pws_l_01.msh");
 | 
					// converter.Convert("E:\\ParkanUnpacked\\intsys.rlb\\277_MESH_o_pws_l_01.msh");
 | 
				
			||||||
// converter.Convert("E:\\ParkanUnpacked\\static.rlb\\2_MESH_s_stn_0_01.msh");
 | 
					// converter.Convert("E:\\ParkanUnpacked\\static.rlb\\2_MESH_s_stn_0_01.msh");
 | 
				
			||||||
// converter.Convert("E:\\ParkanUnpacked\\bases.rlb\\25_MESH_R_H_02.msh");
 | 
					// converter.Convert("E:\\ParkanUnpacked\\bases.rlb\\25_MESH_R_H_02.msh");
 | 
				
			||||||
							
								
								
									
										72
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										72
									
								
								README.md
									
									
									
									
									
								
							@@ -87,6 +87,10 @@ grep -rlU $'\x73\x5f\x74\x72\x65\x65\x5f\x30\x35' .
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Затем `Comp.ini` - тут системные функции, которые используются для загрузки объектов.
 | 
					Затем `Comp.ini` - тут системные функции, которые используются для загрузки объектов.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					IComponent ** LoadSomething(undefined4, undefined4, undefined4, undefined4)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- `Host.url` - этого файла нет
 | 
					- `Host.url` - этого файла нет
 | 
				
			||||||
- `palettes.lib` - тут палитры, но этот NRes пустой
 | 
					- `palettes.lib` - тут палитры, но этот NRes пустой
 | 
				
			||||||
- `system.rlb` - не понятно что
 | 
					- `system.rlb` - не понятно что
 | 
				
			||||||
@@ -211,17 +215,16 @@ grep -rlU $'\x73\x5f\x74\x72\x65\x65\x5f\x30\x35' .
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Загружается в `AniMesh.dll/LoadAniMesh`
 | 
					Загружается в `AniMesh.dll/LoadAniMesh`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Тип 01 - заголовок
 | 
					- Тип 01 - заголовок. Он хранит список деталей (submesh) в разных LOD
 | 
				
			||||||
  ```
 | 
					  ```
 | 
				
			||||||
  нулевому элементу добавляется флаг 0x1000000
 | 
					  нулевому элементу добавляется флаг 0x1000000
 | 
				
			||||||
  Хранит стейты меша (в один стейт может входить несколько submesh)
 | 
					 | 
				
			||||||
  Содержит 2 ссылки на файлы анимаций (короткие - файл 13, длинные - файл 08)
 | 
					  Содержит 2 ссылки на файлы анимаций (короткие - файл 13, длинные - файл 08)
 | 
				
			||||||
  Если интерполируется анимация -0.5s короче чем magic1 у файла 13
 | 
					  Если интерполируется анимация -0.5s короче чем magic1 у файла 13
 | 
				
			||||||
  И у файла есть OffsetIntoFile13
 | 
					  И у файла есть OffsetIntoFile13
 | 
				
			||||||
  И ushort значение в файле 13 по этому оффсету > IndexInFile08 (это по-моему выполняется всегда)
 | 
					  И ushort значение в файле 13 по этому оффсету > IndexInFile08 (это по-моему выполняется всегда)
 | 
				
			||||||
  Тогда вместо IndexInFile08 используется значение из файла 13 по этому оффсету (второй байт)
 | 
					  Тогда вместо IndexInFile08 используется значение из файла 13 по этому оффсету (второй байт)
 | 
				
			||||||
  ```
 | 
					  ```
 | 
				
			||||||
- Тип 02 - описание submesh
 | 
					- Тип 02 - описание одного LOD Submesh
 | 
				
			||||||
  ```
 | 
					  ```
 | 
				
			||||||
  Вначале идёт заголовок 0x8C (140) байт
 | 
					  Вначале идёт заголовок 0x8C (140) байт
 | 
				
			||||||
  В заголовке:
 | 
					  В заголовке:
 | 
				
			||||||
@@ -233,7 +236,7 @@ grep -rlU $'\x73\x5f\x74\x72\x65\x65\x5f\x30\x35' .
 | 
				
			|||||||
  Далее инфа про куски меша
 | 
					  Далее инфа про куски меша
 | 
				
			||||||
  ```
 | 
					  ```
 | 
				
			||||||
- Тип 03 - это вершины (vertex)
 | 
					- Тип 03 - это вершины (vertex)
 | 
				
			||||||
- Тип 06 - 
 | 
					- Тип 06 - индексы треугольников в файле 03
 | 
				
			||||||
- Тип 04 - скорее всего какие-то цвета RGBA или типа того
 | 
					- Тип 04 - скорее всего какие-то цвета RGBA или типа того
 | 
				
			||||||
- Тип 08 - меш-анимации (см файл 01)
 | 
					- Тип 08 - меш-анимации (см файл 01)
 | 
				
			||||||
  ```
 | 
					  ```
 | 
				
			||||||
@@ -257,21 +260,19 @@ grep -rlU $'\x73\x5f\x74\x72\x65\x65\x5f\x30\x35' .
 | 
				
			|||||||
  Буквально (hex)
 | 
					  Буквально (hex)
 | 
				
			||||||
  00 01 01 02 ...
 | 
					  00 01 01 02 ...
 | 
				
			||||||
  ```
 | 
					  ```
 | 
				
			||||||
- Тип 0A
 | 
					- Тип 0A - ссылка на части меша, не упакованные в текущий меш (например у бункера 4 и 5 части хранятся в parts.rlb)
 | 
				
			||||||
  ```
 | 
					  ```
 | 
				
			||||||
  Не имеет фиксированной длины. Хранит какие-то строки в следующем формате.
 | 
					  Не имеет фиксированной длины. Хранит строки в следующем формате.
 | 
				
			||||||
  Игра обращается по индексу, пропуская суммарную длину и пропуская 4 байта на каждую строку (длина).
 | 
					  Игра обращается по индексу, пропуская суммарную длину и пропуская 4 байта на каждую строку (длина).
 | 
				
			||||||
  т.е. буквально файл выглядит так
 | 
					  т.е. буквально файл выглядит так
 | 
				
			||||||
  00 00 00 00 - пустая строка
 | 
					  00 00 00 00 - пустая строка
 | 
				
			||||||
  03 00 00 00 - длина строки 1
 | 
					  03 00 00 00 - длина строки 1
 | 
				
			||||||
  73 74 72 00 - строка "str" + null terminator
 | 
					  73 74 72 00 - строка "str" + null terminator
 | 
				
			||||||
  .. и повторяется до конца файла
 | 
					  .. и повторяется до конца файла
 | 
				
			||||||
  Кол-во элементов из NRes должно быть равно кол-ву строк в этом файле, хотя игра это не проверяет.
 | 
					  Кол-во элементов из файла 01 должно быть равно кол-ву строк в этом файле, хотя игра это не проверяет.
 | 
				
			||||||
  Если у элемента эта строка равна "central", ему выставляется флаг (flag |= 1)
 | 
					  Если у элемента эта строка равна "central", ему выставляется флаг (flag |= 1)
 | 
				
			||||||
  ```
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Тип 02 имеет заголовок 140 байт.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## `.wea`
 | 
					## `.wea`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Загружается в `World3D.dll/LoadMatManager`
 | 
					Загружается в `World3D.dll/LoadMatManager`
 | 
				
			||||||
@@ -289,26 +290,32 @@ grep -rlU $'\x73\x5f\x74\x72\x65\x65\x5f\x30\x35' .
 | 
				
			|||||||
- `0xb` - IAnimation
 | 
					- `0xb` - IAnimation
 | 
				
			||||||
- `0xd` - IMatManager
 | 
					- `0xd` - IMatManager
 | 
				
			||||||
- `0xe` - ILightManager
 | 
					- `0xe` - ILightManager
 | 
				
			||||||
- `0x10` - unknown (implemented by Wizard in Wizard.dll, also by Hallway in ArealMap.dll)
 | 
					- `0x10` - IBehavior
 | 
				
			||||||
- `0x11` - IBasement
 | 
					- `0x11` - IBasement
 | 
				
			||||||
- `0x12` - ICamera2 - BufferingCamera
 | 
					- `0x12` - ICamera2 или IBufferingCamera
 | 
				
			||||||
- `0x13` - IEffectManager
 | 
					- `0x13` - IEffectManager
 | 
				
			||||||
- `0x14` - IPosition
 | 
					- `0x14` - IPosition
 | 
				
			||||||
 | 
					- `0x15` - IAgent
 | 
				
			||||||
- `0x16` - ILifeSystem
 | 
					- `0x16` - ILifeSystem
 | 
				
			||||||
- `0x17` - IBuilding
 | 
					- `0x17` - IBuilding - точно он, т.к. ArealMap.CreateObject на него проверяет
 | 
				
			||||||
- `0x18` - IMesh2
 | 
					- `0x18` - IMesh2
 | 
				
			||||||
- `0x19` - unknown (implemented by Wizard in Wizard.dll, also by Agent in AniMesh.dll)
 | 
					- `0x19` - IManManager
 | 
				
			||||||
- `0x20` - IJointMesh
 | 
					- `0x20` - IJointMesh
 | 
				
			||||||
- `0x21` - IShade
 | 
					- `0x21` - IShade
 | 
				
			||||||
- `0x23` - IGameSettings
 | 
					- `0x23` - IGameSettings
 | 
				
			||||||
- `0x24` - IGameObject2
 | 
					- `0x24` - IGameObject2
 | 
				
			||||||
 | 
					- `0x25` - unknown (implemented by AniMesh)
 | 
				
			||||||
 | 
					- `0x26` - unknown (implemented by AniMesh)
 | 
				
			||||||
 | 
					- `0x28` - ICollObject
 | 
				
			||||||
- `0x101` - 3DRender
 | 
					- `0x101` - 3DRender
 | 
				
			||||||
 | 
					- `0x105` - NResFile
 | 
				
			||||||
- `0x201` - IWizard
 | 
					- `0x201` - IWizard
 | 
				
			||||||
- `0x202` - IItemManager
 | 
					- `0x202` - IItemManager
 | 
				
			||||||
- `0x203` - ICollManager
 | 
					- `0x203` - ICollManager
 | 
				
			||||||
- `0x301` - IArealMap
 | 
					- `0x301` - IArealMap
 | 
				
			||||||
- `0x302` - ISystemArealMap
 | 
					- `0x302` - ISystemArealMap
 | 
				
			||||||
- `0x303` - IHallway
 | 
					- `0x303` - IHallway
 | 
				
			||||||
 | 
					- `0x304` - Distributor
 | 
				
			||||||
- `0x401` - ISuperAI
 | 
					- `0x401` - ISuperAI
 | 
				
			||||||
- `0x105` - NResFile
 | 
					- `0x105` - NResFile
 | 
				
			||||||
- `0x106` - NResFileMetadata
 | 
					- `0x106` - NResFileMetadata
 | 
				
			||||||
@@ -329,25 +336,26 @@ World3D.dll содержит функцию CreateGameSettings.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Остальные наверное не трогают настройки.
 | 
					Остальные наверное не трогают настройки.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| Resource ID |    wOptionID    |            Name            | Default | Description         |
 | 
					| Resource ID |    wOptionID    |            Name            | Default | Description        |
 | 
				
			||||||
|:-----------:|:---------------:|:--------------------------:|:-------:|---------------------|
 | 
					|:-----------:|:---------------:|:--------------------------:|:-------:|--------------------|
 | 
				
			||||||
|      1      |   100 (0x64)    |      "Texture detail"      |         |                     |
 | 
					|      1      |   100 (0x64)    |      "Texture detail"      |         |                    |
 | 
				
			||||||
|      2      |   101 (0x65)    |         "3D Sound"         |         |                     |
 | 
					|      2      |   101 (0x65)    |         "3D Sound"         |         |                    |
 | 
				
			||||||
|      3      |   102 (0x66)    |    "Mouse sensitivity"     |         |                     |
 | 
					|      3      |   102 (0x66)    |    "Mouse sensitivity"     |         |                    |
 | 
				
			||||||
|      4      |   103 (0x67)    |   "Joystick sensitivity"   |         |                     |
 | 
					|      4      |   103 (0x67)    |   "Joystick sensitivity"   |         |                    |
 | 
				
			||||||
|      5      | !not a setting! |    "Illegal wOptionID"     |         |                     |
 | 
					|      5      | !not a setting! |    "Illegal wOptionID"     |         |                    |
 | 
				
			||||||
|      6      |   104 (0x68)    |     "Wait for retrace"     |         |                     |
 | 
					|      6      |   104 (0x68)    |     "Wait for retrace"     |         |                    |
 | 
				
			||||||
|      7      |   105 (0x69)    |     "Inverse mouse X"      |         |                     |
 | 
					|      7      |   105 (0x69)    |     "Inverse mouse X"      |         |                    |
 | 
				
			||||||
|      8      |   106 (0x6a)    |     "Inverse mouse Y"      |         |                     |
 | 
					|      8      |   106 (0x6a)    |     "Inverse mouse Y"      |         |                    |
 | 
				
			||||||
|      9      |   107 (0x6b)    |    "Inverse joystick X"    |         |                     |
 | 
					|      9      |   107 (0x6b)    |    "Inverse joystick X"    |         |                    |
 | 
				
			||||||
|     10      |   108 (0x6c)    |    "Inverse joystick Y"    |         |                     |
 | 
					|     10      |   108 (0x6c)    |    "Inverse joystick Y"    |         |                    |
 | 
				
			||||||
|     11      |   109 (0x6d)    |     "Use BumpMapping"      |         |                     |
 | 
					|     11      |   109 (0x6d)    |     "Use BumpMapping"      |         |                    |
 | 
				
			||||||
|     12      |   110 (0x6e)    |     "3D Sound quality"     |         |                     |
 | 
					|     12      |   110 (0x6e)    |     "3D Sound quality"     |         |                    |
 | 
				
			||||||
|     13      |    90 (0x5a)    |      "Reverse sound"       |         |                     |
 | 
					|     13      |    90 (0x5a)    |      "Reverse sound"       |         |                    |
 | 
				
			||||||
|     14      |    91 (0x5b)    |  "Sound buffer frequency"  |         |                     |
 | 
					|     14      |    91 (0x5b)    |  "Sound buffer frequency"  |         |                    |
 | 
				
			||||||
|     15      |    92 (0x5c)    | "Play sound buffer always" |         |                     |
 | 
					|     15      |    92 (0x5c)    | "Play sound buffer always" |         |                    |
 | 
				
			||||||
|     16      |    93 (0x5d)    | "Select best sound device" |         |                     |
 | 
					|     16      |    93 (0x5d)    | "Select best sound device" |         |                    |
 | 
				
			||||||
|    ----     |    30 (0x1e)    |        ShadeConfig         |         | из файла shade.cfg  |
 | 
					|    ----     |    30 (0x1e)    |        ShadeConfig         |         | из файла shade.cfg |
 | 
				
			||||||
 | 
					|    ----     |    (0x8001e)    |                            |         | добавляет AniMesh  |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Контакты
 | 
					## Контакты
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user