OpenGL视角控制
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
public class View
{
private void OGLView_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.D:
this._currentEye = Matrix3D.RotateY(this._currentEye, -ONE_DEGREE, this._currentCenter);
this._currentUpVector = Matrix3D.RotateY(this._currentUpVector, -ONE_DEGREE, this._defaultCenter);
break;
case Keys.A:
this._currentEye = Matrix3D.RotateY(this._currentEye, ONE_DEGREE, this._currentCenter);
this._currentUpVector = Matrix3D.RotateY(this._currentUpVector, ONE_DEGREE, this._defaultCenter);
break;
case Keys.W:
this._currentEye = Matrix3D.RotateX(this._currentEye, -ONE_DEGREE, this._currentCenter);
this._currentUpVector = Matrix3D.RotateX(this._currentUpVector, -ONE_DEGREE, this._defaultCenter);
break;
case Keys.S:
this._currentEye = Matrix3D.RotateX(this._currentEye, ONE_DEGREE, this._currentCenter);
this._currentUpVector = Matrix3D.RotateX(this._currentUpVector, ONE_DEGREE, this._defaultCenter);
break;
case Keys.Q:
this._currentEye = Matrix3D.RotateZ(this._currentEye, ONE_DEGREE, this._currentCenter);
this._currentUpVector = Matrix3D.RotateZ(this._currentUpVector, ONE_DEGREE, this._defaultCenter);
break;
case Keys.E:
this._currentEye = Matrix3D.RotateZ(this._currentEye, -ONE_DEGREE, this._currentCenter);
this._currentUpVector = Matrix3D.RotateZ(this._currentUpVector, -ONE_DEGREE, this._defaultCenter);
break;
case Keys.R:
ResetUserView();
break;
default:
break;
}
this.Refresh();
}
private void OGLView_MouseMove(object sender, MouseEventArgs e)
{
float xDelta = _mouseState.X - e.X;
float yDelta = _mouseState.Y - e.Y;
_mouseState.X = e.X;
_mouseState.Y = e.Y;
if (e.Button == MouseButtons.Left && e.Button != MouseButtons.Right && e.Button != MouseButtons.Middle)
{
//x方向移动旋转
this._currentEye = Matrix3D.RotateZ(this._currentEye, xDelta * ONE_DEGREE / 5, this._currentCenter);
this._currentUpVector = Matrix3D.RotateZ(this._currentUpVector, xDelta * ONE_DEGREE / 5, this._defaultCenter);
float i = -Math.Abs(this._currentEye.y) / this._currentEye.y;
//y方向移动翻转
IList<Point3DF> upPosition;
upPosition = Matrix3D.RotateXY(this._currentEye, this._currentUpVector, i * yDelta * ONE_DEGREE / 5, this._currentCenter);
this._currentEye = (Point3DF)upPosition[0];
this._currentUpVector = (Point3DF)upPosition[1];
this.Refresh();
}
else if (e.Button != MouseButtons.Left && e.Button == MouseButtons.Right && e.Button != MouseButtons.Middle)
{
Point3DF parTag = Matrix3D.MoveParallel(this._currentUpVector, xDelta);
this._currentEye.x += parTag.x;
this._currentEye.y += parTag.y;
this._currentCenter.x += parTag.x;
this._currentCenter.y += parTag.y;
Point3DF verTag = Matrix3D.MoveVertical(this._currentUpVector, yDelta);
this._currentEye.x += verTag.x;
this._currentEye.y += verTag.y;
this._currentCenter.x += verTag.x;
this._currentCenter.y += verTag.y;
this.Refresh();
}
}
private void OGLView_MouseWheel(object sender, MouseEventArgs e)
{
this._currentEye = Matrix3D.Zoom(this._currentEye, -e.Delta / 100, this._currentCenter);
this.Refresh();
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace A
{
public static class Matrix3D
{
/// <summary>
/// Moves parallelly.
/// </summary>
/// <param name="currentUpVector">The current up vector.</param>
/// <param name="delta">The delta.</param>
/// <returns></returns>
public static Point3DF MoveParallel(Point3DF currentUpVector, float delta)
{
float i = currentUpVector.x / (Math.Abs(currentUpVector.x));
Point3DF newPositionDelta = new Point3DF();
float k = currentUpVector.y / currentUpVector.x;
float temp = symbol * (float)(1 / Math.Sqrt(k * k + 1));
newPositionDelta.x = delta * k * temp;
newPositionDelta.y = - delta * temp;
newPositionDelta.z = currentUpVector.z;
return newPositionDelta;
}
/// <summary>
/// Moves vertically.
/// </summary>
/// <param name="currentUpVector">The current up vector.</param>
/// <param name="delta">The delta.</param>
/// <returns></returns>
public static Point3DF MoveVertical(Point3DF currentUpVector, float delta)
{
float symbol = -currentUpVector.x / (Math.Abs(currentUpVector.x));
Point3DF newPositionDelta = new Point3DF();
float k = currentUpVector.y / currentUpVector.x;
float temp = symbol * (float)(1 / Math.Sqrt(k * k + 1));
newPositionDelta.x = delta * temp;
newPositionDelta.y = delta * k * temp;
newPositionDelta.z = currentUpVector.z;
return newPositionDelta;
}
/// <summary>
/// Rotates around the X axis.
/// </summary>
/// <param name="oldPosition">The old position.</param>
/// <param name="angle">The angle.</param>
/// <returns></returns>
public static Point3DF RotateX(Point3DF position, float angle)
{
Point3DF newPosition = new Point3DF();
newPosition.y = position.y * (float)Math.Cos(angle) - position.z * (float)Math.Sin(angle);
newPosition.z = position.y * (float)Math.Sin(angle) + position.z * (float)Math.Cos(angle);
newPosition.x = position.x;
return newPosition;
}
/// <summary>
/// Rotates around the X axis.
/// </summary>
/// <param name="oldPosition">The old position.</param>
/// <param name="angle">The angle.</param>
/// <param name="center">The center.</param>
/// <returns></returns>
public static Point3DF RotateX(Point3DF position, float angle, Point3DF center)
{
float deltaY = center.y;
float deltaZ = center.z;
Point3DF tagPosition = new Point3DF();
tagPosition.x = position.x;
tagPosition.y = position.y - deltaY;
tagPosition.z = position.z - deltaZ;
tagPosition = Matrix3D.RotateX(tagPosition, angle);
Point3DF newPosition = new Point3DF();
newPosition.x = tagPosition.x;
newPosition.y = tagPosition.y + deltaY;
newPosition.z = tagPosition.z + deltaZ;
return newPosition;
}
/// <summary>
/// Rotates around the Y axis.
/// </summary>
/// <param name="oldPosition">The old position.</param>
/// <param name="angle">The angle.</param>
/// <returns></returns>
public static Point3DF RotateY(Point3DF position, float angle)
{
Point3DF newPosition = new Point3DF();
newPosition.z = position.z * (float)Math.Cos(angle) - position.x * (float)Math.Sin(angle);
newPosition.x = position.z * (float)Math.Sin(angle) + position.x * (float)Math.Cos(angle);
newPosition.y = position.y;
return newPosition;
}
/// <summary>
/// Rotates around the Y axis.
/// </summary>
/// <param name="oldPosition">The old position.</param>
/// <param name="angle">The angle.</param>
/// <param name="center">The center.</param>
/// <returns></returns>
public static Point3DF RotateY(Point3DF position, float angle, Point3DF center)
{
float deltaX = center.x;
float deltaZ = center.z;
Point3DF tagPositon = new Point3DF();
tagPositon.x = position.x - deltaX;
tagPositon.y = position.y;
tagPositon.z = position.z - deltaZ;
tagPositon = Matrix3D.RotateY(tagPositon, angle);
Point3DF newPosition = new Point3DF();
newPosition.x = tagPositon.x + deltaX;
newPosition.y = tagPositon.y;
newPosition.z = tagPositon.z + deltaZ;
return newPosition;
}
/// <summary>
/// Rotates around the z saxis.
/// </summary>
/// <param name="oldPosition">The old position.</param>
/// <param name="angle">The angle.</param>
/// <returns></returns>
public static Point3DF RotateZ(Point3DF position, float angle)
{
Point3DF newPosition = new Point3DF();
newPosition.x = position.x * (float)Math.Cos(angle) - position.y * (float)Math.Sin(angle);
newPosition.y = position.x * (float)Math.Sin(angle) + position.y * (float)Math.Cos(angle);
newPosition.z = position.z;
return newPosition;
}
/// <summary>
/// Rotates around the Z axis.
/// </summary>
/// <param name="oldPosition">The old position.</param>
/// <param name="angle">The angle.</param>
/// <param name="center">The center.</param>
/// <returns></returns>
public static Point3DF RotateZ(Point3DF position, float angle, Point3DF center)
{
float deltaX = center.x;
float deltaY = center.y;
Point3DF tagPositon = new Point3DF();
tagPositon.x = position.x - deltaX;
tagPositon.y = position.y - deltaY;
tagPositon.z = position.z;
tagPositon = Matrix3D.RotateZ(tagPositon, angle);
Point3DF newPosition = new Point3DF();
newPosition.x = tagPositon.x + deltaX;
newPosition.y = tagPositon.y + deltaY;
newPosition.z = tagPositon.z;
return newPosition;
}
/// <summary>
/// Zooms your view.
/// </summary>
/// <param name="oldPosition">The current position.</param>
/// <param name="factor">The factor.</param>
/// <param name="center">The center.</param>
/// <returns></returns>
public static Point3DF Zoom(Point3DF position, float factor, Point3DF center)
{
Point3DF newPosition;
float deltaX = position.x - center.x;
float deltaY = position.y - center.y;
float deltaZ = position.z - center.z;
newPosition.x = center.x + deltaX * (1 + factor / 10);
newPosition.y = center.y + deltaY * (1 + factor / 10);
newPosition.z = center.z + deltaZ * (1 + factor / 10);
return newPosition;
}
/// <summary>
/// Rotate the xy surface
/// </summary>
/// <param name="position"></param>
/// <returns></returns>
public static Point3DF RotateXY(Point3DF position, float angle)
{
float tagK = position.y / position.x;
float k = -1 / tagK;
float kAngle = (float)Math.Atan(k);
Point3DF tagPosition = new Point3DF();
tagPosition = RotateZ(position, -kAngle);
Point3DF tagPosition1 = new Point3DF();
tagPosition1 = RotateX(tagPosition, angle);
Point3DF newPositioin = new Point3DF();
newPositioin = RotateZ(tagPosition1, kAngle);
return newPositioin;
}
/// <summary>
/// Rotates the XY surface.
/// </summary>
/// <param name="position">The current position.</param>
/// <param name="angle">The angle.</param>
/// <param name="currentCenter">The current center.</param>
/// <returns></returns>
public static Point3DF RotateXY(Point3DF position, float angle, Point3DF currentCenter)
{
float deltaX = currentCenter.x;
float deltaY = currentCenter.y;
Point3DF tagPosition = new Point3DF();
tagPosition.x = position.x - deltaX;
tagPosition.y = position.y - deltaY;
tagPosition.z = position.z;
Point3DF tagPosition1 = new Point3DF();
tagPosition1 = RotateXY(tagPosition, angle);
Point3DF newPosition = new Point3DF();
newPosition.x = tagPosition1.x + deltaX;
newPosition.y = tagPosition1.y + deltaY;
newPosition.z = tagPosition1.z;
return newPosition;
}
public static Point3DF RotateXY(Point3DF position, float angle, Point3DF currentCenter)
{
float deltaX = currentCenter.x;
float deltaY = currentCenter.y;
Point3DF tagPosition = new Point3DF();
tagPosition.x = position.x - deltaX;
tagPosition.y = position.y - deltaY;
tagPosition.z = position.z;
Point3DF tagPosition1 = new Point3DF();
tagPosition1 = RotateXY(tagPosition, angle);
Point3DF newPosition = new Point3DF();
newPosition.x = tagPosition1.x + deltaX;
newPosition.y = tagPosition1.y + deltaY;
newPosition.z = tagPosition1.z;
return newPosition;
}
public static IList<Point3DF> RotateXY(Point3DF position, Point3DF up, float angle, Point3DF currentCenter)
{
IList<Point3DF> positionUpList = new List<Point3DF>();
IList<Point3DF> tagPositionUpList = new List<Point3DF>();
float deltaX = currentCenter.x;
float deltaY = currentCenter.y;
Point3DF tagPosition = new Point3DF();
tagPosition.x = position.x - deltaX;
tagPosition.y = position.y - deltaY;
tagPosition.z = position.z;
tagPositionUpList = RotateXY(tagPosition, up, angle);
Point3DF newPosition = new Point3DF();
newPosition.x = ((Point3DF)tagPositionUpList[0]).x + deltaX;
newPosition.y = ((Point3DF)tagPositionUpList[0]).y + deltaY;
newPosition.z = ((Point3DF)tagPositionUpList[0]).z;
positionUpList.Add(newPosition);
positionUpList.Add(tagPositionUpList[1]);
return positionUpList;
}
}
public struct Point3DF
{
public float x;
public float y;
public float z;