OpenGL приведение лучей (сбор): учет преобразования объекта

Для выбора объектов я реализовал алгоритм приведения лучей, подобный тому, что описан здесь. После преобразования щелчка мыши в луч (с началом и направлением) следующая задача - пересечь этот луч со всеми треугольниками в сцене, чтобы определить точки попадания для каждой сетки.

Я также реализовал алгоритм проверки пересечения треугольников на основе описанного здесь. Мой вопрос: как мы должны учитывать преобразования объектов при выполнении пересечения? Очевидно, я не хочу применять матрицу преобразования ко всем вершинам, а затем выполнять тест пересечения (слишком медленно).

РЕДАКТИРОВАТЬ:
Вот реализация UnProject, которую я использую (кстати, я использую OpenTK). Я сравнил результаты, они соответствуют тому, что GluUnProject дает мне:

private Vector3d UnProject(Vector3d screen)
{
    int[] viewport = new int[4];
    OpenTK.Graphics.OpenGL.GL.GetInteger(OpenTK.Graphics.OpenGL.GetPName.Viewport, viewport);

    Vector4d pos = new Vector4d();

    // Map x and y from window coordinates, map to range -1 to 1 
    pos.X = (screen.X - (float)viewport[0]) / (float)viewport[2] * 2.0f - 1.0f;
    pos.Y = 1 - (screen.Y - (float)viewport[1]) / (float)viewport[3] * 2.0f;
    pos.Z = screen.Z * 2.0f - 1.0f;
    pos.W = 1.0f;

    Vector4d pos2 = Vector4d.Transform(pos, Matrix4d.Invert(GetModelViewMatrix() * GetProjectionMatrix()));
    Vector3d pos_out = new Vector3d(pos2.X, pos2.Y, pos2.Z);

    return pos_out / pos2.W;
}  

Затем я использую эту функцию для создания луча (с началом и направлением):

private Ray ScreenPointToRay(Point mouseLocation)
{
    Vector3d near = UnProject(new Vector3d(mouseLocation.X, mouseLocation.Y, 0));
    Vector3d far = UnProject(new Vector3d(mouseLocation.X, mouseLocation.Y, 1));

    Vector3d origin = near;
    Vector3d direction = (far - near).Normalized();
    return new Ray(origin, direction);
} 

2 ответа

Решение

Вместо этого вы можете применить обратное преобразование каждого объекта к лучу.

Я не знаю, является ли это лучшим / наиболее эффективным подходом, но недавно я реализовал нечто подобное:

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

( mouseClick.x, viewportHeight - mouseClick.y, 0 )

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

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

Вы упомянули, что пытались применить обратное преобразование, но оно не сработало - может быть, там есть ошибка? Я использовал GLM - т.е. glm::unProject - для этого.

Другие вопросы по тегам