public override void OnInspectorGUI()
    {
        FlverSubmesh submesh = (FlverSubmesh)target;

        // Long check to see if generating lightmap UVs is safe
        if (submesh.Link != null)
        {
            if (submesh.Link.Submeshes.Count > submesh.SubmeshIdx)
            {
                if (submesh.Link.Submeshes[submesh.SubmeshIdx].Mtd != null)
                {
                    if (submesh.Link.Submeshes[submesh.SubmeshIdx].Mtd.LightmapUVIndex != -1)
                    {
                        if (GUILayout.Button("Generate Lightmap UVs"))
                        {
                            submesh.Link.GenerateLightmapUVSForSubmesh(submesh.SubmeshIdx);
                        }
                    }
                }
            }
        }

        if (GUILayout.Button("Dump Normals"))
        {
            var dump = CreateInstance <NormalDump>();
            var mesh = ((FlverSubmesh)target).gameObject.GetComponent <MeshFilter>().sharedMesh;
            dump.Normals = mesh.normals;
            AssetDatabase.CreateAsset(dump, "Assets/normaldump.asset");
        }

        if (submesh.Link != null)
        {
            if (submesh.Link.Submeshes.Count > submesh.SubmeshIdx)
            {
                if (submesh.Link.Submeshes[submesh.SubmeshIdx].Mtd != null)
                {
                    var sub = submesh.Link.Submeshes[submesh.SubmeshIdx];
                    GUILayout.Label($@"Material Name: {sub.Name}");
                    GUILayout.Label($@"MTD: {sub.Mtd}");
                    GUILayout.Label($@"Lightmap Index: {sub.Mtd.LightmapUVIndex}");
                }
            }
        }
    }
    public override void OnInspectorGUI()
    {
        FlverSubmesh submesh = (FlverSubmesh)target;

        // Long check to see if generating lightmap UVs is safe
        if (submesh.Link != null)
        {
            if (submesh.Link.Submeshes.Count > submesh.SubmeshIdx)
            {
                if (submesh.Link.Submeshes[submesh.SubmeshIdx].Mtd != null)
                {
                    if (submesh.Link.Submeshes[submesh.SubmeshIdx].Mtd.LightmapUVIndex != -1)
                    {
                        if (GUILayout.Button("Generate Lightmap UVs"))
                        {
                            submesh.Link.GenerateLightmapUVSForSubmesh(submesh.SubmeshIdx);
                        }
                    }
                }
            }
        }
    }
Beispiel #3
0
        private bool LoadInternalDeS(AccessLevel al, GameType type)
        {
            if (al == AccessLevel.AccessFull || al == AccessLevel.AccessGPUOptimizedOnly)
            {
                GPUMeshes    = new FlverSubmesh[FlverDeS.Meshes.Count()];
                GPUMaterials = new FlverMaterial[FlverDeS.Materials.Count()];
                Bounds       = new BoundingBox();
                Bones        = FlverDeS.Bones;

                for (int i = 0; i < FlverDeS.Materials.Count(); i++)
                {
                    GPUMaterials[i] = new FlverMaterial();
                    ProcessMaterial(FlverDeS.Materials[i], GPUMaterials[i], type);
                }

                for (int i = 0; i < FlverDeS.Meshes.Count(); i++)
                {
                    GPUMeshes[i] = new FlverSubmesh();
                    ProcessMesh(FlverDeS.Meshes[i], GPUMeshes[i]);
                    if (i == 0)
                    {
                        Bounds = GPUMeshes[i].Bounds;
                    }
                    else
                    {
                        Bounds = BoundingBox.Combine(Bounds, GPUMeshes[i].Bounds);
                    }
                }
            }

            if (al == AccessLevel.AccessGPUOptimizedOnly)
            {
                Flver = null;
            }
            //return false;
            return(true);
        }
