0
\$\begingroup\$

I'm trying to port an old perfectly functioning ray casting implementation from my lwjgl project (FF pipeline) to a new project using JOGL and shaders. My problem is that my ray no longer intersects the model at the mouse location although the ray always passes through the mouse location (see image). Further to this, as soon as I apply any transformation to the model - rotation, movement along x,y or z - the ray is completely off and doesn't pass through the mouse location in any case. Would anyone know why this would be happening? As far as I can tell the code is doing exactly what the old project did. I am currently using FloatUtil.mapWinToRay() although I have also tried FloatUtil.mapWinToObjCoords() with the same results.

Example of testing ray trace

Function that creates the testing ray: I use nearVector and farVector to draw the ray.

public Ray getPickingRay(float[] modelMatrix,
                                float[] projMatrix,
                                int[] viewport,
                                float winx,
                                float winy
                            ) {

    // first the near vector
    float[] mat4Tmp1 = new float[16];
    float[] mat4Tmp2 = new float[16];
    float[] vec4Tmp2 = new float[4];
    Ray ray = new Ray();
    FloatUtil.mapWinToRay(winx, winy, 0, 1, 
            modelMatrix, 0, 
            projMatrix, 0, 
            viewport, 0, 
            ray, 
            mat4Tmp1, mat4Tmp2, vec4Tmp2);

    nearVector[0] = ray.orig[0];
    nearVector[1] = ray.orig[1];
    nearVector[2] = ray.orig[2];
    farVector[0] = ray.dir[0] * 100;
    farVector[1] = ray.dir[1] * 100;
    farVector[2] = ray.dir[2] * 100;

    return ray;
}

Function that updates the ray position:

private void updateLineData(GL4 gl) throws Exception{

   //container for two ray vertices
   float[] all = {0,0,0,0,0,0};

  //apply same translation to ray as is applied to entire model.
  view3 = translate(view2, transX, transY, transZ);
  //pass the matrix to the line shader
  shaderLine.setUniform(iMVPLine, multiply(projection,  view3), 
         Shade.MatDataType.MAT4);


  if (updatePos == true){
    updatePos = false;

    int[] viewport = {0,0,screenWidth,screenHeight};
    float[] dest = new float[3];

     Ray ray = pick.getPickingRay(view3, 
            projection, 
             viewport, 
            mx, my);

    float[] front = pick.nearVector;
    float[] back = pick.farVector;


    all[0] = front[0]; 
    all[1] = -front[1]; 
    all[2] = -front[2]; 
    all[3] = back[0]; 
    all[4] = -back[1]; 
    all[5] = -back[2]; 
    whole.updateLine(gl, all);
  }

}

Update the line data buffer:

  public void updateLine(GL4 gl, float[] pos)
  {

      for (int i=0;i<pos.length; i++){
          vertLineBuffer[i] = pos[i];
      }
      //populate the color buffer
      FloatBuffer fbData = Buffers.newDirectFloatBuffer(vertLineBuffer);

      gl.glBindBuffer(GL4.GL_ARRAY_BUFFER, vboLineHandles[VERTICES_LINE_IDX]);
      gl.glBufferSubData(GL4.GL_ARRAY_BUFFER, 0, fbData.capacity() * 4, fbData);
      fbData.clear(); //don't need this anymore  

  }

A final note/clue is that as I click closer to the centre of the screen the intersection point between the ray and the model gets closer to the mousepointer. It is almost as if the ray always wants to point to 0,0,0. My expectation would be that I wouldn't be able to see the ray when it is drawn as it would be following my line of sight thru the model. Then when I translate the view I would be able to see it as I would be looking at a slight angle to the new ray. Currently when the ray draws I can see it right away as it draws between near the centre of the screen and out in the direction of the mousepointer. Any help/hints or tips would be greatly appreciated.

\$\endgroup\$
1
\$\begingroup\$

The basic cause of the problem was that my value for screenY (2D location of mouseclick on Y-axis) was incorrect and so passing it to any valid picking ray function returned invalid results. My old working project got the mouse position values from the org.lwjgl.input.Mouse class whereas the new project is using java.awt.event.MouseListener. The lwjgl implementation of the click event resolved the Y position to the correct value (0,0 at bottom left corner). java.awt.event.MouseListener returns (0, screenHeight) at bottom left. You have to modify the Y simply by passing (screenHeight - mouseY) instead of just mouseY.
The following routine will get the near and far vertices for a picking ray using JOGL:

public float[] getPickingVector(float[] camera,
                                float[] projection,
                                int[] viewport,
                                float winX,
                                float winY) throws Exception {


    float[] mat4Tmp1 = new float[16];
    float[] mat4Tmp2 = new float[16];

    FloatUtil.mapWinToObjCoords(winX, winY, 0, camera, 0, 
            projection, 0, 
            viewport, 0, 
            nearVector, 0, 
            mat4Tmp1, mat4Tmp2);

    FloatUtil.mapWinToObjCoords(winX, winY, 1, modelview, 0, 
            projection, 0, 
            viewport, 0, 
            farVector, 0, 
            mat4Tmp1, mat4Tmp2);

}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.