mirror of
https://github.com/4sval/FModel.git
synced 2026-04-14 05:26:42 -05:00
cleaned camera + generated .umap position
This commit is contained in:
parent
26f9b5b9ce
commit
76a9f88eee
|
|
@ -17,12 +17,11 @@ public class Camera
|
|||
|
||||
public Vector3 Position;
|
||||
public Vector3 Direction;
|
||||
public Vector3 Focus => Position - Direction;
|
||||
public Vector3 Up = Vector3.UnitY;
|
||||
public WorldMode Mode = UserSettings.Default.CameraMode;
|
||||
public WorldMode Mode;
|
||||
public Vector3 PositionArc => Position - Direction;
|
||||
public Vector3 DirectionArc => Direction - Position;
|
||||
public Vector3 Up => Vector3.UnitY;
|
||||
|
||||
public float Yaw = -90f;
|
||||
public float Pitch = 0f;
|
||||
public float Zoom = 60f;
|
||||
public float Speed = 1f;
|
||||
public float Far = 100f;
|
||||
|
|
@ -33,27 +32,11 @@ public class Camera
|
|||
{
|
||||
Position = new Vector3(0, 1, 1);
|
||||
Direction = Vector3.Zero;
|
||||
|
||||
InitDirection();
|
||||
Mode = UserSettings.Default.CameraMode;
|
||||
}
|
||||
|
||||
public Camera(FBox box, float far)
|
||||
{
|
||||
Far = far;
|
||||
Teleport(FVector.ZeroVector, box, true);
|
||||
}
|
||||
|
||||
public Camera(Vector3 position, Vector3 direction, float far, float speed)
|
||||
{
|
||||
Position = position;
|
||||
Direction = direction;
|
||||
Far = far;
|
||||
Speed = speed;
|
||||
|
||||
InitDirection();
|
||||
}
|
||||
|
||||
public void Teleport(FVector instancePos, FBox box, bool updateSpeed = false)
|
||||
public void Setup(FBox box) => Teleport(FVector.ZeroVector, box, true);
|
||||
public void Teleport(FVector instancePos, FBox box, bool updateAll = false)
|
||||
{
|
||||
box.GetCenterAndExtents(out var center, out var extents);
|
||||
center = center.ToMapVector();
|
||||
|
|
@ -62,58 +45,42 @@ public class Camera
|
|||
|
||||
Position = new Vector3(instancePos.X, center.Y, instancePos.Z + distance * 2);
|
||||
Direction = new Vector3(center.X, center.Y, center.Z);
|
||||
if (updateSpeed) Speed = distance;
|
||||
|
||||
InitDirection();
|
||||
}
|
||||
|
||||
private void InitDirection()
|
||||
{
|
||||
// trigonometric math to calculate the cam's yaw/pitch based on position and direction to look
|
||||
var yaw = MathF.Atan((-Position.X - Direction.X) / (Position.Z - Direction.Z));
|
||||
var pitch = MathF.Atan((Position.Y - Direction.Y) / (Position.Z - Direction.Z));
|
||||
Modify(Helper.RadiansToDegrees(yaw), Helper.RadiansToDegrees(pitch));
|
||||
if (updateAll)
|
||||
{
|
||||
Far = Math.Max(Far, box.Max.AbsMax() * 50f);
|
||||
Speed = Math.Max(Speed, distance);
|
||||
}
|
||||
}
|
||||
|
||||
public void Modify(Vector2 mouseDelta)
|
||||
{
|
||||
var lookSensitivity = Mode switch
|
||||
{
|
||||
WorldMode.FlyCam => 0.1f,
|
||||
WorldMode.Arcball => 0.01f,
|
||||
WorldMode.FlyCam => 0.002f,
|
||||
WorldMode.Arcball => 0.003f,
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
mouseDelta *= lookSensitivity;
|
||||
Modify(mouseDelta.X, mouseDelta.Y);
|
||||
}
|
||||
private void Modify(float xOffset, float yOffset)
|
||||
{
|
||||
|
||||
var rotationX = Matrix4x4.CreateFromAxisAngle(-Up, mouseDelta.X);
|
||||
switch (Mode)
|
||||
{
|
||||
case WorldMode.FlyCam:
|
||||
{
|
||||
Yaw += xOffset;
|
||||
Pitch -= yOffset;
|
||||
Pitch = Math.Clamp(Pitch, -89f, 89f);
|
||||
Direction = Vector3.Transform(DirectionArc, rotationX) + Position;
|
||||
|
||||
var direction = Vector3.Zero;
|
||||
var yaw = Helper.DegreesToRadians(Yaw);
|
||||
var pitch = Helper.DegreesToRadians(Pitch);
|
||||
direction.X = MathF.Cos(yaw) * MathF.Cos(pitch);
|
||||
direction.Y = MathF.Sin(pitch);
|
||||
direction.Z = MathF.Sin(yaw) * MathF.Cos(pitch);
|
||||
Direction = Vector3.Normalize(direction);
|
||||
var right = Vector3.Normalize(Vector3.Cross(Up, DirectionArc));
|
||||
var rotationY = Matrix4x4.CreateFromAxisAngle(right, mouseDelta.Y);
|
||||
Direction = Vector3.Transform(DirectionArc, rotationY) + Position;
|
||||
break;
|
||||
}
|
||||
case WorldMode.Arcball:
|
||||
{
|
||||
var up = -Up;
|
||||
var rotationX = Matrix4x4.CreateFromAxisAngle(up, xOffset);
|
||||
Position = Vector3.Transform(Focus, rotationX) + Direction;
|
||||
Position = Vector3.Transform(PositionArc, rotationX) + Direction;
|
||||
|
||||
var right = Vector3.Normalize(Vector3.Cross(up, Focus));
|
||||
var rotationY = Matrix4x4.CreateFromAxisAngle(right, yOffset);
|
||||
Position = Vector3.Transform(Focus, rotationY) + Direction;
|
||||
var right = Vector3.Normalize(Vector3.Cross(-Up, PositionArc));
|
||||
var rotationY = Matrix4x4.CreateFromAxisAngle(right, mouseDelta.Y);
|
||||
Position = Vector3.Transform(PositionArc, rotationY) + Direction;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
@ -123,71 +90,71 @@ public class Camera
|
|||
|
||||
public void Modify(KeyboardState keyboard, float time)
|
||||
{
|
||||
if (!keyboard.IsAnyKeyDown) return;
|
||||
var multiplier = keyboard.IsKeyDown(Keys.LeftShift) ? 2f : 1f;
|
||||
var moveSpeed = Speed * multiplier * time;
|
||||
|
||||
var focus = Mode switch
|
||||
{
|
||||
WorldMode.FlyCam => Direction,
|
||||
WorldMode.Arcball => -Focus,
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
|
||||
if (keyboard.IsKeyDown(Keys.W))
|
||||
Position += moveSpeed * focus;
|
||||
if (keyboard.IsKeyDown(Keys.S))
|
||||
Position -= moveSpeed * focus;
|
||||
var moveAxis = Vector3.Normalize(-PositionArc);
|
||||
var panAxis = Vector3.Normalize(Vector3.Cross(moveAxis, Up));
|
||||
|
||||
switch (Mode)
|
||||
{
|
||||
case WorldMode.FlyCam:
|
||||
{
|
||||
if (keyboard.IsKeyDown(Keys.A))
|
||||
Position -= Vector3.Normalize(Vector3.Cross(focus, Up)) * moveSpeed;
|
||||
if (keyboard.IsKeyDown(Keys.D))
|
||||
Position += Vector3.Normalize(Vector3.Cross(focus, Up)) * moveSpeed;
|
||||
if (keyboard.IsKeyDown(Keys.E))
|
||||
Position += moveSpeed * Up;
|
||||
if (keyboard.IsKeyDown(Keys.Q))
|
||||
Position -= moveSpeed * Up;
|
||||
if (keyboard.IsKeyDown(Keys.W)) // forward
|
||||
{
|
||||
var d = moveSpeed * moveAxis;
|
||||
Position += d;
|
||||
Direction += d;
|
||||
}
|
||||
if (keyboard.IsKeyDown(Keys.S)) // backward
|
||||
{
|
||||
var d = moveSpeed * moveAxis;
|
||||
Position -= d;
|
||||
Direction -= d;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WorldMode.Arcball:
|
||||
{
|
||||
if (keyboard.IsKeyDown(Keys.A))
|
||||
{
|
||||
var d = Vector3.Normalize(Vector3.Cross(focus, Up)) * moveSpeed;
|
||||
Position -= d;
|
||||
Direction -= d;
|
||||
}
|
||||
if (keyboard.IsKeyDown(Keys.D))
|
||||
{
|
||||
var d = Vector3.Normalize(Vector3.Cross(focus, Up)) * moveSpeed;
|
||||
Position += d;
|
||||
Direction += d;
|
||||
}
|
||||
if (keyboard.IsKeyDown(Keys.E))
|
||||
{
|
||||
var d = moveSpeed * Up;
|
||||
Position += d;
|
||||
Direction += d;
|
||||
}
|
||||
if (keyboard.IsKeyDown(Keys.Q))
|
||||
{
|
||||
var d = moveSpeed * Up;
|
||||
Position -= d;
|
||||
Direction -= d;
|
||||
}
|
||||
if (keyboard.IsKeyDown(Keys.W)) // forward
|
||||
Position += moveSpeed * moveAxis;
|
||||
if (keyboard.IsKeyDown(Keys.S)) // backward
|
||||
Position -= moveSpeed * moveAxis;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
if (keyboard.IsKeyDown(Keys.X))
|
||||
ModifyZoom(-.5f);
|
||||
if (keyboard.IsKeyDown(Keys.C))
|
||||
if (keyboard.IsKeyDown(Keys.A)) // left
|
||||
{
|
||||
var d = panAxis * moveSpeed;
|
||||
Position -= d;
|
||||
Direction -= d;
|
||||
}
|
||||
if (keyboard.IsKeyDown(Keys.D)) // right
|
||||
{
|
||||
var d = panAxis * moveSpeed;
|
||||
Position += d;
|
||||
Direction += d;
|
||||
}
|
||||
if (keyboard.IsKeyDown(Keys.E)) // up
|
||||
{
|
||||
var d = moveSpeed * Up;
|
||||
Position += d;
|
||||
Direction += d;
|
||||
}
|
||||
if (keyboard.IsKeyDown(Keys.Q)) // down
|
||||
{
|
||||
var d = moveSpeed * Up;
|
||||
Position -= d;
|
||||
Direction -= d;
|
||||
}
|
||||
|
||||
if (keyboard.IsKeyDown(Keys.C)) // zoom in
|
||||
ModifyZoom(+.5f);
|
||||
if (keyboard.IsKeyDown(Keys.X)) // zoom out
|
||||
ModifyZoom(-.5f);
|
||||
}
|
||||
|
||||
private void ModifyZoom(float zoomAmount)
|
||||
|
|
@ -196,20 +163,9 @@ public class Camera
|
|||
Zoom = Math.Clamp(Zoom - zoomAmount, 1.0f, 89f);
|
||||
}
|
||||
|
||||
public Matrix4x4 GetViewMatrix()
|
||||
{
|
||||
return Mode switch
|
||||
{
|
||||
WorldMode.FlyCam => Matrix4x4.CreateLookAt(Position, Position + Direction, Up),
|
||||
WorldMode.Arcball => Matrix4x4.CreateLookAt(Position, Direction, Up),
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
}
|
||||
|
||||
public Matrix4x4 GetViewMatrix() => Matrix4x4.CreateLookAt(Position, Direction, Up);
|
||||
public Matrix4x4 GetProjectionMatrix()
|
||||
{
|
||||
return Matrix4x4.CreatePerspectiveFieldOfView(Helper.DegreesToRadians(Zoom), AspectRatio, Near, Far);
|
||||
}
|
||||
=> Matrix4x4.CreatePerspectiveFieldOfView(Helper.DegreesToRadians(Zoom), AspectRatio, Near, Far);
|
||||
|
||||
private const float _step = 0.01f;
|
||||
private const float _zero = 0.000001f; // doesn't actually work if _infinite is used as max value /shrug
|
||||
|
|
|
|||
|
|
@ -1,66 +1,41 @@
|
|||
using CUE4Parse.UE4.Assets.Exports.Material;
|
||||
using CUE4Parse_Conversion.Meshes.PSK;
|
||||
using CUE4Parse.UE4.Assets.Exports.Material;
|
||||
using FModel.Views.Snooper.Shading;
|
||||
|
||||
namespace FModel.Views.Snooper.Models;
|
||||
|
||||
public class Cube : Model
|
||||
{
|
||||
public Cube(UMaterialInterface unrealMaterial) : base(unrealMaterial)
|
||||
public Cube(CStaticMesh mesh, UMaterialInterface unrealMaterial) : base(unrealMaterial)
|
||||
{
|
||||
Indices = new uint[]
|
||||
var lod = mesh.LODs[0];
|
||||
|
||||
Indices = new uint[lod.Indices.Value.Length];
|
||||
for (int i = 0; i < Indices.Length; i++)
|
||||
{
|
||||
0, 1, 2, 3, 4, 5,
|
||||
6, 7, 8, 9, 10, 11,
|
||||
12, 13, 14, 15, 16,
|
||||
17, 18, 19, 20, 21,
|
||||
22, 23, 24, 25, 26,
|
||||
27, 28, 29, 30, 31,
|
||||
32, 33, 34, 35
|
||||
};
|
||||
Vertices = new float[] {
|
||||
// I X Y Z Normals Tangent U V Layer
|
||||
-1, -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, .5f,
|
||||
-1, 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, .5f,
|
||||
-1, 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, .5f,
|
||||
-1, 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, .5f,
|
||||
-1, -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, .5f,
|
||||
-1, -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, .5f,
|
||||
Indices[i] = (uint) lod.Indices.Value[i];
|
||||
}
|
||||
|
||||
-1, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, .5f,
|
||||
-1, 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, .5f,
|
||||
-1, 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, .5f,
|
||||
-1, 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, .5f,
|
||||
-1, -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, .5f,
|
||||
-1, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, .5f,
|
||||
|
||||
-1, -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, .5f,
|
||||
-1, -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, .5f,
|
||||
-1, -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, .5f,
|
||||
-1, -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, .5f,
|
||||
-1, -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, .5f,
|
||||
-1, -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, .5f,
|
||||
|
||||
-1, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, .5f,
|
||||
-1, 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, .5f,
|
||||
-1, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, .5f,
|
||||
-1, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, .5f,
|
||||
-1, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, .5f,
|
||||
-1, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, .5f,
|
||||
|
||||
-1, -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, .5f,
|
||||
-1, 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, .5f,
|
||||
-1, 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, .5f,
|
||||
-1, 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, .5f,
|
||||
-1, -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, .5f,
|
||||
-1, -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, .5f,
|
||||
|
||||
-1, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, .5f,
|
||||
-1, 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, .5f,
|
||||
-1, 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, .5f,
|
||||
-1, 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, .5f,
|
||||
-1, -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, .5f,
|
||||
-1, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, .5f
|
||||
};
|
||||
Vertices = new float[lod.NumVerts * VertexSize];
|
||||
for (int i = 0; i < lod.Verts.Length; i++)
|
||||
{
|
||||
var count = 0;
|
||||
var baseIndex = i * VertexSize;
|
||||
var vert = lod.Verts[i];
|
||||
Vertices[baseIndex + count++] = i;
|
||||
Vertices[baseIndex + count++] = vert.Position.X * Constants.SCALE_DOWN_RATIO;
|
||||
Vertices[baseIndex + count++] = vert.Position.Z * Constants.SCALE_DOWN_RATIO;
|
||||
Vertices[baseIndex + count++] = vert.Position.Y * Constants.SCALE_DOWN_RATIO;
|
||||
Vertices[baseIndex + count++] = vert.Normal.X;
|
||||
Vertices[baseIndex + count++] = vert.Normal.Z;
|
||||
Vertices[baseIndex + count++] = vert.Normal.Y;
|
||||
Vertices[baseIndex + count++] = vert.Tangent.X;
|
||||
Vertices[baseIndex + count++] = vert.Tangent.Z;
|
||||
Vertices[baseIndex + count++] = vert.Tangent.Y;
|
||||
Vertices[baseIndex + count++] = vert.UV.U;
|
||||
Vertices[baseIndex + count++] = vert.UV.V;
|
||||
Vertices[baseIndex + count++] = .5f;
|
||||
}
|
||||
|
||||
Materials = new Material[1];
|
||||
Materials[0] = new Material(unrealMaterial) { IsUsed = true };
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ public class Model : IDisposable
|
|||
private VertexArrayObject<float, uint> _vao;
|
||||
|
||||
private readonly UObject _export;
|
||||
private readonly int _vertexSize = 13; // VertexIndex + Position + Normal + Tangent + UV + TextureLayer
|
||||
protected readonly int VertexSize = 13; // VertexIndex + Position + Normal + Tangent + UV + TextureLayer
|
||||
private const int _faceSize = 3;
|
||||
|
||||
public readonly string Path;
|
||||
|
|
@ -70,7 +70,7 @@ public class Model : IDisposable
|
|||
Name = Path.SubstringAfterLast('/').SubstringBefore('.');
|
||||
Type = export.ExportType;
|
||||
UvCount = 1;
|
||||
Box = new FBox(new FVector(-.65f), new FVector(.65f));
|
||||
Box = new FBox(new FVector(-2f), new FVector(2f));
|
||||
Transforms = new List<Transform>();
|
||||
}
|
||||
|
||||
|
|
@ -96,7 +96,7 @@ public class Model : IDisposable
|
|||
Morphs = new Morph[length];
|
||||
for (var i = 0; i < Morphs.Length; i++)
|
||||
{
|
||||
Morphs[i] = new Morph(Vertices, _vertexSize, morphTargets[i].Load<UMorphTarget>());
|
||||
Morphs[i] = new Morph(Vertices, VertexSize, morphTargets[i].Load<UMorphTarget>());
|
||||
ApplicationService.ApplicationView.Status.UpdateStatusLabel($"{Morphs[i].Name} ... {i}/{length}");
|
||||
}
|
||||
ApplicationService.ApplicationView.Status.UpdateStatusLabel("");
|
||||
|
|
@ -117,13 +117,13 @@ public class Model : IDisposable
|
|||
if (lod.VertexColors is { Length: > 0})
|
||||
{
|
||||
HasVertexColors = true;
|
||||
_vertexSize += 4; // + Color
|
||||
VertexSize += 4; // + Color
|
||||
}
|
||||
|
||||
if (skeleton != null)
|
||||
{
|
||||
Skeleton = new Skeleton(skeleton);
|
||||
_vertexSize += 8; // + BoneIds + BoneWeights
|
||||
VertexSize += 8; // + BoneIds + BoneWeights
|
||||
}
|
||||
|
||||
Indices = new uint[lod.Indices.Value.Length];
|
||||
|
|
@ -132,11 +132,11 @@ public class Model : IDisposable
|
|||
Indices[i] = (uint) lod.Indices.Value[i];
|
||||
}
|
||||
|
||||
Vertices = new float[lod.NumVerts * _vertexSize];
|
||||
Vertices = new float[lod.NumVerts * VertexSize];
|
||||
for (int i = 0; i < vertices.Length; i++)
|
||||
{
|
||||
var count = 0;
|
||||
var baseIndex = i * _vertexSize;
|
||||
var baseIndex = i * VertexSize;
|
||||
var vert = vertices[i];
|
||||
Vertices[baseIndex + count++] = i;
|
||||
Vertices[baseIndex + count++] = vert.Position.X * Constants.SCALE_DOWN_RATIO;
|
||||
|
|
@ -224,15 +224,15 @@ public class Model : IDisposable
|
|||
_vbo = new BufferObject<float>(Vertices, BufferTarget.ArrayBuffer);
|
||||
_vao = new VertexArrayObject<float, uint>(_vbo, _ebo);
|
||||
|
||||
_vao.VertexAttributePointer(0, 1, VertexAttribPointerType.Int, _vertexSize, 0); // vertex index
|
||||
_vao.VertexAttributePointer(1, 3, VertexAttribPointerType.Float, _vertexSize, 1); // position
|
||||
_vao.VertexAttributePointer(2, 3, VertexAttribPointerType.Float, _vertexSize, 4); // normal
|
||||
_vao.VertexAttributePointer(3, 3, VertexAttribPointerType.Float, _vertexSize, 7); // tangent
|
||||
_vao.VertexAttributePointer(4, 2, VertexAttribPointerType.Float, _vertexSize, 10); // uv
|
||||
if (!broken) _vao.VertexAttributePointer(5, 1, VertexAttribPointerType.Float, _vertexSize, 12); // texture index
|
||||
_vao.VertexAttributePointer(6, 4, VertexAttribPointerType.Float, _vertexSize, 13); // color
|
||||
_vao.VertexAttributePointer(7, 4, VertexAttribPointerType.Float, _vertexSize, 17); // boneids
|
||||
_vao.VertexAttributePointer(8, 4, VertexAttribPointerType.Float, _vertexSize, 21); // boneweights
|
||||
_vao.VertexAttributePointer(0, 1, VertexAttribPointerType.Int, VertexSize, 0); // vertex index
|
||||
_vao.VertexAttributePointer(1, 3, VertexAttribPointerType.Float, VertexSize, 1); // position
|
||||
_vao.VertexAttributePointer(2, 3, VertexAttribPointerType.Float, VertexSize, 4); // normal
|
||||
_vao.VertexAttributePointer(3, 3, VertexAttribPointerType.Float, VertexSize, 7); // tangent
|
||||
_vao.VertexAttributePointer(4, 2, VertexAttribPointerType.Float, VertexSize, 10); // uv
|
||||
if (!broken) _vao.VertexAttributePointer(5, 1, VertexAttribPointerType.Float, VertexSize, 12); // texture index
|
||||
_vao.VertexAttributePointer(6, 4, VertexAttribPointerType.Float, VertexSize, 13); // color
|
||||
_vao.VertexAttributePointer(7, 4, VertexAttribPointerType.Float, VertexSize, 17); // boneids
|
||||
_vao.VertexAttributePointer(8, 4, VertexAttribPointerType.Float, VertexSize, 21); // boneweights
|
||||
|
||||
SetupInstances(); // instanced models transform
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ using CUE4Parse.UE4.Assets.Exports.Texture;
|
|||
using CUE4Parse.UE4.Objects.Core.Math;
|
||||
using CUE4Parse.UE4.Objects.Engine;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using FModel.Creator;
|
||||
using FModel.Extensions;
|
||||
using FModel.Settings;
|
||||
using FModel.Views.Snooper.Buffers;
|
||||
using FModel.Views.Snooper.Lights;
|
||||
|
|
@ -36,6 +38,7 @@ public class Renderer : IDisposable
|
|||
public bool ShowLights;
|
||||
public int VertexColor;
|
||||
|
||||
public Camera CameraOp { get; }
|
||||
public PickingTexture Picking { get; }
|
||||
public Options Options { get; }
|
||||
|
||||
|
|
@ -44,6 +47,7 @@ public class Renderer : IDisposable
|
|||
_skybox = new Skybox();
|
||||
_grid = new Grid();
|
||||
|
||||
CameraOp = new Camera();
|
||||
Picking = new PickingTexture(width, height);
|
||||
Options = new Options();
|
||||
|
||||
|
|
@ -52,17 +56,25 @@ public class Renderer : IDisposable
|
|||
VertexColor = 0; // default
|
||||
}
|
||||
|
||||
public Camera Load(CancellationToken cancellationToken, UObject export)
|
||||
public void Load(CancellationToken cancellationToken, UObject export)
|
||||
{
|
||||
ShowLights = false;
|
||||
return export switch
|
||||
switch (export)
|
||||
{
|
||||
UStaticMesh st => LoadStaticMesh(st),
|
||||
USkeletalMesh sk => LoadSkeletalMesh(sk),
|
||||
UMaterialInstance mi => LoadMaterialInstance(mi),
|
||||
UWorld wd => LoadWorld(cancellationToken, wd, Transform.Identity),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(export))
|
||||
};
|
||||
case UStaticMesh st:
|
||||
LoadStaticMesh(st);
|
||||
break;
|
||||
case USkeletalMesh sk:
|
||||
LoadSkeletalMesh(sk);
|
||||
break;
|
||||
case UMaterialInstance mi:
|
||||
LoadMaterialInstance(mi);
|
||||
break;
|
||||
case UWorld wd:
|
||||
LoadWorld(cancellationToken, wd, Transform.Identity);
|
||||
CameraOp.Mode = Camera.WorldMode.FlyCam;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void Swap(UMaterialInstance unrealMaterial)
|
||||
|
|
@ -97,15 +109,15 @@ public class Renderer : IDisposable
|
|||
Options.SetupModelsAndLights();
|
||||
}
|
||||
|
||||
public void Render(Camera cam)
|
||||
public void Render()
|
||||
{
|
||||
var viewMatrix = cam.GetViewMatrix();
|
||||
var projMatrix = cam.GetProjectionMatrix();
|
||||
var viewMatrix = CameraOp.GetViewMatrix();
|
||||
var projMatrix = CameraOp.GetProjectionMatrix();
|
||||
|
||||
if (ShowSkybox) _skybox.Render(viewMatrix, projMatrix);
|
||||
if (ShowGrid) _grid.Render(viewMatrix, projMatrix, cam.Near, cam.Far);
|
||||
if (ShowGrid) _grid.Render(viewMatrix, projMatrix, CameraOp.Near, CameraOp.Far);
|
||||
|
||||
_shader.Render(viewMatrix, cam.Position, projMatrix);
|
||||
_shader.Render(viewMatrix, CameraOp.Position, projMatrix);
|
||||
for (int i = 0; i < 5; i++)
|
||||
_shader.SetUniform($"bVertexColors[{i}]", i == VertexColor);
|
||||
|
||||
|
|
@ -132,7 +144,7 @@ public class Renderer : IDisposable
|
|||
// outline pass
|
||||
if (Options.TryGetModel(out var selected) && selected.Show)
|
||||
{
|
||||
_outline.Render(viewMatrix, cam.Position, projMatrix);
|
||||
_outline.Render(viewMatrix, CameraOp.Position, projMatrix);
|
||||
selected.Outline(_outline);
|
||||
}
|
||||
|
||||
|
|
@ -140,55 +152,73 @@ public class Renderer : IDisposable
|
|||
Picking.Render(viewMatrix, projMatrix, Options.Models);
|
||||
}
|
||||
|
||||
private Camera SetupCamera(FBox box)
|
||||
{
|
||||
var far = box.Max.AbsMax();
|
||||
return new Camera(box, far * 50f);
|
||||
}
|
||||
|
||||
private Camera LoadStaticMesh(UStaticMesh original)
|
||||
private void LoadStaticMesh(UStaticMesh original)
|
||||
{
|
||||
var guid = original.LightingGuid;
|
||||
if (Options.TryGetModel(guid, out var model))
|
||||
{
|
||||
model.AddInstance(Transform.Identity);
|
||||
Application.Current.Dispatcher.Invoke(() => model.SetupInstances());
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!original.TryConvert(out var mesh))
|
||||
return null;
|
||||
return;
|
||||
|
||||
Options.Models[guid] = new Model(original, mesh);
|
||||
Options.SelectModel(guid);
|
||||
return SetupCamera(Options.Models[guid].Box);
|
||||
SetupCamera(Options.Models[guid].Box);
|
||||
}
|
||||
|
||||
private Camera LoadSkeletalMesh(USkeletalMesh original)
|
||||
private void LoadSkeletalMesh(USkeletalMesh original)
|
||||
{
|
||||
var guid = Guid.NewGuid();
|
||||
if (Options.Models.ContainsKey(guid) || !original.TryConvert(out var mesh)) return null;
|
||||
if (Options.Models.ContainsKey(guid) || !original.TryConvert(out var mesh)) return;
|
||||
|
||||
Options.Models[guid] = new Model(original, mesh);
|
||||
Options.SelectModel(guid);
|
||||
return SetupCamera(Options.Models[guid].Box);
|
||||
SetupCamera(Options.Models[guid].Box);
|
||||
}
|
||||
|
||||
private Camera LoadMaterialInstance(UMaterialInstance original)
|
||||
private void LoadMaterialInstance(UMaterialInstance original)
|
||||
{
|
||||
var guid = Guid.NewGuid();
|
||||
if (Options.Models.ContainsKey(guid)) return null;
|
||||
if (!Utils.TryLoadObject("Engine/Content/EditorMeshes/EditorCube.EditorCube", out UStaticMesh editorCube))
|
||||
return;
|
||||
|
||||
Options.Models[guid] = new Cube(original);
|
||||
var guid = editorCube.LightingGuid;
|
||||
if (Options.TryGetModel(guid, out var model))
|
||||
{
|
||||
model.Materials[0].SwapMaterial(original);
|
||||
Application.Current.Dispatcher.Invoke(() => model.Materials[0].Setup(Options, model.UvCount));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!editorCube.TryConvert(out var mesh))
|
||||
return;
|
||||
|
||||
Options.Models[guid] = new Cube(mesh, original);
|
||||
Options.SelectModel(guid);
|
||||
return SetupCamera(Options.Models[guid].Box);
|
||||
SetupCamera(Options.Models[guid].Box);
|
||||
}
|
||||
|
||||
private Camera LoadWorld(CancellationToken cancellationToken, UWorld original, Transform transform)
|
||||
private void SetupCamera(FBox box) => CameraOp.Setup(box);
|
||||
|
||||
private void LoadWorld(CancellationToken cancellationToken, UWorld original, Transform transform)
|
||||
{
|
||||
var cam = new Camera(new Vector3(0f, 5f, 5f), Vector3.Zero, 1000f, 5f);
|
||||
CameraOp.Setup(new FBox(FVector.ZeroVector, new FVector(0, 10, 10)));
|
||||
if (original.PersistentLevel.Load<ULevel>() is not { } persistentLevel)
|
||||
return cam;
|
||||
return;
|
||||
|
||||
if (persistentLevel.TryGetValue(out FSoftObjectPath runtimeCell, "WorldPartitionRuntimeCell") &&
|
||||
Utils.TryLoadObject(runtimeCell.AssetPathName.Text.SubstringBeforeWithLast(".") + runtimeCell.SubPathString.SubstringAfterLast("."), out UObject worldPartition))
|
||||
{
|
||||
var ratio = MathF.Pow(Constants.SCALE_DOWN_RATIO, 2);
|
||||
var position = worldPartition.GetOrDefault("Position", FVector.ZeroVector).ToMapVector() * Constants.SCALE_DOWN_RATIO;
|
||||
var box = worldPartition.GetOrDefault("ContentBounds", new FBox(FVector.ZeroVector, FVector.OneVector));
|
||||
box.Min *= ratio;box.Max *= ratio;
|
||||
|
||||
CameraOp.Teleport(position, box, true);
|
||||
}
|
||||
|
||||
var length = persistentLevel.Actors.Length;
|
||||
for (var i = 0; i < length; i++)
|
||||
|
|
@ -200,27 +230,22 @@ public class Renderer : IDisposable
|
|||
continue;
|
||||
|
||||
Services.ApplicationService.ApplicationView.Status.UpdateStatusLabel($"{original.Name} ... {i}/{length}");
|
||||
WorldCamera(actor, ref cam);
|
||||
WorldCamera(actor);
|
||||
// WorldLight(actor);
|
||||
WorldMesh(actor, transform);
|
||||
AdditionalWorlds(actor, transform.Matrix, cancellationToken);
|
||||
}
|
||||
Services.ApplicationService.ApplicationView.Status.UpdateStatusLabel($"{original.Name} ... {length}/{length}");
|
||||
return cam;
|
||||
}
|
||||
|
||||
private void WorldCamera(UObject actor, ref Camera cam)
|
||||
private void WorldCamera(UObject actor)
|
||||
{
|
||||
if (actor.ExportType != "LevelBounds" || !actor.TryGetValue(out FPackageIndex boxComponent, "BoxComponent") ||
|
||||
boxComponent.Load() is not { } boxObject) return;
|
||||
|
||||
var direction = boxObject.GetOrDefault("RelativeLocation", FVector.ZeroVector).ToMapVector() * Constants.SCALE_DOWN_RATIO;
|
||||
var position = boxObject.GetOrDefault("RelativeScale3D", FVector.OneVector).ToMapVector() / 2f * Constants.SCALE_DOWN_RATIO;
|
||||
var far = position.AbsMax();
|
||||
cam = new Camera(
|
||||
new Vector3(position.X, position.Y, position.Z),
|
||||
new Vector3(direction.X, direction.Y, direction.Z),
|
||||
far * 25f, Math.Max(5f, far / 10f));
|
||||
CameraOp.Setup(new FBox(direction, position));
|
||||
}
|
||||
|
||||
private void WorldLight(UObject actor)
|
||||
|
|
@ -344,12 +369,19 @@ public class Renderer : IDisposable
|
|||
};
|
||||
|
||||
for (int j = 0; j < additionalWorlds.Length; j++)
|
||||
if (Creator.Utils.TryLoadObject(additionalWorlds[j].AssetPathName.Text, out UWorld w))
|
||||
if (Utils.TryLoadObject(additionalWorlds[j].AssetPathName.Text, out UWorld w))
|
||||
LoadWorld(cancellationToken, w, transform);
|
||||
}
|
||||
|
||||
public void WindowResized(int width, int height)
|
||||
{
|
||||
CameraOp.AspectRatio = width / (float) height;
|
||||
Picking.WindowResized(width, height);
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
UserSettings.Default.CameraMode = CameraOp.Mode;
|
||||
UserSettings.Default.ShowSkybox = ShowSkybox;
|
||||
UserSettings.Default.ShowGrid = ShowGrid;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ public class SnimGui
|
|||
ImGui.SetNextItemOpen(true, ImGuiCond.Appearing);
|
||||
if (ImGui.CollapsingHeader("Camera"))
|
||||
{
|
||||
s.Camera.ImGuiCamera();
|
||||
s.Renderer.CameraOp.ImGuiCamera();
|
||||
}
|
||||
|
||||
ImGui.SetNextItemOpen(true, ImGuiCond.Appearing);
|
||||
|
|
@ -351,7 +351,7 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio
|
|||
if (ImGui.Selectable("Teleport To"))
|
||||
{
|
||||
var instancePos = model.Transforms[model.SelectedInstance].Position;
|
||||
s.Camera.Teleport(instancePos, model.Box);
|
||||
s.Renderer.CameraOp.Teleport(instancePos, model.Box);
|
||||
}
|
||||
|
||||
if (ImGui.Selectable("Delete")) s.Renderer.Options.Models.Remove(guid);
|
||||
|
|
@ -524,7 +524,7 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio
|
|||
ImGui.SliderInt("", ref model.SelectedInstance, 0, model.TransformsCount - 1, "Instance %i", ImGuiSliderFlags.AlwaysClamp);
|
||||
ImGui.EndDisabled(); ImGui.PopID();
|
||||
|
||||
model.Transforms[model.SelectedInstance].ImGuiTransform(s.Camera.Speed / 100f);
|
||||
model.Transforms[model.SelectedInstance].ImGuiTransform(s.Renderer.CameraOp.Speed / 100f);
|
||||
model.UpdateMatrix(model.SelectedInstance);
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
|
|
@ -653,7 +653,7 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio
|
|||
largest.Y -= ImGui.GetScrollY();
|
||||
|
||||
var size = new Vector2(largest.X, largest.Y);
|
||||
s.Camera.AspectRatio = size.X / size.Y;
|
||||
s.Renderer.CameraOp.AspectRatio = size.X / size.Y;
|
||||
ImGui.ImageButton(s.Framebuffer.GetPointer(), size, new Vector2(0, 1), new Vector2(1, 0), 0);
|
||||
|
||||
if (ImGui.IsItemHovered())
|
||||
|
|
@ -674,7 +674,7 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio
|
|||
|
||||
if (ImGui.IsMouseDragging(ImGuiMouseButton.Left) && _viewportFocus)
|
||||
{
|
||||
s.Camera.Modify(ImGui.GetIO().MouseDelta);
|
||||
s.Renderer.CameraOp.Modify(ImGui.GetIO().MouseDelta);
|
||||
}
|
||||
|
||||
// if left button up and mouse was in viewport
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ using System.Runtime.InteropServices;
|
|||
using System.Threading;
|
||||
using System.Windows;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using FModel.Settings;
|
||||
using FModel.Views.Snooper.Buffers;
|
||||
using ImGuiNET;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
|
|
@ -19,19 +18,15 @@ namespace FModel.Views.Snooper;
|
|||
|
||||
public class Snooper : GameWindow
|
||||
{
|
||||
public Camera Camera;
|
||||
public readonly FramebufferObject Framebuffer;
|
||||
public readonly Renderer Renderer;
|
||||
|
||||
private readonly SnimGui _gui;
|
||||
|
||||
private float _previousSpeed;
|
||||
|
||||
private bool _init;
|
||||
|
||||
public Snooper(GameWindowSettings gwSettings, NativeWindowSettings nwSettings) : base(gwSettings, nwSettings)
|
||||
{
|
||||
Camera = new Camera();
|
||||
Framebuffer = new FramebufferObject(ClientSize);
|
||||
Renderer = new Renderer(ClientSize.X, ClientSize.Y);
|
||||
|
||||
|
|
@ -41,13 +36,7 @@ public class Snooper : GameWindow
|
|||
|
||||
public bool TryLoadExport(CancellationToken cancellationToken, UObject export)
|
||||
{
|
||||
var newCamera = Renderer.Load(cancellationToken, export) ?? new Camera();
|
||||
if (newCamera.Speed > _previousSpeed)
|
||||
{
|
||||
newCamera.Zoom = Camera.Zoom;
|
||||
Camera = newCamera;
|
||||
_previousSpeed = Camera.Speed;
|
||||
}
|
||||
Renderer.Load(cancellationToken, export);
|
||||
return Renderer.Options.Models.Count > 0;
|
||||
}
|
||||
|
||||
|
|
@ -55,13 +44,12 @@ public class Snooper : GameWindow
|
|||
{
|
||||
if (clear)
|
||||
{
|
||||
_previousSpeed = 0f;
|
||||
Renderer.CameraOp.Speed = 0;
|
||||
Renderer.Options.ResetModelsAndLights();
|
||||
Renderer.Options.SelectModel(Guid.Empty);
|
||||
Renderer.Save();
|
||||
}
|
||||
|
||||
UserSettings.Default.CameraMode = Camera.Mode;
|
||||
GLFW.SetWindowShouldClose(WindowPtr, value); // start / stop game loop
|
||||
IsVisible = !value;
|
||||
}
|
||||
|
|
@ -134,7 +122,7 @@ public class Snooper : GameWindow
|
|||
Framebuffer.Bind(); // switch to viewport background
|
||||
ClearWhatHasBeenDrawn(); // clear viewport background
|
||||
|
||||
Renderer.Render(Camera);
|
||||
Renderer.Render();
|
||||
|
||||
Framebuffer.BindMsaa();
|
||||
Framebuffer.Bind(0); // switch to window background
|
||||
|
|
@ -163,7 +151,7 @@ public class Snooper : GameWindow
|
|||
if (!IsVisible || ImGui.GetIO().WantTextInput)
|
||||
return;
|
||||
|
||||
Camera.Modify(KeyboardState, (float) e.Time);
|
||||
Renderer.CameraOp.Modify(KeyboardState, (float) e.Time);
|
||||
|
||||
if (KeyboardState.IsKeyPressed(Keys.H))
|
||||
WindowShouldClose(true, false);
|
||||
|
|
@ -177,9 +165,8 @@ public class Snooper : GameWindow
|
|||
|
||||
GL.Viewport(0, 0, e.Width, e.Height);
|
||||
|
||||
Camera.AspectRatio = e.Width / (float) e.Height;
|
||||
Framebuffer.WindowResized(e.Width, e.Height);
|
||||
Renderer.Picking.WindowResized(e.Width, e.Height);
|
||||
Renderer.WindowResized(e.Width, e.Height);
|
||||
|
||||
_gui.Controller.WindowResized(e.Width, e.Height);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user