PSPinfo.RU > HomeBrew > Уроки программирования. Урок четвёртый!
Уроки программирования. Урок четвёртый!10.10.09. Разместил: .:Witcher:. |
В данном уроке мы научимся рисовать простые и 3d обьёкты средствами OpenGL на экране PSP. Найти прошлые уроки вы можете в поиске в строке указать программирование У вас уже должен стоять SDK, как это сделать описано тут Подготовка Создаём на рабочем столе или в любом удобном вам месте папку 'lessonsPSP'. Там создаём такие файлы с содержанием: Файл compile.bat make clean make pause Файл Makefile: TARGET = Lessons4 OBJS = main.o PSPPATH = $(shell psp-config --psp-prefix) CFLAGS = -O2 -G0 -Wall CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti ASFLAGS = $(CFLAGS) BUILD_PRX = 1 PSP_FW_VERSION=371 PSP_LARGE_MEMORY = 1 INCDIR = $(PSPPATH)/include/bolbol LIBS = -lglut -lGLU -lGL -lpspvfpu -lpspge -lpspsdk -lpspctrl -lpsprtc -lpsppower -lpspgum -lpspgu -lm -lstdc++ LDFLAGS += -DMODULE_NAME="OpenGL" psp-setup.cpp EXTRA_TARGETS = EBOOT.PBP PSP_EBOOT_TITLE = TEST OPENGL PSPSDK=$(shell psp-config --pspsdk-path) include $(PSPSDK)/lib/build.mak Файл psp-setup.cpp #include #include #if !defined(MODULE_NAME) #define MODULE_NAME NONAME #endif #if !defined(MODULE_VERSION_MAJOR) #define MODULE_VERSION_MAJOR 1 #endif #if !defined(MODULE_VERSION_MINOR) #define MODULE_VERSION_MINOR 0 #endif #if !defined(MODULE_ATTR) #define MODULE_ATTR 0 #endif #define _stringify(s) _tostring(s) #define _tostring(s) #s PSP_MODULE_INFO(_stringify(MODULE_NAME), 0, 1, 0); PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU); PSP_HEAP_SIZE_KB(12*1024); static int exit_callback (int arg1, int arg2, void *common) { sceKernelExitGame(); return 0; } static int update_thread (SceSize args, void *argp) { int cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL); sceKernelRegisterExitCallback(cbid); sceKernelSleepThreadCB(); return 0; } static void setup_callbacks (void) _attribute_(constructor); static void setup_callbacks (void) { int id; if (id = sceKernelCreateThread("update_thread", update_thread, 0x11, 0xFA0, 0, 0) >= 0) sceKernelStartThread(id, 0, 0); } static void back_to_kernel (void) _attribute_(destructor); static void back_to_kernel (void) { sceKernelExitGame(); } Подробно разбирать их работу не будем, и не надо, ЭТО БУДЕТ НАШ ШАБЛОН. Первый файл при запуске его компилирует проэкт Второй это настройка компиляции Третий это стандартные функции для PSP, их трогать не надо, мы вынесли их в отдельный файл что бы не писать каждый раз в новый проэкт. Эти файлы можно кинуть в отдельную папку, они нам будут нужны для каждого нового проэкта, и их редактировать не надо (кроме файла Makefile, но его пока что тоже, все нужные библиотеки я вынес) Создаём наш рабочий файлик main.cpp Его содержание: #include //нужна для выхода #include //математическая функция #include //Подключаем нужные библиотеки для работы с OpenGL #include //Библиотека GLUT #include //Библиотека GLU, которую мы будем использовать позже. //функция где мы указываем что выводит void Display(void) { glClear(GL_COLOR_BUFFER_BIT); //закрашиваем цвет //начало рисование обьекта glBegin(GL_LINES); //рисуем примитив- линию glColor3f(1,0,0); //цвет линии- черный glVertex2f(-1,0); //первая вершина glVertex2f(1,1); //вторая вершина glEnd(); //заканчиваем рисовать примитив //конец glutSwapBuffers(); glFlush(); //выводим изображение на экран } int main(int argc, char **argv) { glutInit(&argc,argv); //инициализация glutInitDisplayMode(GLUT_DOUBLE); //установка режима отображения glutInitWindowSize(480, 272); //размер окна glutInitWindowPosition(0,0); //позиция окна glutCreateWindow("lessons4"); //заглавие нашего окошка glClearColor(1,1,1,1); //заполняем белым цветом glutDisplayFunc(Display); //функция для рисования(она у нас выше) glutMainLoop(); //Обработчик событий return 1; //возращаем 1(пока что не важно) } Подробней описание функции Display чуть ниже. Режимы (функция glutDisplayFunc) GLUT_RGB — режим RGB (отображение цвета с помощью трех основных цветов — красного, зеленого и синего). Используется по умолчанию. GLUT_SINGLE — окно с одиночным буфером. Этот режим используется также по умолчанию. GLUT_DOUBLE — окно с двойным буфером (см. выше). GLUT_DEPTH — окно с буфером глубины (Z-buffer’ом), о котором тоже уже сказано. Запускаем наш батник, происходит компиляция. После кидаем файл EBOOT.PBP в папку X:/PSP/GAME/less4/ где X буква вашей psp И запускаем! Ура! Мы нарисовали линию) Но почему она на весь экран по оси Х растянулась?? Дело в том что наше поле с объектом масштабировать до размера самого объекта. Давайте дополним наш код, и добавим ему обработчик кнопок. Для этого после: glutDisplayFunc(Display); Вставляем: glutKeyboardFunc(keyPressed); glutKeyboardUpFunc(keyReleased); glutReshapeFunc(DisplayResize); Что это делает? Первая команда обращается к функции keyPressed в момент нажатия любой клавиши Команда glutKeyboardUpFunc по сути делает тоже самое, но обращается к функции keyReleased ПОСЛЕ нажатия любой клавиши. Последняя команда самая интересная - именно она будет задавать сетку и вычислять соотношения геометрических размеров для окна. Вот сами наши функции: GLvoid DisplayResize(GLsizei Width, GLsizei Height) { if (Height==0) // Предотвращение деления на ноль, если окно слишком мало Height=1; glViewport(0, 0, Width, Height); // Сброс текущей области вывода // и перспективных преобразований glMatrixMode(GL_PROJECTION); // Выбор матрицы проекций glLoadIdentity(); // Сброс матрицы проекции gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // Вычисление соотношения геометрических размеров для окна glMatrixMode(GL_MODELVIEW); // Выбор матрицы просмотра модели } /* обработчик нажатия кнопки. */ void keyPressed(unsigned char key, int x, int y) { switch (key) { case 'd': /* delta, triangle */ break; case 'o': /* round */ break; case 'q': /* square*/ break; case 'x': /* cross */ break; case 'n': /* key with the music note */ break; case 's': /* select */ break; case 'a': /* startbutton */ /* If START is pressed, kill everything. */ /* exit the program...normal termination. */ exit(0); default: ; } } /* обработчик на отпускание кнопки. */ void keyReleased(unsigned char key, int x, int y) { switch (key) { case 'd': /* delta, triangle */ break; case 'o': /* round */ break; case 'q': /* square*/ break; case 'x': /* cross */ break; case 'n': /* key with the music note */ break; case 's': /* select */ break; case 'a': /* startbutton */ break; default: ; } } Внимание! Стоить учесть что функцию вывода glFlush() можно убрать. Эти функции можно подробно и не разбирать, вроде всё понятно. Давайте разберём нашу функцию Display Первая строка думаю понятна. Далее идёт такой синтаксис: glBegin(тип); glVertex*(…); .... glVertex*(…); glEnd(); Где * может быть [2,3][i,d,f,b], в зависимости от количества точек и от типа чисел, которые мы будет использовать при задании точки. Например, если мы будем рисовать в двухмерном пространстве и при этом использовать тип double, тогда функция будет иметь вид glVertex2d(x,y). Я думаю, с этим все ясно. Список типов: •GL_POINTS — каждая вершина задает координаты некоторой точки. •GL_LINES — каждая отдельная пара вершин определяет отрезок; если задано нечетное число вершин, то последняя вершина игнорируется. •GL_LINE_STRIP — каждая следующая вершина задает отрезок вместе с предыдущей. •GL_LINE_LOOP — отличие от предыдущего примитива только в том, что последний отрезок определяется последней и первой вершиной, образуя замкнутую ломаную. •GL_TRIANGLES — каждая отдельная тройка вершин определяет треугольник; если задано некратное трем число вершин, то остаток игнорируется. •GL_TRIANGLE_STRIP — каждая следующая вершина задает треугольник вместе с двумя предыдущими. •GL_TRIANGLE_FAN — треугольники задаются первой и каждой следующей парой вершин (пары не пересекаются). •GL_QUADS — каждая отдельная четверка вершин определяет четырехугольник; если задано некратное четырем число вершин, то остаток игнорируется. •GL_POLYGON — последовательно задаются вершины выпуклого ----------------------------- Функция glVertex задаёт вершины к примеру: glVertex2d(-1,0); мы взяли вершину -1,0 glVertex2d(1,1); взяли 1,1 Эти вершины объеденились и получилась линия с точки -1,0 до 1,1. Вот мы подходим к завершению, давайте более сложный пример - нарисуем трёхмерный триугольник с квадратом. Синтаксис такой: #include // needed in order to have "exit" function @@@ #include #include //Подключаем нужные библиотеки для работы с OpenGL #include //Библиотека GLUT #include //Библиотека GLU, которую мы будем использовать позже. GLfloat rtri; // Угол для треугольник GLfloat rquad; // Угол для четырехугольника void Display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// Очистка экрана и буфера глубины glLoadIdentity(); /// Сбросить текущую матрицу glTranslatef(-1.5f,0.0f,-6.0f); // Сдвиг влево и вглубь экрана glRotatef(rtri,0.0f,1.0f,0.0f); // Вращение пирамиды по оси Y glBegin(GL_TRIANGLES); // Начало рисования пирамиды glColor3f(1.0f,0.0f,0.0f); // Красный glVertex3f( 0.0f, 1.0f, 0.0f); // Верх треугольника (Передняя) glColor3f(0.0f,1.0f,0.0f); // Зеленный glVertex3f(-1.0f,-1.0f, 1.0f); // Левая точка glColor3f(0.0f,0.0f,1.0f); // Синий glVertex3f( 1.0f,-1.0f, 1.0f); // Правая точка glColor3f(1.0f,0.0f,0.0f); // Красная glVertex3f( 0.0f, 1.0f, 0.0f); // Верх треугольника (Правая) glColor3f(0.0f,0.0f,1.0f); // Синия glVertex3f( 1.0f,-1.0f, 1.0f); // Лево треугольника (Правая) glColor3f(0.0f,1.0f,0.0f); // Зеленная glVertex3f( 1.0f,-1.0f, -1.0f); // Право треугольника (Правая) glColor3f(1.0f,0.0f,0.0f); // Красный glVertex3f( 0.0f, 1.0f, 0.0f); // Низ треугольника (Сзади) glColor3f(0.0f,1.0f,0.0f); // Зеленный glVertex3f( 1.0f,-1.0f, -1.0f); // Лево треугольника (Сзади) glColor3f(0.0f,0.0f,1.0f); // Синий glVertex3f(-1.0f,-1.0f, -1.0f); // Право треугольника (Сзади) glColor3f(1.0f,0.0f,0.0f); // Красный glVertex3f( 0.0f, 1.0f, 0.0f); // Верх треугольника (Лево) glColor3f(0.0f,0.0f,1.0f); // Синий glVertex3f(-1.0f,-1.0f,-1.0f); // Лево треугольника (Лево) glColor3f(0.0f,1.0f,0.0f); // Зеленный glVertex3f(-1.0f,-1.0f, 1.0f); // Право треугольника (Лево) glEnd(); glLoadIdentity(); glTranslatef(1.5f,0.0f,-7.0f); // Сдвинуть вправо и вглубь экрана glRotatef(rquad,1.0f,1.0f,1.0f); // Вращение куба по X, Y & Z glBegin(GL_QUADS); // Рисуем куб glColor3f(0.0f,1.0f,0.0f); // Синий glVertex3f( 1.0f, 1.0f,-1.0f); // Право верх квадрата (Верх) glVertex3f(-1.0f, 1.0f,-1.0f); // Лево верх glVertex3f(-1.0f, 1.0f, 1.0f); // Лево низ glVertex3f( 1.0f, 1.0f, 1.0f); // Право низ glColor3f(1.0f,0.5f,0.0f); // Оранжевый glVertex3f( 1.0f,-1.0f, 1.0f); // Верх право квадрата (Низ) glVertex3f(-1.0f,-1.0f, 1.0f); // Верх лево glVertex3f(-1.0f,-1.0f,-1.0f); // Низ лево glVertex3f( 1.0f,-1.0f,-1.0f); // Низ право glColor3f(1.0f,0.0f,0.0f); // Красный glVertex3f( 1.0f, 1.0f, 1.0f); // Верх право квадрата (Перед) glVertex3f(-1.0f, 1.0f, 1.0f); // Верх лево glVertex3f(-1.0f,-1.0f, 1.0f); // Низ лево glVertex3f( 1.0f,-1.0f, 1.0f); // Низ право glColor3f(1.0f,1.0f,0.0f); // Желтый glVertex3f( 1.0f,-1.0f,-1.0f); // Верх право квадрата (Зад) glVertex3f(-1.0f,-1.0f,-1.0f); // Верх лево glVertex3f(-1.0f, 1.0f,-1.0f); // Низ лево glVertex3f( 1.0f, 1.0f,-1.0f); // Низ право glColor3f(0.0f,0.0f,1.0f); // Синий glVertex3f(-1.0f, 1.0f, 1.0f); // Верх право квадрата (Лево) glVertex3f(-1.0f, 1.0f,-1.0f); // Верх лево glVertex3f(-1.0f,-1.0f,-1.0f); // Низ лево glVertex3f(-1.0f,-1.0f, 1.0f); // Низ право glColor3f(1.0f,0.0f,1.0f); // Фиолетовый glVertex3f( 1.0f, 1.0f,-1.0f); // Верх право квадрата (Право) glVertex3f( 1.0f, 1.0f, 1.0f); // Верх лево glVertex3f( 1.0f,-1.0f, 1.0f); // Низ лево glVertex3f( 1.0f,-1.0f,-1.0f); // Низ право glEnd(); // Закончили квадраты rtri+=0.2f; // Увеличим переменную вращения для треугольника rquad-=0.15f; // Уменьшим переменную вращения для квадрата glutSwapBuffers(); //glFlush(); //выводим изображение на экран . Как говорил не обязатильно } GLvoid DisplayResize(GLsizei Width, GLsizei Height) { if (Height==0) // Предотвращение деления на ноль, если окно слишком мало Height=1; glViewport(0, 0, Width, Height); // Сброс текущей области вывода // и перспективных преобразований glMatrixMode(GL_PROJECTION); // Выбор матрицы проекций glLoadIdentity(); // Сброс матрицы проекции gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // Вычисление соотношения геометрических размеров для окна glMatrixMode(GL_MODELVIEW); // Выбор матрицы просмотра модели } /* обработчик нажатия кнопки. */ void keyPressed(unsigned char key, int x, int y) { switch (key) { case 'd': /* delta, triangle */ break; case 'o': /* round */ break; case 'q': /* square*/ break; case 'x': /* cross */ break; case 'n': /* key with the music note */ break; case 's': /* select */ break; case 'a': /* startbutton */ /* If START is pressed, kill everything. */ /* exit the program...normal termination. */ exit(0); default: ; } } /* обработчик на отпускание кнопки. */ void keyReleased(unsigned char key, int x, int y) { switch (key) { case 'd': /* delta, triangle */ break; case 'o': /* round */ break; case 'q': /* square*/ break; case 'x': /* cross */ break; case 'n': /* key with the music note */ break; case 's': /* select */ break; case 'a': /* startbutton */ break; default: ; } } int main(int argc, char **argv) { glutInit(&argc,argv); //инициализация glutInitDisplayMode(GLUT_DOUBLE); //установка режима отображения glutInitWindowSize(480, 272); //размер окна glutInitWindowPosition(0,0); //позиция окна glutCreateWindow("Boll"); //заглавие нашего окошка glutKeyboardFunc(keyPressed); glutKeyboardUpFunc(keyReleased); glutReshapeFunc(DisplayResize); glutDisplayFunc(Display); //функция для рисования glutMainLoop(); //Запускаем обработчик событий return 1; } Функция glLoadIdentity сбрасывает состояние матрицы Функция glTranslatef перемещает точку по заданой траектории Пример: glTranslatef(-1.5f,0.0f,-6.0f); // Сдвинемся влево на 1.5 единицы и // в экран на 6.0 Теперь у нас есть объект, изображенный в правой части экрана. Нам нужно переместиться в левую часть. Так как мы в прошлый раз перемещались влево на 1.5 единицы, необходимо переместиться на 3.0 единицы вправо (1.5 единицы – это будет центр, плюс еще 1.5 единицы для правого края). glTranslatef(3.0f,0.0f,0.0f); // Сдвинем вправо на 3 единицы Скачать примеры: пример 1 пример 2 В архиве идёт как исходник так и уже откомпилированная программа. Вот и всё) В следующем уроке мы научимся налаживать,фильтрировать и освещать текстуры, если успею, ходить по пространству. Всем спасибо за внимание! Вернуться назад |