‘Ray’ создание для raypicking не полностью работает

Я пытаюсь реализовать ‘raypicker’ для выбора объектов в моем проекте. Я не до конца понимаю, как это реализовать, но концептуально понимаю, как это должно работать. Я пытался узнать, как это сделать, но большинство уроков, которые я нахожу, идут мне на ум. Мой текущий код основан на одном из последних учебных пособий, которые я нашел, Вот.

После нескольких часов ревизий, я считаю, что проблема, с которой я столкнулся с моим raypicker-ом, на самом деле заключается в создании луча. Если я заменить / жёстко мои NEAR / FAR плоскости с координатой, которые неоспоримо быть расположены в пределах области треугольника, сборщик определяет его правильно.

Моя проблема заключается в следующем: мое создание луча, кажется, не полностью учитывает мою текущую «камеру» или перспективу, поэтому вращение камеры не повлияет на то, где находится моя мышь.
Я считаю, что для исправления этого мне нужно что-то вроде использования gluUnProject () или что-то, но всякий раз, когда я использовал это, возвращаемые координаты x, y, z были бы невероятно малы,

Мое нынешнее создание лучей — беспорядок. Я пытался использовать методы, предложенные другими изначально, но мне показалось, что метод, который я пробовал, никогда не работал с моей функцией выбора / пересечения.

Вот код для моего создания луча:

void oglWidget::mousePressEvent(QMouseEvent *event)
{

QVector3D nearP = QVector3D(event->x()+camX, -event->y()-camY, -1.0);
QVector3D farP = QVector3D(event->x()+camX, -event->y()-camY, 1.0);

int i = -1;
for (int x = 0; x < tileCount; x++)
{
bool rayInter = intersect(nearP, farP, tiles[x]->vertices);
if (rayInter == true)
i = x;
}
if (i != -1)
{
tiles[i]->showSelection();
}
else
{
for (int x = 0; x < tileCount; x++)
tiles[x]->hideSelection();
}
//tiles[0]->showSelection();
}

Повторить, Я использовал, чтобы загрузить окно просмотра, модель & матрицы проекции, и не проецировать координаты мыши, но в окне 1920×1080 все, что я получаю, это значения в диапазоне от -2 до 2 для x y & z для каждого события мыши, поэтому я пробую этот метод, но этот метод не работает с поворотом камеры и масштабированием.

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

1

Решение

Взгляни на

http://www.realtimerendering.com/intersections.html

Много помощи в определении пересечений между различными видами геометрии

http://geomalgorithms.com/code.html также имеет некоторые функции C ++, одна из которых служит вашей цели

1

Другие решения

Кажется, у вас проблемы с конструированием ваших лучей, вот как я это сделаю. Это не было проверено напрямую. Вы можете сделать это так, убедившись, что все векторы находятся в одном пространстве. Если вы используете несколько матриц моделей (или их стеки), то вычисления необходимо повторять отдельно с каждой из них.

  1. использование pos = gluUnproject(winx, winy, near, ...) получить координату мыши на ближней плоскости в модельном пространстве; near будучи значением, данным для glFrustum() или же gluPerspective()
  2. Источник луча — это положение камеры в пространстве модели: rayorig = inv(modelmat) * camera_in_worldspace
  3. Направление луча — нормализованный вектор от положения от 1. до начала луча: raydir = normalize(pos - rayorig)

На связанном веб-сайте они используют две точки для луча, и они, по-видимому, не нормализуют вектор направления луча, так что это необязательно.

1

Итак, это начало моего следа с сухарями.

У меня были проблемы с типами данных QT для матриц и логикой, связанной с преобразованиями матриц.

Эта конкретная проблема в этом вопросе возникла из-за того, что на самом деле не было никаких преобразований.

Шаги к решению этой проблемы были:

  • Преобразование координат мыши в пространство NDC (в диапазоне от -1 до 1: x / ширина экрана * 2 — 1, y — высота / высота * 2 — 1)
  • захват матрицы 4х4 для моей матрицы просмотра (может быть той, которая используется при рендеринге, или пересчитывается)
  • В новом векторе, чтобы она была равна матрице обратного просмотра, умноженной на матрицу обратной проекции.

Чтобы построить луч, мне нужно было сделать следующее:

  • Возьмите ранее вычисленное значение для матриц, которые были умножены вместе. Это будет умножено на вектор 4 (массив из 4 точек), где он будет содержать ранее вычисленные координаты x и y, а также -1, тогда +1.
  • Тогда этот вектор будет разделен на значение последней точки всего вектора
  • Создайте еще один вектор 4, который был похож на последний, но вместо -1 поместите «1» .
  • Еще раз разделите это на его последнее значение.

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

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

  • Здесь, Я узнал, что мне нужно принять во внимание высоту экрана для переключения начала оси Y для декартовой системы, так как окна имеют начало оси Y в верхнем левом углу. Кроме того, поиск матриц был излишним, но также и неправильным, поскольку они никогда не объявлялись «должным образом».
  • Здесь, Я узнал, что unProject не работает, потому что я пытался получить модель и просмотреть матрицы, используя функции OpenGL, но я никогда не устанавливал их в первую очередь, потому что я строил матрицы вручную. Я решил эту проблему в два раза: я сделал математику вручную, и я сделал все матрицы одного и того же типа данных (раньше они были смешанными типами данных, что также приводило к проблемам).
  • И, наконец, здесь, Я узнал, что мой порядок операций был немного не соответствующим (нужно умножить матрицы на вектор, а не наоборот), что моя ближняя плоскость должна быть равна -1, а не 0, и что последнее значение вектора, которое будет умножено на матрицы (значение «w») должны были быть 1.

Кредиты идут тем людям, которые помогли мне решить эти проблемы:

0
По вопросам рекламы [email protected]