예제 #1
0
        private static void UpdateGEOS(BinaryReader br, BinaryWriter bw, int size)
        {
            Console.WriteLine("'Fixing' GEOS");

            // write the header and record the chunk size offset
            bw.Write((uint)Chunks.GEOS);
            long offset = bw.BaseStream.Position;

            bw.Write(0);

            long end = br.BaseStream.Position + size;

            while (br.BaseStream.Position < end)
            {
                using (var substream = new SubStream())
                {
                    long sectionEnd = br.BaseStream.Position + br.ReadInt32();
                    substream.Write(0); // inclusive size

                    int  vertexCount = 0;
                    long gndxOffset  = 0;

                    int noOf = 0;
                    if (br.HasTag("VRTX"))
                    {
                        vertexCount             = noOf = br.ReadInt32();
                        br.BaseStream.Position -= 8;
                        substream.Write(br.ReadBytes(8 + 12 * noOf));
                    }

                    if (br.HasTag("NRMS"))
                    {
                        noOf = br.ReadInt32();
                        br.BaseStream.Position -= 8;
                        substream.Write(br.ReadBytes(8 + 12 * noOf));
                    }

                    if (br.HasTag("PTYP"))
                    {
                        noOf = br.ReadInt32();
                        br.BaseStream.Position -= 8;
                        substream.Write(br.ReadBytes(8 + 4 * noOf));
                    }

                    if (br.HasTag("PCNT"))
                    {
                        noOf = br.ReadInt32();
                        br.BaseStream.Position -= 8;
                        substream.Write(br.ReadBytes(8 + 4 * noOf));
                    }

                    if (br.HasTag("PVTX"))
                    {
                        noOf = br.ReadInt32() / 3;
                        br.BaseStream.Position -= 8;
                        substream.Write(br.ReadBytes(8 + 6 * noOf));
                    }

                    if (br.HasTag("GNDX"))
                    {
                        noOf = br.ReadInt32();
                        substream.Write((int)Chunks.GNDX);

                        if (noOf == 0) // this has been moved to the SKIN section
                        {
                            substream.Write(vertexCount);
                            gndxOffset = substream.Position;
                            substream.Write(new byte[vertexCount]);
                        }
                        else
                        {
                            substream.Write(noOf);
                            substream.Write(br.ReadBytes(noOf));
                        }
                    }

                    if (br.HasTag("MTGC"))
                    {
                        noOf = br.ReadInt32();
                        br.BaseStream.Position -= 8;
                        substream.Write(br.ReadBytes(8 + 4 * noOf));
                    }

                    if (br.HasTag("MATS"))
                    {
                        noOf = br.ReadInt32();
                        br.BaseStream.Position -= 8;
                        substream.Write(br.ReadBytes(8 + 4 * noOf));
                    }

                    substream.Write(br.ReadBytes(12));      // MaterialId, SelectionGroup, Unselectable

                    br.BaseStream.Position += 4 + SizeName; // skip LevelOfDetail, FilePath

                    substream.Write(br.ReadBytes(28));      // Bounds

                    noOf = br.ReadInt32();                  // Extents
                    br.BaseStream.Position -= 4;
                    substream.Write(br.ReadBytes(4 + noOf * 28));

                    if (br.HasTag("TANG"))
                    {
                        noOf = br.ReadInt32();
                        br.BaseStream.Position += noOf * 16; // skip Tangents
                    }

                    if (br.HasTag("SKIN"))
                    {
                        noOf = br.ReadInt32();

                        // rebuild the GNDX from the SKIN section
                        // this is (uint32 index, uint32 weight)
                        // casting the indicies to bytes is "enough" for this
                        if (gndxOffset > 0)
                        {
                            byte[] buffer = br.ReadBytes(noOf);
                            substream.Position = gndxOffset;
                            for (int i = 0; i < buffer.Length; i += 8)
                            {
                                substream.WriteByte(buffer[i]);
                            }
                            substream.Position = substream.Length;
                        }
                        else
                        {
                            br.BaseStream.Position += noOf;
                        }
                    }

                    // copy anything else the chunk contains
                    int remaining = (int)(sectionEnd - br.BaseStream.Position);
                    if (remaining > 0)
                    {
                        substream.Write(br.ReadBytes(remaining));
                    }

                    // update the inclusive size and write to the filestream
                    substream.Position = 0;
                    substream.Write((int)substream.Length);
                    substream.WriteTo(bw.BaseStream);
                }
            }

            // update the chunk size
            bw.BaseStream.Position = offset;
            bw.Write((int)(bw.BaseStream.Length - offset - 4));
            bw.BaseStream.Position = bw.BaseStream.Length;
        }