internal ModelDetailLevel(ModelMesh mesh, int index, AssetLoader loader, int dataOffset, ArrayBackedList<byte> bufferData) : base(mesh, index, loader) { var reader = loader.Reader; Mesh = mesh; const int indexSize = 2; Threshold = reader.ReadInt32(); Unknowns.ReadInt16s(reader, IsDS1 ? 1 : 2); if (IsDS1) reader.RequireZeroes(2); IndexCount = reader.ReadInt32(); IndexDataOffset = reader.ReadInt32() + dataOffset; int indexDataSize = reader.ReadInt32(); if (indexDataSize != IndexCount * indexSize) throw new InvalidDataException("Index data size doesn't match the expected value from the index count."); reader.RequireZeroes(4 * 3); BufferIndexOffset = bufferData.Count; long reset = reader.BaseStream.Position; reader.BaseStream.Position = IndexDataOffset; bufferData.AddRange(reader, IndexCount * indexSize); reader.BaseStream.Position = reset; }
internal void ReadDetailLevels(AssetLoader loader, int dataOffset, ArrayBackedList <byte> bufferData) { var detailLevels = new Codex <ModelDetailLevel>(); DetailLevels = detailLevels; for (int index = 0; index < PartCount; index++) { detailLevels.Add(new ModelDetailLevel(this, index, loader, dataOffset, bufferData)); } }
internal void ReadVertexHeaders(BinaryReader reader, int dataOffset, ArrayBackedList <byte> bufferData) { reader.RequireZeroes(4 * 1); VertexDeclarationIndex = reader.ReadInt32(); VertexSize = reader.ReadInt32(); VertexCount = reader.ReadInt32(); reader.RequireZeroes(4 * 2); int vertexDataSize = reader.ReadInt32(); if (VertexSize * VertexCount != vertexDataSize) { throw new Exception(); } VertexDataOffset = reader.ReadInt32() + dataOffset; // Read vertex data. long reset = reader.BaseStream.Position; reader.BaseStream.Position = VertexDataOffset; BufferDataOffset = bufferData.Count; bufferData.AddRange(reader, vertexDataSize); reader.BaseStream.Position = reset; }
internal Model(AssetLoader loader) : base(loader) { Asset context = loader.Context; string name = loader.Name; BinaryReader reader = loader.Reader; FolderAsset textureArchive = null; FolderAsset bonesFolder = new FolderAsset(this, "Bones"); FolderAsset materialsFolder = new FolderAsset(this, "Materials"); FolderAsset meshesFolder = new FolderAsset(this, "Meshes"); FolderAsset vertexDeclarationsFolder = new FolderAsset(this, "Vertex declarations"); ArrayBackedList <byte> bufferData = new ArrayBackedList <byte>(); if (context != null && context.Parent is FolderAsset) { // @"/map/m##_##_##_##/m*.flver.dcx" for DS1; textures are in the @"/map/m##/" folder. if (name.StartsWith(@"map/m")) { string folderName = name.Substring(4, 3); FolderAsset maps = (FolderAsset)context.Parent.Parent; foreach (FolderAsset child in maps.Children) { if (child.Name == folderName) { textureArchive = child; break; } } } else { textureArchive = (FolderAsset)context.Parent; } } #if Marking MarkingStream markingStream = loader.StartMarking(out reader); #endif loader.ExpectMagic(Magic); char endian = (char)reader.ReadByte(); switch (endian) { case 'L': ByteOrder = ByteOrder.LittleEndian; break; case 'B': reader = loader.MakeBigEndian(); ByteOrder = ByteOrder.BigEndian; break; default: throw new Exception(); } using (reader) { // Read header. loader.Expect((byte)0); Version = (ModelVersion)reader.ReadInt32(); if (Version != ModelVersion.DarkSouls && Version != ModelVersion.DarkSouls2) { loader.AddError(loader.Position - 4, "Unknown model version " + VersionString + "; will try to load it anyway."); } int dataOffset = reader.ReadInt32(); int dataSize = reader.ReadInt32(); if (((dataOffset + dataSize + 31) & ~31) != reader.BaseStream.Length) { loader.AddError(loader.Position - 4, "Data size and offset aren't correct."); } int boneUnknownCount = reader.ReadInt32(); int materialCount = reader.ReadInt32(); int boneCount = reader.ReadInt32(); int meshCount = reader.ReadInt32(); int meshCount2 = reader.ReadInt32(); if (meshCount != meshCount2) { loader.AddError(loader.Position - 4, "Mesh count 1 and 2 aren't the same."); } Bounds = new Box3f(reader.ReadVector3f(), reader.ReadVector3f()); Unknowns.ReadInt32s(reader, 1); // Possible the non-degenerate triangle count. Seems related. int triangleCount = reader.ReadInt32(); loader.Expect(IsDS1 ? 272 : 0x10010100); loader.Expect(IsDS1 ? 0 : 0xFFFF); int partCount = reader.ReadInt32(); int vertexDeclarationCount = reader.ReadInt32(); int materialParameterCount = reader.ReadInt32(); loader.Expect(IsDS1 ? 0 : 0x1000000); loader.ExpectZeroes(4, 8); // Calculate offsets. long boneUnknownsOffset = HeaderSize; long materialsOffset = boneUnknownsOffset + boneUnknownCount * ModelBoneUnknown.DataSize; long bonesOffset = materialsOffset + materialCount * ModelMaterial.DataSize; long meshesOffset = bonesOffset + boneCount * ModelBone.DataSize; long detailLevelsOffset = meshesOffset + meshCount * ModelMesh.DataSize; long meshVerticesOffset = detailLevelsOffset + partCount * ModelDetailLevel.DataSize; long vertexDeclarationsOffset = meshVerticesOffset + meshCount * ModelMesh.DataSizeVertexHeader; long materialParametersOffset = vertexDeclarationsOffset + vertexDeclarationCount * ModelVertexDeclaration.DataSize; long postHeaderOffset = materialParametersOffset + materialParameterCount * ModelMaterialParameter.DataSize; // BoneUnknowns ExpectedOffset(loader, boneUnknownsOffset, typeof(ModelBoneUnknown).Name); for (int index = 0; index < boneUnknownCount; index++) { boneUnknowns.Add(new ModelBoneUnknown(bonesFolder, index, loader)); } // Materials ExpectedOffset(loader, materialsOffset, typeof(ModelMaterial).Name); for (int index = 0; index < materialCount; index++) { materials.Add(new ModelMaterial(materialsFolder, index, loader)); } int expectedMaterialParameterCount = materialCount > 0 ? materials[materialCount - 1].ParameterEndIndex : 0; if (expectedMaterialParameterCount != materialParameterCount) { loader.AddError(null, "Expected material parameter count {0} doesn't match actual count {1}.", expectedMaterialParameterCount, materialParameterCount); } // Bones ExpectedOffset(loader, bonesOffset, typeof(ModelBone).Name); for (int index = 0; index < boneCount; index++) { bones.Add(new ModelBone(bonesFolder, index, loader)); } // Meshes ExpectedOffset(loader, meshesOffset, typeof(ModelMesh).Name); for (int index = 0; index < meshCount; index++) { meshes.Add(new ModelMesh(meshesFolder, index, loader)); } int expectedPartCount = meshCount > 0 ? meshes[meshCount - 1].PartEndIndex : 0; if (expectedPartCount != partCount) { throw new InvalidDataException("Expected part count doesn't match actual count."); } // Detail levels ExpectedOffset(loader, detailLevelsOffset, typeof(ModelDetailLevel).Name); foreach (ModelMesh mesh in meshes) { mesh.ReadDetailLevels(loader, dataOffset, bufferData); detailLevels.AddRange(mesh.DetailLevels); } // Mesh vertices ExpectedOffset(loader, meshVerticesOffset, typeof(ModelMesh).Name + " vertex header"); foreach (ModelMesh mesh in meshes) { mesh.ReadVertexHeaders(reader, dataOffset, bufferData); } // Vertex declarations ExpectedOffset(loader, vertexDeclarationsOffset, typeof(ModelVertexDeclaration).Name); for (int index = 0; index < vertexDeclarationCount; index++) { vertexDeclarations.Add(new ModelVertexDeclaration(vertexDeclarationsFolder, index, loader)); } // Material parameters ExpectedOffset(loader, materialParametersOffset, typeof(ModelMaterialParameter).Name); foreach (ModelMaterial material in materials) { material.ReadParameters(loader, textureArchive); materialParameters.AddRange(material.Parameters); } ExpectedOffset(loader, postHeaderOffset, "Post-header"); #if Marking if (markingStream != null) { markingStream.Report(loader); } #endif // Marking #if SkippedChecks /*int vertexDataSize = 0, indexCount = 0, indexSize = 0, vertexCount = 0, expectedTriangleCount = 0, nondegenerateTriangleCount = 0; * foreach (var mesh in Meshes) { * vertexDataSize += mesh.VertexCount * mesh.VertexSize; * vertexCount += mesh.VertexCount; * foreach (var part in mesh.Parts) { * indexCount += part.Indices.Length; * indexSize += part.Indices.Length * 2; * expectedTriangleCount += part.Indices.Length - 2; * for (int index = 0; index < part.Indices.Length - 2; index++) { * if (part.Indices[index] != part.Indices[index + 1] && part.Indices[index + 1] != part.Indices[index + 2] && part.Indices[index] != part.Indices[index + 2]) * nondegenerateTriangleCount++; * } * } * } * if (Math.Abs(expectedTriangleCount - triangleCount) > partCount) * throw new InvalidDataException("Expected triangle count doesn't match the read value.");*/ #endif } Buffer = new GraphicsBuffer(bufferData.Count == 0 ? 1 : bufferData.Count); Buffer.Write(0, bufferData.Array, 0, bufferData.Count); }
internal ModelDetailLevel(ModelMesh mesh, int index, AssetLoader loader, int dataOffset, ArrayBackedList <byte> bufferData) : base(mesh, index, loader) { var reader = loader.Reader; Mesh = mesh; const int indexSize = 2; Threshold = reader.ReadInt32(); Unknowns.ReadInt16s(reader, IsDS1 ? 1 : 2); if (IsDS1) { reader.RequireZeroes(2); } IndexCount = reader.ReadInt32(); IndexDataOffset = reader.ReadInt32() + dataOffset; int indexDataSize = reader.ReadInt32(); if (indexDataSize != IndexCount * indexSize) { throw new InvalidDataException("Index data size doesn't match the expected value from the index count."); } reader.RequireZeroes(4 * 3); BufferIndexOffset = bufferData.Count; long reset = reader.BaseStream.Position; reader.BaseStream.Position = IndexDataOffset; bufferData.AddRange(reader, IndexCount * indexSize); reader.BaseStream.Position = reset; }
internal void ReadVertexHeaders(BinaryReader reader, int dataOffset, ArrayBackedList<byte> bufferData) { reader.RequireZeroes(4 * 1); VertexDeclarationIndex = reader.ReadInt32(); VertexSize = reader.ReadInt32(); VertexCount = reader.ReadInt32(); reader.RequireZeroes(4 * 2); int vertexDataSize = reader.ReadInt32(); if (VertexSize * VertexCount != vertexDataSize) throw new Exception(); VertexDataOffset = reader.ReadInt32() + dataOffset; // Read vertex data. long reset = reader.BaseStream.Position; reader.BaseStream.Position = VertexDataOffset; BufferDataOffset = bufferData.Count; bufferData.AddRange(reader, vertexDataSize); reader.BaseStream.Position = reset; }
internal void ReadDetailLevels(AssetLoader loader, int dataOffset, ArrayBackedList<byte> bufferData) { var detailLevels = new Codex<ModelDetailLevel>(); DetailLevels = detailLevels; for (int index = 0; index < PartCount; index++) detailLevels.Add(new ModelDetailLevel(this, index, loader, dataOffset, bufferData)); }
internal Model(AssetLoader loader) : base(loader) { Asset context = loader.Context; string name = loader.Name; BinaryReader reader = loader.Reader; FolderAsset textureArchive = null; FolderAsset bonesFolder = new FolderAsset(this, "Bones"); FolderAsset materialsFolder = new FolderAsset(this, "Materials"); FolderAsset meshesFolder = new FolderAsset(this, "Meshes"); FolderAsset vertexDeclarationsFolder = new FolderAsset(this, "Vertex declarations"); ArrayBackedList<byte> bufferData = new ArrayBackedList<byte>(); if (context != null && context.Parent is FolderAsset) { // @"/map/m##_##_##_##/m*.flver.dcx" for DS1; textures are in the @"/map/m##/" folder. if (name.StartsWith(@"map/m")) { string folderName = name.Substring(4, 3); FolderAsset maps = (FolderAsset)context.Parent.Parent; foreach (FolderAsset child in maps.Children) { if (child.Name == folderName) { textureArchive = child; break; } } } else textureArchive = (FolderAsset)context.Parent; } #if Marking MarkingStream markingStream = loader.StartMarking(out reader); #endif loader.ExpectMagic(Magic); char endian = (char)reader.ReadByte(); switch (endian) { case 'L': ByteOrder = ByteOrder.LittleEndian; break; case 'B': reader = loader.MakeBigEndian(); ByteOrder = ByteOrder.BigEndian; break; default: throw new Exception(); } using (reader) { // Read header. loader.Expect((byte)0); Version = (ModelVersion)reader.ReadInt32(); if (Version != ModelVersion.DarkSouls && Version != ModelVersion.DarkSouls2) loader.AddError(loader.Position - 4, "Unknown model version " + VersionString + "; will try to load it anyway."); int dataOffset = reader.ReadInt32(); int dataSize = reader.ReadInt32(); if (((dataOffset + dataSize + 31) & ~31) != reader.BaseStream.Length) loader.AddError(loader.Position - 4, "Data size and offset aren't correct."); int boneUnknownCount = reader.ReadInt32(); int materialCount = reader.ReadInt32(); int boneCount = reader.ReadInt32(); int meshCount = reader.ReadInt32(); int meshCount2 = reader.ReadInt32(); if (meshCount != meshCount2) loader.AddError(loader.Position - 4, "Mesh count 1 and 2 aren't the same."); Bounds = new Box3f(reader.ReadVector3f(), reader.ReadVector3f()); Unknowns.ReadInt32s(reader, 1); // Possible the non-degenerate triangle count. Seems related. int triangleCount = reader.ReadInt32(); loader.Expect(IsDS1 ? 272 : 0x10010100); loader.Expect(IsDS1 ? 0 : 0xFFFF); int partCount = reader.ReadInt32(); int vertexDeclarationCount = reader.ReadInt32(); int materialParameterCount = reader.ReadInt32(); loader.Expect(IsDS1 ? 0 : 0x1000000); loader.ExpectZeroes(4, 8); // Calculate offsets. long boneUnknownsOffset = HeaderSize; long materialsOffset = boneUnknownsOffset + boneUnknownCount * ModelBoneUnknown.DataSize; long bonesOffset = materialsOffset + materialCount * ModelMaterial.DataSize; long meshesOffset = bonesOffset + boneCount * ModelBone.DataSize; long detailLevelsOffset = meshesOffset + meshCount * ModelMesh.DataSize; long meshVerticesOffset = detailLevelsOffset + partCount * ModelDetailLevel.DataSize; long vertexDeclarationsOffset = meshVerticesOffset + meshCount * ModelMesh.DataSizeVertexHeader; long materialParametersOffset = vertexDeclarationsOffset + vertexDeclarationCount * ModelVertexDeclaration.DataSize; long postHeaderOffset = materialParametersOffset + materialParameterCount * ModelMaterialParameter.DataSize; // BoneUnknowns ExpectedOffset(loader, boneUnknownsOffset, typeof(ModelBoneUnknown).Name); for (int index = 0; index < boneUnknownCount; index++) boneUnknowns.Add(new ModelBoneUnknown(bonesFolder, index, loader)); // Materials ExpectedOffset(loader, materialsOffset, typeof(ModelMaterial).Name); for (int index = 0; index < materialCount; index++) materials.Add(new ModelMaterial(materialsFolder, index, loader)); int expectedMaterialParameterCount = materialCount > 0 ? materials[materialCount - 1].ParameterEndIndex : 0; if (expectedMaterialParameterCount != materialParameterCount) loader.AddError(null, "Expected material parameter count {0} doesn't match actual count {1}.", expectedMaterialParameterCount, materialParameterCount); // Bones ExpectedOffset(loader, bonesOffset, typeof(ModelBone).Name); for (int index = 0; index < boneCount; index++) bones.Add(new ModelBone(bonesFolder, index, loader)); // Meshes ExpectedOffset(loader, meshesOffset, typeof(ModelMesh).Name); for (int index = 0; index < meshCount; index++) meshes.Add(new ModelMesh(meshesFolder, index, loader)); int expectedPartCount = meshCount > 0 ? meshes[meshCount - 1].PartEndIndex : 0; if (expectedPartCount != partCount) throw new InvalidDataException("Expected part count doesn't match actual count."); // Detail levels ExpectedOffset(loader, detailLevelsOffset, typeof(ModelDetailLevel).Name); foreach (ModelMesh mesh in meshes) { mesh.ReadDetailLevels(loader, dataOffset, bufferData); detailLevels.AddRange(mesh.DetailLevels); } // Mesh vertices ExpectedOffset(loader, meshVerticesOffset, typeof(ModelMesh).Name + " vertex header"); foreach (ModelMesh mesh in meshes) mesh.ReadVertexHeaders(reader, dataOffset, bufferData); // Vertex declarations ExpectedOffset(loader, vertexDeclarationsOffset, typeof(ModelVertexDeclaration).Name); for (int index = 0; index < vertexDeclarationCount; index++) vertexDeclarations.Add(new ModelVertexDeclaration(vertexDeclarationsFolder, index, loader)); // Material parameters ExpectedOffset(loader, materialParametersOffset, typeof(ModelMaterialParameter).Name); foreach (ModelMaterial material in materials) { material.ReadParameters(loader, textureArchive); materialParameters.AddRange(material.Parameters); } ExpectedOffset(loader, postHeaderOffset, "Post-header"); #if Marking if (markingStream != null) { markingStream.Report(loader); } #endif // Marking #if SkippedChecks /*int vertexDataSize = 0, indexCount = 0, indexSize = 0, vertexCount = 0, expectedTriangleCount = 0, nondegenerateTriangleCount = 0; foreach (var mesh in Meshes) { vertexDataSize += mesh.VertexCount * mesh.VertexSize; vertexCount += mesh.VertexCount; foreach (var part in mesh.Parts) { indexCount += part.Indices.Length; indexSize += part.Indices.Length * 2; expectedTriangleCount += part.Indices.Length - 2; for (int index = 0; index < part.Indices.Length - 2; index++) { if (part.Indices[index] != part.Indices[index + 1] && part.Indices[index + 1] != part.Indices[index + 2] && part.Indices[index] != part.Indices[index + 2]) nondegenerateTriangleCount++; } } } if (Math.Abs(expectedTriangleCount - triangleCount) > partCount) throw new InvalidDataException("Expected triangle count doesn't match the read value.");*/ #endif } Buffer = new GraphicsBuffer(bufferData.Count == 0 ? 1 : bufferData.Count); Buffer.Write(0, bufferData.Array, 0, bufferData.Count); }