using OpenTK.GLControl;
|
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Mathematics;
|
|
namespace Yw.WinFrmUI.Hydro
|
{
|
/// <summary>
|
/// 正交2d视图辅助类
|
/// </summary>
|
internal class OrthoViewer2dHelper
|
{
|
|
/// <summary>
|
/// 辅助类
|
/// </summary>
|
public OrthoViewer2dHelper() { }
|
|
#region 公共事件
|
|
/// <summary>
|
/// 旋转改变事件
|
/// </summary>
|
public event Action<Vector3> RotationChangedEvent;
|
|
#endregion
|
|
#region 私有字段
|
|
private GLControl _gl = null;//gl控件
|
private NetworkL3d _nw = null;//管网模型
|
private Vector3CacheHelper _veccache = null;//位置缓存
|
private OrthoCamera2d _camera = null;//相机
|
private Point _lastMos;//最近的鼠标位置
|
private bool _isTranslation, _isRotation;
|
|
#endregion
|
|
#region 公共属性
|
|
/// <summary>
|
/// 是否初始化
|
/// </summary>
|
public bool Initialized
|
{
|
get
|
{
|
if (_nw == null)
|
{
|
return false;
|
}
|
if (_gl == null)
|
{
|
return false;
|
}
|
if (_camera == null)
|
{
|
return false;
|
}
|
return true;
|
}
|
}
|
|
#endregion
|
|
/// <summary>
|
/// 初始化
|
/// </summary>
|
public void Initial(GLControl gl, NetworkL3d nw)
|
{
|
_gl = gl;
|
_nw = nw;
|
_veccache = new Vector3CacheHelper(nw);
|
_camera = new OrthoCamera2d();
|
_camera.Initial(_veccache.GetAll(), gl.Width, gl.Height);
|
}
|
|
|
#region 辅助方法
|
|
//初始化GL状态
|
private void InitialGLState()
|
{
|
GL.ClearColor(Color.Transparent); // 背景颜色
|
GL.Enable(EnableCap.DepthTest);//深度测试
|
GL.DepthMask(true); // 允许写入深度缓冲区
|
GL.Enable(EnableCap.PointSmooth);//启用点平滑
|
GL.Enable(EnableCap.LineSmooth);//启用线平滑
|
GL.Enable(EnableCap.Multisample);// 启用反锯齿
|
GL.ShadeModel(ShadingModel.Smooth);
|
|
// 设置混合模式以支持反锯齿
|
GL.Enable(EnableCap.Blend);
|
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
|
Resize();
|
}
|
|
#endregion
|
|
#region 交互处理
|
|
/// <summary>
|
/// 加载
|
/// </summary>
|
public void Load()
|
{
|
if (!Initialized)
|
{
|
return;
|
}
|
_gl.MakeCurrent();
|
InitialGLState();
|
}
|
|
/// <summary>
|
/// 大小改变
|
/// </summary>
|
public void Resize()
|
{
|
if (!Initialized)
|
{
|
return;
|
}
|
_gl.MakeCurrent();
|
_camera.UpdateViewPort(_gl.Width, _gl.Height);
|
GL.Viewport(0, 0, _gl.Width, _gl.Height);
|
_camera.UpdateMatrices();
|
_gl.Invalidate();
|
}
|
|
/// <summary>
|
/// 绘制
|
/// </summary>
|
public void Render()
|
{
|
if (!Initialized)
|
{
|
return;
|
}
|
_gl.MakeCurrent();
|
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit);
|
//投影矩阵
|
GL.MatrixMode(MatrixMode.Projection);
|
var projectionMatrix = _camera.ProjectionMatrix;
|
GL.LoadMatrix(ref projectionMatrix);
|
|
//视图矩阵
|
GL.MatrixMode(MatrixMode.Modelview);
|
var viewMatrix = _camera.ViewMatrix;
|
GL.LoadMatrix(ref viewMatrix);
|
|
var modelMatrix = _camera.ModelMatrix;
|
GL.MultMatrix(ref modelMatrix);
|
|
_nw.Draw2d(_camera.Zoom);
|
|
_gl.SwapBuffers();
|
}
|
|
/// <summary>
|
/// 鼠标滚轮
|
/// </summary>
|
public void MouseWheel(MouseEventArgs e)
|
{
|
if (!Initialized)
|
{
|
return;
|
}
|
var scale = e.Delta > 0 ? 0.9f : 1.1f;
|
_camera.UpdateZoom(scale);
|
_camera.UpdateMatrices();
|
_gl.Invalidate();
|
}
|
|
/// <summary>
|
/// 鼠标按下
|
/// </summary>
|
public void MouseDown(MouseEventArgs e)
|
{
|
if (!Initialized)
|
{
|
return;
|
}
|
_lastMos = e.Location;
|
if (e.Button == MouseButtons.Right)
|
{
|
_isTranslation = true;
|
_gl.Cursor = Cursors.SizeAll; // 修改光标样式
|
}
|
else if (e.Button == MouseButtons.Left)
|
{
|
_isRotation = true;
|
_gl.Cursor = Cursors.SizeAll; // 修改光标样式
|
}
|
}
|
|
/// <summary>
|
/// 鼠标弹起
|
/// </summary>
|
public void MouseUp(MouseEventArgs e)
|
{
|
if (!Initialized)
|
{
|
return;
|
}
|
_lastMos = e.Location;
|
if (e.Button == MouseButtons.Right)
|
{
|
_isTranslation = false;
|
_gl.Cursor = Cursors.Default;
|
}
|
else if (e.Button == MouseButtons.Left)
|
{
|
_isRotation = false;
|
_gl.Cursor = Cursors.Default;
|
}
|
|
_gl.Invalidate();
|
}
|
|
/// <summary>
|
/// 鼠标移动
|
/// </summary>
|
public void MouseMove(MouseEventArgs e)
|
{
|
if (!Initialized)
|
{
|
return;
|
}
|
float dx = e.X - _lastMos.X;
|
float dy = e.Y - _lastMos.Y;
|
|
if (_isRotation)
|
{
|
_camera.UpdateRotation(dx, dy);
|
_camera.UpdateMatrices();
|
this.RotationChangedEvent?.Invoke(_camera.Rotation);
|
}
|
else if (_isTranslation)
|
{
|
_camera.UpdateTranslation(dx, dy);
|
_camera.UpdateMatrices();
|
}
|
|
var ray = OrthoTransformHelper.CreateRay(e.X, e.Y, _camera.ModelMatrix, _camera.ViewMatrix, _camera.ProjectionMatrix, _gl.Width, _gl.Height);
|
if (ray != null)
|
{
|
_nw.Hover2d(ray, _camera.Zoom, _veccache);
|
}
|
|
_lastMos = e.Location;
|
_gl.Invalidate();
|
|
}
|
|
/// <summary>
|
/// 鼠标点击
|
/// </summary>
|
public void MouseClick(MouseEventArgs e)
|
{
|
if (!Initialized)
|
{
|
return;
|
}
|
var ray = OrthoTransformHelper.CreateRay(e.X, e.Y, _camera.ModelMatrix, _camera.ViewMatrix, _camera.ProjectionMatrix, _gl.Width, _gl.Height);
|
if (ray != null)
|
{
|
_nw.Select2d(ray, _camera.Zoom, _veccache);
|
}
|
_gl.Invalidate();
|
}
|
|
/// <summary>
|
/// 鼠标双击
|
/// </summary>
|
public void MouseDoubleClick(MouseEventArgs e)
|
{
|
var depth = OrthoTransformHelper.GetScreenPointDepth(e.X, e.Y, _gl.Height);
|
var world = OrthoTransformHelper.ScreenToWorld(e.X, e.Y, depth, _camera.ModelMatrix, _camera.ViewMatrix, _camera.ProjectionMatrix, _gl.Width, _gl.Height);
|
MessageBox.Show($"x:{world.X},y:{world.Y},z:{world.Z}");
|
}
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
}
|
}
|