Beispiel #4
0
        unsafe private void ProcessMesh(FLVER2.Mesh mesh, FlverSubmesh dest)
        {
            var factory = Scene.Renderer.Factory;

            dest.Material = GPUMaterials[mesh.MaterialIndex];

            //var MeshVertices = VerticesPool.Rent(mesh.VertexCount);
            var vSize        = dest.Material.VertexSize;
            var meshVertices = Marshal.AllocHGlobal(mesh.VertexCount * (int)vSize);

            dest.PickingVertices = Marshal.AllocHGlobal(mesh.VertexCount * sizeof(Vector3));
            var pvhandle = new Span <Vector3>(dest.PickingVertices.ToPointer(), mesh.VertexCount);

            if (dest.Material.LayoutType == MeshLayoutType.LayoutSky)
            {
                FillVerticesNormalOnly(mesh, pvhandle, meshVertices);
            }
            else if (dest.Material.LayoutType == MeshLayoutType.LayoutUV2)
            {
                FillVerticesUV2(mesh, pvhandle, meshVertices);
            }
            else
            {
                FillVerticesStandard(mesh, pvhandle, meshVertices);
            }

            dest.VertexCount = mesh.VertexCount;

            dest.MeshFacesets = new List <FlverSubmesh.FlverSubmeshFaceSet>();
            var facesets         = mesh.FaceSets;
            var fsUploadsPending = facesets.Count();

            bool is32bit      = Flver.Header.Version > 0x20005 && mesh.VertexCount > 65535;
            int  indicesTotal = 0;

            ushort[] fs16 = null;
            int[]    fs32 = null;
            foreach (var faceset in facesets)
            {
                indicesTotal += faceset.Indices.Length;
            }
            if (is32bit)
            {
                fs32 = new int[indicesTotal];
            }
            else
            {
                fs16 = new ushort[indicesTotal];
            }

            int idxoffset = 0;

            foreach (var faceset in facesets)
            {
                if (faceset.Indices.Length == 0)
                {
                    continue;
                }

                //At this point they use 32-bit faceset vertex indices

                uint buffersize = (uint)faceset.IndicesCount * (is32bit ? 4u : 2u);
                var  indices    = faceset.TriangleStrip ? faceset.Triangulate(true).ToArray() : faceset.Indices.ToArray();
                var  newFaceSet = new FlverSubmesh.FlverSubmeshFaceSet()
                {
                    BackfaceCulling = faceset.CullBackfaces,
                    IsTriangleStrip = faceset.TriangleStrip,
                    //IndexBuffer = factory.CreateBuffer(new BufferDescription(buffersize, BufferUsage.IndexBuffer)),
                    IndexOffset = idxoffset,

                    IndexCount          = faceset.IndicesCount,
                    Is32Bit             = is32bit,
                    PickingIndicesCount = indices.Length,
                    //PickingIndices = Marshal.AllocHGlobal(indices.Length * 4),
                };
                fixed(void *iptr = indices)
                {
                    //Unsafe.CopyBlock(newFaceSet.PickingIndices.ToPointer(), iptr, (uint)indices.Length * 4);
                }

                if ((faceset.Flags & FLVER2.FaceSet.FSFlags.LodLevel1) > 0)
                {
                    newFaceSet.LOD = 1;
                    //HasNoLODs = false;
                    newFaceSet.IsMotionBlur = false;
                }
                else if ((faceset.Flags & FLVER2.FaceSet.FSFlags.LodLevel2) > 0)
                {
                    newFaceSet.LOD = 2;
                    //HasNoLODs = false;
                    newFaceSet.IsMotionBlur = false;
                }

                if ((faceset.Flags & FLVER2.FaceSet.FSFlags.MotionBlur) > 0)
                {
                    newFaceSet.IsMotionBlur = true;
                }

                if (is32bit)
                {
                    for (int i = 0; i < faceset.Indices.Length; i++)
                    {
                        if (faceset.Indices[i] == 0xFFFF && faceset.Indices[i] > mesh.Vertices.Length)
                        {
                            fs32[newFaceSet.IndexOffset + i] = -1;
                        }
                        else
                        {
                            fs32[newFaceSet.IndexOffset + i] = faceset.Indices[i];
                        }
                    }
                }
                else
                {
                    for (int i = 0; i < faceset.Indices.Length; i++)
                    {
                        if (faceset.Indices[i] == 0xFFFF && faceset.Indices[i] > mesh.Vertices.Length)
                        {
                            fs16[newFaceSet.IndexOffset + i] = 0xFFFF;
                        }
                        else
                        {
                            fs16[newFaceSet.IndexOffset + i] = (ushort)faceset.Indices[i];
                        }
                    }
                }

                dest.MeshFacesets.Add(newFaceSet);
                idxoffset += faceset.Indices.Length;
            }

            dest.Bounds = BoundingBox.CreateFromPoints((Vector3 *)dest.PickingVertices.ToPointer(), dest.VertexCount, 12, Quaternion.Identity, Vector3.Zero, Vector3.One);

            uint vbuffersize = (uint)mesh.VertexCount * (uint)vSize;

            dest.GeomBuffer = Scene.Renderer.GeometryBufferAllocator.Allocate(vbuffersize, (uint)indicesTotal * (is32bit ? 4u : 2u), (int)vSize, 4, (h) =>
            {
                h.FillVBuffer(meshVertices, vSize * (uint)mesh.VertexCount, () =>
                {
                    Marshal.FreeHGlobal(meshVertices);
                });
                if (is32bit)
                {
                    h.FillIBuffer(fs32);
                }
                else
                {
                    h.FillIBuffer(fs16);
                }
            });

            facesets = null;

            if (CaptureMaterialLayouts)
            {
                lock (_matLayoutLock)
                {
                    if (!MaterialLayouts.ContainsKey(dest.Material.MaterialName))
                    {
                        MaterialLayouts.Add(dest.Material.MaterialName, Flver.BufferLayouts[mesh.VertexBuffers[0].LayoutIndex]);
                    }
                }
            }

            if (mesh.DefaultBoneIndex != -1 && mesh.DefaultBoneIndex < Bones.Count)
            {
                dest.LocalTransform = Utils.GetBoneObjectMatrix(Bones[mesh.DefaultBoneIndex], Bones);
            }

            Marshal.FreeHGlobal(dest.PickingVertices);
        }
