/* * 三角形が回るアニメ */ #include #include static RECT g_rect; static float g_rotate = 0.0f; static int fps_count = 0; static int fps_frame = 0; void nmgl_disp_num(int num){ switch(num){ case 0: glBegin(GL_LINE_STRIP); glVertex2d(-0.4, 0.8); glVertex2d(-0.4, -0.8); glVertex2d(0.4, -0.8); glVertex2d(0.4, 0.8); glVertex2d(-0.4, 0.8); glEnd(); break; case 1: glBegin(GL_LINE_STRIP); glVertex2d(0.4, 0.8); glVertex2d(0.4, -0.8); glEnd(); break; case 2: glBegin(GL_LINE_STRIP); glVertex2d(-0.4, 0.8); glVertex2d(0.4, 0.8); glVertex2d(0.4, 0.0); glVertex2d(-0.4, 0.0); glVertex2d(-0.4, -0.8); glVertex2d(0.4, -0.8); glEnd(); break; case 3: glBegin(GL_LINE_STRIP); glVertex2d(-0.4, 0.8); glVertex2d(0.4, 0.8); glVertex2d(0.4, -0.8); glVertex2d(-0.4, -0.8); glEnd(); glBegin(GL_LINE_STRIP); glVertex2d(-0.4, 0.0); glVertex2d(0.4, 0.0); glEnd(); break; case 4: glBegin(GL_LINE_STRIP); glVertex2d(-0.4, 0.8); glVertex2d(-0.4, 0.0); glVertex2d(0.4, 0.0); glEnd(); glBegin(GL_LINE_STRIP); glVertex2d(0.4, 0.8); glVertex2d(0.4, -0.8); glEnd(); break; case 5: glBegin(GL_LINE_STRIP); glVertex2d(0.4, 0.8); glVertex2d(-0.4, 0.8); glVertex2d(-0.4, 0.0); glVertex2d(0.4, 0.0); glVertex2d(0.4, -0.8); glVertex2d(-0.4, -0.8); glEnd(); break; case 6: glBegin(GL_LINE_STRIP); glVertex2d(0.4, 0.8); glVertex2d(-0.4, 0.8); glVertex2d(-0.4, -0.8); glVertex2d(0.4, -0.8); glVertex2d(0.4, 0.0); glVertex2d(-0.4, 0.0); glEnd(); break; case 7: glBegin(GL_LINE_STRIP); glVertex2d(-0.4, 0.8); glVertex2d(0.4, 0.8); glVertex2d(0.4, -0.8); glEnd(); break; case 8: glBegin(GL_LINE_STRIP); glVertex2d(-0.4, 0.8); glVertex2d(-0.4, -0.8); glVertex2d(0.4, -0.8); glVertex2d(0.4, 0.8); glVertex2d(-0.4, 0.8); glEnd(); glBegin(GL_LINE_STRIP); glVertex2d(-0.4, 0.0); glVertex2d(0.4, 0.0); glEnd(); break; case 9: glBegin(GL_LINE_STRIP); glVertex2d(0.4, 0.0); glVertex2d(-0.4, 0.0); glVertex2d(-0.4, 0.8); glVertex2d(0.4, 0.8); glVertex2d(0.4, -0.8); glVertex2d(-0.4, -0.8); glEnd(); break; default: glBegin(GL_LINE_STRIP); glVertex2d(0.4, 0.8); glVertex2d(-0.4, 0.8); glVertex2d(-0.4, -0.8); glVertex2d(0.4, -0.8); glEnd(); glBegin(GL_LINE_STRIP); glVertex2d(-0.4, 0.0); glVertex2d(0.4, 0.0); glEnd(); break; } } void nmgl_disp_fsp(int fps){ glPushMatrix(); glColor3d(1.0, 1.0, 1.0); glTranslated(-1.5, 0.0, 0.0); nmgl_disp_num((fps % 10000) / 1000); glTranslated(1.0, 0.0, 0.0); nmgl_disp_num((fps % 1000) / 100); glTranslated(1.0, 0.0, 0.0); nmgl_disp_num((fps % 100) / 10); glTranslated(1.0, 0.0, 0.0); nmgl_disp_num(fps % 10); glPopMatrix(); } /* 初期化の処理 */ void nmgl_init(void){ /* 背景色の指定 RGBA */ glClearColor(0.0, 0.0, 0.0, 0.0); } /* リサイズの処理 */ void nmgl_resize(int w, int h){ /* ビューポートの設定 */ glViewport(0, 0, w, h); /* 射影変換モードに */ glMatrixMode(GL_PROJECTION); /* 変換行列を単位行列に */ glLoadIdentity(); /* 透視射影の視野台形 左、右、下、上、手前、奥 */ glFrustum(-1.33, 1.33, -1.0, 1.0, 1.0, 5.0); /* モデル変換モードに戻す */ glMatrixMode(GL_MODELVIEW); } /* 描画の処理 */ void nmgl_paint(void){ /* 背景色でクリア */ glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); glTranslated(0.0, 0.0, -3.0); glPushMatrix(); glRotated(g_rotate, 0.0, 1.0, 0.0); glBegin(GL_TRIANGLES); glColor3d(1.0, 0.0, 0.0); glVertex3d(1.0, -0.6, 0.0); glVertex3d(-1.0, -0.6, 0.0); glVertex3d(0.0, 1.0, 0.0); glEnd(); glPopMatrix(); glPushMatrix(); glTranslated(0.0, 0.0, 2.0); glTranslated(-1.0, 0.8, 0.0); glScaled(0.1, 0.1, 0.1); nmgl_disp_fsp(fps_frame); glPopMatrix(); glFinish(); fps_count++; } #define ID_TIMER1 100 #define TIMER_BLANK 10 /* msec */ /* Timer1 */ void CALLBACK Timer1(UINT wID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2) { static int r = 0; static int count = 0; /* 回転の計算 */ r++; g_rotate = r * 1.40625f; r &= 0x000000FF; /* FPS の計算 */ count += TIMER_BLANK; if(count >= 1000){ fps_frame = fps_count; fps_count = 0; count = 0; } } #define ID_THREAD1 1000 /* スレッド用構造体 */ typedef struct{ HWND hWnd; BOOL thread_end; } DATA, *PDATA; /* Thread1 */ DWORD WINAPI Thread1(LPVOID data) { PDATA pData; static BOOL th_flag = FALSE; pData = (PDATA)data; if(!th_flag){ th_flag = TRUE; while(!pData->thread_end){ InvalidateRect(pData->hWnd, &g_rect, FALSE); UpdateWindow(pData->hWnd); } } return (DWORD)0; } /* 関数 */ BOOL bSetupPixelFormat(HDC hdc); /* ウィンドウプロシージャ */ LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); /* メイン */ int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int nCmdShow) { WNDCLASSEX wcex; char *wdName = "OpenGL on Win32API"; HWND hWnd; MSG msg; if(!hPrevInstance){ wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = NULL; wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcex.lpszMenuName = NULL; wcex.lpszClassName = wdName; wcex.hIconSm = NULL; /* ウインドウクラスを登録 */ if(!RegisterClassEx(&wcex)){ return 0; } } // ウインドウを作成 hWnd = CreateWindow( wcex.lpszClassName, wdName, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, // ウインドウのスタイル CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); /* ウインドウを表示 */ ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); /* メッセージループ */ while(GetMessage(&msg, NULL, 0, 0)){ TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } /* ウィンドウプロシージャ */ LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static HDC hdc; static HGLRC hrc; static DATA data1; static HANDLE hThread1; static TIMECAPS tc; static unsigned int timer1; switch (message) { case WM_CREATE: { DWORD thId1; hdc = GetDC(hWnd); /* ピクセルフォーマットの設定へ */ bSetupPixelFormat(hdc); /* レンダリングコンテキストの作成 */ hrc = wglCreateContext(hdc); /* レンダリングコンテキストをデバイスコンテキストに結びつける */ wglMakeCurrent(hdc, hrc); /* 初期化 */ nmgl_init(); /* スレッドの作成 */ data1.hWnd = hWnd; data1.thread_end = FALSE; hThread1 = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)Thread1, (LPVOID)&data1, 0, &thId1); /* タイマーの作成 */ timeGetDevCaps(&tc, sizeof(TIMECAPS)); timeBeginPeriod(tc.wPeriodMin); timer1 = timeSetEvent( TIMER_BLANK, tc.wPeriodMin, (LPTIMECALLBACK)Timer1, ID_TIMER1, TIME_PERIODIC); } break; case WM_PAINT: { /* 描画 */ nmgl_paint(); /* ダブルバッファ反転 */ SwapBuffers(hdc); } break; case WM_SIZE: { GetClientRect(hWnd, &g_rect); /* リサイズ */ nmgl_resize(g_rect.right, g_rect.bottom); } break; case WM_DESTROY: { /* タイマーの終了 */ timeKillEvent(timer1); timeEndPeriod(tc.wPeriodMin); /* スレッドの終了 */ data1.thread_end = TRUE; Sleep(1000); CloseHandle(hThread1); Sleep(1000); /* 後片付け */ wglMakeCurrent(hdc, 0); wglDeleteContext(hrc); ReleaseDC(hWnd, hdc); PostQuitMessage(0); } break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } /* ピクセルフォーマットの設定 */ BOOL bSetupPixelFormat(HDC hdc) { static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), /* size of this pfd */ 1, /* version number */ PFD_DRAW_TO_WINDOW | /* support window */ PFD_SUPPORT_OPENGL | /* support OpenGL */ PFD_DOUBLEBUFFER, /* double buffered */ PFD_TYPE_RGBA, /* RGBA type */ 24, /* 24-bit color depth */ 0, 0, 0, 0, 0, 0, /* color bits ignored */ 0, /* no alpha buffer */ 0, /* shift bit ignored */ 0, /* no accumulation buffer */ 0, 0, 0, 0, /* accum bits ignored */ 32, /* 32-bit z-buffer */ 0, /* no stencil buffer */ 0, /* no auxiliary buffer */ PFD_MAIN_PLANE, /* main layer */ 0, /* reserved */ 0, 0, 0 /* layer masks ignored */ }; int pixelformat; if((pixelformat = ChoosePixelFormat(hdc, &pfd)) == 0){ MessageBox(NULL, "ChoosePixelFormat failed", "Error", MB_OK); return FALSE; } if(SetPixelFormat(hdc, pixelformat, &pfd) == FALSE) { MessageBox(NULL, "SetPixelFormat failed", "Error", MB_OK); return FALSE; } return TRUE; }