| Разработка и ромхакинг > Ромхакинг и программирование |
| VC++ & OpenGL |
| (1/1) |
| r57shell:
Для тех кому нехватает возможностей/производительности в каких-то движках например GameMaker... Для начала вводим в MSDN "OpenGL" или в гугле "OpenGL site:msdn.microsoft.com" (без ковычек). Я буду описывать всё по ссылкам на online версии msdn. Сначала попадаем на OpenGL Start Page И смотрим примеры: 1) Портабельный исходник: /* * Example of an X Window System OpenGL program. * OpenGL code is taken from auxdemo.c in the Platform SDK */ #include <GL/glx.h> #include <GL/gl.h> #include <GL/glu.h> #include <X11/keysym.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include <stdio.h> /* X globals, defines, and prototypes */ Display *dpy; Window glwin; static int attributes[] = {GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, None}; #define SWAPBUFFERS glXSwapBuffers(dpy, glwin) #define BLACK_INDEX 0 #define RED_INDEX 1 #define GREEN_INDEX 2 #define BLUE_INDEX 4 #define WIDTH 300 #define HEIGHT 200 /* OpenGL globals, defines, and prototypes */ GLfloat latitude, longitude, latinc, longinc; GLdouble radius; #define GLOBE 1 #define CYLINDER 2 #define CONE 3 GLvoid resize(GLsizei, GLsizei); GLvoid initializeGL(GLsizei, GLsizei); GLvoid drawScene(GLvoid); void polarView( GLdouble, GLdouble, GLdouble, GLdouble); static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg) { if ((e->type == MapNotify) && (e->xmap.window == (Window)arg)) { return GL_TRUE; } return GL_FALSE; } void main(int argc, char **argv) { XVisualInfo *vi; Colormap cmap; XSetWindowAttributes swa; GLXContext cx; XEvent event; GLboolean needRedraw = GL_FALSE, recalcModelView = GL_TRUE; int dummy; dpy = XOpenDisplay(NULL); if (dpy == NULL){ fprintf(stderr, "could not open display\n"); exit(1); } if(!glXQueryExtension(dpy, &dummy, &dummy)){ fprintf(stderr, "could not open display"); exit(1); } /* find an OpenGL-capable Color Index visual with depth buffer */ vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributes); if (vi == NULL) { fprintf(stderr, "could not get visual\n"); exit(1); } /* create an OpenGL rendering context */ cx = glXCreateContext(dpy, vi, None, GL_TRUE); if (cx == NULL) { fprintf(stderr, "could not create rendering context\n"); exit(1); } /* create an X colormap since probably not using default visual */ cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone); swa.colormap = cmap; swa.border_pixel = 0; swa.event_mask = ExposureMask | KeyPressMask | StructureNotifyMask; glwin = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, WIDTH, HEIGHT, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask, &swa); XSetStandardProperties(dpy, glwin, "xogl", "xogl", None, argv, argc, NULL); glXMakeCurrent(dpy, glwin, cx); XMapWindow(dpy, glwin); XIfEvent(dpy, &event, WaitForMapNotify, (char *)glwin); initializeGL(WIDTH, HEIGHT); resize(WIDTH, HEIGHT); /* Animation loop */ while (1) { KeySym key; while (XPending(dpy)) { XNextEvent(dpy, &event); switch (event.type) { case KeyPress: XLookupString((XKeyEvent *)&event, NULL, 0, &key, NULL); switch (key) { case XK_Left: longinc += 0.5; break; case XK_Right: longinc -= 0.5; break; case XK_Up: latinc += 0.5; break; case XK_Down: latinc -= 0.5; break; } break; case ConfigureNotify: resize(event.xconfigure.width, event.xconfigure.height); break; } } drawScene(); } } /* OpenGL code */ GLvoid resize( GLsizei width, GLsizei height ) { GLfloat aspect; glViewport( 0, 0, width, height ); aspect = (GLfloat) width / height; glMatrixMode( GL_PROJECTION ); glLoadIdentity(); gluPerspective( 45.0, aspect, 3.0, 7.0 ); glMatrixMode( GL_MODELVIEW ); } GLvoid createObjects() { GLUquadricObj *quadObj; glNewList(GLOBE, GL_COMPILE); quadObj = gluNewQuadric (); gluQuadricDrawStyle (quadObj, GLU_LINE); gluSphere (quadObj, 1.5, 16, 16); glEndList(); glNewList(CONE, GL_COMPILE); quadObj = gluNewQuadric (); gluQuadricDrawStyle (quadObj, GLU_FILL); gluQuadricNormals (quadObj, GLU_SMOOTH); gluCylinder(quadObj, 0.3, 0.0, 0.6, 15, 10); glEndList(); glNewList(CYLINDER, GL_COMPILE); glPushMatrix (); glRotatef ((GLfloat)90.0, (GLfloat)1.0, (GLfloat)0.0, (GLfloat)0.0); glTranslatef ((GLfloat)0.0, (GLfloat)0.0, (GLfloat)-1.0); quadObj = gluNewQuadric (); gluQuadricDrawStyle (quadObj, GLU_FILL); gluQuadricNormals (quadObj, GLU_SMOOTH); gluCylinder (quadObj, 0.3, 0.3, 0.6, 12, 2); glPopMatrix (); glEndList(); } GLvoid initializeGL(GLsizei width, GLsizei height) { GLfloat maxObjectSize, aspect; GLdouble near_plane, far_plane; glClearIndex( (GLfloat)BLACK_INDEX); glClearDepth( 1.0 ); glEnable(GL_DEPTH_TEST); glMatrixMode( GL_PROJECTION ); aspect = (GLfloat) width / height; gluPerspective( 45.0, aspect, 3.0, 7.0 ); glMatrixMode( GL_MODELVIEW ); near_plane = 3.0; far_plane = 7.0; maxObjectSize = 3.0F; radius = near_plane + maxObjectSize/2.0; latitude = 0.0F; longitude = 0.0F; latinc = 6.0F; longinc = 2.5F; createObjects(); } void polarView(GLdouble radius, GLdouble twist, GLdouble latitude, GLdouble longitude) { glTranslated(0.0, 0.0, -radius); glRotated(-twist, 0.0, 0.0, 1.0); glRotated(-latitude, 1.0, 0.0, 0.0); glRotated(longitude, 0.0, 0.0, 1.0); } GLvoid drawScene(GLvoid) { glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glPushMatrix(); latitude += latinc; longitude += longinc; polarView( radius, 0, latitude, longitude ); glIndexi(RED_INDEX); glCallList(CONE); glIndexi(BLUE_INDEX); glCallList(GLOBE); glIndexi(GREEN_INDEX); glPushMatrix(); glTranslatef(0.8F, -0.65F, 0.0F); glRotatef(30.0F, 1.0F, 0.5F, 1.0F); glCallList(CYLINDER); glPopMatrix(); glPopMatrix(); SWAPBUFFERS; } 2) Исходник портированный под Win32 /* * Example of a Win32 OpenGL program. * The OpenGL code is the same as that used in * the X Window System sample */ #include <windows.h> #include <GL/gl.h> #include <GL/glu.h> /* Windows globals, defines, and prototypes */ CHAR szAppName[]="Win OpenGL"; HWND ghWnd; HDC ghDC; HGLRC ghRC; #define SWAPBUFFERS SwapBuffers(ghDC) #define BLACK_INDEX 0 #define RED_INDEX 13 #define GREEN_INDEX 14 #define BLUE_INDEX 16 #define WIDTH 300 #define HEIGHT 200 LONG WINAPI MainWndProc (HWND, UINT, WPARAM, LPARAM); BOOL bSetupPixelFormat(HDC); /* OpenGL globals, defines, and prototypes */ GLfloat latitude, longitude, latinc, longinc; GLdouble radius; #define GLOBE 1 #define CYLINDER 2 #define CONE 3 GLvoid resize(GLsizei, GLsizei); GLvoid initializeGL(GLsizei, GLsizei); GLvoid drawScene(GLvoid); void polarView( GLdouble, GLdouble, GLdouble, GLdouble); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG msg; WNDCLASS wndclass; /* Register the frame class */ wndclass.style = 0; wndclass.lpfnWndProc = (WNDPROC)MainWndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (hInstance, szAppName); wndclass.hCursor = LoadCursor (NULL,IDC_ARROW); wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wndclass.lpszMenuName = szAppName; wndclass.lpszClassName = szAppName; if (!RegisterClass (&wndclass) ) return FALSE; /* Create the frame */ ghWnd = CreateWindow (szAppName, "Generic OpenGL Sample", WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, WIDTH, HEIGHT, NULL, NULL, hInstance, NULL); /* make sure window was created */ if (!ghWnd) return FALSE; /* show and update main window */ ShowWindow (ghWnd, nCmdShow); UpdateWindow (ghWnd); /* animation loop */ while (1) { /* * Process all pending messages */ while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) == TRUE) { if (GetMessage(&msg, NULL, 0, 0) ) { TranslateMessage(&msg); DispatchMessage(&msg); } else { return TRUE; } } drawScene(); } } /* main window procedure */ LONG WINAPI MainWndProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { LONG lRet = 1; PAINTSTRUCT ps; RECT rect; switch (uMsg) { case WM_CREATE: ghDC = GetDC(hWnd); if (!bSetupPixelFormat(ghDC)) PostQuitMessage (0); ghRC = wglCreateContext(ghDC); wglMakeCurrent(ghDC, ghRC); GetClientRect(hWnd, &rect); initializeGL(rect.right, rect.bottom); break; case WM_PAINT: BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); break; case WM_SIZE: GetClientRect(hWnd, &rect); resize(rect.right, rect.bottom); break; case WM_CLOSE: if (ghRC) wglDeleteContext(ghRC); if (ghDC) ReleaseDC(hWnd, ghDC); ghRC = 0; ghDC = 0; DestroyWindow (hWnd); break; case WM_DESTROY: if (ghRC) wglDeleteContext(ghRC); if (ghDC) ReleaseDC(hWnd, ghDC); PostQuitMessage (0); break; case WM_KEYDOWN: switch (wParam) { case VK_LEFT: longinc += 0.5F; break; case VK_RIGHT: longinc -= 0.5F; break; case VK_UP: latinc += 0.5F; break; case VK_DOWN: latinc -= 0.5F; break; } default: lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); break; } return lRet; } BOOL bSetupPixelFormat(HDC hdc) { PIXELFORMATDESCRIPTOR pfd, *ppfd; int pixelformat; ppfd = &pfd; ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR); ppfd->nVersion = 1; ppfd->dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; ppfd->dwLayerMask = PFD_MAIN_PLANE; ppfd->iPixelType = PFD_TYPE_COLORINDEX; ppfd->cColorBits = 8; ppfd->cDepthBits = 16; ppfd->cAccumBits = 0; ppfd->cStencilBits = 0; pixelformat = ChoosePixelFormat(hdc, ppfd); if ( (pixelformat = ChoosePixelFormat(hdc, ppfd)) == 0 ) { MessageBox(NULL, "ChoosePixelFormat failed", "Error", MB_OK); return FALSE; } if (SetPixelFormat(hdc, pixelformat, ppfd) == FALSE) { MessageBox(NULL, "SetPixelFormat failed", "Error", MB_OK); return FALSE; } return TRUE; } /* OpenGL code */ GLvoid resize( GLsizei width, GLsizei height ) { GLfloat aspect; glViewport( 0, 0, width, height ); aspect = (GLfloat) width / height; glMatrixMode( GL_PROJECTION ); glLoadIdentity(); gluPerspective( 45.0, aspect, 3.0, 7.0 ); glMatrixMode( GL_MODELVIEW ); } GLvoid createObjects() { GLUquadricObj *quadObj; glNewList(GLOBE, GL_COMPILE); quadObj = gluNewQuadric (); gluQuadricDrawStyle (quadObj, GLU_LINE); gluSphere (quadObj, 1.5, 16, 16); glEndList(); glNewList(CONE, GL_COMPILE); quadObj = gluNewQuadric (); gluQuadricDrawStyle (quadObj, GLU_FILL); gluQuadricNormals (quadObj, GLU_SMOOTH); gluCylinder(quadObj, 0.3, 0.0, 0.6, 15, 10); glEndList(); glNewList(CYLINDER, GL_COMPILE); glPushMatrix (); glRotatef ((GLfloat)90.0, (GLfloat)1.0, (GLfloat)0.0, (GLfloat)0.0); glTranslatef ((GLfloat)0.0, (GLfloat)0.0, (GLfloat)-1.0); quadObj = gluNewQuadric (); gluQuadricDrawStyle (quadObj, GLU_FILL); gluQuadricNormals (quadObj, GLU_SMOOTH); gluCylinder (quadObj, 0.3, 0.3, 0.6, 12, 2); glPopMatrix (); glEndList(); } GLvoid initializeGL(GLsizei width, GLsizei height) { GLfloat maxObjectSize, aspect; GLdouble near_plane, far_plane; glClearIndex( (GLfloat)BLACK_INDEX); glClearDepth( 1.0 ); glEnable(GL_DEPTH_TEST); glMatrixMode( GL_PROJECTION ); aspect = (GLfloat) width / height; gluPerspective( 45.0, aspect, 3.0, 7.0 ); glMatrixMode( GL_MODELVIEW ); near_plane = 3.0; far_plane = 7.0; maxObjectSize = 3.0F; radius = near_plane + maxObjectSize/2.0; latitude = 0.0F; longitude = 0.0F; latinc = 6.0F; longinc = 2.5F; createObjects(); } void polarView(GLdouble radius, GLdouble twist, GLdouble latitude, GLdouble longitude) { glTranslated(0.0, 0.0, -radius); glRotated(-twist, 0.0, 0.0, 1.0); glRotated(-latitude, 1.0, 0.0, 0.0); glRotated(longitude, 0.0, 0.0, 1.0); } GLvoid drawScene(GLvoid) { glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glPushMatrix(); latitude += latinc; longitude += longinc; polarView( radius, 0, latitude, longitude ); glIndexi(RED_INDEX); glCallList(CONE); glIndexi(BLUE_INDEX); glCallList(GLOBE); glIndexi(GREEN_INDEX); glPushMatrix(); glTranslatef(0.8F, -0.65F, 0.0F); glRotatef(30.0F, 1.0F, 0.5F, 1.0F); glCallList(CYLINDER); glPopMatrix(); glPopMatrix(); SWAPBUFFERS; } Оба выглядят ужасно (для тех кто видел только консольные приложения на С++, или вообще не видел код на С++). Работать будем со вторым. Почему? Потому что я с первым не работал (зачем я буду обучать тому что не знаю?). Для начала как заставить пример работать? Microsoft Visual Studio 2005 например или VC6.0 File->New->Project->Visual C++ -> Win32->Win32 Project Пишем имя (например: OpenGL Test) Ok, Next, windows application empty project Finish Затем в папке Source Files создаём исполняемый файл (LMOUSE_BUTTON->Add->New Item->Visual C++ -> Code -> C++ File (.cpp) Пишем имя (например: main.cpp) Вставляем исходник примера (второго) Сохраняем файл, и пытаемся скомпилировать (Build->Build Solution или просто F7) |
| r57shell:
У меня выдало: 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); С цветами разобрались, теперь охото чтобы сферы, пирамиды, были обьёмные (то есть с затемнениями на поверхности) |
| HoRRoR:
Не могу понять суть темы... --- Цитата ---С цветами разобрались, теперь охото чтобы сферы, пирамиды, были обьёмные (то есть с затемнениями на поверхности) --- Конец цитаты --- Используй освещение. |
| r57shell:
Чтобы затенять объекты, нужно указать освещение, и матерьял объектам: после строки: glEnable(GL_DEPTH_TEST); вставим: glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); То есть включим освещение, и первый источник света - они нумеруются с нуля. Если теперь запустить и посмотреть, будет серая сфера, цилиндр, конус, это потому что не настроили матерьял. Для того чтобы цвет матерьяла AMBIENT и DIFFUSE брались из текущего цвета включим эту опцию, и настроим, дописав после включения освещения следуйщее: glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); Меня например задолбало что всё постоянно вращается, хочу сам управлять. Для этого отключим старый контроль вращения. Убить функцию вращения void polarView(GLdouble radius, GLdouble twist, GLdouble latitude, GLdouble longitude) { glTranslated(0.0, 0.0, -radius); glRotated(-twist, 0.0, 0.0, 1.0); glRotated(-latitude, 1.0, 0.0, 0.0); glRotated(longitude, 0.0, 0.0, 1.0); } Вводим в поиске "polarView" для устранения любых напоминаний о ней, и смотрим, теперь чёрный экран, видимо вид неправильно настроен )). Из удалённой функции следует что она отодвигает всё на radius, и всяко вращает. Значит надо отодвинуть самим теперь. После longitude += longinc; вставим glTranslated(0.0, 0.0, -radius); Во, теперь всё стоит на месте, и всё видно :) Прогресс. Теперь надо удалить остатки управления старого вращения это всё что связанно с longinc, longitude, latitude, latinc. То есть GLfloat latitude, longitude, latinc, longinc; case WM_KEYDOWN: switch (wParam) { case VK_LEFT: longinc += 0.5F; break; case VK_RIGHT: longinc -= 0.5F; break; case VK_UP: latinc += 0.5F; break; case VK_DOWN: latinc -= 0.5F; break; } latitude = 0.0F; longitude = 0.0F; latinc = 6.0F; longinc = 2.5F; latitude += latinc; longitude += longinc; Выгледит уныло когда всё стоит, и никакой динамики, но это покачто то, на чём остановлюсь и выложу промежуточный исходник. А пока отвлекусь. тупокопипаст того что уже писал когда-то, кстати дефолтный OpenGL юзать наверно уже не модно, сейчас вышел v4.0Теперь немного о том, как работает видеокарта вообще. Конечно сейчас появились новые технологии которые я не знаю, но надеюсь то, что я здесь написал, ещё актуально. Видео карта работает как мастерский художник, то есть она рисует одно, поверх другого, или добавляет некоторые штрихи, причём в том порядке как вы ей скажете. То есть, если вы скажете сначала нарисовать человека стоящего за деревом (вы человека не видите из-за дерева), а затем скажете рисовать дерево, то видеокарта нарисует поверх человека дерево. А если на оборот сначала дерево, а потом человека, то видеокарта поймёт, что человека не надо уже рисовать, так как его невидно (эти проверки настраиваются). На этом основана одна из техник – сортировка объектов спереди назад, чтобы потом не рисовать то, что невидно. Просто есть народ который думает что видеокарта производит Raytrace в сцене ))). Видеокарта не знает ни какого трёхмерного измерения, всё, что видеокарта знает, это большое количество алгебраических операций, и может выставлять пиксель в нужный цвет, ещё, ей вбита по default-у последовательность алгебраических манипуляций чтобы отрисовать на экране polygon. Сначала матрицы WORLD,VIEW,PROJECTION перемножаются в соответствующем порядке, а потом умножаются на все вершины полигона, после чего идёт процесс расторизации, и проверок для каждого пикселя нужно или нет рисовать. Эту последовательность можно настраивать, флагами, а почти полностью менять её позволяют шейдеры. Ещё хочу отметить: текст видеокарта рисует как текстуру на квадрате (два треугольника), поэтому от текста зависит скорость прорисовки. Конечно можно блокировать буфер в котором лежит вся картинка, которая потом будет выведена на экран, и рисовать там текст но это скорее всего будет дольше. Аналогично лучше текст первым выводить, чтобы потом нерисовать то что за ним. |
| Навигация |
| Главная страница сообщений |