mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/PCK-Studio.git
synced 2026-06-02 04:47:03 +00:00
Update Camera setup
This commit is contained in:
@@ -10,17 +10,8 @@ namespace PckStudio.Rendering.Camera
|
||||
{
|
||||
internal abstract class Camera
|
||||
{
|
||||
public abstract float Distance { get; set; }
|
||||
|
||||
public abstract Vector2 Position { get; set; }
|
||||
|
||||
internal abstract Matrix4 GetViewProjection();
|
||||
|
||||
internal abstract void Update(float aspect);
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Position: {Position}\nDistance: {Distance}";
|
||||
}
|
||||
protected Matrix4 projectionMatrix;
|
||||
|
||||
public abstract Matrix4 GetViewProjection();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Octokit;
|
||||
using OpenTK;
|
||||
|
||||
namespace PckStudio.Rendering.Camera
|
||||
{
|
||||
internal class PerspectiveCamera : Camera
|
||||
{
|
||||
public override float Distance
|
||||
public float Distance
|
||||
{
|
||||
get => _position.Z;
|
||||
set => _position.Z = value;
|
||||
get => _distance;
|
||||
set
|
||||
{
|
||||
_distance = value;
|
||||
UpdateViewMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
public override Vector2 Position
|
||||
{
|
||||
get => _position.Xy;
|
||||
set => _position.Xy = value;
|
||||
}
|
||||
public Size ViewportSize { get; set; }
|
||||
|
||||
public Vector3 WorldPosition => _position;
|
||||
public Vector3 FocalPoint
|
||||
{
|
||||
get => _focalPoint;
|
||||
set
|
||||
{
|
||||
_focalPoint = value;
|
||||
UpdateViewMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
public Vector2 Rotation
|
||||
{
|
||||
@@ -30,67 +42,131 @@ namespace PckStudio.Rendering.Camera
|
||||
{
|
||||
_rotation.X = MathHelper.Clamp(value.X, -180f, 180f);
|
||||
_rotation.Y = MathHelper.Clamp(value.Y, -180f, 180f);
|
||||
UpdateViewMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 Orientation => -Vector3.UnitZ;
|
||||
|
||||
public Vector3 Up = Vector3.UnitY;
|
||||
|
||||
public float MinimumFov { get; set; } = 30f;
|
||||
public float MaximumFov { get; set; } = 120f;
|
||||
|
||||
public float Fov
|
||||
{
|
||||
get => fov;
|
||||
set => fov = MathHelper.Clamp(value, MinimumFov, MaximumFov);
|
||||
}
|
||||
|
||||
public PerspectiveCamera(Vector3 position, Vector2 rotation, float fov) : this(position.Xy, position.Z, rotation, fov)
|
||||
{ }
|
||||
|
||||
public PerspectiveCamera(Vector2 position, float distance, Vector2 rotation, float fov)
|
||||
public PerspectiveCamera(float fov, Vector3 position)
|
||||
{
|
||||
LookAt(position);
|
||||
Distance = distance;
|
||||
Fov = fov;
|
||||
_position = position;
|
||||
_focalPoint = Vector3.Zero;
|
||||
}
|
||||
|
||||
private Matrix4 viewProjection;
|
||||
private Matrix4 viewMatrix;
|
||||
private float fov;
|
||||
|
||||
private float _distance;
|
||||
private Vector3 _position;
|
||||
private Vector2 _rotation;
|
||||
private Vector3 _focalPoint;
|
||||
|
||||
|
||||
internal override Matrix4 GetViewProjection()
|
||||
public override Matrix4 GetViewProjection()
|
||||
{
|
||||
return viewProjection;
|
||||
return viewMatrix * projectionMatrix;
|
||||
}
|
||||
|
||||
private void UpdateView()
|
||||
private void UpdateViewMatrix()
|
||||
{
|
||||
// m_Yaw = m_Pitch = 0.0f; // Lock the camera's rotation
|
||||
_position = CalculatePosition();
|
||||
|
||||
Matrix4 rotation = Matrix4.CreateFromAxisAngle(new Vector3(-1f, 0f, 0f), MathHelper.DegreesToRadians(Rotation.X))
|
||||
* Matrix4.CreateFromAxisAngle(new Vector3(0f, 1f, 0f), MathHelper.DegreesToRadians(Rotation.Y));
|
||||
Quaternion orientation = GetOrientation();
|
||||
var rotation = Matrix4.CreateTranslation(_position);
|
||||
rotation *= Matrix4.CreateFromQuaternion(orientation);
|
||||
rotation *= Matrix4.CreateTranslation(_position).Inverted();
|
||||
|
||||
viewMatrix = Matrix4.LookAt(_position, _position + Orientation, Up) * rotation;
|
||||
viewMatrix = Matrix4.CreateTranslation(_position) * rotation;
|
||||
viewMatrix = viewMatrix.Inverted();
|
||||
}
|
||||
|
||||
internal override void Update(float aspect)
|
||||
public void Update(float aspect)
|
||||
{
|
||||
UpdateView();
|
||||
var projection = Matrix4.CreatePerspectiveFieldOfView((float)MathHelper.DegreesToRadians(Fov), aspect, 1f, 1000f);
|
||||
viewProjection = viewMatrix * projection;
|
||||
UpdateViewMatrix();
|
||||
projectionMatrix = Matrix4.CreatePerspectiveFieldOfView((float)MathHelper.DegreesToRadians(Fov), aspect, 1f, 1000f);
|
||||
}
|
||||
|
||||
internal void LookAt(Vector2 pos)
|
||||
private Vector2 GetPanSpeed()
|
||||
{
|
||||
Position = pos;
|
||||
float x = Math.Min(ViewportSize.Width / 100.0f, 1.4f); // max = 2.4f
|
||||
float xFactor = 0.0366f * (x * x) - 0.1778f * x + 0.3021f;
|
||||
|
||||
float y = Math.Min(ViewportSize.Height / 100.0f, 1.4f); // max = 2.4f
|
||||
float yFactor = 0.0366f * (y * y) - 0.1778f * y + 0.3021f;
|
||||
|
||||
return new Vector2(xFactor, yFactor);
|
||||
}
|
||||
|
||||
public void Pan(Vector2 delta)
|
||||
{
|
||||
Pan(delta.X, delta.Y);
|
||||
}
|
||||
|
||||
public void Pan(float deltaX, float deltaY)
|
||||
{
|
||||
Vector2 panSpeed = GetPanSpeed();
|
||||
_focalPoint += -GetRightDirection() * deltaX * panSpeed.X * _distance;
|
||||
_focalPoint += GetUpDirection() * deltaY * panSpeed.Y * _distance;
|
||||
UpdateViewMatrix();
|
||||
}
|
||||
|
||||
public void Rotate(Vector2 delta)
|
||||
{
|
||||
Rotate(delta.X, delta.Y);
|
||||
}
|
||||
|
||||
public void Rotate(float deltaX,float deltaY)
|
||||
{
|
||||
const float RotationSpeed = 0.8f;
|
||||
float yawSign = GetUpDirection().Y < 0 ? -1.0f : 1.0f;
|
||||
_rotation.Y += yawSign * deltaX * RotationSpeed;
|
||||
_rotation.X += deltaY * RotationSpeed;
|
||||
|
||||
UpdateViewMatrix();
|
||||
}
|
||||
|
||||
public Vector3 GetUpDirection()
|
||||
{
|
||||
return GetOrientation() * Up;
|
||||
}
|
||||
|
||||
public Vector3 GetRightDirection()
|
||||
{
|
||||
return GetOrientation() * Vector3.UnitX;
|
||||
}
|
||||
|
||||
public Vector3 GetForwardDirection()
|
||||
{
|
||||
return GetOrientation() * Orientation;
|
||||
}
|
||||
|
||||
private Vector3 CalculatePosition()
|
||||
{
|
||||
Vector3 forwadDirection = GetForwardDirection();
|
||||
return FocalPoint - forwadDirection * Distance;
|
||||
}
|
||||
|
||||
private Quaternion GetOrientation()
|
||||
{
|
||||
return new Quaternion(new Vector3(-Rotation));
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"FOV: {Fov}\nPosition: {Position}\nRotation: {Rotation}";
|
||||
return $"FOV: {Fov}\nPosition: {WorldPosition}\nRotation: {Rotation}";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -60,7 +60,6 @@ namespace PckStudio.Rendering
|
||||
timer.Tick += TimerTick;
|
||||
timer.Start();
|
||||
VSync = true;
|
||||
Camera = new PerspectiveCamera(Vector3.UnitZ, Vector2.Zero, 30f);
|
||||
}
|
||||
|
||||
private void TimerTick(object sender, EventArgs e)
|
||||
@@ -68,6 +67,13 @@ namespace PckStudio.Rendering
|
||||
OnTimerTick?.Invoke(sender, e);
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
protected override void OnResize(EventArgs e)
|
||||
{
|
||||
base.OnResize(e);
|
||||
Camera.Update(AspectRatio);
|
||||
Camera.ViewportSize = Size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -262,10 +262,11 @@ namespace PckStudio.Rendering
|
||||
private const float DefaultCameraDistance = 64f;
|
||||
private void InitializeCamera()
|
||||
{
|
||||
Camera = new PerspectiveCamera(new Vector2(0f, 5f), DefaultCameraDistance, Vector2.Zero, 60f)
|
||||
Camera = new PerspectiveCamera(60f, new Vector3(0f, 0f, 0f))
|
||||
{
|
||||
MinimumFov = 30f,
|
||||
MaximumFov = 120f,
|
||||
Distance = DefaultCameraDistance,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -473,7 +474,6 @@ namespace PckStudio.Rendering
|
||||
return true;
|
||||
case Keys.R:
|
||||
GlobalModelRotation = Vector2.Zero;
|
||||
CameraTarget = Vector2.Zero;
|
||||
Camera.Distance = DefaultCameraDistance;
|
||||
return true;
|
||||
case Keys.A:
|
||||
@@ -676,21 +676,21 @@ namespace PckStudio.Rendering
|
||||
{
|
||||
base.OnMouseMove(e);
|
||||
// Rotate the model
|
||||
if (_isLeftMouseDown)
|
||||
if (e.Button == MouseButtons.Left)
|
||||
{
|
||||
float rotationYDelta = (float)Math.Round((Cursor.Position.X - CurrentMouseLocation.X) * 0.5f);
|
||||
float rotationXDelta = (float)Math.Round(-(Cursor.Position.Y - CurrentMouseLocation.Y) * 0.5f);
|
||||
GlobalModelRotation += new Vector2(rotationXDelta, rotationYDelta);
|
||||
float deltaX = (Cursor.Position.X - CurrentMouseLocation.X) * 0.5f;
|
||||
float deltaY = (Cursor.Position.Y - CurrentMouseLocation.Y) * 0.5f;
|
||||
GlobalModelRotation += new Vector2(-deltaY, deltaX) * Camera.Distance * 0.015f;
|
||||
Cursor.Position = new Point((int)Math.Round(Screen.PrimaryScreen.Bounds.Width / 2d), (int)Math.Round(Screen.PrimaryScreen.Bounds.Height / 2d));
|
||||
CurrentMouseLocation = Cursor.Position;
|
||||
return;
|
||||
}
|
||||
// Move the model
|
||||
if (_isRightMouseDown)
|
||||
if (e.Button == MouseButtons.Right)
|
||||
{
|
||||
float deltaX = -(Cursor.Position.X - CurrentMouseLocation.X) * 0.05f / (float)MathHelper.DegreesToRadians(Camera.Fov);
|
||||
float deltaY = (Cursor.Position.Y - CurrentMouseLocation.Y) * 0.05f / (float)MathHelper.DegreesToRadians(Camera.Fov);
|
||||
CameraTarget += new Vector2(deltaX, deltaY);
|
||||
float deltaX = (Cursor.Position.X - CurrentMouseLocation.X) * 0.05f;
|
||||
float deltaY = (Cursor.Position.Y - CurrentMouseLocation.Y) * 0.05f;
|
||||
Camera.Pan(deltaX, deltaY);
|
||||
Cursor.Position = new Point((int)Math.Round(Screen.PrimaryScreen.Bounds.Width / 2d), (int)Math.Round(Screen.PrimaryScreen.Bounds.Height / 2d));
|
||||
CurrentMouseLocation = Cursor.Position;
|
||||
}
|
||||
@@ -704,26 +704,14 @@ namespace PckStudio.Rendering
|
||||
protected override void OnMouseDown(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseDown(e);
|
||||
if (!_isLeftMouseDown && e.Button == MouseButtons.Left)
|
||||
if (e.Button == MouseButtons.Right || e.Button == MouseButtons.Left)
|
||||
{
|
||||
// If the ray didn't hit the model then rotate the model
|
||||
PreviousMouseLocation = Cursor.Position; // Store the old mouse position to reset it when the action is over
|
||||
if (!IsMouseHidden) // Hide the mouse
|
||||
if (!IsMouseHidden)
|
||||
{
|
||||
IsMouseHidden = true;
|
||||
}
|
||||
CurrentMouseLocation = Cursor.Position; // Store the current mouse position to use it for the rotate action
|
||||
_isLeftMouseDown = true;
|
||||
}
|
||||
else if (!_isRightMouseDown && e.Button == MouseButtons.Right)
|
||||
{
|
||||
PreviousMouseLocation = Cursor.Position; // Store the old mouse position to reset it when the action is over
|
||||
if (!IsMouseHidden) // Hide the mouse
|
||||
{
|
||||
IsMouseHidden = true;
|
||||
}
|
||||
CurrentMouseLocation = Cursor.Position; // Store the current mouse position to use it for the move action
|
||||
_isRightMouseDown = true;
|
||||
PreviousMouseLocation = Cursor.Position;
|
||||
CurrentMouseLocation = Cursor.Position;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user