2013-12-07 4 views
0

Это скорее матовая природа, но в любом случае. Мне нужно определить, где я нажимаю изображение, отображаемое в квадрате в OpenGl. Квадрат 5000x5000 в размере и отображается в 0,0. Теперь из того, что я видел, это отображается из середины окна. Это отображает квадрат в нижнем левом углу оси. Чтобы противостоять этому, вместо того, чтобы изменять вершину квадрата, и поскольку мне нужно кастрюлю, я преобразую, прежде чем я нарисую квадроцикл.Координаты экрана до 2D-мира

Так, чтобы квадрат с центром при запуске, я панорамирую GL.Translate (-2500, -2500), 0).

Теперь координаты мыши относительно верхнего левого угла окна, поэтому я разбиваю их на части, например. Mouse.X/Width Mouse.Y/Высота

Это то место, где оно получает. Я знаю, что мне нужно умножить на 5000, но мне также нужно включить каст как-то.

Я не уверен, если это важно, но это, как моя матрица Орто установка:

GL.Ortho(-G_.MapSize * 1.5^ZoomFactor, G_.MapSize * 1.5^ZoomFactor, G_.MapSize * 1.5^ZoomFactor, -G_.MapSize * 1.5^ZoomFactor, -1, 1) 

ответ

1

ГЛЫ имеет четкий conecpets космического объекта, усеченное пространство, нормированные координаты устройства и оконное пространство. Использование glOrtho() и glTranslate() подразумевает, что вы используете старую фиксированную функцию, где также четко определено пространство глаз.

Если вы хотите отобразить точки окна sapce (например, мышки) обратно в пространство объектов, вам нужно инвертировать вычисления, которые выполняет gl. Трубопровод преобразования для вершин состоит в следующем:

  1. умножение матрица вида модели М. В. объектного положение пространства вершины, чтобы получить глаз пространства Coords (только в фиксированной функции GL, в программируемом трубопроводе, этот шаг полностью определяется пользователь)
  2. умножить проекционную матрицу P на положение в пространстве глаза, чтобы получить положение пространства клипа (только в фиксированной функции GL, в программируемом конвейере, этот шаг полностью определяется пользователем)
  3. Разделить на пространство клипа w компонент для получения декартовых нормализованных устройств. В этом пространстве объем просмотра представляет собой куб оси по шкале в диапазоне [-1,1] вдоль каждой оси. whit z = -1, отдавая ближнюю плоскость, а z = 1 дальняя плоскость
  4. превращает НДЦ в пространство окна, введя видовое окно в окно. точка (-1,1) должна быть отображена в нижний левый угол нижнего левого пикселя окна просмотра, (1,1) отображается в верхний правый верхний пиксель верхнего правого пикселя окна просмотра. Z преобразуется из [-1,1] в [0,1] и может быть дополнительно преобразован указанным glDepthRange, а позже может быть преобразован в некоторое целочисленное представление.

Если у вас есть данное 2D положения мыши, вы можете просто перевернуть эту схему:

  1. Найти видовой экран COORDS (который тривиальный, если использовать полное окно, просто знайте, что GL использует происхождение в левом нижнем углу, тогда как большинство оконных систем помещают начало в верхний левый угол).
  2. Отмените преобразование видового экрана, чтобы положить x и y в диапазоне от [-1, -1].
  3. Теперь вы можете использовать их в качестве клип-пространственных координат по assuimg w = 1. В общем случае каждая позиция мыши 2d представляет собой луч, поэтому вы можете использовать два точек для проецирования луча назад, как z = -1 и z = 1. Однако в вашем ортогональном проекционном случае достаточно одной точки. Поэтому умножьте обратную проекцию P^-1 на координаты пространства клипов вашей точки (точек).
  4. Теперь у вас есть место для глаз. Умножьте обратную матрицу модели MV^-1 на координаты пространства глаза, чтобы вернуться в пространство объектов. (В общем случае вам следует знать, что вы должны разделить конечный результат на w-компонент, поскольку вы были в проективном пространство. С ортогональной проекцией и только аффинными преобразованиями в ModelView w будет 1, чтобы вы могли его игнорировать).

РЕДАКТИРОВАТЬ

Поскольку эта операция является общей, есть также некоторые вспомогательные функции, реализующие этот. Поскольку вы используете матричный стек GL, самым простым решением является использование gluUnproject() из библиотеки GLu. Все, что вам нужно, это трехмерные оконные координаты точки, а также параметры привязки матрицы и вида, которые используются при рисовании объекта, которые могут быть запрошены с использованием glGetDoublev() с использованием различных функций glGet. Существует full example at the old NeHe site.

С современным GL вы должны сделать это самостоятельно. Однако популярная библиотека GLM также имеет метод glm::unProject, аналогичный GLU.

+0

Это, очевидно, правильный ответ, но путь выхода моей лиги, как таковой я пометив его как ответ и надеюсь, что это поможет кому-то остальное. Я просто собираюсь найти другой способ сделать то, что хочу, потому что я абсолютно новичок в OpenGL. –

+0

@ TheEmpireStrikesBack: на самом деле этот ответ меньше о GL, чем о математике. Я обновил свой ответ, чтобы охватить более практические аспекты. – derhass

+0

К сожалению, я использую OpenTK, поэтому я не делаю unProject, но я искал его и нашел для него функцию, тогда я нашел это http://gamedev.stackexchange.com/questions/51820/c-opentk-converting-screen- coords-to-world-coords. Какая функция и как использовать, я собираюсь добавить ответ с моим кодом о том, как это работает. Сейчас он работает очень хорошо, вполне доволен этим. –

0

Это просто расширение моих комментариев, это рабочий код для непроектирования координат мыши в мировых координатах. Это довольно практичный пример того, что сказал дерхасс. Вызов функции:

Dim modelViewMatrix As Matrix4 
    Dim projectionMatrix As Matrix4 
    Dim viewport(4) As Integer 
    GL.GetFloat(GetPName.ModelviewMatrix, modelViewMatrix) 
    GL.GetFloat(GetPName.ProjectionMatrix, projectionMatrix) 
    GL.GetInteger(GetPName.Viewport, viewport) 
    Dim cords As Vector4 = GF.UnProject(projectionMatrix, modelViewMatrix, New Size(viewport(2), viewport(3)), New Vector2(e.Position.X, e.Position.Y)) 

Функция:

Public Function UnProject(ByRef projection As Matrix4, ByVal view As Matrix4, ByVal viewport As Size, ByVal mouse As Vector2) As Vector4 
     Dim vec As Vector4 

     vec.X = 2.0F * mouse.X/CSng(viewport.Width) - 1 
     vec.Y = -(2.0F * mouse.Y/CSng(viewport.Height) - 1) 
     vec.Z = 0 
     vec.W = 1.0F 

     Dim viewInv As Matrix4 = Matrix4.Invert(view) 
     Dim projInv As Matrix4 = Matrix4.Invert(projection) 

     Vector4.Transform(vec, projInv, vec) 
     Vector4.Transform(vec, viewInv, vec) 

     If vec.W > Single.Epsilon OrElse vec.W < Single.Epsilon Then 
      vec.X /= vec.W 
      vec.Y /= vec.W 
      vec.Z /= vec.W 
     End If 

     Return vec 
    End Function 
Смежные вопросы