Beispiel #5
0
        unsafe private void ProcessMesh(FLVER0.Mesh mesh, FlverSubmesh dest)
        {
            var factory = Scene.Renderer.Factory;

            dest.Material = GPUMaterials[mesh.MaterialIndex];

            //var MeshVertices = VerticesPool.Rent(mesh.VertexCount);
            var vSize        = dest.Material.VertexSize;
            var meshVertices = Marshal.AllocHGlobal(mesh.Vertices.Count * (int)vSize);

            dest.PickingVertices = Marshal.AllocHGlobal(mesh.Vertices.Count * sizeof(Vector3));
            var pvhandle = new Span <Vector3>(dest.PickingVertices.ToPointer(), mesh.Vertices.Count);

            if (dest.Material.LayoutType == MeshLayoutType.LayoutSky)
            {
                FillVerticesNormalOnly(mesh, pvhandle, meshVertices);
            }
            else if (dest.Material.LayoutType == MeshLayoutType.LayoutUV2)
            {
                FillVerticesUV2(mesh, pvhandle, meshVertices);
            }
            else
            {
                FillVerticesStandard(mesh, pvhandle, meshVertices);
            }

            dest.VertexCount = mesh.Vertices.Count;

            dest.MeshFacesets = new List <FlverSubmesh.FlverSubmeshFaceSet>();

            bool is32bit      = false;//FlverDeS.Version > 0x20005 && mesh.Vertices.Count > 65535;
            int  indicesTotal = 0;

            ushort[] fs16 = null;
            int[]    fs32 = null;

            int idxoffset = 0;

            if (mesh.VertexIndices.Count != 0)
            {
                var  indices    = mesh.Triangulate(FlverDeS.Version).ToArray();
                uint buffersize = (uint)indices.Length * (is32bit ? 4u : 2u);

                indicesTotal = indices.Length;
                if (is32bit)
                {
                    fs32 = new int[indicesTotal];
                }
                else
                {
                    fs16 = new ushort[indicesTotal];
                }

                var newFaceSet = new FlverSubmesh.FlverSubmeshFaceSet()
                {
                    BackfaceCulling = true,
                    IsTriangleStrip = false,
                    //IndexBuffer = factory.CreateBuffer(new BufferDescription(buffersize, BufferUsage.IndexBuffer)),
                    IndexOffset = idxoffset,

                    IndexCount          = indices.Length,
                    Is32Bit             = is32bit,
                    PickingIndicesCount = indices.Length,
                    //PickingIndices = Marshal.AllocHGlobal(indices.Length * 4),
                };
                fixed(void *iptr = indices)
                {
                    //Unsafe.CopyBlock(newFaceSet.PickingIndices.ToPointer(), iptr, (uint)indices.Length * 4);
                }

                if (is32bit)
                {
                    for (int i = 0; i < indices.Length; i++)
                    {
                        if (indices[i] == 0xFFFF && indices[i] > mesh.Vertices.Count)
                        {
                            fs32[newFaceSet.IndexOffset + i] = -1;
                        }
                        else
                        {
                            fs32[newFaceSet.IndexOffset + i] = indices[i];
                        }
                    }
                }
                else
                {
                    for (int i = 0; i < indices.Length; i++)
                    {
                        if (indices[i] == 0xFFFF && indices[i] > mesh.Vertices.Count)
                        {
                            fs16[newFaceSet.IndexOffset + i] = 0xFFFF;
                        }
                        else
                        {
                            fs16[newFaceSet.IndexOffset + i] = (ushort)indices[i];
                        }
                    }
                }

                dest.MeshFacesets.Add(newFaceSet);
            }

            dest.Bounds = BoundingBox.CreateFromPoints((Vector3 *)dest.PickingVertices.ToPointer(), dest.VertexCount, 12, Quaternion.Identity, Vector3.Zero, Vector3.One);

            uint vbuffersize = (uint)mesh.Vertices.Count * (uint)vSize;

            dest.GeomBuffer = Scene.Renderer.GeometryBufferAllocator.Allocate(vbuffersize, (uint)indicesTotal * (is32bit ? 4u : 2u), (int)vSize, 4, (h) =>
            {
                h.FillVBuffer(meshVertices, vSize * (uint)mesh.Vertices.Count, () =>
                {
                    Marshal.FreeHGlobal(meshVertices);
                });
                if (is32bit)
                {
                    h.FillIBuffer(fs32);
                }
                else
                {
                    h.FillIBuffer(fs16);
                }
            });

            if (CaptureMaterialLayouts)
            {
                lock (_matLayoutLock)
                {
                    if (!MaterialLayouts.ContainsKey(dest.Material.MaterialName))
                    {
                        MaterialLayouts.Add(dest.Material.MaterialName, Flver.BufferLayouts[mesh.LayoutIndex]);
                    }
                }
            }
        }
