如何解决如何在 OpenTK 中为 3D 立方体获取正确的名称堆栈?
我正在尝试在 OpenTK 中绘制一个 3D 立方体(6 个面),然后使用右键单击选择所需的面。我正在使用选择功能,并为每个人脸分配名称(即 1-6)。但是,当我运行我的代码时,即使我右键单击其他面孔,也无法获得正确的名称堆栈。我只是得到同名堆栈(5)。
您知道为什么在这种情况下我无法获得正确的名称堆栈吗?如何获取正确的名称栈?
这是我的代码:
using System;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;
namespace OpenTK3D
{
public class Game3D
{
private GameWindow window;
private float zoom;
private bool hasRotationStarted;
private int startX;
private int startY;
private float xRotAngle;
private float yRotAngle;
private bool hasPanningStarted;
private float xTrans;
private float yTrans;
private int BUFSIZE = 512;
public Game3D(GameWindow wd)
{
this.window = wd;
start();
}
public void start()
{
window.Load += loaded;
window.Resize += resize;
window.RenderFrame += renderFrame;
window.MouseDown += mouseLeftPress;
window.MouseUp += mouseRelease;
window.MouseMove += mouseDragEvent;
window.MouseWheel += MouseWheelHandler;
window.MouseDown += wheelPressEvent;
window.MouseUp += wheelReleaseEvent;
window.MouseMove += wheelDragEvent;
window.MouseDown += select;
window.Run(1.0 / 60.0);
}
public void loaded(object o,EventArgs e)
{
GL.ClearColor(0.0f,0.0f,0.0f);
GL.Enable(EnableCap.DepthTest);
}
public void renderFrame(object o,EventArgs e)
{
GL.LoadIdentity();
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.Translate(xTrans,yTrans,zoom*3);
GL.Rotate(xRotAngle,1.0,0);
GL.Rotate(yRotAngle,1,0);
GL.Begin(BeginMode.Quads);
GL.Color3(1.0,0.0);
GL.Vertex3(-10.0,10.0,10.0);
GL.Vertex3(-10.0,-10.0);
GL.Vertex3(-10.0,-10.0,10.0);
GL.End();
GL.Begin(BeginMode.Quads);
GL.Color3(1.0,0.0,1.0);
GL.Vertex3(10.0,10.0);
GL.Vertex3(10.0,-10.0);
GL.Vertex3(10.0,10.0);
GL.End();
GL.Begin(BeginMode.Quads);
GL.Color3(0.0,0.0);
GL.Vertex3(10.0,-10.0);
GL.End();
GL.Begin(BeginMode.Quads);
GL.Color3(0.0,10.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();
// the fov must be radian
var matrix = Matrix4.CreatePerspectiveFieldOfView(45.0f*(MathHelper.Pi)/180,window.Width / window.Height,1.0f,100.0f);
GL.LoadMatrix(ref matrix);
GL.MatrixMode(MatrixMode.Modelview);
}
private void processHits(int hits,int[] buffer)
{
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);
}
public void select(object o,MouseEventArgs e)
{
var mouse = Mouse.GetState();
if (mouse[MouseButton.Right])
{
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,viewPort);
var matrix = Matrix4.CreatePerspectiveFieldOfView(45.0f * (MathHelper.Pi) / 180,100.0f);
GL.LoadMatrix(ref matrix);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadIdentity();
GL.LoadName(1);
GL.Begin(BeginMode.Quads);
GL.Color3(1.0,0.0);
GL.Vertex3(-10.0,10.0);
GL.Vertex3(-10.0,-10.0);
GL.Vertex3(-10.0,10.0);
GL.End();
GL.LoadName(2);
GL.Begin(BeginMode.Quads);
GL.Color3(1.0,1.0);
GL.Vertex3(10.0,10.0);
GL.Vertex3(10.0,-10.0);
GL.Vertex3(10.0,10.0);
GL.End();
GL.LoadName(3);
GL.Begin(BeginMode.Quads);
GL.Color3(0.0,10.0);
GL.End();
GL.LoadName(4);
GL.Begin(BeginMode.Quads);
GL.Color3(1.0,0.0);
GL.Vertex3(10.0,10.0);
GL.End();
GL.LoadName(5);
GL.Begin(BeginMode.Quads);
GL.Color3(0.0,-10.0);
GL.End();
GL.LoadName(6);
GL.Begin(BeginMode.Quads);
GL.Color3(0.0,10.0);
GL.End();
GL.MatrixMode(MatrixMode.Projection);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Modelview);
GL.Flush();
hits = GL.RenderMode(RenderingMode.Render);
processHits(hits,buffer);
}
}
public void mouseLeftPress(object sender,MouseEventArgs e)
{
if (e.Mouse.LeftButton == ButtonState.pressed)
{
hasRotationStarted = true;
startX = e.Mouse.X;
startY = e.Mouse.Y;
}
}
public void mouseRelease(object sender,MouseEventArgs e)
{
if (e.Mouse.LeftButton == ButtonState.Released)
{
hasRotationStarted = false;
}
}
public void mouseDragEvent(object sender,MouseEventArgs e)
{
if (hasRotationStarted == true && e.Mouse.X != e.Mouse.Y)
{
xRotAngle = xRotAngle + (e.Mouse.Y - startY);
yRotAngle = yRotAngle + (e.Mouse.X - startX);
startX = e.Mouse.X;
startY = e.Mouse.Y;
}
}
public void MouseWheelHandler(object sender,MouseWheelEventArgs e)
{
var xBoundary = 10.0;
if (e.Delta > 0)
{
zoom += 0.1f * (float)xBoundary;
}
if (e.Delta < 0)
{
zoom -= 0.1f * (float)xBoundary;
}
}
public void wheelPressEvent(object sender,MouseEventArgs e)
{
if (e.Mouse.MiddleButton == ButtonState.pressed)
{
hasPanningStarted = true;
startX = e.Mouse.X;
startY = e.Mouse.Y;
}
}
public void wheelReleaseEvent(object sender,MouseEventArgs e)
{
if (e.Mouse.MiddleButton == ButtonState.Released)
{
hasPanningStarted = false;
}
}
public void wheelDragEvent(object sender,MouseEventArgs e)
{
if (hasPanningStarted == true)
{
xTrans = xTrans + 2 * (e.Mouse.X - startX);
yTrans = yTrans - 2 * (e.Mouse.Y - startY);
startX = e.Mouse.X;
startY = e.Mouse.Y;
}
}
}
}
这里是主要功能:
using System;
using OpenTK;
namespace OpenTK3D
{
class Program
{
static void Main(string[] args)
{
var window = new GameWindow(500,500);
var gm = new Game3D(window);
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("Press enter to finish...");
Console.ReadLine();
}
}
}
解决方法
有两个问题:
-
GL.LoadMatrix
加载矩阵并覆盖现有矩阵。如果要将矩阵与当前矩阵连接起来,则需要使用GL.MultMatrix
-
设置投影矩阵是不够的。您还必须设置模型视图矩阵。由于模型视图矩阵已经设置好,去掉
GL.LoadIdentity
后的GL.MatrixMode(MatrixMode.Modelview)
就足够了。
# [...]
GL.MatrixMode(MatrixMode.Projection);
GL.PushMatrix();
GL.LoadIdentity();
GluPickMatrix(e.Mouse.X,viewPort[3] - e.Mouse.Y,5.0,viewPort);
var matrix = Matrix4.CreatePerspectiveFieldOfView(45.0f * (MathHelper.Pi) / 180,window.Width / window.Height,1.0f,100.0f);
GL.MultMatrix(ref matrix); # <-- GL.MultMatrix insterad of GL.LoadMatrix
GL.MatrixMode(MatrixMode.Modelview);
# GL.LoadIdentity(); <-- delete this
# [...]
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。