Russian Qt Forum
Ноябрь 23, 2024, 15:52 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Пошаговая инструкция введения в OpenGL на Qt  (Прочитано 20974 раз)
8Observer8
Гость
« : Сентябрь 15, 2014, 08:45 »

Добавил 1/8/2015 Мои видео-уроки: 001 Qt C++ OpenGL GLSL Рисуем треугольник

Привет!

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

Инструкция
- Установка Qt
- Переключение Qt Creator'a на английский
- Создание нового проекта
- Скопируем код заготовки в Scene.h и Scene.cpp (см. ниже)
- Запускаем приложение. Мы видим падающий вниз квадрат, который мы можем перемещать влево и вправо

Scene.h
Код
C++ (Qt)
#ifndef SCENE_H
#define SCENE_H
 
#include <QGLWidget>
#include <QTimer>
#include <QKeyEvent>
 
class Scene : public QGLWidget
{
   Q_OBJECT
 
public:
   Scene( QWidget *parent = 0 );
 
private slots:
   void slotMove();
 
private:
   void initializeGL();
   void paintGL();
   void resizeGL( int w, int h );
 
   void keyPressEvent( QKeyEvent * event );
 
private:
   // Square position and size
   int x;
   int y;
   const int rsize;
 
   // Step size in x and y directions
   // (number of pixels to move each time)
   int xstep;
   int ystep;
 
   // Keep track of windows changing width and height
   GLfloat windowWidth;
   GLfloat windowHeight;
 
   // Timer
   QTimer *timer;
};
 
#endif // SCENE_H
 

Scene.cpp
Код
C++ (Qt)
 
#include "Scene.h"
 
Scene::Scene( QWidget *parent ) :
   QGLWidget( parent ),
   x( 0 ),
   y( 100 ),
   rsize( 25 ),
   xstep( 25 ),
   ystep( 1 )
{
   timer = new QTimer( this );
   connect( timer, SIGNAL( timeout() ),
            this, SLOT( slotMove() ) );
   timer->start( 33 );
 
   this->setFocusPolicy( Qt::StrongFocus );
}
 
void Scene::slotMove()
{
   y -= ystep;
 
   updateGL();
}
 
void Scene::initializeGL()
{
   glClearColor( 0.8f, 0.8f, 0.6f, 1.0f );
}
 
void Scene::paintGL()
{
   // Clear the window with current clearing color
   glClear( GL_COLOR_BUFFER_BIT );
 
   // Set current drawing color
   glColor3f( 0.0f, 0.5f, 0.5f );
 
   // Draw a filled rectangle with current color
   glRectf( x, y, x + rsize, y - rsize );
}
 
void Scene::resizeGL( int w, int h )
{
   // Prevent a divide by zero
   if ( h == 0 ) {
       h = 1;
   }
 
   // Set Viewport to window dimensions
   glViewport( 0, 0, w, h );
 
   // Reset coordinate system
   glMatrixMode( GL_PROJECTION );
   glLoadIdentity();
 
   // Establish clipping volume (left, right, bottom, top, near, far)
   GLfloat aspectRatio = ( GLfloat ) w / ( GLfloat ) h;
 
   if ( w <= h ) {
       windowWidth = 100.0f;
       windowHeight = 100.0f / aspectRatio;
       glOrtho( -100.0, 100.0, -windowHeight, windowHeight,
                1.0, -1.0 );
   } else {
       windowWidth = 100.0 * aspectRatio;
       windowHeight = 100.0;
       glOrtho( -windowWidth, windowWidth, -100.0, 100.0,
                1.0, -1.0 );
   }
 
   glMatrixMode( GL_MODELVIEW );
   glLoadIdentity();
}
 
void Scene::keyPressEvent( QKeyEvent *event )
{
   switch( event->key() ) {
   case Qt::Key_Left:
       x -= xstep;
       break;
   case Qt::Key_Right:
       x += xstep;
       break;
   }
}
 

Краткие объяснения основных моментов

Примечание. Начало координат находится в середине окна.

- paintGL() - выполняется автоматически, когда приложению надо перерисовать окно. К примеру, если мы свернём окно и развернём, то тело этой функции выполнится. Или если перекроем наше окно каким-то другим. Или изменим размер нашего окна. В этой функции мы рисуем квадрат с помощью такой функции:

Код
C++ (Qt)
glRectf( x, y, x + rsize, y - rsize );
 

Здесь:
x - глобальная переменная, которая хранит x-координату левого верхнего угла прямоугольника
y - глобальная переменная, которая хранит y-координату левого верхнего угла прямоугольника
rsize - глобальная константа, которая хранит размер стороны квадрата
(x + rsize) - x-координата правого нижнего угла квадрата
(y - rsize) - y-координата правого нижнего угла квадрата

