示例#1
0
        protected override SolidMeshVertex GetVertex(BinaryReader reader, SolidObjectMaterial material, int stride)
        {
            World15Material wm     = (World15Material)material;
            SolidMeshVertex vertex = new SolidMeshVertex();

            InternalEffectID id = (InternalEffectID)wm.EffectId;

            switch (id)
            {
            case InternalEffectID.WorldShader:
            case InternalEffectID.GLASS_REFLECT:
            case InternalEffectID.WorldZBiasShader:
            case InternalEffectID.Tree:
            case InternalEffectID.WATER:
                vertex.Position  = BinaryUtil.ReadVector3(reader);
                vertex.Normal    = BinaryUtil.ReadNormal(reader, true);
                vertex.TexCoords = BinaryUtil.ReadVector2(reader);
                vertex.Color     = reader.ReadUInt32(); // daytime color
                reader.ReadUInt32();                    // nighttime color
                break;

            case InternalEffectID.WorldPrelitShader:
                vertex.Position = BinaryUtil.ReadVector3(reader);
                vertex.Color    = reader.ReadUInt32(); // daytime color
                reader.ReadUInt32();                   // nighttime color
                vertex.TexCoords = BinaryUtil.ReadVector2(reader);
                break;

            case InternalEffectID.WorldZBiasPrelitShader:
                vertex.Position = BinaryUtil.ReadVector3(reader);
                vertex.Normal   = BinaryUtil.ReadNormal(reader, true);
                vertex.Color    = reader.ReadUInt32(); // daytime color
                reader.ReadUInt32();                   // nighttime color
                vertex.TexCoords = BinaryUtil.ReadVector2(reader);
                break;

            case InternalEffectID.WorldNormalMap:
            case InternalEffectID.GLASS_REFLECTNM:
            case InternalEffectID.WorldRoadShader:
            case InternalEffectID.WorldFEShader:
                vertex.Position  = BinaryUtil.ReadVector3(reader);
                vertex.Normal    = BinaryUtil.ReadNormal(reader, true);
                vertex.TexCoords = BinaryUtil.ReadVector2(reader);
                vertex.Color     = reader.ReadUInt32(); // daytime color
                reader.ReadUInt32();                    // nighttime color
                vertex.Tangent = BinaryUtil.ReadNormal(reader, true);
                break;

            case InternalEffectID.CarShader:
            case InternalEffectID.CARNORMALMAP:
                vertex.Position  = BinaryUtil.ReadNormal(reader, true) * 8;
                vertex.TexCoords = new Vector2(reader.ReadInt16() / 4096f, reader.ReadInt16() / 4096f - 1);
                vertex.Color     = reader.ReadUInt32();
                vertex.Normal    = BinaryUtil.ReadNormal(reader, true);
                vertex.Tangent   = BinaryUtil.ReadNormal(reader, true);
                break;

            default:
                throw new Exception($"Unsupported effect in object {Name}: {id}");
            }

            return(vertex);
        }
