我正在编写图形2d编辑器,我使用OpenTK作为渲染引擎 我徘徊怎么可能用鼠标移动和滚动相机看起来像在Photoshop中完成。
这是我现在的代码。
GL.Enable(EnableCap.Texture2D);
GL.Enable(EnableCap.Blend);
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
...
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Viewport(0, 0, 1024, 768);
...
///Part od drawing function
ClassNodeField nField = NodeFieldsManager.GetByID(ID);
int Rows = 4000 / 128 + 1;
int Columns = 4000 / 128 + 1;
GL.ClearColor(Color.Silver);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.Color3(200f, 200f, 200f);
GL.Begin(BeginMode.Lines);
for (int i = 0; i < Rows; i++)
{
GL.Vertex3(4000, 128 * i, 0);
GL.Vertex3(4000, 128 * i, 0);
}
for (int i = 0; i < Columns; i++)
{
GL.Vertex3(128 * i, 4000, 0);
GL.Vertex3(128 * i, 4000, 0);
}
GL.End();
/// end part of drawing function
它工作正常a有4000 x 4000像素的字段进行测试。我计划使用45000乘45000.现在我需要浏览这个字段并用鼠标滚轮滚动 帮助我,我应该从OpenTK调用什么来移动我的相机并滚动它。
答案 0 :(得分:2)
如果我对openGL足够了解,则无需移动相机。因此,您可以创建一个转换矩阵,为您完成所有工作。你应该研究一个世界矩阵。
它确实有点弯曲,所以我会尽量为你简化它。由于openGL不允许移动相机(技术上,没有相机),因此必须移动世界。您可以将其视为在显微镜下移动载玻片,为了滑动而无法移动显微镜。我没有直接使用OpenTK,但我使用的是使用OpenTK的Monogame。
因此,您有2个选项,1)尝试将此调用转换为使用OpenTK:
Matrix.CreateTranslation(location.x, location.y, 0f)
其中,location指的是您要查看的位置的中心。另一种选择是审查有关openGL和OpenTK的任何相关文档。
答案 1 :(得分:0)
好的,谢谢大家,我解决了这个任务。 三角形总是随着鼠标光标移动 - 但我认为只有在按下按钮时才会出现问题(使用旧翻译和新翻译的两个变量)。
/*--------------------------------Program.cs------------------------------*/
//Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace OpenTK_OrthoCamera
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
/*--------------------------------Form1.Designer.cs------------------------*/
namespace OpenTK_OrthoCamera
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.glControl1 = new OpenTK.GLControl();
this.SuspendLayout();
//
// glControl1
//
this.glControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.glControl1.BackColor = System.Drawing.Color.Black;
this.glControl1.Location = new System.Drawing.Point(12, 12);
this.glControl1.Name = "glControl1";
this.glControl1.Size = new System.Drawing.Size(892, 521);
this.glControl1.TabIndex = 0;
this.glControl1.VSync = false;
this.glControl1.Load += new System.EventHandler(this.glControl1_Load);
this.glControl1.Paint += new System.Windows.Forms.PaintEventHandler(this.glControl1_Paint);
this.glControl1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.glControl1_MouseMove);
this.glControl1.Resize += new System.EventHandler(this.glControl1_Resize);
this.glControl1.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.OnMouseWheel);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(916, 545);
this.Controls.Add(this.glControl1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
#endregion
private OpenTK.GLControl glControl1;
}
}
/*--------------------------------Form1.cs-------------------------------*/
using OpenTK.Graphics.OpenGL;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace OpenTK_OrthoCamera
{
public partial class Form1 : Form
{
bool loaded = false;
float x = 0;
float y = 0;
float z = 0;
public Form1()
{
InitializeComponent();
}
/// <summary>
/// Loads Control
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void glControl1_Load(object sender, EventArgs e)
{
loaded = true;
GL.ClearColor(Color.SkyBlue); // Yey! .NET Colors can be used directly!
SetupViewport();
}
/// <summary>
/// Setup the Viewport
/// </summary>
private void SetupViewport()
{
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
int w = glControl1.Width;
int h = glControl1.Height;
float orthoW = w * (z + 1);
float orthoH = h * (z + 1);
GL.Ortho(0, orthoW, 0, orthoH, -1, 1); // Bottom-left corner pixel has coordinate (0, 0)
GL.Viewport(0, 0, w, h); // Use all of the glControl painting area
}
/// <summary>
/// Calculate Translation of (X, Y, Z) - according to mouse input
/// </summary>
private void SetupCursorXYZ()
{
x = PointToClient(Cursor.Position).X * (z + 1);
y = (-PointToClient(Cursor.Position).Y + glControl1.Height) * (z + 1);
}
/// <summary>
/// We need to setup each time our viewport and Ortho.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void glControl1_Resize(object sender, EventArgs e)
{
if (!loaded)
return;
SetupViewport();
}
/// <summary>
/// Paint The control.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void glControl1_Paint(object sender, PaintEventArgs e)
{
if (!loaded) // Play nice
return;
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadIdentity();
GL.Translate(x, y, 0); // position triangle according to our x variable
GL.Color3(Color.Yellow);
GL.Begin(BeginMode.Triangles);
GL.Vertex2(10, 20);
GL.Vertex2(100, 20);
GL.Vertex2(100, 50);
GL.End();
glControl1.SwapBuffers();
}
/// <summary>
/// The triangle will always move with the cursor.
/// But is is not a problem to make it only if mousebutton pressed.
/// And do some simple ath with old Translation and new translation.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void glControl1_MouseMove(object sender, MouseEventArgs e)
{
x = PointToClient(Cursor.Position).X * (z + 1);
y = (-PointToClient(Cursor.Position).Y + glControl1.Height) * (z + 1);
SetupCursorXYZ();
glControl1.Invalidate();
}
private void OnMouseWheel(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Delta > 0 && z > 0) z -= 0.5f;
if (e.Delta < 0 && z < 5) z += 0.5f;
SetupCursorXYZ();
SetupViewport();
glControl1.Invalidate();
}
}
}
试试吧。它有效。
答案 2 :(得分:0)
尝试替换代码
GL.Color3(Color.Yellow);
GL.Begin(BeginMode.Triangles);
GL.Vertex2(10, 20);
GL.Vertex2(100, 20);
GL.Vertex2(100, 50);
GL.End();
这一个
GL.Color3(Color.Yellow);
GL.Begin(BeginMode.Triangles);
for (int i = -20; i < 20; i++)
for (int j = -20; j < 20; j++)
{
GL.Vertex2(10 + i * 200 , 20 + j *200);
GL.Vertex2(100 + i * 200, 20 + j * 200);
GL.Vertex2(100 + i * 200, 50 + j * 200);
}
GL.End();
你会看到它的运作方式更清晰: