public override void StreamWriteData(BinaryWriter outstream)
        {
            outstream.Write(this.vert_count);
            outstream.Write(Headers.Count);
            foreach (GeometryHeader head in this.Headers)
            {
                outstream.Write(head.ItemSize);
                outstream.Write((uint)head.ItemType);
            }

            List <Vector3> verts    = this.verts;
            int            vert_pos = 0;
            List <Vector3> normals  = this.normals.ToList();
            int            norm_pos = 0;

            List <GeometryWeightGroups> unknown_15s = this.weight_groups;
            int            unknown_15s_pos          = 0;
            List <Vector3> binormals     = this.binormals;
            int            binormals_pos = 0;
            List <Vector3> tangents      = this.tangents;
            int            tangents_pos  = 0;

            List <byte[]> unknown_data     = this.unknown_item_data;
            int           unknown_data_pos = 0;

            foreach (GeometryHeader head in this.Headers)
            {
                if (head.ItemType == GeometryChannelTypes.POSITION)
                {
                    for (int x = 0; x < this.vert_count; x++)
                    {
                        Vector3 vert = verts[vert_pos];
                        outstream.Write(vert.X);
                        outstream.Write(vert.Y);
                        outstream.Write(vert.Z);
                        vert_pos++;
                    }
                }
                else if (head.ItemType == GeometryChannelTypes.NORMAL)
                {
                    for (int x = 0; x < this.vert_count; x++)
                    {
                        Vector3 norm = normals[norm_pos];
                        outstream.Write(norm.X);
                        outstream.Write(norm.Y);
                        outstream.Write(norm.Z);
                        norm_pos++;
                    }
                }

                else if (head.ItemType == GeometryChannelTypes.COLOR)
                {
                    for (int x = 0; x < this.vert_count; x++)
                    {
                        this.vertex_colors[x].StreamWrite(outstream);
                    }
                }
                else if (head.ItemType == GeometryChannelTypes.BINORMAL)
                {
                    for (int x = 0; x < this.vert_count; x++)
                    {
                        if (this.binormals.Count != this.vert_count)
                        {
                            outstream.Write(0.0f);
                            outstream.Write(0.0f);
                            outstream.Write(0.0f);
                        }
                        else
                        {
                            Vector3 binormal_entry = binormals[x];
                            outstream.Write(binormal_entry.X);
                            outstream.Write(binormal_entry.Y);
                            outstream.Write(binormal_entry.Z);
                            binormals_pos++;
                        }
                    }
                }
                else if (head.ItemType == GeometryChannelTypes.TANGENT)
                {
                    for (int x = 0; x < this.vert_count; x++)
                    {
                        if (this.tangents.Count != this.vert_count)
                        {
                            outstream.Write(0.0f);
                            outstream.Write(0.0f);
                            outstream.Write(0.0f);
                        }
                        else
                        {
                            Vector3 tangent_entry = tangents[x];
                            outstream.Write(tangent_entry.X);
                            outstream.Write(tangent_entry.Y);
                            outstream.Write(tangent_entry.Z);
                            tangents_pos++;
                        }
                    }
                }
                else if (head.ItemType == GeometryChannelTypes.BLENDINDICES)
                {
                    for (int x = 0; x < this.vert_count; x++)
                    {
                        if (this.weight_groups.Count != this.vert_count)
                        {
                            outstream.Write(0.0f);
                            outstream.Write(0.0f);
                        }
                        else
                        {
                            GeometryWeightGroups unknown_15_entry = unknown_15s[x];
                            unknown_15_entry.StreamWrite(outstream);
                            unknown_15s_pos++;
                        }
                    }
                }
                else if (head.ItemType == GeometryChannelTypes.BLENDWEIGHT)
                {
                    if (head.ItemSize == 4)
                    {
                        Log.Default.Warn("Section {0} has four weights", this.HashName.String);
                    }
                    for (int x = 0; x < this.vert_count; x++)
                    {
                        Vector3 weight = this.weights.Count != this.vert_count ? Vector3.UnitX : weights[x];
                        outstream.Write(weight.X);
                        outstream.Write(weight.Y);

                        if (head.ItemSize == 3)
                        {
                            outstream.Write(weight.Z);
                        }
                        else if (head.ItemSize == 4)
                        {
                            outstream.Write(weight.Z);
                            outstream.Write(0.0f);
                        }
                        else if (head.ItemSize != 2)
                        {
                            throw new Exception("Cannot write bad header BLENDWEIGHT s=" + head.ItemSize);
                        }
                    }
                }
                else if (head.ItemType >= GeometryChannelTypes.TEXCOORD0 &&
                         head.ItemType <= GeometryChannelTypes.TEXCOORD7)
                {
                    int idx = head.ItemType - GeometryChannelTypes.TEXCOORD0;
                    for (int x = 0; x < this.vert_count; x++)
                    {
                        Vector2 uv = UVs[idx][x];
                        outstream.Write(uv.X);
                        outstream.Write(-uv.Y);
                    }
                }
                else
                {
                    outstream.Write(unknown_data[unknown_data_pos]);
                    unknown_data_pos++;
                }
            }

            outstream.Write(this.HashName.Hash);

            if (this.remaining_data != null)
            {
                outstream.Write(this.remaining_data);
            }
        }
        public Geometry(BinaryReader instream, SectionHeader section) : this()
        {
            this.SectionId = section.id;
            // Count of everysingle item in headers (Verts, Normals, UVs, UVs for normalmap, Colors, Unknown 20, Unknown 21, etc)
            this.vert_count = instream.ReadUInt32();
            //Count of all headers for items in this section
            uint   header_count = instream.ReadUInt32();
            UInt32 calc_size    = 0;

            for (int x = 0; x < header_count; x++)
            {
                GeometryHeader header = new GeometryHeader();
                header.ItemSize = instream.ReadUInt32();
                header.ItemType = (GeometryChannelTypes)instream.ReadUInt32();
                calc_size      += header.ItemSizeBytes;
                this.Headers.Add(header);
            }

            foreach (GeometryHeader head in this.Headers)
            {
                //Console.WriteLine("Header type: " + head.item_type + " Size: " + head.item_size);
                if (head.ItemType == GeometryChannelTypes.POSITION)
                {
                    verts.Capacity = (int)vert_count + 1;
                    for (int x = 0; x < this.vert_count; x++)
                    {
                        Vector3 vert = new Vector3();
                        vert.X = instream.ReadSingle();
                        vert.Y = instream.ReadSingle();
                        vert.Z = instream.ReadSingle();

                        this.verts.Add(vert);
                    }
                }
                else if (head.ItemType == GeometryChannelTypes.NORMAL)
                {
                    normals.Capacity = (int)vert_count + 1;
                    for (int x = 0; x < this.vert_count; x++)
                    {
                        Vector3 norm = new Vector3();
                        norm.X = instream.ReadSingle();
                        norm.Y = instream.ReadSingle();
                        norm.Z = instream.ReadSingle();
                        this.normals.Add(norm);
                    }
                }
                else if (head.ItemType == GeometryChannelTypes.COLOR0)
                {
                    vertex_colors.Capacity = (int)vert_count + 1;
                    for (int x = 0; x < this.vert_count; x++)
                    {
                        this.vertex_colors.Add(new GeometryColor(instream));
                    }
                }
                //Below is unknown data

                else if (head.ItemType == GeometryChannelTypes.BINORMAL0)
                {
                    binormals.Capacity = (int)vert_count + 1;
                    for (int x = 0; x < this.vert_count; x++)
                    {
                        Vector3 binormal_entry = new Vector3();
                        binormal_entry.X = instream.ReadSingle();
                        binormal_entry.Y = instream.ReadSingle();
                        binormal_entry.Z = instream.ReadSingle();
                        this.binormals.Add(binormal_entry);
                    }
                }
                else if (head.ItemType == GeometryChannelTypes.TANGENT0)
                {
                    tangents.Capacity = (int)vert_count + 1;
                    for (int x = 0; x < this.vert_count; x++)
                    {
                        Vector3 tangent_entry = new Vector3();
                        tangent_entry.X = instream.ReadSingle();
                        tangent_entry.Y = instream.ReadSingle();
                        tangent_entry.Z = instream.ReadSingle();
                        this.tangents.Add(tangent_entry);
                    }
                }

                //Weight Groups
                else if (head.ItemType == GeometryChannelTypes.BLENDINDICES0)
                {
                    weight_groups.Capacity = (int)vert_count + 1;
                    for (int x = 0; x < this.vert_count; x++)
                    {
                        GeometryWeightGroups unknown_15_entry = new GeometryWeightGroups(instream);
                        this.weight_groups.Add(unknown_15_entry);
                    }
                }

                //Weights
                else if (head.ItemType == GeometryChannelTypes.BLENDWEIGHT0)
                {
                    if (head.ItemSize == 4)
                    {
                        Log.Default.Warn("Section {0} has four weights", this.SectionId);
                    }

                    weights.Capacity = (int)vert_count + 1;
                    for (int x = 0; x < this.vert_count; x++)
                    {
                        Vector3 unknown_17_entry = new Vector3();
                        unknown_17_entry.X = instream.ReadSingle();
                        unknown_17_entry.Y = instream.ReadSingle();
                        if (head.ItemSize == 3)
                        {
                            unknown_17_entry.Z = instream.ReadSingle();
                        }
                        else if (head.ItemSize == 4)
                        {
                            unknown_17_entry.Z = instream.ReadSingle();
                            var tmp = instream.ReadSingle();
                            if (tmp != 0)
                            {
                                Log.Default.Warn("Nonzero fourth weight in {0} vtx {1} (is {2})", this.SectionId, x, tmp);
                            }
                        }
                        else if (head.ItemSize != 2)
                        {
                            throw new Exception("Bad BLENDWEIGHT0 item size " + head.ItemSize);
                        }
                        this.weights.Add(unknown_17_entry);
                    }
                }
                else if (head.ItemType >= GeometryChannelTypes.TEXCOORD0 &&
                         head.ItemType <= GeometryChannelTypes.TEXCOORD7)
                {
                    int idx = head.ItemType - GeometryChannelTypes.TEXCOORD0;
                    for (int x = 0; x < vert_count; x++)
                    {
                        // Previously, the Y was only inverted on the TEXCOORD0 channel, and
                        // not on the TEXCOORD1 channel. I assume that was incorrect, TODO check?
                        Vector2 uv = new Vector2 {
                            X = instream.ReadSingle(), Y = -instream.ReadSingle()
                        };
                        UVs[idx].Add(uv);
                    }
                }
                else
                {
                    this.unknown_item_data.Add(
                        instream.ReadBytes((int)(head.ItemSizeBytes * this.vert_count)));
                }
            }

            this.HashName = new HashName(instream.ReadUInt64());

            this.remaining_data = null;
            long sect_end = section.offset + 12 + section.size;

            if (sect_end > instream.BaseStream.Position)
            {
                // If exists, this contains hashed name for this geometry (see hashlist.txt)
                remaining_data = instream.ReadBytes((int)(sect_end - instream.BaseStream.Position));
            }
        }