2015-06-08 4 views
1

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

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

EDIT:
Вот реализация 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

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

+0

Если вы имеете в виду применение обратного преобразования как к началу луча, так и по направлению луча, то я должен сказать, что я его пробовал, и он не работает. – M2X

+0

Применяя (обратное) преобразование к лучу: помните, что это вектор направленности, а не позиция, что означает, что на него не влияют переводы. Этого можно добиться, установив w-компонент в ноль: (dx, dy, dz, 0) вместо одного. –

+0

@ DannyRuijters Я не уверен, что понимаю, что вы имеете в виду. Луч уже находится в формате vec3 (почему бы это было в однородной системе координат (vec4)?!) Вы предлагаете мне преобразовать его в vec4? Можете ли вы объяснить немного больше? – M2X

1

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

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

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

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

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

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

+0

Посмотрите на редактирование. Я делаю больше или меньше что-то похожее на вас. Я попробовал 'Vector4d.Transform (pos, Matrix4d.Invert (GetModelViewMatrix() * GetProjectionMatrix() * ObjectTransform)), но это не давало мне то, что я хотел :( – M2X

Смежные вопросы