diff --git a/FModel/ViewModels/ModelViewerViewModel.cs b/FModel/ViewModels/ModelViewerViewModel.cs index ca1b1608..1db6baa7 100644 --- a/FModel/ViewModels/ModelViewerViewModel.cs +++ b/FModel/ViewModels/ModelViewerViewModel.cs @@ -36,7 +36,6 @@ public class ModelViewerViewModel : ViewModel { private ThreadWorkerViewModel _threadWorkerView => ApplicationService.ThreadWorkerView; - #region BINDINGS private EffectsManager _effectManager; public EffectsManager EffectManager { @@ -71,7 +70,6 @@ public bool AppendMode public bool CanAppend => SelectedModel != null; public TextureModel HDRi { get; private set; } - #endregion private readonly FGame _game; private readonly int[] _facesIndex = { 1, 0, 2 }; @@ -113,18 +111,23 @@ public async Task LoadExport(UObject export) _loadedModels.Add(p); } - bool valid = false; await _threadWorkerView.Begin(_ => { - valid = export switch + switch (export) { - UStaticMesh st => TryLoadStaticMesh(st, p), - USkeletalMesh sk => TryLoadSkeletalMesh(sk, p), - UMaterialInstance mi => TryLoadMaterialInstance(mi, p), - _ => throw new ArgumentOutOfRangeException(nameof(export)) - }; + case UStaticMesh st: + LoadStaticMesh(st, p); + break; + case USkeletalMesh sk: + LoadSkeletalMesh(sk, p); + break; + case UMaterialInstance mi: + LoadMaterialInstance(mi, p); + break; + default: + throw new ArgumentOutOfRangeException(nameof(export)); + } }); - if (!valid) return; SelectedModel = p; Cam.UpDirection = new Vector3D(0, 1, 0); @@ -166,20 +169,7 @@ public void MaterialColorToggle() public void DiffuseOnlyToggle() { if (SelectedModel == null) return; - foreach (var g in SelectedModel.Group3d) - { - if (g is not MeshGeometryModel3D { Material: PBRMaterial mat }) - continue; - - //mat.RenderAmbientOcclusionMap = !mat.RenderAmbientOcclusionMap; - mat.RenderDisplacementMap = !mat.RenderDisplacementMap; - //mat.RenderEmissiveMap = !mat.RenderEmissiveMap; - mat.RenderEnvironmentMap = !mat.RenderEnvironmentMap; - mat.RenderIrradianceMap = !mat.RenderIrradianceMap; - mat.RenderRoughnessMetallicMap = !mat.RenderRoughnessMetallicMap; - mat.RenderShadowMap = !mat.RenderShadowMap; - mat.RenderNormalMap = !mat.RenderNormalMap; - } + SelectedModel.ShowDiffuseOnly = !SelectedModel.ShowDiffuseOnly; } public void FocusOnSelectedMesh() @@ -225,10 +215,10 @@ public async Task TryChangeSelectedMaterial(UMaterialInstance materialInst if (SelectedModel is not { } model || model.SelectedGeometry is null) return false; - PBRMaterial m = null; + CustomPBRMaterial m = null; await _threadWorkerView.Begin(_ => { - var (material, _, _) = LoadMaterial(materialInstance); + var (material, _, _) = LoadMaterial(materialInstance, B(0)); m = material; }); @@ -238,14 +228,14 @@ await _threadWorkerView.Begin(_ => } #endregion - private bool TryLoadMaterialInstance(UMaterialInstance materialInstance, ModelAndCam cam) + private void LoadMaterialInstance(UMaterialInstance materialInstance, ModelAndCam cam) { var builder = new MeshBuilder(); builder.AddSphere(Vector3.Zero, 10); cam.TriangleCount = 1984; // no need to count SetupCameraAndAxis(new FBox(new FVector(-11), new FVector(11)), cam); - var (m, isRendering, isTransparent) = LoadMaterial(materialInstance); + var (m, isRendering, isTransparent) = LoadMaterial(materialInstance, B(0)); Application.Current.Dispatcher.Invoke(() => { @@ -256,14 +246,13 @@ private bool TryLoadMaterialInstance(UMaterialInstance materialInstance, ModelAn Material = m, IsTransparent = isTransparent, IsRendering = isRendering }); }); - return true; } - private bool TryLoadStaticMesh(UStaticMesh mesh, ModelAndCam cam) + private void LoadStaticMesh(UStaticMesh mesh, ModelAndCam cam) { if (!mesh.TryConvert(out var convertedMesh) || convertedMesh.LODs.Count <= 0) { - return false; + return; } SetupCameraAndAxis(convertedMesh.BoundingBox, cam); @@ -273,15 +262,13 @@ private bool TryLoadStaticMesh(UStaticMesh mesh, ModelAndCam cam) PushLod(lod.Sections.Value, lod.Verts, lod.Indices.Value, cam); break; } - - return true; } - private bool TryLoadSkeletalMesh(USkeletalMesh mesh, ModelAndCam cam) + private void LoadSkeletalMesh(USkeletalMesh mesh, ModelAndCam cam) { if (!mesh.TryConvert(out var convertedMesh) || convertedMesh.LODs.Count <= 0) { - return false; + return; } SetupCameraAndAxis(convertedMesh.BoundingBox, cam); @@ -291,8 +278,6 @@ private bool TryLoadSkeletalMesh(USkeletalMesh mesh, ModelAndCam cam) PushLod(lod.Sections.Value, lod.Verts, lod.Indices.Value, cam); break; } - - return true; } private void PushLod(CMeshSection[] sections, CMeshVertex[] verts, FRawStaticIndexBuffer indices, ModelAndCam cam) @@ -312,8 +297,8 @@ private void PushLod(CMeshSection[] sections, CMeshVertex[] verts, FRawStaticInd var p = new Vector3(vert.Position.X, vert.Position.Z, vert.Position.Y); // up direction is Y var n = new Vector3(vert.Normal.X, vert.Normal.Z, vert.Normal.Y); n.Normalize(); - var uv = new Vector2(vert.UV.U, vert.UV.V); - builder.AddNode(p, n, uv); + + builder.AddNode(p, n, new Vector2(vert.UV.U, vert.UV.V)); builder.TriangleIndices.Add(j * 3 + t); // one mesh part is "j * 3 + t" use "id" if you're building the full mesh } } @@ -321,29 +306,32 @@ private void PushLod(CMeshSection[] sections, CMeshVertex[] verts, FRawStaticInd if (section.Material == null || !section.Material.TryLoad(out var unrealMaterial)) continue; - var index = (i & 0xFFF8) | _table2[i & 7] ^ 7; - var (m, isRendering, isTransparent) = LoadMaterial(unrealMaterial); - + var (m, isRendering, isTransparent) = LoadMaterial(unrealMaterial, B(i)); Application.Current.Dispatcher.Invoke(() => { cam.Group3d.Add(new MeshGeometryModel3D { Name = FixName(unrealMaterial.Name), Geometry = builder.ToMeshGeometry3D(), - Material = m, IsTransparent = isTransparent, IsRendering = isRendering, - Tag = new PBRMaterial - { - AlbedoColor = new Color4(_table[C(index)] / 255, _table[C(index >> 1)] / 255, _table[C(index >> 2)] / 255, 1) - } + Material = m, IsTransparent = isTransparent, IsRendering = isRendering }); }); } } - private int C(int x) => (x & 1) | ((x >> 2) & 2); - - private (PBRMaterial material, bool isRendering, bool isTransparent) LoadMaterial(UMaterialInterface unrealMaterial) + private (CustomPBRMaterial material, bool isRendering, bool isTransparent) LoadMaterial(UMaterialInterface unrealMaterial, int index) { - var m = new PBRMaterial { RenderShadowMap = true, EnableAutoTangent = true, RenderEnvironmentMap = true }; + var m = new CustomPBRMaterial {RenderShadowMap = true, EnableAutoTangent = true, RenderEnvironmentMap = true}; // default + Application.Current.Dispatcher.Invoke(() => // tweak this later + { + m = new CustomPBRMaterial // recreate on ui thread + { + RenderShadowMap = true, + EnableAutoTangent = true, + RenderEnvironmentMap = true, + MaterialColor = new Color4(_table[C(index)] / 255, _table[C(index >> 1)] / 255, _table[C(index >> 2)] / 255, 1) + }; + }); + var parameters = new CMaterialParams(); unrealMaterial.GetParams(parameters); @@ -351,9 +339,15 @@ private void PushLod(CMeshSection[] sections, CMeshVertex[] verts, FRawStaticInd if (isRendering) { if (parameters.Diffuse is UTexture2D diffuse) - m.AlbedoMap = new TextureModel(diffuse.Decode()?.Encode().AsStream()); + { + var s = diffuse.Decode()?.Encode().AsStream(); + Application.Current.Dispatcher.Invoke(() => m.AlbedoMap = new TextureModel(s)); + } if (parameters.Normal is UTexture2D normal) - m.NormalMap = new TextureModel(normal.Decode()?.Encode().AsStream()); + { + var s = normal.Decode()?.Encode().AsStream(); + Application.Current.Dispatcher.Invoke(() => m.NormalMap = new TextureModel(s)); + } if (parameters.Specular is UTexture2D specular) { var mip = specular.GetFirstMip(); @@ -458,15 +452,19 @@ private void PushLod(CMeshSection[] sections, CMeshVertex[] verts, FRawStaticInd } // R -> AO G -> Roughness B -> Metallic - m.RoughnessMetallicMap = new TextureModel(bitmap.Encode(SKEncodedImageFormat.Png, 100).AsStream()); - m.RoughnessFactor = parameters.RoughnessValue; - m.MetallicFactor = parameters.MetallicValue; - m.RenderAmbientOcclusionMap = parameters.SpecularValue > 0; + var s = bitmap.Encode(SKEncodedImageFormat.Png, 100).AsStream(); + Application.Current.Dispatcher.Invoke(() => + { + m.RoughnessMetallicMap = new TextureModel(s); + m.RoughnessFactor = parameters.RoughnessValue; + m.MetallicFactor = parameters.MetallicValue; + m.RenderAmbientOcclusionMap = parameters.SpecularValue > 0; + }); } } else { - m.AlbedoColor = new Color4(1, 0, 0, 1); + Application.Current.Dispatcher.Invoke(() => m.AlbedoColor = new Color4(1, 0, 0, 1)); } return (m, isRendering, parameters.IsTransparent); @@ -502,6 +500,9 @@ private string FixName(string input) return input.Replace('-', '_'); } + private int B(int x) => (x & 0xFFF8) | _table2[x & 7] ^ 7; + private int C(int x) => (x & 1) | ((x >> 2) & 2); + public void Clear() { foreach (var g in _loadedModels.ToList()) @@ -538,10 +539,35 @@ public bool ShowMaterialColor SetProperty(ref _showMaterialColor, value); foreach (var g in Group3d) { - if (g is not MeshGeometryModel3D geometryModel) + if (g is not MeshGeometryModel3D { Material: CustomPBRMaterial material }) continue; - (geometryModel.Material, geometryModel.Tag) = ((PBRMaterial)geometryModel.Tag, geometryModel.Material); + material.RenderAlbedoMap = !_showMaterialColor; + material.AlbedoColor = _showMaterialColor ? material.MaterialColor : Color4.White; + } + } + } + + private bool _showDiffuseOnly; + public bool ShowDiffuseOnly + { + get => _showDiffuseOnly; + set + { + SetProperty(ref _showDiffuseOnly, value); + foreach (var g in Group3d) + { + if (g is not MeshGeometryModel3D { Material: CustomPBRMaterial material }) + continue; + + material.RenderAmbientOcclusionMap = !material.RenderAmbientOcclusionMap; + material.RenderDisplacementMap = !material.RenderDisplacementMap; + material.RenderEmissiveMap = !material.RenderEmissiveMap; + material.RenderEnvironmentMap = !material.RenderEnvironmentMap; + material.RenderIrradianceMap = !material.RenderIrradianceMap; + material.RenderRoughnessMetallicMap = !material.RenderRoughnessMetallicMap; + material.RenderShadowMap = !material.RenderShadowMap; + material.RenderNormalMap = !material.RenderNormalMap; } } } @@ -578,4 +604,9 @@ public void Dispose() } } } + + public class CustomPBRMaterial : PBRMaterial + { + public Color4 MaterialColor { get; set; } + } } diff --git a/FModel/Views/ModelViewer.xaml b/FModel/Views/ModelViewer.xaml index 0654382a..a944e023 100644 --- a/FModel/Views/ModelViewer.xaml +++ b/FModel/Views/ModelViewer.xaml @@ -107,8 +107,10 @@ + diff --git a/FModel/Views/ModelViewer.xaml.cs b/FModel/Views/ModelViewer.xaml.cs index bed3f6ce..2e881453 100644 --- a/FModel/Views/ModelViewer.xaml.cs +++ b/FModel/Views/ModelViewer.xaml.cs @@ -62,9 +62,9 @@ private void OnWindowKeyDown(object sender, KeyEventArgs e) case Key.H: _applicationView.ModelViewer.RenderingToggle(); break; - // case Key.D: - // _applicationView.ModelViewer.DiffuseOnlyToggle(); - // break; + case Key.D: + _applicationView.ModelViewer.DiffuseOnlyToggle(); + break; case Key.M: _applicationView.ModelViewer.MaterialColorToggle(); break; diff --git a/FModel/Views/Resources/Converters/TagToColorConverter.cs b/FModel/Views/Resources/Converters/TagToColorConverter.cs index 9b7012ea..a5725e5e 100644 --- a/FModel/Views/Resources/Converters/TagToColorConverter.cs +++ b/FModel/Views/Resources/Converters/TagToColorConverter.cs @@ -2,7 +2,7 @@ using System.Globalization; using System.Windows.Data; using System.Windows.Media; -using HelixToolkit.Wpf.SharpDX; +using FModel.ViewModels; namespace FModel.Views.Resources.Converters { @@ -12,12 +12,12 @@ public class TagToColorConverter : IValueConverter public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - if (value is not PBRMaterial material) + if (value is not CustomPBRMaterial material) return new SolidColorBrush(Colors.Red); return new SolidColorBrush(Color.FromScRgb( - material.AlbedoColor.Alpha, material.AlbedoColor.Red, - material.AlbedoColor.Green, material.AlbedoColor.Blue)); + material.MaterialColor.Alpha, material.MaterialColor.Red, + material.MaterialColor.Green, material.MaterialColor.Blue)); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) diff --git a/FModel/Views/Resources/Resources.xaml b/FModel/Views/Resources/Resources.xaml index cb74a243..ff9a5e5f 100644 --- a/FModel/Views/Resources/Resources.xaml +++ b/FModel/Views/Resources/Resources.xaml @@ -672,7 +672,7 @@ -