В прошлом посте я рассказал про создание OpenGl окна. Сегодня я расскажу , как туда поместить объект. Сначала создадим окно , как описано тут http://alexkutsan.blogspot.com/2012/04/opengl-qt.html .
Всё не так сложно.
Изменять я буду функцию paintGL(). В ней происходит отрисовка.Вызывается она всякий раз, когда окно перерисовывается. Мы нарисуем 8 угольник. Определим его вершины:
Да, мы можем заставить компьютер считать все эти косинусы и синусы, но зачем? Компьютер будет раскладывать в ряд каждое выражение. Лучше попросим любого 7-миклассника посчитать нам эти значения. Он нам с первого взгляда всё выведет (стыдно, да?)
Ближе к коду.
Немного описания.
Мы работаем уже в матричной модели. Изменяем ведь саму модель - glMatrixMode(GL_MODELVIEW);
Мы очищаем буфер цветов - glClear(GL_COLOR_BUFFER_BIT); , ведь у нас появляются здесь цвета( пока-что только белый)
Загружаем единичную матрицу - glLoadIdentity(); . Никаких трансформаций над матрицей мы не делаем, поэтому этот шаг не обязателен,но делать его принято. Попробуйте вставить
...
glRotated(30,0,0,1);
glBegin(GL_POLYGON);
...
Вы увидите, что матрица повернётся относительно единичной. Теперь уберите glLoadIdentity();. Видите? Матрица поворачивается всякий раз при перерисовке окна относительно прошлого её состояния. Это потому, что функция glRotated(30,0,0,1); не поворачивает объект, это мы с вами думаем, что она поворачивает объект. glRotated умножает текущую матрицу на матрицу поворота, параметры которой мы задаём.
Всё серо и грустно.
Давайте добавим радости - добавим цвета.
Перед каждой точкой будем задавать цвет функцией glColor3f. Её параметры - RGB (0.0f-1.0f);
Хочу, чтоб всё вертелось!
Когда мы смотрим на объект, мы смотрим на него сверху.
Для простоты , сейчас мы повертим его относительно оси Z.
Если вы посмотрите код выше, то увидите, что наш 6-угольник находился в плоскости Z на уровне - -1. Давайте это изменим, и поставим его на уровень 0. И воспользуемся функцией смещения glTranslated(0,0,-3); Тем самым, мы отведём от глаз шестиугольник на 3 шага.
Для того, чтоб повернуть этот шестиугольник , используется функция glRotatef. Она принимает 4 параметра:
angel - угол на который нужно повернуть объект.
x - поворачивать относительно Ох?
y - поворачивать относительно Оу?
z - поворачивать относительно Oz?
Давайте создадим private переменную int rot; И создадим public slot void update();
Внутри update напишем.
Теперь, давайте повертим наш шести угольник не только относительно Z, а ещё относительно X и Y. Для этого изменим glRotatef(rot,0,0,1); на glRotatef(rot,1,1,1);. Для большей наглядности нарисуем Оси координат. Создайте private функцию
Теперь изменим функцию paintGL вот так:
Итог получается вот такой:Всё не так сложно.
Изменять я буду функцию paintGL(). В ней происходит отрисовка.Вызывается она всякий раз, когда окно перерисовывается. Мы нарисуем 8 угольник. Определим его вершины:
Да, мы можем заставить компьютер считать все эти косинусы и синусы, но зачем? Компьютер будет раскладывать в ряд каждое выражение. Лучше попросим любого 7-миклассника посчитать нам эти значения. Он нам с первого взгляда всё выведет (стыдно, да?)
void SceneGL::paintGL(){ glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glBegin(GL_POLYGON); glVertex3f( 0.5f, 1.0f,0.0f); glVertex3f(1.0f,0.5f, 0.0f); glVertex3f( 1.0f,-0.5f,0.0f); glVertex3f(0.5f,-1.0f,0.0f); glVertex3f(-0.5f,-1.0f,0.0f); glVertex3f(-1.0f,-0.5f,0.0f); glVertex3f(-1.0f,0.5f,0.0f); glVertex3f(-0.5f,1.0f,0.0f); glEnd(); }
Немного описания.
Мы работаем уже в матричной модели. Изменяем ведь саму модель - glMatrixMode(GL_MODELVIEW);
Мы очищаем буфер цветов - glClear(GL_COLOR_BUFFER_BIT); , ведь у нас появляются здесь цвета( пока-что только белый)
Загружаем единичную матрицу - glLoadIdentity(); . Никаких трансформаций над матрицей мы не делаем, поэтому этот шаг не обязателен,но делать его принято. Попробуйте вставить
...
glRotated(30,0,0,1);
glBegin(GL_POLYGON);
...
Вы увидите, что матрица повернётся относительно единичной. Теперь уберите glLoadIdentity();. Видите? Матрица поворачивается всякий раз при перерисовке окна относительно прошлого её состояния. Это потому, что функция glRotated(30,0,0,1); не поворачивает объект, это мы с вами думаем, что она поворачивает объект. glRotated умножает текущую матрицу на матрицу поворота, параметры которой мы задаём.
Всё серо и грустно.
Давайте добавим радости - добавим цвета.
Перед каждой точкой будем задавать цвет функцией glColor3f. Её параметры - RGB (0.0f-1.0f);
glBegin(GL_POLYGON); glColor3f(1,0,0); glVertex3f( 0.5f, 1.0f,-1.0f); glColor3f(0,1,0); glVertex3f(1.0f,0.5f, -1.0f); glColor3f(0,0,1); glVertex3f( 1.0f,-0.5f,-1.0f); glColor3f(1,0,1); glVertex3f(0.5f,-1.0f,-1.0f); glColor3f(1,1,0); glVertex3f(-0.5f,-1.0f,-1.0f); glColor3f(1,1,1); glVertex3f(-1.0f,-0.5f,-1.0f); glColor3f(0.5,0.5,0.5); glVertex3f(-1.0f,0.5f,-1.0f); glColor3f(0,0.5,1); glVertex3f(-0.5f,1.0f,-1.0f); glEnd();
И результат:Хочу, чтоб всё вертелось!
Когда мы смотрим на объект, мы смотрим на него сверху.
Для простоты , сейчас мы повертим его относительно оси Z.
Если вы посмотрите код выше, то увидите, что наш 6-угольник находился в плоскости Z на уровне - -1. Давайте это изменим, и поставим его на уровень 0. И воспользуемся функцией смещения glTranslated(0,0,-3); Тем самым, мы отведём от глаз шестиугольник на 3 шага.
Для того, чтоб повернуть этот шестиугольник , используется функция glRotatef. Она принимает 4 параметра:
angel - угол на который нужно повернуть объект.
x - поворачивать относительно Ох?
y - поворачивать относительно Оу?
z - поворачивать относительно Oz?
Давайте создадим private переменную int rot; И создадим public slot void update();
Внутри update напишем.
void SceneGL::update() { rot++; updateGL(); }Теперь, изменим код initializeGL
void SceneGL::initializeGL(){ glClearColor(0.0f,0.0f,0.0f,1.0f); glEnable(GL_DEPTH_TEST); QTimer *timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(update())); timer->start(10); }Как видите, мы запускаем таймер, и через каждые 10 миллисекунд будет выполняться update(), тем самым увеличивая переменную rot и перерисовывая сцену. Стоит изменить функцию paintGL
void SceneGL::paintGL(){ glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslated(0,0,-4); glRotatef(rot,0,0,1); ...После загрузки единичной матрицы я поворачиваю сцену на rot градусов, а rot постоянно меняется таймером. Запускайте, любуйтесь.
Теперь, давайте повертим наш шести угольник не только относительно Z, а ещё относительно X и Y. Для этого изменим glRotatef(rot,0,0,1); на glRotatef(rot,1,1,1);. Для большей наглядности нарисуем Оси координат. Создайте private функцию
void SceneGL::drawAxis() { glLineWidth(3.0f); // до вызова команды ширина равна 9 пикселю по умолчанию // устанавливаем цвет последующих примитивов glColor4f(1.00f, 0.00f, 0.00f, 1.0f); // ось x кvoid Scene3D::drawAxis() { glLineWidth(3.0f); // до вызова команды ширина равна 9 пикселю по умолчанию // устанавливаем цвет последующих примитивов glColor4f(1.00f, 0.00f, 0.00f, 1.0f); // ось x красного цвета glBegin(GL_LINES); // построение линии glVertex3f( 9.0f, 0.0f, 0.0f); // первая точка glVertex3f(-9.0f, 0.0f, 0.0f); // вторая точка glEnd(); QColor halfGreen(0, 128, 0, 255); qglColor(halfGreen); glBegin(GL_LINES); // ось y зеленого цвета glVertex3f( 0.0f, 9.0f, 0.0f); glVertex3f( 0.0f, -9.0f, 0.0f); glColor4f(0.00f, 0.00f, 1.00f, 9.0f); // ось z синего цвета glVertex3f( 0.0f, 0.0f, 9.0f); glVertex3f( 0.0f, 0.0f, -9.0f); glEnd(); } }
Теперь изменим функцию paintGL вот так:
... glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslated(0,0,-4); glRotatef(30,1,1,0); drawAxis(); glRotatef(rot,1,1,1); ...и функцию initializeGL
void SceneGL::initializeGL(){ glClearColor(0.0f,0.0f,0.0f,1.0f); glEnable(GL_DEPTH_TEST); QTimer *timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(update())); timer->start(10); }Обратите внимание на glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); и glEnable(GL_DEPTH_TEST);. Я включил тест глубины, если его не включить, то openGl не будет учитывать дальность объектов. Виден будет объект, которые нарисуется первым. С включённым тестом глубины будет виден тот объект, который ближе к наблюдателю(к нам). Ещё я поместил сюда второй glRotatef, который поворачивает сцену на 30 градусов по X и Y - это даст нам удобный угол просмотра. После этого я рисую оси и поворачиваю сцену на rot градусов по всем осям, и рисую 6-угольник. Благодоря этой последовательности прорисовки, оси у меня остаются всегда в 30 градусах, а объект крутится.
В следующий раз я расскажу как сделать управляемую сцену, чтоб мы в ней могли перемещаться динамически. Ещё я хочу рассказать, как с помощью примитивов нарисовать сферу. На сегодня всё.Спасибо всем, кто это прочёл. Исходники можно получить здесь : Arctors.zip
По-моему, это ВОСЬМИугольник, не?
ОтветитьУдалитьВы абсолютно правы :-) Моя оплошность.
УдалитьПерезалейте исходники, пожалуйста
ОтветитьУдалитьВот так сюрприз, дропбокс решил, что ему больше незачем хранить мои файлы.
УдалитьИзвиняйте за ненадёжные сервисы. На днях перезалью в другое место.
закиньте пожалуйста, исходники!
ОтветитьУдалитьЭтот комментарий был удален автором.
ОтветитьУдалитьна виндовсе почему-то мерцает картинка, перерисовывается многоугольник не всегда полностью
ОтветитьУдалить