Ejemplo n.º 1
0
        protected override SolidMeshVertex GetVertex(BinaryReader reader, SolidObjectMaterial material, int stride)
        {
            CarbonMaterial  cm     = (CarbonMaterial)material;
            SolidMeshVertex vertex = new SolidMeshVertex();

            InternalEffectID id = (InternalEffectID)cm.EffectId;

            switch (id)
            {
            case InternalEffectID.WorldShader:
                vertex.Position  = BinaryUtil.ReadVector3(reader);
                vertex.Normal    = BinaryUtil.ReadVector3(reader);
                vertex.Color     = reader.ReadUInt32();
                vertex.TexCoords = BinaryUtil.ReadVector2(reader);
                break;

            case InternalEffectID.skyshader:
                vertex.Position             = BinaryUtil.ReadVector3(reader);
                vertex.Normal               = BinaryUtil.ReadVector3(reader);
                vertex.Color                = reader.ReadUInt32();
                vertex.TexCoords            = BinaryUtil.ReadVector2(reader);
                reader.BaseStream.Position += 8;     // TODO: What's this additional D3DDECLUSAGE_TEXCOORD element?
                break;

            case InternalEffectID.WorldNormalMap:
            case InternalEffectID.WorldReflectShader:
                vertex.Position             = BinaryUtil.ReadVector3(reader);
                vertex.Normal               = BinaryUtil.ReadVector3(reader);
                vertex.Color                = reader.ReadUInt32();
                vertex.TexCoords            = BinaryUtil.ReadVector2(reader);
                vertex.Tangent              = BinaryUtil.ReadVector3(reader);
                reader.BaseStream.Position += 4;     // skip W component of tangent vector
                break;

            case InternalEffectID.CarShader:
                vertex.Position  = BinaryUtil.ReadVector3(reader);
                vertex.Normal    = BinaryUtil.ReadVector3(reader);
                vertex.Color     = reader.ReadUInt32();
                vertex.TexCoords = BinaryUtil.ReadVector2(reader);
                vertex.Tangent   = BinaryUtil.ReadVector3(reader);
                break;

            case InternalEffectID.CARNORMALMAP:
                vertex.Position  = BinaryUtil.ReadVector3(reader);
                vertex.TexCoords = BinaryUtil.ReadVector2(reader);
                vertex.Color     = reader.ReadUInt32();
                vertex.Normal    = BinaryUtil.ReadVector3(reader);
                vertex.Tangent   = BinaryUtil.ReadVector3(reader);
                break;

            case InternalEffectID.GLASS_REFLECT:
                vertex.Position  = BinaryUtil.ReadVector3(reader);
                vertex.TexCoords = BinaryUtil.ReadVector2(reader);
                vertex.Color     = reader.ReadUInt32();
                vertex.Normal    = BinaryUtil.ReadVector3(reader);
                break;

            case InternalEffectID.WATER:
                vertex.Position  = BinaryUtil.ReadVector3(reader);
                vertex.Color     = reader.ReadUInt32();
                vertex.TexCoords = BinaryUtil.ReadVector2(reader);
                vertex.Normal    = BinaryUtil.ReadVector3(reader);
                break;

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

            return(vertex);
        }
Ejemplo n.º 2
0
        private SolidObject ReadObject(BinaryReader br, long size, SolidObject solidObject = null)
        {
            if (solidObject == null)
            {
                solidObject = new CarbonObject();
            }

            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;

                if (chunkSize == 0)
                {
                    continue;
                }

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

                    while (br.ReadByte() == 0x11)
                    {
                        padding++;
                    }

                    br.BaseStream.Position--;

                    if (padding % 2 != 0)
                    {
                        padding--;
                        br.BaseStream.Position--;
                    }

                    chunkSize -= padding;

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

                        var header = BinaryUtil.ReadStruct <SolidObjectHeader>(br);
                        var name   = BinaryUtil.ReadNullTerminatedString(br);

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

                        break;
                    }

                    // 12 40 13 00
                    case 0x00134012:
                    {
                        for (var j = 0; j < chunkSize / 8; j++)
                        {
                            solidObject.TextureHashes.Add(br.ReadUInt32());
                            br.BaseStream.Position += 4;
                        }

                        break;
                    }

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

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

                        break;
                    }

                    case 0x00134b02:
                    {
                        Debug.Assert(chunkSize % 144 == 0);
                        var numMats = chunkSize / 144;

                        var streamIndex  = 0;
                        var lastEffectID = 0u;

                        for (var j = 0; j < numMats; j++)
                        {
                            var shadingGroup = BinaryUtil.ReadStruct <SolidObjectShadingGroup>(br);

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

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

                            solidObject.Materials.Add(solidObjectMaterial);

                            solidObject.MeshDescriptor.NumVerts += shadingGroup.NumVerts;
                            lastEffectID = shadingGroup.EffectId;
                        }

                        break;
                    }

                    case 0x134b01:
                    {
                        if (chunkSize > 0)
                        {
                            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;
                    }

                    default:
                        //Console.WriteLine($"0x{chunkId:X8} [{chunkSize}] @{br.BaseStream.Position}");
                        break;
                    }
                }

                br.BaseStream.Position = chunkEndPos;
            }

            return(solidObject);
        }