-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathCamera.cs
More file actions
112 lines (92 loc) · 4.26 KB
/
Camera.cs
File metadata and controls
112 lines (92 loc) · 4.26 KB
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
using OpenTK.Mathematics;
using System;
namespace MedViewer
{
public class Camera
{
// Those vectors are directions pointing outwards from the camera to define how it rotated.
private Vector3 _front = -Vector3.UnitZ;
private Vector3 _up = Vector3.UnitY;
private Vector3 _right = Vector3.UnitX;
// Rotation around the X axis (radians)
private float _pitch;
// Rotation around the Y axis (radians)
private float _yaw = -MathHelper.PiOver2; // Without this, you would be started rotated 90 degrees right.
// The field of view of the camera (radians)
private float _fov = MathHelper.PiOver2;
public Camera(Vector3 position, float aspectRatio)
{
Position = position;
AspectRatio = aspectRatio;
}
// The position of the camera
public Vector3 Position { get; set; }
// This is simply the aspect ratio of the viewport, used for the projection matrix.
public float AspectRatio { private get; set; }
public Vector3 Front => _front;
public Vector3 Up => _up;
public Vector3 Right => _right;
// We convert from degrees to radians as soon as the property is set to improve performance.
public float Pitch
{
get => MathHelper.RadiansToDegrees(_pitch);
set
{
// We clamp the pitch value between -89 and 89 to prevent the camera from going upside down, and a bunch
// of weird "bugs" when you are using euler angles for rotation.
// If you want to read more about this you can try researching a topic called gimbal lock
var angle = MathHelper.Clamp(value, -89f, 89f);
_pitch = MathHelper.DegreesToRadians(angle);
UpdateVectors();
}
}
// We convert from degrees to radians as soon as the property is set to improve performance.
public float Yaw
{
get => MathHelper.RadiansToDegrees(_yaw);
set
{
_yaw = MathHelper.DegreesToRadians(value);
UpdateVectors();
}
}
// The field of view (FOV) is the vertical angle of the camera view.
// This has been discussed more in depth in a previous tutorial,
// but in this tutorial, you have also learned how we can use this to simulate a zoom feature.
// We convert from degrees to radians as soon as the property is set to improve performance.
public float Fov
{
get => MathHelper.RadiansToDegrees(_fov);
set
{
var angle = MathHelper.Clamp(value, 1f, 45f);
_fov = MathHelper.DegreesToRadians(angle);
}
}
// Get the view matrix using the amazing LookAt function described more in depth on the web tutorials
public Matrix4 GetViewMatrix()
{
return Matrix4.LookAt(Position, Position + _front, _up);
}
// Get the projection matrix using the same method we have used up until this point
public Matrix4 GetProjectionMatrix()
{
return Matrix4.CreatePerspectiveFieldOfView(_fov, AspectRatio, 0.01f, 100f);
}
// This function is going to update the direction vertices using some of the math learned in the web tutorials.
private void UpdateVectors()
{
// First, the front matrix is calculated using some basic trigonometry.
_front.X = MathF.Cos(_pitch) * MathF.Cos(_yaw);
_front.Y = MathF.Sin(_pitch);
_front.Z = MathF.Cos(_pitch) * MathF.Sin(_yaw);
// We need to make sure the vectors are all normalized, as otherwise we would get some funky results.
_front = Vector3.Normalize(_front);
// Calculate both the right and the up vector using cross product.
// Note that we are calculating the right from the global up; this behaviour might
// not be what you need for all cameras so keep this in mind if you do not want a FPS camera.
_right = Vector3.Normalize(Vector3.Cross(_front, Vector3.UnitY));
_up = Vector3.Normalize(Vector3.Cross(_right, _front));
}
}
}