示例#2
0
        private World15Object ReadObject(BinaryReader br, long size, World15Object solidObject = null)
        {
            if (solidObject == null)
            {
                solidObject = new World15Object();
            }

            var endPos = br.BaseStream.Position + size;

            while (br.BaseStream.Position < endPos)
            {
                var chunkId     = br.ReadUInt32();
                var chunkSize   = br.ReadUInt32();
                var chunkEndPos = br.BaseStream.Position + chunkSize;

                //Console.WriteLine($"@{chunkEndPos}: 0x{chunkId:X8} [{chunkSize}]");

                if ((chunkId & 0x80000000) == 0x80000000)
                {
                    solidObject = ReadObject(br, chunkSize, solidObject);
                }
                else
                {
                    var padding = 0u;

                    while (br.ReadUInt32() == 0x11111111)
                    {
                        padding += 4;
                    }

                    br.BaseStream.Position -= 4;
                    chunkSize -= padding;

                    switch (chunkId)
                    {
                    case SolidListObjHeadChunk:
                    {
                        _namedMaterials = 0;

                        var header = BinaryUtil.ReadUnmanagedStruct <ObjectHeader>(br);
                        var name   = BinaryUtil.ReadNullTerminatedString(br);

                        solidObject.Name     = name;
                        solidObject.Hash     = header.ObjectHash;
                        solidObject.MinPoint = header.BoundsMin;
                        solidObject.MaxPoint = header.BoundsMax;

                        solidObject.Transform = header.Transform;

                        break;
                    }

                    case 0x134900:
                    {
                        var descriptor = BinaryUtil.ReadUnmanagedStruct <MeshDescriptor>(br);

                        solidObject.MeshDescriptor = new SolidMeshDescriptor
                        {
                            Flags            = descriptor.Flags,
                            HasNormals       = true,
                            NumIndices       = descriptor.NumTriIndex,
                            NumMats          = descriptor.MaterialShaderNum,
                            NumVertexStreams = descriptor.NumVertexStreams,
                            NumTris          = descriptor.NumTriangles
                        };

                        break;
                    }

                    case 0x00134b02:
                    {
                        Debug.Assert(chunkSize % solidObject.MeshDescriptor.NumMats == 0);

                        var streamIndex  = 0;
                        var lastEffectId = 0u;

                        for (var j = 0; j < solidObject.MeshDescriptor.NumMats; j++)
                        {
                            var shadingGroup = BinaryUtil.ReadUnmanagedStruct <Material>(br);

                            if (j > 0 && shadingGroup.EffectId != lastEffectId)
                            {
                                streamIndex++;
                            }

                            var solidObjectMaterial = new World15Material
                            {
                                Flags             = shadingGroup.Flags,
                                NumIndices        = shadingGroup.NumIndices == 0 ? shadingGroup.NumTris * 3 : shadingGroup.NumIndices,
                                MinPoint          = shadingGroup.BoundsMin,
                                MaxPoint          = shadingGroup.BoundsMax,
                                NumVerts          = shadingGroup.NumVerts,
                                TextureHash       = solidObject.TextureHashes[shadingGroup.DiffuseMapId],
                                EffectId          = shadingGroup.EffectId,
                                VertexStreamIndex = streamIndex
                            };

                            solidObject.Materials.Add(solidObjectMaterial);

                            solidObject.MeshDescriptor.NumVerts += shadingGroup.NumVerts;

                            lastEffectId = shadingGroup.EffectId;
                        }

                        break;
                    }

                    case 0x134012:
                    {
                        for (var j = 0; j < chunkSize / 8; j++)
                        {
                            solidObject.TextureHashes.Add(br.ReadUInt32());
                            br.BaseStream.Position += 4;
                        }
                        break;
                    }

                    case 0x134b01:
                    {
                        var vb       = new byte[chunkSize];
                        var readSize = br.Read(vb, 0, vb.Length);
                        Debug.Assert(readSize == chunkSize);

                        solidObject.VertexBuffers.Add(vb);

                        break;
                    }

                    case 0x134b03:
                    {
                        foreach (var material in solidObject.Materials)
                        {
                            material.Indices = new ushort[material.NumIndices];
                            for (var j = 0; j < material.NumIndices; j++)
                            {
                                material.Indices[j] = br.ReadUInt16();
                            }
                        }

                        break;
                    }

                    case 0x00134c02:
                    {
                        if (chunkSize > 0)
                        {
                            solidObject.Materials[_namedMaterials++].Name =
                                BinaryUtil.ReadNullTerminatedString(br);
                        }
                        break;
                    }

                    case 0x134c06:
                    {
                        Debug.Assert(chunkSize % 0x40 == 0);

                        for (int i = 0; i < chunkSize / 0x40; i++)
                        {
                            solidObject.MorphMatrices.Add(BinaryUtil.ReadUnmanagedStruct <Matrix4x4>(br));
                        }

                        break;
                    }

                    case 0x134c05:
                    {
                        Debug.Assert(chunkSize % 0x10 == 0);
                        var morphList = new List <World15Object.MorphInfo>();

                        for (int i = 0; i < chunkSize / 0x10; i++)
                        {
                            morphList.Add(new World15Object.MorphInfo
                                {
                                    VertexStartIndex = br.ReadInt32(),
                                    VertexEndIndex   = br.ReadInt32(),
                                    MorphMatrixIndex = br.ReadInt32()
                                });
                            br.ReadInt32();
                        }

                        solidObject.MorphLists.Add(morphList);

                        break;
                    }

                    default:
                        //Debug.WriteLine($"unhandled chunk in World15Solids: 0x{chunkId:X8} [{chunkSize}] @{br.BaseStream.Position:X}");
                        break;
                    }
                }

                br.BaseStream.Position = chunkEndPos;
            }

            return(solidObject);
        }