mahesh Rao
mahesh Rao

Reputation: 375

OpenglGL - how to check if cursor coincides with object region?

I am trying to implement a logic where, on mouse click, a shot is fired at an object.
To do so, I did the following,

I first considered the .obj file of my model and found the region (list of coordinates) that the shot works on (a particular weak point of the body). I then considered the least and largest x,y and z values present in the file for that particular region (xmin,ymin,zmin and xmax,ymax,zmax).

To figure out whether the shot has landed on the weak point, I considered the assumption that a shot would land on the weak point, if the coordinates of the shot lie between (xmin,ymin,zmin) and (xmax,ymax,zmax).

I assumed the coordinates from the .obj file to be the actual coordinates of the model, since the assimp code I have directly loads in the coordinates of the model. Considering (xmin,ymin,zmin) and (xmax,ymax,zmax), I converted the coordinates to window coordinates via gluProject().

I then considered the current cursor position and checked if the cursor position lies between (xmin,ymin,zmin) and (xmax,ymax,zmax).

The problems I now face are:

How can I get my logic working ?

Here is the code:

// 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);


Mouse button callback

// 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--;}


The .obj coordinates have eg. values as shown:
0.032046 1.533727 4.398055

Upvotes: 0

Views: 236

Answers (1)

BDL
BDL

Reputation: 22175

You are confusing the parameters of gluProject, especially the view parameter. This parameter should contain 4 integers which describe the viewport (x,y,width,height) and not the view matrix.

gluProject (and a lot of other glu functions) are tailored towards the fixed function pipeline and their matrix stacks. Due to this, you have to pass the following information:

  • model: The modelview matrix, as returned by glGetDoublev( GL_MODELVIEW_MATRIX, ...)).
  • proj: The projection matrix, as returned by glGetDoublev( GL_PROJECTION_MATRIX, ...).
  • view: The current viewport, as returned by glGetIntegerv( GL_VIEWPORT, ...)

As you see, the view matrix is packed together with the model matrix and view contains the viewport.

I'd strongly advice not to use glu functions at all when working with modern OpenGL. Especially when the matrices are already stored in glm, it would be better to use glm::project.

Note1: Converting a floating point matrix to an integer matrix by casting each element almost never results in anything meaningful.

Note2: When projecting a bounding rectangle to screenspace, the result will in general not be a rectangle anymore. During projection, angles are not preserved, thus the result is a general four cornered polygon and not a rectangle anymore. Same goes for bounding boxes: You can't even guarantee that the projected box is contained in the screen-space rectangle defined by projecting [x_min, y_min, z_min] and [x_max, y_max, z_max].

Upvotes: 0

Related Questions