OpenTK实现拾取功能时无法获取正确名称栈及点击缩放异常问题
问题根因
1. 点击后屏幕异常放大
你在select方法中修改投影矩阵后没有正确恢复矩阵状态:
- 你先将矩阵模式切换到
MatrixMode.Projection并调用GL.PushMatrix()保存原始投影状态 - 后续切换到了
MatrixMode.Modelview模式,结束拾取时调用的GL.PopMatrix()实际弹出的是模型视图矩阵栈,投影矩阵栈的拾取状态没有被弹出,导致后续正常渲染时一直使用拾取模式下的缩放投影矩阵,画面就会异常放大。
2. 点击永远返回名称1
OpenGL不允许在glBegin/glEnd块内部调用glLoadName,你把两个物体的GL.LoadName调用都放在了同一个GL.Begin(BeginMode.Quads)和GL.End()之间,第二个GL.LoadName(2)调用无效,两个矩形都绑定了名称1,所以拾取结果永远是1。
修正代码
只需修改select方法中的两处错误即可:
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(); // 修正:将LoadName放到Begin外部,每个物体单独用Begin/End包裹 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(); // 修正:先切回Projection模式再弹出矩阵,恢复原始投影状态 GL.MatrixMode(MatrixMode.Projection); GL.PopMatrix(); GL.MatrixMode(MatrixMode.Modelview); // 切回默认模型视图模式,不影响后续渲染 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); } }
内容的提问来源于stack exchange,提问作者maantarng
相关产品推荐
相关产品推荐

