Exemplo n.º 1
0
        /// <summary>
        /// Creates a preview of the given <see cref="Unreal.Classes.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, Unreal.Classes.StaticMesh m, PreviewTextureCache texcache)
        {
            // STEP 1: MESH
            List <Triangle>    triangles = new List <Triangle>();
            List <WorldVertex> vertices  = new List <WorldVertex>();

            // Gather all the vertex data
            // Only one LOD? odd but I guess that's just how it rolls.
            for (int i = 0; i < m.Mesh.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 uesd exactly once.
            // Note that this is based on the earlier implementstion which didn't take LODs into consideration, which is odd considering that both the hit testing and the skeletalmesh class do.
            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
            Materials = new Dictionary <string, ModelPreviewMaterial>();
            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 = new List <ModelPreviewSection>();

            foreach (Unreal.Classes.StaticMesh.Section section in m.Mesh.Mat.Lods[0].Sections)
            {
                sections.Add(new ModelPreviewSection(m.pcc.getObjectName(section.Name), (uint)section.FirstIdx1, (uint)section.NumFaces1));
            }
            LODs = new List <ModelPreviewLOD>();
            LODs.Add(new ModelPreviewLOD(new WorldMesh(Device, triangles, vertices), sections));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Creates a TexturedPreviewMaterial that renders as close to what the given <see cref="MaterialInstanceConstant"/> looks like as possible.
        /// </summary>
        /// <param name="texcache">The texture cache to request textures from.</param>
        /// <param name="mat">The material that this ModelPreviewMaterial will try to look like.</param>
        public TexturedPreviewMaterial(PreviewTextureCache texcache, MaterialInstanceConstant mat, PackageCache assetCache, List <PreloadedTextureData> preloadedTextures = null) : base(texcache, mat, assetCache, preloadedTextures)
        {
            string matPackage = null;

            if (mat.Export.Parent != null)
            {
                matPackage = mat.Export.Parent.FullPath.ToLower();
            }
            foreach (var textureEntry in mat.Textures)
            {
                var texObjectName = textureEntry.FullPath.ToLower();
                if ((matPackage == null || texObjectName.StartsWith(matPackage)) && texObjectName.Contains("diff"))
                {
                    // we have found the diffuse texture!
                    DiffuseTextureFullName = textureEntry.FullPath;
                    Debug.WriteLine("Diffuse texture of new material <" + Properties["Name"] + "> is " + DiffuseTextureFullName);
                    return;
                }
            }

            foreach (var textureEntry in mat.Textures)
            {
                var texObjectName = textureEntry.ObjectName.Name.ToLower();
                if (texObjectName.Contains("diff") || texObjectName.Contains("tex"))
                {
                    // we have found the diffuse texture!
                    DiffuseTextureFullName = textureEntry.FullPath;
                    Debug.WriteLine("Diffuse texture of new material <" + Properties["Name"] + "> is " + DiffuseTextureFullName);
                    return;
                }
            }
            foreach (var texparam in mat.Textures)
            {
                var texObjectName = texparam.ObjectName.Name.ToLower();

                if (texObjectName.Contains("detail"))
                {
                    // I guess a detail texture is good enough if we didn't return for a diffuse texture earlier...
                    DiffuseTextureFullName = texparam.FullPath;
                    Debug.WriteLine("Diffuse (Detail) texture of new material <" + Properties["Name"] + "> is " + DiffuseTextureFullName);
                    return;
                }
            }
            foreach (var texparam in mat.Textures)
            {
                var texObjectName = texparam.ObjectName.Name.ToLower();
                if (!texObjectName.Contains("norm") && !texObjectName.Contains("opac"))
                {
                    //Anything is better than nothing I suppose
                    DiffuseTextureFullName = texparam.FullPath;
                    Debug.WriteLine("Using first found texture (last resort)  of new material <" + Properties["Name"] + "> as diffuse: " + DiffuseTextureFullName);
                    return;
                }
            }
        }
Exemplo n.º 3
0
 /// <summary>
 /// Creates a ModelPreviewMaterial that renders as close to what the given <see cref="Unreal.Classes.MaterialInstanceConstant"/> looks like as possible.
 /// </summary>
 /// <param name="texcache">The texture cache to request textures from.</param>
 /// <param name="mat">The material that this ModelPreviewMaterial will try to look like.</param>
 public ModelPreviewMaterial(PreviewTextureCache texcache, Unreal.Classes.MaterialInstanceConstant mat)
 {
     Properties.Add("Name", mat.pcc.Exports[mat.index].ObjectName);
     foreach (Unreal.Classes.MaterialInstanceConstant.TextureParam texparam in mat.Textures)
     {
         if (texparam.TexIndex != 0)
         {
             Textures.Add(texparam.Desc, FindTexture(texcache, mat.pcc.getEntry(texparam.TexIndex).GetFullPath, mat.pcc.FileName));
         }
     }
 }
Exemplo n.º 4
0
        /// <summary>
        /// Creates a preview of a generic untextured mesh
        /// </summary>
        /// <param name="device"></param>
        /// <param name="mesh"></param>
        public ModelPreview(Device device, WorldMesh mesh, PreviewTextureCache texcache, PackageCache assetCache, PreloadedModelData preloadedData = null)
        {
            //Preloaded
            List <ModelPreviewSection> sections = new List <ModelPreviewSection>();

            if (preloadedData != null)
            {
                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);
                }
            }
            LODs.Add(new ModelPreviewLOD(mesh, sections));
        }
