Форум » Вопросы о разработке игр » Управление камерой OpenGL » Ответить

Управление камерой OpenGL

Vitaliy_3d: Скажите, пожалуйста! Как можно код разделить на разные файлы, так что бы инициализация OpenGL была в одном “ini.cpp” файле а, загрузка или создание и вывод какова ни будь объекта в фтором “obyekt.cpp” а управление описывалось бы им в третьем и т.д. Можно ссылку на статью или книгу где это описывается. За ранее огромное спасибо!

Ответов - 22, стр: 1 2 All

8daemon: Для этого есть заголовочные файлы(.h), в которых описываются прототипы функций, определения инлайн функций, описание классов и структур, определение новых типов, макросы и т.д. и т.п. Эти файлы инклудятся в основной файл либо иной другой (.cpp). Причём название заголовочного файла должно совпадать с названием исходного файла, с ккоторому он относится ( определение функций, прототипы которых находятся в заголовочном, и т.д и т.п.)

Vitaliy_3d: Огромное спасибо! Всё оказалось так просто )

8daemon: Всегда пожалуйста. Почитай книги Ламота, благо есть в инете электронные варианты. Ищи тут infanata.org/prog


stayer: ИМХО, Ламот - это уже совсем не то. Для того чтоб такие простые вещи понять я всем советую Лафоре, еще Липмана можно почитать. У Ламота такой жуткий стиль программирования - что аж зубы сводит. Но как теорию по визуализации для начинающих - вполне...

Vitaliy_3d: Огромное спасибо! )

Vitaliy_3d: Подскажите, пожалуйста! Как можно вывести несколько независимых камер, на подобии “3ds Max”? OpenGL C++

8daemon: попробуй создать дочерние окна, с соответствующими стилями и на каждый свой девайс. Я давно конечно не работал уже с этим. И правда с опен жл не работал, но думаю там щас всё схоже с директх. Надеюсь суть понятна

