Ejemplo n.º 1
0
        /// <summary>
        /// Creates a preview of the given <see cref="StaticMesh"/>.
        /// </summary>
        /// <param name="Device">The Direct3D device to use for buffer creation.</param>
        /// <param name="m">The mesh to generate a preview for.</param>
        /// <param name="texcache">The texture cache for loading textures.</param>
        public ModelPreview(Device Device, StaticMesh m, int selectedLOD, PreviewTextureCache texcache, PackageCache assetCache, PreloadedModelData preloadedData = null)
        {
            if (selectedLOD < 0)  //PREVIEW BUG WORKAROUND
            {
                return;
            }

            // STEP 1: MESH
            var                lodModel  = m.LODModels[selectedLOD];
            List <Triangle>    triangles = new List <Triangle>(lodModel.IndexBuffer.Length / 3);
            List <WorldVertex> vertices  = new List <WorldVertex>((int)lodModel.NumVertices);

            // Gather all the vertex data
            // Only one LOD? odd but I guess that's just how it rolls.

            for (int i = 0; i < lodModel.NumVertices; i++)
            {
                var v = lodModel.PositionVertexBuffer.VertexData[i];
                if (lodModel.VertexBuffer.bUseFullPrecisionUVs)
                {
                    var uvVector = lodModel.VertexBuffer.VertexData[i].FullPrecisionUVs;
                    //SharpDX takes items differently than unreal.
                    vertices.Add(new Scene3D.WorldVertex(new Vector3(-v.X, v.Z, v.Y), Vector3.Zero, new Vector2(uvVector[0].X, uvVector[0].Y)));
                }
                else
                {
                    var uvVector = lodModel.VertexBuffer.VertexData[i].HalfPrecisionUVs;
                    //SharpDX takes items differently than unreal.
                    vertices.Add(new Scene3D.WorldVertex(new Vector3(-v.X, v.Z, v.Y), Vector3.Zero, new Vector2(uvVector[0].X, uvVector[0].Y)));
                }
            }

            //OLD CODE
            //for (int i = 0; i < m.L.Vertices.Points.Count; i++)
            //{
            //    // Note the reversal of the Z and Y coordinates. Unreal seems to think that Z should be up.
            //    vertices.Add(new Scene3D.WorldVertex(new SharpDX.Vector3(-m.Mesh.Vertices.Points[i].X, m.Mesh.Vertices.Points[i].Z, m.Mesh.Vertices.Points[i].Y), SharpDX.Vector3.Zero, new SharpDX.Vector2(m.Mesh.Edges.UVSet[i].UVs[0].X, m.Mesh.Edges.UVSet[i].UVs[0].Y)));
            //}

            // Sometimes there might not be an index buffer.
            // If there is one, use that.
            // Otherwise, assume that each vertex is used exactly once.
            // Note that this is based on the earlier implementation which didn't take LODs into consideration, which is odd considering that both the hit testing and the skeletalmesh class do.
            if (lodModel.IndexBuffer.Length > 0)
            {
                // Hey, we have indices all set up for us. How considerate.
                for (int i = 0; i < lodModel.IndexBuffer.Length; i += 3)
                {
                    triangles.Add(new Triangle(lodModel.IndexBuffer[i], lodModel.IndexBuffer[i + 1], lodModel.IndexBuffer[i + 2]));
                }
            }
            else
            {
                // Gather all the vertex data from the raw triangles, not the Mesh.Vertices.Point list.
                if (m.Export.Game <= MEGame.ME2)
                {
                    var kdop = m.kDOPTreeME1ME2;
                    for (int i = 0; i < kdop.Triangles.Length; i++)
                    {
                        triangles.Add(new Triangle(kdop.Triangles[i].Vertex1, kdop.Triangles[i].Vertex2, kdop.Triangles[i].Vertex3));
                    }
                }
                else
                {
                    var kdop = m.kDOPTreeME3UDK;
                    for (int i = 0; i < kdop.Triangles.Length; i++)
                    {
                        triangles.Add(new Triangle(kdop.Triangles[i].Vertex1, kdop.Triangles[i].Vertex2, kdop.Triangles[i].Vertex3));
                    }
                }
            }



            /*
             * if (m.Mesh.IdxBuf.Indexes != null && m.Mesh.IdxBuf.Indexes.Count > 0)
             * {
             *  // Hey, we have indices all set up for us. How considerate.
             *  for (int i = 0; i < m.Mesh.IdxBuf.Indexes.Count; i += 3)
             *  {
             *      triangles.Add(new Triangle(m.Mesh.IdxBuf.Indexes[i], m.Mesh.IdxBuf.Indexes[i + 1], m.Mesh.IdxBuf.Indexes[i + 2]));
             *  }
             * }
             * else
             * {
             *  // Gather all the vertex data from the raw triangles, not the Mesh.Vertices.Point list.
             *  for (int i = 0; i < m.Mesh.RawTris.RawTriangles.Count; i++)
             *  {
             *      triangles.Add(new Triangle((uint)m.Mesh.RawTris.RawTriangles[i].v0, (uint)m.Mesh.RawTris.RawTriangles[i].v1, (uint)m.Mesh.RawTris.RawTriangles[i].v2));
             *  }
             * }*/


            //OLD CODE

            /* if (m.Mesh.IdxBuf.Indexes != null && m.Mesh.IdxBuf.Indexes.Count > 0)
             *          {
             *              // Hey, we have indices all set up for us. How considerate.
             *              for (int i = 0; i < m.Mesh.IdxBuf.Indexes.Count; i += 3)
             *              {
             *                  triangles.Add(new Triangle(m.Mesh.IdxBuf.Indexes[i], m.Mesh.IdxBuf.Indexes[i + 1], m.Mesh.IdxBuf.Indexes[i + 2]));
             *              }
             *          }
             *          else
             *          {
             *              // Gather all the vertex data from the raw triangles, not the Mesh.Vertices.Point list.
             *              for (int i = 0; i < m.Mesh.RawTris.RawTriangles.Count; i++)
             *              {
             *                  triangles.Add(new Triangle((uint)m.Mesh.RawTris.RawTriangles[i].v0, (uint)m.Mesh.RawTris.RawTriangles[i].v1, (uint)m.Mesh.RawTris.RawTriangles[i].v2));
             *              }
             *          }*/

            // STEP 2: MATERIALS
            //foreach (var v in lodModel.Elements)


            //foreach (Unreal.Classes.MaterialInstanceConstant mat in m.Mesh.Mat.MatInst)
            //{
            //    ModelPreviewMaterial material;
            //    // TODO: pick what material class best fits based on what properties the
            //    // MaterialInstanceConstant mat has.
            //    // For now, just use the default material.
            //    material = new TexturedPreviewMaterial(texcache, mat);
            //    AddMaterial(material.Properties["Name"], material);
            //}

            // STEP 3: SECTIONS
            List <ModelPreviewSection> sections = preloadedData != null ? preloadedData.sections : null;
            List <IMEPackage>          assetLookupPackagesToDispose = new List <IMEPackage>();

            //This section exists for Meshplorer Winforms. WPF version preloads this in a background thread to improve performance
            if (sections == null)
            {
                sections = new List <ModelPreviewSection>();
                foreach (var section in lodModel.Elements)
                {
                    if (section.Material.value > 0)
                    {
                        ModelPreviewMaterial material;
                        // TODO: pick what material class best fits based on what properties the
                        // MaterialInstanceConstant mat has.
                        // For now, just use the default material.
                        ExportEntry entry = m.Export.FileRef.GetUExport(section.Material.value);
                        material = new TexturedPreviewMaterial(texcache, new MaterialInstanceConstant(entry), assetCache);
                        AddMaterial(material.Properties["Name"], material);
                    }
                    else if (section.Material.value < 0)
                    {
                        var extMaterialExport = FindExternalAsset(m.Export.FileRef.GetImport(section.Material.value), texcache.cache.Select(x => x.TextureExport).ToList(), assetLookupPackagesToDispose);
                        if (extMaterialExport != null)
                        {
                            ModelPreviewMaterial material;
                            // TODO: pick what material class best fits based on what properties the
                            // MaterialInstanceConstant mat has.
                            // For now, just use the default material.
                            material = new TexturedPreviewMaterial(texcache, new MaterialInstanceConstant(extMaterialExport), assetCache);
                            AddMaterial(material.Properties["Name"], material);
                        }
                        else
                        {
                            Debug.WriteLine("Could not find import material from section.");
                            Debug.WriteLine("Import material: " + m.Export.FileRef.GetEntryString(section.Material.value));
                        }
                    }

                    sections.Add(new ModelPreviewSection(m.Export.FileRef.getObjectName(section.Material.value), section.FirstIndex, section.NumTriangles));
                }
            }
            else
            {
                //Preloaded
                sections = preloadedData.sections;
                var uniqueMaterials = preloadedData.texturePreviewMaterials.Select(x => x.MaterialExport).Distinct();
                foreach (var mat in uniqueMaterials)
                {
                    var material = new TexturedPreviewMaterial(texcache, new MaterialInstanceConstant(mat), assetCache, preloadedData.texturePreviewMaterials);
                    AddMaterial(mat.ObjectName.Name, material);
                }
            }

            foreach (var package in assetLookupPackagesToDispose)
            {
                package?.Dispose(); //Release
            }
            //List<ModelPreviewSection> sections = new List<ModelPreviewSection>();
            //foreach (var section in lodModel.Elements)
            //{
            //    sections.Add(new ModelPreviewSection(m.Export.FileRef.getObjectName(section.Material.value), section.FirstIndex, section.NumTriangles));
            //}
            LODs.Add(new ModelPreviewLOD(new WorldMesh(Device, triangles, vertices), sections));
        }
