У меня выдало:
1>------ Build started: Project: OpenGL Test, Configuration: Debug Win32 ------
1>Compiling...
1>main.cpp
1>***\opengl test\opengl test\main.cpp(51) : error C2664: 'LoadIconW' : cannot convert parameter 2 from 'CHAR [11]' to 'LPCWSTR'
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>***\opengl test\opengl test\main.cpp(54) : error C2440: '=' : cannot convert from 'CHAR [11]' to 'LPCWSTR'
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>***\opengl test\opengl test\main.cpp(55) : error C2440: '=' : cannot convert from 'CHAR [11]' to 'LPCWSTR'
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>***\opengl test\opengl test\main.cpp(71) : error C2664: 'CreateWindowExW' : cannot convert parameter 2 from 'CHAR [11]' to 'LPCWSTR'
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>***\opengl test\opengl test\main.cpp(173) : warning C4244: '=' : conversion from 'LRESULT' to 'LONG', possible loss of data
1>***\opengl test\opengl test\main.cpp(202) : error C2664: 'MessageBoxW' : cannot convert parameter 2 from 'const char [25]' to 'LPCWSTR'
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>***\opengl test\opengl test\main.cpp(208) : error C2664: 'MessageBoxW' : cannot convert parameter 2 from 'const char [22]' to 'LPCWSTR'
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>Build log was saved at "file://***\OpenGL Test\OpenGL Test\Debug\BuildLog.htm"
1>OpenGL Test - 6 error(s), 1 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
CHAR - это тип символов простых (байтовых) а WCHAR - это тип UNICODE символов. Аналогично STR и WSTR - только не символы а строки. Такие ошибки чаще всего из-за несоответствия: UNICODE программа, а строки простые или наоборот.
Можно устранить несколькими способами:
1) Сделать в настройках проэкта тип программы не UNICODE и всё станет гладко (Project->Project Settings->Configuration Properties->Character Set поставить "Use Multi-Byte Character Set")
2) Поправить строки первым способом: вручную изменить типы CHAR на WCHAR и STR на WSTR и похожие на них, и функции связанные с ними.
3) Поправить строки вторым способом (я так сделал в этот раз): подключить библиотеку <tchar.h>.
Теперь по подробнее как я сделал:
1) Подключил библиотеку
#include <tchar.h> после cтрочки
#include <GL/glu.h>.
2)заменил
CHAR szAppName[]=
"Win OpenGL";
на
TCHAR szAppName[]=_T(
"Win OpenGL");
TCHAR это такой гибкий тип, который если программа UNICODE то тоже самое что WCHAR а если программа Multi-Byte то просто CHAR.
А _T(текст) гибкий макрос, который если использовать UNICODE то преобразует строку "asd" (эта строка Multi-Byte) в строку L"asd" где L означает что строка UNICODE. А если используется Multi-Byte то ничего не делает со строкой.
3)Аналогично
"Generic OpenGL Sample" заменил на _T(
"Generic OpenGL Sample") И остальные строки
"ChoosePixelFormat failed"...
Сохранил. Снова компилирую (F7).
1>------ Build started: Project: OpenGL Test, Configuration: Debug Win32 ------
1>Compiling...
1>main.cpp
1>***\opengl test\opengl test\main.cpp(174) : warning C4244: '=' : conversion from 'LRESULT' to 'LONG', possible loss of data
1>Compiling manifest to resources...
1>Linking...
1>main.obj : error LNK2019: unresolved external symbol __imp__wglDeleteContext@4 referenced in function "long __stdcall MainWndProc(struct HWND__ *,unsigned int,unsigned int,long)" (?MainWndProc@@YGJPAUHWND__@@IIJ@Z)
1>main.obj : error LNK2019: unresolved external symbol __imp__wglMakeCurrent@8 referenced in function "long __stdcall MainWndProc(struct HWND__ *,unsigned int,unsigned int,long)" (?MainWndProc@@YGJPAUHWND__@@IIJ@Z)
1>main.obj : error LNK2019: unresolved external symbol __imp__wglCreateContext@4 referenced in function "long __stdcall MainWndProc(struct HWND__ *,unsigned int,unsigned int,long)" (?MainWndProc@@YGJPAUHWND__@@IIJ@Z)
1>main.obj : error LNK2019: unresolved external symbol _gluPerspective@32 referenced in function "void __cdecl resize(int,int)" (?resize@@YAXHH@Z)
1>main.obj : error LNK2019: unresolved external symbol __imp__glLoadIdentity@0 referenced in function "void __cdecl resize(int,int)" (?resize@@YAXHH@Z)
1>main.obj : error LNK2019: unresolved external symbol __imp__glMatrixMode@4 referenced in function "void __cdecl resize(int,int)" (?resize@@YAXHH@Z)
1>main.obj : error LNK2019: unresolved external symbol __imp__glViewport@16 referenced in function "void __cdecl resize(int,int)" (?resize@@YAXHH@Z)
1>main.obj : error LNK2019: unresolved external symbol __imp__glPopMatrix@0 referenced in function "void __cdecl createObjects(void)" (?createObjects@@YAXXZ)
1>main.obj : error LNK2019: unresolved external symbol __imp__glTranslatef@12 referenced in function "void __cdecl createObjects(void)" (?createObjects@@YAXXZ)
1>main.obj : error LNK2019: unresolved external symbol __imp__glRotatef@16 referenced in function "void __cdecl createObjects(void)" (?createObjects@@YAXXZ)
1>main.obj : error LNK2019: unresolved external symbol __imp__glPushMatrix@0 referenced in function "void __cdecl createObjects(void)" (?createObjects@@YAXXZ)
1>main.obj : error LNK2019: unresolved external symbol _gluCylinder@36 referenced in function "void __cdecl createObjects(void)" (?createObjects@@YAXXZ)
1>main.obj : error LNK2019: unresolved external symbol _gluQuadricNormals@8 referenced in function "void __cdecl createObjects(void)" (?createObjects@@YAXXZ)
1>main.obj : error LNK2019: unresolved external symbol __imp__glEndList@0 referenced in function "void __cdecl createObjects(void)" (?createObjects@@YAXXZ)
1>main.obj : error LNK2019: unresolved external symbol _gluSphere@20 referenced in function "void __cdecl createObjects(void)" (?createObjects@@YAXXZ)
1>main.obj : error LNK2019: unresolved external symbol _gluQuadricDrawStyle@8 referenced in function "void __cdecl createObjects(void)" (?createObjects@@YAXXZ)
1>main.obj : error LNK2019: unresolved external symbol _gluNewQuadric@0 referenced in function "void __cdecl createObjects(void)" (?createObjects@@YAXXZ)
1>main.obj : error LNK2019: unresolved external symbol __imp__glNewList@8 referenced in function "void __cdecl createObjects(void)" (?createObjects@@YAXXZ)
1>main.obj : error LNK2019: unresolved external symbol __imp__glEnable@4 referenced in function "void __cdecl initializeGL(int,int)" (?initializeGL@@YAXHH@Z)
1>main.obj : error LNK2019: unresolved external symbol __imp__glClearDepth@8 referenced in function "void __cdecl initializeGL(int,int)" (?initializeGL@@YAXHH@Z)
1>main.obj : error LNK2019: unresolved external symbol __imp__glClearIndex@4 referenced in function "void __cdecl initializeGL(int,int)" (?initializeGL@@YAXHH@Z)
1>main.obj : error LNK2019: unresolved external symbol __imp__glRotated@32 referenced in function "void __cdecl polarView(double,double,double,double)" (?polarView@@YAXNNNN@Z)
1>main.obj : error LNK2019: unresolved external symbol __imp__glTranslated@24 referenced in function "void __cdecl polarView(double,double,double,double)" (?polarView@@YAXNNNN@Z)
1>main.obj : error LNK2019: unresolved external symbol __imp__glCallList@4 referenced in function "void __cdecl drawScene(void)" (?drawScene@@YAXXZ)
1>main.obj : error LNK2019: unresolved external symbol __imp__glIndexi@4 referenced in function "void __cdecl drawScene(void)" (?drawScene@@YAXXZ)
1>main.obj : error LNK2019: unresolved external symbol __imp__glClear@4 referenced in function "void __cdecl drawScene(void)" (?drawScene@@YAXXZ)
1>***\OpenGL Test\Debug\OpenGL Test.exe : fatal error LNK1120: 26 unresolved externals
1>Build log was saved at "file://***\OpenGL Test\OpenGL Test\Debug\BuildLog.htm"
1>OpenGL Test - 27 error(s), 1 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Образно сказать "не находит OpenGL в проэкте". На самом деле не находит экспортированные функции OpenGL в проэкте. Нужно просто подключить библиотеки.
Project->Project Properties->Configuration Properties->Linker->Input->Additional Dependencies
Пишем ручками "OpenGL32.lib Glu32.lib"
Ok
Cнова Build (F7)
1>------ Build started: Project: OpenGL Test, Configuration: Debug Win32 ------
1>Linking...
1>Embedding manifest...
1>Build log was saved at "file://***\OpenGL Test\OpenGL Test\Debug\BuildLog.htm"
1>OpenGL Test - 0 error(s), 0 warning(s)
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
Тада! Успешно (succeeded).
Запускаем (F5 на отладку).
Видим окно с безумно вертящейся картинкой. Это первое что исправим - скорость.
GLvoid drawScene(GLvoid) //из названия функции логично предположить отрисовка сцены
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); //очистить экран и буфер глубины (буфер глубины используется для того чтобы рисовать только поверх
glPushMatrix(); //запомнить текущюю ориентацию
latitude += latinc; //увеличить на latinc широту (latitude increment скорее всего)
longitude += longinc; //увеличить на longinc долготу (longitude increment скорее всего)
polarView( radius, 0, latitude, longitude ); //полярный вид(меняет ориентацию текущюю) (функция которая описана выше)
glIndexi(RED_INDEX); //сменить цвет на красный (INDEX потому что это выбор цвета из палитры)
glCallList(CONE); //вызвать список с названием CONE (который рисует конус).
glIndexi(BLUE_INDEX); //сменить цвет на синий (INDEX потому что это выбор цвета из палитры)
glCallList(GLOBE); //вызвать список с названием GLOBE (который рисует шар).
glIndexi(GREEN_INDEX); //сменить цвет на зелёный (INDEX потому что это выбор цвета из палитры)
glPushMatrix(); //запомнить текущюю ориентацию
glTranslatef(0.8F, -0.65F, 0.0F); //сдвиг всего (всех объектов...) на 0.8 по X, на -0.65 по Y...
glRotatef(30.0F, 1.0F, 0.5F, 1.0F); //поворот всего на 30 градусов вокруг вектора (1.0 ; 0.5 ; 1.0)
glCallList(CYLINDER); //вызвать список с названием CYLINDER (который рисует цилиндр).
glPopMatrix(); //вспомнить предыдущюю запомненную ориентацию
glPopMatrix(); //вспомнить ещё раньше запомненную ориентацию
SWAPBUFFERS; //поменять местами буферы, где буферы подразумеваются: буфер экрана который показывается, и буфер невидимый в который скоро будет писаться. Чтобы не мелькало, сначала всё отрисовывается в памяти, а потом уже показывается.
}
Заметим что latitude += latinc; выполняется в каждый вызов функции drawScene. А функция drawScene вызывается в
while (1) {
/*
* Process all pending messages
*/
//Напрашивается вопрос что за сообщения?! А сообщения которые операционная система, а точнее система, которая работает с окошками, шлёт когда окна создаются, мышь на них нажимает, и вообще когда происходят какие-то события.
while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) == TRUE) //пока (взять сообщение(но не удалять)) - возможно, тогда делать:
{ //раз мы сюда зашли, значит взять сообщение возможно (то есть мы уверенны что есть что взять и функция GetMessage не будет ждать сообщение т.к. оно итак есть)
if (GetMessage(&msg, NULL, 0, 0) ) //берём сообщение, тем самым его удаляя (так устроена функция)
{
TranslateMessage(&msg); //передаём сообщение адресату
DispatchMessage(&msg); //так и незнаю что это делает ^^ но оно надо (наверно удаляет сообщение)
} else { //если не смогли взять сообщение значит произошла ошибка
return TRUE; // выйдем из программы с кодом выхода 1
}
}
//раз мы тут, значит? значит условие while (пока) не верно, что означает что нету сообщений в данный момент окну, то есть оно простаивает.
drawScene(); //раз делать нечего можно отрисовать сцену.
}
Вывод какой? То что drawScene() вызывается в любой момент когда делать нечего. А делать нечего может быть очень долго, а комп может быть очень шустрым, вот и скорость вращения бешенная.
Сразу приходит три варьянта как можно поправить (в зависимости чего хотим). Рассмотрим все
1) Просто после отрисовки сказать пусть "отдохнёт".
Делается простым добавлением Sleep(10) (10 милисекунд) после drawScene. Но тогда и сообщения будет отражать с таймаутом 10 милисекунд, что мало заметно, и отрисовка будет не быстрее 100 фпс, но а вдруг комп медленный, тогда будет ужасно лагать, а если не спать может бы и не лагало. Не тру решение.
2) Ограничить FPS. Опишу как сделать не точное ограничение FPS.
Есть такая функция GetTickCount() возвращяет кол-во милисекунд с запуска системы. Заведём переменную, которая будет означать последнее время отрисовки, назовём lastdraw. Теперь будем отрисовывать только в том случае если текущее время больше чем lastdraw+10, а обновлять lastdraw только если действительно отрисовываем. Время отрисовки тоже может быть солидное, поэтому будем обновлять lastdraw значение перед отрисовкой.
Итого теперь вместо
drawScene();
будет
static int lastdraw=0; //static чтобы переменная сохраняла значение даже после выхода из функции.
if (lastdraw+10<=GetTickCount()) //если текущее время больше либо равно чем время старой отрисовки + 10 милисекунд
{
lastdraw=GetTickCount(); //обновим время старой отрисовки
drawScene(); //отрисуем
}Вроде всё хорошо, только есть незаметные грабли. Если посмотреть какие значения может выдавать GetTickCount() то обнаружится что не до милисекунд, а с каким-то шагом примерно равным 15..20. Поэтому таким таймером не обеспечить допустим 60 FPS когда надо чётко 16.666... ждать.
3) Вместо ограничений на отрисовку, использовать масштабирование пройденного времени. То есть прибавлять не latinc а latinc*time где time это пройденное время с последней отрисовки, а latinc инкремент в одну милисекунду.
Тогда это будет выгледить так:
а) GLvoid drawScene(GLvoid) будет теперь GLvoid drawScene(GLdouble delay)
б) Вместо latitude += latinc; будет теперь latitude += latinc * delay / 10; (поделить на 10 чтобы как 100 фпс было)
в) Вместо longitude += longinc; будет теперь longitude += longinc * delay / 10; (поделить на 10 чтобы как 100 фпс было)
Я сделал второй варьянт покачто.
Добавлено позже:Следуйщее с чем охото разобраться - в сэмпле сделаны выборы цветов, а всё белое. Не хочу разбираться с палитрами, сделаю всё в RGB.
Для этого пиксель формат надо RGBA то есть
ppfd->iPixelType = PFD_TYPE_COLORINDEX;
ppfd->cColorBits = 8;
заменить на
ppfd->iPixelType = PFD_TYPE_RGBA;
ppfd->cColorBits = 32;
Теперь у нас нету индексов в палитре, так что и цвет которым заполнять тоже надо указать не через индекс.
glClearIndex( (GLfloat)BLACK_INDEX);
заменить на
glClearColor(0,0,0,1);
Цвета объектов:
glIndexi(RED_INDEX);
glIndexi(BLUE_INDEX);
glIndexi(GREEN_INDEX);
теперь
glColor3f(1,0,0);
glColor3f(0,0,1);
glColor3f(0,1,0);
С цветами разобрались, теперь охото чтобы сферы, пирамиды, были обьёмные (то есть с затемнениями на поверхности)