mirror of
https://github.com/4sval/FModel.git
synced 2026-04-18 23:57:42 -05:00
hello you
This commit is contained in:
parent
1b9bd2c56a
commit
eb987195d6
|
|
@ -36,7 +36,6 @@ namespace FModel.ViewModels
|
|||
{
|
||||
private ThreadWorkerViewModel _threadWorkerView => ApplicationService.ThreadWorkerView;
|
||||
|
||||
#region BINDINGS
|
||||
private EffectsManager _effectManager;
|
||||
public EffectsManager EffectManager
|
||||
{
|
||||
|
|
@ -71,7 +70,6 @@ namespace FModel.ViewModels
|
|||
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 @@ namespace FModel.ViewModels
|
|||
_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 @@ namespace FModel.ViewModels
|
|||
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 @@ namespace FModel.ViewModels
|
|||
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 @@ namespace FModel.ViewModels
|
|||
}
|
||||
#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 @@ namespace FModel.ViewModels
|
|||
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 @@ namespace FModel.ViewModels
|
|||
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 @@ namespace FModel.ViewModels
|
|||
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 @@ namespace FModel.ViewModels
|
|||
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 @@ namespace FModel.ViewModels
|
|||
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);
|
||||
|
||||
|
|
@ -351,9 +339,15 @@ namespace FModel.ViewModels
|
|||
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 @@ namespace FModel.ViewModels
|
|||
}
|
||||
|
||||
// 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 @@ namespace FModel.ViewModels
|
|||
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 @@ namespace FModel.ViewModels
|
|||
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 @@ namespace FModel.ViewModels
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CustomPBRMaterial : PBRMaterial
|
||||
{
|
||||
public Color4 MaterialColor { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -62,9 +62,9 @@ namespace FModel.Views
|
|||
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;
|
||||
|
|
|
|||
|
|
@ -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 @@ namespace FModel.Views.Resources.Converters
|
|||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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}}" />
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user