internal void ReadVertices(BinaryReaderEx br, int dataOffset, List <BufferLayout> layouts, FLVERHeader header, FlverCache cache)
            {
                var layoutMembers = layouts.SelectMany(l => l);
                int uvCap         = layoutMembers.Where(m => m.Semantic == FLVER.LayoutSemantic.UV).Count();
                int tanCap        = layoutMembers.Where(m => m.Semantic == FLVER.LayoutSemantic.Tangent).Count();
                int colorCap      = layoutMembers.Where(m => m.Semantic == FLVER.LayoutSemantic.VertexColor).Count();

                VertexCount = VertexBuffers[0].VertexCount;
                Vertices    = cache.GetCachedVertexArray(VertexCount);
                if (Vertices == null)
                {
                    Vertices = new FLVER.Vertex[VertexCount];
                    for (int i = 0; i < VertexCount; i++)
                    {
                        Vertices[i] = new FLVER.Vertex(uvCap, tanCap, colorCap);
                    }
                    cache.CacheVertexArray(Vertices);
                }
                else
                {
                    for (int i = 0; i < Vertices.Length; i++)
                    {
                        Vertices[i].UVCount      = 0;
                        Vertices[i].TangentCount = 0;
                    }
                }

                foreach (VertexBuffer buffer in VertexBuffers)
                {
                    buffer.ReadBuffer(br, layouts, Vertices, VertexCount, dataOffset, header);
                }
            }
Esempio n. 2
0
            public ushort[] ToTriangleList()
            {
                var  converted = new List <ushort>();
                bool checkFlip = false;
                bool flip      = false;

                for (int i = 0; i < VertexIndices.Length - 2; i++)
                {
                    ushort vi1 = VertexIndices[i];
                    ushort vi2 = VertexIndices[i + 1];
                    ushort vi3 = VertexIndices[i + 2];

                    if (vi1 == 0xFFFF || vi2 == 0xFFFF || vi3 == 0xFFFF)
                    {
                        checkFlip = true;
                    }
                    else
                    {
                        if (vi1 != vi2 && vi1 != vi3 && vi2 != vi3)
                        {
                            // Every time the triangle strip restarts, compare the average vertex normal to the face normal
                            // and flip the starting direction if they're pointing away from each other.
                            // I don't know why this is necessary; in most models they always restart with the same orientation
                            // as you'd expect. But on some, I can't discern any logic to it, thus this approach.
                            // It's probably hideously slow because I don't know anything about math.
                            // Feel free to hit me with a PR. :slight_smile:
                            if (checkFlip)
                            {
                                FLVER.Vertex v1           = Vertices[vi1];
                                FLVER.Vertex v2           = Vertices[vi2];
                                FLVER.Vertex v3           = Vertices[vi3];
                                Vector3      n1           = new Vector3(v1.Normal.X, v1.Normal.Y, v1.Normal.Z);
                                Vector3      n2           = new Vector3(v2.Normal.X, v2.Normal.Y, v2.Normal.Z);
                                Vector3      n3           = new Vector3(v3.Normal.X, v3.Normal.Y, v3.Normal.Z);
                                Vector3      vertexNormal = Vector3.Normalize((n1 + n2 + n3) / 3);
                                Vector3      faceNormal   = Vector3.Normalize(Vector3.Cross(v2.Position - v1.Position, v3.Position - v1.Position));
                                float        angle        = Vector3.Dot(faceNormal, vertexNormal) / (faceNormal.Length() * vertexNormal.Length());
                                flip      = angle >= 0;
                                checkFlip = false;
                            }

                            if (!flip)
                            {
                                converted.Add(vi1);
                                converted.Add(vi2);
                                converted.Add(vi3);
                            }
                            else
                            {
                                converted.Add(vi3);
                                converted.Add(vi2);
                                converted.Add(vi1);
                            }
                        }
                        flip = !flip;
                    }
                }
                return(converted.ToArray());
            }
