Renderowanie Muchy w OpenGL
Program stworzony razem ze studentami w ramach zajęć z przedmiotu Zaawansowane Techniki Programowania w Multimediach w semestrze 2017/2018 Mucha.
/*// _ _ _ | | __ _ _ __ ___ | |__ _-(")- | | / _` | '_ ` _ \| '_ \ `%%%%% | |__| (_| | | | |_| | |_) | _ // \\ |_____\__,_|_| |_| |_|_.__/_| |__ ___ | | / _` | '_ \/ __| | |__| (_| | |_) \__ \ 2018-05-24 |_____\__,_|_.__/|___/ //*/ #include <windows.h> #include <gl/glew.h> //#include <gl/gl.h> //#include <gl/glu.h> #include <stdio.h> #include <math.h> #include "res.h" #define IDT_REDRAW_FRAME 2018 GLuint uiTextureEyeID; GLuint uiTextureBodyID; </pre> <!--more--> <pre escaped="true" lang="cpp" line="24"> unsigned char* ReadBmpFromFile(const char* szFileName, int &riWidth, int &riHeight) { BITMAPFILEHEADER bfh; BITMAPINFOHEADER bih; int i, j, h, v, lev, l, ls; unsigned char* buff = NULL; unsigned char* p_palette = NULL; unsigned short n_colors = 0; unsigned char* pRGBBuffer=NULL; FILE* hfile; fopen_s(&hfile,szFileName, "rb"); if (hfile != NULL) { fread(&bfh, sizeof(bfh), 1, hfile); if (!(bfh.bfType != 0x4d42 || (bfh.bfOffBits < (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER))))) { fread(&bih, sizeof(bih), 1, hfile); v = bih.biWidth; h = bih.biHeight; lev = bih.biBitCount; riWidth = v; riHeight = h; pRGBBuffer = new unsigned char[riWidth*riHeight * 3]; //Zaalokowanie odpowiedniego buffora obrazu //Załaduj Palete barw jesli jest if ((lev == 1) || (lev == 4) || (lev == 8)) { n_colors = 1 << lev; p_palette = new unsigned char[4 * n_colors]; fread(p_palette, 4 * n_colors, 1, hfile); } fseek(hfile, bfh.bfOffBits, SEEK_SET); buff = new unsigned char[v * 4]; switch (lev) { case 1: //Nie obsługiwane break; case 4: //nie Obsługiwane break; case 8: //Skala szarości ls = (v + 3) & 0xFFFFFFFC; for (j = (h - 1); j >= 0; j--) { fread(buff, ls, 1, hfile); for (i = 0, l = 0; i<v; i++) { pRGBBuffer[((j*riWidth) + i) * 3 + 2] = p_palette[(buff[i] << 2) + 2];//R pRGBBuffer[((j*riWidth) + i) * 3 + 1] = p_palette[(buff[i] << 2) + 1];//G pRGBBuffer[((j*riWidth) + i) * 3 + 0] = p_palette[(buff[i] << 2) + 0];//B } }; break; case 24: //bitmapa RGB ls = (v * 3 + 3) & 0xFFFFFFFC; for (j = (h - 1); j >= 0; j--) { //x_fread(hfile,buff,ls); fread(buff, ls, 1, hfile); for (i = 0, l = 0; i<v; i++, l += 3) { pRGBBuffer[((j*riWidth) + i) * 3 + 2] = buff[l + 0]; pRGBBuffer[((j*riWidth) + i) * 3 + 1] = buff[l + 1]; pRGBBuffer[((j*riWidth) + i) * 3 + 0] = buff[l + 2]; }; }; break; case 32: // RGBA bitmap for (j = (h - 1); j >= 0; j--) { fread(buff, v * 4, 1, hfile); for (i = 0, l = 0; i<v; i++, l += 4) { pRGBBuffer[((j*riWidth) + i) * 3 + 0] = buff[l + 0]; pRGBBuffer[((j*riWidth) + i) * 3 + 1] = buff[l + 1]; pRGBBuffer[((j*riWidth) + i) * 3 + 2] = buff[l + 2]; } }; break; }; delete buff; if (p_palette) delete p_palette; } } return pRGBBuffer; } void DrawAxes(float a) { glPushMatrix(); glScalef(a, a, a); glBegin(GL_LINES); glColor3f(0.0, 0.0, 1.0); glVertex3f(-10, 0, 0); glVertex3f(+10, 0, 0); glColor3f(0.0, 1.0, 0.0); glVertex3f(0, -10, 0); glVertex3f(0, +10, 0); glColor3f(1.0, 0.0, 0.0); glVertex3f(0, 0, -10); glVertex3f(0, 0, +10); glEnd(); glPopMatrix(); } void DrawBox(float a, float b, float c) { glPushMatrix(); glScalef(a/2, b/2, c/2); glBegin(GL_QUADS); glNormal3i(0, -1, 0); glTexCoord2f(0.0, 0.0); glVertex3i(-1, -1, -1); glTexCoord2f(0.0, 1.0); glVertex3i(-1, -1, +1); glTexCoord2f(1.0, 1.0); glVertex3i(+1, -1, +1); glTexCoord2f(1.0, 0.0); glVertex3i(+1, -1, -1); glNormal3i(0, +1, 0); glTexCoord2f(0.0, 0.0); glVertex3i(-1, +1, -1); glTexCoord2f(0.0, 1.0); glVertex3i(-1, +1, +1); glTexCoord2f(1.0, 1.0); glVertex3i(+1, +1, +1); glTexCoord2f(1.0, 0.0); glVertex3i(+1, +1, -1); glNormal3i(-1, 0, 0); glTexCoord2f(0.0, 0.0); glVertex3i(-1, -1, -1); glTexCoord2f(0.0, 1.0); glVertex3i(-1, -1, +1); glTexCoord2f(1.0, 1.0); glVertex3i(-1, +1, +1); glTexCoord2f(1.0, 0.0); glVertex3i(-1, +1, -1); glNormal3i(+1, 0, 0); glTexCoord2f(0.0, 0.0); glVertex3i(+1, -1, -1); glTexCoord2f(0.0, 1.0); glVertex3i(+1, -1, +1); glTexCoord2f(1.0, 1.0); glVertex3i(+1, +1, +1); glTexCoord2f(1.0, 0.0); glVertex3i(+1, +1, -1); glNormal3i(0, 0, -1); glTexCoord2f(0.0, 0.0); glVertex3i(-1, -1, -1); glTexCoord2f(0.0, 1.0); glVertex3i(-1, +1, -1); glTexCoord2f(1.0, 1.0); glVertex3i(+1, +1, -1); glTexCoord2f(1.0, 0.0); glVertex3i(+1, -1, -1); glNormal3i(0, 0, +1); glTexCoord2f(0.0, 0.0); glVertex3i(-1, -1, +1); glTexCoord2f(0.0, 1.0); glVertex3i(-1, +1, +1); glTexCoord2f(1.0, 1.0); glVertex3i(+1, +1, +1); glTexCoord2f(1.0, 0.0); glVertex3i(+1, -1, +1); glEnd(); glPopMatrix(); } void DrawFly(float fScale) { glPushMatrix(); glScalef(fScale, fScale, fScale); //Body of the fly glColor3f(0.2, 0.2, 0.2); DrawBox(2.0, 1.0, 1.5); //Legs for(int i=0;i<3;i++) for (int j = 0; j < 2; j++) { glPushMatrix(); glTranslatef(-1.0+(2.0/5.0/2.0)+i*(2.0- (2.0 / 5.0))/2, -0.5-0.5/2, -0.75+(1.5/3/2)+j*(1.5-1.5/3)/1); DrawBox(2.0 / 5.0, 0.5, 1.5 / 3.0); glPopMatrix(); } //Eyes glColor3f(1.0, 1.0, 1.0); glBindTexture(GL_TEXTURE_2D, uiTextureEyeID); for (int i = 0; i < 2; i++) { glPushMatrix(); glTranslatef(-1.0,0.5+0.6,-0.75+i*1.5); DrawBox(1.4, 1.4, 1.4); glPopMatrix(); } glBindTexture(GL_TEXTURE_2D, 0); //Nose glColor3f(0.2, 0.2, 0.2); glPushMatrix(); glTranslatef(-1.0-0.75, 0.2, 0.0); DrawBox(1.5, 0.2, 0.2); glPopMatrix(); //Wings glColor3f(0.8, 0.8, 1.0); for (int i = -1; i < 2; i+=2) { glPushMatrix(); glTranslatef(0.9, 0.5, i*0.70); glRotatef(- i * 30, 0, 1, 0); glTranslatef(-1.0, 0, 0); glRotatef(7.5*sin(GetTickCount()/100.0)+7.5, 0, 0, 1); glTranslatef(1.0, 0, 0); DrawBox(2.0, 0.2, 1.4); glPopMatrix(); } glPopMatrix(); } void DrawFrame() { glClearColor(0.1, 0.1, 0.1, 0.5); glClearDepth(1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glTranslatef(0.0, -1.0, -10.0); static float fAngle = 0.0; fAngle += 1; glRotatef(fAngle, 0, 1, 0); DrawAxes(1.0); glColor3f(1.0, 1.0, 1.0); glEnable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); //DrawBox(2.0, 1.0, 1.0); DrawFly(1.0); } void InitOpenGL() { glewExperimental = GL_TRUE; GLenum err = glewInit(); if (err != GLEW_OK) { char strMsg[1000]; printf_s(strMsg, "%s", glewGetErrorString(err)); MessageBox(0, (LPCWSTR)strMsg, TEXT("Error Glew"), MB_OK); } glEnable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glShadeModel(GL_SMOOTH); } void InitTexture() { int iWidth; int iHeight; unsigned char* pImageData = ReadBmpFromFile("..\\res\\eye.bmp", iWidth, iHeight); glActiveTexture(GL_TEXTURE0); glGenTextures(1, &uiTextureEyeID); glBindTexture(GL_TEXTURE_2D, uiTextureEyeID); //glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, iWidth, iHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, pImageData); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); //glGenerateMipmap(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); //glGenerateMipmap(GL_TEXTURE_2D); delete[] pImageData; glShadeModel(GL_FLAT); } INT_PTR OnWmClose( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { DestroyWindow(hwndDlg); PostQuitMessage(0); return TRUE; } INT_PTR OnWmDestroy( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { HGLRC hglrc = wglGetCurrentContext(); HDC hdc = wglGetCurrentDC(); wglMakeCurrent(NULL, NULL); wglDeleteContext(hglrc); ReleaseDC(hwndDlg,hdc); KillTimer(hwndDlg, IDT_REDRAW_FRAME); PostQuitMessage(0); return TRUE; } INT_PTR OnWmInitDialog( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { HDC hdc; HGLRC hglrc; hdc = GetDC(hwndDlg); PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL, PFD_TYPE_RGBA, 24, 0,0,0,0,0,0, 0,0,0, 0,0,0,0, 32, 0,0, PFD_MAIN_PLANE, 0,0,0,0 }; int iPixelFormat = ChoosePixelFormat(hdc, &pfd); SetPixelFormat(hdc, iPixelFormat, &pfd); if (hglrc = wglCreateContext(hdc)) { bool bHaveCurrentRC = wglMakeCurrent(hdc, hglrc); } InitOpenGL(); InitTexture(); return TRUE; } INT_PTR OnWmSize( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { int iWidth = LOWORD(lParam); int iHeight = HIWORD(lParam); if (iHeight == 0) iHeight++; glViewport(0, 0, iWidth, iHeight); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0, ((float)iWidth) / iHeight, 0.1, 100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); return TRUE; } INT_PTR OnWmTimer( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (wParam) { case IDT_REDRAW_FRAME: DrawFrame(); HDC hdc = wglGetCurrentDC(); glFlush(); SwapBuffers(hdc); break; } return TRUE; } INT_PTR CALLBACK DialogProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: return OnWmInitDialog(hwndDlg, uMsg, wParam, lParam); case WM_CLOSE: return OnWmClose(hwndDlg, uMsg, wParam, lParam); case WM_DESTROY: return OnWmDestroy(hwndDlg, uMsg, wParam, lParam); case WM_SIZE: return OnWmSize(hwndDlg, uMsg, wParam, lParam); case WM_TIMER: return OnWmTimer(hwndDlg, uMsg, wParam, lParam); } return FALSE; } int CALLBACK WinMain( _In_ HINSTANCE hInstance, _In_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow ) { HWND hwndMainDialog = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogProc); ShowWindow(hwndMainDialog,SW_SHOW); SetTimer(hwndMainDialog, IDT_REDRAW_FRAME, 1000 / 25, NULL); //Main loop MSG uMsg; BOOL bRet; while ((bRet=GetMessage(&uMsg, hwndMainDialog, 0, 0)) != 0) { TranslateMessage(&uMsg); DispatchMessage(&uMsg); } return uMsg.wParam; }