Найти точку пересечения луч / треугольник в правой системе координат - PullRequest
0 голосов
/ 24 апреля 2020

Я хотел бы получить точку пересечения линии (определяемой вектором и началом координат) на треугольнике. Мой двигатель использует правую систему координат, поэтому X направлен вперед, Y направлен влево и Z направлен вверх.


---- Редактировать ----

С помощью Антареса я преобразовать мои точки в пространство двигателя с помощью:

p0.x = -pt0.y;
p0.y = pt0.z;
p0.z = pt0.x;

Но я не знаю, как сделать то же самое с вектором направления.


Я использую функцию из этот вопрос стека переполнения , оригинальный постер использует этот урок .

Сначала мы ищем расстояние t от начала координат до точки пересечения, чтобы найти ее координаты. Но у меня есть отрицательное t, и код возвращает true, когда луч находится за пределами треугольника. Я установил это снаружи визуально. Когда я нахожусь в треугольнике, когда-нибудь возвращается false post.

float kEpsilon = 0.000001;

V3f crossProduct(V3f point1, V3f point2){

  V3f vector; 

  vector.x = point1.y * point2.z - point2.y * point1.z; 
  vector.y = point2.x * point1.z - point1.x * point2.z; 
  vector.z = point1.x * point2.y - point1.y * point2.x; 

  return vector;
}

float dotProduct(V3f dot1, V3f dot2){

  float dot = dot1.x * dot2.x + dot1.y * dot2.y + dot1.z * dot2.z; 

  return dot;
}

//orig: ray origin, dir: ray direction, Triangle vertices: p0, p1, p2.  
bool rayTriangleIntersect(V3f orig, V3f dir, V3f p0, V3f p1, V3f p2){ 

// compute plane's normal

  V3f p0p1, p0p2;

  p0p1.x = p1.x - p0.x; 
  p0p1.y = p1.y - p0.y; 
  p0p1.z = p1.z - p0.z; 

  p0p2.x = p2.x - p0.x;
  p0p2.y = p2.y - p0.y; 
  p0p2.z = p2.z - p0.z;

  // no need to normalize
  V3f N = crossProduct(p0p1, p0p2); // N 

  // Step 1: finding P

  // check if ray and plane are parallel ?
  float NdotRayDirection = dotProduct(N, dir); // if the result is 0, the function will return the value false (no intersection).

  if (fabs(NdotRayDirection) < kEpsilon){ // almost 0 

      return false; // they are parallel so they don't intersect ! 
  }

  // compute d parameter using equation 2
  float d = dotProduct(N, p0); 

  // compute t (equation P=O+tR P intersection point ray origin O and its direction R)

  float t = -((dotProduct(N, orig) - d) / NdotRayDirection);

  // check if the triangle is in behind the ray
  //if (t < 0){ return false; } // the triangle is behind 

  // compute the intersection point using equation
  V3f P; 

  P.x = orig.x + t * dir.x; 
  P.y = orig.y + t * dir.y; 
  P.z = orig.z + t * dir.z; 


  // Step 2: inside-outside test
  V3f C; // vector perpendicular to triangle's plane 

  // edge 0
  V3f edge0; 

  edge0.x = p1.x - p0.x;
  edge0.y = p1.y - p0.y;
  edge0.z = p1.z - p0.z;

  V3f vp0; 

  vp0.x = P.x - p0.x;
  vp0.y = P.y - p0.y; 
  vp0.z = P.z - p0.z; 

  C = crossProduct(edge0, vp0); 

  if (dotProduct(N, C) < 0) { return false; }// P is on the right side 

  // edge 1
  V3f edge1;

  edge1.x = p2.x - p1.x;
  edge1.y = p2.y - p1.y;
  edge1.z = p2.z - p1.z;

  V3f vp1; 

  vp1.x = P.x - p1.x; 
  vp1.y = P.y - p1.y; 
  vp1.z = P.z - p1.z; 

  C = crossProduct(edge1, vp1); 

  if (dotProduct(N, C) < 0) { return false; } // P is on the right side 

  // edge 2
  V3f edge2;

  edge2.x = p0.x - p2.x;    
  edge2.y = p0.y - p2.y;
  edge2.z = p0.z - p2.z;

  V3f vp2; 

  vp2.x = P.x - p2.x;
  vp2.y = P.y - p2.y;
  vp2.z = P.z - p2.z;

  C = crossProduct(edge2, vp2);

  if (dotProduct(N, C) < 0) { return false; } // P is on the right side; 

  return true; // this ray hits the triangle 
} 

