Ваш вопрос все еще недостаточно ясен, но я сделаю несколько предположений и надеюсь, что они соответствуют вашей ситуации.
Во-первых, нам нужен выбирающий луч, который представляет 2D-положение мыши в 3D-пространстве. Для этого мы сначала преобразуем положение мыши из координат пикселей в нормализованные координаты устройства между -1 и 1:
mouseNDCX = 2 * mousePixelX / viewportWidth - 1
mouseNDCY = 1 - 2 * mousePixelY / viewportHeight
Затем мы находим луч. Для этого нам понадобится матрица проекции вида вашей камеры. Тогда:
mouseNear = inverse(viewProjection) * (mouseNDCX, mouseNDCY, 0, 1)
mouseFar = inverse(viewProjection) * (mouseNDCX, mouseNDCY, 1, 1)
Это даст вам две позиции на луче выбора. Один на плоскости z-ближний и один на плоскости z-дальний. Не забудьте сделать перспективное деление:
mouseNear = (1 / mouseNear.w) * mouseNear
mouseFar = (1 / mouseFar.w) * mouseFar
Следующим шагом является вычисление точки пересечения с сеткой. Здесь ваш вопрос сильно не указан. Я предполагаю, что сетка лежит на плоскости, параллельной одной из главных плоскостей. В дальнейшем это будет плоскость xy. Если у вас другая плоскость, вам необходимо заменить соответствующие компоненты. Далее я буду предполагать, что сетка находится на высоте z
.
Теперь мы хотим найти пересечение, т. Е .:
((1 - t) * mouseNear + t * mouseFar).z = z
<=> mouseNear.z + t * (mouseFar.z - mouseNear.z) = z
<=> t = (z - mouseNear.z) / (mouseFar.z - mouseNear.z)
Это позволяет нам вычислить точку пересечения:
intersection = (1 - t) * mouseNear + t * mouseFar
Эта точка пересечения лежит на плоскости сетки. Наконец, нам нужно найти индекс плитки. Для этого нам нужно только рассмотреть x- и y-компоненты. Если предположить, что источник вашей сетки находится на o
, а плитки имеют размер s
, то индексы плиток:
i = floor((intersection.x - o.x) / s)
j = floor((intersection.y - o.y) / s)