2013-09-13 7 views
0

Я пытаюсь отобразить сферу в OpenGL. К сожалению, на экране всегда появляется только фон. Я пробовал переориентировать камеру безрезультатно (хотя я могу ошибаться). Любое понимание было бы оценено.Форма OpenGL не отображается

Вот функция OpenGL требует обновления экрана:

//The draw function - I have confirmed that this is called periodically. 
void draw() 
{ 
    glClearColor(1.0f, 0.0f, 0.0f, 1.0f); 
    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 
    glEnable(GL_CULL_FACE); 
    glPolygonMode(GL_FRONT_AND_BACK, (globals.wireframe == true) ? GL_LINE : GL_FILL); 

    glViewport(0, 0, globals.window_size.x, globals.window_size.y); 

    mat4 prj = perspective(globals.fov, float(globals.window_size.x)/float(globals.window_size.y), globals.hither, globals.yon); 
    glMatrixMode(GL_PROJECTION); 
    glLoadMatrixf(value_ptr(prj)); 

    glMatrixMode(GL_MODELVIEW); 
    mat4 context = mat4(1.0f); 
    globals.ship.draw(context); //the ship only draws a sphere for now 
    mat4 mv = lookAt(vec3(0.0f, 0.0f, -5.5f), vec3(0.0f, 0.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f)); 
    glLoadMatrixf(value_ptr(mv)); 

    glutSwapBuffers(); 
} 

и определение корабля:

GLuint Ship::sphere_handle; //static 
bool Ship::is_initialized; //static 

mat4 Ship::draw(mat4 context) const { 
    glLoadMatrixf(value_ptr(context)); 
    glCallList(sphere_handle); 
    return context; 
} 

//called when program starts, after window created 
bool Ship::initialize() { 
    if (sphere_handle == BAD_GL_VALUE) 
    { 
     GLUquadric *q = gluNewQuadric(); 
     if (q != NULL) 
     { 
      if ((sphere_handle = glGenLists(1)) == 0) 
      { 
       cout << "Model::Initialize() - Failed to GenLists()" << endl; 
       return false; 
      } 
      glNewList(sphere_handle, GL_COMPILE); 
      gluSphere(q, 1.0, 10, 10); 
      glEndList(); 
      gluDeleteQuadric(q); 
      is_initialized = true; 
     } 
     else 
     { 
      return false; 
     } 
    } 
    return true; 
} 
+0

Вы плакат-мальчик для избыточных изменений состояния. :) – thokra

ответ

2

Основная проблема заключается здесь:

glMatrixMode(GL_MODELVIEW); 
mat4 context = mat4(1.0f); 
globals.ship.draw(context); //the ship only draws a sphere for now 
mat4 mv = lookAt(vec3(0.0f, 0.0f, -5.5f), vec3(0.0f, 0.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f)); 
glLoadMatrixf(value_ptr(mv)); 

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

Добавьте к этому, что glLoadMatrix просто заменяет все, что находится на стеке матриц прямо сейчас. Поэтому, когда вы последовательно загружаете несколько преобразований, они не будут объединяться. На самом деле здорово, что вы пытаетесь не полагаться на математические функции матрицы OpenGL (они устарели и удалены из более поздних версий OpenGL). Итак, как это изменить? Вы должны создать составную матрицу просмотра модели. Поэтому замените вышеуказанный:

mat4 view = lookAt(
    vec3(0.0f, 0.0f, -5.5f), 
    vec3(0.0f, 0.0f, 0.0f), 
    vec3(0.0f, 1.0f, 0.0f)); 
globals.ship.draw(view); 

Момент, где идет матричный режим и загрузка матрицы? Вдали они нам не нужны. Но вы должны слегка настроить код рисования вашего судна.

void Ship::draw(mat4 view) const { 

    /* transform depending on your ships location and orientation */ 
    mat4 model = …; 

    /* order of operations matters. OpenGL uses column major indexing 
    * hence matrix multiplication is right associative, i.e. column 
    * vectors (like vertex positions) enter on the right and "go" 
    * through the compound toward the left. 
    * Since model is the first transformation to apply, and view 
    * after the multiplication for the whole compound transform is */ 
    mat4 mv = view * model; 

    glLoadMatrixf(value_ptr(mv)); 

Так вы пошли на большие длины, чтобы избежать использования старой и запыленные OpenGL матрицы математических функций (который является большим); вам просто нужно заменить все звонки glLoadMatrix звонками glUniform в современном, основанном на шейдере подходе.

glCallList(sphere_handle); 
} 