Exemplo n.º 5
0
        /// <summary>
        /// Creates a preview of the given <see cref="Unreal.Classes.SkeletalMesh"/>.
        /// </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, Unreal.Classes.SkeletalMesh m, PreviewTextureCache texcache)
        {
            // STEP 1: MATERIALS
            Materials = new Dictionary <string, ModelPreviewMaterial>();
            foreach (Unreal.Classes.MaterialInstanceConstant mat in m.MatInsts)
            {
                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 2: LODS
            LODs = new List <ModelPreviewLOD>();
            foreach (Unreal.Classes.SkeletalMesh.LODModelStruct lodmodel in m.LODModels)
            {
                // Vertices
                List <WorldVertex> vertices = new List <WorldVertex>();
                foreach (Unreal.Classes.SkeletalMesh.GPUSkinVertexStruct vertex in lodmodel.VertexBufferGPUSkin.Vertices)
                {
                    // NOTE: note the switched Y and Z coordinates. Unreal seems to think that Z is up.
                    vertices.Add(new WorldVertex(new Vector3(-vertex.Position.X, vertex.Position.Z, vertex.Position.Y), Vector3.Zero, new Vector2(HalfToFloat(vertex.U), HalfToFloat(vertex.V))));
                }
                // Triangles
                List <Triangle> triangles = new List <Triangle>();
                for (int i = 0; i < lodmodel.IndexBuffer.Indexes.Count; i += 3)
                {
                    triangles.Add(new Triangle(lodmodel.IndexBuffer.Indexes[i], lodmodel.IndexBuffer.Indexes[i + 1], lodmodel.IndexBuffer.Indexes[i + 2]));
                }
                WorldMesh mesh = new WorldMesh(Device, triangles, vertices);
                // Sections
                List <ModelPreviewSection> sections = new List <ModelPreviewSection>();
                foreach (Unreal.Classes.SkeletalMesh.SectionStruct section in lodmodel.Sections)
                {
                    if (section.MaterialIndex < Materials.Count)
                    {
                        sections.Add(new ModelPreviewSection(Materials.Keys.ElementAt(section.MaterialIndex), (uint)section.BaseIndex, (uint)section.NumTriangles));
                    }
                }
                LODs.Add(new ModelPreviewLOD(mesh, sections));
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Creates a ModelPreviewMaterial that renders as close to what the given <see cref="MaterialInstanceConstant"/> looks like as possible.
        /// </summary>
        /// <param name="texcache">The texture cache to request textures from.</param>
        /// <param name="mat">The material that this ModelPreviewMaterial will try to look like.</param>
        protected ModelPreviewMaterial(PreviewTextureCache texcache, MaterialInstanceConstant mat, PackageCache assetCache, List <PreloadedTextureData> preloadedTextures = null)
        {
            if (mat == null)
            {
                return;
            }
            Properties.Add("Name", mat.Export.ObjectName);
            foreach (var textureEntry in mat.Textures)
            {
                if (!Textures.ContainsKey(textureEntry.FullPath) && textureEntry.ClassName == "Texture2D")  //Apparently some assets are cubemaps, we don't want these.
                {
                    if (preloadedTextures != null)
                    {
                        var preloadedInfo = preloadedTextures.FirstOrDefault(x => x.MaterialExport == mat.Export && x.Mip.Export.ObjectName.Name == textureEntry.ObjectName.Name); //i don't like matching on object name but its export vs import here.
                        if (preloadedInfo != null)
                        {
                            Textures.Add(textureEntry.FullPath, texcache.LoadTexture(preloadedInfo.Mip.Export, preloadedInfo.Mip, preloadedInfo.decompressedTextureData));
                        }
                        else
                        {
                            Debug.WriteLine("Preloading error");
                        }
                        //if (textureEntry is ExportEntry texPort && preloadedMipInfo.Export != texPort) throw new Exception();
                        continue; //Don't further parse
                    }

                    if (textureEntry is ImportEntry import)
                    {
                        var extAsset = EntryImporter.ResolveImport(import, null, assetCache);
                        if (extAsset != null)
                        {
                            Textures.Add(textureEntry.FullPath, texcache.LoadTexture(extAsset));
                        }
                    }
                    else
                    {
                        Textures.Add(textureEntry.FullPath, texcache.LoadTexture(textureEntry as ExportEntry));
                    }
                }
            }
        }
Exemplo n.º 7
0
 /// <summary>
 /// Creates a TexturedPreviewMaterial that renders as close to what the given <see cref="Unreal.Classes.MaterialInstanceConstant"/> looks like as possible.
 /// </summary>
 /// <param name="texcache">The texture cache to request textures from.</param>
 /// <param name="mat">The material that this ModelPreviewMaterial will try to look like.</param>
 public TexturedPreviewMaterial(PreviewTextureCache texcache, Unreal.Classes.MaterialInstanceConstant mat) : base(texcache, mat)
 {
     foreach (Unreal.Classes.MaterialInstanceConstant.TextureParam texparam in mat.Textures)
     {
         if (texparam.Desc.ToLower().Contains("diff") || texparam.Desc.ToLower().Contains("tex"))
         {
             // we have found the diffuse texture!
             DiffuseTextureFullName = texparam.Desc;
             //Console.WriteLine("Diffuse texture of new material <" + Properties["Name"] + "> is " + DiffuseTextureFullName);
             return;
         }
     }
     foreach (Unreal.Classes.MaterialInstanceConstant.TextureParam texparam in mat.Textures)
     {
         if (texparam.Desc.ToLower().Contains("detail"))
         {
             // I guess a detail texture is good enough if we didn't return for a diffuse texture earlier...
             DiffuseTextureFullName = texparam.Desc;
             //Console.WriteLine("Diffuse texture of new material <" + Properties["Name"] + "> is " + DiffuseTextureFullName);
             return;
         }
     }
 }
Exemplo n.º 8
0
        /// <summary>
        /// Creates a preview of the given <see cref="SkeletalMesh"/>.
        /// </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, SkeletalMesh m, PreviewTextureCache texcache, PackageCache assetCache, PreloadedModelData preloadedData = null)
        {
            // STEP 1: MATERIALS
            if (preloadedData == null)
            {
                for (int i = 0; i < m.Materials.Length; i++)
                {
                    UIndex materialUIndex        = m.Materials[i];
                    MaterialInstanceConstant mat = null;
                    if (materialUIndex.value > 0)
                    {
                        mat = new MaterialInstanceConstant(m.Export.FileRef.GetUExport(materialUIndex.value));
                    }
                    else if (materialUIndex.value < 0)
                    {
                        // The material instance is an import!
                        ImportEntry matImport     = m.Export.FileRef.GetImport(materialUIndex.value);
                        var         externalAsset = EntryImporter.ResolveImport(matImport, null, assetCache);
                        if (externalAsset != null)
                        {
                            mat = new MaterialInstanceConstant(externalAsset);
                        }
                    }

                    if (mat != 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, mat, assetCache);
                        AddMaterial(material.Properties["Name"], material);
                    }
                }
            }
            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);
                }
            }

            // STEP 2: LODS
            foreach (var lodmodel in m.LODModels)
            {
                // Vertices
                List <WorldVertex> vertices = new List <WorldVertex>(m.Export.Game == MEGame.ME1 ? lodmodel.ME1VertexBufferGPUSkin.Length : lodmodel.VertexBufferGPUSkin.VertexData.Length);
                if (m.Export.Game == MEGame.ME1)
                {
                    foreach (var vertex in lodmodel.ME1VertexBufferGPUSkin)
                    {
                        vertices.Add(new WorldVertex(new Vector3(-vertex.Position.X, vertex.Position.Z, vertex.Position.Y), Vector3.Zero, new Vector2(vertex.UV.X, vertex.UV.Y)));
                    }
                }
                else
                {
                    foreach (var vertex in lodmodel.VertexBufferGPUSkin.VertexData)
                    {
                        vertices.Add(new WorldVertex(new Vector3(-vertex.Position.X, vertex.Position.Z, vertex.Position.Y), Vector3.Zero, new Vector2(vertex.UV.X, vertex.UV.Y)));
                    }
                }
                // Triangles
                List <Triangle> triangles = new List <Triangle>(lodmodel.IndexBuffer.Length / 3);
                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]));
                }
                WorldMesh mesh = new WorldMesh(Device, triangles, vertices);
                // Sections
                List <ModelPreviewSection> sections = new List <ModelPreviewSection>();
                foreach (var section in lodmodel.Sections)
                {
                    if (section.MaterialIndex < Materials.Count)
                    {
                        sections.Add(new ModelPreviewSection(Materials.Keys.ElementAt(section.MaterialIndex), section.BaseIndex, (uint)section.NumTriangles));
                    }
                }
                LODs.Add(new ModelPreviewLOD(mesh, sections));
            }
        }
