/// <summary> /// Read a primitive object from a file /// </summary> /// <param name="file">The files contents as a byte array</param> /// <param name="address">The starting address of the primitive</param> /// <param name="indexFlags">How the indices of the loops are structured</param> public GCPrimitive(byte[] file, int address, GCIndexAttributeFlags indexFlags, out int end) { primitiveType = (GCPrimitiveType)file[address]; bool wasBigEndian = ByteConverter.BigEndian; ByteConverter.BigEndian = true; ushort vtxCount = ByteConverter.ToUInt16(file, address + 1); // checking the flags bool hasFlag(GCIndexAttributeFlags flag) { return(indexFlags.HasFlag(flag)); } // position always exists bool has_color = hasFlag(GCIndexAttributeFlags.HasColor); bool has_normal = hasFlag(GCIndexAttributeFlags.HasNormal); bool has_uv = hasFlag(GCIndexAttributeFlags.HasUV); //whether any of the indices use 16 bits instead of 8 bool pos16bit = hasFlag(GCIndexAttributeFlags.Position16BitIndex); bool col16bit = hasFlag(GCIndexAttributeFlags.Color16BitIndex); bool nrm16bit = hasFlag(GCIndexAttributeFlags.Normal16BitIndex); bool uv16bit = hasFlag(GCIndexAttributeFlags.UV16BitIndex); int tmpaddr = address + 3; loops = new List <Loop>(); for (ushort i = 0; i < vtxCount; i++) { Loop l = new Loop(); // reading position, which should always exist if (pos16bit) { l.PositionIndex = ByteConverter.ToUInt16(file, tmpaddr); tmpaddr += 2; } else { l.PositionIndex = file[tmpaddr]; tmpaddr++; } // reading normals if (has_normal) { if (nrm16bit) { l.NormalIndex = ByteConverter.ToUInt16(file, tmpaddr); tmpaddr += 2; } else { l.NormalIndex = file[tmpaddr]; tmpaddr++; } } // reading colors if (has_color) { if (col16bit) { l.Color0Index = ByteConverter.ToUInt16(file, tmpaddr); tmpaddr += 2; } else { l.Color0Index = file[tmpaddr]; tmpaddr++; } } // reading uvs if (has_uv) { if (uv16bit) { l.UV0Index = ByteConverter.ToUInt16(file, tmpaddr); tmpaddr += 2; } else { l.UV0Index = file[tmpaddr]; tmpaddr++; } } loops.Add(l); } end = tmpaddr; ByteConverter.BigEndian = wasBigEndian; }
/// <summary> /// Create a new empty Primitive /// </summary> /// <param name="type">The type of primitive</param> public GCPrimitive(GCPrimitiveType type) { primitiveType = type; loops = new List <Loop>(); }