Files
PCK-Studio/MinecraftUSkinEditor/Classes/StoneVOX/client/Camera.cs
PhoenixARC 10f1c8daa0 update
2021-08-09 19:05:20 -04:00

397 lines
13 KiB
C#

using OpenTK;
using OpenTK.Input;
using System;
namespace stonevox
{
public class Camera : Singleton<Camera>
{
public Vector3 position;
public Vector3 direction;
public Matrix4 projection;
public Matrix4 view;
public Matrix4 modelviewprojection;
private Input input;
private QbManager manager;
public Vector3 cameraright { get { return Vector3.Cross(direction, VectorUtils.UP); } }
public Vector3 cameraup { get { return Vector3.Cross(cameraright, direction); } }
float fov = 45f;
float nearPlane = 1f;
float farPlane = 300;
bool dotransition;
Vector3 startpos;
Vector3 startdir;
Vector3 _goto;
Vector3 centerposition;
float time = 0;
public bool freecam;
public Camera(GLWindow window, Input input, QbManager manager)
: base()
{
this.input = input;
this.manager = manager;
window.Resize += (e, s) =>
{
projection = Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(fov), (float)window.Width / (float)window.Height, nearPlane, farPlane);
};
position = new Vector3(0f, 0f, 10f);
direction = new Vector3(0f, 0f, 1f);
direction.Normalize();
projection = Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(fov), (float)window.Width / (float)window.Height, nearPlane, farPlane);
view = Matrix4.LookAt(position, position + direction, VectorUtils.UP);
modelviewprojection = projection * view;
InputHandler handler = new InputHandler()
{
Keydownhandler = (e) =>
{
var gui = Singleton<GUI>.INSTANCE;
//freecam is super interesting... but need a bit of work
//if (e.Key == Key.C)
//{
// freecam = !freecam;
// if (freecam)
// {
// Client.window.CursorVisible = false;
// }
// else
// {
// Client.window.CursorVisible = true;
// }
//}
},
mousewheelhandler = (e) =>
{
if (!Singleton<GUI>.INSTANCE.OverWidget)
{
if (e.Delta < 0)
{
position -= direction * 6 * 1f;
}
else if (e.Delta > 0)
{
position += direction * 6 * 1f;
}
}
else if (Singleton<GUI>.INSTANCE.lastWidgetOver.Drag)
{
if (e.Delta < 0)
{
position -= direction * 6 * 1f;
}
else if (e.Delta > 0)
{
position += direction * 6 * 1f;
}
}
}
};
input.AddHandler(handler);
}
public void update(float delta)
{
if (!Singleton<GUI>.INSTANCE.OverWidget)
{
if (input.Keydown(Key.Q))
position += Vector3.UnitY * -15f * delta;
if (input.Keydown(Key.E))
position -= Vector3.UnitY * -15f * delta;
if (input.Keydown(Key.W) || input.Keydown(Key.Up))
{
position += direction * 25f * delta;
}
if (input.Keydown(Key.S) || input.Keydown(Key.Down))
{
position -= direction * 25f * delta;
}
if (input.Keydown(Key.A) || input.Keydown(Key.Left))
{
Vector3 camerar = cameraright;
position.X -= camerar.X * 25f * delta;
position.Z -= camerar.Z * 25f * delta;
}
if (input.Keydown(Key.D) || input.Keydown(Key.Right))
{
Vector3 camerar = cameraright;
position.X += camerar.X * 25f * delta;
position.Z += camerar.Z * 25f * delta;
}
}
if (input.mousedown(MouseButton.Right) || freecam)
{
Vector3 camright = cameraright;
Vector3 camup = cameraup;
float roty = (float)MathHelper.DegreesToRadians(-input.mousedx * .15f);
float rotx = (float)MathHelper.DegreesToRadians(-input.mousedy * .15f);
if (Math.Abs(direction.Y) >= .95f && Math.Sign(rotx) == Math.Sign(direction.Y))
{
camright.Normalize();
camup.Normalize();
Vector3 focus = position - manager.ActiveMatrix.centerposition;
float length = focus.Length;
focus.Normalize();
focus = Vector3.Transform(focus, Quaternion.FromAxisAngle(camup, roty));
position = focus * length + manager.ActiveMatrix.centerposition;
direction = Vector3.Transform(direction, Quaternion.FromAxisAngle(camup, roty));
direction.Normalize();
}
else
{
camright.Normalize();
camup.Normalize();
Vector3 focus = position - manager.ActiveMatrix.centerposition;
float length = focus.Length;
focus.Normalize();
if (!freecam)
{
focus = Vector3.Transform(focus, Quaternion.FromAxisAngle(camup, roty));
focus = Vector3.Transform(focus, Quaternion.FromAxisAngle(camright, rotx));
}
position = focus * length + manager.ActiveMatrix.centerposition;
direction = Vector3.Transform(direction, Quaternion.FromAxisAngle(camup, roty));
direction = Vector3.Transform(direction, Quaternion.FromAxisAngle(camright, rotx));
direction.Normalize();
direction.Y = direction.Y.Clamp(-.95f, .95f);
}
}
if (input.mousedown(MouseButton.Middle))
{
Vector3 camright = Vector3.Cross(direction, Vector3.UnitY);
camright.Normalize();
Vector3 camup = Vector3.Cross(camright, direction);
camup.Normalize();
camright *= -input.mousedx;
camup *= input.mousedy;
camright += camup;
position.X += camright.X * .06f;
position.Y += camright.Y * .06f;
position.Z += camright.Z * .06f;
}
if (dotransition)
{
time += delta;
if (time >= .5f)
{
position = _goto;
direction = (centerposition - position).Normalized();
dotransition = false;
time = 0;
}
else
{
position = Vector3.Lerp(startpos, _goto, time / .5f);
direction = Vector3.Lerp(startdir, (centerposition - position).Normalized(), time / .5f);
direction.Normalize();
}
}
view = Matrix4.LookAt(position, position + direction, Vector3.UnitY);
modelviewprojection = view * projection;
}
public void LookAtModel(bool skipVoxels = false)
{
if (!skipVoxels)
{
int minx = 10000;
int miny = 10000;
int minz = 10000;
int maxx = 0;
int maxy = 0;
int maxz = 0;
int sizex = 0;
int sizey = 0;
int sizez = 0;
foreach (var matrix in manager.ActiveModel.matrices)
{
if (matrix.minx < minx)
minx = matrix.minx;
if (matrix.maxx > maxx)
maxx = matrix.maxx;
if (matrix.miny < miny)
miny = matrix.miny;
if (matrix.maxy > maxy)
maxy = matrix.maxy;
if (matrix.minz < minz)
minz = matrix.minz;
if (matrix.maxz > maxz)
maxz = matrix.maxz;
}
sizex = maxx - minx;
sizey = maxy - miny;
sizez = maxz - minz;
float backup = 0;
if (sizey * 1.5f > 20)
backup = sizey * 1.5f;
else if (sizex * 1.5f > 20)
backup = sizex * 1.5f;
else backup = 20;
var centerpos = new Vector3((minx + ((maxx - minx) / 2)), (miny + ((maxy - miny) / 2)), (minz + ((maxz - minz) / 2)));
position = centerpos + new Vector3(.5f, sizey * .65f, backup);
Vector3.Subtract(ref centerpos, ref position, out direction);
direction.Normalize();
view = Matrix4.LookAt(position, position + direction, cameraup);
modelviewprojection = Matrix4.CreateScale(.1f) * projection * view;
}
else
{
float sizey = manager.ActiveMatrix.sizey;
float sizex = manager.ActiveMatrix.sizex;
float backup = 0;
if (sizey * 1.5f > 20)
backup = sizey * 1.5f;
else if (sizex * 1.5f > 20)
backup = sizex * 1.5f;
else backup = 20;
var centerpos = manager.ActiveMatrix.centerposition;
position = centerpos + new Vector3(0, sizey * .65f, backup*.7f);
Vector3.Subtract(ref centerpos, ref position, out direction);
direction.Normalize();
view = Matrix4.LookAt(position, position + direction, cameraup);
modelviewprojection = Matrix4.CreateScale(.1f) * projection * view;
}
}
public void TransitionToMatrix()
{
startpos = position;
startdir = direction;
var mat = manager.ActiveMatrix;
_goto = mat.centerposition;
centerposition = mat.centerposition;
float height = (mat.maxy - mat.miny);
float width = (mat.maxx - mat.minx);
float length = (mat.maxz - mat.minz);
float distance;
if (height < 10 && width < 10 && length < 10)
{
height = (mat.maxy - mat.miny) * 2.5f;
width = (mat.maxx - mat.minx) * 2.5f;
length = (mat.maxz - mat.minz) * 2.5f;
distance = Math.Max(Math.Max(height, width), length);
}
else if (height < 18 && width < 18 && length < 18)
{
height = (mat.maxy - mat.miny) * 3.5f;
width = (mat.maxx - mat.minx) * 3.5f;
length = (mat.maxz - mat.minz) * 3.5f;
distance = Math.Max(Math.Max(height, width), length);
}
else
{
height = (mat.maxy - mat.miny) * 1.5f;
width = (mat.maxx - mat.minx) * 1.5f;
length = (mat.maxz - mat.minz) * 1.5f;
distance = Math.Max(Math.Max(height, width), length);
}
Vector3 offset = direction;
if (Math.Abs(offset.X) > .5f)
offset.X = 1f * -Math.Sign(direction.X);
else
offset.X = 0;
if (Math.Abs(offset.Z) > .5f)
offset.Z = 1f * -Math.Sign(direction.Z);
else
offset.Z = 0;
if (Math.Abs(offset.Y) > .5f)
offset.Y = 1f * -Math.Sign(direction.Y);
else
offset.Y = 0;
if (offset.Y == 1 && offset.X == 0 && offset.Z == 0)
{
offset = direction;
float starting = .5f;
bool b = true;
while (b)
{
if (Math.Abs(offset.X) > starting)
{
offset.X = 1f * -Math.Sign(direction.X);
b = false;
}
if (Math.Abs(offset.Z) > starting)
{
offset.Z = 1f * -Math.Sign(direction.Z);
b = false;
}
starting -= .07f;
}
offset.Y = 0;
}
offset.Normalize();
_goto += offset * distance;
dotransition = true;
}
}
}