Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        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());
        }