Вызов glLoadIdentity показывает странное поведение

Я написал этот фрагмент кода на языке 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) с матрицей идентичности, чтобы эффект всех переводов и поворотов был обратным, но почему в этом случае объекты, нарисованные при его вызове, отображаются по-разному, когда нет поворотов или преобразования выполняются до его вызова?


person bhuwansahni    schedule 17.03.2013    source источник


Ответы (2)


Я подозреваю, что у вас действуют другие преобразования в матрице ModelView. Если бы он уже был установлен на идентификатор, то загрузка идентификатора не изменила бы поведение.

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

Без предварительного преобразования вида первая сфера будет отрисовываться в том же месте, что и вид — другими словами, камера будет внутри сферы.

person JasonD    schedule 19.03.2013

Я подозреваю, что ваша проблема связана с тем, как вы используете 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 указывает, насколько растение вращается вокруг своей полярной оси, правильный порядок преобразований будет следующим:

  1. Повернуть на day вокруг оси Y
  2. Перевести
  3. Повернуть на year вокруг оси Y

(Прямо сейчас вы делаете это наоборот, что может объяснить странное поведение, которое вы испытываете. См. также здесь.)

Согласно комментарию JasonD, ваш порядок трансформации изначально был правильным, но все же не помешает узнать о предыстории. ;)

person Zultar    schedule 17.03.2013
comment
Я бы отодвинул последнее в сторону к началу. Новый OpenGL с шейдерами и прочим намного интереснее и мощнее. - person Display Name; 17.03.2013
comment
Полностью! Кроме того, нет еще больших усилий, связанных с его правильным изучением. По крайней мере, это то, что я испытал. - person Zultar; 17.03.2013
comment
@Zultar Поскольку перед вызовом glLoadIdentity() нет поворотов и преобразований, разве вызов glLoadIdentity() не должен ни на что влиять ?? - person bhuwansahni; 17.03.2013
comment
Вы уверены, что раньше не было преобразований? Может быть, из разных частей вашего кода? - person Zultar; 17.03.2013
comment
Наткнулся на другую проблему и добавил объяснение к моему ответу. Надеюсь, это исправят! - person Zultar; 17.03.2013
comment
@Zultar Преобразования применяются в предложенном вами порядке, они объединяются GL, так что они эффективно применяются к геометрии в обратном порядке. - person JasonD; 19.03.2013
comment
@JasonD Не знал об этом, можете ли вы поделиться ссылкой, в которой более подробно рассказывается о процессе? - person Zultar; 19.03.2013
comment
@Zultar Это на самом деле объясняется в ссылке, которую вы сами предоставили. - person JasonD; 19.03.2013
comment
@JasonD Вау, я даже не знал, что старые вызовы преобразования имитировали матричную алгебру вот так. Я как бы вырос, перемножая матрицы в коде шейдера. Спасибо за указание на это! - person Zultar; 19.03.2013