Я написал этот фрагмент кода на языке C, чтобы нарисовать планетную систему с солнцем и планетой.
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0,0.0,0.0);
glMatrixMode(GL_MODELVIEW_MATRIX);
glPushMatrix();
glutWireSphere(1.0, 20, 16);
glLoadIdentity();
glRotatef((GLfloat) year ,0.0,1.0,0.0);
glTranslatef(2.0, 0.0, 0.0);
glRotatef((GLfloat) day, 0.0, 1.0, 0.0);
glutWireSphere(0.2, 10, 8);
glPopMatrix();
glutSwapBuffers();
Но когда я компилирую и запускаю код, вторая сфера не отображается. После того, как я увеличиваю значение y, оно появляется на половине оборота, когда оно находится за центральной сферой, а затем снова выходит из поля зрения, а также размер сферы больше, чем ожидалось. если я закомментирую вызов glLoadIdentity(), все будет работать нормально. Насколько я знаю, glLoadIdentity() загружает текущую матрицу (ModelView_Matrix) с матрицей идентичности, чтобы эффект всех переводов и поворотов был обратным, но почему в этом случае объекты, нарисованные при его вызове, отображаются по-разному, когда нет поворотов или преобразования выполняются до его вызова?
Ответ 1 · рейтинг 1 · JasonD
Я подозреваю, что у вас действуют другие преобразования в матрице ModelView. Если бы он уже был установлен на идентификатор, то загрузка идентификатора не изменила бы поведение.
Предоставленный вами код устанавливает только преобразование локальной модели. Преобразования проекций или видов не применяются, поэтому их нужно выполнять в другом месте. Возможно при инициализации.
Без предварительного преобразования вида первая сфера будет отрисовываться в том же месте, что и вид - другими словами, камера будет внутри сферы.
Ответ 2 · рейтинг 1 · Zultar
Я подозреваю, что ваша проблема связана с тем, как вы используете glPushMatrix и glPopMatrix в сочетании с glLoadIdentity:
Предположим, у вас есть некоторая матрица A в стеке просмотра модели. Теперь вы используете glPushMatrix, фактически сохраняя A, чтобы восстановить его позже. Внутри блока push-pop вы говорите GLUT нарисовать сферу, что он и делает, используя ранее упомянутую матрицу представления модели A.
Если вы сейчас вызовете glLoadIdentity, все, что было раньше A, исчезнет, пока вы не вызовете glPopMatrix, который восстановит предыдущее состояние A.
Короче говоря, вызовы трансформации после glLoadIdentity основаны на единичной матрице, а не на состоянии матрицы до glPushMatrix.
Видя, что вы хотите сделать, это нарисовать солнечную систему. Вероятно, было бы лучше сделать что-то вроде:
glPushMatrix();
/* Transformations positioning the sun */
/* Draw the sun */
glPushMatrix();
/* Transformations for getting from the sun to the planet */
/* Draw the planet */
glPopMatrix();
glPopMatrix();
Кроме того, конвейер с фиксированными функциями (glTranslate, glRotate, glPushMatrix, ...) уже давно устарел (около 10 лет?), поэтому я бы предложил выбрать OpenGL, используя более современный подход.
Изменить:
При перечитывании вопроса мое внимание привлекла еще одна вещь:
Предполагая, что year указывает, где планета находится в своем вращении вокруг Солнца, а day указывает, насколько растение вращается вокруг своей полярной оси, правильный порядок преобразований будет следующим:
- Повернуть на
day вокруг оси Y
- Перевести
- Повернуть на
year вокруг оси Y
(Прямо сейчас вы делаете это наоборот, что может объяснить странное поведение, которое вы испытываете. См. также здесь.)
Согласно комментарию JasonD, ваш порядок трансформации изначально был правильным, но все же не помешает узнать о предыстории. ;)