Vitaliy_3d: Подскажите, пожалуйста, как можно место phong3.bmp вставить переменную teks, что бы можно её было бы вводить texturer(a, teks); a = номер текстуры teks = имя текстуры texturer(1, phong3.bmp); texturer(2, phong7.bmp); итд. GLuint texture[3]; void texturer(int a) { // Загрузка картинки AUX_RGBImageRec *texture1; texture1 = auxDIBImageLoad ("phong3.bmp"); // Создание текстуры glGenTextures(1, &texture[a]); glBindTexture(GL_TEXTURE_2D, texture[a]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, 3, texture1->sizeX, texture1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, texture1->data); }

8daemon: Если я правильно понял вопрос то так GLuint texture[3]; void texturer(int a, char* teks) { // Загрузка картинки AUX_RGBImageRec *texture1; texture1 = auxDIBImageLoad (teks); // Создание текстуры glGenTextures(1, &texture[a]); glBindTexture(GL_TEXTURE_2D, texture[a]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, 3, texture1->sizeX, texture1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, texture1->data); }

8daemon: char strPattern[] = "phongN.bmp"; for(int i=0; i<MAX_PHONG_NUM_0_9; i++) { strPattern[6] = i+0x30; // 'N' <- i+'0' texturer(i, strPattern); } Число одноимённых текстур в данном случаи 10 (0-9). Ну можно конечно и больше сделать. Есть воля для фантазий :)

Vitaliy_3d: Огромное спасибо! :)

Vitaliy_3d: Скажите, пожалуйста, почему вместе с объектом (кубом) вращается свет? Как можно сделать, что бы свет был независим от объекта? И в данном примере светил прямо на объект, а не периодически пропадал! За ранее огромное спасибо :) // Glaux.lib Opengl32.lib Glu32.lib /subsystem:windows #include <windows.h> #include <GL/gl.h> // Наша OpenGL библиотека #include <GL/glu.h> // Библиотека утилит OpenGL #include <GL/glaux.h> // И еще одна, с ее помощью можно рисовать стандартрые обьекты(сферы, кубы, и др.) #pragma comment (lib, "OpenGL32.lib") static GLint resW = 800, resH = 600; // Размер окна bool isFullscr = false; // Полноэкранный режим (по умолчанию - нет) static GLdouble cntr; // Счетчик. Отвечает за вращение шарика BOOL keys[256]; // Массив для процедуры обработки клавиатуры HGLRC hGLRC; // Контекст рендеринга OpenGL HDC hDC; // Контекст устройства Windows GLvoid InitGL() // Вызвать после создания окна GL { glClearColor (0.3f, 0.3f, 0.3f, 0.0f); //цвет фона // двухсторонний расчет освещения glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); // автоматическое приведение нормалей к единичной длине //Свет-------------------------------------------------------------------------------- GLfloat light_position[] = {4.0, 4.0, 4.0, 1.0}; //Позиция источника света (x.y.z.-) glLightf (GL_LIGHT0, GL_SPOT_EXPONENT, 20.0); glLightfv (GL_LIGHT0, GL_POSITION, light_position); glLightf (GL_LIGHT0, GL_SPECULAR, 128); glEnable (GL_LIGHTING); // рассчет освещения glEnable (GL_LIGHT0); //------------------------------------------------------------------------------------ glShadeModel (GL_SMOOTH); // Метод закраски: СГЛАЖЕНЫЙ glEnable (GL_DEPTH_TEST); // Включаем тест глубины // ВКЛ. АВТОМАТИЧЕСКИЙ ПЕРЕСЧЕТ НОРМАЛЕЙ glEnable (GL_AUTO_NORMAL); glEnable (GL_NORMALIZE); // ВКЛ. ОТСЕЧЕНИЕ ЗАДНИХ ГРАНЕЙ glEnable (GL_CULL_FACE); // Включаем отсечение граней glCullFace (GL_BACK); // Указываем, что отсекать будем задние грани } void reshape(int width, int height) { glViewport(0,0,width,height); // Устанавливаем размер порта просмотра 0,0 - верхний левый угол glMatrixMode( GL_PROJECTION ); // Переключаемся на матрицу прэкции glLoadIdentity(); // Сбрасываем матрицу прэкции путем установки еденичной матрицы gluPerspective (45.0, (GLfloat)width/(GLfloat)height, 1.0, 1000.0); // настраиваем нашу камеру // gluPerspective (угол_обзора, отношение_ширины_к_высоте_порта_просмотра, ближняя_плоскость_отсечения, дальняя_плоскость_отсечения); //glOrtho(-1.2, 1.2, -1.2, 1.2, -1, 1); glTranslatef(0,0,0); glRotated(0,0,0,0); glMatrixMode( GL_MODELVIEW ); // Переключаемся на матрицу модели-вида glLoadIdentity(); // Сбрасываем матрицу модели-вида путем установки еденичной матрицы } float vv, cv; void display() { // очищаем буфер кадра и глубины glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //Свойство материала GLfloat material_diffuse[] = {1.0, 1.0, 1.0, 1.0}; glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material_diffuse); if (vv >= 360.0f) vv =0.0f; vv = vv + 1; glLoadIdentity(); glTranslatef(0, 0, -10); glRotated(vv, 0.0f, 1.0f, 1.0f); glBegin(GL_QUADS); // Передняя грань 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); // Верх лево // Задняя грань 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); // Низ лево // Верхняя грань 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); // Верх право // Нижняя грань 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); // Низ право ; // Правая грань 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); // Низ лево // Левая грань 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(); glPopMatrix();//Функция glPopMatrix выталкивает на вершину стека матрицу glFlush(); // Досрочное завершение рисования (функция необязательна) } LRESULT CALLBACK WindowFunc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) { RECT Screen; GLuint PixelFormat; static PIXELFORMATDESCRIPTOR pfd= { sizeof(PIXELFORMATDESCRIPTOR), //Размер структуры 1, // Номер версии PFD_DRAW_TO_WINDOW | // Рисовать будем в окно PFD_SUPPORT_OPENGL | // Установим поддержку OpenGL PFD_DOUBLEBUFFER, // Выберем двойной буфер PFD_TYPE_RGBA, // Режим цветности - RGBA 32, // Выберем 32 битную глубину цвета 0, 0, 0, 0, 0, 0, // Игнорирование цветовых битов 0, // Нет буфера прозрачности 0, // Игнорируем сдвиговый бит 0,//---------------------// Нет буфера аккумуляции 1, 1, 1, 1, // Биты аккумуляции игнорируются 32, // 32 битный Z-буфер (буфер глубины) 0, // Нет буфера траффарета 0, // Нет вспомогательных буферов PFD_MAIN_PLANE, // Рисовать в главный слой рисования 0, // Резерв 0, 0, 0 // Маски слоя игнорируются }; switch(message) { // сообщение WM_CREATE приходит // один раз при создании окна case WM_CREATE: hDC = GetDC(hWnd); // Получить контекст устройства для окна PixelFormat = ChoosePixelFormat(hDC, &pfd);// Найти ближайшее совпадение для нашего формата пикселов if (!PixelFormat) // Если неудалось то... { // Выводим сообщение об ошибке MessageBox (0, "Не удается найти подходящий PixelFormat!", "Error", MB_OK | MB_ICONERROR); SendMessage(hWnd, WM_DESTROY, wParam, lParam);// Это сообщение говорит, что программа должна завершится break; //Предотвращение повтора кода } SetPixelFormat (hDC, PixelFormat, &pfd); // Теперь нкжно установить наш формата пикселов if (!SetPixelFormat (hDC, PixelFormat, &pfd)) // Если неудалось то... { // Выводим сообщение об ошибке MessageBox (0, "Не удается установить PixelFormat!", "Ошибка!!!", MB_OK | MB_ICONERROR); // Уничтожаем окно! SendMessage(hWnd, WM_DESTROY, wParam, lParam); break; } hGLRC = wglCreateContext (hDC); //Захватывает Контекст Рендеринга и сохраняет его в переменной hGLRC if (!hGLRC) // Захватить не удалось... { // Выводим сообщение об ошибке MessageBox (0, "Не удается создать контекст рендеринга OpenGL!", "Ошибка!!!", MB_OK | MB_ICONERROR); // Уничтожаем окно! SendMessage(hWnd, WM_DESTROY, wParam, lParam); break; } wglMakeCurrent(hDC, hGLRC); // делаем его текущим if (!wglMakeCurrent(hDC, hGLRC)) { MessageBox (0, "Не удается активировать контекст рендеринга GLRC!", "Ошибка!!!", MB_OK | MB_ICONERROR); // Уничтожаем окно! SendMessage(hWnd, WM_DESTROY, wParam, lParam); break; } // Все... окошко создано... InitGL (); // Инициализируем наш GL break; // это сообщение приходит при уничтожении окна case WM_DESTROY: //Уничтожает окно case WM_CLOSE: //-|-|-|-|-|-|- ChangeDisplaySettings (NULL, 0);//Восстанавливает первоначальное разрешение if(hDC) wglMakeCurrent(hDC, NULL); // Освобождаем контекст рендеринга... if(hGLRC) wglDeleteContext(hGLRC); // ...и удаляем его if(hWnd) ReleaseDC(hWnd, hDC); // Рвем с ним всякие связи. PostQuitMessage(0); // Убиваем окно! break; case WM_SIZE: GetClientRect (hWnd, &Screen);//Создает область рисования и возвращает высоту и ширину окна reshape(Screen.right, Screen.bottom ); break; case WM_SYSKEYDOWN: case WM_KEYDOWN: //Если клавиша нажата то... keys[wParam] = TRUE; //В масив keys[key number] заносится TRUE break; case WM_SYSKEYUP: case WM_KEYUP: //Если клавиша отпущена то... keys[wParam] = FALSE; //В масив keys[key number] заносится FALSE break; default: // Реакция на все осталные сообщения ОС... return DefWindowProc(hWnd,message,wParam,lParam); // ...по умолчанию } // если гдето чтото не так... return 0; // ...возвращаем ошибку } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR str,int nWinMode) { MSG msg;//Структура сообщения Windows WNDCLASS wc; //Структура класса Windows для установки типа окна HWND hWnd;//Сохранение дескриптора окна wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Стиль нашего окна wc.lpfnWndProc = WindowFunc; // Определяем ф-цию ответственную за обработку сообщений ОС wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = NULL; // иконка нашего окошка (по умолчанию) wc.hCursor = LoadCursor (NULL, IDC_ARROW); // Курсор который будет отображаться при наведении на наше окошко (стрелка) wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = "OpenGLWinClass"; // Определяем название класса окна if (!RegisterClass(&wc)) // Если класс зарегистрировать не удалось... { MessageBox(0, "Ошибка при регистрации класса окна!","Ошибка!!!", MB_OK | MB_ICONERROR); return FALSE; } if(isFullscr) // Если режим полноэкранный - создаем окно с соответствующими параметрами { // создаем окно hWnd = CreateWindow( "OpenGLWinClass", // название класса окна "УРОК 01 >OpenGL is COOL", // Заголовок окна WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, // Стиль (вид) окна 0, 0, resW, resH, // Размеры окна NULL, NULL, hInstance, NULL); } else // Иначе утанавливаем наше окошко, его вид и свойства { // создаем окно hWnd = CreateWindow( "OpenGLWinClass", // название класса окна "Игра №1 версия 1.0", // Заголовок окна WS_OVERLAPPEDWINDOW | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE | WS_SIZEBOX, // Стиль (вид) окна 0, 0, resW, resH, // Размеры окна NULL, NULL, hInstance, NULL); } if (!hWnd) // если создать окно не удалось { MessageBox(0, "Ошибка при создании окна!","Ошибка!!!", MB_OK | MB_ICONERROR); return FALSE; } if(isFullscr) { DEVMODE dmScreenSettings; // Режим работы устройства (видио платы) memset (&dmScreenSettings, 0, sizeof(DEVMODE));// Очистка для хранения установок dmScreenSettings.dmSize = sizeof(DEVMODE); // Размер структуры Devmode dmScreenSettings.dmPelsWidth = resW; // Ширина экрана dmScreenSettings.dmPelsHeight = resH; // Высота экрана dmScreenSettings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;// Режим Пиксела ChangeDisplaySettings (&dmScreenSettings, CDS_FULLSCREEN);// Переключение в полный экран } //else ChangeDisplaySettings (&dmScreenSettings, CDS_GLOBAL); ShowWindow(hWnd,nWinMode); // Показать окно UpdateWindow(hWnd); // Обновить окно SetFocus(hWnd); // Сделать окно активным while (1) { // Обработка всех сообщений while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { if (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage (&msg); DispatchMessage (&msg); } else return TRUE; } display(); // Нарисовать сцену SwapBuffers(hDC); // Переключить буфер экрана if (keys[VK_ESCAPE]) SendMessage(hWnd, WM_CLOSE, 0, 0);// Если ESC - выйти } }

8daemon: Во-первых, ОпенЖЛ никогда не пользовался. Во-вторых, когда я врубил твою демку куб вращался так что я даже не понял что там :) - добавил ограничение числа кадров 30 к/с. В-третьих я так посмотрел без запуска вроде всё норм было, однако предположил, что когда ты задаёшь матрицы вращения и перемещения ты воздействуешь и на вектор света, так и оказалось, так что я перенёс установку вектора света в область кода отрисовки и всё норм. Библиотеки и хидера glaux у меня нету. Скорее всего glTranslatef(0, 0, -10); glRotated(vv, 0.0f, 1.0f, 1.0f); мы задаем положение камеры, так как я в коде не увидел задание матрицы Камеры. // Glaux.lib Opengl32.lib Glu32.lib winmm.lib /subsystem:windows #include <windows.h> #include <GL/gl.h> // Наша OpenGL библиотека #include <GL/glu.h> // Библиотека утилит OpenGL //#include <GL/glaux.h> // И еще одна, с ее помощью можно рисовать стандартрые обьекты(сферы, кубы, и др.) #include <MMSystem.h>// Узнать время прошедшее с запуска Винды в миллисекундах //#pragma comment (lib, "OpenGL32.lib") static GLint resW = 800, resH = 600; // Размер окна bool isFullscr = false; // Полноэкранный режим (по умолчанию - нет) static GLdouble cntr; // Счетчик. Отвечает за вращение шарика BOOL keys[256]; // Массив для процедуры обработки клавиатуры HGLRC hGLRC; // Контекст рендеринга OpenGL HDC hDC; // Контекст устройства Windows GLfloat light_position[] = {4.0, 4.0, 4.0, 1.0}; //Позиция источника света (x.y.z.-) // делаем глобальным GLvoid InitGL() // Вызвать после создания окна GL { glClearColor (0.3f, 0.3f, 0.3f, 0.0f); //цвет фона // двухсторонний расчет освещения glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); // автоматическое приведение нормалей к единичной длине //Свет-------------------------------------------------------------------------------- glLightf (GL_LIGHT0, GL_SPOT_EXPONENT, 20.0); glLightf (GL_LIGHT0, GL_SPECULAR, 128); glEnable (GL_LIGHTING); // рассчет освещения glEnable (GL_LIGHT0); //------------------------------------------------------------------------------------ glShadeModel (GL_SMOOTH); // Метод закраски: СГЛАЖЕНЫЙ glEnable (GL_DEPTH_TEST); // Включаем тест глубины // ВКЛ. АВТОМАТИЧЕСКИЙ ПЕРЕСЧЕТ НОРМАЛЕЙ glEnable (GL_AUTO_NORMAL); glEnable (GL_NORMALIZE); // ВКЛ. ОТСЕЧЕНИЕ ЗАДНИХ ГРАНЕЙ glEnable (GL_CULL_FACE); // Включаем отсечение граней glCullFace (GL_BACK); // Указываем, что отсекать будем задние грани } void reshape(int width, int height) { glViewport(0,0,width,height); // Устанавливаем размер порта просмотра 0,0 - верхний левый угол glMatrixMode( GL_PROJECTION ); // Переключаемся на матрицу прэкции glLoadIdentity(); // Сбрасываем матрицу прэкции путем установки еденичной матрицы gluPerspective (45.0, (GLfloat)width/(GLfloat)height, 1.0, 1000.0); // настраиваем нашу камеру // gluPerspective (угол_обзора, отношение_ширины_к_высоте_порта_просмотра, ближняя_плоскость_отсечения, дальняя_плоскость_отсечения); //glOrtho(-1.2, 1.2, -1.2, 1.2, -1, 1); glTranslatef(0,0,0); glRotated(0,0,0,0); glMatrixMode( GL_MODELVIEW ); // Переключаемся на матрицу модели-вида glLoadIdentity(); // Сбрасываем матрицу модели-вида путем установки еденичной матрицы } float vv, cv; void display() { DWORD CurTime = GetTickCount(); // очищаем буфер кадра и глубины glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //Свойство материала GLfloat material_diffuse[] = {1.0, 1.0, 1.0, 1.0}; glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material_diffuse); if (vv >= 360.0f) vv =0.0f; vv = vv + 1; glLoadIdentity(); glTranslatef(0, 0, -10); glRotated(vv, 0.0f, 1.0f, 1.0f); glLightfv (GL_LIGHT0, GL_POSITION, light_position); glBegin(GL_QUADS); // Передняя грань 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); // Верх лево // Задняя грань 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); // Низ лево // Верхняя грань 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); // Верх право // Нижняя грань 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); // Низ право ; // Правая грань 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); // Низ лево // Левая грань 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(); glPopMatrix();//Функция glPopMatrix выталкивает на вершину стека матрицу glFlush(); // Досрочное завершение рисования (функция необязательна) while(GetTickCount() - CurTime < 33); } LRESULT CALLBACK WindowFunc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) { RECT Screen; GLuint PixelFormat; static PIXELFORMATDESCRIPTOR pfd= { sizeof(PIXELFORMATDESCRIPTOR), //Размер структуры 1, // Номер версии PFD_DRAW_TO_WINDOW | // Рисовать будем в окно PFD_SUPPORT_OPENGL | // Установим поддержку OpenGL PFD_DOUBLEBUFFER, // Выберем двойной буфер PFD_TYPE_RGBA, // Режим цветности - RGBA 32, // Выберем 32 битную глубину цвета 0, 0, 0, 0, 0, 0, // Игнорирование цветовых битов 0, // Нет буфера прозрачности 0, // Игнорируем сдвиговый бит 0,//---------------------// Нет буфера аккумуляции 1, 1, 1, 1, // Биты аккумуляции игнорируются 32, // 32 битный Z-буфер (буфер глубины) 0, // Нет буфера траффарета 0, // Нет вспомогательных буферов PFD_MAIN_PLANE, // Рисовать в главный слой рисования 0, // Резерв 0, 0, 0 // Маски слоя игнорируются }; switch(message) { // сообщение WM_CREATE приходит // один раз при создании окна case WM_CREATE: hDC = GetDC(hWnd); // Получить контекст устройства для окна PixelFormat = ChoosePixelFormat(hDC, &pfd);// Найти ближайшее совпадение для нашего формата пикселов if (!PixelFormat) // Если неудалось то... { // Выводим сообщение об ошибке MessageBox (0, "Не удается найти подходящий PixelFormat!", "Error", MB_OK | MB_ICONERROR); SendMessage(hWnd, WM_DESTROY, wParam, lParam);// Это сообщение говорит, что программа должна завершится break; //Предотвращение повтора кода } SetPixelFormat (hDC, PixelFormat, &pfd); // Теперь нкжно установить наш формата пикселов if (!SetPixelFormat (hDC, PixelFormat, &pfd)) // Если неудалось то... { // Выводим сообщение об ошибке MessageBox (0, "Не удается установить PixelFormat!", "Ошибка!!!", MB_OK | MB_ICONERROR); // Уничтожаем окно! SendMessage(hWnd, WM_DESTROY, wParam, lParam); break; } hGLRC = wglCreateContext (hDC); //Захватывает Контекст Рендеринга и сохраняет его в переменной hGLRC if (!hGLRC) // Захватить не удалось... { // Выводим сообщение об ошибке MessageBox (0, "Не удается создать контекст рендеринга OpenGL!", "Ошибка!!!", MB_OK | MB_ICONERROR); // Уничтожаем окно! SendMessage(hWnd, WM_DESTROY, wParam, lParam); break; } wglMakeCurrent(hDC, hGLRC); // делаем его текущим if (!wglMakeCurrent(hDC, hGLRC)) { MessageBox (0, "Не удается активировать контекст рендеринга GLRC!", "Ошибка!!!", MB_OK | MB_ICONERROR); // Уничтожаем окно! SendMessage(hWnd, WM_DESTROY, wParam, lParam); break; } // Все... окошко создано... InitGL (); // Инициализируем наш GL break; // это сообщение приходит при уничтожении окна case WM_DESTROY: //Уничтожает окно case WM_CLOSE: //-|-|-|-|-|-|- ChangeDisplaySettings (NULL, 0);//Восстанавливает первоначальное разрешение if(hDC) wglMakeCurrent(hDC, NULL); // Освобождаем контекст рендеринга... if(hGLRC) wglDeleteContext(hGLRC); // ...и удаляем его if(hWnd) ReleaseDC(hWnd, hDC); // Рвем с ним всякие связи. PostQuitMessage(0); // Убиваем окно! break; case WM_SIZE: GetClientRect (hWnd, &Screen);//Создает область рисования и возвращает высоту и ширину окна reshape(Screen.right, Screen.bottom ); break; case WM_SYSKEYDOWN: case WM_KEYDOWN: //Если клавиша нажата то... keys[wParam] = TRUE; //В масив keys[key number] заносится TRUE break; case WM_SYSKEYUP: case WM_KEYUP: //Если клавиша отпущена то... keys[wParam] = FALSE; //В масив keys[key number] заносится FALSE break; default: // Реакция на все осталные сообщения ОС... return DefWindowProc(hWnd,message,wParam,lParam); // ...по умолчанию } // если гдето чтото не так... return 0; // ...возвращаем ошибку } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR str,int nWinMode) { MSG msg;//Структура сообщения Windows WNDCLASS wc; //Структура класса Windows для установки типа окна HWND hWnd;//Сохранение дескриптора окна wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Стиль нашего окна wc.lpfnWndProc = WindowFunc; // Определяем ф-цию ответственную за обработку сообщений ОС wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = NULL; // иконка нашего окошка (по умолчанию) wc.hCursor = LoadCursor (NULL, IDC_ARROW); // Курсор который будет отображаться при наведении на наше окошко (стрелка) wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = "OpenGLWinClass"; // Определяем название класса окна if (!RegisterClass(&wc)) // Если класс зарегистрировать не удалось... { MessageBox(0, "Ошибка при регистрации класса окна!","Ошибка!!!", MB_OK | MB_ICONERROR); return FALSE; } if(isFullscr) // Если режим полноэкранный - создаем окно с соответствующими параметрами { // создаем окно hWnd = CreateWindow( "OpenGLWinClass", // название класса окна "УРОК 01 >OpenGL is COOL", // Заголовок окна WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, // Стиль (вид) окна 0, 0, resW, resH, // Размеры окна NULL, NULL, hInstance, NULL); } else // Иначе утанавливаем наше окошко, его вид и свойства { // создаем окно hWnd = CreateWindow( "OpenGLWinClass", // название класса окна "Игра №1 версия 1.0", // Заголовок окна WS_OVERLAPPEDWINDOW | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE | WS_SIZEBOX, // Стиль (вид) окна 0, 0, resW, resH, // Размеры окна NULL, NULL, hInstance, NULL); } if (!hWnd) // если создать окно не удалось { MessageBox(0, "Ошибка при создании окна!","Ошибка!!!", MB_OK | MB_ICONERROR); return FALSE; } if(isFullscr) { DEVMODE dmScreenSettings; // Режим работы устройства (видио платы) memset (&dmScreenSettings, 0, sizeof(DEVMODE));// Очистка для хранения установок dmScreenSettings.dmSize = sizeof(DEVMODE); // Размер структуры Devmode dmScreenSettings.dmPelsWidth = resW; // Ширина экрана dmScreenSettings.dmPelsHeight = resH; // Высота экрана dmScreenSettings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;// Режим Пиксела ChangeDisplaySettings (&dmScreenSettings, CDS_FULLSCREEN);// Переключение в полный экран } //else ChangeDisplaySettings (&dmScreenSettings, CDS_GLOBAL); ShowWindow(hWnd,nWinMode); // Показать окно UpdateWindow(hWnd); // Обновить окно SetFocus(hWnd); // Сделать окно активным while (1) { // Обработка всех сообщений while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { if (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage (&msg); DispatchMessage (&msg); } else return TRUE; } display(); // Нарисовать сцену SwapBuffers(hDC); // Переключить буфер экрана if (keys[VK_ESCAPE]) SendMessage(hWnd, WM_CLOSE, 0, 0);// Если ESC - выйти } }

