void IBinarySerializable.Read(EndianBinaryReader reader, object context) { NodeIndex = ( short )context; var positionsPacket = reader.ReadObject <VifPacket>(); VifValidationHelper.Ensure(positionsPacket, null, true, false, null, VifUnpackElementFormat.Float, 4); Positions = positionsPacket.Vector4Array; // @NOTE(TGE): Not a single mesh type 7 mesh has the normals flag not set so I'm not sure if the flag is checked for. var normalsPacket = reader.ReadObject <VifPacket>(); VifValidationHelper.Ensure(normalsPacket, null, true, false, VertexCount, VifUnpackElementFormat.Float, 3); Normals = normalsPacket.Vector3Array; var cmdTag = reader.ReadObject <VifCode>(); if (cmdTag.Command == VifCommand.ActMicro) { VifValidationHelper.Ensure(cmdTag, 0x14, 0, VifCommand.ActMicro); } else if (cmdTag.Command != VifCommand.CntMicro) { throw new InvalidDataException("Expected activate or execute microprogram vif command"); } }
void IBinarySerializable.Read(EndianBinaryReader reader, object context) { var flags = ( MeshFlags )context; var headerPacket = reader.ReadObject <VifPacket>(); VifValidationHelper.Ensure(headerPacket, 0xFF, true, false, 1, VifUnpackElementFormat.Short, 2); var vertexCount = headerPacket.Int16Arrays[0][0]; if (headerPacket.Int16Arrays[0][1] != 0) { throw new InvalidDataException("Header packet second short is not 0"); } var positionsPacket = reader.ReadObject <VifPacket>(); VifValidationHelper.Ensure(positionsPacket, 0, true, false, vertexCount, VifUnpackElementFormat.Float, 3); Positions = positionsPacket.Vector3Array; var normalsPacket = reader.ReadObject <VifPacket>(); VifValidationHelper.Ensure(normalsPacket, 0x18, true, false, vertexCount, VifUnpackElementFormat.Float, 3); Normals = normalsPacket.Vector3Array; var texCoordPacket = reader.ReadObject <VifPacket>(); VifValidationHelper.Ensure(texCoordPacket, 0x30, true, false, vertexCount, VifUnpackElementFormat.Float, 2); TexCoords = texCoordPacket.Vector2Array; var activateTag = reader.ReadObject <VifCode>(); VifValidationHelper.Ensure(activateTag, 0x16, 0, VifCommand.ActMicro); var flushTag = reader.ReadObject <VifCode>(); VifValidationHelper.Ensure(flushTag, 0, 0, VifCommand.FlushEnd); reader.Align(16); }
void IBinarySerializable.Read(EndianBinaryReader reader, object context) { (short[] usedNodeIds, MeshFlags flags) = ((short[], MeshFlags))context; var headerPacket = reader.ReadObject <VifPacket>(); VifValidationHelper.Ensure(headerPacket, 0xFF, true, false, 1, VifUnpackElementFormat.Short, 2); var usedNodeCount = headerPacket.Int16Arrays[0][0]; var vertexCount = headerPacket.Int16Arrays[0][1]; if (usedNodeCount + 1 != usedNodeIds.Length) { throw new InvalidDataException("Used node count + 1 is not equal to the number of used node ids."); } foreach (short nodeId in usedNodeIds) { NodeBatches.Add(reader.ReadObject <MeshType7NodeBatch>(nodeId)); } // @NOTE(TGE): Not a single mesh type 7 mesh does not have this flag set so I don't know if it should be checked for. var texCoordsPacket = reader.ReadObject <VifPacket>(); VifValidationHelper.Ensure(texCoordsPacket, null, true, false, vertexCount, VifUnpackElementFormat.Float, 2); TexCoords = texCoordsPacket.Vector2Array; var texCoordsKickTag = reader.ReadObject <VifCode>(); VifValidationHelper.Ensure(texCoordsKickTag, 0, 0, VifCommand.CntMicro); var flushTag = reader.ReadObject <VifCode>(); VifValidationHelper.Ensure(flushTag, 0, 0, VifCommand.FlushEnd); reader.Align(16); }
void IBinarySerializable.Read(EndianBinaryReader reader, object context) { var ctx = ( IOContext )context; NodeIndex = ctx.NodeIndex; // Read header var headerPacket = reader.ReadObject <VifPacket>(); VifValidationHelper.Ensure(headerPacket, 0, true, true, 1, VifUnpackElementFormat.Short, 4); var triangleCount = headerPacket.Int16Arrays[0][0]; var vertexCount = headerPacket.Int16Arrays[0][1]; var flags = Flags = ( MeshFlags )(( ushort )headerPacket.Int16Arrays[0][2] | ( ushort )headerPacket.Int16Arrays[0][3] << 16); if (ctx.IsLastBatch) { // Read triangles var indicesPacket = reader.ReadObject <VifPacket>(); VifValidationHelper.Ensure(indicesPacket, 1, true, true, triangleCount, VifUnpackElementFormat.Byte, 4); ctx.Triangles = indicesPacket.SByteArrays.Select(x => { if (x[3] != 0) { throw new InvalidDataException(); } return(new Triangle(( byte )x[0], ( byte )x[1], ( byte )x[2])); }).ToArray(); } var positionsPacket = reader.ReadObject <VifPacket>(); VifValidationHelper.Ensure(positionsPacket, !ctx.IsLastBatch ? 1 : ( int? )null, true, true, vertexCount, VifUnpackElementFormat.Float, 4); Positions = positionsPacket.Vector4Array; // Read normals if (flags.HasFlag(MeshFlags.Normal)) { var normalsPacket = reader.ReadObject <VifPacket>(); VifValidationHelper.Ensure(normalsPacket, null, true, true, vertexCount, VifUnpackElementFormat.Float, 3); Normals = normalsPacket.Vector3Array; } if (ctx.IsLastBatch) { if (flags.HasFlag(MeshFlags.TexCoord)) { var texCoordsPacket = reader.ReadObject <VifPacket>(); // Read texture coords if (!flags.HasFlag(MeshFlags.TexCoord2)) { VifValidationHelper.Ensure(texCoordsPacket, null, true, true, vertexCount, VifUnpackElementFormat.Float, 2); ctx.TexCoords = texCoordsPacket.Vector2Array; } else { VifValidationHelper.Ensure(texCoordsPacket, null, true, true, vertexCount, VifUnpackElementFormat.Float, 4); ctx.TexCoords = texCoordsPacket.Vector4Array.Select(x => new Vector2(x.X, x.Y)).ToArray(); ctx.TexCoords2 = texCoordsPacket.Vector4Array.Select(x => new Vector2(x.Z, x.W)).ToArray(); } } if (flags.HasFlag(MeshFlags.Color)) { // Read colors var colorsPacket = reader.ReadObject <VifPacket>(); VifValidationHelper.Ensure(colorsPacket, null, true, true, vertexCount, VifUnpackElementFormat.Byte, 4); ctx.Colors = colorsPacket.SByteArrays.Select(x => new Color(( byte )x[0], ( byte )x[1], ( byte )x[2], ( byte )x[3])) .ToArray(); } } // Read activate command var activateCode = reader.ReadObject <VifCode>(); VifValidationHelper.ValidateActivateMicro(activateCode); // Not sure if this makes any difference yet RenderMode = activateCode.Immediate == 0x0C ? MeshBatchRenderMode.Mode1 : MeshBatchRenderMode.Mode2; Debug.Assert(Flags == flags); }