2012-06-15 2 views
0

Что мне нужно сделать, это щелкнуть где-нибудь в моем окне просмотра OpenGL и иметь объект рендеринга в этом месте. Я уже знаю основные вещи, то есть создание окна, обнаружение щелчков мыши, получение координат кликов и рисование объектов. Недостающее звено, которое у меня есть, - это правильные координаты. Мне нужно определить, что точка (X, Y), которую я нажимаю на экране, означает глобальные координаты openGL. Я знаю о функции GLUT, называемой gluUnProject, но по техническим причинам я не могу использовать GLUT. Я проверил множество алгоритмов, чтобы сделать свою собственную функцию unproject вручную:Как создать объекты opengl при щелчке мышью?

http://schabby.de/picking-opengl-ray-tracing/ http://collagefactory.blogspot.mx/2010/03/gluunproject-source-code.html OpenGL Math - Projecting Screen space to World space coords

и другие, но никто не работал, когда я нажал на экране объект был составлен в странных местах. Я даже не уверен, что я ищу здесь, я не знаю, что то, что я пытаюсь реализовать, это Picking, Raycasting или Raypicking или что-то еще. Кто-нибудь знает алгоритм, который я ищу?

EDIT: Я добавляю захват экрана, я отметил место, где я щелкнул, и, как вы можете видеть, сфера рисует другое место. http://img23.imageshack.us/img23/4738/proofxd.jpg Я также добавлять мой OPENGL исходный код:

/**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; 
    } 
+0

Как поживаешь координата Z.? – zacaj

+0

@zacaj Прямо сейчас, я не, я просто делаю его равным нулю. Я прочитал, что я могу прочитать более точное приближение Z-координат назад из буфера кадров, но я еще не пробовал это. – Samssonart

+0

настроить соотношение сторон? – zacaj

ответ

1

GLU и GLUT не то же самое. Функциональность GLU должна присутствовать на любой достаточно современной установке OpenGL.

Для чего это стоит, реализация gluUnProject фактически описана в its man page.

0
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 

Это то, что я использую в моем двигателе

+0

Спасибо за ваш ответ. То, что я не понимаю о вашем коде, заключается в том, как задействовать координаты экрана, которые я захватил с помощью мыши. – Samssonart

+0

mousePos.x и mousePos.y, если я не понимаю ваш вопрос? – zacaj

+0

О, хорошо, я попробую и расскажу вам, что происходит, спасибо. – Samssonart

Смежные вопросы