2013-02-27 2 views
1

У меня есть учебный проект, который представляет собой простую трехмерную сцену. Я модифицирую матрицу Model-view, чтобы переместить точку зрения в некоторую точку, отличную от нуля, используя gluLookAt(), тогда я помещаю проводную сферу в начало координат. И, наконец, я модифицирую матрицу проекции для получения ортогональной проекции с некоторыми параметрами, используя glOrtho(). Но при изменении размера окна сфера искажается. Я полагаю, мне следует изменить функции reshape() и glOrtho(), но как?Скриншот проекции OpenGL

void display(void){ 
    glClear(GL_COLOR_BUFFER_BIT); 
    glColor3b(197, 96, 63); 
    glLoadIdentity();  
    gluLookAt(2, 0.5 ,2, 0, 0, 0, 0, 1, 0); 
    glutWireSphere(0.2, 20, 10); 
    glFlush(); 
} 

void reshape(int w, int h){ 
    glViewport(0, 0, (GLsizei) w, (GLsizei) h); 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    glOrtho(-1, 1, -1, 1, 0.8 , 100); 
    glMatrixMode(GL_MODELVIEW); 
} 
+0

Как бы вы хотели, чтобы ваше содержимое масштабировалось? Letterboxed? Увеличено окно? –

+0

Вам нужно изменить команду 'glOrtho', чтобы уважать« AspectRatio »вашего экрана. В настоящее время вы говорите, что делаете идеальный квадрат. Если вы измените размер своего окна, но не меняете часть вызова функции (-1, 1, -1, 1, ...), glOrtho настроит вашу систему координат, чтобы объекты отображались на экране в идеальном квадрате , даже если видовой экран (w и h) не представляет квадрат. – 2013-02-27 09:06:58

ответ

3

Как я уже сказал в комментариях, вам нужно настроить ортогональную проекцию чтобы соответствовать вашему окну. Предполагая, что ваше окно OpenGL началось как квадрат перед его изменением размера, (-1, 1, -1, 1, ...) принимал квадратную систему координат. Если вы измените его, чтобы лучше отражать соотношение сторон вашего окна, вы должны лучше посмотреть. Попробуйте следующее:

glOrtho ((float)w/(float)h, (float)-w/(float)h, -1, 1, 0.8, 100);

Это должно поддерживать вашу систему координат, как вы установили его, но уважать пропорции (по ширине).

+0

Да, это работает! Отличный совет, спасибо. – vard

+1

@vard, Имейте в виду, что это касается того, когда соотношение сторон окна перекошено к ширине, превышающей высоту. В других случаях, d необходимо перенести этот (float) материал на другие 2 параметра и сделать (float) h/(float) w, чтобы соотношение сторон соответствовало высоте, превышающей ширину. – 2013-02-27 09:20:35

0

На данный момент вы проецировать окно на квадрике выходе с glOrtho(-1, 1, -1, 1, 0.8 , 100);, так как ширина и высота равна ист. Вы должны изменить первые четыре параметра на текущее соотношение сторон окна, чтобы предотвратить искажение. Как

glOrtho(-w/2f, w/2f, -h/2f, h/2f, 0.8 , 100); 

(В моем примере вы должны сделать свой шар больше, так как проекция плоскость будет больше, то ваше.)

+0

Хм, я ничего не вижу на своем экране, используя ваш код ((может быть, в этой проекции моя сфера слишком мала? – vard

+0

Да, как я писал, вы должны изменить размер своей сферы как минимум на w или h раз больше, чтобы иметь тот же как и раньше. – Gnietschow

2

Во-первых, и полностью не связано с вашей проблемой: переместите все, что у вас есть прямо сейчас, в reshape для отображения. Да, я знаю, что многие учебники имеют это так, как вы это делали, но поверьте мне, это делает вещи намного яснее, когда делаете это не так.


Теперь по поводу вашего вопроса: Ortho устанавливает объем в пространстве вида, that'e сопоставляемого окно просмотра координат. (Нижний, левый) угол glOrtho сопоставляется с (x, y) glViewport и (сверху, справа) отображается на (x, y) + (ширина, высота) glViewport.

Итак, вы должны отрегулировать параметры glOrtho в отношении размеров окна просмотра. Достаточно легко:

void display(void) 
{ 
    int const win_width = glutGet(GLUT_WINDOW_WIDTH); 
    int const win_height = glutGet(GLUT_WINDOW_HEIGHT); 
    float const win_aspect = (float)win_width/(float)win_height; 

    glClear(GL_COLOR_BUFFER_BIT); 
    glViewport(0, 0, win_width, win_height); 

    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    glOrtho(-win_aspect, win_aspect, -1, 1, 0.8 , 100); 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity();  
    gluLookAt(2, 0.5 ,2, 0, 0, 0, 0, 1, 0); 

    glColor3b(197, 96, 63); 
    glutWireSphere(0.2, 20, 10); 
    glFlush(); 
} 
+0

datenwold, спасибо за советы. вы хотите сказать, что частоту вызова функции отображения достаточно, чтобы не увидеть изменения, произошедшие при изменении окна, поэтому мы можем переместить все функции функции преобразования для отображения функции? – vard

+1

@vard: функция отображения всегда будет вызываться после изменения размера окна, так как изменение размера окна приводит к повреждению содержимого окна, требующему обновления дисплея. Основное использование выделенного обработчика переформатирования - это дело с вещью, которая должна произойти только при изменении размера окна, например, повторной инициализации буферов промежуточной обработки постобработки или тому подобного. Однако установка матрицы проецирования - это то, что происходит несколько раз в процессе рендеринга фрейма (думаю, HUD, мини-карта, верхние правые или подобные) в любом серьезном приложении, так что код все равно будет отображаться. – datenwolf

Смежные вопросы