В прошлом посте я рассказал про создание 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();
}
Теперь, изменим код initializeGLvoid 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 и перерисовывая сцену. Стоит изменить функцию paintGLvoid 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




По-моему, это ВОСЬМИугольник, не?
ОтветитьУдалитьВы абсолютно правы :-) Моя оплошность.
УдалитьПерезалейте исходники, пожалуйста
ОтветитьУдалитьВот так сюрприз, дропбокс решил, что ему больше незачем хранить мои файлы.
УдалитьИзвиняйте за ненадёжные сервисы. На днях перезалью в другое место.
закиньте пожалуйста, исходники!
ОтветитьУдалитьЭтот комментарий был удален автором.
ОтветитьУдалитьна виндовсе почему-то мерцает картинка, перерисовывается многоугольник не всегда полностью
ОтветитьУдалить