mirror of
https://github.com/4sval/FModel.git
synced 2026-03-21 17:24:26 -05:00
bump c4p + spline mesh preview in umaps
Some checks are pending
FModel QA Builder / build (push) Waiting to run
Some checks are pending
FModel QA Builder / build (push) Waiting to run
This commit is contained in:
parent
20a5c63baa
commit
e3764ef2d0
|
|
@ -1 +1 @@
|
|||
Subproject commit 74405d72a8a3a0403cd702ec7e4d32cf7bc79b4d
|
||||
Subproject commit 85bc1ddbb3e4ef43170c9593ef08d147a4945ed3
|
||||
|
|
@ -102,6 +102,7 @@
|
|||
<None Remove="Resources\npcleftside.png" />
|
||||
<None Remove="Resources\default.frag" />
|
||||
<None Remove="Resources\default.vert" />
|
||||
<None Remove="Resources\spline.vert" />
|
||||
<None Remove="Resources\grid.frag" />
|
||||
<None Remove="Resources\grid.vert" />
|
||||
<None Remove="Resources\skybox.frag" />
|
||||
|
|
@ -122,6 +123,7 @@
|
|||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\Json.xshd" />
|
||||
<EmbeddedResource Include="Resources\Ini.xshd" />
|
||||
<EmbeddedResource Include="Resources\spline.vert" />
|
||||
<EmbeddedResource Include="Resources\Verse.xshd" />
|
||||
<EmbeddedResource Include="Resources\Xml.xshd" />
|
||||
<EmbeddedResource Include="Resources\Cpp.xshd" />
|
||||
|
|
|
|||
|
|
@ -85,10 +85,7 @@ public partial class MainWindow
|
|||
#if DEBUG
|
||||
// await _threadWorkerView.Begin(cancellationToken =>
|
||||
// _applicationView.CUE4Parse.Extract(cancellationToken,
|
||||
// _applicationView.CUE4Parse.Provider["Marvel/Content/Marvel/Characters/1050/1050300/Meshes/SK_1050_1050300_Lobby.uasset"]));
|
||||
// await _threadWorkerView.Begin(cancellationToken =>
|
||||
// _applicationView.CUE4Parse.Extract(cancellationToken,
|
||||
// "RED/Content/Chara/ABA/Costume01/Animation/Charaselect/body/stand_body01.uasset"));
|
||||
// _applicationView.CUE4Parse.Provider["FortniteGame/Plugins/GameFeatures/BRMapCh6/Content/Maps/Hermes_Terrain/_Generated_/A6Z7VUFLP2917NVTLT6WZFOVC.umap"]));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -81,6 +81,18 @@ void main()
|
|||
finalNormal = normalize(finalNormal);
|
||||
finalTangent = normalize(finalTangent);
|
||||
}
|
||||
else if (uIsSpline)
|
||||
{
|
||||
GpuSplineMeshParams params = uSplineParameters[gl_InstanceID];
|
||||
float distanceAlong = GetAxisValueRef(params.ForwardAxis, bindPos.xzy);
|
||||
vec3 computed = ComputeRatioAlongSpline(params, distanceAlong);
|
||||
mat4 sliceTransform = CalcSliceTransformAtSplineOffset(params, computed);
|
||||
SetAxisValueRef(params.ForwardAxis, bindPos.xzy, 0f);
|
||||
|
||||
finalPos = (sliceTransform * bindPos.xzyw).xzyw;
|
||||
finalNormal = bindNormal;
|
||||
finalTangent = bindTangent;
|
||||
}
|
||||
else
|
||||
{
|
||||
finalPos = bindPos;
|
||||
|
|
|
|||
|
|
@ -62,6 +62,17 @@ void main()
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (uIsSpline)
|
||||
{
|
||||
GpuSplineMeshParams params = uSplineParameters[gl_InstanceID];
|
||||
float distanceAlong = GetAxisValueRef(params.ForwardAxis, bindPos.xzy);
|
||||
vec3 computed = ComputeRatioAlongSpline(params, distanceAlong);
|
||||
mat4 sliceTransform = CalcSliceTransformAtSplineOffset(params, computed);
|
||||
SetAxisValueRef(params.ForwardAxis, bindPos.xzy, 0f);
|
||||
|
||||
finalPos = (sliceTransform * bindPos.xzyw).xzyw;
|
||||
finalNormal = bindNormal;
|
||||
}
|
||||
else
|
||||
{
|
||||
finalPos = bindPos;
|
||||
|
|
|
|||
|
|
@ -47,6 +47,16 @@ void main()
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (uIsSpline)
|
||||
{
|
||||
GpuSplineMeshParams params = uSplineParameters[gl_InstanceID];
|
||||
float distanceAlong = GetAxisValueRef(params.ForwardAxis, bindPos.xzy);
|
||||
vec3 computed = ComputeRatioAlongSpline(params, distanceAlong);
|
||||
mat4 sliceTransform = CalcSliceTransformAtSplineOffset(params, computed);
|
||||
SetAxisValueRef(params.ForwardAxis, bindPos.xzy, 0f);
|
||||
|
||||
finalPos = (sliceTransform * bindPos.xzyw).xzyw;
|
||||
}
|
||||
else finalPos = bindPos;
|
||||
|
||||
gl_Position = uProjection * uView * vInstanceMatrix * finalPos;
|
||||
|
|
|
|||
216
FModel/Resources/spline.vert
Normal file
216
FModel/Resources/spline.vert
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
#version 460 core
|
||||
|
||||
// yeeted from minshu https://github.com/FabianFG/CUE4Parse/commit/61cef25b8eef4160651ee41e2b1ceefc5135803f
|
||||
|
||||
struct GpuSplineMeshParams {
|
||||
int ForwardAxis;
|
||||
float SplineBoundaryMin;
|
||||
float SplineBoundaryMax;
|
||||
bool bSmoothInterpRollScale;
|
||||
|
||||
vec3 MeshOrigin;
|
||||
vec3 MeshBoxExtent;
|
||||
|
||||
vec3 StartPos;
|
||||
float StartRoll;
|
||||
vec3 StartTangent;
|
||||
vec2 StartScale;
|
||||
vec2 StartOffset;
|
||||
vec3 EndPos;
|
||||
float EndRoll;
|
||||
vec3 EndTangent;
|
||||
vec2 EndScale;
|
||||
vec2 EndOffset;
|
||||
|
||||
vec3 SplineUpDir;
|
||||
};
|
||||
|
||||
layout(std430, binding = 3) buffer SplineParameters
|
||||
{
|
||||
GpuSplineMeshParams uSplineParameters[];
|
||||
};
|
||||
|
||||
uniform bool uIsSpline;
|
||||
|
||||
vec3 getSafeNormal(vec3 vector) {
|
||||
float squareSum = dot(vector, vector);
|
||||
|
||||
if (squareSum == 1.0) {
|
||||
return vector;
|
||||
}
|
||||
|
||||
if (squareSum < 1e-8f) {
|
||||
return vec3(0.0); // Return a zero vector
|
||||
}
|
||||
|
||||
// Calculate the scale factor to normalize the vector
|
||||
float scale = inversesqrt(squareSum);
|
||||
return vector * scale;
|
||||
}
|
||||
|
||||
float GetAxisValueRef(int forwardAxis, vec3 pos)
|
||||
{
|
||||
switch (forwardAxis)
|
||||
{
|
||||
case 0: return pos.x;
|
||||
case 1: return pos.y;
|
||||
case 2: return pos.z;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SetAxisValueRef(int forwardAxis, inout vec3 pos, float v)
|
||||
{
|
||||
switch (forwardAxis)
|
||||
{
|
||||
case 0: pos.x = v; break;
|
||||
case 1: pos.y = v; break;
|
||||
case 2: pos.z = v; break;
|
||||
}
|
||||
}
|
||||
|
||||
vec3 SplineEvalTangent(GpuSplineMeshParams params, float a)
|
||||
{
|
||||
vec3 c = (6 * params.StartPos) + (3 * params.StartTangent) + (3 * params.EndTangent) - (6 * params.EndPos);
|
||||
vec3 d = (-6 * params.StartPos) - (4 * params.StartTangent) - (2 * params.EndTangent) + (6 * params.EndPos);
|
||||
vec3 e = params.StartTangent;
|
||||
|
||||
float a2 = a * a;
|
||||
|
||||
return (c * a2) + (d * a) + e;
|
||||
}
|
||||
|
||||
vec3 SplineEvalDir(GpuSplineMeshParams params, float a)
|
||||
{
|
||||
return getSafeNormal(SplineEvalTangent(params, a));
|
||||
}
|
||||
|
||||
vec3 SplineEvalPos(GpuSplineMeshParams params, float a)
|
||||
{
|
||||
float a2 = a * a;
|
||||
float a3 = a2 * a;
|
||||
|
||||
return (((2 * a3) - (3 * a2) + 1) * params.StartPos) + ((a3 - (2 * a2) + a) * params.StartTangent) + ((a3 - a2) * params.EndTangent) + (((-2 * a3) + (3 * a2)) * params.EndPos);
|
||||
}
|
||||
|
||||
vec3 ComputeRatioAlongSpline(GpuSplineMeshParams params, float distanceAlong)
|
||||
{
|
||||
float alpha = 0f;
|
||||
float minT = 0f;
|
||||
float maxT = 1f;
|
||||
|
||||
const float SmallNumber = 1e-8f;
|
||||
bool bHasCustomBoundary = abs(params.SplineBoundaryMin - params.SplineBoundaryMax) > SmallNumber;
|
||||
if (bHasCustomBoundary)
|
||||
{
|
||||
float splineLength = params.SplineBoundaryMax - params.SplineBoundaryMin;
|
||||
if (splineLength > 0)
|
||||
{
|
||||
alpha = (distanceAlong - params.SplineBoundaryMin) / splineLength;
|
||||
}
|
||||
|
||||
float boundMin = GetAxisValueRef(params.ForwardAxis, params.MeshOrigin - params.MeshBoxExtent);
|
||||
float boundMax = GetAxisValueRef(params.ForwardAxis, params.MeshOrigin + params.MeshBoxExtent);
|
||||
|
||||
float boundMinT = (boundMin - params.SplineBoundaryMin) / (params.SplineBoundaryMax - params.SplineBoundaryMin);
|
||||
float boundMaxT = (boundMax - params.SplineBoundaryMin) / (params.SplineBoundaryMax - params.SplineBoundaryMin);
|
||||
|
||||
const float MaxSplineExtrapolation = 4.0f;
|
||||
minT = max(-MaxSplineExtrapolation, boundMinT);
|
||||
maxT = min(boundMaxT, MaxSplineExtrapolation);
|
||||
}
|
||||
else
|
||||
{
|
||||
float meshMinZ = GetAxisValueRef(params.ForwardAxis, params.MeshOrigin) - GetAxisValueRef(params.ForwardAxis, params.MeshBoxExtent);
|
||||
float meshRangeZ = 2 * GetAxisValueRef(params.ForwardAxis, params.MeshBoxExtent);
|
||||
|
||||
if (meshRangeZ > SmallNumber) {
|
||||
alpha = (distanceAlong - meshMinZ) / meshRangeZ;
|
||||
}
|
||||
}
|
||||
return vec3(alpha, minT, maxT);
|
||||
}
|
||||
|
||||
mat4 CalcSliceTransformAtSplineOffset(GpuSplineMeshParams params, vec3 computed)
|
||||
{
|
||||
float alpha = computed.x;
|
||||
float minT = computed.y;
|
||||
float maxT = computed.z;
|
||||
|
||||
float hermiteAlpha = params.bSmoothInterpRollScale ? smoothstep(0.0f, 1.0f, alpha) : alpha;
|
||||
|
||||
vec3 splinePos;
|
||||
vec3 splineDir;
|
||||
if (alpha < minT)
|
||||
{
|
||||
vec3 startTangent = SplineEvalTangent(params, minT);
|
||||
splinePos = SplineEvalPos(params, minT) + (startTangent * (alpha - minT));
|
||||
splineDir = getSafeNormal(startTangent);
|
||||
}
|
||||
else if (alpha > maxT)
|
||||
{
|
||||
vec3 endTangent = SplineEvalTangent(params, maxT);
|
||||
splinePos = SplineEvalPos(params, maxT) + (endTangent * (alpha - maxT));
|
||||
splineDir = getSafeNormal(endTangent);
|
||||
}
|
||||
else
|
||||
{
|
||||
splinePos = SplineEvalPos(params, alpha);
|
||||
splineDir = SplineEvalDir(params, alpha);
|
||||
}
|
||||
|
||||
// base
|
||||
vec3 baseXVec = getSafeNormal(cross(params.SplineUpDir, splineDir));
|
||||
vec3 baseYVec = getSafeNormal(cross(splineDir, baseXVec));
|
||||
|
||||
// Offset the spline by the desired amount
|
||||
vec2 sliceOffset = mix(params.StartOffset, params.EndOffset, hermiteAlpha);
|
||||
splinePos += sliceOffset.x * baseXVec;
|
||||
splinePos += sliceOffset.y * baseYVec;
|
||||
|
||||
// Apply Roll
|
||||
float useRoll = mix(params.StartRoll, params.EndRoll, hermiteAlpha);
|
||||
float cosAng = cos(useRoll);
|
||||
float sinAng = sin(useRoll);
|
||||
vec3 xVec = (cosAng * baseXVec) - (sinAng * baseYVec);
|
||||
vec3 yVec = (cosAng * baseYVec) + (sinAng * baseXVec);
|
||||
|
||||
// Find Scale
|
||||
vec2 useScale = mix(params.StartScale, params.EndScale, hermiteAlpha);
|
||||
|
||||
// Build overall transform
|
||||
mat4 sliceTransform = mat4(0);
|
||||
vec3 scale;
|
||||
switch (params.ForwardAxis) {
|
||||
case 0:
|
||||
sliceTransform[0] = vec4(splineDir, 0f);
|
||||
sliceTransform[1] = vec4(xVec, 0f);
|
||||
sliceTransform[2] = vec4(yVec, 0f);
|
||||
sliceTransform[3] = vec4(splinePos, 1f);
|
||||
scale = vec3(1, useScale.x, useScale.y);
|
||||
break;
|
||||
case 1:
|
||||
sliceTransform[0] = vec4(yVec, 0f);
|
||||
sliceTransform[1] = vec4(splineDir, 0f);
|
||||
sliceTransform[2] = vec4(xVec, 0f);
|
||||
sliceTransform[3] = vec4(splinePos, 1f);
|
||||
scale = vec3(useScale.y, 1, useScale.x);
|
||||
break;
|
||||
case 2:
|
||||
sliceTransform[0] = vec4(xVec, 0f);
|
||||
sliceTransform[1] = vec4(yVec, 0f);
|
||||
sliceTransform[2] = vec4(splineDir, 0f);
|
||||
sliceTransform[3] = vec4(splinePos, 1f);
|
||||
scale = vec3(useScale.x, useScale.y, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
mat4 scaleMatrix = mat4(
|
||||
vec4(scale.x, 0.0, 0.0, 0.0),
|
||||
vec4(0.0, scale.y, 0.0, 0.0),
|
||||
vec4(0.0, 0.0, scale.z, 0.0),
|
||||
vec4(0.0, 0.0, 0.0, 1.0)
|
||||
);
|
||||
|
||||
return sliceTransform * scaleMatrix;
|
||||
}
|
||||
109
FModel/Views/Snooper/Models/SplineModel.cs
Normal file
109
FModel/Views/Snooper/Models/SplineModel.cs
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
using CUE4Parse_Conversion.Meshes.PSK;
|
||||
using CUE4Parse.UE4.Assets.Exports.Component.SplineMesh;
|
||||
using CUE4Parse.UE4.Assets.Exports.Material;
|
||||
using CUE4Parse.UE4.Assets.Exports.StaticMesh;
|
||||
using CUE4Parse.UE4.Assets.Exports.Texture;
|
||||
using CUE4Parse.UE4.Objects.Core.Math;
|
||||
using FModel.Views.Snooper.Buffers;
|
||||
using FModel.Views.Snooper.Shading;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
|
||||
namespace FModel.Views.Snooper.Models;
|
||||
|
||||
public class SplineModel : StaticModel
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct GpuParams
|
||||
{
|
||||
public int ForwardAxis;
|
||||
public float SplineBoundaryMin;
|
||||
public float SplineBoundaryMax;
|
||||
public bool bSmoothInterpRollScale;
|
||||
|
||||
public FVector MeshOrigin;
|
||||
public int _padding0;
|
||||
public FVector MeshBoxExtent;
|
||||
public int _padding1;
|
||||
|
||||
public FVector StartPos;
|
||||
public float StartRoll;
|
||||
public FVector StartTangent;
|
||||
public int _padding2;
|
||||
public FVector2D StartScale;
|
||||
public FVector2D StartOffset;
|
||||
public FVector EndPos;
|
||||
public float EndRoll;
|
||||
public FVector EndTangent;
|
||||
public int _padding3;
|
||||
public FVector2D EndScale;
|
||||
public FVector2D EndOffset;
|
||||
|
||||
public FVector SplineUpDir;
|
||||
public int _padding4;
|
||||
|
||||
public GpuParams(USplineMeshComponent splineMesh)
|
||||
{
|
||||
ForwardAxis = (int)splineMesh.ForwardAxis;
|
||||
SplineBoundaryMin = splineMesh.SplineBoundaryMin;
|
||||
SplineBoundaryMax = splineMesh.SplineBoundaryMax;
|
||||
bSmoothInterpRollScale = splineMesh.bSmoothInterpRollScale;
|
||||
|
||||
var b = splineMesh.GetLoadedStaticMesh()?.RenderData?.Bounds ?? new FBoxSphereBounds();
|
||||
MeshOrigin = b.Origin * Constants.SCALE_DOWN_RATIO;
|
||||
MeshBoxExtent = b.BoxExtent * Constants.SCALE_DOWN_RATIO;
|
||||
|
||||
var p = splineMesh.SplineParams;
|
||||
StartPos = p.StartPos * Constants.SCALE_DOWN_RATIO;
|
||||
StartRoll = p.StartRoll;
|
||||
StartTangent = p.StartTangent * Constants.SCALE_DOWN_RATIO;
|
||||
StartScale = p.StartScale;
|
||||
StartOffset = p.StartOffset;
|
||||
EndPos = p.EndPos * Constants.SCALE_DOWN_RATIO;
|
||||
EndRoll = p.EndRoll;
|
||||
EndTangent = p.EndTangent * Constants.SCALE_DOWN_RATIO;
|
||||
EndScale = p.EndScale;
|
||||
EndOffset = p.EndOffset;
|
||||
|
||||
SplineUpDir = splineMesh.SplineUpDir;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly List<GpuParams> _splineParams;
|
||||
private BufferObject<GpuParams> _ssbo;
|
||||
|
||||
public SplineModel(UStaticMesh export, CStaticMesh staticMesh, USplineMeshComponent splineMesh, Transform transform = null) : base(export, staticMesh, transform)
|
||||
{
|
||||
_splineParams = [new GpuParams(splineMesh)];
|
||||
|
||||
Type = "SplineMesh";
|
||||
IsVisible = true;
|
||||
IsTwoSided = true;
|
||||
}
|
||||
|
||||
public void AddComponent(USplineMeshComponent splineMesh)
|
||||
{
|
||||
_splineParams.Add(new GpuParams(splineMesh));
|
||||
}
|
||||
|
||||
public override void Setup(Options options)
|
||||
{
|
||||
base.Setup(options);
|
||||
|
||||
_ssbo = new BufferObject<GpuParams>(_splineParams.ToArray(), BufferTarget.ShaderStorageBuffer);
|
||||
}
|
||||
|
||||
public void Render(Shader shader)
|
||||
{
|
||||
shader.SetUniform("uIsSpline", true);
|
||||
_ssbo.BindBufferBase(3);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
base.Dispose();
|
||||
_ssbo?.Dispose();
|
||||
}
|
||||
}
|
||||
|
|
@ -50,7 +50,7 @@ public abstract class UModel : IRenderableModel
|
|||
|
||||
public string Path { get; }
|
||||
public string Name { get; }
|
||||
public string Type { get; }
|
||||
public string Type { get; protected set; }
|
||||
public int UvCount { get; }
|
||||
public uint[] Indices { get; set; }
|
||||
public float[] Vertices { get; set; }
|
||||
|
|
@ -219,7 +219,7 @@ public abstract class UModel : IRenderableModel
|
|||
collision.Setup();
|
||||
}
|
||||
|
||||
if (options.Models.Count == 1 && Sections.All(x => !x.Show))
|
||||
if (options.Models.Count == 1 && Sections.All(x => !x.Show)) // visible if alone and invisible
|
||||
{
|
||||
IsVisible = true;
|
||||
foreach (var section in Sections)
|
||||
|
|
@ -227,9 +227,20 @@ public abstract class UModel : IRenderableModel
|
|||
section.Show = true;
|
||||
}
|
||||
}
|
||||
else foreach (var section in Sections)
|
||||
else if (!IsVisible) // default: visible if one section is visible
|
||||
{
|
||||
if (!IsVisible) IsVisible = section.Show;
|
||||
foreach (var section in Sections)
|
||||
{
|
||||
if (section.Show)
|
||||
{
|
||||
IsVisible = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else foreach (var section in Sections) // force visibility
|
||||
{
|
||||
section.Show = true;
|
||||
}
|
||||
|
||||
IsSetup = true;
|
||||
|
|
@ -246,7 +257,13 @@ public abstract class UModel : IRenderableModel
|
|||
}
|
||||
|
||||
if (this is SkeletalModel skeletalModel) skeletalModel.Render(shader);
|
||||
else shader.SetUniform("uIsAnimated", false);
|
||||
else if (this is SplineModel splineModel) splineModel.Render(shader);
|
||||
else
|
||||
{
|
||||
shader.SetUniform("uIsAnimated", false);
|
||||
shader.SetUniform("uIsSpline", false);
|
||||
}
|
||||
|
||||
if (!outline)
|
||||
{
|
||||
shader.SetUniform("uUvCount", UvCount);
|
||||
|
|
@ -290,9 +307,13 @@ public abstract class UModel : IRenderableModel
|
|||
public void PickingRender(Shader shader)
|
||||
{
|
||||
if (IsTwoSided) GL.Disable(EnableCap.CullFace);
|
||||
if (this is SkeletalModel skeletalModel)
|
||||
skeletalModel.Render(shader);
|
||||
else shader.SetUniform("uIsAnimated", false);
|
||||
if (this is SkeletalModel skeletalModel) skeletalModel.Render(shader);
|
||||
if (this is SplineModel splineModel) splineModel.Render(shader);
|
||||
else
|
||||
{
|
||||
shader.SetUniform("uIsAnimated", false);
|
||||
shader.SetUniform("uIsSpline", false);
|
||||
}
|
||||
|
||||
Vao.Bind();
|
||||
foreach (var section in Sections)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ using CUE4Parse_Conversion.Animations;
|
|||
using CUE4Parse_Conversion.Meshes;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Assets.Exports.Animation;
|
||||
using CUE4Parse.UE4.Assets.Exports.Component.SplineMesh;
|
||||
using CUE4Parse.UE4.Assets.Exports.Component.StaticMesh;
|
||||
using CUE4Parse.UE4.Assets.Exports.GeometryCollection;
|
||||
using CUE4Parse.UE4.Assets.Exports.Material;
|
||||
|
|
@ -443,8 +444,7 @@ public class Renderer : IDisposable
|
|||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (persistentLevel.Actors[i].Load() is not { } actor ||
|
||||
actor.ExportType is "LODActor" or "SplineMeshActor")
|
||||
if (persistentLevel.Actors[i].Load() is not { } actor || actor.ExportType is "LODActor")
|
||||
continue;
|
||||
|
||||
Services.ApplicationService.ApplicationView.Status.UpdateStatusLabel($"{original.Name} ... {i}/{length}");
|
||||
|
|
@ -535,17 +535,17 @@ public class Renderer : IDisposable
|
|||
{
|
||||
foreach (var component in instanceComponents)
|
||||
{
|
||||
if (!component.TryLoad(out UInstancedStaticMeshComponent staticMeshComp) ||
|
||||
if (!component.TryLoad(out UStaticMeshComponent staticMeshComp) ||
|
||||
!staticMeshComp.GetStaticMesh().TryLoad(out UStaticMesh m) || m.Materials.Length < 1)
|
||||
continue;
|
||||
|
||||
if (staticMeshComp.PerInstanceSMData is { Length: > 0 })
|
||||
var relation = CalculateTransform(staticMeshComp, transform);
|
||||
if (staticMeshComp is UInstancedStaticMeshComponent { PerInstanceSMData.Length: > 0 } instancedStaticMeshComp)
|
||||
{
|
||||
|
||||
var relation = CalculateTransform(staticMeshComp, transform);
|
||||
foreach (var perInstanceData in staticMeshComp.PerInstanceSMData)
|
||||
foreach (var perInstanceData in instancedStaticMeshComp.PerInstanceSMData)
|
||||
{
|
||||
ProcessMesh(actor, staticMeshComp, m, new Transform
|
||||
ProcessMesh(actor, instancedStaticMeshComp, m, new Transform
|
||||
{
|
||||
Relation = relation.Matrix,
|
||||
Position = perInstanceData.TransformData.Translation * Constants.SCALE_DOWN_RATIO,
|
||||
|
|
@ -554,7 +554,7 @@ public class Renderer : IDisposable
|
|||
});
|
||||
}
|
||||
}
|
||||
else ProcessMesh(actor, staticMeshComp, m, CalculateTransform(staticMeshComp, transform));
|
||||
else ProcessMesh(actor, staticMeshComp, m, relation);
|
||||
}
|
||||
}
|
||||
else if (actor.TryGetValue(out FPackageIndex componentTemplate, "ComponentTemplate") &&
|
||||
|
|
@ -574,7 +574,7 @@ public class Renderer : IDisposable
|
|||
ProcessMesh(actor, compTemplate, m, CalculateTransform(compTemplate, transform), forceShow);
|
||||
}
|
||||
}
|
||||
else if (actor.TryGetValue(out FPackageIndex staticMeshComponent, "StaticMeshComponent", "ComponentTemplate", "StaticMesh", "Mesh", "LightMesh") &&
|
||||
else if (actor.TryGetValue(out FPackageIndex staticMeshComponent, "StaticMeshComponent", "ComponentTemplate", "StaticMesh", "Mesh", "LightMesh", "SplineMesh") &&
|
||||
staticMeshComponent.TryLoad(out UStaticMeshComponent staticMeshComp) &&
|
||||
staticMeshComp.GetStaticMesh().TryLoad(out UStaticMesh m) && m.Materials.Length > 0)
|
||||
{
|
||||
|
|
@ -589,14 +589,17 @@ public class Renderer : IDisposable
|
|||
}
|
||||
private void ProcessMesh(IPropertyHolder actor, UObject staticMeshComp, UStaticMesh m, Transform transform, bool forceShow)
|
||||
{
|
||||
var bSpline = staticMeshComp is USplineMeshComponent;
|
||||
var guid = m.LightingGuid;
|
||||
if (Options.TryGetModel(guid, out var model))
|
||||
{
|
||||
model.AddInstance(transform);
|
||||
if (bSpline && model is SplineModel splineModel)
|
||||
splineModel.AddComponent((USplineMeshComponent)staticMeshComp);
|
||||
}
|
||||
else if (m.TryConvert(out var mesh))
|
||||
{
|
||||
model = new StaticModel(m, mesh, transform);
|
||||
model = bSpline ? new SplineModel(m, mesh, (USplineMeshComponent)staticMeshComp, transform) : new StaticModel(m, mesh, transform);
|
||||
model.IsTwoSided = actor.GetOrDefault("bMirrored", staticMeshComp.GetOrDefault("bDisallowMeshPaintPerInstance", model.IsTwoSided));
|
||||
|
||||
if (actor.TryGetAllValues(out FPackageIndex[] textureData, "TextureData"))
|
||||
|
|
@ -671,6 +674,11 @@ public class Renderer : IDisposable
|
|||
|
||||
private Transform CalculateTransform(IPropertyHolder staticMeshComp, Transform relation)
|
||||
{
|
||||
if (staticMeshComp.TryGetValue(out FPackageIndex ap, "AttachParent") && ap.TryLoad(out UObject component))
|
||||
{
|
||||
relation = CalculateTransform(component, relation);
|
||||
}
|
||||
|
||||
return new Transform
|
||||
{
|
||||
Relation = relation.Matrix,
|
||||
|
|
|
|||
|
|
@ -47,13 +47,20 @@ public class Shader : IDisposable
|
|||
private int LoadShader(ShaderType type, string file)
|
||||
{
|
||||
var executingAssembly = Assembly.GetExecutingAssembly();
|
||||
using var stream = executingAssembly.GetManifestResourceStream($"{executingAssembly.GetName().Name}.Resources.{file}");
|
||||
var executingAssemblyName = executingAssembly.GetName().Name;
|
||||
using var stream = executingAssembly.GetManifestResourceStream($"{executingAssemblyName}.Resources.{file}");
|
||||
using var reader = new StreamReader(stream);
|
||||
var handle = GL.CreateShader(type);
|
||||
|
||||
var content = reader.ReadToEnd();
|
||||
if (file.Equals("default.frag") && GL.GetInteger(GetPName.MaxTextureCoords) == 0)
|
||||
content = content.Replace("#define MAX_UV_COUNT 8", "#define MAX_UV_COUNT 1");
|
||||
if (type == ShaderType.VertexShader && Array.IndexOf(["default.vert", "outline.vert", "picking.vert"], file) > -1)
|
||||
{
|
||||
using var splineStream = executingAssembly.GetManifestResourceStream($"{executingAssemblyName}.Resources.spline.vert");
|
||||
using var splineReader = new StreamReader(splineStream);
|
||||
content = splineReader.ReadToEnd() + Environment.NewLine + content.Replace("#version 460 core", "");
|
||||
}
|
||||
|
||||
GL.ShaderSource(handle, content);
|
||||
GL.CompileShader(handle);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user