Вы можете использовать gluUnProject для преобразования координат мыши в трехмерное пространство и получения вектора (разница между двумя точками).Этот вектор может быть использован для применения «силы» к выбранной грани.Поскольку gluUnProject использует матрицу проекции, он будет автоматически иметь дело с ориентацией камеры.
По сути, как только вы получите свой вектор «силы», вы спроецируете его на три оси (т. Е. На (1,0,0), (0,1,0), (0,0,1)).Затем выберите тот, который имеет наибольшую величину.Затем вы должны преобразовать это направление в ось вращения, как показано на диаграмме ниже (извините за плохие навыки рисования):
Итак, у нас есть вектор «силы»в черном и выделенные рубики лица в сером.Чтобы получить ось вращения, просто возьмите перекрестное произведение вектор «силы» с нормалью выбранной грани.Это дает красную стрелку.Исходя из этого, вы сможете вращать свои кубики в правильном направлении.
Изменить, чтобы ответить на вопрос более подробно
Итак, продолжая объяснение, я будуприведите пример того, как это вам поможет.Давайте сначала предположим, что ваш экран имеет размер 800x800 пикселей, а кубик Рубика всегда центрирован.Теперь давайте также предположим, что, согласно вашим чертежам в комментариях, мы находимся в случае слева.
Мы перетаскиваем мышь и получаем две позиции, которые с помощью gluUnProject преобразуются в мировые координаты (числа быливыбранный, чтобы показать мою точку зрения, а не каким-либо расчетом):
p1 : (600, 600) -> (1, -0.5, 0)
p2 : (630, 605) -> (1.3, -0.505, 0)
Теперь мы получаем вектор разности: p2 - p1 = v = (0,3, -0,05, 0).Причина, по которой я говорил «проецировать на три оси», заключается в том, что вы извлекаете свое основное движение (которое в данном случае составляет 0,3 по оси x) (поскольку куб Рубика не может вращаться вдоль диагоналей).Чтобы выполнить «проекцию», вам просто нужно взять оси x, y, z по отдельности и создать из них векторы, чтобы получить:
v1 = (0.3, 0, 0)
v2 = (0, -0.05, 0)
v3 = (0, 0, 0)
Теперь возьмите величины и отбросьте наименьшие векторы, так чтомы остались с вектором v1 = (0.3, 0, 0).Это ваш вектор движения в мировом пространстве.Теперь вы берете перекрестное произведение этого вектора с вектором нормали выбранной грани (который в этом случае будет (0, 0, 1)).Это дает вам вектор, который указывает вниз (0, 1, 0) (после нормализации) (на этом этапе вам, вероятно, также придется извлечь только самый большой компонент (0.02, 1.2, 0.8) -> (0, 1, 0)в противном случае вы получите странные повороты, если ваша камера не будет направлена прямо вдоль главных осей).Теперь вы можете использовать этот вектор в качестве оси вращения и использовать 0,3 в качестве величины вращения (если он вращается в направлении, противоположном ожидаемому, просто введите -).
Теперь, как это поможет, если ваш кубСверху вниз?Предположим, мы нажимаем на экран таким же образом.Теперь мы получаем:
p1 : (600, 600) -> (-1, 0.5, 0)
p2 : (630, 605) -> (-1.3, 0.505, 0)
Видите разницу в мировых координатах?Они перевернуты!Поэтому, когда вы берете вектор разности p2 - p1 = v = (-0,3, 0,05, 0).Извлечение вектора наибольшего компонента дает (-0,3, 0, 0).Выполнение перекрестного произведения еще раз дает вам ось вращения, но теперь вращение происходит в противоположном направлении, что вам и нужно.
Еще одна причина для перекрестного произведения с нормалью грани заключается в том, что если вынужно было выбрать грани вверху (на наших чертежах), а затем либо задать ось вращения вдоль осей x или z (влево или на экран), что и нужно для верхних граней.