Но почему вы используете здесь отображаемые здесь списки с таким старым-этим-разлагающимся списком? * Yuck * Они также недоступны в современном OpenGL, но не могут быть так же тривиально перенесены, как с вашим матричным кодом.

Используйте массив вершин здесь.

+0

+1: равноценный ответ. – thokra

2

От первого до всегда проверить, есть ли любые ошибки GL! Если да, найдите причину и исправьте ее.

Кроме этого, я вижу то, что, похоже, связано с неправильным пониманием того, как работает матричная манипуляция в устаревшем GL, или вы не писали то, что вы намеревались написать. В вашей draw() функции вы:

glMatrixMode(GL_MODELVIEW); 
mat4 context = mat4(1.0f); 
globals.ship.draw(context); //the ship only draws a sphere for now 
mat4 mv = lookAt(vec3(0.0f, 0.0f, -5.5f), vec3(0.0f, 0.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f)); 
glLoadMatrixf(value_ptr(mv)); 

На третьей строке вы называете

mat4 Ship::draw(mat4 context) const 
{ 
    glLoadMatrixf(value_ptr(context)); 
    glCallList(sphere_handle); 
    return context; 
} 

заряжаются идентичность на вершине MODELVIEW стека, а затем вызвать glCallList. На данный момент нет перевода, т. Е. Концептуально ваша камера находится прямо внутри области единиц измерения. Из-за отбраковки задней поверхности вы ничего не увидите. То, что вы на самом деле хотите, - это перевести сферу назад 5.5 единиц, так что вы ищете вниз -Z с прямыми, непосредственно в центре шара:

glMatrixMode(GL_MODELVIEW); 
// load the view matrix FIRST! 
mat4 mv = lookAt(vec3(0.0f, 0.0f, -5.5f), vec3(0.0f, 0.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f)); 
glLoadMatrixf(value_ptr(mv)); 
// draw the model with an indentity model-matrix - mind the changes to the function below!! 
glPushMatrix(); // you don't want to mess up the view matrix for good 
globals.ship.draw(mat4(1.0f)); 
glPopMatrix(); 

Перегруппировка вызовы не будут резать. Ship::draw() также необходимо будет изменить. Во-первых, вы можете улучшить функцию с точки зрения дизайна: не принимать матрицу по значению, принимать ее по ссылке const, поскольку функция draw не имеет и не должна изменять модель-матрицу вообще. Во-вторых, вам нужно применить правильное умножение матриц, если вы планируете использовать не-indentity model-matrices в какой-то момент. Почему функция должна возвращать копию модели-матрицы, в которую вы проходили, я откровенно не могу понять. :) Мое предложение переписать его следующим образом:

void Ship::draw(const mat4& context) const 
{ 
    glMultMatrixf(value_ptr(context)); 
    glCallList(sphere_handle); 
} 

После этого, есть еще одна вещь, чтобы сделать. Вы переводите сферу на 5,5 единиц вдоль + Z (т. Е. Вы устанавливаете точку зрения вашей камеры на (0, 0, -5,5)). Поскольку вы не вращаете сферу, нет возможности, чтобы камера оказалась видимой после проецирования и будет полностью обрезана. То, что вы, вероятно, хотели, - установить точку наблюдения (0, 0, 5.5).

На другой ноте, вы понесете ненужные накладные расходы в различных местах в вашей функции рисования:

glClearColor(1.0f, 0.0f, 0.0f, 1.0f); 

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

Так является

glEnable(GL_CULL_FACE); 
glPolygonMode(GL_FRONT_AND_BACK, (globals.wireframe == true) ? GL_LINE : GL_FILL); 

Для изменения видового экрана, рамки оконных как Qt или FreeGLUT обеспечивают особый функцию обратного вызов для изменения размера. Поместите туда функцию и обновите свою проекцию там (так как изменение размеров часто приводит к изменению соотношения сторон).

РЕДАКТИРОВАТЬ: Пожалуйста, обратите внимание на замечание датенольфа и отойти от наследия GL. Если вы уже используете GLM, вы уже на один шаг ближе к современному OpenGL. :)

Ознакомьтесь с tutorial и нашим wiki на OpenGL.org, чтобы получить обширную коллекцию информации о современном OpenGL.

EDIT2: Исправлен недостающий толчок/поп-логика.

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