Exemplo n.º 9
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));
        }
Exemplo n.º 10
0
        /// <summary>
        /// Creates a preview of the given <see cref="Unreal.Classes.SkeletalMesh"/>.
        /// </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, Unreal.Classes.SkeletalMesh m, PreviewTextureCache texcache)
        {
            // STEP 1: MATERIALS
            for (int i = 0; i < m.Materials.Count; i++)
            {
                Unreal.Classes.MaterialInstanceConstant mat = m.MatInsts[i];
                if (mat == null && m.Materials[i] < 0)
                {
                    // The material instance is an import!
                    ImportEntry matImport     = m.Export.FileRef.GetImport(m.Materials[i]);
                    var         externalAsset = FindExternalAsset(matImport, texcache.cache.Select(x => x.TextureExport).ToList());
                    if (externalAsset != null)
                    {
                        mat = new MaterialInstanceConstant(externalAsset);
                    }
                }

                if (mat != 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, mat);
                    AddMaterial(material.Properties["Name"], material);
                }
            }

            // STEP 2: LODS
            foreach (Unreal.Classes.SkeletalMesh.LODModelStruct lodmodel in m.LODModels)
            {
                // Vertices
                List <WorldVertex> vertices = new List <WorldVertex>();
                if (m.Export.Game == MEGame.ME1)
                {
                    foreach (Unreal.Classes.SkeletalMesh.GPUSkinVertexStruct vertex in lodmodel.VertexBufferGPUSkin.Vertices)
                    {
                        vertices.Add(new WorldVertex(new Vector3(-vertex.Position.X, vertex.Position.Z, vertex.Position.Y), Vector3.Zero, new Vector2(vertex.UFullPrecision, vertex.VFullPrecision)));
                    }
                }
                else
                {
                    foreach (Unreal.Classes.SkeletalMesh.GPUSkinVertexStruct vertex in lodmodel.VertexBufferGPUSkin.Vertices)
                    {
                        // NOTE: note the switched Y and Z coordinates. Unreal seems to think that Z is up.
                        vertices.Add(new WorldVertex(new Vector3(-vertex.Position.X, vertex.Position.Z, vertex.Position.Y), Vector3.Zero, new Vector2(HalfToFloat(vertex.U), HalfToFloat(vertex.V))));
                    }
                }
                // Triangles
                List <Triangle> triangles = new List <Triangle>();
                for (int i = 0; i < lodmodel.IndexBuffer.Indexes.Count; i += 3)
                {
                    triangles.Add(new Triangle(lodmodel.IndexBuffer.Indexes[i], lodmodel.IndexBuffer.Indexes[i + 1], lodmodel.IndexBuffer.Indexes[i + 2]));
                }
                WorldMesh mesh = new WorldMesh(Device, triangles, vertices);
                // Sections
                List <ModelPreviewSection> sections = new List <ModelPreviewSection>();
                foreach (Unreal.Classes.SkeletalMesh.SectionStruct section in lodmodel.Sections)
                {
                    if (section.MaterialIndex < Materials.Count)
                    {
                        sections.Add(new ModelPreviewSection(Materials.Keys.ElementAt(section.MaterialIndex), (uint)section.BaseIndex, (uint)section.NumTriangles));
                    }
                }
                LODs.Add(new ModelPreviewLOD(mesh, sections));
            }
        }
        public void LoadDirect3D(SharpDX.Direct3D11.Device device)
        {
            // Set up description of swap chain

            /*SwapChainDescription scd = new SwapChainDescription();
             * scd.BufferCount = 1;
             * scd.ModeDescription = new ModeDescription(Width, Height, new Rational(60, 1), Format.B8G8R8A8_UNorm);
             * scd.Usage = Usage.RenderTargetOutput;
             * scd.OutputHandle = Handle;
             * scd.SampleDescription.Count = 1;
             * scd.SampleDescription.Quality = 0;
             * scd.IsWindowed = true;
             * scd.ModeDescription.Width = Width;
             * scd.ModeDescription.Height = Height;*/

            // Create device and swap chain according to the description above
            //SharpDX.Direct3D11.Device d;
            //SwapChain sc;
            //DeviceCreationFlags flags = DeviceCreationFlags.BgraSupport | DeviceCreationFlags.SingleThreaded;
#if DEBUG
            //flags |= DeviceCreationFlags.Debug;
#endif
            //SharpDX.Direct3D11.Device.CreateWithSwapChain(DriverType.Hardware, flags, scd, out d, out sc);
            //this.SwapChain = sc; // we have to use these temp variables
            //this.Device = new SharpDX.Direct3D11.Device(DriverType.Hardware, flags);
            //this.Device = d; // because properties can't be passed as out parameters. =(

            // Set up the rendering context and buffers and stuff
            this.Device      = device;
            ImmediateContext = Device.ImmediateContext;
            //BuildBuffers();

            // Build a custom rasterizer state that doesn't cull backfaces
            RasterizerStateDescription frs = new RasterizerStateDescription();
            frs.CullMode        = CullMode.None;
            frs.FillMode        = FillMode.Solid;
            FillRasterizerState = new RasterizerState(Device, frs);
            ImmediateContext.Rasterizer.State = FillRasterizerState;
            // Build a custom rasterizer state for wireframe drawing
            RasterizerStateDescription wrs = new RasterizerStateDescription();
            wrs.CullMode = CullMode.None;
            wrs.FillMode = FillMode.Wireframe;
            wrs.IsAntialiasedLineEnabled = false;
            wrs.DepthBias            = -10;
            WireframeRasterizerState = new RasterizerState(Device, wrs);

            // Set texture sampler state
            SamplerStateDescription ssd = new SamplerStateDescription();
            ssd.AddressU          = TextureAddressMode.Wrap;
            ssd.AddressV          = TextureAddressMode.Wrap;
            ssd.AddressW          = TextureAddressMode.Wrap;
            ssd.Filter            = Filter.MinMagMipLinear;
            ssd.MaximumAnisotropy = 1;
            SampleState           = new SamplerState(Device, ssd);
            ImmediateContext.PixelShader.SetSampler(0, SampleState);

            // Load the default texture
            System.Drawing.Bitmap deftex = new System.Drawing.Bitmap(System.Environment.CurrentDirectory + "\\exec\\Default.bmp");
            DefaultTexture = LoadTexture(deftex);
            deftex.Dispose();
            DefaultTextureView = new ShaderResourceView(Device, DefaultTexture);

            // Load the default position-texture shader
            DefaultEffect = new Effect <WorldConstants, WorldVertex>(Device, Properties.Resources.StandardShader);

            TextureCache = new PreviewTextureCache(Device);
        }