Beispiel #6
0
        public List <Vector4> SolveTangents(FlverSubmesh mesh,
                                            List <ushort> vertexIndices,
                                            List <Vector3> highQualityVertexNormals,
                                            List <Vector3> hqVertPositions,
                                            List <Vector2> hqVertUVs)
        {
            int triangleCount = vertexIndices.Count;

            int vertexCount = mesh.Vertices.Count;

            Vector3[] tan1 = new Vector3[vertexCount];
            Vector3[] tan2 = new Vector3[vertexCount];

            List <Vector4> tangentList = new List <Vector4>();

            for (int a = 0; a < vertexIndices.Count; a += 3)
            {
                try
                {
                    int i1 = vertexIndices[a];
                    int i2 = vertexIndices[a + 1];
                    int i3 = vertexIndices[a + 2];

                    if (i1 != i2 || i2 != i3)
                    {
                        Vector3 v1 = hqVertPositions[i1];
                        Vector3 v2 = hqVertPositions[i2];
                        Vector3 v3 = hqVertPositions[i3];

                        Vector2 w1 = new Vector2(hqVertUVs[i1].X, hqVertUVs[i1].Y);
                        Vector2 w2 = new Vector2(hqVertUVs[i2].X, hqVertUVs[i2].Y);
                        Vector2 w3 = new Vector2(hqVertUVs[i3].X, hqVertUVs[i3].Y);

                        float x1 = v2.X - v1.X;
                        float x2 = v3.X - v1.X;
                        float y1 = v2.Y - v1.Y;
                        float y2 = v3.Y - v1.Y;
                        float z1 = v2.Z - v1.Z;
                        float z2 = v3.Z - v1.Z;

                        float s1 = w2.X - w1.X;
                        float s2 = w3.X - w1.X;
                        float t1 = w2.Y - w1.Y;
                        float t2 = w3.Y - w1.Y;

                        float r = 1.0f / (s1 * t2 - s2 * t1);

                        Vector3 sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
                        Vector3 tdir = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);

                        tan1[i1] += sdir;
                        tan1[i2] += sdir;
                        tan1[i3] += sdir;

                        tan2[i1] += tdir;
                        tan2[i2] += tdir;
                        tan2[i3] += tdir;
                    }
                }
                catch (Exception ex)
                {
                    Importer.PrintError($"Exception encountered while solving mesh tangents:\n{ex}");
                    break;
                }
            }
            for (int i = 0; i < vertexCount; i++)
            {
                Vector3 n = highQualityVertexNormals[i];
                Vector3 t = tan1[i];

                float w = ((!(Vector3.Dot(Vector3.Cross(n, t), tan2[i]) < 0f)) ? 1 : (-1));

                //mesh.Vertices[i].BiTangent = new Vector4(Vector3.Normalize((t - n * Vector3.Dot(n, t))),
                //    (Vector3.Dot(Vector3.Cross(n, t), tan2[i]) < 0.0f) ? -1.0f : 1.0f);

                mesh.Vertices[i].BiTangent = new Vector4(Vector3.Normalize(t - n * Vector3.Dot(n, t)), w);

                tangentList.Add(new Vector4(Vector3.Normalize(t - n * Vector3.Dot(n, t)), w));
            }

            return(tangentList);
        }
