OpenglGL - как проверить, совпадает ли курсор с областью объекта? - PullRequest
0 голосов
/ 04 июня 2018

Я пытаюсь реализовать логику, при которой, по щелчку мыши, выстреливается в объектДля этого я сделал следующее,Сначала я рассмотрел файл .obj моей модели и нашел область (список координат), над которой работает снимок (определенная слабая точка тела).Затем я рассмотрел наименьшие и самые большие значения x, y и z, присутствующие в файле для этой конкретной области (xmin, ymin, zmin и xmax, ymax, zmax).Чтобы выяснить, попал ли выстрел в слабую точку, я рассмотрел предположение, что выстрел будет попадать в слабую точку, если координаты выстрела лежат между (xmin, ymin, zmin) и (xmax, ymax, zmax),Я предположил, что координаты из файла .obj являются фактическими координатами модели, так как код ассимпа, который я имею, загружается непосредственно в координаты модели.Учитывая (xmin, ymin, zmin) и (xmax, ymax, zmax), я преобразовал координаты в координаты окна через gluProject().Затем я рассмотрел текущую позицию курсора и проверил, находится ли позиция курсора между (xmin, ymin, zmin) и (xmax, ymax, zmax).Проблемы, с которыми я сейчас сталкиваюсь:

  • Координаты объекта, указанные в диапазоне .obj, находятся в диапазоне от -4 до 4, которые затем лежат около 1,0 после gluProject(), тогда как положение курсора находится между (0, 0) и (1280 720).
  • После gluProject(), (xmin, ymin) и (xmax, ymax) равны (0,1) или (1,0), тогда как zmin и zmaxзначения кажутся нормальными.

Как мне заставить мою логику работать?Вот код:

// Call shader to draw and acquire necessary information for gluProject()
    modelShader.use();
    modelShader.setMat4("projection", projection);
    modelShader.setMat4("view", view);
    glm::mat4 model_dragon;
    double time=glfwGetTime();
    model_dragon=glm::translate(model_dragon, glm::vec3(cos((360.0-time)/2.0)*60.0,cos(((360.0-time)/2.0))*(-2.5),sin((360-time)/1.0)*60.0));
    model_dragon=glm::rotate(model_dragon,(float)(glm::radians(30.0)),glm::vec3(0.0,0.0,1.0));
    model_dragon=glm::scale(model_dragon,glm::vec3(1.4,1.4,1.4));
    modelShader.setMat4("model", model_dragon);
    collision_model=model_dragon;collision_view=view;collision_proj=projection; //so that I can provide the view,model and projection required for gluProject()
    ourModel.Draw(modelShader);

Обратный вызов кнопки мыши

// Note: dragon_min and dragon_max variables hold the constant position of the min and max coordinates.
void mouse_button_callback(GLFWwindow* window,int button,int action,int mods){
if(button==GLFW_MOUSE_BUTTON_LEFT && action==GLFW_PRESS){
    Mix_PlayChannel( -1, shot, 0 ); //Play sound
    GLdouble x,y,xmin,ymin,zmin,xmax,ymax,zmax,dmodel[16],dproj[16];
    GLint dview[16];
    float *model = (float*)glm::value_ptr(collision_model);
    float *proj = (float*)glm::value_ptr(collision_proj);
    float *view = (float*)glm::value_ptr(collision_view);
    for (int i = 0; i < 16; ++i){dmodel[i]=model[i];dproj[i]=proj[i];dview[i]=(int)view[i];} // Convert mat4 to double array
    glfwGetCursorPos(window,&x,&y);
    gluProject(dragon_min_x,dragon_min_y,dragon_min_z,dmodel,dproj,dview,&xmin,&ymin,&zmin);  
    gluProject(dragon_max_x,dragon_max_y,dragon_max_z,dmodel,dproj,dview,&xmax,&ymax,&zmax);
if((x>=xmin && x<=xmax) && (y>=ymin && y<=ymax)){printf("Hit\n");defense--;}

Координаты .obj имеют например.значения как показано:0.032046 1.533727 4.398055

1 Ответ

0 голосов
/ 04 июня 2018

Вы путаете параметры gluProject, особенно параметр view.Этот параметр должен содержать 4 целых числа, которые описывают область просмотра (x, y, width, height), а не матрицу представления.

gluProject (и множество других функций glu) предназначены для конвейера с фиксированными функциямии их матричные стеки.В связи с этим вам необходимо передать следующую информацию:

  • модель: модель матрица , возвращаемая glGetDoublev( GL_MODELVIEW_MATRIX, ...)).
  • proj:Матрица проекции, возвращаемая представлением glGetDoublev( GL_PROJECTION_MATRIX, ...).
  • : текущий видовой экран, возвращаемый glGetIntegerv( GL_VIEWPORT, ...)

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

Я бы настоятельно рекомендовал вообще не использовать функции glu при работе с современным OpenGL.Особенно, когда матрицы уже хранятся в glm, было бы лучше использовать glm::project.

Примечание 1. Преобразование матрицы с плавающей запятой в целочисленную матрицу путем приведения каждого элемента почти никогда не приводит к результатам.в любом значимом.

Примечание 2. При проецировании ограничивающего прямоугольника на пространство экрана результат, как правило, больше не будет прямоугольником.Во время проецирования углы не сохраняются, поэтому получается общий четырехугольный многоугольник, а не прямоугольник.То же самое касается ограничивающих прямоугольников: вы даже не можете гарантировать, что проецируемый прямоугольник содержится в прямоугольнике экранного пространства, заданном проецированием [x_min, y_min, z_min] и [x_max, y_max, z_max].

...