Итак, в основном я создал программу с использованием OpenGL, которая может выполнять 3D-подбор лучей. Если Camera View Direction Ray
касается/пересекает что-либо (что не является воздухом), тогда в точке пересечения/точках будет отображаться немного фиолетового поля.
Если луч пересекается с любым из "красных ящиков", один раз, пересекающийся с лучом, станет зеленым. Земля и стены не изменят цвет или текстуру вообще.
Примеры:
Текущий способ, которым я занимаюсь 3D Ray Picking, получает луч направления обзора камеры, а затем просто вычисляет для пересечений. Моя функция вычисления пересечений не возвращается как логическая, она возвращается как 3D-вектор (координаты самого пересечения)
Вопрос
То, что я пытаюсь достичь, - это рассчитать Picking Ray, но в соответствии с мышью, когда не заблокирован на экране.
Пример. Итак, вы можете видеть, что фиолетовая коробка находится на перекрестье, хотя если бы я разблокировал мышь и переместил ее (поверх экрана, как обычно) и переместил ее к центру зеленой метки X, которую я рисую, тогда я хочу рассчитать луч от центра камеры к координате мыши сверху экрана.
Текущие тесты и идеи
Это должна быть математическая проблема. Вот лишь краткий список вещей, которые я сейчас использую для вычисления луча (и пытается рассчитать второй луч)
- Cameara X, Y, Z
- Камера Pitch Yaw Roll (Roll не используется прямо сейчас)
- Камера рядом с дальним (расстояния)
- Камера Fov
- Аспект камеры
- Мышь X, Y (В верхней части экрана)
- Ширина Sceen, Высота
Мышь X и Y origin (0x0) находится в левом нижнем углу окна/кадра.
Вычисление самого самого самого собирающего луча
Vector3D position = new Vector3D(
camera.x,
camera.y,
camera.z);
Vector3D direction = new Vector3D(
Math.cos(Math.toRadians(camera.pitch)) * -Math.sin(Math.toRadians(-camera.yaw)) * camera.far,
Math.cos(Math.toRadians(camera.pitch)) * cameara.far,
Math.cos(Math.toRadians(camera.pitch)) * -Math.sin(Math.toRadians(-camera.yaw)) * camera.far);
direction.normalize();
Ray3D ray = new Ray(position, direction);
Вот как я вычисляю сам основной луч отбора (луч для захвата запертой мыши). Я сам делал классы, хотя они должны иметь смысл (Vector3D
, Ray3D
и т.д.), А методы normalize()
делают именно то, что он говорит, нормализует вектор.
Идея
Итак, когда я попытался вычислить с помощью координат мыши, я вставил следующий код прямо перед тем, как позвонить direction.normalize();
, поэтому сразу после создания Vector3D direction
.
if (!Mouse.isGrabbed())
{
float mx = Mouse.getX() / (float) scene.width - 0.5f;
float my = Mouse.getY() / (float) scene.height - 0.5f;
mx *= camera.far;
my *= camera.far;
line.b.x += mx;
line.b.y += my;
line.b.z += mz;
}
Это дает мне странный результат, когда мышь не заблокирована/схвачена. Это имеет смысл, так как я просто возился и пытался кое-что из того, что было первым в моей голове.
Я предполагаю, что мне нужно перевести координаты мыши в соответствии с шагом, рыскангом и рулоном. Хотя я и не знаю, как бы я это сделал.
Поэтому я надеюсь, что есть кто-то, кто может помочь мне достичь этого и/или дать мне какой-то ресурс, чтобы я мог понять, как делать то, что я пытаюсь сделать.
Extra
Если вам нужна дополнительная информация об этом, просто напишите комментарий, и я сделаю все возможное.
Ответ - благодаря fen
В итоге я использовал fen, так как это было намного проще, чем вычислять все!
FloatBuffer projection = BufferTools.createFloatBuffer(16);
FloatBuffer modelview = BufferTools.createFloatBuffer(16);
IntBuffer viewport = BufferTools.createIntBuffer(16);
glGetFloat(GL_PROJECTION_MATRIX, projection);
glGetFloat(GL_MODELVIEW_MATRIX, modelview);
glGetInteger(GL_VIEWPORT, viewport);
float win_x = Mouse.getX();
float win_y = Mouse.getY();
FloatBuffer position_near = BufferTools.createFloatBuffer(3);
FloatBuffer position_far = BufferTools.createFloatBuffer(3);
gluUnProject(win_x, win_y, 0f, modelview, projection, viewport, position_near);
gluUnProject(win_x, win_y, 1f, modelview, projection, viewport, position_far);
Ray3D ray = new Ray3D(
new Vector3D(
position_near.get(0),
position_near.get(1),
position_near.get(2)),
new Vector3D(
position_far.get(0),
position_far.get(1),
position_far.get(2)));