Beispiel #7
0
        public static (int VertsFixed, int TotalSourceVerts) FixBodyPiece(FlverSubmesh mesh, string bodyPieceType, out string possibleError)
        {
            possibleError = null;
            if (!MaterialToEmbeddedFlverMap.ContainsKey(bodyPieceType))
            {
                possibleError = "Invalid body piece type: '{bodyPieceType}' in material name of this body part. Below is a list of valid types:" +
                                " -HD_M\n" +
                                " -BD_M\n" +
                                " -AM_M\n" +
                                " -LG_M\n" +
                                " -HD_F\n" +
                                " -BD_F\n" +
                                " -AM_F\n" +
                                " -LG_F\n" +
                                " -HD_M_Hollow\n" +
                                " -BD_M_Hollow\n" +
                                " -AM_M_Hollow\n" +
                                " -LG_M_Hollow\n" +
                                " -HD_F_Hollow\n" +
                                " -BD_F_Hollow\n" +
                                " -AM_F_Hollow\n" +
                                " -LG_F_Hollow\n";
                return(-1, -1);
            }

            var flverName = MaterialToEmbeddedFlverMap[bodyPieceType];
            var flver     = GetFlver(flverName);

            List <FlverVertex> possibleVertices = new List <FlverVertex>();

            foreach (var v in flver.Submeshes[0].Vertices)
            {
                possibleVertices.Add(v);
            }

            int numberOfVertsFixed = 0;
            int totalVerts         = possibleVertices.Count;

            foreach (var v in mesh.Vertices)
            {
                foreach (var possible in possibleVertices)
                {
                    if (CheckIfVertexMatches(v, possible))
                    {
                        v.Position  = possible.Position;
                        v.Normal    = possible.Normal;
                        v.BiTangent = possible.BiTangent;

                        string targetBoneNameA = flver.GetBoneFromIndex(possible.BoneIndices.A)?.Name;
                        string targetBoneNameB = flver.GetBoneFromIndex(possible.BoneIndices.B)?.Name;
                        string targetBoneNameC = flver.GetBoneFromIndex(possible.BoneIndices.C)?.Name;
                        string targetBoneNameD = flver.GetBoneFromIndex(possible.BoneIndices.D)?.Name;

                        v.BoneIndices.A = mesh.FindOrAddBoneIndex(targetBoneNameA);
                        v.BoneIndices.B = mesh.FindOrAddBoneIndex(targetBoneNameB);
                        v.BoneIndices.C = mesh.FindOrAddBoneIndex(targetBoneNameC);
                        v.BoneIndices.D = mesh.FindOrAddBoneIndex(targetBoneNameD);

                        v.BoneWeights = possible.BoneWeights;

                        numberOfVertsFixed++;

                        possibleVertices.Remove(possible);
                    }
                }
            }

            return(numberOfVertsFixed, totalVerts);
        }