Моя проблема в том, что я получаю t: -52.603783

точка пересечения P: [-1143.477295, -1053.412842, 49.525799] Это дает мне, относительно текстуры 640X480, уф-точка: [-658, 41].

Возможно, потому что мой двигатель использует Z, направленную вверх?

Ответы [ 2 ]

0 голосов
/ 01 мая 2020

@ GUNNM: Что касается ваших отзывов о том, что вы не знаете, как обращаться с вектором направления, вот несколько идей, которые могут быть вам полезны.

Как я уже сказал, должен быть способ умножения матриц. Ищите ключевые слова, такие как «преобразование вектора направленности с помощью матрицы» или «преобразование нормалей (векторов нормалей) с помощью матрицы». Это должно привести к чему-то вроде: «использовать транспонирование используемой матрицы преобразования» или «инверсию матрицы» или что-то в этом роде.

Обходной путь может быть таким: Вы можете «преобразовать» вектор направления в точка, думая о направлении как о «двух точках», образующих вектор: начальную точку и другую точку, которая находится в направлении, которое вы хотите указать.

Начальная точка вашего луча у вас уже есть в наличии. Теперь вам нужно убедиться, что ваш вектор направления интерпретируется как «вторая точка», а не как «вектор направления».

Если ваш двигатель обрабатывает луч, как в первом случае, у вас будет: Вот моя отправная точка (0,0,0) и вот мой вектор направления (5,6, -7) (я сделал эти числа и взять начало в качестве отправной точки, чтобы иметь простой пример). Так что это просто обычный случай «начало + взгляд».

Во втором случае вы должны иметь: Вот мой старт с (0,0,0), а моя вторая точка - точка на моем направлении вектор (5,6, -7), например, любое направление t *. Который для t = 1 должен точно указывать точку, на которую указывает вектор направления, если он считается вектором (а исходной точкой является начало координат (0,0,0)).

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

Чтобы сделать вектор направления из двух точек, обычно их просто нужно вычесть. Это дает «чистое направление», но без определенной ориентации (которая может быть + t или -t). Поэтому, если вам нужно, чтобы это направление было зафиксировано, вы можете взять абсолютное значение вашего «вектора скользящего значения» t, например, в более поздних вычислениях (это может быть не самый лучший / самый быстрый способ сделать это).

0 голосов
/ 26 апреля 2020

Мой двигатель использует правую систему координат, поэтому X направлен вперед, Y направлен влево и Z направлен вверх.

Вы немного ошибочно представляете правую систему координат .. пожалуйста, отметьте https://en.wikipedia.org/wiki/Cartesian_coordinate_system#In_three_dimensions.

Как следует из названия, X указывает вправо (большой палец правой руки вправо), Y указывает вверх (прямой указательный палец) и Z (прямой средний палец) указывает «вперед» (на самом деле -Z вперед, а Z - назад в системе координат камеры).
На самом деле ... ваши компоненты координат расположены справа, но интерпретация как X - вперед и др. c. необычно.

Если вы подозреваете, что проблема может быть связана с системой координат вашего двигателя (возможно, OGRE? обычный OpenGL? или что-то самодельное?), то вам нужно преобразовать координаты точки и направления в систему координат. вашего алгоритма. Представленный вами алгоритм работает в системе координат камеры, если я не ошибаюсь. Конечно, вам нужно преобразовать полученную точку пересечения обратно в интерпретацию, которую вы используете в двигателе. Чтобы повернуть направление векторного компонента (например, координату Z), вы можете использовать умножение на -1 для достижения эффекта.

Редактировать: Еще одна вещь: я понял, что алгоритм также использует векторы направления, не просто очки. Перестановка компонентов работает только для точек, а не для направлений, если я правильно помню. Возможно, вам нужно выполнить умножение матриц с помощью матрицы преобразования CameraView (или ее обратной M ^ -1, или это была транспонированная M ^ T, я не уверен). Я не могу вам помочь, я надеюсь, что вы можете понять это или просто сделать проб и ошибок.

Моя проблема в том, что я получаю t: -52.603783

точка пересечения P: [- 1143.477295, -1053.412842, 49.525799] Это дает мне, относительно текстуры 640X480, точку ультрафиолета: [-658, 41]

Я считаю, вы считаете, что ваши значения неверны. Какие значения вы ожидаете получить для координат t и UV? Какие из них будут "правильными" для вашего ввода?

Надеюсь, это поможет вам начать. GL, HF с вашим проектом! :)

...