Пример #1
0
        internal Autodesk3ds(AssetLoader loader, Autodesk3dsFormat format)
            : base(format.Manager, "3DS Model - " + loader.Name)
        {
            var reader = loader.Reader;

            AssetFormat = format;

            Chunk chunk, subchunk;
            if (!Chunk.ReadRequired(loader, ChunkId.Main, out chunk))
                return;

            while (chunk.ReadSubchunk(out subchunk)) {
                switch (subchunk.Id) {
                    case ChunkId.ModelVersion:
                        int modelVersion = subchunk.ReadContentInt(0);
                        if (modelVersion > MaxModelVersion || modelVersion < MinModelVersion)
                            loader.AddError(chunk.Offset, "3DS model version {0} is out of range ({1} to {2} supported).", modelVersion, MinModelVersion, MaxModelVersion);
                        break;

                    case ChunkId.Editor:
                        ReadEditor(subchunk);
                        break;

                    default:
                        chunk.ReportUnknownSubchunkError(subchunk);
                        break;
                }

                subchunk.RequireAtEnd();
            }
        }
Пример #2
0
 void ExpectedOffset(AssetLoader loader, long offset, string section)
 {
     if (loader.Position != offset)
     {
         loader.AddError(loader.Position, "Expected to be at offset " + offset + " for section " + section + ".");
         loader.Position = offset;
     }
 }
Пример #3
0
        /// <summary>Load the block.</summary>
        /// <param name="loader"></param>
        public ScriptBlock(AssetLoader loader)
        {
            HeaderOffset = loader.Position;
            Type         = (ScriptBlockType)loader.Reader.ReadUInt16();

            if (Type == ScriptBlockType.End)
            {
                TotalSize = 2;
            }
            else
            {
                TotalSize = loader.Reader.ReadUInt16();
                if (TotalSize < 4)
                {
                    loader.AddError(HeaderOffset, "Invalid block size in script resource; terminating reading.");
                    TotalSize = 2;
                    Type      = ScriptBlockType.End;
                }
            }
        }
Пример #4
0
        internal ParameterTable(AssetLoader loader)
            : base(loader)
        {
            var reader             = loader.Reader;
            int stringsOffset      = reader.ReadInt32();
            int firstRowDataOffset = reader.ReadUInt16();

            Unknowns.ReadInt16s(reader, 2);
            int rowCount = reader.ReadUInt16();

            Name = reader.ReadStringz(0x20, Encoding.ASCII);
            Unknowns.ReadInt32s(reader, 1);

            // Read in the row headers.
            RowInfo[] rows = new RowInfo[rowCount];
            for (int index = 0; index < rowCount; index++)
            {
                rows[index].Read(reader);
            }

            // Read in the rows.
            for (int index = 0; index < rowCount; index++)
            {
                loader.Position = rows[index].DataOffset;
                int next = index < rows.Length - 1 ? rows[index + 1].DataOffset : stringsOffset;
                ParameterTableRow item = ParameterTableRow.ReadRow(this, index, loader, next);
                item.Id = rows[index].Id;

                if (loader.Position != next)
                {
                    loader.AddError(rows[index].DataOffset, "Row {0} of the table did not read the correct amount; position should be {1}, but is {2}.", index, next, loader.Position);
                }
            }

            // Read in the row names.
            for (int index = 0; index < rowCount; index++)
            {
                loader.Position = rows[index].NameOffset;
                ((ParameterTableRow)Children[index]).Name = reader.ReadStringz(EncodingShiftJis).Trim();                //((index < rows.Length - 1 ? rows[index + 1].NameOffset : loader.ShortLength) - rows[index].NameOffset - 1, EncodingShiftJis));
            }
        }
Пример #5
0
            /// <summary>Read a content integer based on the length.</summary>
            /// <param name="defaultValue"></param>
            /// <returns></returns>
            public int ReadContentInt(int defaultValue)
            {
                switch (DataLength)
                {
                case 1: return(Reader.ReadByte());

                case 2: return(Reader.ReadUInt16());

                case 4: return(Reader.ReadInt32());

                default:
                    Loader.AddError(Offset, "Expected chunk {0} to contain an integer; but its data length is {1}.", IdString, DataLength);
                    return(defaultValue);
                }
            }
Пример #6
0
        internal Autodesk3ds(AssetLoader loader, Autodesk3dsFormat format)
            : base(format.Manager, "3DS Model - " + loader.Name)
        {
            var reader = loader.Reader;

            AssetFormat = format;

            Chunk chunk, subchunk;

            if (!Chunk.ReadRequired(loader, ChunkId.Main, out chunk))
            {
                return;
            }

            while (chunk.ReadSubchunk(out subchunk))
            {
                switch (subchunk.Id)
                {
                case ChunkId.ModelVersion:
                    int modelVersion = subchunk.ReadContentInt(0);
                    if (modelVersion > MaxModelVersion || modelVersion < MinModelVersion)
                    {
                        loader.AddError(chunk.Offset, "3DS model version {0} is out of range ({1} to {2} supported).", modelVersion, MinModelVersion, MaxModelVersion);
                    }
                    break;

                case ChunkId.Editor:
                    ReadEditor(subchunk);
                    break;

                default:
                    chunk.ReportUnknownSubchunkError(subchunk);
                    break;
                }

                subchunk.RequireAtEnd();
            }
        }
Пример #7
0
            internal Part(Table table, int index, AssetLoader loader, int next)
                : base(table, index)
            {
                BinaryReader reader = loader.Reader;
                long         start  = reader.BaseStream.Position;

                loader.Expect(HeaderLength);
                Type = (ModelType)reader.ReadInt32();
                Unknowns.ReadInt32s(reader, 1);
                Index = reader.ReadInt32();
                int pathOffset = reader.ReadInt32();

                Position = reader.ReadVector3f();
                Rotation = Angle3.Degrees(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                Scale    = reader.ReadVector3f();
                Unknowns.ReadInt32s(reader, 8);
                int offset1 = reader.ReadInt32();
                int offset2 = reader.ReadInt32();

                if (offset1 + 0x18 != offset2)
                {
                    loader.AddError(start, "Offset2 is not correct.");
                }
                loader.ExpectZeroes(4, 1);
                Name = reader.ReadStringz(EncodingShiftJis);
                Path = reader.ReadStringz(EncodingShiftJis);

                loader.Position = start + offset1;
                Unknowns.ReadInt32s(reader, 6, "Offset1s");

                if (loader.Position > next || (next - loader.Position) / 4 > 64)
                {
                }

                Unknowns.ReadInt32s(reader, (int)(next - loader.Position) / 4, "Offset2s");
            }
Пример #8
0
            internal Event(Table table, int index, AssetLoader loader, int next)
                : base(table, index)
            {
                BinaryReader reader = loader.Reader;
                long         start  = loader.Position;

                loader.Expect(HeaderLength);
                Unknowns.ReadInt32s(reader, 1);
                Type  = reader.ReadInt32();
                Index = reader.ReadInt32();
                int offseta = reader.ReadInt32();
                int offsetb = reader.ReadInt32();

                if (offsetb != offseta + 0x10)
                {
                    loader.AddError(start, "{0} index {1} does not have a normal offset A/B", GetType().Name, index);
                }
                loader.ExpectZeroes(4, 1);
                Name = reader.ReadStringz(EncodingShiftJis);

                loader.Position = start + offseta;
                Unknowns.ReadInt32s(reader, 4);
                Unknowns.ReadInt32s(reader, (next - (int)loader.Position) / 4);
            }
Пример #9
0
        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);
        }