/// <summary> /// Read a primitive object from a file /// </summary> /// <param name="source">The files contents as a byte array</param> /// <param name="address">The starting address of the primitive</param> /// <param name="indexAttribs">How the indices of the loops are structured</param> public static Poly Read(byte[] source, ref uint address, IndexAttributes indexAttribs) { PushBigEndian(true); PolyType type = (PolyType)source[address]; ushort vtxCount = source.ToUInt16(address + 1); // checking the attributes bool hasFlag(IndexAttributes attrib) => indexAttribs.HasFlag(attrib); // position always exists bool hasCol = hasFlag(IndexAttributes.HasColor); bool hasNrm = hasFlag(IndexAttributes.HasNormal); bool hasUV = hasFlag(IndexAttributes.HasUV); //whether any of the indices use 16 bits instead of 8 bool shortPos = hasFlag(IndexAttributes.Position16BitIndex); bool shortCol = hasFlag(IndexAttributes.Color16BitIndex); bool shortNrm = hasFlag(IndexAttributes.Normal16BitIndex); bool shortUV = hasFlag(IndexAttributes.UV16BitIndex); address += 3; List <Corner> corners = new(); for (ushort i = 0; i < vtxCount; i++) { Corner l = new(); // reading position, which should always exist if (shortPos) { l.PositionIndex = source.ToUInt16(address); address += 2; } else { l.PositionIndex = source[address]; address++; } // reading normals if (hasNrm) { if (shortNrm) { l.NormalIndex = source.ToUInt16(address); address += 2; } else { l.NormalIndex = source[address]; address++; } } // reading colors if (hasCol) { if (shortCol) { l.Color0Index = source.ToUInt16(address); address += 2; } else { l.Color0Index = source[address]; address++; } } // reading uvs if (hasUV) { if (shortUV) { l.UV0Index = source.ToUInt16(address); address += 2; } else { l.UV0Index = source[address]; address++; } } corners.Add(l); } PopEndian(); return(new Poly(type, corners.ToArray())); }
/// <summary> /// Write the contents /// </summary> /// <param name="writer">The output stream</param> /// <param name="indexAttribs">How the indices of the loops are structured</param> public void Write(EndianWriter writer, IndexAttributes indexAttribs) { writer.PushBigEndian(true); writer.Write((byte)Type); writer.Write((ushort)Corners.Length); // checking the attributes bool hasFlag(IndexAttributes attrib) => indexAttribs.HasFlag(attrib); // position always exists bool hasCol = hasFlag(IndexAttributes.HasColor); bool hasNrm = hasFlag(IndexAttributes.HasNormal); bool hasUV = hasFlag(IndexAttributes.HasUV); bool shortPos = hasFlag(IndexAttributes.Position16BitIndex); bool shortCol = hasFlag(IndexAttributes.Color16BitIndex); bool shortNrm = hasFlag(IndexAttributes.Normal16BitIndex); bool shortUV = hasFlag(IndexAttributes.UV16BitIndex); foreach (Corner v in Corners) { // Position should always exist if (shortPos) { writer.Write(v.PositionIndex); } else { writer.Write((byte)v.PositionIndex); } if (hasNrm) { if (shortNrm) { writer.Write(v.NormalIndex); } else { writer.Write((byte)v.NormalIndex); } } if (hasCol) { if (shortCol) { writer.Write(v.Color0Index); } else { writer.Write((byte)v.Color0Index); } } if (hasUV) { if (shortUV) { writer.Write(v.UV0Index); } else { writer.Write((byte)v.UV0Index); } } } writer.PopEndian(); }