示例#1
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));
         }
     }
 }
示例#2
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, List <PreloadedTextureData> preloadedTextures = null) : base(texcache, mat, preloadedTextures)
        {
            var matPackage = mat.Export.Parent.FullPath.ToLower();

            foreach (var textureEntry in mat.Textures)
            {
                var texObjectName = textureEntry.FullPath.ToLower();
                if (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;
                }
            }
        }
示例#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>
        protected ModelPreviewMaterial(PreviewTextureCache texcache, Unreal.Classes.MaterialInstanceConstant mat, 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 = ModelPreview.FindExternalAsset(import, texcache.cache.Select(x => x.TextureExport).ToList());
                        if (extAsset != null)
                        {
                            Textures.Add(textureEntry.FullPath, texcache.LoadTexture(extAsset));
                        }
                    }
                    else
                    {
                        Textures.Add(textureEntry.FullPath, texcache.LoadTexture(textureEntry as ExportEntry));
                    }
                }
            }
        }
示例#4
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;
         }
     }
 }
示例#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
            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));
            }
        }