internal static W3dTimeCodedAnimationChannel Parse(BinaryReader reader, W3dParseContext context) { return(ParseChunk(reader, context, header => { var result = new W3dTimeCodedAnimationChannel { NumTimeCodes = reader.ReadUInt32(), Pivot = reader.ReadUInt16(), VectorLength = reader.ReadByte(), ChannelType = reader.ReadByteAsEnum <W3dAnimationChannelType>() }; W3dAnimationChannel.ValidateChannelDataSize(result.ChannelType, result.VectorLength); var data = new W3dTimeCodedDatum[result.NumTimeCodes]; for (var i = 0; i < result.NumTimeCodes; i++) { data[i] = W3dTimeCodedDatum.Parse(reader, result.ChannelType); } result.Data = data; return result; })); }
internal static W3dRgbaList Parse(BinaryReader reader, W3dParseContext context, W3dChunkType chunkType) { var result = ParseList(reader, context, W3dRgba.Parse); result._chunkType = chunkType; return(result); }
internal static W3dHierarchyDef Parse(BinaryReader reader, W3dParseContext context) { return(ParseChunk(reader, context, header => { var result = new W3dHierarchyDef(); ParseChunks(reader, context.CurrentEndPosition, chunkType => { switch (chunkType) { case W3dChunkType.W3D_CHUNK_HIERARCHY_HEADER: result.Header = W3dHierarchy.Parse(reader, context); break; case W3dChunkType.W3D_CHUNK_PIVOTS: result.Pivots = W3dPivots.Parse(reader, context); break; case W3dChunkType.W3D_CHUNK_PIVOT_FIXUPS: result.PivotFixups = W3dPivotFixups.Parse(reader, context); break; default: throw CreateUnknownChunkException(chunkType); } }); return result; })); }
internal static W3dVector3List Parse(BinaryReader reader, W3dParseContext context, W3dChunkType chunkType) { var result = ParseList(reader, context, r => r.ReadVector3()); result._chunkType = chunkType; return(result); }
internal static W3dTexture Parse(BinaryReader reader, W3dParseContext context) { return(ParseChunk(reader, context, header => { var result = new W3dTexture(); ParseChunks(reader, context.CurrentEndPosition, chunkType => { switch (chunkType) { case W3dChunkType.W3D_CHUNK_TEXTURE_NAME: result.Name = W3dTextureName.Parse(reader, context); break; case W3dChunkType.W3D_CHUNK_TEXTURE_INFO: result.TextureInfo = W3dTextureInfo.Parse(reader, context); break; default: throw CreateUnknownChunkException(chunkType); } }); return result; })); }
internal static W3dHLod Parse(BinaryReader reader, W3dParseContext context) { return(ParseChunk(reader, context, header => { var result = new W3dHLod(); ParseChunks(reader, context.CurrentEndPosition, chunkType => { switch (chunkType) { case W3dChunkType.W3D_CHUNK_HLOD_HEADER: result.Header = W3dHLodHeader.Parse(reader, context); break; case W3dChunkType.W3D_CHUNK_HLOD_LOD_ARRAY: result.Lods.Add(W3dHLodArray.Parse(reader, context)); break; case W3dChunkType.W3D_CHUNK_HLOD_AGGREGATE_ARRAY: result.Aggregate = W3dHLodAggregateArray.Parse(reader, context); break; default: throw CreateUnknownChunkException(chunkType); } }); return result; })); }
internal static TDerived Parse(BinaryReader reader, W3dParseContext context) { return(ParseChunk(reader, context, header => { var result = new TDerived(); ParseChunks(reader, context.CurrentEndPosition, chunkType => { switch (chunkType) { case W3dChunkType.W3D_CHUNK_HLOD_SUB_OBJECT_ARRAY_HEADER: result.Header = W3dHLodArrayHeader.Parse(reader, context); break; case W3dChunkType.W3D_CHUNK_HLOD_SUB_OBJECT: result.SubObjects.Add(W3dHLodSubObject.Parse(reader, context)); break; default: throw CreateUnknownChunkException(chunkType); } }); return result; })); }
internal static W3dAnimationChannel Parse(BinaryReader reader, W3dParseContext context) { return(ParseChunk(reader, context, header => { var startPosition = reader.BaseStream.Position; var result = new W3dAnimationChannel { FirstFrame = reader.ReadUInt16(), LastFrame = reader.ReadUInt16(), VectorLength = reader.ReadUInt16(), ChannelType = reader.ReadUInt16AsEnum <W3dAnimationChannelType>(), Pivot = reader.ReadUInt16(), Unknown = reader.ReadUInt16() }; ValidateChannelDataSize(result.ChannelType, result.VectorLength); var numElements = result.LastFrame - result.FirstFrame + 1; var data = new W3dAnimationChannelDatum[numElements]; for (var i = 0; i < numElements; i++) { data[i] = W3dAnimationChannelDatum.Parse(reader, result.ChannelType); } result.Data = data; result.NumPadBytes = (uint)(context.CurrentEndPosition - reader.BaseStream.Position); reader.BaseStream.Seek((int)result.NumPadBytes, SeekOrigin.Current); return result; })); }
internal static W3dShaderMaterial Parse(BinaryReader reader, W3dParseContext context) { return(ParseChunk(reader, context, header => { var result = new W3dShaderMaterial(); ParseChunks(reader, context.CurrentEndPosition, chunkType => { switch (chunkType) { case W3dChunkType.W3D_CHUNK_SHADER_MATERIAL_HEADER: result.Header = W3dShaderMaterialHeader.Parse(reader, context); break; case W3dChunkType.W3D_CHUNK_SHADER_MATERIAL_PROPERTY: result.Properties.Add(W3dShaderMaterialProperty.Parse(reader, context)); break; default: throw CreateUnknownChunkException(chunkType); } }); return result; })); }
internal static W3dTextureStage Parse(BinaryReader reader, W3dParseContext context) { return(ParseChunk(reader, context, header => { var result = new W3dTextureStage(); ParseChunks(reader, context.CurrentEndPosition, chunkType => { switch (chunkType) { case W3dChunkType.W3D_CHUNK_TEXTURE_IDS: result.TextureIds = W3dTextureIds.Parse(reader, context); break; case W3dChunkType.W3D_CHUNK_PER_FACE_TEXCOORD_IDS: result.PerFaceTexCoordIds = new W3dVectorUInt32[header.ChunkSize / W3dVectorUInt32.SizeInBytes]; for (var count = 0; count < result.PerFaceTexCoordIds.Length; count++) { result.PerFaceTexCoordIds[count] = W3dVectorUInt32.Parse(reader); } break; case W3dChunkType.W3D_CHUNK_STAGE_TEXCOORDS: result.TexCoords = W3dVector2List.Parse(reader, context, chunkType); break; default: throw CreateUnknownChunkException(chunkType); } }); return result; })); }
internal static W3dAdaptiveDeltaAnimationChannel Parse(BinaryReader reader, W3dParseContext context, W3dAdaptiveDeltaBitCount bitCount) { return(ParseChunk(reader, context, header => { var result = new W3dAdaptiveDeltaAnimationChannel { NumTimeCodes = reader.ReadUInt32(), Pivot = reader.ReadUInt16(), VectorLength = reader.ReadByte(), ChannelType = reader.ReadByteAsEnum <W3dAnimationChannelType>(), Scale = reader.ReadSingle(), }; W3dAnimationChannel.ValidateChannelDataSize(result.ChannelType, result.VectorLength); result.Data = W3dAdaptiveDeltaData.Parse( reader, result.NumTimeCodes, result.ChannelType, result.VectorLength, bitCount); // Skip 3 unknown bytes at chunk end. reader.BaseStream.Seek(3, SeekOrigin.Current); return result; })); }
internal static W3dMeshAabTree Parse(BinaryReader reader, W3dParseContext context) { return(ParseChunk <W3dMeshAabTree>(reader, context, header => { var result = new W3dMeshAabTree(); ParseChunks(reader, context.CurrentEndPosition, chunkType => { switch (chunkType) { case W3dChunkType.W3D_CHUNK_AABTREE_HEADER: result.Header = W3dMeshAabTreeHeader.Parse(reader, context); break; case W3dChunkType.W3D_CHUNK_AABTREE_POLYINDICES: result.PolygonIndices = W3dMeshAabTreePolyIndices.Parse(reader, context); break; case W3dChunkType.W3D_CHUNK_AABTREE_NODES: result.Nodes = W3dMeshAabTreeNodes.Parse(reader, context); break; default: throw CreateUnknownChunkException(chunkType); } }); return result; })); }
internal static W3dVertexMaterial Parse(BinaryReader reader, W3dParseContext context) { return(ParseChunk(reader, context, header => { var result = new W3dVertexMaterial(); ParseChunks(reader, context.CurrentEndPosition, chunkType => { switch (chunkType) { case W3dChunkType.W3D_CHUNK_VERTEX_MATERIAL_NAME: result.Name = W3dVertexMaterialName.Parse(reader, context); break; case W3dChunkType.W3D_CHUNK_VERTEX_MAPPER_ARGS0: result.MapperArgs0 = W3dVertexMapperArgs.Parse(reader, context, chunkType); break; case W3dChunkType.W3D_CHUNK_VERTEX_MAPPER_ARGS1: result.MapperArgs1 = W3dVertexMapperArgs.Parse(reader, context, chunkType); break; case W3dChunkType.W3D_CHUNK_VERTEX_MATERIAL_INFO: result.Info = W3dVertexMaterialInfo.Parse(reader, context); break; default: throw CreateUnknownChunkException(chunkType); } }); return result; })); }
} // Bounding sphere radius internal static W3dMeshHeader3 Parse(BinaryReader reader, W3dParseContext context) { return(ParseChunk(reader, context, header => { return new W3dMeshHeader3 { Version = reader.ReadUInt32(), Attributes = reader.ReadUInt32AsEnumFlags <W3dMeshFlags>(), MeshName = reader.ReadFixedLengthString(W3dConstants.NameLength), ContainerName = reader.ReadFixedLengthString(W3dConstants.NameLength), NumTris = reader.ReadUInt32(), NumVertices = reader.ReadUInt32(), NumMaterials = reader.ReadUInt32(), NumDamageStages = reader.ReadUInt32(), SortLevel = reader.ReadUInt32(), PrelitVersion = reader.ReadUInt32(), FutureCounts = reader.ReadUInt32(), VertexChannels = reader.ReadUInt32AsEnumFlags <W3dVertexChannels>(), FaceChannels = reader.ReadUInt32AsEnum <W3dFaceChannels>(), Min = reader.ReadVector3(), Max = reader.ReadVector3(), SphCenter = reader.ReadVector3(), SphRadius = reader.ReadSingle() }; })); }
internal static W3dEmitterInfo Parse(BinaryReader reader, W3dParseContext context) { return(ParseChunk(reader, context, header => { return new W3dEmitterInfo { TextureFileName = reader.ReadFixedLengthString(TextureFileNameLength), StartSize = reader.ReadSingle(), EndSize = reader.ReadSingle(), Lifetime = reader.ReadSingle(), EmissionRate = reader.ReadSingle(), MaxEmissions = reader.ReadSingle(), VelocityRandom = reader.ReadSingle(), PositionRandom = reader.ReadSingle(), FadeTime = reader.ReadSingle(), Gravity = reader.ReadSingle(), Elasticity = reader.ReadSingle(), Velocity = reader.ReadVector3(), Acceleration = reader.ReadVector3(), StartColor = W3dRgba.Parse(reader), EndColor = W3dRgba.Parse(reader) }; })); }
internal static T ParseChunk <T>( BinaryReader reader, W3dParseContext context, Func <W3dChunkHeader, T> parseCallback) where T : W3dChunk { var chunkHeader = W3dChunkHeader.Parse(reader); var startPosition = reader.BaseStream.Position; var endPosition = startPosition + chunkHeader.ChunkSize; context.PushChunk(typeof(T).Name, endPosition); var result = parseCallback(chunkHeader); result.StartPosition = startPosition; result.EndPosition = endPosition; context.PopAsset(); if (reader.BaseStream.Position != endPosition) { throw new InvalidDataException($"Error while parsing asset '{typeof(T).Name}'. Expected reader to be at position {endPosition}, but was at {reader.BaseStream.Position}."); } return(result); }
internal static W3dAnimation Parse(BinaryReader reader, W3dParseContext context) { return(ParseChunk(reader, context, header => { var result = new W3dAnimation(); ParseChunks(reader, context.CurrentEndPosition, chunkType => { switch (chunkType) { case W3dChunkType.W3D_CHUNK_ANIMATION_HEADER: result.Header = W3dAnimationHeader.Parse(reader, context); break; case W3dChunkType.W3D_CHUNK_ANIMATION_CHANNEL: result.Channels.Add(W3dAnimationChannel.Parse(reader, context)); break; case W3dChunkType.W3D_CHUNK_BIT_CHANNEL: result.Channels.Add(W3dBitChannel.Parse(reader, context)); break; default: throw CreateUnknownChunkException(chunkType); } }); return result; })); }
internal static W3dEmitter Parse(BinaryReader reader, W3dParseContext context) { return(ParseChunk(reader, context, header => { var result = new W3dEmitter(); ParseChunks(reader, context.CurrentEndPosition, chunkType => { switch (chunkType) { case W3dChunkType.W3D_CHUNK_EMITTER_HEADER: result.Header = W3dEmitterHeader.Parse(reader, context); break; case W3dChunkType.W3D_CHUNK_EMITTER_USER_DATA: result.UserData = W3dEmitterUserData.Parse(reader, context); break; case W3dChunkType.W3D_CHUNK_EMITTER_INFO: result.Info = W3dEmitterInfo.Parse(reader, context); break; case W3dChunkType.W3D_CHUNK_EMITTER_INFOV2: result.InfoV2 = W3dEmitterInfoV2.Parse(reader, context); break; case W3dChunkType.W3D_CHUNK_EMITTER_PROPS: result.Properties = W3dEmitterProperties.Parse(reader, context); break; case W3dChunkType.W3D_CHUNK_EMITTER_ROTATION_KEYFRAMES: result.RotationKeyframes = W3dEmitterRotationKeyframes.Parse(reader, context); break; case W3dChunkType.W3D_CHUNK_EMITTER_FRAME_KEYFRAMES: result.FrameKeyframes = W3dEmitterFrameKeyframes.Parse(reader, context); break; case W3dChunkType.W3D_CHUNK_EMITTER_LINE_PROPERTIES: result.LineProperties = W3dEmitterLineProperties.Parse(reader, context); break; case W3dChunkType.W3D_CHUNK_EMITTER_BLUR_TIME_KEYFRAMES: result.BlurTimeKeyframes = W3dEmitterBlurTimeKeyframes.Parse(reader, context); break; case W3dChunkType.W3D_CHUNK_EMITTER_EXTRA_INFO: result.ExtraInfo = W3dEmitterExtraInfo.Parse(reader, context); break; default: throw CreateUnknownChunkException(chunkType); } }); return result; })); }
internal static W3dTextureIds Parse(BinaryReader reader, W3dParseContext context) { return(ParseList(reader, context, r => { var textureId = r.ReadInt32(); return textureId != -1 ? (uint)textureId : (uint?)null; })); }
internal static W3dVertexMaterialName Parse(BinaryReader reader, W3dParseContext context) { return(ParseChunk(reader, context, header => { return new W3dVertexMaterialName { Value = reader.ReadFixedLengthString((int)header.ChunkSize) }; })); }
internal static W3dEmitterExtraInfo Parse(BinaryReader reader, W3dParseContext context) { return(ParseChunk(reader, context, header => { return new W3dEmitterExtraInfo { Unknown = reader.ReadBytes((int)header.ChunkSize) }; })); }
internal static W3dMeshUserText Parse(BinaryReader reader, W3dParseContext context) { return(ParseChunk(reader, context, header => { return new W3dMeshUserText { Value = reader.ReadFixedLengthString((int)header.ChunkSize) }; })); }
internal static W3dHLodArrayHeader Parse(BinaryReader reader, W3dParseContext context) { return(ParseChunk(reader, context, header => { return new W3dHLodArrayHeader { ModelCount = reader.ReadUInt32(), MaxScreenSize = reader.ReadSingle() }; })); }
internal static W3dEmitterHeader Parse(BinaryReader reader, W3dParseContext context) { return(ParseChunk(reader, context, header => { return new W3dEmitterHeader { Version = reader.ReadUInt32(), Name = reader.ReadFixedLengthString(W3dConstants.NameLength) }; })); }
internal static W3dHLodSubObject Parse(BinaryReader reader, W3dParseContext context) { return ParseChunk(reader, context, header => { return new W3dHLodSubObject { BoneIndex = reader.ReadUInt32(), Name = reader.ReadFixedLengthString(W3dConstants.NameLength * 2) }; }); }
internal static TList ParseList(BinaryReader reader, W3dParseContext context, Func <BinaryReader, TItem> parseItem) { return(ParseChunk(reader, context, header => { var result = new TList(); while (reader.BaseStream.Position < context.CurrentEndPosition) { result.Items.Add(parseItem(reader)); } return result; })); }
internal static W3dMaterialPass Parse(BinaryReader reader, W3dParseContext context) { return(ParseChunk(reader, context, header => { var result = new W3dMaterialPass(); ParseChunks(reader, context.CurrentEndPosition, chunkType => { switch (chunkType) { case W3dChunkType.W3D_CHUNK_VERTEX_MATERIAL_IDS: result.VertexMaterialIds = W3dUInt32List.Parse(reader, context, chunkType); break; case W3dChunkType.W3D_CHUNK_SHADER_IDS: result.ShaderIds = W3dUInt32List.Parse(reader, context, chunkType); break; case W3dChunkType.W3D_CHUNK_DCG: result.Dcg = W3dRgbaList.Parse(reader, context, chunkType); break; case W3dChunkType.W3D_CHUNK_DIG: result.Dig = W3dRgbaList.Parse(reader, context, chunkType); break; case W3dChunkType.W3D_CHUNK_SCG: result.Scg = W3dRgbaList.Parse(reader, context, chunkType); break; case W3dChunkType.W3D_CHUNK_TEXTURE_STAGE: result.TextureStages.Add(W3dTextureStage.Parse(reader, context)); break; case W3dChunkType.W3D_CHUNK_SHADER_MATERIAL_ID: result.ShaderMaterialIds = W3dUInt32List.Parse(reader, context, chunkType); break; // Normally this appears inside W3dTextureStage, but it can also // appear directly under W3dMaterialPass if using shader materials. case W3dChunkType.W3D_CHUNK_STAGE_TEXCOORDS: result.TexCoords = W3dVector2List.Parse(reader, context, chunkType); break; default: throw CreateUnknownChunkException(chunkType); } }); return result; })); }
private static W3dFile Parse(BinaryReader reader, string filePath) { var context = new W3dParseContext(); context.PushChunk(nameof(W3dFile), reader.BaseStream.Length); var result = new W3dFile { FilePath = filePath }; W3dContainerChunk.ParseChunks(reader, reader.BaseStream.Length, chunkType => { switch (chunkType) { case W3dChunkType.W3D_CHUNK_MESH: result.Chunks.Add(W3dMesh.Parse(reader, context)); break; case W3dChunkType.W3D_CHUNK_BOX: result.Chunks.Add(W3dBox.Parse(reader, context)); break; case W3dChunkType.W3D_CHUNK_HIERARCHY: result.Chunks.Add(W3dHierarchyDef.Parse(reader, context)); break; case W3dChunkType.W3D_CHUNK_HLOD: result.Chunks.Add(W3dHLod.Parse(reader, context)); break; case W3dChunkType.W3D_CHUNK_ANIMATION: result.Chunks.Add(W3dAnimation.Parse(reader, context)); break; case W3dChunkType.W3D_CHUNK_COMPRESSED_ANIMATION: result.Chunks.Add(W3dCompressedAnimation.Parse(reader, context)); break; case W3dChunkType.W3D_CHUNK_EMITTER: result.Chunks.Add(W3dEmitter.Parse(reader, context)); break; default: throw W3dContainerChunk.CreateUnknownChunkException(chunkType); } }); context.PopAsset(); return(result); }
internal static W3dMaterialInfo Parse(BinaryReader reader, W3dParseContext context) { return(ParseChunk(reader, context, header => { return new W3dMaterialInfo { PassCount = reader.ReadUInt32(), VertexMaterialCount = reader.ReadUInt32(), ShaderCount = reader.ReadUInt32(), TextureCount = reader.ReadUInt32() }; })); }
internal static W3dTextureInfo Parse(BinaryReader reader, W3dParseContext context) { return(ParseChunk(reader, context, header => { return new W3dTextureInfo { Attributes = reader.ReadUInt16AsEnumFlags <W3dTextureFlags>(), AnimationType = reader.ReadUInt16AsEnum <W3dTextureAnimation>(), FrameCount = reader.ReadUInt32(), FrameRate = reader.ReadSingle(), }; })); }