OpenGL ES 2.0 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 и _normalMatrix помещены в шейдер
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m);
и в конце касания
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);
Как я могу получить дальнюю точку? И моя ближняя точка верна или нет?
Спасибо!
2 ответа
Мы можем нарисовать линию от ближней к дальней точке.
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);
Похоже у тебя
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) для вычисления нормализованных координат устройства ближайшей точки.
Чтобы получить дальнюю точку, просто поменяйте местами -1
координата Z для 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);
И примените то же самое обратное преобразование к этому. Это должно делать свое дело.
Фон: при нормальных обстоятельствах, окончательные координаты, полученные GL для превращения фрагмента в пиксель, являются так называемыми нормализованными координатами устройства. Они лежат в кубе, углы которого находятся в (-1,-1,-1_ и (1,1,1). Таким образом, центр экрана (0,0,z), верхний левый угол (-1,1,z) и т. Д. Координаты преобразуются таким образом, что точка, лежащая на ближней плоскости, будет иметь координату z, равную 1, а точка, лежащая непосредственно на дальней плоскости, будет иметь координату az, равную -1. Это числа, которые используются для проверки глубины, если она включена.
Так что, как вы можете догадаться, когда вы хотите преобразовать местоположение экрана обратно в точку в трехмерном пространстве, у вас на самом деле есть несколько точек на выбор - линия, фактически вытягивающаяся из ближней плоскости в дальнюю плоскость. В нормированных координатах устройства это линия, растягивающаяся от z=-1 до z=1. Итак, процесс идет так:
- преобразовать координаты x и y в нормализованные координаты устройства x'и y'
- Для каждого из z' = 1 и z' = -1:
Результатом являются две координаты вашей линии в трехмерном пространстве.