using OpenTK.GLControl;
using OpenTK.Graphics.OpenGL;
using OpenTK.Mathematics;
using System.Drawing.Imaging;
namespace Yw.WinFrmUI.Hydro
{
///
/// 正交旋转2d辅助类
///
internal class OrthoRotate2dHelper : IDisposable
{
///
///
///
public OrthoRotate2dHelper() { }
#region 静态资源
//立方体尺寸
private const int Size = 100;
private const string UpText = "上";
private const string DownText = "下";
private const string LeftText = "左";
private const string RightText = "右";
private const string FrontText = "前";
private const string BackText = "后";
//颜色字典
private readonly static Dictionary TextColor = new()
{
{ UpText,ColorTranslator.FromHtml("#800080")},
{ DownText,ColorTranslator.FromHtml("#242424")},
{ LeftText,ColorTranslator.FromHtml("#87CEEB")},
{ RightText,ColorTranslator.FromHtml("#FF0000")},
{ FrontText,ColorTranslator.FromHtml("#00008B")},
{ BackText,ColorTranslator.FromHtml("#008000")},
};
#endregion
#region 私有字段
private GLControl _gl = null;//GL控件
private OrthoCamera2d _camera = null;
private Dictionary _textures = null;//文本纹理
private Point _lastMos;//最近的鼠标位置
private bool _isTranslation, _isRotation;
#endregion
#region 公共属性
///
/// 是否初始化
///
public bool Initialized
{
get
{
if (_gl == null)
{
return false;
}
if (_camera == null)
{
return false;
}
return true;
}
}
#endregion
///
/// 初始化
///
public void Initial(GLControl gl)
{
_gl = gl;
_camera = new OrthoCamera2d();
_camera.Initial(GetVertices(), gl.Width, gl.Height);
}
#region 辅助方法
//初始化GL状态
private void InitialGLState()
{
GL.ClearColor(Color.LightBlue);
GL.Enable(EnableCap.DepthTest);
GL.Enable(EnableCap.Texture2D);
GL.Enable(EnableCap.Blend);
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
// 生成六个面的文字纹理
CreateTextures();
Resize();
}
//绘制立方体
private void DrawCube()
{
GL.Begin(PrimitiveType.Quads);
// 上 (Z+ 方向)
GL.Color3(TextColor[UpText]);
var vers = GetVertices(UpText);
vers.ForEach(x => GL.Vertex3(x));
// 下 (Z- 方向)
GL.Color3(TextColor[DownText]);
vers = GetVertices(DownText);
vers.ForEach(x => GL.Vertex3(x));
// 左 (X- 方向)
GL.Color3(TextColor[LeftText]);
vers = GetVertices(LeftText);
vers.ForEach(x => GL.Vertex3(x));
// 右 (X+ 方向)
GL.Color3(TextColor[RightText]);
vers = GetVertices(RightText);
vers.ForEach(x => GL.Vertex3(x));
// 后 (Y+ 方向)
GL.Color3(TextColor[BackText]);
vers = GetVertices(BackText);
vers.ForEach(x => GL.Vertex3(x));
// 前 (Y- 方向)
GL.Color3(TextColor[FrontText]);
vers = GetVertices(FrontText);
vers.ForEach(x => GL.Vertex3(x));
GL.End();
}
//获取坐标
private List GetVertices(string text)
{
float half = Size / 2f;
List vertices = null;
switch (text)
{
case UpText:
vertices = new List()
{
new Vector3(-half, -half, half),
new Vector3(half, -half, half),
new Vector3(half, half, half),
new Vector3(-half, half, half)
};
break;
case DownText:
vertices = new List()
{
new Vector3(-half, -half, -half),
new Vector3(-half, half, -half),
new Vector3(half, half, -half),
new Vector3(half, -half, -half)
};
break;
case LeftText:
vertices = new List()
{
new Vector3(-half, -half, -half),
new Vector3(-half, -half, half),
new Vector3(-half, half, half),
new Vector3(-half, half, -half)
};
break;
case RightText:
vertices = new List()
{
new Vector3(half, -half, half),
new Vector3(half, -half, -half),
new Vector3(half, half, -half),
new Vector3(half, half, half)
};
break;
case BackText:
vertices = new List()
{
new Vector3(-half, half, half),
new Vector3(half, half, half),
new Vector3(half, half, -half),
new Vector3(-half, half, -half)
};
break;
case FrontText:
vertices = new List()
{
new Vector3(-half, -half, -half),
new Vector3(half, -half, -half),
new Vector3(half, -half, half),
new Vector3(-half, -half, half)
};
break;
default: break;
}
return vertices;
}
//获取坐标
private List GetVertices()
{
var texts = new List() { UpText, DownText, LeftText, RightText, FrontText, BackText };
return texts.SelectMany(x => GetVertices(x)).ToList();
}
//创建纹理
private void CreateTexture(string text)
{
if (_textures == null)
{
_textures = new Dictionary();
}
if (_textures.ContainsKey(text))
{
return;
}
// 创建位图并绘制文字
using (var bmp = new Bitmap(Size, Size))
using (var gfx = Graphics.FromImage(bmp))
{
var bgColor = TextColor[text];
gfx.Clear(bgColor);
var font = new Font("宋体", 32, FontStyle.Bold);
var format = new StringFormat
{
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center
};
gfx.DrawString(text, font, new SolidBrush(Color.White),
new RectangleF(0, 0, Size, Size), format);
//反转y轴(图片坐标与GL屏幕坐标y轴正好是相反的)
bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);
// 转换位图为OpenGL纹理
var data = bmp.LockBits(
new Rectangle(0, 0, bmp.Width, bmp.Height),
ImageLockMode.ReadOnly,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
int texId = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, texId);
GL.TexImage2D(TextureTarget.Texture2D, 0,
PixelInternalFormat.Rgba,
data.Width, data.Height, 0,
OpenTK.Graphics.OpenGL.PixelFormat.Bgra,
PixelType.UnsignedByte, data.Scan0);
// 设置纹理参数
GL.TexParameter(TextureTarget.Texture2D,
TextureParameterName.TextureMinFilter,
(int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D,
TextureParameterName.TextureMagFilter,
(int)TextureMagFilter.Linear);
bmp.UnlockBits(data);
_textures.Add(text, texId);
}
}
//创建纹理s
private void CreateTextures()
{
var texts = new List() { UpText, DownText, LeftText, RightText, FrontText, BackText };
texts.ForEach(x => CreateTexture(x));
}
//绘制纹理
private void DrawTexture(string text)
{
if (_textures == null || _textures.Count < 1)
{
return;
}
var tetId = _textures[text];
var vers = GetVertices(text);
GL.BindTexture(TextureTarget.Texture2D, tetId);
GL.Begin(PrimitiveType.Quads);
GL.TexCoord2(0, 0); GL.Vertex3(vers[0]);
GL.TexCoord2(1, 0); GL.Vertex3(vers[1]);
GL.TexCoord2(1, 1); GL.Vertex3(vers[2]);
GL.TexCoord2(0, 1); GL.Vertex3(vers[3]);
// 修正后的纹理坐标(翻转Y方向)
//GL.TexCoord2(0, 1); GL.Vertex3(vers[0]); // 左上→左下
//GL.TexCoord2(1, 1); GL.Vertex3(vers[1]); // 右上→右下
//GL.TexCoord2(1, 0); GL.Vertex3(vers[2]); // 右下→右上
//GL.TexCoord2(0, 0); GL.Vertex3(vers[3]); // 左下→左上
GL.End();
}
//绘制纹理s
private void DrawTextures()
{
var texts = new List() { UpText, DownText, LeftText, RightText, FrontText, BackText };
texts.ForEach(x => DrawTexture(x));
}
#endregion
#region 交互处理
///
/// 加载
///
public void Load()
{
if (!Initialized)
{
return;
}
_gl.MakeCurrent();
InitialGLState();
}
///
/// 调整大小
///
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();
}
///
/// 绘制
///
public void Render()
{
if (!Initialized)
{
return;
}
_gl.MakeCurrent();
//GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
//投影矩阵
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);
//DrawCube();
DrawTextures();
var error = GL.GetError();
_gl.SwapBuffers();
}
///
/// 鼠标按下
///
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; // 修改光标样式
}
}
///
/// 鼠标弹起
///
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();
}
///
/// 鼠标移动
///
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();
}
else if (_isTranslation)
{
_camera.UpdateTranslation(dx, dy);
_camera.UpdateMatrices();
}
_lastMos = e.Location;
_gl.Invalidate();
}
///
/// 鼠标滚动
///
public void MouseWheel(MouseEventArgs e)
{
if (!Initialized)
{
return;
}
var scale = e.Delta > 0 ? 0.9f : 1.1f;
_camera.UpdateZoom(scale);
_camera.UpdateMatrices();
_gl.Invalidate();
}
///
/// 鼠标点击
///
public void MouseClick(MouseEventArgs e)
{
}
///
/// 鼠标双击
///
public void MouseDoubleClick(MouseEventArgs e)
{
}
#endregion
///
/// 释放
///
public void Dispose()
{
if (_textures != null && _textures.Count > 0)
{
GL.DeleteTextures(_textures.Count, _textures.Values.ToArray());
}
}
}
}