// Jacobo Romero Manrique, 2007 #define _USE_MATH_DEFINES #include #define WIN32_LEAN_AND_MEAN #include #include // timeGetTime() #include GLuint list; void cube() { glEnable(GL_NORMALIZE); static const GLshort s[][3] = { { -1, -1, 1 }, { 1, -1, 1 }, { -1, 1, 1 }, { 1, 1, 1 }, { -1, 1, -1 }, { 1, 1, -1 }, { -1, -1, -1 }, { 1, -1, -1 } }; static const unsigned char ind[] = { 2, 4, 0, 6, 1, 7, 3, 5 }; glBegin(GL_QUAD_STRIP); for (int i = 0; i < 8; i++) { glNormal3sv(s[i]); glVertex3sv(s[i]); } glEnd(); glBegin(GL_QUAD_STRIP); for (int i = 0; i < 8; i++) { glNormal3sv(s[ind[i]]); glVertex3sv(s[ind[i]]); } glEnd(); glDisable(GL_NORMALIZE); } void initlists() { list = glGenLists(5); // Mobius band glNewList(list, GL_COMPILE); static const GLfloat v0[] = { 0.4, 0.4, 0.8, 1.0 }; static const GLfloat v1[] = { 0.7, 0.7, 1.0, 1.0 }; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, v0); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, v1); glBegin(GL_QUAD_STRIP); for (int i = 0; i < 129; i++) { float theta = i*M_PI/128.0; // normal to the band at that point glNormal3f(sin(2*theta)*cos(theta + M_PI_2), sin(theta + M_PI_2), cos(2*theta)*cos(theta + M_PI_2)); for (int j = 0; j <= 1; j++) { // point through parametric eqn float t = j - 0.5; glVertex3f(sin(2*theta)*(2.0 + t*cos(theta)), t*sin(theta), cos(2*theta)*(2.0 + t*cos(theta))); } } glEnd(); glEndList(); // body glNewList(list + 1, GL_COMPILE); glPushMatrix(); glScalef(1.75, 1.75, 0.75); static const GLfloat v2[] = { 0.0, 0.0, 1.0, 1.0 }; glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, v2); cube(); glPopMatrix(); glEndList(); // head glNewList(list + 2, GL_COMPILE); glPushMatrix(); glTranslatef(-0.5, 0.25, 1.0); glPushMatrix(); glScalef(0.25, 0.25, 0.25); cube(); glPopMatrix(); glTranslatef(1.0, 0.0, 0.0); glScalef(0.25, 0.25, 0.25); cube(); glPopMatrix(); static const GLfloat v3[] = { 1.0, 1.0, 0.0, 1.0 }; glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, v3); cube(); glEndList(); // arm glNewList(list + 3, GL_COMPILE); glPushMatrix(); glTranslatef(0.0, -0.5, 0.0); glPushMatrix(); glScalef(0.5, 1.0, 0.625); cube(); glPopMatrix(); glTranslatef(0.0, -1.25, 0.5); glRotatef(35.0, 1.0, 0.0, 0.0); glScalef(0.4, 0.5, 1.0); cube(); glPopMatrix(); glEndList(); // leg glNewList(list + 4, GL_COMPILE); glPushMatrix(); glTranslatef(0.0, -2.0, 0.0); glScalef(0.75, 1.25, 0.75); cube(); glPopMatrix(); glEndList(); } void init() { initlists(); glMatrixMode(GL_PROJECTION); glFrustum(-0.5, 0.5, -0.5, 0.5, 1.0, 100.0); glMatrixMode(GL_MODELVIEW); glTranslatef(0.0, 0.0, -6.0); glClearColor(0.75, 0.5, 0.32, 1.0); glClearDepth(1.0); glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); static const float pos[] = { -8.0, 2.0, 1.0, 1.0 }; glLightfv(GL_LIGHT0, GL_POSITION, pos); glEnable(GL_LIGHT0); glEnable(GL_LIGHTING); } void robot(float frame) { if (frame > 0.5) frame = -frame + 1.0; // body glCallList(list + 1); // head glPushMatrix(); glTranslatef(0.0, 2.75, 0.0); glRotatef(120.0*frame - 30.0, 0.0, 1.0, 0.0); glCallList(list + 2); glPopMatrix(); // arms glPushMatrix(); glTranslatef(-2.25, 1.0, 0.0); glRotatef(-120.0*frame + 30.0, 1.0, 0.0, 0.0); glCallList(list + 3); glPopMatrix(); glPushMatrix(); glTranslatef(2.25, 1.0, 0.0); glRotatef(120.0*frame - 30.0, 1.0, 0.0, 0.0); glCallList(list + 3); glPopMatrix(); // legs glPushMatrix(); glTranslatef(-0.875, -1.0, 0.0); glRotatef(120.0*frame - 30.0, 1.0, 0.0, 0.0); glCallList(list + 4); glPopMatrix(); glPushMatrix(); glTranslatef(0.875, -1.0, 0.0); glRotatef(-120.0*frame + 30.0, 1.0, 0.0, 0.0); glCallList(list + 4); glPopMatrix(); } float xang = 45.0, yang = 0.0; void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glRotatef(yang, 0.0f, 1.0f, 0.0f); glRotatef(xang, 1.0f, 0.0f, 0.0f); glDisable(GL_CULL_FACE); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1); glCallList(list); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); glEnable(GL_CULL_FACE); int time = timeGetTime() & 8191; int time2 = time & 4095; float rad = 2*M_PI*time2/4096.0; glTranslatef(2*cos(rad), 0.0, 2*sin(rad)); glRotatef(-time2*360.0/4096.0, 0.0, 1.0, 0.0); glRotatef(-time*360.0/8192.0 + 45.0, 0.0, 0.0, 1.0); glTranslatef(0.0, 0.7, 0.0); glScalef(0.16, 0.16, 0.16); robot((time & 511) / 512.0); glPopMatrix(); glFlush(); } static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static int xmouse, ymouse; switch (uMsg) { case WM_LBUTTONDOWN: if (wParam == MK_LBUTTON) { xmouse = LOWORD(lParam); ymouse = HIWORD(lParam); } return 0; case WM_MOUSEMOVE: if (wParam == MK_LBUTTON) { xang += float(HIWORD(lParam) - ymouse); yang += float(LOWORD(lParam) - xmouse); xmouse = LOWORD(lParam); ymouse = HIWORD(lParam); } return 0; case WM_KEYDOWN: if (wParam != VK_ESCAPE) break; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, uMsg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR szCmdLine, int iCmdShow) { // we need to register a custom window class, because opengl rendering on windows without the CS_OWNDC style // doesn't work for too long on Win95 static const char szClassName[] = "ualmat"; static const WNDCLASS wc = { CS_OWNDC, WndProc, 0, 0, hInstance, 0, LoadCursor(0, IDC_ARROW), 0, 0, szClassName }; RegisterClass(&wc); // obtain the window size for a 600x600 client area and create the window RECT r = { 0, 0, 600, 600 }; AdjustWindowRect(&r, WS_CAPTION | WS_SYSMENU, 0); HWND hWnd = CreateWindow(szClassName, szClassName, WS_CAPTION | WS_SYSMENU | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, r.right - r.left, r.bottom - r.top, 0, 0, hInstance, 0); if (hWnd) { HDC hDC = GetDC(hWnd); // establish the pixel format static const PIXELFORMATDESCRIPTOR pfd = { sizeof pfd, 1, PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL, PFD_TYPE_RGBA, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0 }; int pf = ChoosePixelFormat(hDC, &pfd); SetPixelFormat(hDC, pf, &pfd); // create the rendering context HGLRC hRC = wglCreateContext(hDC); wglMakeCurrent(hDC, hRC); // turn on vsync to save cpu load (we don't need 700 fps here since only about 60 are commonly shown) BOOL (APIENTRY *wglSwapIntervalEXT)(int) = (BOOL(APIENTRY *)(int))wglGetProcAddress("wglSwapIntervalEXT"); if (wglSwapIntervalEXT) wglSwapIntervalEXT(1); // opengl settings init(); MSG msg; for (;;) if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) if (msg.message == WM_QUIT) break; else { TranslateMessage(&msg); DispatchMessage(&msg); } else { display(); SwapBuffers(hDC); } wglDeleteContext(hRC); return msg.wParam; } return 1; }