Exemplo n.º 1
0
        internal void Read(EndianBinaryReader reader, ObjectSection section = null)
        {
            reader.SeekCurrent(4);   // Unused flags

            BoundingSphere = reader.ReadBoundingSphere();

            int  subMeshCount    = reader.ReadInt32();
            long subMeshesOffset = reader.ReadOffset();

            var vertexFormat     = ( VertexFormatAttributes )reader.ReadUInt32();
            int vertexSize       = reader.ReadInt32();
            int vertexCount      = reader.ReadInt32();
            var attributeOffsets = reader.ReadOffsets(20);

            Flags = ( MeshFlags )reader.ReadInt32();

            uint attributeFlags = reader.ReadUInt32();

            reader.SkipNulls(6 * sizeof(uint));

            Name = reader.ReadString(StringBinaryFormat.FixedLength, 64);

            reader.ReadAtOffset(subMeshesOffset, () =>
            {
                SubMeshes.Capacity = subMeshCount;

                for (int i = 0; i < subMeshCount; i++)
                {
                    var subMesh = new SubMesh();
                    subMesh.Read(reader, section);
                    SubMeshes.Add(subMesh);
                }
            });

            // Modern Format
            if ((vertexFormat & VertexFormatAttributes.UsesModernStorage) != 0)
            {
                ReadVertexAttributesModern();
            }

            else
            {
                ReadVertexAttributesClassic();
            }

            void ReadVertexAttributesClassic()
            {
                Vector4[] boneWeights = null;
                Vector4[] boneIndices = null;

                for (int i = 0; i < attributeOffsets.Length; i++)
                {
                    var attribute = ( VertexFormatAttributes )(1 << i);

                    reader.ReadAtOffsetIf((vertexFormat & attribute) != 0, attributeOffsets[i], () =>
                    {
                        switch (attribute)
                        {
                        case VertexFormatAttributes.Position:
                            Positions = reader.ReadVector3s(vertexCount);
                            break;

                        case VertexFormatAttributes.Normal:
                            Normals = reader.ReadVector3s(vertexCount);
                            break;

                        case VertexFormatAttributes.Tangent:
                            Tangents = reader.ReadVector4s(vertexCount);
                            break;

                        case VertexFormatAttributes.TexCoord0:
                            TexCoords0 = reader.ReadVector2s(vertexCount);
                            break;

                        case VertexFormatAttributes.TexCoord1:
                            TexCoords1 = reader.ReadVector2s(vertexCount);
                            break;

                        case VertexFormatAttributes.TexCoord2:
                            TexCoords2 = reader.ReadVector2s(vertexCount);
                            break;

                        case VertexFormatAttributes.TexCoord3:
                            TexCoords3 = reader.ReadVector2s(vertexCount);
                            break;

                        case VertexFormatAttributes.Color0:
                            Colors0 = reader.ReadColors(vertexCount);
                            break;

                        case VertexFormatAttributes.Color1:
                            Colors1 = reader.ReadColors(vertexCount);
                            break;

                        case VertexFormatAttributes.BoneWeight:
                            boneWeights = reader.ReadVector4s(vertexCount);
                            break;

                        case VertexFormatAttributes.BoneIndex:
                            boneIndices = reader.ReadVector4s(vertexCount);
                            break;

                        default:
                            Console.WriteLine("Unhandled vertex format element: {0}", attribute);
                            break;
                        }
                    });
                }

                if (boneWeights == null || boneIndices == null)
                {
                    return;
                }

                BoneWeights = new BoneWeight[vertexCount];

                for (int i = 0; i < vertexCount; i++)
                {
                    var weight4 = boneWeights[i];
                    var index4  = Vector4.Divide(boneIndices[i], 3);

                    var boneWeight = new BoneWeight
                    {
                        Weight1 = weight4.X,
                        Weight2 = weight4.Y,
                        Weight3 = weight4.Z,
                        Weight4 = weight4.W,
                        Index1  = ( int )index4.X,
                        Index2  = ( int )index4.Y,
                        Index3  = ( int )index4.Z,
                        Index4  = ( int )index4.W
                    };

                    boneWeight.Validate();

                    BoneWeights[i] = boneWeight;
                }
            }

            void ReadVertexAttributesModern()
            {
                Positions  = new Vector3[vertexCount];
                Normals    = new Vector3[vertexCount];
                Tangents   = new Vector4[vertexCount];
                TexCoords0 = new Vector2[vertexCount];
                TexCoords1 = new Vector2[vertexCount];

                if (attributeFlags == 10)
                {
                    TexCoords2 = new Vector2[vertexCount];
                    TexCoords3 = new Vector2[vertexCount];
                }
                else if (attributeFlags == 6)
                {
                    TexCoords2 = new Vector2[vertexCount];
                }

                Colors0 = new Color[vertexCount];

                if (attributeFlags == 4)
                {
                    BoneWeights = new BoneWeight[vertexCount];
                }

                bool hasTangents = false;

                EndianBinaryReader vertexReader;
                long baseOffset;

                if (section != null)
                {
                    vertexReader = section.VertexData.Reader;
                    baseOffset   = section.VertexData.DataOffset;
                }
                else
                {
                    vertexReader = reader;
                    baseOffset   = reader.BaseOffset;
                }

                long current = reader.Position;

                for (int i = 0; i < vertexCount; i++)
                {
                    vertexReader.SeekBegin(baseOffset + attributeOffsets[13] + vertexSize * i);

                    Positions[i] = vertexReader.ReadVector3();
                    Normals[i]   = vertexReader.ReadVector3(VectorBinaryFormat.Int16);
                    vertexReader.SeekCurrent(2);
                    Tangents[i]   = vertexReader.ReadVector4(VectorBinaryFormat.Int16);
                    TexCoords0[i] = vertexReader.ReadVector2(VectorBinaryFormat.Half);
                    TexCoords1[i] = vertexReader.ReadVector2(VectorBinaryFormat.Half);

                    if (attributeFlags == 10)
                    {
                        TexCoords2[i] = vertexReader.ReadVector2(VectorBinaryFormat.Half);
                        TexCoords3[i] = vertexReader.ReadVector2(VectorBinaryFormat.Half);
                    }
                    else if (attributeFlags == 6)
                    {
                        TexCoords2[i] = vertexReader.ReadVector2(VectorBinaryFormat.Half);
                    }

                    Colors0[i] = vertexReader.ReadColor(VectorBinaryFormat.Half);

                    if (attributeFlags == 4)
                    {
                        var boneWeight = new BoneWeight
                        {
                            Weight1 = vertexReader.ReadUInt16() / 32767f,
                            Weight2 = vertexReader.ReadUInt16() / 32767f,
                            Weight3 = vertexReader.ReadUInt16() / 32767f,
                            Weight4 = vertexReader.ReadUInt16() / 32767f,
                            Index1  = vertexReader.ReadByte() / 3,
                            Index2  = vertexReader.ReadByte() / 3,
                            Index3  = vertexReader.ReadByte() / 3,
                            Index4  = vertexReader.ReadByte() / 3
                        };

                        boneWeight.Validate();

                        BoneWeights[i] = boneWeight;
                    }

                    // Normalize normal because precision
                    Normals[i] = Vector3.Normalize(Normals[i]);

                    // Checks to get rid of useless data after reading
                    if (Tangents[i] != Vector4.Zero)
                    {
                        hasTangents = true;
                    }
                }

                if (!hasTangents)
                {
                    Tangents = null;
                }

                reader.SeekBegin(current);
            }

            if (Tangents == null)
            {
                return;
            }

            for (int i = 0; i < Tangents.Length; i++)
            {
                int direction = Math.Sign(Tangents[i].W);
                var tangent   = Vector3.Normalize(new Vector3(Tangents[i].X, Tangents[i].Y, Tangents[i].Z));

                Tangents[i] = new Vector4(tangent, direction);
            }
        }
