budnhead/org.budnhead/graphics/GLCameraController.cs

197 lines
4.1 KiB
C#

/**
* GLCameraController
*
* Default camera controller using mouse dragging
*
**/
using System;
using System.Drawing;
using OpenTK;
using System.Drawing.Drawing2D;
using org.budnhead.core;
namespace org.budnhead.graphics
{
public class GLCameraController
{
private SceneWindow sceneWindow;
private GLCamera camera;
private Point mouseCapturePosition;
private bool mouseCaptured;
public Limits LimitUpDown { get; set; } = new Limits(MathHelper.PiOver2,MathHelper.Pi);
public Limits LimitLeftRight { get; set; } = new Limits(-MathHelper.Pi, MathHelper.Pi);
public GLCameraController(GLCamera camera, SceneWindow sceneWindow){
this.sceneWindow = sceneWindow;
this.camera = camera;
}
public GLCameraController(GLCamera camera){
this.sceneWindow = null;
this.camera = camera;
}
public SceneWindow SceneWindow {
get { return sceneWindow; }
set {
releaseSceneWindow();
sceneWindow = value;
allocSceneWindow();
}
}
public GLCamera Camera {
get { return this.camera; }
set { this.camera = value; }
}
private void releaseSceneWindow(){
if (sceneWindow != null){
sceneWindow.MouseWheel -= SceneWindow_MouseWheel;
sceneWindow.MouseDown -= SceneWindow_MouseDown;
sceneWindow.MouseUp -= SceneWindow_MouseUp;
sceneWindow.MouseMove -= SceneWindow_MouseMove;
}
}
private void allocSceneWindow(){
if (sceneWindow != null){
sceneWindow.MouseWheel += SceneWindow_MouseWheel;
sceneWindow.MouseDown += SceneWindow_MouseDown;
sceneWindow.MouseUp += SceneWindow_MouseUp;
sceneWindow.MouseMove += SceneWindow_MouseMove;
}
}
private void captureMouse()
{
mouseCapturePosition = new Point(sceneWindow.Mouse.X, sceneWindow.Mouse.Y);
mouseCaptured = true;
SceneWindow.CursorVisible = false;
}
private void releaseMouse()
{
mouseCaptured = false;
SceneWindow.CursorVisible = true;
}
void SceneWindow_MouseWheel(object sender, OpenTK.Input.MouseWheelEventArgs e)
{
Vector3 p, // Camera position
v; // Camera viewing direction
p = camera.Position;
v = camera.View;
p += v * e.Delta;
camera.Position = p;
}
void SceneWindow_MouseDown(object sender, OpenTK.Input.MouseButtonEventArgs e)
{
switch (e.Button)
{
case OpenTK.Input.MouseButton.Left:
//markMouse(e.X,e.Y);
break;
case OpenTK.Input.MouseButton.Right:
captureMouse();
break;
}
}
void SceneWindow_MouseUp(object sender, OpenTK.Input.MouseButtonEventArgs e)
{
releaseMouse();
}
void SceneWindow_MouseMove(object sender, OpenTK.Input.MouseMoveEventArgs e)
{
if (mouseCaptured)
{
Point delta = new Point(e.X - mouseCapturePosition.X, e.Y - mouseCapturePosition.Y);
onMouseCapturedMove(delta);
mouseCapturePosition = e.Position;
}
else {
}
}
protected virtual void onMouseCapturedMove(Point delta)
{
rotateLeftRight(((float)delta.X) / -50.0f);
rotateUpDown(((float)delta.Y) / -50.0f);
}
public void rotateUpDown(float arc)
{
Vector3 v, // view direction
t, // top direction
r; // rotation axis
v = camera.View;
t = camera.Top;
r = Vector3.Cross(v, t);
Matrix3 mrot = Matrix3.CreateFromAxisAngle(r, arc);
v *= mrot;
t *= mrot;
float angle = (float)Math.Acos(Vector3.Dot(v, Vector3.UnitZ));
if ((camera.View.X * v.X <= 0)||(camera.View.Y * v.Y <= 0)){
angle = (float)((2 * Math.PI) - angle);
}
Console.WriteLine("Angle: {0}",angle);
if (LimitUpDown.ValueIsValid(angle)){
camera.View = v;
camera.Top = t;
}
}
public void rotateLeftRight(float arc)
{
Vector3 v, // view direction
t, // top direction
r; // rotation axis
v = camera.View;
t = camera.Top;
r = Vector3.UnitZ;
Matrix3 mrot = Matrix3.CreateFromAxisAngle(r, arc);
v *= mrot;
t *= mrot;
float angle = (float)Math.Acos(Vector2.Dot(v.Xy, Vector2.UnitY));
if (LimitLeftRight.ValueIsValid(angle))
{
camera.View = v;
camera.Top = t;
}
}
public void walk(float distance)
{
}
public void strafe(float distance)
{
}
}
}