微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

无法在 OpenTK 中获取正确的名称堆栈

如何解决无法在 OpenTK 中获取正确的名称堆栈

我指的是这里的 LWJGL 教程 (https://www.youtube.com/watch?v=V9e7A4konHo) 进行挑选。可在此处 (https://docs.google.com/document/d/1MEcdkcCCM-BKmuL2Rg5SR-_RG6cCH7Ek9_hU7xXlW4Y/pub) 找到本教程的源代码

基本上我想在这里做的是使用 OpenTK 将此 Java 代码转换为 C# 代码在这代码中,有 2 个对象(矩形)被渲染到屏幕上。然后我想在单击对象时获得正确的名称堆栈。但是,当我运行我的代码时,即使我单击了其他对象,我也只会得到相同的名称 1。此外,当我点击对象时,屏幕会放大,这不是我想要的。

我不确定我的代码有什么问题。我怀疑错误的部分是 gluPickMatrix 函数。这是我的代码

using System;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;


namespace OpenTkSelectTry
{
    public class Game2D
    {
        GameWindow window;
        private int BUFSIZE = 512;

        public Game2D(GameWindow wd)
        {
            this.window = wd;
            start();
        }

        public void start()
        {
            window.Load += loaded;
            window.Resize += resize;
            window.MouseDown += select;
            window.RenderFrame += renderFrame;      
            window.Run(1.0 / 60.0);
        }

        public void loaded(object o,EventArgs e)
        {
            GL.ClearColor(0.0f,0.0f,0.0f);
        }

        public void renderFrame(object o,EventArgs e)
        {
            GL.LoadIdentity();
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
            
            GL.Begin(BeginMode.Quads);
            GL.Color3(1.0,1.0,0.0);
            GL.Vertex3(-5.0,-5.0,-80.0);
            GL.Vertex3(5.0,5.0,-80.0);
            GL.Vertex3(-5.0,-80.0);
                     
            GL.Color3(1.0,0.0,0.0);
            GL.Vertex3(-10.0,-10.0,-80.0);
            GL.Vertex3(0.0,-80.0);
            GL.Vertex3(-10.0,-80.0);
            GL.End();
            window.SwapBuffers();
        }

        public void resize(object o,EventArgs e)
        {
            GL.Viewport(0,window.Width,window.Height);
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadIdentity();
            GL.Ortho(-50.0,50.0,-50.0,-100.0,100.0);
            GL.MatrixMode(MatrixMode.Modelview);
            GL.Enable(EnableCap.DepthTest);
        }     

        public void select(object o,MouseEventArgs e)
        {
            var buffer = new int[BUFSIZE];
            var viewPort = new int[4];
            int hits;
            GL.GetInteger(GetPName.Viewport,viewPort);
            GL.SelectBuffer(BUFSIZE,buffer);
            GL.RenderMode(RenderingMode.Select);

            GL.InitNames();
            GL.PushName(0);
            GL.MatrixMode(MatrixMode.Projection);
            GL.Pushmatrix();
            GL.LoadIdentity();

            gluPickMatrix(e.Mouse.X,viewPort[3] - e.Mouse.Y,viewPort);  
            GL.Ortho(-50.0,100.0);             
            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadIdentity();
            GL.LoadName(1);
            GL.Begin(BeginMode.Quads);
            GL.Color3(1.0,-80.0);
   
            GL.LoadName(2);
            GL.Color3(1.0,-80.0);
            GL.End();    
            GL.PopMatrix();

            GL.Flush();

            hits = GL.RenderMode(RenderingMode.Render);
            Console.WriteLine("hit: {0}",hits);

            if (hits>0)
            {
                int choose = buffer[3];
                int depth = buffer[1];
                for (int i=0;i<hits;i++)
                {
                    if (buffer[i * 4 + 1] < depth)
                    {
                        choose = buffer[i * 4 + 3];
                        depth = buffer[i * 4 + 1];
                    }
                }
                Console.WriteLine("choosen: {0}",choose);
            }     
        }
        private void gluPickMatrix(double x,double y,double deltax,double deltay,int[] viewport)
        {
            if (deltax <= 0 || deltay <= 0)
            {
                return;
            }

            GL.Translate((viewport[2] - 2 * (x - viewport[0])) / deltax,(viewport[3] - 2 * (y - viewport[1])) / deltay,0);
            GL.Scale(viewport[2] / deltax,viewport[3] / deltay,1.0);
        }
    }
}

主要功能

using System;
using OpenTK;

namespace OpenTkSelectTry
{
    class Program
    {
        static void Main(string[] args)
        {
            var window = new GameWindow(500,500);
            var gm = new Game2D(window);
            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine("Press enter to finish...");
            Console.ReadLine();
        }
    }
}

这是最初在屏幕中呈现的 2 个对象:

Initial objects rendered on screen

我点击对象后,屏幕放大(不是我想要的),名称堆栈不正确(总是1)。

The screen get zoom in(not what I want)

解决方法

屏幕放大(不是我想要的),

这是因为您在 select 方法中更改了矩阵模式。在 MatrixMode.Projection 之前选择 GL.PopMatrix()

并且名称堆栈不正确(始终为 1)。

不允许在 GL.LoadName/GL.Begin 序列中调用 GL.End。这会导致无效操作错误 (GL.GetError)。您需要绘制 2 个单独的四边形。

public void select(object o,MouseEventArgs e)
{
    // [...]

    GL.MatrixMode(MatrixMode.Projection);
    GL.PushMatrix();
    GL.LoadIdentity();

    GluPickMatrix(e.Mouse.X,viewPort[3] - e.Mouse.Y,5.0,viewPort);
    GL.Ortho(-50.0,50.0,-50.0,-100.0,100.0);

    GL.MatrixMode(MatrixMode.Modelview);
    GL.LoadIdentity();

    GL.LoadName(1);
    GL.Begin(BeginMode.Quads);
    GL.Color3(1.0,1.0,0.0);
    GL.Vertex3(-5.0,-5.0,-80.0);
    GL.Vertex3(5.0,-80.0);
    GL.Vertex3(-5.0,-80.0);
    GL.End();

    GL.LoadName(2);
    GL.Begin(BeginMode.Quads);
    GL.Color3(1.0,0.0,0.0);
    GL.Vertex3(-10.0,-10.0,-80.0);
    GL.Vertex3(0.0,-80.0);
    GL.Vertex3(-10.0,-80.0);
    GL.End();
  
    GL.MatrixMode(MatrixMode.Projection);
    GL.PopMatrix();
    GL.MatrixMode(MatrixMode.Modelview);

    // [...]
}


原始示例使用 Perspective projection 而不是 Orthographic projection。使用 Matrix4.CreatePerspectiveFieldOfView 指定透视投影矩阵。使用 GL.MultMatrix 将当前矩阵乘以投影矩阵:

GL.Ortho(-50.0,100.0);

Matrix4 perspective = Matrix4.CreatePerspectiveFieldOfView(
    40f * (float)Math.PI / 180f,500f / 500f,0.001f,400f);
GL.MultMatrix(ref perspective);

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。