Ejemplo n.º 2
0
        public static StaticMesh ConvertToME3StaticMesh(this SkeletalMesh skeletalMesh)
        {
            StaticLODModel lodModel    = skeletalMesh.LODModels[0];
            uint           numVertices = lodModel.NumVertices;
            var            stm         = new StaticMesh
            {
                Bounds    = skeletalMesh.Bounds,
                BodySetup = new UIndex(0),
                LODModels = new[] { new StaticMeshRenderData
                                    {
                                        IndexBuffer                 = lodModel.IndexBuffer.TypedClone(),
                                        NumVertices                 = numVertices,
                                        Edges                       = new MeshEdge[0],
                                        RawTriangles                = new StaticMeshTriangle[0],
                                        ColorVertexBuffer           = new ColorVertexBuffer(),
                                        ShadowTriangleDoubleSided   = new byte[0],
                                        WireframeIndexBuffer        = new ushort[0],
                                        ShadowExtrusionVertexBuffer = new ExtrusionVertexBuffer
                                        {
                                            Stride     = 4,
                                            VertexData = new float[0]
                                        },
                                        PositionVertexBuffer = new PositionVertexBuffer
                                        {
                                            NumVertices = numVertices,
                                            Stride      = 12,
                                            VertexData  = new Vector3[numVertices]
                                        },
                                        VertexBuffer = new StaticMeshVertexBuffer
                                        {
                                            bUseFullPrecisionUVs = false,
                                            NumTexCoords         = 1,
                                            NumVertices          = numVertices,
                                            VertexData           = new StaticMeshVertexBuffer.StaticMeshFullVertex[numVertices]
                                        },
                                        Elements = lodModel.Sections.Select(sec =>
                        {
                            var indices = lodModel.IndexBuffer.Skip((int)sec.BaseIndex).Take(sec.NumTriangles * 3).ToList();
                            return(new StaticMeshElement
                            {
                                bEnableShadowCasting = true,
                                EnableCollision = true,
                                OldEnableCollision = true,
                                FirstIndex = sec.BaseIndex,
                                NumTriangles = (uint)sec.NumTriangles,
                                MaterialIndex = sec.MaterialIndex,
                                Material = skeletalMesh.Materials[sec.MaterialIndex],
                                Fragments = new FragmentRange[0],
                                MinVertexIndex = indices.Min(),
                                MaxVertexIndex = indices.Max()
                            });
                        }).ToArray()
                                    } },
                InternalVersion = 18,
                LightingGuid    = Guid.NewGuid()
            };

            Vector3[] posVertData = stm.LODModels[0].PositionVertexBuffer.VertexData;
            StaticMeshVertexBuffer.StaticMeshFullVertex[] stmVertData = stm.LODModels[0].VertexBuffer.VertexData;
            if (lodModel.ME1VertexBufferGPUSkin != null)
            {
                for (int i = 0; i < lodModel.ME1VertexBufferGPUSkin.Length; i++)
                {
                    SoftSkinVertex vert = lodModel.ME1VertexBufferGPUSkin[i];
                    posVertData[i] = vert.Position;
                    stmVertData[i] = new StaticMeshVertexBuffer.StaticMeshFullVertex
                    {
                        HalfPrecisionUVs = new Vector2DHalf[] { vert.UV },
                        TangentX         = vert.TangentX,
                        TangentZ         = vert.TangentZ
                    };
                }
            }
            else
            {
                for (int i = 0; i < lodModel.VertexBufferGPUSkin.VertexData.Length; i++)
                {
                    GPUSkinVertex vert = lodModel.VertexBufferGPUSkin.VertexData[i];
                    posVertData[i] = vert.Position;
                    stmVertData[i] = new StaticMeshVertexBuffer.StaticMeshFullVertex
                    {
                        HalfPrecisionUVs = new[] { vert.UV },
                        TangentX         = vert.TangentX,
                        TangentZ         = vert.TangentZ
                    };
                }
            }
            var tris = new kDOPCollisionTriangle[lodModel.IndexBuffer.Length / 3];

            for (int i = 0, elIdx = 0, triCount = 0; i < lodModel.IndexBuffer.Length; i += 3, ++triCount)
            {
                if (triCount > lodModel.Sections[elIdx].NumTriangles)
                {
                    triCount = 0;
                    ++elIdx;
                }
                tris[i / 3] = new kDOPCollisionTriangle(lodModel.IndexBuffer[i], lodModel.IndexBuffer[i + 1], lodModel.IndexBuffer[i + 2],
                                                        lodModel.Sections[elIdx].MaterialIndex);
            }

            stm.kDOPTreeME3UDK = KDOPTreeBuilder.ToCompact(tris, stm.LODModels[0].PositionVertexBuffer.VertexData);

            return(stm);
        }