Beispiel #8
0
        public static (int VertsFixed, int TotalSourceVerts) FixBodyPiece(FlverSubmesh mesh, string bodyPieceType, out string possibleError)
        {
            possibleError = null;
            if (!MaterialToEmbeddedFlverMap.ContainsKey(bodyPieceType))
            {
                possibleError = $"Invalid body piece type: '{bodyPieceType}' in material name of this body part. Below is a list of valid types:" +
                                " -HD_M\n" +
                                " -BD_M\n" +
                                " -AM_M\n" +
                                " -LG_M\n" +
                                " -HD_F\n" +
                                " -BD_F\n" +
                                " -AM_F\n" +
                                " -LG_F\n" +
                                " -HD_M_Hollow\n" +
                                " -BD_M_Hollow\n" +
                                " -AM_M_Hollow\n" +
                                " -LG_M_Hollow\n" +
                                " -HD_F_Hollow\n" +
                                " -BD_F_Hollow\n" +
                                " -AM_F_Hollow\n" +
                                " -LG_F_Hollow\n";
                return(-1, -1);
            }

            var flverName = MaterialToEmbeddedFlverMap[bodyPieceType];
            var flver     = GetFlver(flverName);

            List <FlverVertex> possibleVertices = new List <FlverVertex>();

            foreach (var v in flver.Submeshes[0].Vertices)
            {
                possibleVertices.Add(v);
            }

            int numberOfVertsFixed = 0;
            int totalVerts         = possibleVertices.Count;

            //List<FlverVertex> possibleVertsCheckedOff = new List<FlverVertex>();

            foreach (var v in mesh.Vertices)
            {
                //(FlverVertex Vert, float Dist) closestDistance = (null, float.MaxValue);

                FlverVertex closest = null;

                foreach (var possible in possibleVertices)
                {
                    //float dist = ((Vector3)(possible.Position - v.Position)).LengthSquared();

                    //if (dist < closestDistance.Dist)
                    //    closestDistance = (possible, dist);

                    if (CheckIfVertexMatches(v, possible))
                    {
                        closest = possible;

                        v.Position  = closest.Position;
                        v.Normal    = closest.Normal;
                        v.BiTangent = closest.BiTangent;

                        string targetBoneNameA = closest.BoneIndices.A >= 0 ? flver.GetBoneFromIndex(flver.Submeshes[0].BoneIndices[closest.BoneIndices.A])?.Name : null;
                        string targetBoneNameB = closest.BoneIndices.B >= 0 ? flver.GetBoneFromIndex(flver.Submeshes[0].BoneIndices[closest.BoneIndices.B])?.Name : null;
                        string targetBoneNameC = closest.BoneIndices.C >= 0 ? flver.GetBoneFromIndex(flver.Submeshes[0].BoneIndices[closest.BoneIndices.C])?.Name : null;
                        string targetBoneNameD = closest.BoneIndices.D >= 0 ? flver.GetBoneFromIndex(flver.Submeshes[0].BoneIndices[closest.BoneIndices.D])?.Name : null;

                        v.BoneIndices.A = mesh.FindOrAddBoneIndex(targetBoneNameA);
                        v.BoneIndices.B = mesh.FindOrAddBoneIndex(targetBoneNameB);
                        v.BoneIndices.C = mesh.FindOrAddBoneIndex(targetBoneNameC);
                        v.BoneIndices.D = mesh.FindOrAddBoneIndex(targetBoneNameD);

                        v.BoneWeights = closest.BoneWeights;

                        v.UVs = closest.UVs;

                        numberOfVertsFixed++;
                    }
                }



                //if (possibleVertsCheckedOff.Count > 0)
                //{
                //    foreach (var checkoff in possibleVertsCheckedOff)
                //        possibleVertices.Remove(checkoff);
                //    possibleVertsCheckedOff.Clear();
                //}
            }

            return(numberOfVertsFixed, totalVerts);
        }