/
Arc.cs
143 lines (114 loc) · 4.47 KB
/
Arc.cs
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
namespace Pirates.Locked3rdPersonCamera
{
public class ArcBallCamera
{
// Rotation around the two axes
public float RotationX { get; set; }
public float RotationY { get; set; }
// Y axis rotation limits (radians)
public float MinRotationY { get; set; }
public float MaxRotationY { get; set; }
// Distance between the target and camera
public float Distance { get; set; }
// Distance limits
public float MinDistance { get; set; }
public float MaxDistance { get; set; }
// Calculated position and specified target
public Vector3 Position { get; private set; }
public Vector3 Target { get; set; }
private Matrix view;
public Matrix View
{
get { return view; }
set { view = value; }
}
private Vector3 eye;
public Vector3 Eye
{
get { return eye; }
set { eye = View.Translation; }
}
private ButtonState previous;
private MouseState lastMouseState;
public ArcBallCamera(Vector3 Target, float RotationX,
float RotationY, float MinRotationY, float MaxRotationY,
float Distance, float MinDistance, float MaxDistance)
{
this.Target = Target;
this.MinRotationY = MinRotationY;
this.MaxRotationY = MaxRotationY;
// Lock the y axis rotation between the min and max values
this.RotationY = MathHelper.Clamp(RotationY, MinRotationY,
MaxRotationY);
this.RotationX = RotationX;
this.MinDistance = MinDistance;
this.MaxDistance = MaxDistance;
previous = ButtonState.Released;
// Lock the distance between the min and max values
this.Distance = MathHelper.Clamp(Distance, MinDistance,
MaxDistance);
}
public void Move(float DistanceChange)
{
this.Distance += DistanceChange *0.1f;
this.Distance = MathHelper.Clamp(Distance, MinDistance,
MaxDistance);
}
public void Rotate(float RotationXChange, float RotationYChange)
{
this.RotationX += RotationXChange;
this.RotationY += -RotationYChange;
this.RotationY = MathHelper.Clamp(RotationY, MinRotationY,
MaxRotationY);
}
public void Translate(Vector3 PositionChange)
{
this.Position += PositionChange;
}
public Matrix Update()
{
updateCamera();
return UpdateMatrix();
}
public Matrix UpdateMatrix()
{
// Calculate rotation matrix from rotation values
Matrix rotation = Matrix.CreateFromYawPitchRoll(RotationX, -
RotationY, 0);
// Translate down the Z axis by the desired distance
// between the camera and object, then rotate that
// vector to find the camera offset from the target
Vector3 translation = new Vector3(0, 0, Distance);
translation = Vector3.Transform(translation, rotation);
Position = Target + translation;
// Calculate the up vector from the rotation matrix
Vector3 up = Vector3.Transform(Vector3.Up, rotation);
View = Matrix.CreateLookAt(Position, Target, up);
return View;
}
private void updateCamera()
{
MouseState mouseState = Mouse.GetState();
KeyboardState keyState = Keyboard.GetState();
float scrollDelta = (float)lastMouseState.ScrollWheelValue - (float)mouseState.ScrollWheelValue;
this.Move(scrollDelta);
if (mouseState.LeftButton == ButtonState.Pressed &&
previous == ButtonState.Pressed)
{
// Determine how much the camera should turn
float deltaX = (float)lastMouseState.X - (float)mouseState.X;
float deltaY = (float)lastMouseState.Y - (float)mouseState.Y;
// Rotate the camera
this.Rotate(deltaX * .001f, deltaY * .001f);
lastMouseState = mouseState;
}
else if (mouseState.LeftButton == ButtonState.Pressed)
{
lastMouseState = mouseState;
}
previous = mouseState.LeftButton;
}
}
}