Advertisement
Guest User

MD2File.cs

a guest
Apr 4th, 2018
270
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 24.80 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.IO;
  7.  
  8. namespace DromeEd.Drome
  9. {
  10.     public static class Utils
  11.     {
  12.         public static string ReadStringASCIINT(BinaryReader reader, int length)
  13.         {
  14.             byte[] array = reader.ReadBytes(length);
  15.             int num = 0;
  16.             while (num < length && array[num] != 0)
  17.             {
  18.                 num++;
  19.             }
  20.             return Encoding.ASCII.GetString(array, 0, num);
  21.         }
  22.  
  23.         public static uint EndianSwap(uint input)
  24.         {
  25.             return ((input & 0xFF000000) >> 0x18) | ((input & 0x00FF0000) >> 0x08) | ((input & 0x0000FF00) << 0x08) | ((input & 0x000000FF) << 0x18);
  26.         }
  27.     }
  28.  
  29.     public struct Vector3
  30.     {
  31.         public float X;
  32.         public float Y;
  33.         public float Z;
  34.  
  35.         public Vector3(BinaryReader reader)
  36.         {
  37.             X = reader.ReadSingle();
  38.             Y = reader.ReadSingle();
  39.             Z = reader.ReadSingle();
  40.         }
  41.  
  42.         public Vector3(float x, float y, float z)
  43.         {
  44.             X = x;
  45.             Y = y;
  46.             Z = z;
  47.         }
  48.  
  49.         public void Normalize()
  50.         {
  51.             float len = (float)Math.Sqrt(X * X + Y * Y + Z * Z);
  52.             X /= len;
  53.             Y /= len;
  54.             Z /= len;
  55.         }
  56.     }
  57.  
  58.     public struct Vector4
  59.     {
  60.         public float X;
  61.         public float Y;
  62.         public float Z;
  63.         public float W;
  64.  
  65.         public Vector4(BinaryReader reader)
  66.         {
  67.             X = reader.ReadSingle();
  68.             Y = reader.ReadSingle();
  69.             Z = reader.ReadSingle();
  70.             W = reader.ReadSingle();
  71.         }
  72.  
  73.         public Vector4(float x, float y, float z, float w)
  74.         {
  75.             X = x;
  76.             Y = y;
  77.             Z = z;
  78.             W = w;
  79.         }
  80.     }
  81.  
  82.     public class TextureReference
  83.     {
  84.         private const int MaxLength = 256;
  85.  
  86.         public string Filename = "";
  87.         public Texture.MapType UsageType;
  88.         public int BaseIndex;
  89.  
  90.         public TextureReference(BinaryReader reader)
  91.         {
  92.             Filename = Utils.ReadStringASCIINT(reader, MaxLength);
  93.             UsageType = (Texture.MapType)reader.ReadUInt32();
  94.             BaseIndex = reader.ReadInt32();
  95.         }
  96.     }
  97.  
  98.     public class MaterialInfo
  99.     {
  100.         public Vector4 Ambient;
  101.         public Vector4 Diffuse;
  102.         public Vector4 Specular;
  103.         public Vector4 Emissive;
  104.         public float Shininess;
  105.         public float Transparency;
  106.         uint TransparencyType;
  107.         uint PropertyBits;
  108.         string AnimationName;
  109.  
  110.         public MaterialInfo(BinaryReader reader)
  111.         {
  112.             Ambient = new Vector4(reader);
  113.             Diffuse = new Vector4(reader);
  114.             Specular = new Vector4(reader);
  115.             Emissive = new Vector4(reader);
  116.             Shininess = reader.ReadSingle();
  117.             Transparency = reader.ReadSingle();
  118.             TransparencyType = reader.ReadUInt32();
  119.             PropertyBits = reader.ReadUInt32();
  120.             AnimationName = Utils.ReadStringASCIINT(reader, 12);
  121.             //AnimationName = Encoding.ASCII.GetString(reader.ReadBytes(12));//.TrimEnd(new char[] { (char)0 });
  122.         }
  123.     }
  124.  
  125.     public class BlockHeader
  126.     {
  127.         // MD2 Model
  128.         public const string MAGIC_MODEL0 = "MDL0";
  129.         public const string MAGIC_MODEL2 = "MDL2";
  130.         public const string MAGIC_MODEL3 = "MDL3";
  131.         public const string MAGIC_SKIN1 = "SKN0"; // Skin data
  132.         public const string MAGIC_SKIN2 = "SKN1"; // PS2 VU1 format skin
  133.         public const string MAGIC_SKIN3 = "SKN2"; // Skin and morph data
  134.         public const string MAGIC_SHADOW1 = "SHA0";
  135.         public const string MAGIC_SHADOWPS2 = "P2S0"; // PS2 VU1 format shadow
  136.         public const string MAGIC_COLLDATA = "COLD";
  137.         public const string MAGIC_GEOMETRY = "GEO0";
  138.         public const string MAGIC_GEOMETRY1 = "GEO1";
  139.         public const string MAGIC_GEOMETRY2 = "GEO2"; // Has render groups with an ID
  140.         public const string MAGIC_GEOMETRYPS2 = "P2G0";
  141.         public const string MAGIC_INDEXPS2 = "P2I0";
  142.         public const string MAGIC_ANCHOR = "ANC0";
  143.         public const string MAGIC_SKINGCN = "SKNG"; // GCN skin data
  144.         public const string MAGIC_GEOMETRYGCN = "GCG0"; // GCN geometry data
  145.  
  146.         // OLI terrain stuff
  147.         public const string MAGIC_OLI_CMO = "\u0001CMO";
  148.         public const string MAGIC_OLI_COI = "COI0";
  149.        
  150.  
  151.         public string Signature { get; }
  152.         public int Length { get; }
  153.  
  154.         public BlockHeader(string signature, int length)
  155.         {
  156.             Signature = signature;
  157.             Length = length;
  158.         }
  159.  
  160.         public BlockHeader(BinaryReader reader)
  161.         {
  162.             Signature = Encoding.ASCII.GetString(reader.ReadBytes(4));
  163.             Length = reader.ReadInt32();
  164.         }
  165.     }
  166.  
  167.     public abstract class Block
  168.     {
  169.         public BlockHeader Header { get; }
  170.  
  171.         public Block(BlockHeader header)
  172.         {
  173.             Header = header;
  174.         }
  175.     }
  176.  
  177.     [Flags()]
  178.     public enum BufferAccess : uint
  179.     {
  180.         None = 0,
  181.         Read = 1,
  182.         Write = 2,
  183.         ReadWrite = Read | Write,
  184.     }
  185.  
  186.     public class MDLBlock : Block
  187.     {
  188.         //public int Size;
  189.         public Vector3 InertiaTensor;
  190.         public float BoundingRadius;
  191.         public bool AllowDistanceFade = false;
  192.         public bool IncludesBoundingBox = false;
  193.         public Vector3 AABBMin;
  194.         public Vector3 AABBMax;
  195.         public Vector3 AABBCenter;
  196.         public float AABBYaw;
  197.         public uint UseUniqueMaterials;
  198.         public uint UseUniqueTextures;
  199.         public uint UseGenericGeometry; // don't load platform specific stuff
  200.         public BufferAccess VertexBufferAccessFlags; // for cVertexBuffer
  201.  
  202.         public List<TextureReference> TextureReferences = new List<TextureReference>();
  203.         public List<MaterialInfo> Materials = new List<MaterialInfo>();
  204.  
  205.         public MDLBlock(BinaryReader reader, BlockHeader header) : base(header)
  206.         {
  207.             InertiaTensor = new Vector3(reader);
  208.             BoundingRadius = reader.ReadSingle();
  209.             if (header.Signature != BlockHeader.MAGIC_MODEL0)
  210.             {
  211.                 AllowDistanceFade = reader.ReadUInt32() > 0;
  212.                 IncludesBoundingBox = reader.ReadUInt32() > 0;
  213.                 if (IncludesBoundingBox)
  214.                 {
  215.                     AABBMin = new Vector3(reader);
  216.                     AABBMax = new Vector3(reader);
  217.                     AABBCenter = new Vector3(reader);
  218.                     AABBYaw = reader.ReadSingle();
  219.                 }
  220.                 UseUniqueMaterials = reader.ReadUInt32();
  221.                 UseUniqueTextures = reader.ReadUInt32();
  222.                 UseGenericGeometry = reader.ReadUInt32();
  223.                 VertexBufferAccessFlags = (BufferAccess)reader.ReadUInt32();
  224.                 reader.ReadBytes(12 * 4);
  225.  
  226.             }
  227.             else
  228.             {
  229.                 AllowDistanceFade = false;
  230.             }
  231.  
  232.             int textureReferenceCount = reader.ReadInt32();
  233.             for (int i = 0; i < textureReferenceCount; i++)
  234.             {
  235.                 TextureReferences.Add(new TextureReference(reader));
  236.             }
  237.  
  238.             int materialCount = reader.ReadInt32();
  239.             for (int i = 0; i < materialCount; i++)
  240.             {
  241.                 Materials.Add(new MaterialInfo(reader));
  242.             }
  243.  
  244.         }
  245.     }
  246.  
  247.     /*public class GEO1Block : Block
  248.     {
  249.  
  250.         public List<LOD> LODs = new List<LOD>();
  251.  
  252.         public GEO1Block(BinaryReader reader, BlockHeader header) : base(header)
  253.         {
  254.             int LODCount = reader.ReadInt32();
  255.             for (int i = 0; i < LODCount; i++)
  256.             {
  257.                 LODs.Add(new LOD(reader));
  258.             }
  259.         }
  260.     }*/
  261.  
  262.     public class GeometryBlock : Block
  263.     {
  264.         public enum TextureTileParam : byte
  265.         {
  266.             None = 0,
  267.             Tile_U = 1,
  268.             TileV = 2,
  269.             MirrorU = 4,
  270.             MirrorV = 8,
  271.             NoBorders = 16
  272.         }
  273.         public class TextureBlend
  274.         {
  275.             public Texture.MapType Effect;
  276.             public ushort TextureIndex;
  277.             public byte CoordIndex;
  278.             public TextureTileParam TilingInfo;
  279.  
  280.             public TextureBlend(BinaryReader reader)
  281.             {
  282.                 Effect = (Texture.MapType)reader.ReadUInt32();
  283.                 TextureIndex = reader.ReadUInt16();
  284.                 CoordIndex = reader.ReadByte();
  285.                 TilingInfo = (TextureTileParam)reader.ReadByte();
  286.             }
  287.         }
  288.  
  289.         [Flags()]
  290.         public enum RenderEffects : ushort
  291.         {
  292.             RenderZBiased = 1,
  293.             RenderWireframe = 2,
  294.             RenderNoPolygons = 4,
  295.             RenderNoZTesting = 8,
  296.             RenderNoZWriting = 16,
  297.             RenderNoCulling = 32,
  298.             RenderNoLighting = 64,
  299.             RenderMinimalSetup = 128,
  300.             RenderNoClipping = 256,
  301.             VertexColor = 512,
  302.         }
  303.  
  304.         public class RenderGroup
  305.         {
  306.             public uint ID; // Dummy
  307.             public ushort PrimitiveCount;
  308.             public ushort VertexCount;
  309.             public ushort Material; // Material Index
  310.             public RenderEffects Effects;
  311.             uint pBumpData; // Dummy
  312.             uint pVertexBuffer; // Dummy
  313.             uint pIndexBuffer; // Dummy
  314.  
  315.             public const int BlendCount = 4;
  316.  
  317.             [Flags()]
  318.             public enum VertexComponent : ushort
  319.             {
  320.                 Position = 1,
  321.                 Normal = 2,
  322.                 Color = 4,
  323.                 UV = 8,
  324.                 BDNormal = 16,
  325.                 BSNormal = 32
  326.             }
  327.  
  328.             // Texture Blends
  329.             public ushort EffectsMask; // Each applied effect is a bit in this variable
  330.             public ushort RendererReference;
  331.             public ushort EffectCount;
  332.             public byte Custom;
  333.             public byte CoordsCount;
  334.             public List<TextureBlend> TextureBlends = new List<TextureBlend>();
  335.  
  336.             // 'Source' Vertex buffer
  337.             public uint PositionOffset;
  338.             public uint NormalOffset;
  339.             public uint ColorOffset;
  340.             public uint UVOffset;
  341.             public uint VertexSize;
  342.             public uint UVCount;
  343.             public VertexComponent VertexComponents;
  344.             public ushort VertexCount2;
  345.             public ushort ManagedBuffer;
  346.             public ushort CurrentVertex;
  347.             public uint pSourceBuffer; // Dummy
  348.             public uint pVertexOffset; // Dummy
  349.             public byte[] VertexData;
  350.  
  351.             // Index buffer
  352.             public enum Primitive : uint
  353.             {
  354.                 TriangleList,
  355.                 TriangleStrip,
  356.                 TriangleFan,
  357.                 LineList,
  358.                 LineStrip,
  359.                 PointList,
  360.                 PlatformSpecific
  361.             }
  362.             public uint PrimitiveBufferCount;
  363.             public Primitive PrimitiveType;
  364.             public uint IndexCount;
  365.             public byte[] IndexData;
  366.  
  367.             public RenderGroup(BinaryReader reader)
  368.             {
  369.                 if (Context.Current.Game >= Context.NextGenGame.DromeRacers)
  370.                     ID = reader.ReadUInt32();
  371.                 PrimitiveCount = reader.ReadUInt16();
  372.                 VertexCount = reader.ReadUInt16();
  373.                 Material = reader.ReadUInt16();
  374.                 Effects = (RenderEffects)reader.ReadUInt16();
  375.                 pBumpData = reader.ReadUInt32();
  376.                 pVertexBuffer = reader.ReadUInt32();
  377.                 pIndexBuffer = reader.ReadUInt32();
  378.  
  379.                 EffectsMask = reader.ReadUInt16();
  380.                 RendererReference = reader.ReadUInt16();
  381.                 EffectCount = reader.ReadUInt16();
  382.                 Custom = reader.ReadByte();
  383.                 CoordsCount = reader.ReadByte();
  384.                
  385.                 for (int i = 0; i < BlendCount; i++)
  386.                 {
  387.                     TextureBlends.Add(new TextureBlend(reader));
  388.                 }
  389.  
  390.                 PositionOffset = reader.ReadUInt32();
  391.                 NormalOffset = reader.ReadUInt32();
  392.                 ColorOffset = reader.ReadUInt32();
  393.                 UVOffset = reader.ReadUInt32();
  394.                 VertexSize = reader.ReadUInt32();
  395.                 UVCount = reader.ReadUInt32();
  396.                 VertexComponents = (VertexComponent)reader.ReadUInt16();
  397.                 VertexCount2 = reader.ReadUInt16();
  398.                 ManagedBuffer = reader.ReadUInt16();
  399.                 CurrentVertex = reader.ReadUInt16();
  400.                 pSourceBuffer = reader.ReadUInt32();
  401.                 pVertexOffset = reader.ReadUInt32();
  402.                 VertexData = reader.ReadBytes(VertexCount2 * (int)VertexSize);
  403.  
  404.                 PrimitiveBufferCount = reader.ReadUInt32();
  405.                 PrimitiveType = (Primitive)reader.ReadUInt32();
  406.                 IndexCount = reader.ReadUInt32();
  407.                 IndexData = reader.ReadBytes((int)IndexCount * 2); // 2 bytes per index
  408.             }
  409.         }
  410.  
  411.         public class LOD
  412.         {
  413.             public enum LODLevel : uint
  414.             {
  415.                 GeometryFirstLevel,
  416.                 GeometrySubdivisionDetail = 0,
  417.                 GeometryNormalDetail,
  418.                 GeometryReducedDetail,
  419.                 GeometrySortedDetail,
  420.                 GeometryCollisionMesh,
  421.                 GeometryFacialMorphTarget,
  422.                 GeometryBlankDetailLevel,
  423.                 GeometryNumLevels = 6,
  424.                 GeometryAllLevels
  425.             }
  426.  
  427.             public LODLevel Type;
  428.             public float MaxEdgeLength;
  429.             public uint GroupCount; // 0x00000003
  430.             Vector3[] Positions; // Positions for z-sorting the rendergroups
  431.             public uint PositionsPointer; // 0x00000000 pPositions Just here because the C++ class is literally dumped to the file.
  432.             public uint RenderGroupsPointer; // 0x0212DEA4 pRenderGroups Just here because the C++ class is literally dumped to the file.
  433.  
  434.             public List<RenderGroup> RenderGroups = new List<RenderGroup>();
  435.  
  436.             public LOD(BinaryReader reader)
  437.             {
  438.                 Type = (LODLevel)reader.ReadUInt32();
  439.                 MaxEdgeLength = reader.ReadSingle();
  440.                 GroupCount = reader.ReadUInt32();
  441.                 PositionsPointer = reader.ReadUInt32();
  442.                 //if (Context.Current.Game == Context.NextGenGame.DromeRacers)
  443.                     RenderGroupsPointer = reader.ReadUInt32();
  444.                 if (PositionsPointer > 0)
  445.                 {
  446.                     Positions = new Vector3[GroupCount];
  447.                     for (int i = 0; i < GroupCount; i++)
  448.                     {
  449.                         Positions[i] = new Vector3(reader);
  450.                     }
  451.                 }
  452.                 for (int i = 0; i < GroupCount; i++)
  453.                 {
  454.                     RenderGroups.Add(new RenderGroup(reader));
  455.                 }
  456.             }
  457.         }
  458.  
  459.         public List<LOD> LODs = new List<LOD>();
  460.  
  461.         public GeometryBlock(BinaryReader reader, BlockHeader header) : base(header)
  462.         {
  463.             int LODCount = reader.ReadInt32();
  464.             for (int i = 0; i < LODCount; i++)
  465.             {
  466.                 LODs.Add(new LOD(reader));
  467.             }
  468.         }
  469.     }
  470.  
  471.     public class Anchor
  472.     {
  473.         private const int NameLength = 0x20;
  474.         private const int PathLength = 0x80;
  475.         public string Name = "";
  476.         public uint AnchorType;
  477.         public uint MaterialIndex;
  478.         public string LinkedFilename = "";
  479.         public Vector3 Position;
  480.         public Vector3 Forward;
  481.         public Vector3 Right;
  482.         public Vector3 Up;
  483.         public Vector3 ModelOffset;
  484.  
  485.         public Anchor(BinaryReader reader)
  486.         {
  487.             Name = Utils.ReadStringASCIINT(reader, NameLength);
  488.             AnchorType = reader.ReadUInt32();
  489.             MaterialIndex = reader.ReadUInt32();
  490.             LinkedFilename = Utils.ReadStringASCIINT(reader, PathLength);
  491.             Position = new Vector3(reader);
  492.             Forward = new Vector3(reader);
  493.             Right = new Vector3(reader);
  494.             Up = new Vector3(reader);
  495.             ModelOffset = new Vector3(reader);
  496.         }
  497.  
  498.         public override string ToString()
  499.         {
  500.             return "<" + Position.X + ", " + Position.Y + ", " + Position.Z + ">: " + Name;
  501.         }
  502.     }
  503.  
  504.     public class AnchorBlock : Block
  505.     {
  506.         public List<Anchor> Anchors = new List<Anchor>();
  507.  
  508.         public AnchorBlock(BinaryReader reader, BlockHeader header) : base(header)
  509.         {
  510.             byte anchorCount = reader.ReadByte();
  511.  
  512.             for (int i = 0; i < anchorCount; i++)
  513.             {
  514.                 Anchors.Add(new Anchor(reader));
  515.             }
  516.         }
  517.     }
  518.  
  519.     public class MD2File
  520.     {
  521.         public Dictionary<string, Block> Blocks = new Dictionary<string, Block>();
  522.  
  523.         public MD2File(BinaryReader reader)
  524.         {
  525.             while (reader.BaseStream.Position < reader.BaseStream.Length - 4)
  526.             {
  527.                 BlockHeader header = new BlockHeader(reader);
  528.                 long offset = reader.BaseStream.Position;
  529.                 System.Console.WriteLine("Reading Block '" + header.Signature + "' : " + ((int)reader.BaseStream.Position).ToString("X8") + " + " + header.Length.ToString("X8") + " bytes");
  530.  
  531.                 Block newBlock = null;
  532.                 if (header.Signature == BlockHeader.MAGIC_MODEL0 || header.Signature == BlockHeader.MAGIC_MODEL2 || header.Signature == BlockHeader.MAGIC_MODEL3)
  533.                 {
  534.                     newBlock = new MDLBlock(reader, header);
  535.                 }
  536.                 else if (header.Signature == BlockHeader.MAGIC_GEOMETRY ||
  537.                          header.Signature == BlockHeader.MAGIC_GEOMETRY1 ||
  538.                          header.Signature == BlockHeader.MAGIC_GEOMETRY2)
  539.                 {
  540.                     newBlock = new GeometryBlock(reader, header);
  541.                 }
  542.                 else if (header.Signature == BlockHeader.MAGIC_ANCHOR)
  543.                 {
  544.                     newBlock = new AnchorBlock(reader, header);
  545.                 }
  546.                
  547.                 if (newBlock != null)
  548.                 {
  549.                     Blocks.Add(header.Signature, newBlock);
  550.                 }
  551.  
  552.                 reader.BaseStream.Position = offset + header.Length;
  553.             }
  554.         }
  555.  
  556.         public void ExportOBJ(string filename)
  557.         {
  558.             MDLBlock mdl;// = (Blocks[BlockHeader.MAGIC_MODEL3] ?? Blocks[BlockHeader.MAGIC_MODEL2]) as MDLBlock;
  559.             if (Blocks.ContainsKey(BlockHeader.MAGIC_MODEL2))
  560.                 mdl = Blocks[BlockHeader.MAGIC_MODEL2] as MDLBlock;
  561.             else if (Blocks.ContainsKey(BlockHeader.MAGIC_MODEL3))
  562.                 mdl = Blocks[BlockHeader.MAGIC_MODEL3] as MDLBlock;
  563.             else
  564.                 throw new Exception("No supported MDL block found.");
  565.  
  566.             GeometryBlock geo;// = Blocks[BlockHeader.MAGIC_GEOMETRY2] as GeometryBlock;
  567.             if (Blocks.ContainsKey(BlockHeader.MAGIC_GEOMETRY1))
  568.                 geo = Blocks[BlockHeader.MAGIC_GEOMETRY1] as GeometryBlock;
  569.             else if (Blocks.ContainsKey(BlockHeader.MAGIC_GEOMETRY2))
  570.                 geo = Blocks[BlockHeader.MAGIC_GEOMETRY2] as GeometryBlock;
  571.             else
  572.                 throw new Exception("No supported GEO block found.");
  573.  
  574.             using (StreamWriter matwriter = new StreamWriter(Path.ChangeExtension(filename, ".mtl")))
  575.             using (StreamWriter writer = new StreamWriter(filename))
  576.             {
  577.                 writer.WriteLine("mtllib " + Path.GetFileNameWithoutExtension(filename) + ".mtl");
  578.  
  579.                 int m = 0;
  580.                 int vertexOffset = 0;
  581.                 foreach (GeometryBlock.LOD lod in geo.LODs)
  582.                 {
  583.                     writer.WriteLine("g LOD" + lod.Type.ToString());
  584.                     foreach (GeometryBlock.RenderGroup group in lod.RenderGroups)
  585.                     {
  586.                         // Write a new material
  587.                         MaterialInfo mat = mdl.Materials[group.Material];
  588.                         matwriter.WriteLine("newmtl " + Path.GetFileNameWithoutExtension(filename) + "_" + m);
  589.                         matwriter.WriteLine("Ka " + (mat.Ambient.X + mat.Emissive.X) + " " + (mat.Ambient.Y + mat.Emissive.Y) + " " + (mat.Ambient.Z + mat.Emissive.Z));
  590.                         matwriter.WriteLine("Kd " + mat.Diffuse.X + " " + mat.Diffuse.Y + " " + mat.Diffuse.Z);
  591.                         matwriter.WriteLine("Ks " + mat.Specular.X + " " + mat.Specular.Y + " " + mat.Specular.Z);
  592.                         matwriter.WriteLine("Ns " + mat.Shininess);
  593.                         matwriter.WriteLine("d " + (1.0f - mat.Transparency));
  594.  
  595.                         foreach (GeometryBlock.TextureBlend blend in group.TextureBlends)
  596.                         {
  597.                             if (blend.Effect == Texture.MapType.Base)
  598.                             {
  599.                                 matwriter.WriteLine("map_Kd " + Path.GetFileName(mdl.TextureReferences[blend.TextureIndex].Filename));
  600.                                 // Write Texture
  601.                                 if (Program.Filesystem != null)
  602.                                 {
  603.                                     using (MemoryStream ms = new MemoryStream(Program.Filesystem.GetFileData(Program.Filesystem.GetFileEntry(mdl.TextureReferences[blend.TextureIndex].Filename.Replace(".tga", ".PC TEXTURE")))))
  604.                                     using (BinaryReader texReader = new BinaryReader(ms))
  605.                                     {
  606.                                         Texture tex = new Texture(texReader);
  607.                                         tex.DumpTGA(Path.Combine(Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(mdl.TextureReferences[blend.TextureIndex].Filename)) + ".tga");
  608.                                     }
  609.                                 }
  610.                             }
  611.                         }
  612.  
  613.                         writer.WriteLine("usemtl " + Path.GetFileNameWithoutExtension(filename) + "_" + m);
  614.                         writer.WriteLine("o LOD" + lod.Type.ToString() + "_group" + lod.RenderGroups.IndexOf(group));
  615.  
  616.                         // Write vertices
  617.                         for (int v = 0; v < group.VertexCount; v++)
  618.                         {
  619.                             writer.WriteLine("v " + (Context.Current.Game == Context.NextGenGame.LegoRacers2 ? -1.0f : 1.0f) * ParseFloat(group.VertexData, v * (int)group.VertexSize + (int)group.PositionOffset) + " " + ParseFloat(group.VertexData, v * (int)group.VertexSize + (int)group.PositionOffset + 4) + " " + ParseFloat(group.VertexData, v * (int)group.VertexSize + (int)group.PositionOffset + 8));
  620.                             writer.WriteLine("vn " + ParseFloat(group.VertexData, v * (int)group.VertexSize + (int)group.NormalOffset) + " " + ParseFloat(group.VertexData, v * (int)group.VertexSize + (int)group.NormalOffset + 4) + " " + ParseFloat(group.VertexData, v * (int)group.VertexSize + (int)group.NormalOffset + 8));
  621.                             writer.WriteLine("vt " + ParseFloat(group.VertexData, v * (int)group.VertexSize + (int)group.UVOffset) + " " + ParseFloat(group.VertexData, v * (int)group.VertexSize + (int)group.UVOffset + 4));
  622.                         }
  623.  
  624.                         for (int i = 0; i < group.IndexCount; i += 3)
  625.                         {
  626.                             int i1 = BitConverter.ToUInt16(group.IndexData, i * 2) + vertexOffset + 1;
  627.                             int i2 = BitConverter.ToUInt16(group.IndexData, i * 2 + 2) + vertexOffset + 1;
  628.                             int i3 = BitConverter.ToUInt16(group.IndexData, i * 2 + 4) + vertexOffset + 1;
  629.                             /*if (Context.Current.Game == Context.NextGenGame.LegoRacers2)
  630.                             {
  631.                                 // Flip the order of the indices
  632.                                 int temp = i1;
  633.                                 i1 = i2;
  634.                                 i2 = i3;
  635.                                 i3 = temp;
  636.                             }*/
  637.                             writer.WriteLine("f " + i1 + "/" + i1 + "/" + i1 + " " + i2 + "/" + i2 + "/" + i2 + " " + i3 + "/" + i3 + "/" + i3);
  638.                         }
  639.  
  640.                         vertexOffset += group.VertexCount;
  641.                         m++;
  642.                     }
  643.                 }
  644.             }
  645.         }
  646.  
  647.         private static float ParseFloat(byte[] buffer, int offset)
  648.         {
  649.             return BitConverter.ToSingle(buffer, offset);
  650.         }
  651.     }
  652. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement