Лучевое преобразование для пересечения луч-треугольник - PullRequest
1 голос
/ 19 октября 2010

В openGL у меня есть 3D-модель, на которой я выполняю пересечение лучей и треугольников, используя код, описанный в статье «Быстрое минимальное пересечение лучей / треугольников» (http://jgt.akpeters.com/papers/MollerTrumbore97/).

Моя позиция курсора не проецируется в мировое пространство с использованием следующего кода:

bool SCamera::unproject(Vector3 input, Vector3 & output){

  GLint viewport[4]; 
  glGetIntegerv(GL_VIEWPORT,viewport); //Grab screen info

  float x = input.mX; 
  float y = input.mY;
  float z = input.mZ;

  Matrix4 P, Mv, res;

  P = getProjection();
  Mv = getCameraTransform();

  Vector3 N; //Cursor point translated to having 0,0 at screen center
  N.mX = ((x-viewport[0]) / viewport[2])*2 - 1;
  N.mY = ((y-viewport[1]) / viewport[3])*2 - 1;
  N.mZ = z*2-1;

  res = P * Mv; //Multiply P * Mv to get transform
  Vector3 w = res.inverse() * N; //Apply transform to N.

  output.mX = w[0];
  output.mY = w[1];
  output.mZ = w[2];
  return true;
}

После этого я формирую луч, выполняя следующее:

unproject(Vector3(xClick, yClick,0),resultUnproject)
ray.origin = cameraPosition;
ray.direction = resultUnproject - ray.origin;
ray.direction.normalize();

Теперь, наконец, я пытаюсь пропустить этот луч через код треугольника (ссылка выше), но я не могу преобразовать его правильно. Моя текущая попытка выглядит следующим образом:

Matrix4 mview, T;
mview = getModelview();
T = mview.inverse();
ray.origin = T*ray.origin;
ray.direction = T*ray.direction;
ray.direction.normalize();

По какой-то причине это не работает. Я неправильно формирую свой луч? Или преобразить это неправильно?

Ответы [ 4 ]

3 голосов
/ 12 февраля 2011

Моим решением было сделать то, что предложил sje397, но просто использовать результат в качестве вашего нового луча.

Итак, в моем проекте (который является XNA), задано ray без проекции курсора:

rayTransform = Matrix.Invert(model_transform);

//Transform ray (or more accurately its defining components into a new ray)
Vector3 v1 = Vector3.Transform(ray.Position, rayTransform);
Vector3 v2 = Vector3.Transform((ray.Position + ray.Direction), rayTransform);
transformedray = new Ray(v1, v2 - v1);

model_transform здесь генерируется так же, как преобразование для шейдера (т. Е. Без перестановки умножений World / Local или чего-либо еще)

Это прекрасно работает в моем проекте с цельювыборка поворачивается, трансформируется и масштабируется различными способами.

Кроме того, вы можете найти это немного бесполезным, но если у вас все еще есть проблемы, вы уверены, что код для снятия проекции курсора и генерации луча выбора работаетправо?Я полагаю, что это должно было бы произойти, если бы ваш код выбора треугольника работал, просто мне кажется, что он получает луч «вокруг».

В моем проекте я беру две точки, одну 'на' плоскости 'области просмотра, поэтому Vector3(cursorx,cursory,0) это снова, но продвижение по оси Z Vector3(cursorx,cursory,1).Отпроектируйте оба этих пункта, результат первого - ваше происхождение, а разница - ваше направление.

Удачи!

3 голосов
/ 19 октября 2010

Один из методов может быть:

Возьмите свое происхождение луча и определите точку на единичном расстоянии в направлении луча в мировом пространстве.Затем выполните преобразование в обе точки - т.е. умножьте на обратную матрицу преобразования.Затем вы можете определить новое направление луча по разности между двумя переведенными точками.Проверка того, отличается ли это направление от оригинала, быстро подскажет, пропустили ли вы шаг.

0 голосов
/ 14 июня 2013

Если у вас есть какой-то луч (уже преобразованный в мировое пространство) и вы хотите проверить, пересекает ли он объект / треугольник, вам нужно умножить его на инвертированные матрицы объекта.Вот некоторый псевдокод:

NewRayPosition = Vector3.Transform(OldRay.Position, Matrix.Invert(Transformation);
NewRayDirection = Vector3.Transform(OldRay.Direction, Matrix.Invert(Rotation*Scale));
NewRayDirection.Normalize();

Умножьте положение луча по сдвигу, шкале и повороту, но по направлению только по шкале и повороту.Делать это так, как вы, недопустимо по причине производительности.Больше здесь: http://www.cl.cam.ac.uk/teaching/1999/AGraphHCI/SMAG/node2.html#SECTION00024100000000000000

0 голосов
/ 22 октября 2010

Итак, я наконец-то заработал, хотя меня не устраивает то, как. В моем случае вращение отдельной модели применяется как преобразование перед рендерингом, поэтому мне пришлось преобразовать целевой треугольник с помощью матрицы вида модели.

То, что я пытался сделать выше, это вычислить луч, который будет служить той же цели, перемещая источник луча вокруг объекта так, как если бы объект вращался. К сожалению, я не мог понять математику правильно.

Конечный результат означает одно преобразование на треугольник вместо одного на луч. К счастью, это не так уж плохо с точки зрения производительности, так как я использую это только для выбора.

...