Прошу прощения, но ваш код разбит на несколько уровней.Позвольте мне объяснить это для вас:
#include "GAME.h"
using namespace std;
GAME::GAME()
{
glfwInit();
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_NORMALIZE);
}
Здесь кроется первая ошибка: GLFW - это библиотека C, и ее нужно инициализировать точно один раз .Вызов glfwInit()
принадлежит основной функции, а не конструктору класса.Другие вызовы функций - это вызовы OpenGL, однако они требуют активного контекста OpenGL.Однако в этой точке программы нет контекста OpenGL, поэтому все вызовы, которые вы выполняете, вообще не действуют.
int GAME::execute()
{
glfwOpenWindow(640, 320, 16, 16, 16, 16, 16, 16, GLFW_WINDOW);
glfwSetWindowTitle("Viraj");
glClearColor(1.0, 1.0, 1.0, 1.0);
Опять же, природа GLFW не согласуется с использованием в качестве части класса.Вы можете иметь только одно окно в GLFW и только один цикл обработки событий.Это не очень хорошо отображается на классы и объекты.Конечно, у вас может быть класс EventLoop
или аналогичный, но вы не будете использовать его таким образом.
А затем есть следующая строка, я удивляюсь, что она фактически скомпилирована:
glfwSetKeyCallback(events);
events
если функция-член класса GAME
, и если это не статическая функция-член, вы не можете использовать функцию-член класса в качестве обратного вызова, особенно если это не библиотека C, которая не знает классов,Откуда ему знать, к какому экземпляру относится эта функция события?В C ++ отсутствует концепция замыканий или делегатов , которая требовалась для этого (другие языки делают именно по этой причине).
running = true;
while(glfwGetWindowParam(GLFW_OPENED))
{
glfwPollEvents();
loop();
render();
}
return 0;
}
ЧтоТеперь пришло классическое заблуждение новичка:
void GAME::events(int key, int action)
{
switch(key)
{
case GLFW_KEY_UP:
glRotatef(10, 1, 0, 0);
break;
case GLFW_KEY_DOWN:
glRotatef(-10, 1, 0, 0);
break;
case GLFW_KEY_RIGHT:
glRotatef(10, 0, 1, 0);
break;
case GLFW_KEY_LEFT:
glRotatef(-10, 0, 1, 0);
break;
}
}
Вызовы манипуляций с матрицей имеют смысл только в коде чертежа.Вызов glRotate здесь будет просто мешать со стеком матриц, но каждая нормальная функция рендеринга OpenGL будет инициализировать все состояния, поэтому некоторые нормальные значения в начале.
То, что вы хотите сделать в обработчике событий, накапливает весь ввод в переменные, который вы позже используете в коде чертежа для настройки и управления рендерингом.
int GAME::loop()
{
return 0;
}
Если это предназначено для цикла, почему нет цикла?
int GAME::render()
{
int win_width;
int win_height;
glfwGetWindowSize(&win_width, &win_height);
const float win_aspect = (float)win_width / (float)win_height;
Отсутствует только одна деталь: Вы должны установить область просмотра здесь.Ничего страшного: glViewport(0, 0, win_width, win_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//glOrtho(-win_aspect, win_aspect, -1., 1., -1., 1.);
gluPerspective(90, win_aspect, 1, 100.0);
Теперь это действительно хорошо! Вы настраиваете матрицу проекции в функции рендеринга.Вперед, придерживайтесь этого шаблона!
ОБНОВЛЕНИЕ Однако следующая строка неверна:
gluLookAt(0, 0, 3.0, 0, 0, 0, 0.0, 1.0, 0.0);
gluLookAt
- это функция, предназначенная для выполнения на модель просмотра матрица.Матрица вида модели отвечает как за размещение моделей в мировом пространстве, так и за выравнивание мира с видом, поэтому преобразование составляет model→world, world→view
, из которого вы можете уменьшить промежуточный шаг world
, чтобы он составлял только model→view
.
glMatrixMode(GL_MODELVIEW);
Здесь вы бы назвали glLoadIdentity(); gluLookAt(...);
.Теперь должно стать очевидным, почему делать манипуляции с матрицами в обработчиках событий не имеет смысла.
На самом деле вы должны установить матрицу просмотра модели со всеми преобразованиями, выполняемыми здесь с нуля.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Этонемного необычно вызывать glClear
после настройки матриц, окна просмотра и т. д., но не ошибается.Вы можете оставить это так.
Однако, прежде чем начать рендеринг, вы должны должны установить все необходимые состояния OpenGL.Помните те «инициализирующие» вызовы OpenGL в конструкторе.Они принадлежат здесь .
glBegin(GL_QUADS);
glColor3f(0.0f, 0.0f, 0.0f);
//Front
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(1.0, 0.0, 0.0);
glVertex3f(1.0, 1.0, 0.0);
glVertex3f(0.0, 1.0, 0.0);
glColor3f(1.0f, 0.0f, 0.0f);
//Left
glVertex3f(1.0, 0.0, 0.0);
glVertex3f(1.0, 0.0, -1.0);
glVertex3f(1.0, 1.0, -1.0);
glVertex3f(1.0, 1.0, 0.0);
glColor3f(0.0f, 1.0f, 0.0f);
//Back
glVertex3f(1.0, 0.0, -1.0);
glVertex3f(1.0, 1.0, -1.0);
glVertex3f(0.0, 1.0, -1.0);
glVertex3f(0.0, 0.0, -1.0);
glColor3f(0.0f, 0.0f, 1.0f);
//Right
glVertex3f(0.0, 0.0, -1.0);
glVertex3f(0.0, 1.0, -1.0);
glVertex3f(0.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glColor3f(1.0f, 0.0f, 1.0f);
//Top
glVertex3f(0.0, 0.0, -0.0);
glVertex3f(0.0, 0.0, -1.0);
glVertex3f(1.0, 0.0, -1.0);
glVertex3f(1.0, 0.0, 0.0);
glColor3f(1.0f, 1.0f, 0.0f);
//Bottom
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(1.0, 0.0, 0.0);
glVertex3f(1.0, 0.0, -1.0);
glVertex3f(0.0, 0.0, -1.0);
glEnd();
Если вы хотите освещение, вам нужно обеспечить нормальные значения.Но я не стал бы добавлять туда большую группу вызовов glNormal
: Немедленный режим (glBegin, glEnd) устарел, я настоятельно рекомендую вам ознакомиться с массивами вершин и объектами буферов вершин.
glfwSwapBuffers();
return 0;
}
Подведение итогов: уберите звонки GLFW из класса.GLFW не является объектно-ориентированным.Просто используйте его глобально из функции main
.Передача событий в классы в порядке, но вы не можете использовать функции-члены класса в качестве обратных вызовов для GLFW.Вам нужно написать некоторую вспомогательную функцию
extern GAME *pGame;
void eventhandler(int key, int action)
{
pGame->event(key, action);
}
. Также вы можете иметь класс GAME
для управления статическим списком всех экземпляров и обеспечения статической функции-члена, которая передает событие всем экземплярам в списке.Или используйте синглтон (однако я думаю, что синглтоны - это анти-паттерн, и его следует избегать).