Exemplo n.º 12
0
        private PreviewTextureCache.PreviewTextureEntry FindTexture(PreviewTextureCache texcache, string FullTextureName, string ImportPCC)
        {
            string importfiledir  = System.IO.Path.GetDirectoryName(ImportPCC).ToLower();
            string importfilename = System.IO.Path.GetFileName(ImportPCC).ToLower();
            string pccpath        = "";
            int    id             = 0;

            // First, check the pcc that contains the material
            using (ME3Package pcc = MEPackageHandler.OpenME3Package(ImportPCC))
            {
                foreach (IExportEntry exp in pcc.Exports)
                {
                    if (exp.GetFullPath == FullTextureName && exp.ClassName == "Texture2D")
                    {
                        pccpath = ImportPCC;
                        id      = exp.Index;
                        break;
                    }
                }
            }
            // Next, split the filename by underscores
            string[] parts = System.IO.Path.GetFileNameWithoutExtension(importfilename).Split('_');
            if (pccpath == "" && (importfilename.StartsWith("bioa") || importfilename.StartsWith("biod")))
            {
                // Maybe go for the one with one less segment? ex. for input BioA_Nor_201CIC.pcc, look in BioA_Nor.pcc
                if (parts.Length == 3)
                {
                    string filename = importfiledir + "\\" + parts[0] + "_" + parts[1] + ".pcc";
                    if (System.IO.File.Exists(filename))
                    {
                        using (ME3Package pcc = MEPackageHandler.OpenME3Package(filename))
                        {
                            foreach (IExportEntry exp in pcc.Exports)
                            {
                                if (exp.GetFullPath == FullTextureName && exp.ClassName == "Texture2D")
                                {
                                    pccpath = importfiledir + "\\" + parts[0] + "_" + parts[1] + ".pcc";
                                    id      = exp.Index;
                                    break;
                                }
                            }
                        }
                    }
                }
                // Now go for the BioP one.
                if (pccpath == "" && parts.Length >= 2)
                {
                    string filename = importfiledir + "\\" + "BioP" + "_" + parts[1] + ".pcc";
                    if (System.IO.File.Exists(filename))
                    {
                        using (ME3Package pcc = MEPackageHandler.OpenME3Package(filename))
                        {
                            foreach (IExportEntry exp in pcc.Exports)
                            {
                                if (exp.GetFullPath == FullTextureName && exp.ClassName == "Texture2D")
                                {
                                    pccpath = importfiledir + "\\" + "BioP" + "_" + parts[1] + ".pcc";
                                    id      = exp.Index;
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            if (id > 0)
            {
                return(texcache.LoadTexture(pccpath, id));
            }
            else
            {
                Console.WriteLine("[TEXLOAD]: Could not find texture \"" + FullTextureName + "\", imported in \"" + ImportPCC + "\".");
                return(null);
            }
        }