ClassiCube/Camera.cs
UnknownShadow200 423d365267 Add everything.
2014-12-17 14:47:17 +11:00

138 lines
3.9 KiB
C#

using System;
using System.Drawing;
using System.Windows.Forms;
using OpenTK;
using OpenTK.Input;
namespace ClassicalSharp {
public abstract class Camera {
public Game Window;
public abstract Matrix4 GetProjection();
public abstract Matrix4 GetView();
public abstract bool IsThirdPerson { get; }
public virtual void Tick( double elapsed ) {
}
public virtual void MouseZoom( MouseWheelEventArgs e ) {
}
public abstract void RegrabMouse();
public virtual PickedPos GetPickedPos() {
return null;
}
}
public abstract class PerspectiveCamera : Camera {
protected Player player;
public PerspectiveCamera( Game window ) {
Window = window;
player = Window.LocalPlayer;
}
public override Matrix4 GetProjection() {
float fovy = (float)Utils.DegreesToRadians( 70 );
float aspectRatio = (float)Window.Width / Window.Height;
return Matrix4.CreatePerspectiveFieldOfView( fovy, aspectRatio, 0.1f, Window.ViewDistance );
}
public override PickedPos GetPickedPos() {
Vector3 dir = Utils.GetDirectionVector( player.YawRadians, player.PitchRadians + Math.PI );
Vector3 eyePos = player.EyePosition;
float reach = Window.LocalPlayer.ReachDistance;
return Picking.GetPickedBlockPos( Window, eyePos, dir, reach );
}
Point previous, delta;
Vector2 Orientation;
void CentreMousePosition() {
if( !Window.Focused ) return;
Point current = Cursor.Position;
delta = new Point( current.X - previous.X, current.Y - previous.Y );
Rectangle bounds = Window.Bounds;
int cenX = bounds.Left + bounds.Width / 2;
int cenY = bounds.Top + bounds.Height / 2;
Cursor.Position = new Point( cenX, cenY );
previous = new Point( cenX, cenY );
}
public override void RegrabMouse() {
Rectangle bounds = Window.Bounds;
int cenX = bounds.Left + bounds.Width / 2;
int cenY = bounds.Top + bounds.Height / 2;
Cursor.Position = new Point( cenX, cenY );
previous = new Point( cenX, cenY );
delta = Point.Empty;
}
const float sensitivity = 0.01f; // max 0.025?
private void UpdateMouseRotation() {
Orientation.X += delta.X * sensitivity;
Orientation.Y += delta.Y * sensitivity;
Clamp( ref Orientation.Y, halfPi + 0.01f, threeHalfPi - 0.01f );
LocationUpdate update = LocationUpdate.MakeOri(
(float)Utils.RadiansToDegrees( Orientation.X ),
(float)Utils.RadiansToDegrees( Orientation.Y - Math.PI )
);
Window.LocalPlayer.SetLocation( update, true );
}
const float halfPi = (float)( Math.PI / 2 );
const float threeHalfPi = (float)( 3 * Math.PI / 2 );
public override void Tick( double elapsed ) {
if( Window.ScreenLockedInput ) return;
CentreMousePosition();
UpdateMouseRotation();
}
static void Clamp( ref float value, float min, float max ) {
if( value < min ) value = min;
if( value > max ) value = max;
}
}
public class ThirdPersonCamera : PerspectiveCamera {
public ThirdPersonCamera( Game window ) : base( window ) {
}
float distance = 3;
public override void MouseZoom( MouseWheelEventArgs e ) {
distance -= e.DeltaPrecise;
if( distance < 2 ) distance = 2;
}
public override Matrix4 GetView() {
Vector3 eyePos = player.EyePosition;
Vector3 cameraPos = eyePos - Utils.GetDirectionVector( player.YawRadians, player.PitchRadians + Math.PI ) * distance;
return Matrix4.LookAt( cameraPos, eyePos, Vector3.UnitY );
}
public override bool IsThirdPerson {
get { return true; }
}
}
public class FirstPersonCamera : PerspectiveCamera {
public FirstPersonCamera( Game window ) : base( window ) {
}
public override Matrix4 GetView() {
Vector3 eyePos = player.EyePosition;
Vector3 cameraDir = Utils.GetDirectionVector( player.YawRadians, player.PitchRadians + Math.PI );
return Matrix4.LookAt( eyePos, eyePos + cameraDir, Vector3.UnitY );
}
public override bool IsThirdPerson {
get { return false; }
}
}
}