OpenTK投影移动和滚动相机

时间:2014-07-01 22:02:27

标签: c# opengl 2d opentk

我正在编写图形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调用什么来移动我的相机并滚动它。

3 个答案:

答案 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();

你会看到它的运作方式更清晰: