Я работаю над вилкой Pleasant3D .
При вращении отображаемого объекта объект всегда вращается вокруг одной и той же точки относительно себя, даже если эта точка находится не в центре вида (например, из-за того, что пользователь панорамировал, чтобы переместить объект в виде).
Я хотел бы изменить это так, чтобы представление всегда вращало объект вокруг точки в центре представления, как оно отображается пользователю, а не в центре объекта.
Вот ядро текущего кода, который вращает объект вокруг его центра (немного упрощенно) (от здесь ):
glLoadIdentity();
// midPlatform is the offset to reach the "middle" of the object (or more specifically the platform on which the object sits) in the x/y dimension.
// This the point around which the view is currently rotated.
Vector3 *midPlatform = [self.currentMachine calcMidBuildPlatform];
glTranslatef((GLfloat)cameraTranslateX - midPlatform.x,
(GLfloat)cameraTranslateY - midPlatform.y,
(GLfloat)cameraOffset);
// trackBallRotation and worldRotation come from trackball.h/c which appears to be
// from an Apple OpenGL sample.
if (trackBallRotation[0] != 0.0f) {
glRotatef (trackBallRotation[0], trackBallRotation[1], trackBallRotation[2], trackBallRotation[3]);
}
// accumlated world rotation via trackball
glRotatef (worldRotation[0], worldRotation[1], worldRotation[2], worldRotation[3]);
glTranslatef(midPlatform.x, midPlatform.y, 0.);
// Now draw object...
Какие преобразования мне нужно применить, в каком порядке, чтобы получить желаемый эффект?
Что-то из того, что я пробовал до сих пор
Насколько я понимаю, это то, что делает текущий код:
«OpenGL выполняет умножение матриц в обратном порядке, если к вершине применяется несколько преобразований» (с здесь ). Это означает, что первое применяемое преобразование фактически является последним в приведенном выше коде. Он перемещает центр вида (0,0) к центру объекта.
Эта точка затем используется в качестве центра вращения для следующих двух преобразований (поворотов).
Наконец, перевод midPlatform выполняется в обратном порядке, чтобы переместить центр обратно в исходное местоположение, и применяются XY-переводы (панорамирование), выполненные пользователем. Здесь также «камера» перемещается от объекта в нужное место (обозначено cameraOffset).
Это кажется достаточно простым. Так что мне нужно изменить, вместо того, чтобы перевести центр вида в центр объекта (midPlatform
), мне нужно перевести его в текущий центр вида, видимый пользователем, верно?
К сожалению, именно здесь трансформации начинают влиять друг на друга интересным образом, и у меня возникают проблемы.
Я попытался изменить код на это:
glLoadIdentity();
glTranslatef(0,
0,
(GLfloat)cameraOffset);
if (trackBallRotation[0] != 0.0f) {
glRotatef (trackBallRotation[0], trackBallRotation[1], trackBallRotation[2], trackBallRotation[3]);
}
// accumlated world rotation via trackball
glRotatef (worldRotation[0], worldRotation[1], worldRotation[2], worldRotation[3]);
glTranslatef(cameraTranslateX, cameraTranslateY, 0.);
Другими словами, я перевожу центр обзора в предыдущий центр, вращаюсь вокруг него, а затем применяю смещение камеры, чтобы переместить камеру в правильное положение. Это заставляет вращение вести себя именно так, как я хочу, но оно порождает новую проблему. Теперь любое панорамирование, выполненное пользователем, относится к объекту. Например, если объект вращается так, что камера смотрит вдоль оси X, и если пользователь перемещается влево-вправо, то объект, кажется, перемещается ближе / дальше от пользователя, а не влево или вправо.
Я думаю, что могу понять, почему это так (переводы XY камеры применяются до поворота), и я думаю, что мне нужно найти способ отменить перевод до поворота после поворота (чтобы избежать странный эффект панорамирования), а затем выполнить другой перевод, который переводит относительно объекта просмотра (пространство координат глаза) вместо объекта (пространство координат объекта), но я не совсем точно знаю, как это сделать.
Я нашел некоторые подсказки в FAQ по OpenGL (http://www.opengl.org/resources/faq/technical/transformations.htm), например:
9.070 Как преобразовать мои объекты вокруг фиксированной системы координат, а не в локальной системе координат объекта?
Если вы вращаете объект вокруг своей оси Y, вы обнаружите, что оси X и Z вращаются вместе с объектом. Последующее вращение вокруг одной из этих осей вращается вокруг вновь преобразованной оси, а не исходной оси. Часто желательно выполнять преобразования в фиксированной системе координат, а не в локальной системе координат объекта.
Основной причиной проблемы является то, что матричные операции OpenGL повторно умножаются на стек матрицы, что приводит к преобразованию в объектном пространстве. Чтобы повлиять на трансформации пространства экрана, вам нужно предварительно умножить. OpenGL не предоставляет переключателя режимов для порядка умножения матриц, поэтому вам нужно предварительно умножить вручную. Приложение может реализовать это путем извлечения текущей матрицы после каждого кадра. Приложение умножает новые преобразования для следующего кадра поверх единичной матрицы и умножает накопленные текущие преобразования (из последнего кадра) на эти преобразования, используя glMultMatrix ().
Вы должны знать, что получение матрицы ModelView один раз за кадр может отрицательно повлиять на производительность вашего приложения. Однако вам нужно сравнить эту операцию с эталоном, поскольку производительность будет варьироваться от одной реализации к другой.
И
9.120 Как найти координаты вершины, преобразованной только матрицей ModelView?
Часто полезно получить значение координатной точки глаза для вершины (то есть вершины пространства объекта, преобразованной матрицей ModelView). Вы можете получить это, извлекая текущую матрицу ModelView и выполняя простое умножение вектора на матрицу.
Но я не уверен, как применять их в моей ситуации.