2013-03-31 3 views
0

Я только начал пытаться использовать простой «draw cube» openGl tutorial. После окончательной победы над тем, чтобы OpenGL работал, у меня все еще есть очень странные результаты. Моя проблема в том, что объекты имеют тенденцию к изменению размеров в соответствии с размером окна. Вместо этого я хотел бы, чтобы размер окна определял область рендеринга - чем больше окно, тем больше вы можете видеть.Что такое координаты OpenGL? Игнорировать размер окна OpenGL

Вот несколько скриншотов из изменений размера:
Normal size
Resized
Изображения хранятся в виде ссылок намеренно!

Это поведение при автоматическом изменении размеров задает вопрос, какие координаты используются в OpenGL.

+0

взглянуть на это [вопрос] (http://stackoverflow.com/questions/15536333/keeping-a-square -clipping объема квадратных независимо-оф-порта просмотра размера-в-OpenGL/15536710 # 15536710). Я думаю, он обращается к тому, что вы просите. – radical7

ответ

2

Первое, что нужно иметь в виду: OpenGL - это API-интерфейс чертежа. Он не поддерживает сцену или что-то в этом роде.

Итак, что такое OpenGL, он отображает входные координаты геометрии в виде атрибутов вершин на экранное пространство. В старой фиксированной функции есть специальный атрибут вершины, называемый «вершинная позиция» или просто короткая «вершина» (фактическая вершина больше, чем просто позиция).

Положения трансформируются в пространство окна в три этапе:

1. Преобразование в поле зрения/глазах пространства: Это делается путем умножения положения вершины с видовой матрицей.

Некоторые дополнительные расчеты, такие как расчет освещенности, выполняются в пространстве взгляда.

2. Преобразование в пространство клипа: Положение пространства зрения преобразуется в пространство клипа. Обычно это называется проекцией, а матрица, описывающая это преобразование, называется матрицей проектирования.

В пространстве клипа происходят какие-то особые вещи, обобщенные как отсечения, вам не о чем беспокоиться.

3. На заключительном этапе преобразованная обрезанная геометрия преобразуется в нормализованные координаты устройства (NDC). Пространство NDC практически равно 1: 1 для отображения в окне просмотра, т. Е. Пределы объема NDC непосредственно соответствуют смещению и размеру окна просмотра, установленного с glViewport.

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

Итак, вот что вам нужно сделать: Пределы проекции должны быть прямо пропорциональны экстентам просмотра. Как это, например

glViewport(0, 0, width, height); 
glMatrixMode(GL_PROJECTION); 
glLoadIdentity(); 
glOrtho(-width/2, width/2, -height/2, height/2, -1, 1); 

О, и только на общее примечание: Вы всегда должны установить окно просмотра и настройки проецирования в функции рисования, тоже. Если вы видите учебник, в котором эти операторы помещают в обработчик изменения размера окна, просто игнорируйте его и просто делайте это в коде чертежа. В долгосрочной перспективе это действительно упрощает ситуацию.

+0

Мне нравится ваше общее примечание, но моя проблема в том, что я совершенно не знаю, как получить размеры окна (будет ли это Google, но я боюсь новых злых функций, которые готовы показать мне, насколько я хромаю) и также, как применить это на gluPerspective (обнаружил, что в Интернете во время ожидания ответа), который просто принимает widht/height - поэтому изменение размера приведет к увеличению масштаба (возможно, какой-то перевод может быть использован, но это правильно?). –

+0

ну, genpfault отправил то, что вы объяснили, поэтому мои ресурсы полны. Спасибо :) –

+1

@ TomášZato: Размер окна выходит за рамки OpenGL. Вероятно, вы используете фреймворк, такой как GLFW, GLUT или SDL (в учебнике, который вы связали, используется GLUT). glutGet (GLUT_WINDOW_WIDTH) и glutGet (GLUT_WINDOW_HEIGHT) - это то, что вы ищете. – datenwolf

1

Интересная часть:

glMatrixMode(GL_PROJECTION); 
glLoadIdentity(); 
double w = glutGet(GLUT_WINDOW_WIDTH)/300.0; 
double h = glutGet(GLUT_WINDOW_HEIGHT)/300.0; 
glOrtho(-1 * w, 1 * w, -1 * h, 1 * h, 10, -10); 

glMatrixMode(GL_MODELVIEW); 
glLoadIdentity(); 

В контексте:

#include <GL/glut.h> 

void display(); 
void specialKeys(); 

double rotate_y=0; 
double rotate_x=0; 

