diff --git a/CodeWalker.Core/GameFiles/FileTypes/YddFile.cs b/CodeWalker.Core/GameFiles/FileTypes/YddFile.cs index 1d3787d..c084216 100644 --- a/CodeWalker.Core/GameFiles/FileTypes/YddFile.cs +++ b/CodeWalker.Core/GameFiles/FileTypes/YddFile.cs @@ -111,9 +111,24 @@ namespace CodeWalker.GameFiles { ddsfolder = Path.Combine(outputFolder, ydd.Name); - if (!Directory.Exists(ddsfolder)) + bool hastxd = false; + if (ydd?.DrawableDict?.Drawables?.data_items != null) { - Directory.CreateDirectory(ddsfolder); + foreach (var d in ydd.DrawableDict.Drawables.data_items) + { + if (d?.ShaderGroup?.TextureDictionary != null) + { + hastxd = true; + break; + } + } + } + if (hastxd) + { + if (!Directory.Exists(ddsfolder)) + { + Directory.CreateDirectory(ddsfolder); + } } } diff --git a/CodeWalker.Core/GameFiles/FileTypes/YdrFile.cs b/CodeWalker.Core/GameFiles/FileTypes/YdrFile.cs index 2a5f766..5096590 100644 --- a/CodeWalker.Core/GameFiles/FileTypes/YdrFile.cs +++ b/CodeWalker.Core/GameFiles/FileTypes/YdrFile.cs @@ -76,9 +76,12 @@ namespace CodeWalker.GameFiles { ddsfolder = Path.Combine(outputFolder, ydr.Name); - if (!Directory.Exists(ddsfolder)) + if (ydr?.Drawable?.ShaderGroup?.TextureDictionary != null) { - Directory.CreateDirectory(ddsfolder); + if (!Directory.Exists(ddsfolder)) + { + Directory.CreateDirectory(ddsfolder); + } } } diff --git a/CodeWalker.Core/GameFiles/FileTypes/YftFile.cs b/CodeWalker.Core/GameFiles/FileTypes/YftFile.cs index 1d5a7de..f531e59 100644 --- a/CodeWalker.Core/GameFiles/FileTypes/YftFile.cs +++ b/CodeWalker.Core/GameFiles/FileTypes/YftFile.cs @@ -80,9 +80,38 @@ namespace CodeWalker.GameFiles { ddsfolder = Path.Combine(outputFolder, yft.Name); - if (!Directory.Exists(ddsfolder)) + bool hastxd = false; + if (yft?.Fragment != null) { - Directory.CreateDirectory(ddsfolder); + hastxd = hastxd || (yft.Fragment.Drawable?.ShaderGroup?.TextureDictionary != null); + hastxd = hastxd || (yft.Fragment.Drawable2?.ShaderGroup?.TextureDictionary != null); + if (yft.Fragment.DrawableArray?.data_items != null) + { + foreach (var d in yft.Fragment.DrawableArray?.data_items) + { + if (hastxd) break; + if (d?.ShaderGroup?.TextureDictionary != null) + { + hastxd = true; + } + } + } + if (yft.Fragment.PhysicsLODGroup?.PhysicsLOD1?.Children?.data_items != null) + { + foreach (var child in yft.Fragment.PhysicsLODGroup.PhysicsLOD1.Children.data_items) + { + if (hastxd) break; + hastxd = hastxd || (child.Drawable1?.ShaderGroup?.TextureDictionary != null); + hastxd = hastxd || (child.Drawable2?.ShaderGroup?.TextureDictionary != null); + } + } + } + if (hastxd) + { + if (!Directory.Exists(ddsfolder)) + { + Directory.CreateDirectory(ddsfolder); + } } } diff --git a/CodeWalker.Core/GameFiles/FileTypes/YptFile.cs b/CodeWalker.Core/GameFiles/FileTypes/YptFile.cs index 5724f09..96f0f55 100644 --- a/CodeWalker.Core/GameFiles/FileTypes/YptFile.cs +++ b/CodeWalker.Core/GameFiles/FileTypes/YptFile.cs @@ -128,9 +128,24 @@ namespace CodeWalker.GameFiles { ddsfolder = Path.Combine(outputFolder, ypt.Name); - if (!Directory.Exists(ddsfolder)) + bool hastxd = false; + if (ypt?.DrawableDict != null) { - Directory.CreateDirectory(ddsfolder); + foreach (var d in ypt.DrawableDict.Values) + { + if (d?.ShaderGroup?.TextureDictionary != null) + { + hastxd = true; + break; + } + } + } + if (hastxd) + { + if (!Directory.Exists(ddsfolder)) + { + Directory.CreateDirectory(ddsfolder); + } } } diff --git a/CodeWalker.Core/GameFiles/GameFileCache.cs b/CodeWalker.Core/GameFiles/GameFileCache.cs index 288e9b8..066ec44 100644 --- a/CodeWalker.Core/GameFiles/GameFileCache.cs +++ b/CodeWalker.Core/GameFiles/GameFileCache.cs @@ -4264,7 +4264,7 @@ namespace CodeWalker.GameFiles if (((vd.Flags >> i) & 1) == 1) { string typestr = "Unknown"; - uint type = (uint)((vd.Types >> (4 * i)) & 0xF); + uint type = (uint)(((ulong)vd.Types >> (4 * i)) & 0xF); switch (type) { case 0: typestr = "ushort"; break;// Data[i] = new ushort[1 * count]; break; diff --git a/CodeWalker.Core/GameFiles/Resources/Drawable.cs b/CodeWalker.Core/GameFiles/Resources/Drawable.cs index ca3bd7f..09573a6 100644 --- a/CodeWalker.Core/GameFiles/Resources/Drawable.cs +++ b/CodeWalker.Core/GameFiles/Resources/Drawable.cs @@ -38,6 +38,24 @@ namespace CodeWalker.GameFiles public TextureDictionary TextureDictionary { get; set; } public ResourcePointerArray64 Shaders { get; set; } + + public int TotalParameters + { + get + { + int c = 0; + if (Shaders?.data_items != null) + { + foreach (var s in Shaders.data_items) + { + c += s.ParameterCount; + } + } + return c; + } + } + + public override void Read(ResourceDataReader reader, params object[] parameters) { // read structure data @@ -650,12 +668,12 @@ namespace CodeWalker.GameFiles for (int i = 0; i < Count; i++) { var param = Parameters[i]; - var hash = Hashes[i]; + var name = (ShaderParamNames)Hashes[i]; var typestr = ""; if (param.DataType == 0) typestr = "Texture"; else if (param.DataType == 1) typestr = "Vector"; else if (param.DataType > 1) typestr = "Array"; - var otstr = "Item name=\"" + YdrXml.HashString(hash) + "\" type=\"" + typestr + "\""; + var otstr = "Item name=\"" + name.ToString() + "\" type=\"" + typestr + "\""; if (param.DataType == 0) { @@ -708,7 +726,7 @@ namespace CodeWalker.GameFiles foreach (XmlNode pnode in pnodes) { var p = new ShaderParameter(); - var h = (MetaName)(uint)XmlMeta.GetHash(Xml.GetStringAttribute(pnode, "name")); + var h = (MetaName)(uint)XmlMeta.GetHash(Xml.GetStringAttribute(pnode, "name")?.ToLowerInvariant()); var type = Xml.GetStringAttribute(pnode, "type"); if (type == "Texture") { @@ -750,6 +768,7 @@ namespace CodeWalker.GameFiles Parameters = plist.ToArray(); Hashes = hlist.ToArray(); + Count = plist.Count; for (int i = 0; i < Parameters.Length; i++) { @@ -2015,6 +2034,18 @@ namespace CodeWalker.GameFiles set { SkeletonBinding = (SkeletonBinding & 0xFFFFFF00) + ((value & 0xFFu) << 0); } } + public byte RenderMask + { + get { return (byte)((RenderMaskFlags >> 0) & 0xFF); } + set { RenderMaskFlags = (ushort)((RenderMaskFlags & 0xFF00u) + ((value & 0xFFu) << 0)); } + } + public byte Flags + { + get { return (byte)((RenderMaskFlags >> 8) & 0xFF); } + set { RenderMaskFlags = (ushort)((RenderMaskFlags & 0xFFu) + ((value & 0xFFu) << 8)); } + } + + // reference data public ResourcePointerArray64 Geometries { get; set; } @@ -2153,10 +2184,11 @@ namespace CodeWalker.GameFiles } public void WriteXml(StringBuilder sb, int indent) { - YdrXml.ValueTag(sb, indent, "BoneIndex", BoneIndex.ToString()); + YdrXml.ValueTag(sb, indent, "RenderMask", RenderMask.ToString()); + YdrXml.ValueTag(sb, indent, "Flags", Flags.ToString()); YdrXml.ValueTag(sb, indent, "HasSkin", HasSkin.ToString()); + YdrXml.ValueTag(sb, indent, "BoneIndex", BoneIndex.ToString()); YdrXml.ValueTag(sb, indent, "Unknown1", SkeletonBindUnk1.ToString()); - YdrXml.ValueTag(sb, indent, "RenderMask", RenderMaskFlags.ToString()); if (Geometries?.data_items != null) { @@ -2166,13 +2198,16 @@ namespace CodeWalker.GameFiles } public void ReadXml(XmlNode node) { - BoneIndex = (byte)Xml.GetChildUIntAttribute(node, "BoneIndex", "value"); + RenderMask = (byte)Xml.GetChildUIntAttribute(node, "RenderMask", "value"); + Flags = (byte)Xml.GetChildUIntAttribute(node, "Flags", "value"); HasSkin = (byte)Xml.GetChildUIntAttribute(node, "HasSkin", "value"); + BoneIndex = (byte)Xml.GetChildUIntAttribute(node, "BoneIndex", "value"); SkeletonBindUnk1 = (byte)Xml.GetChildUIntAttribute(node, "Unknown1", "value"); - RenderMaskFlags = (ushort)Xml.GetChildUIntAttribute(node, "RenderMask", "value"); var aabbs = new List(); var shids = new List(); + var min = new Vector4(float.MaxValue); + var max = new Vector4(float.MinValue); var geoms = XmlMeta.ReadItemArray(node, "Geometries"); if (geoms != null) { @@ -2182,8 +2217,17 @@ namespace CodeWalker.GameFiles { aabbs.Add(geom.AABB); shids.Add(geom.ShaderID); + min = Vector4.Min(min, geom.AABB.Min); + max = Vector4.Max(max, geom.AABB.Max); } + GeometriesCount1 = GeometriesCount2 = GeometriesCount3 = (ushort)geoms.Length; } + if (aabbs.Count > 1) + { + var outeraabb = new AABB_s() { Min = min, Max = max }; + aabbs.Insert(0, outeraabb); + } + BoundsData = (aabbs.Count > 0) ? aabbs.ToArray() : null; ShaderMapping = (shids.Count > 0) ? shids.ToArray() : null; } @@ -2425,11 +2469,13 @@ namespace CodeWalker.GameFiles if (VertexBuffer != null) { YdrXml.OpenTag(sb, indent, "VertexBuffer"); + VertexBuffer.WriteXml(sb, indent + 1); YdrXml.CloseTag(sb, indent, "VertexBuffer"); } if (IndexBuffer != null) { YdrXml.OpenTag(sb, indent, "IndexBuffer"); + IndexBuffer.WriteXml(sb, indent + 1); YdrXml.CloseTag(sb, indent, "IndexBuffer"); } } @@ -2460,10 +2506,15 @@ namespace CodeWalker.GameFiles var vnode = node.SelectSingleNode("VertexBuffer"); if (vnode != null) { + VertexBuffer = new VertexBuffer(); + VertexBuffer.ReadXml(vnode); + VertexData = VertexBuffer.Data1 ?? VertexBuffer.Data2; } var inode = node.SelectSingleNode("IndexBuffer"); if (inode != null) { + IndexBuffer = new IndexBuffer(); + IndexBuffer.ReadXml(inode); } } @@ -2498,7 +2549,7 @@ namespace CodeWalker.GameFiles public uint VFT { get; set; } public uint Unknown_4h { get; set; } = 1; // 0x00000001 public ushort VertexStride { get; set; } - public ushort Unknown_Ah { get; set; } //only 0 or 1024 + public ushort Flags { get; set; } //only 0 or 1024 public uint Unknown_Ch { get; set; } // 0x00000000 public ulong DataPointer1 { get; set; } public uint VertexCount { get; set; } @@ -2531,16 +2582,13 @@ namespace CodeWalker.GameFiles public VertexData Data2 { get; set; } public VertexDeclaration Info { get; set; } - /// - /// Reads the data-block from a stream. - /// public override void Read(ResourceDataReader reader, params object[] parameters) { // read structure data this.VFT = reader.ReadUInt32(); this.Unknown_4h = reader.ReadUInt32(); this.VertexStride = reader.ReadUInt16(); - this.Unknown_Ah = reader.ReadUInt16(); + this.Flags = reader.ReadUInt16(); this.Unknown_Ch = reader.ReadUInt32(); this.DataPointer1 = reader.ReadUInt64(); this.VertexCount = reader.ReadUInt32(); @@ -2586,21 +2634,17 @@ namespace CodeWalker.GameFiles ); - switch (Unknown_Ah) - { - case 0: - break; - case 1024://micro flag? //micro_brow_down.ydr, micro_chin_pointed.ydr - break; - default: - break; - } + //switch (Flags) + //{ + // case 0: + // break; + // case 1024://micro flag? //micro_brow_down.ydr, micro_chin_pointed.ydr + // break; + // default: + // break; + //} } - - /// - /// Writes the data-block to a stream. - /// public override void Write(ResourceDataWriter writer, params object[] parameters) { // update structure data @@ -2613,7 +2657,7 @@ namespace CodeWalker.GameFiles writer.Write(this.VFT); writer.Write(this.Unknown_4h); writer.Write(this.VertexStride); - writer.Write(this.Unknown_Ah); + writer.Write(this.Flags); writer.Write(this.Unknown_Ch); writer.Write(this.DataPointer1); writer.Write(this.VertexCount); @@ -2641,10 +2685,57 @@ namespace CodeWalker.GameFiles writer.Write(this.Unknown_78h); writer.Write(this.Unknown_7Ch); } + public void WriteXml(StringBuilder sb, int indent) + { + YdrXml.ValueTag(sb, indent, "Flags", Flags.ToString()); + + if (Info != null) + { + YdrXml.OpenTag(sb, indent, "Layout type=\"" + Info.Types.ToString() + "\""); + Info.WriteXml(sb, indent + 1); + YdrXml.CloseTag(sb, indent, "Layout"); + } + if (Data1 != null) + { + YdrXml.OpenTag(sb, indent, "Data"); + Data1.WriteXml(sb, indent + 1); + YdrXml.CloseTag(sb, indent, "Data"); + } + if ((Data2 != null) && (Data2 != Data1)) + { + YdrXml.OpenTag(sb, indent, "Data2"); + Data2.WriteXml(sb, indent + 1); + YdrXml.CloseTag(sb, indent, "Data2"); + } + } + public void ReadXml(XmlNode node) + { + Flags = (ushort)Xml.GetChildUIntAttribute(node, "Flags", "value"); + + var inode = node.SelectSingleNode("Layout"); + if (inode != null) + { + Info = new VertexDeclaration(); + Info.ReadXml(inode); + VertexStride = Info.Stride; + } + var dnode = node.SelectSingleNode("Data"); + if (dnode != null) + { + Data1 = new VertexData(); + Data1.ReadXml(dnode, Info); + Data2 = Data1; + VertexCount = (uint)Data1.VertexCount; + } + var dnode2 = node.SelectSingleNode("Data2"); + if (dnode2 != null) + { + Data2 = new VertexData(); + Data2.ReadXml(dnode2, Info); + } + } + - /// - /// Returns a list of data blocks which are referenced by this block. - /// public override IResourceBlock[] GetReferences() { var list = new List(); @@ -2669,17 +2760,13 @@ namespace CodeWalker.GameFiles } - - public VertexDeclaration info { get; set; } - public object[] Data { get; set; } - public uint[] Types { get; set; } - - + public int VertexStride { get; set; } + public int VertexCount { get; set; } + public VertexDeclaration Info { get; set; } public VertexType VertexType { get; set; } + public byte[] VertexBytes { get; set; } - public int VertexCount { get; set; } - public int VertexStride { get; set; } public long MemoryUsage { @@ -2693,26 +2780,24 @@ namespace CodeWalker.GameFiles { VertexStride = Convert.ToInt32(parameters[0]); VertexCount = Convert.ToInt32(parameters[1]); - info = (VertexDeclaration)parameters[2]; - - VertexType = (VertexType)info.Flags; + Info = (VertexDeclaration)parameters[2]; + VertexType = (VertexType)Info.Flags; VertexBytes = reader.ReadBytes(VertexCount * VertexStride); - - switch (info.Types) + switch (Info.Types) { - case 8598872888530528662: //YDR - 0x7755555555996996 + case VertexDeclarationTypes.GTAV1: //YDR - 0x7755555555996996 break; - case 216172782140628998: //YFT - 0x030000000199A006 - switch (info.Flags) + case VertexDeclarationTypes.GTAV2: //YFT - 0x030000000199A006 + switch (Info.Flags) { case 16473: VertexType = VertexType.PCCH2H4; break; // PCCH2H4 default:break; } break; - case 216172782140612614: //YFT - 0x0300000001996006 PNCH2H4 - switch (info.Flags) + case VertexDeclarationTypes.GTAV3: //YFT - 0x0300000001996006 PNCH2H4 + switch (Info.Flags) { case 89: VertexType = VertexType.PNCH2; break; // PNCH2 default: break; @@ -2723,244 +2808,6 @@ namespace CodeWalker.GameFiles } } - - public /*override*/ void ReadOrig(ResourceDataReader reader, params object[] parameters) - { - int stride = Convert.ToInt32(parameters[0]); - int count = Convert.ToInt32(parameters[1]); - var info = (VertexDeclaration)parameters[2]; - this.VertexCount = count; - this.info = info; - - - bool[] IsUsed = new bool[16]; - for (int i = 0; i < 16; i++) - IsUsed[i] = ((info.Flags >> i) & 0x1) == 1; - - Types = new uint[16]; - for (int i = 0; i < 16; i++) - Types[i] = (uint)((info.Types >> (int)(4 * i)) & 0xF); - - - - Data = new object[16]; - for (int i = 0; i < 16; i++) - { - if (IsUsed[i]) - { - switch (Types[i]) - { - case 0: Data[i] = new ushort[1 * count]; break; - case 1: Data[i] = new ushort[2 * count]; break; - case 2: Data[i] = new ushort[3 * count]; break; - case 3: Data[i] = new ushort[4 * count]; break; - case 4: Data[i] = new float[1 * count]; break; - case 5: Data[i] = new float[2 * count]; break; - case 6: Data[i] = new float[3 * count]; break; - case 7: Data[i] = new float[4 * count]; break; - case 8: Data[i] = new uint[count]; break; - case 9: Data[i] = new uint[count]; break; - case 10: Data[i] = new uint[count]; break; - default: - throw new Exception(); - } - } - } - - - - long pos = reader.Position; - - // read... - for (int i = 0; i < count; i++) - { - - for (int k = 0; k < 16; k++) - { - if (IsUsed[k]) - { - switch (Types[k]) - { - // float16 - case 0: - { - var buf = Data[k] as ushort[]; - buf[i * 1 + 0] = reader.ReadUInt16(); - break; - } - case 1: - { - var buf = Data[k] as ushort[]; - buf[i * 2 + 0] = reader.ReadUInt16(); - buf[i * 2 + 1] = reader.ReadUInt16(); - break; - } - case 2: - { - var buf = Data[k] as ushort[]; - buf[i * 3 + 0] = reader.ReadUInt16(); - buf[i * 3 + 1] = reader.ReadUInt16(); - buf[i * 3 + 2] = reader.ReadUInt16(); - break; - } - case 3: - { - var buf = Data[k] as ushort[]; - buf[i * 4 + 0] = reader.ReadUInt16(); - buf[i * 4 + 1] = reader.ReadUInt16(); - buf[i * 4 + 2] = reader.ReadUInt16(); - buf[i * 4 + 3] = reader.ReadUInt16(); - break; - } - - // float32 - case 4: - { - var buf = Data[k] as float[]; - buf[i * 1 + 0] = reader.ReadSingle(); - break; - } - case 5: - { - var buf = Data[k] as float[]; - buf[i * 2 + 0] = reader.ReadSingle(); - buf[i * 2 + 1] = reader.ReadSingle(); - break; - } - case 6: - { - var buf = Data[k] as float[]; - buf[i * 3 + 0] = reader.ReadSingle(); - buf[i * 3 + 1] = reader.ReadSingle(); - buf[i * 3 + 2] = reader.ReadSingle(); - break; - } - case 7: - { - var buf = Data[k] as float[]; - buf[i * 4 + 0] = reader.ReadSingle(); - buf[i * 4 + 1] = reader.ReadSingle(); - buf[i * 4 + 2] = reader.ReadSingle(); - buf[i * 4 + 3] = reader.ReadSingle(); - break; - } - - case 8: - case 9: - case 10: - { - var buf = Data[k] as uint[]; - buf[i * 1 + 0] = reader.ReadUInt32(); - break; - } - - default: - throw new Exception(); - } - } - } - - } - - //this.length = stride * count; - } - - public /*override*/ void WriteOrig(ResourceDataWriter writer, params object[] parameters) - { - - // write... - for (int i = 0; i < VertexCount; i++) - { - - for (int k = 0; k < 16; k++) - { - if (Data[k] != null) - { - switch (Types[k]) - { - // float16 - case 0: - { - var buf = Data[k] as ushort[]; - writer.Write(buf[i * 1 + 0]); - break; - } - case 1: - { - var buf = Data[k] as ushort[]; - writer.Write(buf[i * 2 + 0]); - writer.Write(buf[i * 2 + 1]); - break; - } - case 2: - { - var buf = Data[k] as ushort[]; - writer.Write(buf[i * 3 + 0]); - writer.Write(buf[i * 3 + 1]); - writer.Write(buf[i * 3 + 2]); - break; - } - case 3: - { - var buf = Data[k] as ushort[]; - writer.Write(buf[i * 4 + 0]); - writer.Write(buf[i * 4 + 1]); - writer.Write(buf[i * 4 + 2]); - writer.Write(buf[i * 4 + 3]); - break; - } - - // float32 - case 4: - { - var buf = Data[k] as float[]; - writer.Write(buf[i * 1 + 0]); - break; - } - case 5: - { - var buf = Data[k] as float[]; - writer.Write(buf[i * 2 + 0]); - writer.Write(buf[i * 2 + 1]); - break; - } - case 6: - { - var buf = Data[k] as float[]; - writer.Write(buf[i * 3 + 0]); - writer.Write(buf[i * 3 + 1]); - writer.Write(buf[i * 3 + 2]); - break; - } - case 7: - { - var buf = Data[k] as float[]; - writer.Write(buf[i * 4 + 0]); - writer.Write(buf[i * 4 + 1]); - writer.Write(buf[i * 4 + 2]); - writer.Write(buf[i * 4 + 3]); - break; - } - - case 8: - case 9: - case 10: - { - var buf = Data[k] as uint[]; - writer.Write(buf[i * 1 + 0]); - break; - } - - default: - throw new Exception(); - } - } - } - - } - - } - public override void Write(ResourceDataWriter writer, params object[] parameters) { if (VertexBytes != null) @@ -2968,6 +2815,467 @@ namespace CodeWalker.GameFiles writer.Write(VertexBytes); //not dealing with individual vertex data here any more! } } + public void WriteXml(StringBuilder sb, int indent) + { + var flags = Info?.Flags ?? 0; + var row = new StringBuilder(); + for (int v = 0; v < VertexCount; v++) + { + row.Clear(); + for (int k = 0; k < 16; k++) + { + if (((flags >> k) & 0x1) == 1) + { + if (row.Length > 0) row.Append(" "); + var str = GetString(v, k, " "); + row.Append(str); + } + } + YdrXml.Indent(sb, indent); + sb.AppendLine(row.ToString()); + } + } + public void ReadXml(XmlNode node, VertexDeclaration info) + { + Info = info; + VertexType = (VertexType)(info?.Flags ?? 0); + + if (Info != null) + { + var flags = Info.Flags; + var stride = Info.Stride; + var vstrs = new List(); + var coldelim = new[] { ' ', '\t' }; + var rowdelim = new[] { '\n' }; + var rows = node?.InnerText?.Trim()?.Split(rowdelim, StringSplitOptions.RemoveEmptyEntries); + if (rows != null) + { + foreach (var row in rows) + { + var rowt = row.Trim(); + if (string.IsNullOrEmpty(rowt)) continue; + var cols = row.Split(coldelim, StringSplitOptions.RemoveEmptyEntries); + vstrs.Add(cols); + } + } + if (vstrs.Count > 0) + { + AllocateData(vstrs.Count); + for (int v = 0; v < vstrs.Count; v++) + { + var vstr = vstrs[v]; + var sind = 0; + for (int k = 0; k < 16; k++) + { + if (((flags >> k) & 0x1) == 1) + { + SetString(v, k, vstr, ref sind); + } + } + } + } + } + } + + + public void AllocateData(int vertexCount) + { + if (Info != null) + { + var stride = Info.Stride; + var byteCount = vertexCount * stride; + VertexBytes = new byte[byteCount]; + VertexCount = vertexCount; + } + } + + public void SetString(int v, int c, string[] strs, ref int sind) + { + if ((Info != null) && (VertexBytes != null) && (strs != null)) + { + var ind = sind; + float f(int i) => FloatUtil.Parse(strs[ind + i].Trim()); + byte b(int i) { if (byte.TryParse(strs[ind + i].Trim(), out byte x)) return x; else return 0; } + var ct = Info.GetComponentType(c); + var cc = VertexComponentTypes.GetComponentCount(ct); + if (sind + cc > strs.Length) + { return; } + switch (ct) + { + case VertexComponentType.Float: SetFloat(v, c, f(0)); break; + case VertexComponentType.Float2: SetVector2(v, c, new Vector2(f(0), f(1))); break; + case VertexComponentType.Float3: SetVector3(v, c, new Vector3(f(0), f(1), f(2))); break; + case VertexComponentType.Float4: SetVector4(v, c, new Vector4(f(0), f(1), f(2), f(3))); break; + case VertexComponentType.Dec3N: SetDec3N(v, c, new Vector3(f(0), f(1), f(2))); break; + case VertexComponentType.Half2: SetHalf2(v, c, new Half2(f(0), f(1))); break; + case VertexComponentType.Half4: SetHalf4(v, c, new Half4(f(0), f(1), f(2), f(3))); break; + case VertexComponentType.Colour: SetColour(v, c, new Color(b(0), b(1), b(2), b(3))); break; + case VertexComponentType.UByte4: SetUByte4(v, c, new Color(b(0), b(1), b(2), b(3))); break; + default: + break; + } + sind += cc; + } + } + public void SetFloat(int v, int c, float val) + { + if ((Info != null) && (VertexBytes != null)) + { + var s = Info.Stride; + var co = Info.GetComponentOffset(c); + var o = (v * s) + co; + var e = o + 4;//sizeof(float) + if (e <= VertexBytes.Length) + { + var b = BitConverter.GetBytes(val); + Buffer.BlockCopy(b, 0, VertexBytes, o, 4); + } + } + } + public void SetVector2(int v, int c, Vector2 val) + { + if ((Info != null) && (VertexBytes != null)) + { + var s = Info.Stride; + var co = Info.GetComponentOffset(c); + var o = (v * s) + co; + var e = o + 8;//sizeof(Vector2) + if (e <= VertexBytes.Length) + { + var x = BitConverter.GetBytes(val.X); + var y = BitConverter.GetBytes(val.Y); + Buffer.BlockCopy(x, 0, VertexBytes, o + 0, 4); + Buffer.BlockCopy(y, 0, VertexBytes, o + 4, 4); + } + } + } + public void SetVector3(int v, int c, Vector3 val) + { + if ((Info != null) && (VertexBytes != null)) + { + var s = Info.Stride; + var co = Info.GetComponentOffset(c); + var o = (v * s) + co; + var e = o + 12;//sizeof(Vector3) + if (e <= VertexBytes.Length) + { + var x = BitConverter.GetBytes(val.X); + var y = BitConverter.GetBytes(val.Y); + var z = BitConverter.GetBytes(val.Z); + Buffer.BlockCopy(x, 0, VertexBytes, o + 0, 4); + Buffer.BlockCopy(y, 0, VertexBytes, o + 4, 4); + Buffer.BlockCopy(z, 0, VertexBytes, o + 8, 4); + } + } + } + public void SetVector4(int v, int c, Vector4 val) + { + if ((Info != null) && (VertexBytes != null)) + { + var s = Info.Stride; + var co = Info.GetComponentOffset(c); + var o = (v * s) + co; + var e = o + 16;//sizeof(Vector4) + if (e <= VertexBytes.Length) + { + var x = BitConverter.GetBytes(val.X); + var y = BitConverter.GetBytes(val.Y); + var z = BitConverter.GetBytes(val.Z); + var w = BitConverter.GetBytes(val.W); + Buffer.BlockCopy(x, 0, VertexBytes, o + 0, 4); + Buffer.BlockCopy(y, 0, VertexBytes, o + 4, 4); + Buffer.BlockCopy(z, 0, VertexBytes, o + 8, 4); + Buffer.BlockCopy(w, 0, VertexBytes, o + 12, 4); + } + } + } + public void SetDec3N(int v, int c, Vector3 val) + { + //see https://docs.microsoft.com/en-us/previous-versions/windows/desktop/bb322868(v%3Dvs.85) + if ((Info != null) && (VertexBytes != null)) + { + var s = Info.Stride; + var co = Info.GetComponentOffset(c); + var o = (v * s) + co; + var e = o + 4;//sizeof(Dec3N) + if (e <= VertexBytes.Length) + { + var sx = (val.X < 0.0f); + var sy = (val.X < 0.0f); + var sz = (val.X < 0.0f); + var x = Math.Min((uint)(Math.Abs(val.X) * 511.0f), 511); + var y = Math.Min((uint)(Math.Abs(val.Y) * 511.0f), 511); + var z = Math.Min((uint)(Math.Abs(val.Z) * 511.0f), 511); + var ux = ((sx ? ~x : x) & 0x1FF) + (sx ? 0x200 : 0); + var uy = ((sy ? ~y : y) & 0x1FF) + (sy ? 0x200 : 0); + var uz = ((sz ? ~z : z) & 0x1FF) + (sz ? 0x200 : 0); + var uw = 0u; + var u = ux + (uy << 10) + (uz << 20) + (uw << 30); + var b = BitConverter.GetBytes(u); + Buffer.BlockCopy(b, 0, VertexBytes, o, 4); + } + } + } + public void SetHalf2(int v, int c, Half2 val) + { + if ((Info != null) && (VertexBytes != null)) + { + var s = Info.Stride; + var co = Info.GetComponentOffset(c); + var o = (v * s) + co; + var e = o + 4;//sizeof(Half2) + if (e <= VertexBytes.Length) + { + var x = BitConverter.GetBytes(val.X.RawValue); + var y = BitConverter.GetBytes(val.Y.RawValue); + Buffer.BlockCopy(x, 0, VertexBytes, o + 0, 2); + Buffer.BlockCopy(y, 0, VertexBytes, o + 2, 2); + } + } + } + public void SetHalf4(int v, int c, Half4 val) + { + if ((Info != null) && (VertexBytes != null)) + { + var s = Info.Stride; + var co = Info.GetComponentOffset(c); + var o = (v * s) + co; + var e = o + 8;//sizeof(Half4) + if (e <= VertexBytes.Length) + { + var x = BitConverter.GetBytes(val.X.RawValue); + var y = BitConverter.GetBytes(val.Y.RawValue); + var z = BitConverter.GetBytes(val.Z.RawValue); + var w = BitConverter.GetBytes(val.W.RawValue); + Buffer.BlockCopy(x, 0, VertexBytes, o + 0, 2); + Buffer.BlockCopy(y, 0, VertexBytes, o + 2, 2); + Buffer.BlockCopy(z, 0, VertexBytes, o + 4, 2); + Buffer.BlockCopy(w, 0, VertexBytes, o + 6, 2); + } + } + } + public void SetColour(int v, int c, Color val) + { + if ((Info != null) && (VertexBytes != null)) + { + var s = Info.Stride; + var co = Info.GetComponentOffset(c); + var o = (v * s) + co; + var e = o + 4;//sizeof(Color) + if (e <= VertexBytes.Length) + { + var u = val.ToRgba(); + var b = BitConverter.GetBytes(u); + Buffer.BlockCopy(b, 0, VertexBytes, o, 4); + } + } + } + public void SetUByte4(int v, int c, Color val) + { + if ((Info != null) && (VertexBytes != null)) + { + var s = Info.Stride; + var co = Info.GetComponentOffset(c); + var o = (v * s) + co; + var e = o + 4;//sizeof(UByte4) + if (e <= VertexBytes.Length) + { + var u = val.ToRgba(); + var b = BitConverter.GetBytes(u); + Buffer.BlockCopy(b, 0, VertexBytes, o, 4); + } + } + } + + public string GetString(int v, int c, string d = ", ") + { + if ((Info != null) && (VertexBytes != null)) + { + var ct = Info.GetComponentType(c); + switch (ct) + { + case VertexComponentType.Float: return FloatUtil.ToString(GetFloat(v, c)); + case VertexComponentType.Float2: return FloatUtil.GetVector2String(GetVector2(v, c), d); + case VertexComponentType.Float3: return FloatUtil.GetVector3String(GetVector3(v, c), d); + case VertexComponentType.Float4: return FloatUtil.GetVector4String(GetVector4(v, c), d); + case VertexComponentType.Dec3N: return FloatUtil.GetVector3String(GetDec3N(v, c), d); + case VertexComponentType.Half2: return FloatUtil.GetHalf2String(GetHalf2(v, c), d); + case VertexComponentType.Half4: return FloatUtil.GetHalf4String(GetHalf4(v, c), d); + case VertexComponentType.Colour: return FloatUtil.GetColourString(GetColour(v, c), d); + case VertexComponentType.UByte4: return FloatUtil.GetColourString(GetUByte4(v, c), d); + default: + break; + } + } + return string.Empty; + } + public float GetFloat(int v, int c) + { + if ((Info != null) && (VertexBytes != null)) + { + var s = Info.Stride; + var co = Info.GetComponentOffset(c); + var o = (v * s) + co; + var e = o + 4;//sizeof(float) + if (e <= VertexBytes.Length) + { + var f = BitConverter.ToSingle(VertexBytes, o); + return f; + } + } + return 0; + } + public Vector2 GetVector2(int v, int c) + { + if ((Info != null) && (VertexBytes != null)) + { + var s = Info.Stride; + var co = Info.GetComponentOffset(c); + var o = (v * s) + co; + var e = o + 8;//sizeof(Vector2) + if (e <= VertexBytes.Length) + { + var x = BitConverter.ToSingle(VertexBytes, o + 0); + var y = BitConverter.ToSingle(VertexBytes, o + 4); + return new Vector2(x, y); + } + } + return Vector2.Zero; + } + public Vector3 GetVector3(int v, int c) + { + if ((Info != null) && (VertexBytes != null)) + { + var s = Info.Stride; + var co = Info.GetComponentOffset(c); + var o = (v * s) + co; + var e = o + 12;//sizeof(Vector3) + if (e <= VertexBytes.Length) + { + var x = BitConverter.ToSingle(VertexBytes, o + 0); + var y = BitConverter.ToSingle(VertexBytes, o + 4); + var z = BitConverter.ToSingle(VertexBytes, o + 8); + return new Vector3(x, y, z); + } + } + return Vector3.Zero; + } + public Vector4 GetVector4(int v, int c) + { + if ((Info != null) && (VertexBytes != null)) + { + var s = Info.Stride; + var co = Info.GetComponentOffset(c); + var o = (v * s) + co; + var e = o + 16;//sizeof(Vector4) + if (e <= VertexBytes.Length) + { + var x = BitConverter.ToSingle(VertexBytes, o + 0); + var y = BitConverter.ToSingle(VertexBytes, o + 4); + var z = BitConverter.ToSingle(VertexBytes, o + 8); + var w = BitConverter.ToSingle(VertexBytes, o + 12); + return new Vector4(x, y, z, w); + } + } + return Vector4.Zero; + } + public Vector3 GetDec3N(int v, int c) + { + //see https://docs.microsoft.com/en-us/previous-versions/windows/desktop/bb322868(v%3Dvs.85) + if ((Info != null) && (VertexBytes != null)) + { + var s = Info.Stride; + var co = Info.GetComponentOffset(c); + var o = (v * s) + co; + var e = o + 4;//sizeof(Dec3N) + if (e <= VertexBytes.Length) + { + var u = BitConverter.ToUInt32(VertexBytes, o); + var ux = (u >> 0) & 0x3FF; + var uy = (u >> 10) & 0x3FF; + var uz = (u >> 20) & 0x3FF; + var uw = (u >> 30); + var sx = (ux & 0x200) > 0; + var sy = (uy & 0x200) > 0; + var sz = (uz & 0x200) > 0; + var x = ((sx ? ~ux : ux) & 0x1FF) / (sx ? -511.0f : 511.0f); + var y = ((sy ? ~uy : uy) & 0x1FF) / (sy ? -511.0f : 511.0f); + var z = ((sz ? ~uz : uz) & 0x1FF) / (sz ? -511.0f : 511.0f); + return new Vector3(x, y, z); + } + } + return Vector3.Zero; + } + public Half2 GetHalf2(int v, int c) + { + if ((Info != null) && (VertexBytes != null)) + { + var s = Info.Stride; + var co = Info.GetComponentOffset(c); + var o = (v * s) + co; + var e = o + 4;//sizeof(Half2) + if (e <= VertexBytes.Length) + { + var x = BitConverter.ToUInt16(VertexBytes, o + 0); + var y = BitConverter.ToUInt16(VertexBytes, o + 2); + return new Half2(x, y); + } + } + return new Half2(0, 0); + } + public Half4 GetHalf4(int v, int c) + { + if ((Info != null) && (VertexBytes != null)) + { + var s = Info.Stride; + var co = Info.GetComponentOffset(c); + var o = (v * s) + co; + var e = o + 8;//sizeof(Half4) + if (e <= VertexBytes.Length) + { + var x = BitConverter.ToUInt16(VertexBytes, o + 0); + var y = BitConverter.ToUInt16(VertexBytes, o + 2); + var z = BitConverter.ToUInt16(VertexBytes, o + 4); + var w = BitConverter.ToUInt16(VertexBytes, o + 6); + return new Half4(x, y, z, w); + } + } + return new Half4(0, 0, 0, 0); + } + public Color GetColour(int v, int c) + { + if ((Info != null) && (VertexBytes != null)) + { + var s = Info.Stride; + var co = Info.GetComponentOffset(c); + var o = (v * s) + co; + var e = o + 4;//sizeof(Color) + if (e <= VertexBytes.Length) + { + var rgba = BitConverter.ToUInt32(VertexBytes, o); + return new Color(rgba); + } + } + return Color.Black; + } + public Color GetUByte4(int v, int c) + { + //Color is the same as UByte4 really + if ((Info != null) && (VertexBytes != null)) + { + var s = Info.Stride; + var co = Info.GetComponentOffset(c); + var o = (v * s) + co; + var e = o + 4;//sizeof(UByte4) + if (e <= VertexBytes.Length) + { + var rgba = BitConverter.ToUInt32(VertexBytes, o); + return new Color(rgba); + } + } + return new Color(0, 0, 0, 0); + } + public override string ToString() { @@ -2985,13 +3293,10 @@ namespace CodeWalker.GameFiles // structure data public uint Flags { get; set; } public ushort Stride { get; set; } - public byte Unknown_6h { get; set; } + public byte Unknown_6h { get; set; }//0 public byte Count { get; set; } - public ulong Types { get; set; } + public VertexDeclarationTypes Types { get; set; } - /// - /// Reads the data-block from a stream. - /// public override void Read(ResourceDataReader reader, params object[] parameters) { // read structure data @@ -2999,12 +3304,14 @@ namespace CodeWalker.GameFiles this.Stride = reader.ReadUInt16(); this.Unknown_6h = reader.ReadByte(); this.Count = reader.ReadByte(); - this.Types = reader.ReadUInt64(); - } + this.Types = (VertexDeclarationTypes)reader.ReadUInt64(); - /// - /// Writes the data-block to a stream. - /// + ////just testing! + //UpdateCountAndStride(); + //if (Unknown_6h != 0) + //{ }//no hit + + } public override void Write(ResourceDataWriter writer, params object[] parameters) { // write structure data @@ -3012,7 +3319,37 @@ namespace CodeWalker.GameFiles writer.Write(this.Stride); writer.Write(this.Unknown_6h); writer.Write(this.Count); - writer.Write(this.Types); + writer.Write((ulong)this.Types); + } + public void WriteXml(StringBuilder sb, int indent) + { + for (int k = 0; k < 16; k++) + { + if (((Flags >> k) & 0x1) == 1) + { + var componentSemantic = (VertexSemantics)k; + var tag = componentSemantic.ToString(); + YdrXml.SelfClosingTag(sb, indent, tag); + } + } + } + public void ReadXml(XmlNode node) + { + Types = Xml.GetEnumValue(Xml.GetStringAttribute(node, "type")); + + uint f = 0; + foreach (XmlNode cnode in node.ChildNodes) + { + if (cnode is XmlElement celem) + { + var componentSematic = Xml.GetEnumValue(celem.Name); + var idx = (int)componentSematic; + f = f | (1u << idx); + } + } + Flags = f; + + UpdateCountAndStride(); } public ulong GetDeclarationId() @@ -3022,12 +3359,57 @@ namespace CodeWalker.GameFiles { if (((Flags >> i) & 1) == 1) { - res += (Types & (0xFu << (i * 4))); + res += ((ulong)Types & (0xFu << (i * 4))); } } return res; } + public VertexComponentType GetComponentType(int index) + { + //index is the flags bit index + return (VertexComponentType)(((ulong)Types >> (index * 4)) & 0x0000000F); + } + + public int GetComponentOffset(int index) + { + //index is the flags bit index + var offset = 0; + for (int k = 0; k < index; k++) + { + if (((Flags >> k) & 0x1) == 1) + { + var componentType = GetComponentType(k); + offset += VertexComponentTypes.GetSizeInBytes(componentType); + } + } + return offset; + } + + public void UpdateCountAndStride() + { + var cnt = 0; + var str = 0; + for (int k = 0; k < 16; k++) + { + if (((Flags >> k) & 0x1) == 1) + { + var componentType = GetComponentType(k); + str += VertexComponentTypes.GetSizeInBytes(componentType); + cnt++; + } + } + + ////just testing + //if (Count != cnt) + //{ }//no hit + //if (Stride != str) + //{ }//no hit + + Count = (byte)cnt; + Stride = (ushort)str; + } + public override string ToString() { return Stride.ToString() + ": " + Count.ToString() + ": " + Flags.ToString() + ": " + Types.ToString(); @@ -3043,7 +3425,7 @@ namespace CodeWalker.GameFiles // structure data public uint VFT { get; set; } - public uint Unknown_4h { get; set; } // 0x00000001 + public uint Unknown_4h { get; set; } = 1; // 0x00000001 public uint IndicesCount { get; set; } public uint Unknown_Ch { get; set; } // 0x00000000 public ulong IndicesPointer { get; set; } @@ -3074,9 +3456,6 @@ namespace CodeWalker.GameFiles private ResourceSystemStructBlock IndicesBlock = null; //only used when saving - /// - /// Reads the data-block from a stream. - /// public override void Read(ResourceDataReader reader, params object[] parameters) { // read structure data @@ -3111,10 +3490,6 @@ namespace CodeWalker.GameFiles //); this.Indices = reader.ReadUshortsAt(this.IndicesPointer, this.IndicesCount); } - - /// - /// Writes the data-block to a stream. - /// public override void Write(ResourceDataWriter writer, params object[] parameters) { // update structure data @@ -3146,10 +3521,24 @@ namespace CodeWalker.GameFiles writer.Write(this.Unknown_58h); writer.Write(this.Unknown_5Ch); } + public void WriteXml(StringBuilder sb, int indent) + { + if (Indices != null) + { + YdrXml.WriteRawArray(sb, Indices, indent, "Data", "", null, 24); + } + } + public void ReadXml(XmlNode node) + { + var inode = node.SelectSingleNode("Data"); + if (inode != null) + { + Indices = Xml.GetRawUshortArray(node); + IndicesCount = (uint)(Indices?.Length ?? 0); + } + } + - /// - /// Returns a list of data blocks which are referenced by this block. - /// public override IResourceBlock[] GetReferences() { var list = new List(); @@ -3325,16 +3714,58 @@ namespace CodeWalker.GameFiles public float LodDistMed { get; set; } public float LodDistLow { get; set; } public float LodDistVlow { get; set; } - public uint Unknown_80h { get; set; } - public uint Unknown_84h { get; set; } - public uint Unknown_88h { get; set; } - public uint Unknown_8Ch { get; set; } + public uint RenderMaskFlagsHigh { get; set; } + public uint RenderMaskFlagsMed { get; set; } + public uint RenderMaskFlagsLow { get; set; } + public uint RenderMaskFlagsVlow { get; set; } public ulong JointsPointer { get; set; } - public ushort Unknown_98h { get; set; } + public ushort Unknown_98h { get; set; } // 0 public ushort Unknown_9Ah { get; set; } public uint Unknown_9Ch { get; set; } // 0x00000000 public ulong DrawableModelsXPointer { get; set; } + public byte FlagsHigh + { + get { return (byte)(RenderMaskFlagsHigh & 0xFF); } + set { RenderMaskFlagsHigh = (RenderMaskFlagsHigh & 0xFFFFFF00) + (value & 0xFFu); } + } + public byte FlagsMed + { + get { return (byte)(RenderMaskFlagsMed & 0xFF); } + set { RenderMaskFlagsMed = (RenderMaskFlagsMed & 0xFFFFFF00) + (value & 0xFFu); } + } + public byte FlagsLow + { + get { return (byte)(RenderMaskFlagsLow & 0xFF); } + set { RenderMaskFlagsLow = (RenderMaskFlagsLow & 0xFFFFFF00) + (value & 0xFFu); } + } + public byte FlagsVlow + { + get { return (byte)(RenderMaskFlagsVlow & 0xFF); } + set { RenderMaskFlagsVlow = (RenderMaskFlagsVlow & 0xFFFFFF00) + (value & 0xFFu); } + } + public byte RenderMaskHigh + { + get { return (byte)((RenderMaskFlagsHigh >> 8) & 0xFF); } + set { RenderMaskFlagsHigh = (RenderMaskFlagsHigh & 0xFFFF00FF) + ((value & 0xFFu) << 8); } + } + public byte RenderMaskMed + { + get { return (byte)((RenderMaskFlagsMed >> 8) & 0xFF); } + set { RenderMaskFlagsMed = (RenderMaskFlagsMed & 0xFFFF00FF) + ((value & 0xFFu) << 8); } + } + public byte RenderMaskLow + { + get { return (byte)((RenderMaskFlagsLow >> 8) & 0xFF); } + set { RenderMaskFlagsLow = (RenderMaskFlagsLow & 0xFFFF00FF) + ((value & 0xFFu) << 8); } + } + public byte RenderMaskVlow + { + get { return (byte)((RenderMaskFlagsVlow >> 8) & 0xFF); } + set { RenderMaskFlagsVlow = (RenderMaskFlagsVlow & 0xFFFF00FF) + ((value & 0xFFu) << 8); } + } + + // reference data public ShaderGroup ShaderGroup { get; set; } public Skeleton Skeleton { get; set; } @@ -3393,10 +3824,10 @@ namespace CodeWalker.GameFiles this.LodDistMed = reader.ReadSingle(); this.LodDistLow = reader.ReadSingle(); this.LodDistVlow = reader.ReadSingle(); - this.Unknown_80h = reader.ReadUInt32(); - this.Unknown_84h = reader.ReadUInt32(); - this.Unknown_88h = reader.ReadUInt32(); - this.Unknown_8Ch = reader.ReadUInt32(); + this.RenderMaskFlagsHigh = reader.ReadUInt32(); + this.RenderMaskFlagsMed = reader.ReadUInt32(); + this.RenderMaskFlagsLow = reader.ReadUInt32(); + this.RenderMaskFlagsVlow = reader.ReadUInt32(); this.JointsPointer = reader.ReadUInt64(); this.Unknown_98h = reader.ReadUInt16(); this.Unknown_9Ah = reader.ReadUInt16(); @@ -3465,6 +3896,177 @@ namespace CodeWalker.GameFiles VertexDecls = new Dictionary(vds); AssignGeometryShaders(ShaderGroup); + + + + + + ////just testing!!! + //if ((DrawableModelsHigh?.data_items != null) != (Unknown_80h != 0)) + //{ }//no hit + //if ((DrawableModelsMedium?.data_items != null) != (Unknown_84h != 0)) + //{ }//no hit + //if ((DrawableModelsLow?.data_items != null) != (Unknown_88h != 0)) + //{ }//no hit + //if ((DrawableModelsVeryLow?.data_items != null) != (Unknown_8Ch != 0)) + //{ }//no hit + //if ((Unknown_80h & 0xFFFF0000) > 0) + //{ }//no hit + //if ((Unknown_84h & 0xFFFF0000) > 0) + //{ }//no hit + //if ((Unknown_88h & 0xFFFF0000) > 0) + //{ }//no hit + //if ((Unknown_8Ch & 0xFFFF0000) > 0) + //{ }//no hit + //BuildRenderMasks(); + + //switch (FlagsHigh) + //{ + // case 2: + // case 1: + // case 13: + // case 4: + // case 12: + // case 5: + // case 3: + // case 8: + // case 9: + // case 15: + // case 130: + // case 11: + // case 10: + // case 7: + // case 131: + // case 129: + // case 75: + // case 69: + // case 6: + // case 64: + // case 14: + // case 77: + // case 73: + // case 76: + // case 71: + // case 79: + // case 65: + // case 0://some yft's have null HD models + // case 19: + // case 51: + // break; + // default: + // break; + //} + //switch (FlagsMed) + //{ + // case 0: + // case 1: + // case 9: + // case 8: + // case 13: + // case 3: + // case 2: + // case 5: + // case 11: + // case 15: + // case 10: + // case 12: + // case 4: + // case 7: + // case 51: + // break; + // default: + // break; + //} + //switch (FlagsLow) + //{ + // case 0: + // case 9: + // case 1: + // case 8: + // case 5: + // case 3: + // case 13: + // case 2: + // case 11: + // case 15: + // case 4: + // case 7: + // case 51: + // break; + // default: + // break; + //} + //switch (FlagsVlow) + //{ + // case 0: + // case 1: + // case 9: + // case 3: + // case 7: + // case 5: + // case 49: + // case 51: + // case 11: + // break; + // default: + // break; + //} + //switch (Unknown_98h) + //{ + // case 0: + // break; + // default: + // break;//no hit + //} + //switch (Unknown_9Ah)//wtf isthis? flags? + //{ + // case 18: + // case 33: + // case 34: + // case 46: + // case 58: + // case 209: + // case 71: + // case 172: + // case 64: + // case 122: + // case 96: + // case 248: + // case 147: + // case 51: + // case 159: + // case 134: + // case 108: + // case 83: + // case 336: + // case 450: + // case 197: + // case 374: + // case 184: + // case 310: + // case 36: + // case 386: + // case 285: + // case 260: + // case 77: + // case 361: + // case 235: + // case 91: + // case 223: + // case 1207: + // case 2090: + // case 45: + // case 52: + // case 526: + // case 3081: + // case 294: + // case 236: + // case 156: + // break; + // default://still lots more.. + // break; + //} + } public override void Write(ResourceDataWriter writer, params object[] parameters) { @@ -3495,10 +4097,10 @@ namespace CodeWalker.GameFiles writer.Write(this.LodDistMed); writer.Write(this.LodDistLow); writer.Write(this.LodDistVlow); - writer.Write(this.Unknown_80h); - writer.Write(this.Unknown_84h); - writer.Write(this.Unknown_88h); - writer.Write(this.Unknown_8Ch); + writer.Write(this.RenderMaskFlagsHigh); + writer.Write(this.RenderMaskFlagsMed); + writer.Write(this.RenderMaskFlagsLow); + writer.Write(this.RenderMaskFlagsVlow); writer.Write(this.JointsPointer); writer.Write(this.Unknown_98h); writer.Write(this.Unknown_9Ah); @@ -3515,11 +4117,10 @@ namespace CodeWalker.GameFiles YdrXml.ValueTag(sb, indent, "LodDistMed", FloatUtil.ToString(LodDistMed)); YdrXml.ValueTag(sb, indent, "LodDistLow", FloatUtil.ToString(LodDistLow)); YdrXml.ValueTag(sb, indent, "LodDistVlow", FloatUtil.ToString(LodDistVlow)); - YdrXml.ValueTag(sb, indent, "Unknown80", Unknown_80h.ToString()); - YdrXml.ValueTag(sb, indent, "Unknown84", Unknown_84h.ToString()); - YdrXml.ValueTag(sb, indent, "Unknown88", Unknown_88h.ToString()); - YdrXml.ValueTag(sb, indent, "Unknown8C", Unknown_8Ch.ToString()); - YdrXml.ValueTag(sb, indent, "Unknown98", Unknown_98h.ToString()); + YdrXml.ValueTag(sb, indent, "FlagsHigh", FlagsHigh.ToString()); + YdrXml.ValueTag(sb, indent, "FlagsMed", FlagsMed.ToString()); + YdrXml.ValueTag(sb, indent, "FlagsLow", FlagsLow.ToString()); + YdrXml.ValueTag(sb, indent, "FlagsVlow", FlagsVlow.ToString()); YdrXml.ValueTag(sb, indent, "Unknown9A", Unknown_9Ah.ToString()); if (ShaderGroup != null) { @@ -3570,11 +4171,10 @@ namespace CodeWalker.GameFiles LodDistMed = Xml.GetChildFloatAttribute(node, "LodDistMed", "value"); LodDistLow = Xml.GetChildFloatAttribute(node, "LodDistLow", "value"); LodDistVlow = Xml.GetChildFloatAttribute(node, "LodDistVlow", "value"); - Unknown_80h = Xml.GetChildUIntAttribute(node, "Unknown80", "value"); - Unknown_84h = Xml.GetChildUIntAttribute(node, "Unknown84", "value"); - Unknown_88h = Xml.GetChildUIntAttribute(node, "Unknown88", "value"); - Unknown_8Ch = Xml.GetChildUIntAttribute(node, "Unknown8C", "value"); - Unknown_98h = (ushort)Xml.GetChildUIntAttribute(node, "Unknown98", "value"); + FlagsHigh = (byte)Xml.GetChildUIntAttribute(node, "FlagsHigh", "value"); + FlagsMed = (byte)Xml.GetChildUIntAttribute(node, "FlagsMed", "value"); + FlagsLow = (byte)Xml.GetChildUIntAttribute(node, "FlagsLow", "value"); + FlagsVlow = (byte)Xml.GetChildUIntAttribute(node, "FlagsVlow", "value"); Unknown_9Ah = (ushort)Xml.GetChildUIntAttribute(node, "Unknown9A", "value"); var sgnode = node.SelectSingleNode("ShaderGroup"); if (sgnode != null) @@ -3624,6 +4224,12 @@ namespace CodeWalker.GameFiles DrawableModelsX = new ResourcePointerList64(); DrawableModelsX.data_items = dmx; } + else + { + DrawableModelsX = DrawableModelsHigh; + } + + BuildRenderMasks(); } public override IResourceBlock[] GetReferences() @@ -3672,6 +4278,43 @@ namespace CodeWalker.GameFiles } + public void BuildRenderMasks() + { + var hmask = BuildRenderMask(DrawableModelsHigh?.data_items); + var mmask = BuildRenderMask(DrawableModelsMedium?.data_items); + var lmask = BuildRenderMask(DrawableModelsLow?.data_items); + var vmask = BuildRenderMask(DrawableModelsVeryLow?.data_items); + + ////just testing + //if (hmask != RenderMaskHigh) + //{ }//no hit + //if (mmask != RenderMaskMed) + //{ }//no hit + //if (lmask != RenderMaskLow) + //{ }//no hit + //if (vmask != RenderMaskVlow) + //{ }//no hit + + RenderMaskHigh = hmask; + RenderMaskMed = mmask; + RenderMaskLow = lmask; + RenderMaskVlow = vmask; + + } + private byte BuildRenderMask(DrawableModel[] models) + { + byte mask = 0; + if (models != null) + { + foreach (var model in models) + { + mask = (byte)(mask | model.RenderMask); + } + } + return mask; + } + + public DrawableBase ShallowCopy() { DrawableBase r = null; @@ -3711,10 +4354,10 @@ namespace CodeWalker.GameFiles r.LodDistMed = LodDistMed; r.LodDistLow = LodDistLow; r.LodDistVlow = LodDistVlow; - r.Unknown_80h = Unknown_80h; - r.Unknown_84h = Unknown_84h; - r.Unknown_88h = Unknown_88h; - r.Unknown_8Ch = Unknown_8Ch; + r.RenderMaskFlagsHigh = RenderMaskFlagsHigh; + r.RenderMaskFlagsMed = RenderMaskFlagsMed; + r.RenderMaskFlagsLow = RenderMaskFlagsLow; + r.RenderMaskFlagsVlow = RenderMaskFlagsVlow; r.Unknown_98h = Unknown_98h; r.Unknown_9Ah = Unknown_9Ah; r.ShaderGroup = ShaderGroup; @@ -3826,12 +4469,10 @@ namespace CodeWalker.GameFiles { Bound = Bounds.ReadXmlNode(bnode, this); } - var lights = XmlMeta.ReadItemArray(node, "LightAttributes"); - if (lights != null) - { - LightAttributes = new ResourceSimpleList64_s(); - LightAttributes.data_items = lights; - } + + LightAttributes = new ResourceSimpleList64_s(); + LightAttributes.data_items = XmlMeta.ReadItemArray(node, "LightAttributes"); + } public static void WriteXmlNode(Drawable d, StringBuilder sb, int indent, string ddsfolder, string name = "Drawable") { diff --git a/CodeWalker.Core/GameFiles/Resources/VertexType.cs b/CodeWalker.Core/GameFiles/Resources/VertexType.cs index bdecd28..1fc25ee 100644 --- a/CodeWalker.Core/GameFiles/Resources/VertexType.cs +++ b/CodeWalker.Core/GameFiles/Resources/VertexType.cs @@ -10,15 +10,15 @@ namespace CodeWalker.GameFiles public enum VertexComponentType : byte { Nothing = 0, - Float16Two = 1, + Half2 = 1, Float = 2, - Float16Four = 3, - Float_unk = 4, + Half4 = 3, + FloatUnk = 4, Float2 = 5, Float3 = 6, Float4 = 7, UByte4 = 8, - Color = 9, + Colour = 9, Dec3N = 10, Unk1 = 11, Unk2 = 12, @@ -27,11 +27,53 @@ namespace CodeWalker.GameFiles Unk5 = 15, } + public static class VertexComponentTypes + { + public static int GetSizeInBytes(VertexComponentType type) + { + switch (type) + { + case VertexComponentType.Nothing: return 0; + case VertexComponentType.Half2: return 4; + case VertexComponentType.Float: return 4; + case VertexComponentType.Half4: return 8; + case VertexComponentType.FloatUnk: return 0; + case VertexComponentType.Float2: return 8; + case VertexComponentType.Float3: return 12; + case VertexComponentType.Float4: return 16; + case VertexComponentType.UByte4: return 4; + case VertexComponentType.Colour: return 4; + case VertexComponentType.Dec3N: return 4; + default: return 0; + } + } + + public static int GetComponentCount(VertexComponentType type) + { + switch (type) + { + case VertexComponentType.Nothing: return 0; + case VertexComponentType.Half2: return 2; + case VertexComponentType.Float: return 1; + case VertexComponentType.Half4: return 4; + case VertexComponentType.FloatUnk: return 0; + case VertexComponentType.Float2: return 2; + case VertexComponentType.Float3: return 3; + case VertexComponentType.Float4: return 4; + case VertexComponentType.UByte4: return 4; + case VertexComponentType.Colour: return 4; + case VertexComponentType.Dec3N: return 3; + default: return 0; + } + } + + } + public enum VertexDeclarationTypes : ulong { - Types1 = 0x7755555555996996, // GTAV - used by most drawables - Types2 = 0x030000000199A006, // GTAV - used on cloth? - Types3 = 0x0300000001996006, // GTAV - used on cloth? + GTAV1 = 0x7755555555996996, // GTAV - used by most drawables + GTAV2 = 0x030000000199A006, // GTAV - used on cloth? + GTAV3 = 0x0300000001996006, // GTAV - used on cloth? //Types4 = 0x0000000007097007, // Max Payne 3 //Types5 = 0x0700000007097977, // Max Payne 3 @@ -40,6 +82,26 @@ namespace CodeWalker.GameFiles //Types8 = 0x0700007777997977, // Max Payne 3 } + public enum VertexSemantics : int + { + Position = 0, + BlendWeights = 1, + BlendIndices = 2, + Normal = 3, + Colour0 = 4, + Colour1 = 5, + TexCoord0 = 6, + TexCoord1 = 7, + TexCoord2 = 8, + TexCoord3 = 9, + TexCoord4 = 10, + TexCoord5 = 11, + TexCoord6 = 12, + TexCoord7 = 13, + Tangent = 14, + Binormal = 15, + } + public enum VertexType : uint { Default = 89, //PNCT @@ -82,52 +144,47 @@ namespace CodeWalker.GameFiles PBBNCTTTX = 16863, } - - //0x7755555555996996 - public struct VertexTypeGTAV1 + public struct VertexTypeGTAV1 //0x7755555555996996 { public Vector3 Position; public uint BlendWeights; public uint BlendIndices; - public Vector3 Normals; + public Vector3 Normal; public uint Colour0; public uint Colour1; - public Vector2 Texcoords0; - public Vector2 Texcoords1; - public Vector2 Texcoords2; - public Vector2 Texcoords3; - public Vector2 Texcoords4; - public Vector2 Texcoords5; - public Vector2 Texcoords6; - public Vector2 Texcoords7; - public Vector4 Tangents; - public Vector4 Binormals; + public Vector2 Texcoord0; + public Vector2 Texcoord1; + public Vector2 Texcoord2; + public Vector2 Texcoord3; + public Vector2 Texcoord4; + public Vector2 Texcoord5; + public Vector2 Texcoord6; + public Vector2 Texcoord7; + public Vector4 Tangent; + public Vector4 Binormal; } - //0x030000000199A006 - public struct VertexTypeGTAV2 + public struct VertexTypeGTAV2 //0x030000000199A006 { public Vector3 Position; - public uint Normals; // Packed as Dec3N + public uint Normal; // Packed as Dec3N public uint Colour0; public uint Colour1; - public Half2 Texcoords0; - public Half4 Tangents; + public Half2 Texcoord0; + public Half4 Tangent; } - //0x0300000001996006 - public struct VertexTypeGTAV3 + public struct VertexTypeGTAV3 //0x0300000001996006 { public Vector3 Position; - public Vector3 Normals; + public Vector3 Normal; public uint Colour0; public uint Colour1; - public Half2 Texcoords0; - public Half4 Tangents; + public Half2 Texcoord0; + public Half4 Tangent; } - //vertex data to be used by the editor. TODO: maybe move somewhere else. - public struct EditorVertex + public struct EditorVertex //vertex data to be used by the editor. TODO: maybe move somewhere else. { public Vector3 Position; public uint Colour; diff --git a/CodeWalker.Core/Utils/FbxConverter.cs b/CodeWalker.Core/Utils/FbxConverter.cs index a49de4e..8b361d4 100644 --- a/CodeWalker.Core/Utils/FbxConverter.cs +++ b/CodeWalker.Core/Utils/FbxConverter.cs @@ -164,10 +164,6 @@ namespace CodeWalker d.LodDistMed = 9998; d.LodDistLow = 9998; d.LodDistVlow = 9998; - d.Unknown_80h = 0;//TODO: figure these out! related to high/med/low/vlow 0xFF00 + ? - d.Unknown_84h = 0; - d.Unknown_88h = 0; - d.Unknown_8Ch = 0; d.Unknown_9Ah = 33;//WTF is this??? d.FileVFT = 1079446584; d.FileUnknown = 1; @@ -175,31 +171,33 @@ namespace CodeWalker { d.DrawableModelsHigh = new ResourcePointerList64(); d.DrawableModelsHigh.data_items = mlHigh.ToArray(); - d.Unknown_80h = 65281;//WTF is this??? 0xFF00 + ? + d.FlagsHigh = 1;//what flags should be used?? } if (mlMed.Count > 0) { d.DrawableModelsMedium = new ResourcePointerList64(); d.DrawableModelsMedium.data_items = mlMed.ToArray(); d.LodDistHigh = bsRad * 2.0f; //when med models present, generate a high lod dist.. - d.Unknown_84h = 65281;//WTF is this??? 0xFF00 + ? + d.FlagsMed = 1; } if (mlLow.Count > 0) { d.DrawableModelsLow = new ResourcePointerList64(); d.DrawableModelsLow.data_items = mlLow.ToArray(); d.LodDistMed = bsRad * 8.0f; //when low models present, generate a med lod dist.. - d.Unknown_88h = 65281;//WTF is this??? 0xFF00 + ? + d.FlagsLow = 1; } if (mlVlow.Count > 0) { d.DrawableModelsVeryLow = new ResourcePointerList64(); d.DrawableModelsVeryLow.data_items = mlVlow.ToArray(); d.LodDistLow = bsRad * 32.0f; //when vlow models present, generate a low lod dist.. - d.Unknown_8Ch = 65281;//WTF is this??? 0xFF00 + ? + d.FlagsVlow = 1; } d.DrawableModelsX = d.DrawableModelsHigh; + d.BuildRenderMasks(); + d.LightAttributes = new ResourceSimpleList64_s(); //todo: light attributes? @@ -598,7 +596,7 @@ namespace CodeWalker var vData = new VertexData(); - vData.info = dVertDecl; + vData.Info = dVertDecl; vData.VertexType = (VertexType)dVertDecl.Flags; vData.VertexStride = dVertDecl.Stride; vData.VertexCount = vList.Count; @@ -817,7 +815,7 @@ namespace CodeWalker private VertexDeclaration GetVertexDeclaration(ShaderFX shader) { var d = new VertexDeclaration(); - d.Types = 8598872888530528662; + d.Types = VertexDeclarationTypes.GTAV1; d.Unknown_6h = 0; switch (shader.Name) diff --git a/CodeWalker.Core/Utils/Utils.cs b/CodeWalker.Core/Utils/Utils.cs index 2138fbe..340ee1f 100644 --- a/CodeWalker.Core/Utils/Utils.cs +++ b/CodeWalker.Core/Utils/Utils.cs @@ -128,22 +128,22 @@ namespace CodeWalker } - public static string GetVector2String(Vector2 v) + public static string GetVector2String(Vector2 v, string d = ", ") { var c = CultureInfo.InvariantCulture; - return v.X.ToString(c) + ", " + v.Y.ToString(c); + return v.X.ToString(c) + d + v.Y.ToString(c); } public static string GetVector2XmlString(Vector2 v) { var c = CultureInfo.InvariantCulture; return string.Format("x=\"{0}\" y=\"{1}\"", v.X.ToString(c), v.Y.ToString(c)); } - public static string GetVector3String(Vector3 v) + public static string GetVector3String(Vector3 v, string d = ", ") { var c = CultureInfo.InvariantCulture; - return v.X.ToString(c) + ", " + v.Y.ToString(c) + ", " + v.Z.ToString(c); + return v.X.ToString(c) + d + v.Y.ToString(c) + d + v.Z.ToString(c); } - public static string GetVector3String(Vector3 v, string format) + public static string GetVector3StringFormat(Vector3 v, string format) { var c = CultureInfo.InvariantCulture; return v.X.ToString(format, c) + ", " + v.Y.ToString(format, c) + ", " + v.Z.ToString(format, c); @@ -153,6 +153,11 @@ namespace CodeWalker var c = CultureInfo.InvariantCulture; return string.Format("x=\"{0}\" y=\"{1}\" z=\"{2}\"", v.X.ToString(c), v.Y.ToString(c), v.Z.ToString(c)); } + public static string GetVector4String(Vector4 v, string d = ", ") + { + var c = CultureInfo.InvariantCulture; + return v.X.ToString(c) + d + v.Y.ToString(c) + d + v.Z.ToString(c) + d + v.W.ToString(c); + } public static string GetVector4XmlString(Vector4 v) { var c = CultureInfo.InvariantCulture; @@ -163,6 +168,23 @@ namespace CodeWalker var c = CultureInfo.InvariantCulture; return string.Format("x=\"{0}\" y=\"{1}\" z=\"{2}\" w=\"{3}\"", q.X.ToString(c), q.Y.ToString(c), q.Z.ToString(c), q.W.ToString(c)); } + public static string GetHalf2String(Half2 v, string d = ", ") + { + var c = CultureInfo.InvariantCulture; + var f = Half.ConvertToFloat(new[] { v.X, v.Y }); + return f[0].ToString(c) + d + f[1].ToString(c); + } + public static string GetHalf4String(Half4 v, string d = ", ") + { + var c = CultureInfo.InvariantCulture; + var f = Half.ConvertToFloat(new[] { v.X, v.Y, v.Z, v.W }); + return f[0].ToString(c) + d + f[1].ToString(c) + d + f[2].ToString(c) + d + f[3].ToString(c); + } + public static string GetColourString(Color v, string d = ", ") + { + var c = CultureInfo.InvariantCulture; + return v.R.ToString(c) + d + v.G.ToString(c) + d + v.B.ToString(c) + d + v.A.ToString(c); + } public static Vector2 ParseVector2String(string s) @@ -179,7 +201,6 @@ namespace CodeWalker } return p; } - public static Vector3 ParseVector3String(string s) { Vector3 p = new Vector3(0.0f); @@ -198,14 +219,6 @@ namespace CodeWalker } return p; } - - - - public static string GetVector4String(Vector4 v) - { - var c = CultureInfo.InvariantCulture; - return v.X.ToString(c) + ", " + v.Y.ToString(c) + ", " + v.Z.ToString(c) + ", " + v.W.ToString(c); - } public static Vector4 ParseVector4String(string s) { Vector4 p = new Vector4(0.0f); diff --git a/CodeWalker.Core/Utils/Xml.cs b/CodeWalker.Core/Utils/Xml.cs index 0b1d6c8..566c4cf 100644 --- a/CodeWalker.Core/Utils/Xml.cs +++ b/CodeWalker.Core/Utils/Xml.cs @@ -222,6 +222,30 @@ namespace CodeWalker return GetRawByteArray(cnode); } + public static ushort[] GetRawUshortArray(XmlNode node) + { + if (node == null) return new ushort[0]; + var data = new List(); + var split = Regex.Split(node.InnerText, @"[\s\r\n\t]"); + for (int i = 0; i < split.Length; i++) + { + if (!string.IsNullOrEmpty(split[i])) + { + var str = split[i]; + if (string.IsNullOrEmpty(str)) continue; + var val = (ushort)0; + ushort.TryParse(str, out val); + data.Add(val); + } + } + return data.ToArray(); + } + public static ushort[] GetChildRawUshortArray(XmlNode node, string name) + { + var cnode = node.SelectSingleNode(name); + return GetRawUshortArray(cnode); + } + public static uint[] GetRawUintArray(XmlNode node) { if (node == null) return new uint[0]; diff --git a/Rendering/Shaders/BasicShader.cs b/Rendering/Shaders/BasicShader.cs index ff45b59..974a580 100644 --- a/Rendering/Shaders/BasicShader.cs +++ b/Rendering/Shaders/BasicShader.cs @@ -256,7 +256,7 @@ namespace CodeWalker.Rendering //supported layouts - requires Position, Normal, Colour, Texcoord layouts.Add(VertexType.Default, new InputLayout(device, vspnctbytes, VertexTypeGTAV.GetLayout(VertexType.Default))); - layouts.Add(VertexType.PNCH2, new InputLayout(device, vspnctbytes, VertexTypeGTAV.GetLayout(VertexType.PNCH2, VertexDeclarationTypes.Types3)));//TODO? + layouts.Add(VertexType.PNCH2, new InputLayout(device, vspnctbytes, VertexTypeGTAV.GetLayout(VertexType.PNCH2, VertexDeclarationTypes.GTAV3)));//TODO? layouts.Add(VertexType.PNCTT, new InputLayout(device, vspncttbytes, VertexTypeGTAV.GetLayout(VertexType.PNCTT))); layouts.Add(VertexType.PNCTTT, new InputLayout(device, vspnctttbytes, VertexTypeGTAV.GetLayout(VertexType.PNCTTT))); layouts.Add(VertexType.PNCCT, new InputLayout(device, vspncctbytes, VertexTypeGTAV.GetLayout(VertexType.PNCCT))); @@ -267,7 +267,7 @@ namespace CodeWalker.Rendering //normalmap layouts - requires Position, Normal, Colour, Texcoord, Tangent (X) layouts.Add(VertexType.DefaultEx, new InputLayout(device, vspnctxbytes, VertexTypeGTAV.GetLayout(VertexType.DefaultEx))); - layouts.Add(VertexType.PCCH2H4, new InputLayout(device, vspnctxbytes, VertexTypeGTAV.GetLayout(VertexType.PCCH2H4, VertexDeclarationTypes.Types2))); + layouts.Add(VertexType.PCCH2H4, new InputLayout(device, vspnctxbytes, VertexTypeGTAV.GetLayout(VertexType.PCCH2H4, VertexDeclarationTypes.GTAV2))); layouts.Add(VertexType.PNCCTX, new InputLayout(device, vspncctxbytes, VertexTypeGTAV.GetLayout(VertexType.PNCCTX))); layouts.Add(VertexType.PNCTTX, new InputLayout(device, vspncttxbytes, VertexTypeGTAV.GetLayout(VertexType.PNCTTX))); layouts.Add(VertexType.PNCCTTX, new InputLayout(device, vspnccttxbytes, VertexTypeGTAV.GetLayout(VertexType.PNCCTTX))); diff --git a/Rendering/Shaders/ShadowShader.cs b/Rendering/Shaders/ShadowShader.cs index 8e11eb4..9d526cb 100644 --- a/Rendering/Shaders/ShadowShader.cs +++ b/Rendering/Shaders/ShadowShader.cs @@ -113,8 +113,8 @@ namespace CodeWalker.Rendering layouts.Add(VertexType.PNCCTTTX, new InputLayout(device, vsbytes, VertexTypeGTAV.GetLayout(VertexType.PNCCTTTX))); layouts.Add(VertexType.PNCCTT, new InputLayout(device, vsbytes, VertexTypeGTAV.GetLayout(VertexType.PNCCTT))); layouts.Add(VertexType.PNCCTX, new InputLayout(device, vsbytes, VertexTypeGTAV.GetLayout(VertexType.PNCCTX))); - layouts.Add(VertexType.PNCH2, new InputLayout(device, vsbytes, VertexTypeGTAV.GetLayout(VertexType.PNCH2, VertexDeclarationTypes.Types3))); - layouts.Add(VertexType.PCCH2H4, new InputLayout(device, vsbytes, VertexTypeGTAV.GetLayout(VertexType.PCCH2H4, VertexDeclarationTypes.Types2))); + layouts.Add(VertexType.PNCH2, new InputLayout(device, vsbytes, VertexTypeGTAV.GetLayout(VertexType.PNCH2, VertexDeclarationTypes.GTAV3))); + layouts.Add(VertexType.PCCH2H4, new InputLayout(device, vsbytes, VertexTypeGTAV.GetLayout(VertexType.PCCH2H4, VertexDeclarationTypes.GTAV2))); layouts.Add(VertexType.PNCTT, new InputLayout(device, vsbytes, VertexTypeGTAV.GetLayout(VertexType.PNCTT))); layouts.Add(VertexType.PNCTTT, new InputLayout(device, vsbytes, VertexTypeGTAV.GetLayout(VertexType.PNCTTT))); diff --git a/Rendering/VertexTypes.cs b/Rendering/VertexTypes.cs index 70a17f7..8460107 100644 --- a/Rendering/VertexTypes.cs +++ b/Rendering/VertexTypes.cs @@ -32,45 +32,26 @@ namespace CodeWalker.Rendering "BINORMAL", }; - public static int GetVertexComponentTypeSizeInBytes(VertexComponentType type) - { - switch (type) - { - case VertexComponentType.Nothing: return 0; - case VertexComponentType.Float16Two: return 4; - case VertexComponentType.Float: return 4; - case VertexComponentType.Float16Four: return 8; - case VertexComponentType.Float_unk: return 0; - case VertexComponentType.Float2: return 8; - case VertexComponentType.Float3: return 12; - case VertexComponentType.Float4: return 16; - case VertexComponentType.UByte4: return 4; - case VertexComponentType.Color: return 4; - case VertexComponentType.Dec3N: return 4; - default: return 0; - } - } - public static Format GetDXGIFormat(VertexComponentType type) { switch (type) { case VertexComponentType.Nothing: return Format.Unknown; - case VertexComponentType.Float16Two: return Format.R16G16_Float; + case VertexComponentType.Half2: return Format.R16G16_Float; case VertexComponentType.Float: return Format.R32_Float; - case VertexComponentType.Float16Four: return Format.R16G16B16A16_Float; - case VertexComponentType.Float_unk: return Format.Unknown; + case VertexComponentType.Half4: return Format.R16G16B16A16_Float; + case VertexComponentType.FloatUnk: return Format.Unknown; case VertexComponentType.Float2: return Format.R32G32_Float; case VertexComponentType.Float3: return Format.R32G32B32_Float; case VertexComponentType.Float4: return Format.R32G32B32A32_Float; case VertexComponentType.UByte4: return Format.R8G8B8A8_UInt; - case VertexComponentType.Color: return Format.R8G8B8A8_UNorm; + case VertexComponentType.Colour: return Format.R8G8B8A8_UNorm; case VertexComponentType.Dec3N: return Format.R10G10B10A2_UNorm; default: return Format.Unknown; } } - public static InputElement[] GetLayout(VertexType componentsFlags, VertexDeclarationTypes componentsTypes = VertexDeclarationTypes.Types1) + public static InputElement[] GetLayout(VertexType componentsFlags, VertexDeclarationTypes componentsTypes = VertexDeclarationTypes.GTAV1) { List inputElements = new List(); @@ -87,7 +68,7 @@ namespace CodeWalker.Rendering if (componentType == VertexComponentType.Nothing) continue; // should never hit this - var componentTypeSize = GetVertexComponentTypeSizeInBytes(componentType); + var componentTypeSize = VertexComponentTypes.GetSizeInBytes(componentType); var format = GetDXGIFormat(componentType); if (componentTypeSize == 0 || format == Format.Unknown) continue; diff --git a/WorldForm.cs b/WorldForm.cs index 054a0b4..7d0fce3 100644 --- a/WorldForm.cs +++ b/WorldForm.cs @@ -5609,7 +5609,7 @@ namespace CodeWalker UpdateTimeOfDayLabel(); } - CameraPositionTextBox.Text = FloatUtil.GetVector3String(camera.Position, "0.##"); + CameraPositionTextBox.Text = FloatUtil.GetVector3StringFormat(camera.Position, "0.##"); } private void WorldForm_Load(object sender, EventArgs e)