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()); } } } }