How do I make opengl objects appear on mouse click?
我需要做的是单击OpenGL视区中的某个位置,并在该位置进行对象渲染。我已经知道基本的东西,例如创建窗口、检测鼠标点击、获取点击坐标和绘制对象。我丢失的链接就是得到正确的坐标。我需要确定我在屏幕上单击的(x,y)点意味着OpenGL世界坐标。我知道一个叫做glunproject的glut函数,但是由于技术原因,我不能使用glut。我已经检查了许多算法,手工生成了自己的未经处理的函数:
http://schaby.de/picking-opengl-ray-tracing/http://collagefactory.blogspot.mx/2010/03/glunproject-source-code.htmlOpenGL Math-将屏幕空间投影到世界空间坐标
还有其他的,但都没用,当我点击屏幕时,物体被画到了奇怪的地方。我甚至不确定我要在这里寻找什么,我不知道我要实现的是选择,还是光线投射或光线拾取或其他什么。有人知道我要找的算法吗?
编辑:我正在添加一个屏幕截图,我标记了我单击的位置,如您所见,球体正在另一个地方绘制。网址:http://img23.imageshack.us/img23/4738/proofxd.jpg我还添加了我的OpenGL源代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | /**OPENGL**/ private void GLC_display_Load(object sender, EventArgs e) { //CONTEXT GL.ClearColor(Color.LightGray); GL.Enable(EnableCap.Texture2D); GL.Enable(EnableCap.Blend); GL.Enable(EnableCap.DepthTest); GL.Enable(EnableCap.CullFace); GL.CullFace(CullFaceMode.Back); GL.Enable(EnableCap.Blend); GL.DepthFunc(DepthFunction.Always); GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest); SetupViewport(); } private void SetupViewport() { GL.Clear(ClearBufferMask.ColorBufferBit); GL.ShadeModel(ShadingModel.Smooth); float aspectRatio = (float)GLC_display.Width / (float)GLC_display.Height; GL.Viewport(0, 0, GLC_display.Width, GLC_display.Height); GL.MatrixMode(MatrixMode.Projection); GL.LoadIdentity(); OpenTK.Matrix4 perspective = OpenTK.Matrix4.CreatePerspectiveFieldOfView((float)(System.Math.PI / 4f), aspectRatio, 0.1f, 2000f); GL.MultMatrix(ref perspective); GL.MatrixMode(MatrixMode.Modelview); GL.LoadIdentity(); } private void GLC_display_Resize(object sender, EventArgs e) { SetupViewport(); GLC_display.Invalidate(); } private void GLC_display_Paint(object sender, EventArgs e) { GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); Matrix4 lookat = Matrix4.LookAt(posVector, eyeVector, Vector3.UnitY); GL.MatrixMode(MatrixMode.Modelview); GL.LoadMatrix(ref lookat); GL.Color3(Color.Red); //GL.PushMatrix(); //GL.Translate(new Vector3(10f,3f,5f)); //Geometry.drawSphere(5, 20); //GL.PopMatrix(); foreach (Vector3 coord in clicks) { Console.WriteLine("List:"+coord.ToString()); //GL.Color3(0f, 1f, 0f); GL.PushMatrix(); GL.Translate(coord); Geometry.drawSphere(5, 20); GL.PopMatrix(); } GLC_display.SwapBuffers(); } public Vector3 unProjectInput(Vector2 mouse) { Vector4 result; int[] view = new int[4]; GL.GetInteger(GetPName.Viewport, view); mouse.Y = view[3] - mouse.Y; result.X = (2f*((float)(mouse.X - view[0])/view[2])) - 1f; result.Y = (2f*((float)(mouse.Y - view[1]) / view[3])) - 1f; result.Z = 0f; result.W = 1f; double[] projection = new double[16]; GL.GetDouble(GetPName.ProjectionMatrix, projection); Matrix4 Projection = new Matrix4((float)projection[0], (float)projection[1], (float)projection[2], (float)projection[3], (float)projection[4], (float)projection[5], (float)projection[6], (float)projection[7], (float)projection[8], (float)projection[9], (float)projection[10], (float)projection[11], (float)projection[12], (float)projection[13], (float)projection[14], (float)projection[15]); double[] modelViewMatrix = new double[16]; GL.GetDouble(GetPName.ModelviewMatrix, modelViewMatrix); Matrix4 MV = new Matrix4((float)modelViewMatrix[0], (float)modelViewMatrix[1], (float)modelViewMatrix[2], (float)modelViewMatrix[3], (float)modelViewMatrix[4], (float)modelViewMatrix[5], (float)modelViewMatrix[6], (float)modelViewMatrix[7], (float)modelViewMatrix[8], (float)modelViewMatrix[9], (float)modelViewMatrix[10], (float)modelViewMatrix[11], (float)modelViewMatrix[12], (float)modelViewMatrix[13], (float)modelViewMatrix[14], (float)modelViewMatrix[15]); Matrix4 iMVP = Matrix4.Invert(Matrix4.Mult(MV, Projection)); result = Vector4.Transform(result, iMVP); if (result.W > float.Epsilon || result.W < float.Epsilon) { result.X /= result.W; result.Y /= result.W; result.Z = 0f; //result.Z /= result.W; } return result.Xyz; } |
GLU和GLUT不一样。任何合理现代化的OpenGL安装都应该具有GLU功能。
对于它的价值,glunproject的实现实际上在其手册页中进行了详细说明。
1 2 3 4 5 6 7 8 9 | vec3f cameraPos=camera->position(); vec3f objectPos=vec3f( (float)(mousePos.x)/(videoProperties.w)*2-1, 1, (float)(((videoProperties.h)-mousePos.y))/(videoProperties.h)*2-1); objectPos.x/=(videoProperties.h)/(videoProperties.w); objectPos*=distance; objectPos+=cameraPos; objectPos*=camera->transformation();//may need to inverse this depending on your camera system |
这是我在发动机里用的