Vitaliy_3d: Надеюсь, ещё не надоел с вопросами! :) Подскажите, пожалуйста, как в GL_LIGHT3 можно занести в переменную место 3. glEnable(GL_LIGHTnomer); nomer = 3; void progektor(int poz_x, int poz_y, int poz_z, float napravleniye, ?????) { glLoadIdentity(); glTranslated(poz_x, poz_y, poz_z); glRotated(0, 0.0f, 0.0f, 0.0f); // прожектор // убывание интенсивности с расстоянием // отключено (по умолчанию) // половина угла при вершине 30 градусов // направление на центр плоскости GLfloat light3_diffuse[] = {0.9, 0.9, 0.2}; GLfloat light3_position[] = {0.0, 0.0, 1.0, 1.0}; GLfloat light3_spot_direction[] = {0.0, 0.0, napravleniye}; glEnable(GL_LIGHT3); glLightfv(GL_LIGHT3, GL_DIFFUSE, light3_diffuse); glLightfv(GL_LIGHT3, GL_POSITION, light3_position); glLightf(GL_LIGHT3, GL_SPOT_CUTOFF, 30); glLightfv(GL_LIGHT3, GL_SPOT_DIRECTION, light3_spot_direction); } // отключение источников света //glDisable(GL_LIGHT3);

8daemon: Я так понимаю GL_LIGHT3 это определение типа #define GL_LIGHT3 3 // -это как я думаю системное определение ОпенЖЛ,тогда void progektor(int poz_x, int poz_y, int poz_z, float napravleniye, int nomer) { glLoadIdentity(); glTranslated(poz_x, poz_y, poz_z); glRotated(0, 0.0f, 0.0f, 0.0f); // прожектор // убывание интенсивности с расстоянием // отключено (по умолчанию) // половина угла при вершине 30 градусов // направление на центр плоскости GLfloat light_diffuse[] = {0.9, 0.9, 0.2}; GLfloat light_position[] = {0.0, 0.0, 1.0, 1.0}; GLfloat light_spot_direction[] = {0.0, 0.0, napravleniye}; glEnable(nomer); glLightfv(nomer, GL_DIFFUSE, light_diffuse[] ); glLightfv(nomer, GL_POSITION, light_position[]); glLightf(nomer, GL_SPOT_CUTOFF, 30); glLightfv(nomer, GL_SPOT_DIRECTION, light_spot_direction[] ); } // отключение источников света //glDisable(nomer);

8daemon: А лучше struct Vector3D { union { struct { float x; float y; float z; }; struct { float r; float g; float b; }; }; }; struct Light { Vector3D pos; Vector3D direction; Vector3D diffuse; }; void progektor(Light* light, int nomer) { glLoadIdentity(); // -? // прожектор // убывание интенсивности с расстоянием // отключено (по умолчанию) // половина угла при вершине 30 градусов // направление на центр плоскости glEnable(nomer); glLightfv(nomer, GL_DIFFUSE, (GLfloat*)&light->diffuse ); glLightfv(nomer, GL_POSITION,(GLfloat*)&light->pos); glLightf(nomer, GL_SPOT_CUTOFF, 30); glLightfv(nomer, GL_SPOT_DIRECTION, (GLfloat*)&light->direction ); } // отключение источников света //glDisable(nomer); //Пример вызова Light light; //...заполнение структуры light// progektor(&light, GL_LIGHT3);

Vitaliy_3d: Подскажите пожалуйста как можно сделать в этом примере так, чтобы при загрузке модели можно было бы указывать переменную (имя или какой либо номер(tank, 1, 2)): Load3DS(переменная, “путь к объекту”); Load3DS(tank, 3ds/kkk3.3DS"); Load3DS(1, 3ds/kkk3.3DS"); Load3DS(2, 3ds/kkk3.3DS"); А при выводе указываешь эту переменную(tank, 1, 2) и он выводит этот объект. ris3DS(tank); ris3DS(1); ris3DS(2); /*------ЗАГРУЗКА И ВЫВОД 3DS ОБЬЕКТА------*/ //----------------------------------------------------------------------- #include <io.h> #define MAX_VERTICES 800000 // Количество максимальых граней #define MAX_POLYGONS 800000 // Количество максимальых многоугольников // Наш тип вершины typedef struct{ float x,y,z; }vertex_type; // Переменные для 3-х граней треугольников typedef struct{ int a,b,c; } polygon_type; // Координаты текстур по 2 на один треугольник typedef struct{ float u,v; }mapcoord_type; // Тип обьекта typedef struct { char name[20]; int vertices_qty; int polygons_qty; vertex_type vertex[MAX_VERTICES]; polygon_type polygon[MAX_POLYGONS]; mapcoord_type mapcoord[MAX_VERTICES]; int id_texture; } obj_type, *obj_type_ptr; //Load3DS(&object_3d,"3ds/kkk3.3DS"); char Load3DS (obj_type_ptr p_object, char *name3ds) { int i; //Индексная переменная FILE *l_file; //Файловый указатель unsigned short l_chunk_id; unsigned int l_chunk_lenght; unsigned char l_char; //Символьная переменная unsigned short l_qty; //Количество элементов в каждом chunk(куске) unsigned short l_face_flags; //Флаг, который загружает некоторую лицевую информацию /*Открытие файла, если файла нет то выводится без него*/ if ((l_file=fopen (name3ds, "rb"))== NULL) return 0; while (ftell (l_file) < filelength (fileno (l_file))) //Цикл должен сканировать целый файл { fread (&l_chunk_id, 2, 1, l_file); fread (&l_chunk_lenght, 4, 1, l_file); switch (l_chunk_id) { //----------------- MAIN3DS Сцена 3DS----------------- case 0x4d4d: break; //----------------- EDIT3DS Всяческие обьекты----------------- case 0x3d3d: break; //--------------- EDIT_OBJECT объект--------------- case 0x4000: i=0; do { fread (&l_char, 1, 1, l_file); p_object->name=l_char; i++; }while(l_char != '\0' && i<20); break; //--------------- OBJ_TRIMESH trimesh-объект--------------- break; //--------------- TRI_VERTEXL список вершин--------------- case 0x4110: fread (&l_qty, sizeof (unsigned short), 1, l_file); p_object->vertices_qty = l_qty; for (i=0; i<l_qty; i++) { fread (&p_object->vertex.x, sizeof(float), 1, l_file); fread (&p_object->vertex.y, sizeof(float), 1, l_file); fread (&p_object->vertex.z, sizeof(float), 1, l_file); } break; //--------------- TRI_FACEL1 список граней---------------- case 0x4120: fread (&l_qty, sizeof (unsigned short), 1, l_file); p_object->polygons_qty = l_qty; for (i=0; i<l_qty; i++) { fread (&p_object->polygon.a, sizeof (unsigned short), 1, l_file); fread (&p_object->polygon.b, sizeof (unsigned short), 1, l_file); fread (&p_object->polygon.c, sizeof (unsigned short), 1, l_file); fread (&l_face_flags, sizeof (unsigned short), 1, l_file); } break; //------------- TRI_MAPPINGCOORS текстурные координаты------------ case 0x4140: fread (&l_qty, sizeof (unsigned short), 1, l_file); for (i=0; i<l_qty; i++) { fread (&p_object->mapcoord.u, sizeof (float), 1, l_file); fread (&p_object->mapcoord.v, sizeof (float), 1, l_file); } break; fseek(l_file, l_chunk_lenght-6, SEEK_CUR); } } fclose (l_file); // Закрывает файловый поток return (1); // Возврат ok } //--------------- obj_type object_3d; //--------------- //ris3DS(); //Рисование 3DS void ris3DS() { int l_index; glBegin(GL_TRIANGLES); for (l_index=0;l_index<object_3d.polygons_qty;l_index++) { //----------------- ПЕРВАЯ ВЕРШИНА ----------------- // Координаты Текстуры первой вершины glTexCoord2f( object_3d.mapcoord[ object_3d.polygon[l_index].a ].u, object_3d.mapcoord[ object_3d.polygon[l_index].a ].v); // Координаты первой вершины glVertex3f( object_3d.vertex[ object_3d.polygon[l_index].a ].x, object_3d.vertex[ object_3d.polygon[l_index].a ].y, object_3d.vertex[ object_3d.polygon[l_index].a ].z); //Vertex definition //----------------- ВТОРАЯ ВЕРШИНА ----------------- // Координаты Текстуры второй вершины glTexCoord2f( object_3d.mapcoord[ object_3d.polygon[l_index].b ].u, object_3d.mapcoord[ object_3d.polygon[l_index].b ].v); // Координаты второй вершины glVertex3f( object_3d.vertex[ object_3d.polygon[l_index].b ].x, object_3d.vertex[ object_3d.polygon[l_index].b ].y, object_3d.vertex[ object_3d.polygon[l_index].b ].z); //----------------- ТРЕТЬЯ ВЕРШИНА ----------------- // Координаты Текстуры третьей вершины glTexCoord2f( object_3d.mapcoord[ object_3d.polygon[l_index].c ].u, object_3d.mapcoord[ object_3d.polygon[l_index].c ].v); // Координаты Третьей вершины glVertex3f( object_3d.vertex[ object_3d.polygon[l_index].c ].x, object_3d.vertex[ object_3d.polygon[l_index].c ].y, object_3d.vertex[ object_3d.polygon[l_index].c ].z); } glEnd(); } И как в этом коде можно сделать что бы загружались все объекты сцены, а не последняя?

8daemon: Правильно бы было написать две функции LoadObjectFrom3DS и UnLoadObject , первая ф-ия занимается следующим: открывает файл по указ. адресу, читает заголовок файла(делает проверку формата и т.п.), выделяет память под требуемое количество вершин(динамически, а не как у тебя статически массивом), производит чтение вершин и свойств в память из файла, закрывает файл; вторая ф-ция занимается освобождением памяти, выделенной первой. Я так думаю будет лучше. Насчет второго вопроса, используй ф-цию типа LoadSceneFrom3DS и UnLoadScene и структуру типа struct scene_3d { uint numobjects; object_3d* objects; }; Описанные ф-ии схожи с выше описанными

Vitaliy_3d: Помогите! ) Когда двигаешься прямо и вращяешься вправо влево, то всё нормально работает но при вращении вверх и в низ, особенно разворот на 180 градусов сразу всё управление переворачивает! Вот эту простую проблему мне пока не получаеться решить! const float constantn = 0.017f; float anglex; float angley; float positionx; float positiony; float positionz; float position_speed; float angle_speed; void Camera() { glViewport(0,0,1024,768); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glClearColor (0.5f, 0.5f, 0.0f, 0.0f); gluPerspective (45.0, (GLfloat)1024/(GLfloat)768, 1.0, 1000.0); glMatrixMode( GL_MODELVIEW ); glMatrixMode( GL_PROJECTION ); glRotatef(anglex,1.0f,0,0); glRotatef(-angley,0,1.0f,0); glTranslatef(positionx, positiony, positionz); position_speed = 5.0f; angle_speed = 1.0f; if (GetAsyncKeyState('W')) //Вперёт { positionx += sin(angley * constantn) * position_speed; positiony += sin(anglex * constantn) * position_speed; positionz += cos(angley * constantn) * position_speed; } if (GetAsyncKeyState('S')) //Назад { positionx -= sin(angley * constantn) * position_speed; positiony -= sin(anglex * constantn) * position_speed; positionz -= cos(angley * constantn) * position_speed; } if (GetAsyncKeyState(VK_RIGHT)) //Вправо { angley -= angle_speed; } if (GetAsyncKeyState(VK_LEFT)) //Влево { angley += angle_speed; } if (GetAsyncKeyState(VK_UP)) //Вверх { anglex -= angle_speed; } if (GetAsyncKeyState(VK_DOWN)) //Вниз { anglex += angle_speed; } glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); }

Vitaliy_3d: В верх и вниз я разобрался! Осталось только в право и влево! И ещё интересно было бы реализовать поворот по оси Z! float anglex; float angley; float anglez; float positionx; float positiony; float positionz; float position_speed; float angle_speed; float ff; float gg; float constantn;// = 0.017f; void Camera() { glViewport(0,0,1024,768); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glClearColor (0.0f, 0.0f, 0.0f, 0.0f); gluPerspective (45.0, (GLfloat)1024/(GLfloat)768, 1.0, 10000.0); //glMatrixMode( GL_MODELVIEW ); //glMatrixMode( GL_PROJECTION ); if (anglex >= 360) { anglex = 1; } if(anglex <= 0) { anglex = 360;} if (angley >= 360) { angley = 1; } if(angley <= 0) { angley = 360;} if (anglez >= 360) { anglez = 1; } if(anglez <= 0) { anglez = 360;} glRotatef(anglex, 1.0f, 0, 0); glRotatef(-angley, 0, 1.0f, 0); glRotatef(-anglez, 0, 0, 1.0f); glTranslatef(positionx, positiony, positionz-300); position_speed = 5.0f; angle_speed = 1.0f; constantn = 0.017f; if (GetAsyncKeyState('W')) //Вперёт { positionx += sin(angley* constantn) * position_speed; positiony += sin(anglex * constantn) * position_speed; positionz += cos((angley - anglex) * constantn) * position_speed; } if (GetAsyncKeyState('S')) //Назад { positionx -= sin(angley * constantn) * position_speed; positiony -= sin(anglex * constantn) * position_speed; positionz -= cos((angley - anglex) * constantn) * position_speed; } if (GetAsyncKeyState('A')) //Влево { //? } if (GetAsyncKeyState('D')) //Вправо { //? } if (GetAsyncKeyState(VK_UP)) //Поворот Вверх { anglex -= angle_speed; } if (GetAsyncKeyState(VK_DOWN)) //Поворот Вниз { anglex += angle_speed; } if (GetAsyncKeyState(VK_RIGHT)) //Поворот Вправо { angley -= angle_speed; } if (GetAsyncKeyState(VK_LEFT)) //Поворот Влево { angley += angle_speed; } if (GetAsyncKeyState('E')) //Наклон вправо { anglez -= angle_speed;//? } if (GetAsyncKeyState('Q')) //Наклон влево { anglez += angle_speed;//? } glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); }



полная версия страницы