Exemplo n.º 2
0
        internal void Read(EndianBinaryReader reader, ObjectSection section = null)
        {
            reader.SeekCurrent(4);
            BoundingSphere = reader.ReadBoundingSphere();
            int  subMeshCount    = reader.ReadInt32();
            long subMeshesOffset = reader.ReadOffset();
            var  attributes      = ( VertexFormatAttribute )reader.ReadUInt32();
            int  stride          = reader.ReadInt32();
            int  vertexCount     = reader.ReadInt32();
            var  elemItems       = reader.ReadUInt32s(section?.Format == BinaryFormat.X ? 49 : 28);

            Name = reader.ReadString(StringBinaryFormat.FixedLength, 64);

            SubMeshes.Capacity = subMeshCount;
            for (int i = 0; i < subMeshCount; i++)
            {
                reader.ReadAtOffset(subMeshesOffset + i * SubMesh.GetByteSize(section?.Format ?? BinaryFormat.DT),
                                    () =>
                {
                    var subMesh = new SubMesh();
                    subMesh.Read(reader, section);
                    SubMeshes.Add(subMesh);
                });
            }

            // Modern Format
            if (section != null)
            {
                ReadVertexAttributesModern();
            }
            else
            {
                ReadVertexAttributesClassic();
            }

            void ReadVertexAttributesClassic()
            {
                Vector4[] boneWeights = null;
                Vector4[] boneIndices = null;

                for (int i = 0; i < 28; i++)
                {
                    var attribute = ( VertexFormatAttribute )(1 << i);

                    reader.ReadAtOffsetIf((attributes & attribute) != 0, elemItems[i], () =>
                    {
                        switch (attribute)
                        {
                        case VertexFormatAttribute.Vertex:
                            Vertices = reader.ReadVector3s(vertexCount);
                            break;

                        case VertexFormatAttribute.Normal:
                            Normals = reader.ReadVector3s(vertexCount);
                            break;

                        case VertexFormatAttribute.Tangent:
                            Tangents = reader.ReadVector4s(vertexCount);
                            break;

                        case VertexFormatAttribute.UVChannel1:
                            UVChannel1 = reader.ReadVector2s(vertexCount);
                            break;

                        case VertexFormatAttribute.UVChannel2:
                            UVChannel2 = reader.ReadVector2s(vertexCount);
                            break;

                        case VertexFormatAttribute.Color:
                            Colors = reader.ReadColors(vertexCount);
                            break;

                        case VertexFormatAttribute.BoneWeight:
                            boneWeights = reader.ReadVector4s(vertexCount);
                            break;

                        case VertexFormatAttribute.BoneIndex:
                            boneIndices = reader.ReadVector4s(vertexCount);
                            break;

                        default:
                            Console.WriteLine("Unhandled vertex format element: {0}", attribute);
                            break;
                        }
                    });
                }

                if (boneWeights != null && boneIndices != null)
                {
                    BoneWeights = new BoneWeight[vertexCount];
                    for (int i = 0; i < vertexCount; i++)
                    {
                        var weight4 = boneWeights[i];
                        var index4  = Vector4.Divide(boneIndices[i], 3);

                        var boneWeight = new BoneWeight
                        {
                            Weight1 = weight4.X,
                            Weight2 = weight4.Y,
                            Weight3 = weight4.Z,
                            Weight4 = weight4.W,
                            Index1  = ( int )index4.X,
                            Index2  = ( int )index4.Y,
                            Index3  = ( int )index4.Z,
                            Index4  = ( int )index4.W
                        };
                        boneWeight.Validate();

                        BoneWeights[i] = boneWeight;
                    }
                }
            }

            void ReadVertexAttributesModern()
            {
                uint dataOffset     = elemItems[section.Format == BinaryFormat.X ? 27 : 13];
                uint attributeFlags = elemItems[section.Format == BinaryFormat.X ? 42 : 21];

                if (attributeFlags == 2 || attributeFlags == 4)
                {
                    Vertices   = new Vector3[vertexCount];
                    Normals    = new Vector3[vertexCount];
                    Tangents   = new Vector4[vertexCount];
                    UVChannel1 = new Vector2[vertexCount];
                    UVChannel2 = new Vector2[vertexCount];
                    Colors     = new Color[vertexCount];

                    if (attributeFlags == 4)
                    {
                        BoneWeights = new BoneWeight[vertexCount];
                    }

                    bool hasTangents   = false;
                    bool hasUVChannel2 = false;
                    bool hasColors     = false;

                    var vertexReader = section.VertexData.Reader;
                    for (int i = 0; i < vertexCount; i++)
                    {
                        vertexReader.SeekBegin(section.VertexData.DataOffset + dataOffset + stride * i);
                        Vertices[i] = vertexReader.ReadVector3();
                        Normals[i]  = vertexReader.ReadVector3(VectorBinaryFormat.Int16);
                        vertexReader.SeekCurrent(2);
                        Tangents[i]   = vertexReader.ReadVector4(VectorBinaryFormat.Int16);
                        UVChannel1[i] = vertexReader.ReadVector2(VectorBinaryFormat.Half);
                        UVChannel2[i] = vertexReader.ReadVector2(VectorBinaryFormat.Half);
                        Colors[i]     = vertexReader.ReadColor(VectorBinaryFormat.Half);

                        if (attributeFlags == 4)
                        {
                            var boneWeight = new BoneWeight
                            {
                                Weight1 = vertexReader.ReadUInt16() / 32767f,
                                Weight2 = vertexReader.ReadUInt16() / 32767f,
                                Weight3 = vertexReader.ReadUInt16() / 32767f,
                                Weight4 = vertexReader.ReadUInt16() / 32767f,
                                Index1  = vertexReader.ReadByte() / 3,
                                Index2  = vertexReader.ReadByte() / 3,
                                Index3  = vertexReader.ReadByte() / 3,
                                Index4  = vertexReader.ReadByte() / 3
                            };
                            boneWeight.Validate();

                            BoneWeights[i] = boneWeight;
                        }

                        // Normalize normal because precision
                        Normals[i] = Vector3.Normalize(Normals[i]);

                        // Checks to get rid of useless data after reading
                        if (Tangents[i] != Vector4.Zero)
                        {
                            hasTangents = true;
                        }
                        if (UVChannel1[i] != UVChannel2[i])
                        {
                            hasUVChannel2 = true;
                        }
                        if (!Colors[i].Equals(Color.White))
                        {
                            hasColors = true;
                        }
                    }

                    if (!hasTangents)
                    {
                        Tangents = null;
                    }
                    if (!hasUVChannel2)
                    {
                        UVChannel2 = null;
                    }
                    if (!hasColors)
                    {
                        Colors = null;
                    }
                }

                if (Tangents != null)
                {
                    for (int i = 0; i < Tangents.Length; i++)
                    {
                        int direction = Math.Sign(Tangents[i].W);
                        var tangent   =
                            Vector3.Normalize(new Vector3(Tangents[i].X, Tangents[i].Y, Tangents[i].Z));

                        Tangents[i] = new Vector4(tangent, direction);
                    }
                }
            }
        }