초보프로그래머인데, OpenGL 프로그래밍 공부를 하고 있었는데
제 프로그램을 반디캠으로 동영상찰열을 하려 하니 제 프로그램에서 에러를 뿜고 죽어버리네요.
컴파일러는 비주얼스튜디오2013
운영체제는 윈도우8.1
사양은 모바일 I7 8Gib GTX 765M입니다.
제 코드에 문제가 있다면 어쩔 수 없지만
반디캠에 문제가 있는거라면 수정해 주셨으면 좋겠습니다.
#include <tchar.h>
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <memory>
#include <vector>
#include "FreeImage.h"
#include <string>
#include <memory.h>
#pragma comment(lib,"FreeImage.lib")
#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"glu32.lib")
/* Declare Windows procedure */
LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
/* Make the class name into a global variable */
TCHAR szClassName[] = _T("CodeBlocksWindowsApp");
HDC g_hdc;
HGLRC g_hrc;
LRESULT OnCreate(HWND, UINT, WPARAM, LPARAM);
LRESULT OnDestroy(HWND, UINT, WPARAM, LPARAM);
LRESULT OnPaint(HWND, UINT, WPARAM, LPARAM);
LRESULT OnSize(HWND, UINT, WPARAM, LPARAM);
void Paint(HWND hWnd);
class SurfaceManager;
class Surface{
friend class SurfaceManager;
public:
Surface(int width, int height) {
GLfloat t[] = { 0.0f, 0.0f, 1.0f, 0.f, 1.f, 1.0f, 0.f, 0.f, 1.f, 1.0f, 0.f, 1.f };
GLfloat t2[] = {
-width/2.0f, -height/2.0f,
width / 2.0f, -height / 2.0f,
width / 2.0f, height / 2.0f,
-width / 2.0f, -height / 2.0f,
width / 2.0f, height / 2.0f,
-width / 2.0f, height / 2.0f
};
memcpy(m_textureVertArr, t, sizeof(GLfloat) * 12);
memcpy(m_vertArr, t2, sizeof(GLfloat) * 12);
m_x = 0;
m_y = 0;
m_angle = 0;
m_width = width;
m_height = height;
}
void Move(GLfloat dx, GLfloat dy){
m_x += dx; m_y += dy;
}
void Rotate(GLfloat dangle)
{
m_angle += dangle;
if (m_angle >= 360.0f)
{
m_angle -= 360.0f;
}
else if (m_angle < 0)
{
m_angle += 360.0f;
}
}
int GetOriginWidth()
{
return m_width;
}
int GetOriginHeight()
{
return m_height;
}
GLfloat GetWidth()
{
return 0.0f;
}
GLfloat GetHeight()
{
return 0.0f;
}
void Draw(){
glTranslatef(m_x, m_y, 0);
glRotatef(m_angle, 0, 0, 1);
glBindTexture(GL_TEXTURE_2D, m_textureId);
glVertexPointer(2, GL_FLOAT, 0, m_vertArr);
glTexCoordPointer(2, GL_FLOAT, 0, m_textureVertArr);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
private:
GLfloat m_vertArr[12];
GLfloat m_textureVertArr[12];
GLuint m_textureId;
GLfloat m_x;
GLfloat m_y;
GLfloat m_angle;
int m_width;
int m_height;
};
class SurfaceManager{
public:
SurfaceManager(int size = 64){
m_textureIdxs = new GLuint[size];
m_size = size;
m_cur = 0;
glGenTextures(m_size, m_textureIdxs);
}
~SurfaceManager(){
delete[] m_textureIdxs;
}
std::shared_ptr<Surface> CreateSurface(const std::wstring & fileName){
bool isExistInLoadFile = false;
for (auto & f : m_loadingFile)
{
if (f.m_name == fileName)
{
isExistInLoadFile = true;
break;
}
}
if (isExistInLoadFile == false)
{
FIBITMAP * pBitmap = FreeImage_LoadU(FREE_IMAGE_FORMAT::FIF_PNG, fileName.c_str());
if (pBitmap == nullptr){
return std::shared_ptr<Surface>(nullptr);
}
BYTE * bits = FreeImage_GetBits(pBitmap);
BITMAPINFO * info = FreeImage_GetInfo(pBitmap);
unsigned pitch = FreeImage_GetPitch(pBitmap);
for (int y = 0; y < info->bmiHeader.biHeight; y++){
for (int x = 0; x < info->bmiHeader.biWidth; x++){
BYTE temp = bits[y * pitch + x * 4 + FI_RGBA_BLUE];
bits[y * pitch + x * 4 + FI_RGBA_BLUE] = bits[y * pitch + x * 4 + FI_RGBA_RED];
bits[y * pitch + x * 4 + FI_RGBA_RED] = temp;
BYTE alpha = bits[y * pitch + x * 4 + FI_RGBA_ALPHA];
if (alpha != 0){
printf("%d", alpha);
}
}
}
glBindTexture(GL_TEXTURE_2D, m_textureIdxs[m_cur]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, info->bmiHeader.biWidth, info->bmiHeader.biHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, bits);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
std::shared_ptr<Surface> res(new Surface(info->bmiHeader.biWidth, info->bmiHeader.biHeight));
res->m_textureId = m_textureIdxs[m_cur];
FreeImage_Unload(pBitmap);
_tagTexture n;
n.m_idx = m_cur;
n.m_name = fileName;
m_loadingFile.push_back(n);
m_cur++;
return res;
}
else
{
}
}
void Draw();
private:
struct _tagTexture
{
std::wstring m_name;
GLuint m_idx;
int m_width;
int m_height;
};
std::vector<_tagTexture> m_loadingFile;
GLuint * m_textureIdxs;
int m_size;
int m_cur;
};
SurfaceManager * g_sm;
std::shared_ptr<Surface> g_humi;
std::shared_ptr<Surface> g_sur;
int WINAPI WinMain(HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nCmdShow)
{
HWND hwnd; /* This is the handle for our window */
MSG messages; /* Here messages to the application are saved */
WNDCLASSEX wincl; /* Data structure for the windowclass */
/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */
wincl.style = CS_DBLCLKS | CS_OWNDC ; /* Catch double-clicks */
wincl.cbSize = sizeof(WNDCLASSEX);
/* Use default icon and mouse-pointer */
wincl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor(NULL, IDC_ARROW);
wincl.lpszMenuName = NULL; /* No menu */
wincl.cbClsExtra = 0; /* No extra bytes after the window class */
wincl.cbWndExtra = 0; /* structure or the window instance */
/* Use Windows's default colour as the background of the window */
wincl.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx(&wincl))
return 0;
/* The class is registered, let's create the program*/
hwnd = CreateWindowEx(
0, /* Extended possibilites for variation */
szClassName, /* Classname */
_T("Code::Blocks Template Windows App"), /* Title Text */
WS_OVERLAPPEDWINDOW, /* default window */
CW_USEDEFAULT, /* Windows decides the position */
CW_USEDEFAULT, /* where the window ends up on the screen */
544, /* The programs width */
375, /* and height in pixels */
HWND_DESKTOP, /* The window is a child-window to desktop */
NULL, /* No menu */
hThisInstance, /* Program Instance handler */
NULL /* No Window Creation data */
);
/* Make the window visible on the screen */
ShowWindow(hwnd, nCmdShow);
int tick = GetTickCount();
int preTick = tick;
double timeDelta = (tick - preTick) / 1000.0;
double fpsLimit = 0.0;
while (true)
{
tick = GetTickCount();
timeDelta = (tick - preTick) / 1000.0;
if (PeekMessage(&messages, NULL, NULL, NULL, PM_REMOVE))
{
TranslateMessage(&messages);
DispatchMessage(&messages);
}
else
{
if (timeDelta < 1 / 60.0)
{
fpsLimit += timeDelta;
}
while (fpsLimit > 1 / 60.0)
{
Paint(messages.hwnd);
InvalidateRect(hwnd, NULL, false);
fpsLimit -= 1 / 60.0;
}
}
if (messages.message == WM_QUIT)
{
break;
}
g_humi->Rotate(timeDelta * 180);
preTick = tick;
}
/* The program return-value is 0 - The value that PostQuitMessage() gave */
return messages.wParam;
}
LRESULT OnCreate(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PIXELFORMATDESCRIPTOR pfd = { 0, };
int nPixelFormat;
g_hdc = GetDC(hWnd);
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
nPixelFormat = ChoosePixelFormat(g_hdc, &pfd);
SetPixelFormat(g_hdc, nPixelFormat, &pfd);
g_hrc = wglCreateContext(g_hdc);
wglMakeCurrent(g_hdc, g_hrc);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
glDisable(GL_COLOR_MATERIAL);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
g_sm = new SurfaceManager();
g_sur = g_sm->CreateSurface(L"074_4.png");
g_humi = g_sm->CreateSurface(L"074_3.png");
g_sur->Move(400, 0);
return 0;
}
LRESULT OnDestroy(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
delete g_sm;
g_humi.reset();
g_sur.reset();
wglMakeCurrent(g_hdc, NULL);
wglDeleteContext(g_hrc);
ReleaseDC(hWnd, g_hdc);
PostQuitMessage(0);
return 0;
}
void Paint(HWND hWnd)
{
RECT rc = { 0, };
GetClientRect(hWnd, &rc);
glClearColor(1, 1, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-rc.right, rc.right, -rc.bottom, rc.bottom);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//glColor3f(1.0f, 1.0f, 1.0f);
glPushMatrix();
g_sur->Draw();
glPopMatrix();
glPushMatrix();
g_humi->Draw();
glPopMatrix();
}
LRESULT OnPaint(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
//Paint(hWnd);
SwapBuffers(g_hdc);
ValidateRect(hWnd, NULL);
return 0;
}
LRESULT OnSize(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
glViewport(0, 0, LOWORD(lParam), HIWORD(lParam));
//OnPaint(hWnd, uMsg, wParam, lParam);
Paint(hWnd);
return 0;
}
/* This function is called by the Windows function DispatchMessage() */
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
switch (message){
case WM_CREATE:
return OnCreate(hwnd, message, wParam, lParam);
case WM_DESTROY:
return OnDestroy(hwnd, message, wParam, lParam);
case WM_PAINT:
return OnPaint(hwnd, message, wParam, lParam);
case WM_SIZE:
return OnSize(hwnd, message, wParam, lParam);
default: /* for messages that we don't deal with */
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}