Esempio n. 3
0
            internal Mesh(BinaryReaderEx br, List <Material> materials, int dataOffset)
            {
                Dynamic       = br.ReadBoolean();
                MaterialIndex = br.ReadByte();
                Unk02         = br.ReadBoolean();
                Unk03         = br.ReadByte();

                int vertexIndexCount = br.ReadInt32();
                int vertexCount      = br.ReadInt32();

                DefaultBoneIndex = br.ReadInt16();
                BoneIndices      = br.ReadInt16s(28);
                br.AssertInt16(0);
                br.AssertInt32(vertexIndexCount * 2);
                int vertexIndicesOffset = br.ReadInt32();
                int bufferSize          = br.ReadInt32();
                int bufferOffset        = br.ReadInt32();

                br.ReadInt32(); // Buffers header offset
                br.AssertInt32(0);
                br.AssertInt32(0);

                VertexIndices = br.GetUInt16s(dataOffset + vertexIndicesOffset, vertexIndexCount);

                br.StepIn(dataOffset + bufferOffset);
                {
                    BufferLayout layout = null;
                    foreach (var bl in materials[MaterialIndex].Layouts)
                    {
                        if (bl.Size * vertexCount == bufferSize)
                        {
                            layout = bl;
                        }
                    }

                    float uvFactor = 1024;
                    // NB hack
                    if (!br.BigEndian)
                    {
                        uvFactor = 2048;
                    }

                    Vertices = new List <FLVER.Vertex>(vertexCount);
                    for (int i = 0; i < vertexCount; i++)
                    {
                        var vert = new FLVER.Vertex();
                        vert.Read(br, layout, uvFactor);
                        Vertices.Add(vert);
                    }
                }
                br.StepOut();
            }
Esempio n. 4
0
            internal Mesh(BinaryReaderEx br, FLVER0 flv, int dataOffset)
            {
                Dynamic       = br.ReadByte();
                MaterialIndex = br.ReadByte();
                Unk02         = br.ReadBoolean();
                Unk03         = br.ReadByte();

                int vertexIndexCount = br.ReadInt32();
                int vertexCount      = br.ReadInt32();

                DefaultBoneIndex = br.ReadInt16();
                BoneIndices      = br.ReadInt16s(28);
                Unk46            = br.ReadInt16();
                br.ReadInt32(); // Vertex indices length
                int vertexIndicesOffset  = br.ReadInt32();
                int bufferDataLength     = br.ReadInt32();
                int bufferDataOffset     = br.ReadInt32();
                int vertexBuffersOffset1 = br.ReadInt32();
                int vertexBuffersOffset2 = br.ReadInt32();

                br.AssertInt32(0);

                if (flv.VertexIndexSize == 16)
                {
                    VertexIndices = new List <int>(vertexCount);
                    foreach (ushort index in br.GetUInt16s(dataOffset + vertexIndicesOffset, vertexIndexCount))
                    {
                        VertexIndices.Add(index);
                    }
                }
                else if (flv.VertexIndexSize == 32)
                {
                    VertexIndices = new List <int>(br.GetInt32s(dataOffset + vertexIndicesOffset, vertexIndexCount));
                }

                VertexBuffer buffer;

                // Stupid hack for old (version F?) flvers; for example DeS o9993.
                if (vertexBuffersOffset1 == 0)
                {
                    buffer = new VertexBuffer()
                    {
                        BufferLength = bufferDataLength,
                        BufferOffset = bufferDataOffset,
                        LayoutIndex  = 0,
                    };
                }
                else
                {
                    br.StepIn(vertexBuffersOffset1);
                    {
                        List <VertexBuffer> vertexBuffers1 = VertexBuffer.ReadVertexBuffers(br);
                        if (vertexBuffers1.Count == 0)
                        {
                            throw new NotSupportedException("First vertex buffer list is expected to contain at least 1 buffer.");
                        }
                        for (int i = 1; i < vertexBuffers1.Count; i++)
                        {
                            if (vertexBuffers1[i].BufferLength != 0)
                            {
                                throw new NotSupportedException("Vertex buffers after the first one in the first buffer list are expected to be empty.");
                            }
                        }
                        buffer = vertexBuffers1[0];
                    }
                    br.StepOut();
                }

                if (vertexBuffersOffset2 != 0)
                {
                    br.StepIn(vertexBuffersOffset2);
                    {
                        List <VertexBuffer> vertexBuffers2 = VertexBuffer.ReadVertexBuffers(br);
                        if (vertexBuffers2.Count != 0)
                        {
                            throw new NotSupportedException("Second vertex buffer list is expected to contain exactly 0 buffers.");
                        }
                    }
                    br.StepOut();
                }

                br.StepIn(dataOffset + buffer.BufferOffset);
                {
                    LayoutIndex = buffer.LayoutIndex;
                    BufferLayout layout = flv.Materials[MaterialIndex].Layouts[LayoutIndex];

                    float uvFactor = 1024;
                    // NB hack
                    if (!br.BigEndian)
                    {
                        uvFactor = 2048;
                    }

                    Vertices = new List <FLVER.Vertex>(vertexCount);
                    for (int i = 0; i < vertexCount; i++)
                    {
                        var vert = new FLVER.Vertex();
                        vert.Read(br, layout, uvFactor);
                        Vertices.Add(vert);
                    }
                }
                br.StepOut();
            }