2017-02-15 31 views
1

Я пытаюсь реализовать метод выбора лучей для функции GLM glm :: unProject. Мои проблемы с неправильным расположением лучей на экране и неправильной перспективой. Ниже какой-то упрощенный код ...glm :: unProject не работает и неправильное положение луча на экране

Моя LookAt функция:

glm::mat4 ViewMatrix() 
{ 
    Front.x = cos(glm::radians(Yaw)) * cos(glm::radians(Pitch)); 
    Front.y = -sin(glm::radians(Pitch)); 
    Front.z = sin(glm::radians(Yaw)) * cos(glm::radians(Pitch)); 
    Right = glm::normalize(glm::cross(Front, WorldUp)); 
    Up = glm::normalize(glm::cross(Right, Front)); 
    glm::vec3 PositionPan = RightPan + UpPan; 
    Position += PositionPan; 

    return glm::lookAt((Position + radius * (Front)), Position , Up); 
} 

Вы заметите мою функцию включают неправильный параметр, но я хочу сделать бесплатную камеру (что-то вроде 3ds Max и т.д.) с прицелом на 0,0,0 с возможным панорамированием (PositionPan for Position) и масштабированием (радиус). Я потратил так много времени, чтобы работать правильно, и я не знаю другого способа сделать это по-другому. У меня есть подозрение, что эта функция является причиной неправильной работы функции Ray с GLM. Если вы заметили что-то неправильное, дайте мне знать, пожалуйста.

Моей Transform функции:

glm::mat4 view = ViewMatrix(); 
glm::mat4 projection = glm::perspective(1.0f, 
(float)screenWidth/(float)screenHeight, 0.1f, 100.0f); 

Луч Моей функция:

void Ray(posx, posy, glm::mat4 view, glm::mat4 projection) 
{ 
    x = (posx/screenWidth - 0.5f) * 2.0f; 
    y = (posy/screenHeight - 0.5f) * -2.0f; 

    worldSpaceNear = glm::unProject(glm::vec3(x, y, 0.0), 
    view, projection,   
    glm::vec4(0.0, 0.0, screenWidth, screenHeight)); 

    worldSpaceFar = glm::unProject(glm::vec3(x, y, 1.0), 
    view, projection, 
    glm::vec4(0.0, 0.0, screenWidth, screenHeight)); 
} 

Следующие проходят worldSpaceNear/Далекие параметры в ВАО и производить в геометрическом шейдере длинный параллелепипеда начинается с Ближнего к дальнему плану. Преобразование из пространства экрана в пространство клипа верное, но при отладке луч начинает с левого нижнего угла и сразу исчезает. Положение мыши на экране существенно не влияет на луч. НО! если изменить функцию Ray для классического метода:

void mRay(glm::mat4 view, glm::mat4 projection 
{ 
    x = (posx/screenWidth - 0.5f) * 2.0f; 
    y = (posy/screenHeight - 0.5f) * -2.0f; 

    glm::vec4 localNear{ x, y, 0.0, 1.0 }; 
    glm::vec4 localFar{ x, y, 1.0, 1.0 }; 

    auto wsn = glm::inverse(projection * view) * localNear; 
    worldSpaceNear = glm::vec3(wsn.x, wsn.y, wsn.z); 

    auto wsf = glm::inverse(projection * view) * localFar; 
    worldSpaceFar = glm::vec3(wsf.x, wsf.y, wsf.z); 

}

все почти в порядке. Луч, чтобы следить за мышью, но имеет неправильную перспективу. Луч должен рассеиваться в соответствии с перспективой, но в моем случае он стремится к центру Дальнего плана. Как я могу исправить это, или как я могу его решить на GLM?

обновления для DERHASS

После mRay() Я отправить worldSpaceNear/Дальний, чтобы сделать петлю. I khow Ussually работает с направлением, но я сделал так:

renderLine(glm::vec3 worldSpaceNear, glm::vec3 worldSpaceFar, 
glm::mat4 view, glm::mat4 projection, glm::vec3 colorOverlay, 
Shader shader) 
{ 
... 
//Create VAO, VBO 
... 
GLfloat vertices[] ={ 
    worldSpaceNear.x - 0.01, worldSpaceNear.y + 0.01, worldSpaceNear.z, 
    worldSpaceFar.x - 0.01, worldSpaceFar.y + 0.01, worldSpaceFar.z, 
    worldSpaceNear.x - 0.01, worldSpaceNear.y - 0.01, worldSpaceNear.z... 
// Long box from near to far 
... 
glDrawArrays(GL_LINE_LOOP, 0, 8); 
} 

В вершинном шейдере просто:

gl_Position = projection * view * model * vec4(position, 1.0f); 

Теперь я думаю, может быть, я забыл удалить поворот компонента из вида матрицы для линии, или наоборот, чтобы добавить поворот с камеры.

ответ

1

glm::unProject unprojects a point from window sapce для глазного пространства (или любых других матриц, которые вы вкладываете в это). Однако целью, которую вы не разрабатываете, является

x = (posx/screenWidth - 0.5f) * 2.0f; 
y = (posy/screenHeight - 0.5f) * -2.0f; 

который не является окном. Вы фактически преобразуете его в нормализованные координаты устройства здесь. Функция unproject сделает это преобразование уже внутренне (поэтому вам нужно передать четыре параметра видового экрана).Это также объясняет, почему луч не сильно движется, потому что перемещение мыши по всему экрану просто изменит его на два пикселя, когда эти значения будут интерпретироваться как пространство окон.

Единственное, что вы должны сделать сами это зеркальное отображение в у, как оконное пространство происхождения GL находится в нижнем левом углу:

x = posx; 
y = screenHeight - 1.0f - posy; 
+0

Спасибо! Я решил эту проблему с отображением непроектов GLM и координат мыши правильно. Но мой луч стал просто точкой под мышкой. Вы замечаете что-то странное в моей части LookAt? – OpenGLNoob

+0

Я не думаю, что ваш вызов 'LookAt' виноват. Но вы не показываете все, если соответствующий код вы используете для создания луча. – derhass

+0

derhass Посмотрите обновление! – OpenGLNoob

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

  • Нет связанных вопросов^_^