- slotMove() - выполняется примерно 30 раз в секунду. Главное, чтобы было больше, чем 24 кадра в секунду. В этой функции мы меняем координаты квадрата (глобальные переменные x и y) и вызываем updateGL(), чтобы спровоцировать вызов paintGL() и тем самым перерисовать квадрат с новыми координатами

- keyPressEvent - вызывается при нажатии любой клавиши. В заготовке мы используем только стрелки: "влево" и "вправо". При нажатии кнопки "влево" нам надо уменьшить координату x, а если переместить вправо, то увеличить y

- "Почему квадрат падает?" Потому что каждые "30 раз в секунду" вызывается функция slotMove() и уменьшает глобальную переменную y, которая хранит y-координату нашего квадрата

- windowWidth и windowHeight - глобальные переменные, которые хранят актуальные размеры клиентской области (области, в которой мы рисуем)

- glClearColor( 0.3f, 0.3f, 1.0f, 1.0f ) - с помощью этой функции мы задаём цвет фона. Первые три параметра - это соответственно: красный, зелёный, синий. Их можно менять в диапазоне [0.0, 1.0]. Четвёрный параметр нам не нужен, поэтому мы его выставляем в значение поумолчанию - в единицу

- glColor3f( 0.0f, 0.5f, 0.5f ); - с помощью этой функции мы задаём цвет нашего квадрата. Здесь так же: красный, зелёный, синий

- resizeGL() - не обращайте внимания на содержимое этой функции. Просто не трогайте её.

Продолжение: http://www.prog.org.ru/topic_27563_0.html

Литература:
- OpenGL Суперкнига (диск к книге)
- Beginning OpenGL Game Programming, 2nd edition, 2009 (book+code)

P.S. Эта же тема под другим ракурсом:
- http://www.gamedev.ru/code/forum/?id=193241
- http://programmersforum.ru/showthread.php?t=265504
« Последнее редактирование: Январь 08, 2015, 14:09 от 8Observer8 » Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #1 : Сентябрь 15, 2014, 13:17 »

лови симпу!

на геймдеве хорошие, годные комментарии.
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Сентябрь 16, 2014, 07:28 »

- glColor3f( 0.0f, 0.5f, 0.5f ); - с помощью этой функции мы задаём цвет нашего квадрата. Здесь так же: красный, зелёный, синий
Не надо "прикрываться начинающими". Если человек по имени ф-ции не понял что она примерно делает и нуждается в таких разжевываниях как Ваши - значит он полный идиот, и попытки его обучения есть бесполезная трата времени.

Подача такого материала на достаточно профессиональный форум никакой смысловой нагрузки не несет и воспринимается как навязчивая самореклама. Это раздражает. Хотите - пишите, но когда в след раз на Вас кто-то сорвется помните - Вы это 100% заслужили.
 
Записан
Bepec
Гость
« Ответ #3 : Сентябрь 16, 2014, 10:19 »

А давайте введём минусы и заминусуем Igors Улыбающийся
Такие пояснения естественны И. И они нивелируют разницу между "профессионалом" и "новичком". Если они вам не нужны - пропускайте.

А так похоже на возгордившегося "профессионала". Я де много раз так делал, всё знаю. Пусть кто хочет, тот найдет описание функции - изучит его.  Такая точка зрения создаёт не руководства, а извращённое их подобие - когда вместо "прочитал и сделал" получается "прочитал, нашёл все описания функций, изучил их, изучил паттерн используемый в примере и ... бросил это дело, потому что писавший - *****" Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Сентябрь 16, 2014, 10:56 »

получается "прочитал, нашёл все описания функций, изучил их,
Да, так всегда было и будет, и усердное переписывание документации "в популярной форме" никак не помогает начинающему, только вредит. Чтение букваря никто не отменял и чем раньше новичок начнет - тем лучше. 
Записан
Bepec
Гость
« Ответ #5 : Сентябрь 16, 2014, 11:05 »

Ну тут уже современное образование напакостило.
Надо не забывать логическую цепочку.
Получить пример -> запустить пример -> по шагам разобрать работу примера -> модифицировать под свои нужды.
В случае подробной инструкции пропускается звено "по шагам разобрать работу примера", что уменьшает время до логического конца % на 80.

Если ваш девиз - обучаться. Тогда проходите всю цепочку.
Если же ваш девиз - использовать наработки других, вместо создания собственных велосипедов - то убираем шаг "по шагам разобрать работу примера".

PS дальше спорить бессмысленно. Своё мнение я выразил.
Записан
8Observer8
Гость
« Ответ #6 : Ноябрь 17, 2014, 17:15 »

Может кому пригодится: http://www.cyberforum.ru/blogs/416874/blog2944.html
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.135 секунд. Запросов: 23.