Skip to content

Commit

Permalink
hello you
Browse files Browse the repository at this point in the history
  • Loading branch information
4sval committed Nov 25, 2021
1 parent 1b9bd2c commit eb98719
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 69 deletions.
151 changes: 91 additions & 60 deletions FModel/ViewModels/ModelViewerViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ public class ModelViewerViewModel : ViewModel
{
private ThreadWorkerViewModel _threadWorkerView => ApplicationService.ThreadWorkerView;

#region BINDINGS
private EffectsManager _effectManager;
public EffectsManager EffectManager
{
Expand Down Expand Up @@ -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 };
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -225,10 +215,10 @@ public async Task<bool> 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;
});

Expand All @@ -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(() =>
{
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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)
Expand All @@ -312,48 +297,57 @@ 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
}
}

if (section.Material == null || !section.Material.TryLoad<UMaterialInterface>(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);

var isRendering = !parameters.IsNull;
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();
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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;
}
}
}
Expand Down Expand Up @@ -578,4 +604,9 @@ public void Dispose()
}
}
}

public class CustomPBRMaterial : PBRMaterial
{
public Color4 MaterialColor { get; set; }
}
}
4 changes: 3 additions & 1 deletion FModel/Views/ModelViewer.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,10 @@
<GridSplitter Grid.Column="1" ResizeDirection="Columns" Width="4" VerticalAlignment="Stretch" ResizeBehavior="PreviousAndNext"
Background="{DynamicResource {x:Static adonisUi:Brushes.Layer3BackgroundBrush}}" />

<TextBlock Grid.Column="2" Text="Model is loading, please wait..." HorizontalAlignment="Center" VerticalAlignment="Center"/>
<helix:Viewport3DX Grid.Column="2" EffectsManager="{Binding ModelViewer.EffectManager}" Camera="{Binding ModelViewer.Cam}"
IsChangeFieldOfViewEnabled="False" IsMoveEnabled="False" UseDefaultGestures="False" ShowViewCube="False"
Visibility="{Binding IsReady, Converter={StaticResource BoolToVisibilityConverter}}" ShowViewCube="False"
IsChangeFieldOfViewEnabled="False" IsMoveEnabled="False" UseDefaultGestures="False"
ShowCameraTarget="False" FXAALevel="Ultra" MSAA="Maximum" BackgroundColor="#2A2B34"
EnableSSAO="True" SSAOIntensity="1" EnableSwapChainRendering="True">
<helix:Viewport3DX.InputBindings>
Expand Down
6 changes: 3 additions & 3 deletions FModel/Views/ModelViewer.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
8 changes: 4 additions & 4 deletions FModel/Views/Resources/Converters/TagToColorConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion FModel/Views/Resources/Resources.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,7 @@
</Canvas>
</Viewbox>
</ToggleButton>
<Rectangle Grid.Column="5" Width="19" Height="22" Fill="{Binding Tag, Mode=OneTime, Converter={x:Static converters:TagToColorConverter.Instance}}"
<Rectangle Grid.Column="5" Width="19" Height="22" Fill="{Binding Material, Mode=OneTime, Converter={x:Static converters:TagToColorConverter.Instance}}"
Visibility="{Binding DataContext.ModelViewer.SelectedModel.ShowMaterialColor,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:Views.ModelViewer}},
Converter={StaticResource BoolToVisibilityConverter}}" />
Expand Down

0 comments on commit eb98719

Please sign in to comment.