public ChunkAttach(byte[] file, int address, uint imageBase, Dictionary <int, string> labels) : this() { if (labels.ContainsKey(address)) { Name = labels[address]; } else { Name = "attach_" + address.ToString("X8"); } ChunkType ctype; int tmpaddr = ByteConverter.ToInt32(file, address); if (tmpaddr != 0) { tmpaddr = (int)unchecked ((uint)tmpaddr - imageBase); Vertex = new List <VertexChunk>(); if (labels.ContainsKey(tmpaddr)) { VertexName = labels[tmpaddr]; } else { VertexName = "vertex_" + tmpaddr.ToString("X8"); } ctype = (ChunkType)(ByteConverter.ToUInt32(file, tmpaddr) & 0xFF); while (ctype != ChunkType.End) { VertexChunk chunk = new VertexChunk(file, tmpaddr); Vertex.Add(chunk); tmpaddr += (chunk.Size * 4) + 4; ctype = (ChunkType)(ByteConverter.ToUInt32(file, tmpaddr) & 0xFF); } } tmpaddr = ByteConverter.ToInt32(file, address + 4); if (tmpaddr != 0) { tmpaddr = (int)unchecked ((uint)tmpaddr - imageBase); Poly = new List <PolyChunk>(); if (labels.ContainsKey(tmpaddr)) { PolyName = labels[tmpaddr]; } else { PolyName = "poly_" + tmpaddr.ToString("X8"); } PolyChunk chunk = PolyChunk.Load(file, tmpaddr); while (chunk.Type != ChunkType.End) { //if (chunk.Type != ChunkType.Null) Poly.Add(chunk); tmpaddr += chunk.ByteSize; chunk = PolyChunk.Load(file, tmpaddr); } } Bounds = new BoundingSphere(file, address + 8); }
public VertexChunk Clone() { VertexChunk result = (VertexChunk)MemberwiseClone(); result.Vertices = new List <Vertex>(Vertices.Count); foreach (Vertex item in Vertices) { result.Vertices.Add(item.Clone()); } result.Normals = new List <Vertex>(Normals.Count); foreach (Vertex item in Normals) { result.Normals.Add(item.Clone()); } result.Diffuse = new List <Color>(Diffuse); result.Specular = new List <Color>(Specular); result.UserFlags = new List <uint>(UserFlags); result.NinjaFlags = new List <uint>(NinjaFlags); return(result); }
public static List <VertexChunk> Merge(List <VertexChunk> source) { if (source == null) { return(null); } if (source.Count < 2) { return(source); } var chunks = new Dictionary <ChunkType, List <VertexChunk> >(); foreach (var c in source) { if (!chunks.ContainsKey(c.Type)) { chunks[c.Type] = new List <VertexChunk>(); } chunks[c.Type].Add(c); } var result = new List <VertexChunk>(); foreach (var list in chunks.Values) { var t = list[0].Type; switch (t) { case ChunkType.Vertex_VertexNinjaFlags: case ChunkType.Vertex_VertexNormalNinjaFlags: var weights = new Dictionary <WeightStatus, List <VertexChunk> >(); foreach (var c in list) { if (!weights.ContainsKey(c.WeightStatus)) { weights[c.WeightStatus] = new List <VertexChunk>(); } weights[c.WeightStatus].Add(c); } foreach (var(s, l2) in weights.OrderBy(a => a.Key)) { var r = new VertexChunk(t) { WeightStatus = s, IndexOffset = l2.Min(a => a.IndexOffset) }; foreach (var c in l2) { r.Vertices.AddRange(c.Vertices); if (c.Normals?.Count > 0) { r.Normals.AddRange(c.Normals); } if (c.IndexOffset == r.IndexOffset) { r.NinjaFlags.AddRange(c.NinjaFlags); } else { for (int i = 0; i < c.Vertices.Count; i++) { int ind = (int)c.NinjaFlags[i] & 0xFFFF; ind += c.IndexOffset - r.IndexOffset; r.NinjaFlags.Add((c.NinjaFlags[i] & 0xFFFF0000) | (uint)ind); } } } result.Add(r); } break; default: list.Sort((a, b) => a.IndexOffset.CompareTo(b.IndexOffset)); var r2 = new VertexChunk(t) { IndexOffset = list[0].IndexOffset }; foreach (var c in list) { if (c.IndexOffset != r2.IndexOffset + r2.VertexCount) { result.Add(r2); r2 = c; } else { r2.Vertices.AddRange(c.Vertices); if (c.Normals?.Count > 0) { r2.Normals.AddRange(c.Normals); } if (c.Diffuse?.Count > 0) { r2.Diffuse.AddRange(c.Diffuse); } if (c.Specular?.Count > 0) { r2.Specular.AddRange(c.Specular); } if (c.UserFlags?.Count > 0) { r2.UserFlags.AddRange(c.UserFlags); } } } result.Add(r2); break; } } return(result); }
public byte[] GetBytes() { VertexChunk next = null; int vertlimit; int vertcount = Vertices.Count; switch (Type) { case ChunkType.Vertex_VertexSH: vertlimit = 65535 / 4; if (Vertices.Count > vertlimit) { next = new VertexChunk(Type) { Vertices = Vertices.Skip(vertlimit).ToList() }; vertcount = vertlimit; } break; case ChunkType.Vertex_VertexNormalSH: vertlimit = 65535 / 8; if (Vertices.Count > vertlimit) { next = new VertexChunk(Type) { Vertices = Vertices.Skip(vertlimit).ToList(), Normals = Normals.Skip(vertlimit).ToList() }; vertcount = vertlimit; } break; case ChunkType.Vertex_Vertex: vertlimit = 65535 / 3; if (Vertices.Count > vertlimit) { next = new VertexChunk(Type) { Vertices = Vertices.Skip(vertlimit).ToList() }; vertcount = vertlimit; } break; case ChunkType.Vertex_VertexDiffuse8: vertlimit = 65535 / 4; if (Vertices.Count > vertlimit) { next = new VertexChunk(Type) { Vertices = Vertices.Skip(vertlimit).ToList(), Diffuse = Diffuse.Skip(vertlimit).ToList() }; vertcount = vertlimit; } break; case ChunkType.Vertex_VertexUserFlags: vertlimit = 65535 / 4; if (Vertices.Count > vertlimit) { next = new VertexChunk(Type) { Vertices = Vertices.Skip(vertlimit).ToList(), UserFlags = UserFlags.Skip(vertlimit).ToList() }; vertcount = vertlimit; } break; case ChunkType.Vertex_VertexNinjaFlags: vertlimit = 65535 / 4; if (Vertices.Count > vertlimit) { next = new VertexChunk(Type) { Vertices = Vertices.Skip(vertlimit).ToList(), NinjaFlags = NinjaFlags.Skip(vertlimit).ToList() }; vertcount = vertlimit; } break; case ChunkType.Vertex_VertexDiffuseSpecular5: case ChunkType.Vertex_VertexDiffuseSpecular4: vertlimit = 65535 / 4; if (Vertices.Count > vertlimit) { next = new VertexChunk(Type) { Vertices = Vertices.Skip(vertlimit).ToList(), Diffuse = Diffuse.Skip(vertlimit).ToList(), Specular = Specular.Skip(vertlimit).ToList() }; vertcount = vertlimit; } break; case ChunkType.Vertex_VertexNormal: vertlimit = 65535 / 6; if (Vertices.Count > vertlimit) { next = new VertexChunk(Type) { Vertices = Vertices.Skip(vertlimit).ToList(), Normals = Normals.Skip(vertlimit).ToList() }; vertcount = vertlimit; } break; case ChunkType.Vertex_VertexNormalDiffuse8: vertlimit = 65535 / 7; if (Vertices.Count > vertlimit) { next = new VertexChunk(Type) { Vertices = Vertices.Skip(vertlimit).ToList(), Normals = Normals.Skip(vertlimit).ToList(), Diffuse = Diffuse.Skip(vertlimit).ToList() }; vertcount = vertlimit; } break; case ChunkType.Vertex_VertexNormalUserFlags: vertlimit = 65535 / 7; if (Vertices.Count > vertlimit) { next = new VertexChunk(Type) { Vertices = Vertices.Skip(vertlimit).ToList(), Normals = Normals.Skip(vertlimit).ToList(), UserFlags = UserFlags.Skip(vertlimit).ToList() }; vertcount = vertlimit; } break; case ChunkType.Vertex_VertexNormalNinjaFlags: vertlimit = 65535 / 7; if (Vertices.Count > vertlimit) { next = new VertexChunk(Type) { Vertices = Vertices.Skip(vertlimit).ToList(), Normals = Normals.Skip(vertlimit).ToList(), NinjaFlags = NinjaFlags.Skip(vertlimit).ToList() }; vertcount = vertlimit; } break; case ChunkType.Vertex_VertexNormalDiffuseSpecular5: case ChunkType.Vertex_VertexNormalDiffuseSpecular4: vertlimit = 65535 / 7; if (Vertices.Count > vertlimit) { next = new VertexChunk(Type) { Vertices = Vertices.Skip(vertlimit).ToList(), Normals = Normals.Skip(vertlimit).ToList(), Diffuse = Diffuse.Skip(vertlimit).ToList(), Specular = Specular.Skip(vertlimit).ToList() }; vertcount = vertlimit; } break; case ChunkType.End: break; default: throw new NotSupportedException("Unsupported chunk type " + Type + "."); } SetVertCount(vertcount); switch (Type) { case ChunkType.Vertex_Vertex: Size = (ushort)(vertcount * 3 + 1); break; case ChunkType.Vertex_VertexSH: case ChunkType.Vertex_VertexDiffuse8: case ChunkType.Vertex_VertexUserFlags: case ChunkType.Vertex_VertexNinjaFlags: case ChunkType.Vertex_VertexDiffuseSpecular5: case ChunkType.Vertex_VertexDiffuseSpecular4: Size = (ushort)(vertcount * 4 + 1); break; case ChunkType.Vertex_VertexNormal: Size = (ushort)(vertcount * 6 + 1); break; case ChunkType.Vertex_VertexNormalDiffuse8: case ChunkType.Vertex_VertexNormalUserFlags: case ChunkType.Vertex_VertexNormalNinjaFlags: case ChunkType.Vertex_VertexNormalDiffuseSpecular5: case ChunkType.Vertex_VertexNormalDiffuseSpecular4: Size = (ushort)(vertcount * 7 + 1); break; case ChunkType.Vertex_VertexNormalSH: Size = (ushort)(vertcount * 8 + 1); break; } List <byte> result = new List <byte>((Size * 4) + 4); result.AddRange(ByteConverter.GetBytes(Header1)); result.AddRange(ByteConverter.GetBytes(Header2)); for (int i = 0; i < vertcount; i++) { switch (Type) { case ChunkType.Vertex_VertexSH: result.AddRange(Vertices[i].GetBytes()); result.AddRange(ByteConverter.GetBytes(1.0f)); break; case ChunkType.Vertex_VertexNormalSH: result.AddRange(Vertices[i].GetBytes()); result.AddRange(ByteConverter.GetBytes(1.0f)); result.AddRange(Normals[i].GetBytes()); result.AddRange(ByteConverter.GetBytes(1.0f)); break; case ChunkType.Vertex_Vertex: result.AddRange(Vertices[i].GetBytes()); break; case ChunkType.Vertex_VertexDiffuse8: result.AddRange(Vertices[i].GetBytes()); result.AddRange(VColor.GetBytes(Diffuse[i], ColorType.ARGB8888_32)); break; case ChunkType.Vertex_VertexUserFlags: result.AddRange(Vertices[i].GetBytes()); result.AddRange(ByteConverter.GetBytes(UserFlags[i])); break; case ChunkType.Vertex_VertexNinjaFlags: result.AddRange(Vertices[i].GetBytes()); result.AddRange(ByteConverter.GetBytes(NinjaFlags[i])); break; case ChunkType.Vertex_VertexDiffuseSpecular5: result.AddRange(Vertices[i].GetBytes()); result.AddRange(ByteConverter.GetBytes( ByteConverter.ToUInt16(VColor.GetBytes(Diffuse[i], ColorType.RGB565), 0) | (ByteConverter.ToUInt16(VColor.GetBytes(Specular[i], ColorType.RGB565), 0) << 16))); break; case ChunkType.Vertex_VertexDiffuseSpecular4: result.AddRange(Vertices[i].GetBytes()); result.AddRange(ByteConverter.GetBytes( ByteConverter.ToUInt16(VColor.GetBytes(Diffuse[i], ColorType.ARGB4444), 0) | (ByteConverter.ToUInt16(VColor.GetBytes(Specular[i], ColorType.RGB565), 0) << 16))); break; case ChunkType.Vertex_VertexNormal: result.AddRange(Vertices[i].GetBytes()); result.AddRange(Normals[i].GetBytes()); break; case ChunkType.Vertex_VertexNormalDiffuse8: result.AddRange(Vertices[i].GetBytes()); result.AddRange(Normals[i].GetBytes()); result.AddRange(VColor.GetBytes(Diffuse[i], ColorType.ARGB8888_32)); break; case ChunkType.Vertex_VertexNormalUserFlags: result.AddRange(Vertices[i].GetBytes()); result.AddRange(Normals[i].GetBytes()); result.AddRange(ByteConverter.GetBytes(UserFlags[i])); break; case ChunkType.Vertex_VertexNormalNinjaFlags: result.AddRange(Vertices[i].GetBytes()); result.AddRange(Normals[i].GetBytes()); result.AddRange(ByteConverter.GetBytes(NinjaFlags[i])); break; case ChunkType.Vertex_VertexNormalDiffuseSpecular5: result.AddRange(Vertices[i].GetBytes()); result.AddRange(Normals[i].GetBytes()); result.AddRange(ByteConverter.GetBytes( ByteConverter.ToUInt16(VColor.GetBytes(Diffuse[i], ColorType.RGB565), 0) | (ByteConverter.ToUInt16(VColor.GetBytes(Specular[i], ColorType.RGB565), 0) << 16))); break; case ChunkType.Vertex_VertexNormalDiffuseSpecular4: result.AddRange(Vertices[i].GetBytes()); result.AddRange(Normals[i].GetBytes()); result.AddRange(ByteConverter.GetBytes( ByteConverter.ToUInt16(VColor.GetBytes(Diffuse[i], ColorType.ARGB4444), 0) | (ByteConverter.ToUInt16(VColor.GetBytes(Specular[i], ColorType.RGB565), 0) << 16))); break; } } if (next != null) { result.AddRange(next.GetBytes()); } return(result.ToArray()); }