无法在 OpenTK 中获取正确的名称堆栈
Cannot get the correct name stack in OpenTK
我这里指的是LWJGL教程(https://www.youtube.com/watch?v=V9e7A4konHo) for the picking. The source code for this tutorial can be found here (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,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, 5.0, -80.0);
GL.Vertex3(-5.0, 5.0, -80.0);
GL.Color3(1.0, 0.0, 0.0);
GL.Vertex3(-10.0, -10.0, -80.0);
GL.Vertex3(0.0, -10.0, -80.0);
GL.Vertex3(0.0, 0.0, -80.0);
GL.Vertex3(-10.0, 0.0, -80.0);
GL.End();
window.SwapBuffers();
}
public void resize(object o,EventArgs e)
{
GL.Viewport(0, 0, window.Width, window.Height);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Ortho(-50.0, 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, 5.0, 5.0, viewPort);
GL.Ortho(-50.0, 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, -5.0, -80.0);
GL.Vertex3(5.0, 5.0, -80.0);
GL.Vertex3(-5.0, 5.0, -80.0);
GL.LoadName(2);
GL.Color3(1.0, 0.0, 0.0);
GL.Vertex3(-10.0, -10.0, -80.0);
GL.Vertex3(0.0, -10.0, -80.0);
GL.Vertex3(0.0, 0.0, -80.0);
GL.Vertex3(-10.0, 0.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 个对象:
点击对象后,屏幕放大(不是我想要的),名称堆栈不正确(总是1)。
the screen zoom in (not what I want),
这是因为您在 select
方法中更改了矩阵模式。在GL.PopMatrix()
之前选择MatrixMode.Projection
:
and the name stack is not correct (always 1).
不允许在 GL.Begin
/GL.End
序列中调用 GL.LoadName
。这会导致无效操作错误 (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, 5.0, viewPort);
GL.Ortho(-50.0, 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, -5.0, -80.0);
GL.Vertex3(5.0, 5.0, -80.0);
GL.Vertex3(-5.0, 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, -10.0, -80.0);
GL.Vertex3(0.0, 0.0, -80.0);
GL.Vertex3(-10.0, 0.0, -80.0);
GL.End();
GL.MatrixMode(MatrixMode.Projection);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Modelview);
// [...]
}
原始示例使用 Perspective projection instead of Orthographic projection。使用 Matrix4.CreatePerspectiveFieldOfView
指定透视投影矩阵。使用GL.MultMatrix
将当前矩阵乘以投影矩阵:
GL.Ortho(-50.0, 50.0, -50.0, 50.0, -100.0, 100.0);
Matrix4 perspective = Matrix4.CreatePerspectiveFieldOfView(
40f * (float)Math.PI / 180f, 500f / 500f, 0.001f, 400f);
GL.MultMatrix(ref perspective);
我这里指的是LWJGL教程(https://www.youtube.com/watch?v=V9e7A4konHo) for the picking. The source code for this tutorial can be found here (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,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, 5.0, -80.0);
GL.Vertex3(-5.0, 5.0, -80.0);
GL.Color3(1.0, 0.0, 0.0);
GL.Vertex3(-10.0, -10.0, -80.0);
GL.Vertex3(0.0, -10.0, -80.0);
GL.Vertex3(0.0, 0.0, -80.0);
GL.Vertex3(-10.0, 0.0, -80.0);
GL.End();
window.SwapBuffers();
}
public void resize(object o,EventArgs e)
{
GL.Viewport(0, 0, window.Width, window.Height);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Ortho(-50.0, 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, 5.0, 5.0, viewPort);
GL.Ortho(-50.0, 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, -5.0, -80.0);
GL.Vertex3(5.0, 5.0, -80.0);
GL.Vertex3(-5.0, 5.0, -80.0);
GL.LoadName(2);
GL.Color3(1.0, 0.0, 0.0);
GL.Vertex3(-10.0, -10.0, -80.0);
GL.Vertex3(0.0, -10.0, -80.0);
GL.Vertex3(0.0, 0.0, -80.0);
GL.Vertex3(-10.0, 0.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 个对象:
点击对象后,屏幕放大(不是我想要的),名称堆栈不正确(总是1)。
the screen zoom in (not what I want),
这是因为您在 select
方法中更改了矩阵模式。在GL.PopMatrix()
之前选择MatrixMode.Projection
:
and the name stack is not correct (always 1).
不允许在 GL.Begin
/GL.End
序列中调用 GL.LoadName
。这会导致无效操作错误 (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, 5.0, viewPort);
GL.Ortho(-50.0, 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, -5.0, -80.0);
GL.Vertex3(5.0, 5.0, -80.0);
GL.Vertex3(-5.0, 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, -10.0, -80.0);
GL.Vertex3(0.0, 0.0, -80.0);
GL.Vertex3(-10.0, 0.0, -80.0);
GL.End();
GL.MatrixMode(MatrixMode.Projection);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Modelview);
// [...]
}
原始示例使用 Perspective projection instead of Orthographic projection。使用 Matrix4.CreatePerspectiveFieldOfView
指定透视投影矩阵。使用GL.MultMatrix
将当前矩阵乘以投影矩阵:
GL.Ortho(-50.0, 50.0, -50.0, 50.0, -100.0, 100.0);
Matrix4 perspective = Matrix4.CreatePerspectiveFieldOfView(
40f * (float)Math.PI / 180f, 500f / 500f, 0.001f, 400f);
GL.MultMatrix(ref perspective);