Help me please with ray picking

float aspect = fabsf(self.view.bounds.size.width / self.view.bounds.size.height);
GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(35.0f), aspect, 0.1f, 1000.0f);

GLKMatrix4 modelViewMatrix = _mainmodelViewMatrix;


    // some transformations

_mainmodelViewMatrix = modelViewMatrix;

_modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix);
_normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL);

_modelViewProjectionMatrix and _normalMatrix put to shader

glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m);

and in touch end

GLKVector4 normalisedVector = GLKVector4Make((2 * position.x / self.view.bounds.size.width - 1),
                                             (2 * (self.view.bounds.size.height-position.y) / self.view.bounds.size.height - 1)   ,  //1 - 2 * position.y / self.view.bounds.size.height,
                                               -1,
                                               1);
GLKMatrix4 inversedMatrix = GLKMatrix4Invert(_modelViewProjectionMatrix, nil);


GLKVector4 near_point = GLKMatrix4MultiplyVector4(inversedMatrix, normalisedVector);

How I can get far point? And my near_point is correct or not?

Thanks!

有帮助吗?

解决方案 2

We can draw line from near_point to far_point.

  GLKVector4 normalisedVector = GLKVector4Make((2 * position.x / self.view.bounds.size.width - 1),
                                                 (2 * (self.view.bounds.size.height-position.y) / self.view.bounds.size.height - 1),  
                                                   -1,
                                                   1);

    GLKMatrix4 inversedMatrix = GLKMatrix4Invert(_modelViewProjectionMatrix, nil);

    GLKVector4 near_point = GLKMatrix4MultiplyVector4(inversedMatrix, normalisedVector);

    near_point.v[3] = 1.0/near_point.v[3];
    near_point = GLKVector4Make(near_point.v[0]*near_point.v[3], near_point.v[1]*near_point.v[3], near_point.v[2]*near_point.v[3], 1);

    normalisedVector.z = 1.0;
    GLKVector4 far_point = GLKMatrix4MultiplyVector4(inversedMatrix, normalisedVector);

    far_point.v[3] = 1.0/far_point.v[3];
    far_point = GLKVector4Make(far_point.v[0]*far_point.v[3], far_point.v[1]*far_point.v[3], far_point.v[2]*far_point.v[3], 1);

其他提示

it looks like you have

GLKVector4 normalisedVector = GLKVector4Make((2 * position.x / self.view.bounds.size.width - 1),
   (2 * (self.view.bounds.size.height-position.y) / self.view.bounds.size.height - 1) ,
   -1, 1);

(phew) to calculate the normalized device coordinates of the near point.

To get the far point, just swap the -1 z coordinate for a 1:

GLKVector4 normalisedFarVector = GLKVector4Make((2 * position.x / self.view.bounds.size.width - 1),
   (2 * (self.view.bounds.size.height-position.y) / self.view.bounds.size.height - 1) ,
   1, 1);

And apply the same inverse transform to that. That should do the trick.

Background: Under normal circumstances, the final coordinates received by the GL for turning a fragment into a pixel are what are called normalised device coordinates. These lie within a cube whose corners are at (-1,-1,-1_ and (1,1,1). So the center of the screen is (0,0,z), the top left corner is (-1,1,z) and so on. The coordinates are transformed so that a point lying on the near plane will have a z coordinate of 1, and one lying just on the far plane will have a z coordinate of -1. These are the numbers that are used for depth testing, if you have it turned on.

So, as you might guess, when you want to convert a screen location back to a point in 3D space, you actually have a number of points to choose from - a line, in fact, stretching from the near plane to the far plane. In normalised device coordinates, this is the line stretching from z=-1 to z=1. So the process goes like this:

  • convert the x and y coordinates into normalised device coordinates x' and y'
  • For each of z' = 1 and z' = -1:
    • convert the coordinates to normalised device coordinates (see here for the formula)
    • apply the inverse of the projection matrix
    • apply the inverse of the model/view matrix (as it is before any per-object transformations)

The results are the two coordinates of your line in 3D space.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top