diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj
index 623f5a84..d0056336 100644
--- a/FModel/FModel.csproj
+++ b/FModel/FModel.csproj
@@ -109,13 +109,13 @@
-
-
+
+
-
+
-
-
+
+
diff --git a/FModel/ViewModels/ModelViewerViewModel.cs b/FModel/ViewModels/ModelViewerViewModel.cs
index 2cc7e260..7b3ccbf8 100644
--- a/FModel/ViewModels/ModelViewerViewModel.cs
+++ b/FModel/ViewModels/ModelViewerViewModel.cs
@@ -1,6 +1,4 @@
using System;
-using System.Collections.ObjectModel;
-using System.Linq;
using CUE4Parse.UE4.Assets.Exports;
using CUE4Parse.UE4.Assets.Exports.Material;
using CUE4Parse.UE4.Assets.Exports.SkeletalMesh;
@@ -10,11 +8,14 @@ using CUE4Parse.UE4.Objects.Core.Math;
using CUE4Parse_Conversion.Meshes;
using CUE4Parse_Conversion.Meshes.PSK;
using CUE4Parse_Conversion.Textures;
-using FModel.Extensions;
using FModel.Framework;
using HelixToolkit.SharpDX.Core;
using HelixToolkit.Wpf.SharpDX;
using SharpDX;
+using Camera = HelixToolkit.Wpf.SharpDX.Camera;
+using Geometry3D = HelixToolkit.SharpDX.Core.Geometry3D;
+using Material = HelixToolkit.Wpf.SharpDX.Material;
+using PerspectiveCamera = HelixToolkit.Wpf.SharpDX.PerspectiveCamera;
namespace FModel.ViewModels
{
@@ -26,28 +27,28 @@ namespace FModel.ViewModels
get => _effectManager;
set => SetProperty(ref _effectManager, value);
}
-
+
private Camera _cam;
public Camera Cam
{
get => _cam;
set => SetProperty(ref _cam, value);
}
-
+
private Geometry3D _xAxis;
public Geometry3D XAxis
{
get => _xAxis;
set => SetProperty(ref _xAxis, value);
}
-
+
private Geometry3D _yAxis;
public Geometry3D YAxis
{
get => _yAxis;
set => SetProperty(ref _yAxis, value);
}
-
+
private Geometry3D _zAxis;
public Geometry3D ZAxis
{
@@ -62,43 +63,25 @@ namespace FModel.ViewModels
set => SetProperty(ref _showWireframe, value);
}
- private Geometry3D _mesh;
- public Geometry3D Mesh
+ private ObservableElement3DCollection _group3d;
+ public ObservableElement3DCollection Group3d
{
- get => _mesh;
- set => SetProperty(ref _mesh, value);
+ get => _group3d;
+ set => SetProperty(ref _group3d, value);
}
-
- private Material _meshMat;
- public Material MeshMat
- {
- get => _meshMat;
- set => SetProperty(ref _meshMat, value);
- }
-
- public ObservableCollection Lods { get; }
+ public Material MainMaterial { get; } = PhongMaterials.White;
+
+ private readonly int[] _FACES_INDEX = { 1, 0, 2 };
public ModelViewerViewModel()
{
- Lods = new ObservableCollection();
EffectManager = new DefaultEffectsManager();
- Cam = new PerspectiveCamera
- {
- NearPlaneDistance = 0.1,
- FarPlaneDistance = 10000000,
- FieldOfView = 80
- };
+ Cam = new PerspectiveCamera { NearPlaneDistance = 0.1, FarPlaneDistance = 99999999, FieldOfView = 80 };
}
- public void NextLod() => Mesh = Lods.Next(Mesh);
- public void PreviousLod() => Mesh = Lods.Previous(Mesh);
-
public void LoadExport(UObject export)
{
- Lods.Clear();
- Mesh = null;
- MeshMat = PhongMaterials.Bisque;
-
+ Group3d = new ObservableElement3DCollection();
switch (export)
{
case UStaticMesh st:
@@ -111,31 +94,24 @@ namespace FModel.ViewModels
throw new ArgumentOutOfRangeException();
}
}
-
+
private void LoadStaticMesh(UStaticMesh mesh)
{
if (!mesh.TryConvert(out var convertedMesh) || convertedMesh.LODs.Count <= 0)
{
return;
}
-
+
SetupCameraAndAxis(convertedMesh.BoundingBox.Min, convertedMesh.BoundingBox.Max);
- var pushedMaterial = false;
foreach (var lod in convertedMesh.LODs)
{
if (lod.SkipLod) continue;
-
- PushLod(lod.Verts, lod.Indices.Value);
- if (!pushedMaterial)
- {
- PushMaterial(lod.Sections.Value);
- pushedMaterial = true;
- }
+ PushLod(lod.Sections.Value, lod.Verts, lod.Indices.Value);
+ break;
}
- Mesh = Lods.First();
}
-
+
private void LoadSkeletalMesh(USkeletalMesh mesh)
{
if (!mesh.TryConvert(out var convertedMesh) || convertedMesh.LODs.Count <= 0)
@@ -145,52 +121,50 @@ namespace FModel.ViewModels
SetupCameraAndAxis(convertedMesh.BoundingBox.Min, convertedMesh.BoundingBox.Max);
- var pushedMaterial = false;
foreach (var lod in convertedMesh.LODs)
{
if (lod.SkipLod) continue;
-
- PushLod(lod.Verts, lod.Indices.Value);
- if (!pushedMaterial)
+ PushLod(lod.Sections.Value, lod.Verts, lod.Indices.Value);
+ break;
+ }
+ }
+
+ private void PushLod(CMeshSection[] sections, CMeshVertex[] verts, FRawStaticIndexBuffer indices)
+ {
+ foreach (var section in sections) // each section is a mesh part with its own material
+ {
+ var builder = new MeshBuilder();
+ // NumFaces * 3 (triangle) = next section FirstIndex
+ for (var j = 0; j < section.NumFaces; j++) // draw a triangle for each face
{
- PushMaterial(lod.Sections.Value);
- pushedMaterial = true;
+ foreach (var t in _FACES_INDEX) // triangle face 1 then 0 then 2
+ {
+ var id = section.FirstIndex + j * 3 + t;
+ var vert = verts[indices[id]];
+ var p = new Vector3(vert.Position.X, -vert.Position.Y, vert.Position.Z);
+ var n = new Vector3(vert.Normal.X, -vert.Normal.Y, vert.Normal.Z);
+ var uv = new Vector2(vert.UV.U, vert.UV.V);
+ builder.AddNode(p, n, uv);
+ builder.TriangleIndices.Add(j * 3 + t); // one mesh part is "j * 3 + k" use "id" if you're building the full mesh
+ }
}
- }
- Mesh = Lods.First();
- }
- private void PushLod(CMeshVertex[] verts, FRawStaticIndexBuffer indices)
- {
- var builder = new MeshBuilder {TextureCoordinates = new Vector2Collection()};
- for (var i = 0; i < verts.Length; i++)
- {
- builder.AddNode(
- new Vector3(verts[i].Position.X, -verts[i].Position.Y, verts[i].Position.Z),
- new Vector3(verts[i].Normal.X, -verts[i].Normal.Y, verts[i].Normal.Z),
- new Vector2(verts[i].UV.U, verts[i].UV.V));
- }
-
- for (var i = 0; i < indices.Length; i++)
- {
- builder.TriangleIndices.Add(indices[i]);
- }
-
- Lods.Add(builder.ToMesh());
- }
-
- private void PushMaterial(CMeshSection[] sections)
- {
- for (var j = 0; j < sections.Length; j++)
- {
- if (sections[j].Material == null || !sections[j].Material.TryLoad(out var unrealMaterial))
+ if (section.Material == null || !section.Material.TryLoad(out var unrealMaterial))
continue;
var parameters = new CMaterialParams();
unrealMaterial.GetParams(parameters);
- if (parameters.Diffuse is not UTexture2D diffuse) continue;
- MeshMat = new DiffuseMaterial {DiffuseMap = new TextureModel(diffuse.Decode()?.Encode().AsStream())};
- break;
+ if (parameters.Diffuse is not UTexture2D diffuse)
+ continue;
+
+ Group3d.Add(new MeshGeometryModel3D
+ {
+ Geometry = builder.ToMeshGeometry3D(),
+ Material = new PhongMaterial
+ {
+ DiffuseMap = new TextureModel(diffuse.Decode()?.Encode().AsStream())
+ }
+ });
}
}
@@ -201,7 +175,7 @@ namespace FModel.ViewModels
Cam.UpDirection = new System.Windows.Media.Media3D.Vector3D(0, 0, 1);
Cam.Position = new System.Windows.Media.Media3D.Point3D(maxOfMax, maxOfMax, (minOfMin + maxOfMax) / 1.25);
Cam.LookDirection = new System.Windows.Media.Media3D.Vector3D(-Cam.Position.X, -Cam.Position.Y, 0);
-
+
var lineBuilder = new LineBuilder();
lineBuilder.AddLine(new Vector3(0, 0, 0), new Vector3(max.X, 0, 0));
XAxis = lineBuilder.ToLineGeometry3D();
@@ -213,4 +187,4 @@ namespace FModel.ViewModels
ZAxis = lineBuilder.ToLineGeometry3D();
}
}
-}
\ No newline at end of file
+}
diff --git a/FModel/Views/ModelViewer.xaml b/FModel/Views/ModelViewer.xaml
index 9037a229..cf144f61 100644
--- a/FModel/Views/ModelViewer.xaml
+++ b/FModel/Views/ModelViewer.xaml
@@ -31,17 +31,15 @@
-
+
-
+
-
-
+
+
diff --git a/FModel/Views/ModelViewer.xaml.cs b/FModel/Views/ModelViewer.xaml.cs
index d7810b67..2b041001 100644
--- a/FModel/Views/ModelViewer.xaml.cs
+++ b/FModel/Views/ModelViewer.xaml.cs
@@ -9,7 +9,7 @@ namespace FModel.Views
public partial class ModelViewer
{
private ApplicationViewModel _applicationView => ApplicationService.ApplicationView;
-
+
public ModelViewer()
{
DataContext = _applicationView;
@@ -17,15 +17,15 @@ namespace FModel.Views
}
public void Load(UObject export) => _applicationView.ModelViewer.LoadExport(export);
-
+
private void OnWindowKeyDown(object sender, KeyEventArgs e)
{
- if (UserSettings.Default.DirLeftTab.IsTriggered(e.Key))
+ /*if (UserSettings.Default.DirLeftTab.IsTriggered(e.Key))
_applicationView.ModelViewer.PreviousLod();
else if (UserSettings.Default.DirRightTab.IsTriggered(e.Key))
_applicationView.ModelViewer.NextLod();
- else if (e.Key == Key.W)
+ else */if (e.Key == Key.W)
_applicationView.ModelViewer.ShowWireframe = !_applicationView.ModelViewer.ShowWireframe;
}
}
-}
\ No newline at end of file
+}