void display(){ 
    // Clear screen and Z-buffer 
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 

    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    double w = glutGet(GLUT_WINDOW_WIDTH)/300.0; 
    double h = glutGet(GLUT_WINDOW_HEIGHT)/300.0; 
    glOrtho(-1 * w, 1 * w, -1 * h, 1 * h, 10, -10); 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 

    // Rotate when user changes rotate_x and rotate_y 
    glRotatef(rotate_x, 1.0, 0.0, 0.0); 
    glRotatef(rotate_y, 0.0, 1.0, 0.0); 

    //Multi-colored side - FRONT 
    glBegin(GL_POLYGON); 

    glColor3f(1.0, 0.0, 0.0);  glVertex3f( 0.5, -0.5, -0.5);  // P1 is red 
    glColor3f(0.0, 1.0, 0.0);  glVertex3f( 0.5, 0.5, -0.5);  // P2 is green 
    glColor3f(0.0, 0.0, 1.0);  glVertex3f(-0.5, 0.5, -0.5);  // P3 is blue 
    glColor3f(1.0, 0.0, 1.0);  glVertex3f(-0.5, -0.5, -0.5);  // P4 is purple 

    glEnd(); 

    // White side - BACK 
    glBegin(GL_POLYGON); 
    glColor3f( 1.0, 1.0, 1.0); 
    glVertex3f( 0.5, -0.5, 0.5); 
    glVertex3f( 0.5, 0.5, 0.5); 
    glVertex3f(-0.5, 0.5, 0.5); 
    glVertex3f(-0.5, -0.5, 0.5); 
    glEnd(); 

    // Purple side - RIGHT 
    glBegin(GL_POLYGON); 
    glColor3f( 1.0, 0.0, 1.0); 
    glVertex3f(0.5, -0.5, -0.5); 
    glVertex3f(0.5, 0.5, -0.5); 
    glVertex3f(0.5, 0.5, 0.5); 
    glVertex3f(0.5, -0.5, 0.5); 
    glEnd(); 

    // Green side - LEFT 
    glBegin(GL_POLYGON); 
    glColor3f( 0.0, 1.0, 0.0); 
    glVertex3f(-0.5, -0.5, 0.5); 
    glVertex3f(-0.5, 0.5, 0.5); 
    glVertex3f(-0.5, 0.5, -0.5); 
    glVertex3f(-0.5, -0.5, -0.5); 
    glEnd(); 

    // Blue side - TOP 
    glBegin(GL_POLYGON); 
    glColor3f( 0.0, 0.0, 1.0); 
    glVertex3f( 0.5, 0.5, 0.5); 
    glVertex3f( 0.5, 0.5, -0.5); 
    glVertex3f(-0.5, 0.5, -0.5); 
    glVertex3f(-0.5, 0.5, 0.5); 
    glEnd(); 

    // Red side - BOTTOM 
    glBegin(GL_POLYGON); 
    glColor3f( 1.0, 0.0, 0.0); 
    glVertex3f( 0.5, -0.5, -0.5); 
    glVertex3f( 0.5, -0.5, 0.5); 
    glVertex3f(-0.5, -0.5, 0.5); 
    glVertex3f(-0.5, -0.5, -0.5); 
    glEnd(); 

    glFlush(); 
    glutSwapBuffers(); 
} 

void specialKeys(int key, int x, int y) { 
    // Right arrow - increase rotation by 5 degree 
    if (key == GLUT_KEY_RIGHT) 
    rotate_y += 5; 

    // Left arrow - decrease rotation by 5 degree 
    else if (key == GLUT_KEY_LEFT) 
    rotate_y -= 5; 

    else if (key == GLUT_KEY_UP) 
    rotate_x += 5; 

    else if (key == GLUT_KEY_DOWN) 
    rotate_x -= 5; 

    // Request display update 
    glutPostRedisplay(); 
} 

int main(int argc, char* argv[]){ 
    // Initialize GLUT and process user parameters 
    glutInit(&argc,argv); 

    // Request double buffered true color window with Z-buffer 
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); 

    // Create window 
    glutCreateWindow("Awesome Cube"); 

    // Enable Z-buffer depth test 
    glEnable(GL_DEPTH_TEST); 

    // Callback functions 
    glutDisplayFunc(display); 
    glutSpecialFunc(specialKeys); 

    // Pass control to GLUT for events 
    glutMainLoop(); 

    // Return to OS 
    return 0; 
} 
+0

Спасибо! В этом коде есть много вдохновения :) Я постараюсь применить его. –

+0

Могу ли я спросить, почему glMatrixMode вызывается дважды? И почему размер окна делится на 300? –

+0

Однажды переключитесь на матрицу проекционных матриц и один раз переключитесь на стек модели. Вы технически могли бы справиться с одним [но вы действительно не должны этого делать] (http://sjbaker.org/steve/omniv/projection_abuse.html). GLUT по умолчанию использует окна размером 300x300 пикселей (и вы не переопределяли через 'glutInitWindowSize()'), поэтому я решил, что это тот размер, который вы хотели придерживаться. – genpfault