#include #include #include #include #include #include #include #include #include #include #define PI 3.14159265358979323846 #define NLETTERS 64 #define FIRST_LETTER '@' #define NOBJS 6 GLenum doubleBuffer; GLenum videoMemory; GLenum noSwap; GLenum noClear; GLenum fullScreen; GLenum useMcd; GLenum modeX; GLenum stretch; GLenum paletted; GLenum timings; GLenum spin; GLenum updateMovie = GL_TRUE; GLenum linearFilter = GL_FALSE; int fullWidth, fullHeight, fullDepth; int winWidth, winHeight; int texWidth, texHeight; int movX, movY; int movWidth, movHeight; GLuint clearBits; DWORD ticks; int frames; GLint letters; GLYPHMETRICSFLOAT letterMetrics[NLETTERS]; double xrot, yrot; GLDDWINDOW gwMain = NULL; PFNGLCOLORTABLEEXTPROC pfnColorTableEXT; PFNGLCOLORSUBTABLEEXTPROC pfnColorSubTableEXT; LPDIRECTDRAWSURFACE pddsTex; DDSURFACEDESC ddsdTex; char *aviFileName = "d:\\winnt\\clock.avi"; PAVISTREAM aviStream; long aviLength; long curFrame; PGETFRAME aviGetFrame; BITMAPINFO *pbmiMovie; typedef struct _Object { void (*build_fn)(void); GLenum canCull; GLenum needsZ; GLint dlist; } Object; int objIdx = 0; float c[6][4][3] = { { { 1.0f, 1.0f, -1.0f }, { -1.0f, 1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f }, { 1.0f, -1.0f, -1.0f } }, { { 1.0f, 1.0f, 1.0f }, { 1.0f, 1.0f, -1.0f }, { 1.0f, -1.0f, -1.0f }, { 1.0f, -1.0f, 1.0f } }, { { -1.0f, 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f }, { 1.0f, -1.0f, 1.0f }, { -1.0f, -1.0f, 1.0f } }, { { -1.0f, 1.0f, -1.0f }, { -1.0f, 1.0f, 1.0f }, { -1.0f, -1.0f, 1.0f }, { -1.0f, -1.0f, -1.0f } }, { { -1.0f, 1.0f, 1.0f }, { -1.0f, 1.0f, -1.0f }, { 1.0f, 1.0f, -1.0f }, { 1.0f, 1.0f, 1.0f } }, { { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, 1.0f }, { 1.0f, -1.0f, 1.0f }, { 1.0f, -1.0f, -1.0f } } }; float n[6][3] = { { 0.0f, 0.0f, -1.0f }, { 1.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 1.0f }, { -1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, -1.0f, 0.0f } }; float t[6][4][2] = { { { 1.0f, 1.0f }, { -0.0f, 1.0f }, { -0.0f, -0.0f }, { 1.0f, -0.0f } }, { { 1.0f, 1.0f }, { -0.0f, 1.0f }, { -0.0f, -0.0f }, { 1.0f, -0.0f } }, { { -0.0f, 1.0f }, { 1.0f, 1.0f }, { 1.0f, -0.0f }, { -0.0f, -0.0f } }, { { 1.0f, 1.0f }, { -0.0f, 1.0f }, { -0.0f, -0.0f }, { 1.0f, -0.0f } }, { { 1.0f, 1.0f }, { -0.0f, 1.0f }, { -0.0f, -0.0f }, { 1.0f, -0.0f } }, { { 1.0f, 1.0f }, { -0.0f, 1.0f }, { -0.0f, -0.0f }, { 1.0f, -0.0f } }, }; void BuildSphere(void) { GLUquadricObj *quadObj; quadObj = gluNewQuadric (); gluQuadricDrawStyle (quadObj, GLU_FILL); gluQuadricNormals (quadObj, GLU_SMOOTH); gluQuadricTexture (quadObj, GL_TRUE); gluSphere (quadObj, 1.0, 16, 16); gluDeleteQuadric(quadObj); } void BuildCube(void) { GLint i; for (i = 0; i < 6; i++) { glBegin(GL_POLYGON); glNormal3fv(n[i]); glTexCoord2fv(t[i][0]); glVertex3fv(c[i][0]); glNormal3fv(n[i]); glTexCoord2fv(t[i][3]); glVertex3fv(c[i][3]); glNormal3fv(n[i]); glTexCoord2fv(t[i][2]); glVertex3fv(c[i][2]); glNormal3fv(n[i]); glTexCoord2fv(t[i][1]); glVertex3fv(c[i][1]); glEnd(); } } void BuildCylinder(void) { GLUquadricObj *quadObj; 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); gluQuadricTexture (quadObj, GL_TRUE); gluCylinder (quadObj, 1.0, 1.0, 1.5, 20, 2); glPopMatrix (); gluDeleteQuadric(quadObj); } void BuildCone(void) { GLUquadricObj *quadObj; quadObj = gluNewQuadric (); gluQuadricDrawStyle (quadObj, GLU_FILL); gluQuadricTexture (quadObj, GL_TRUE); gluCylinder (quadObj, 1.0, 0.0, 1.5, 20, 2); gluDeleteQuadric(quadObj); } void BuildTeapot(void) { auxSolidTeapot(1.0); } #define STRING "OpenGL" void BuildString(void) { char *str; int i, l; float wd, ht; GLfloat fv4[4]; str = STRING; l = strlen(str); wd = 0.0f; for (i = 0; i < l-1; i++) { wd += letterMetrics[str[i]-FIRST_LETTER].gmfCellIncX; } wd += letterMetrics[str[i]-FIRST_LETTER].gmfBlackBoxX; ht = letterMetrics[str[0]-FIRST_LETTER].gmfBlackBoxY; glPushMatrix(); glScalef(1.0f, 2.0f, 1.0f); glTranslatef(-wd/2.0f, -ht/2.0f, 0.0f); fv4[0] = 1.0f/wd; fv4[1] = 0.0f; fv4[2] = 0.0f; fv4[3] = 0.0f; glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR ); glTexGenfv(GL_S, GL_EYE_PLANE, fv4 ); fv4[0] = 0.0f; fv4[1] = -1.0f/ht; fv4[2] = 0.0f; fv4[3] = 0.0f; glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR ); glTexGenfv(GL_T, GL_EYE_PLANE, fv4 ); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glListBase(letters-FIRST_LETTER); glCallLists(l, GL_UNSIGNED_BYTE, str); glListBase(0); glPopMatrix(); glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); } Object objects[NOBJS] = { BuildCube, GL_TRUE, GL_FALSE, 0, BuildSphere, GL_TRUE, GL_FALSE, 0, BuildCylinder, GL_FALSE, GL_TRUE, 0, BuildCone, GL_FALSE, GL_TRUE, 0, BuildTeapot, GL_FALSE, GL_TRUE, 0, BuildString, GL_TRUE, GL_TRUE, 0, }; void BuildLists(void) { int i; GLint base; base = glGenLists(NOBJS); for (i = 0; i < NOBJS; i++) { objects[i].dlist = base+i; glNewList(objects[i].dlist, GL_COMPILE); objects[i].build_fn(); glEndList(); } } void Quit(char *fmt, ...) { va_list args; if (fmt != NULL) { va_start(args, fmt); vprintf(fmt, args); va_end(args); } if (aviGetFrame != NULL) { AVIStreamGetFrameClose(aviGetFrame); } if (aviStream != NULL) { AVIStreamRelease(aviStream); AVIFileExit(); } if (gwMain != NULL) { glddDestroyWindow(gwMain); } exit(1); } void Draw(void) { DWORD fticks; fticks = GetTickCount(); glClear(clearBits); glLoadIdentity(); glRotated(xrot, 1.0, 0.0, 0.0); glRotated(yrot, 0.0, 1.0, 0.0); glCallList(objects[objIdx].dlist); glFlush(); if (doubleBuffer && !noSwap) { glddSwapBuffers(gwMain); } ticks += GetTickCount()-fticks; frames++; if (timings && ticks > 1000) { printf("%d frames in %d ticks, %.3lf f/s\n", frames, ticks, (double)frames*1000.0/ticks); frames = 0; ticks = 0; } } void *UpdateBmi(BITMAPINFO *pbmi) { if (pbmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER)) { Quit("Unknown stream format data\n"); } memcpy(pbmiMovie->bmiColors, pbmi->bmiColors, 256*sizeof(RGBQUAD)); // Return pointer to data after BITMAPINFO return pbmi->bmiColors+256; } void FrameToTex(long frame) { HDC hdc; HRESULT hr; LPVOID pvFrame, pvData; pvFrame = AVIStreamGetFrame(aviGetFrame, frame); if (pvFrame == NULL) { Quit("AVIStreamGetFrame failed\n"); } // Skip past BITMAPINFO at start of frame. // If it becomes interesting to support palette changes per frame // this should call UpdateBmi #if 0 pvData = (LPVOID)((BYTE *)pvFrame+sizeof(BITMAPINFO)+255*sizeof(RGBQUAD)); #else pvData = UpdateBmi(pvFrame); if (paletted) { pfnColorSubTableEXT(GL_TEXTURE_2D, 0, 256, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pbmiMovie->bmiColors); } #endif if (stretch) { hr = pddsTex->lpVtbl->GetDC(pddsTex, &hdc); if (hr != DD_OK) { Quit("Stretch GetDC failed, 0x%08lX\n", hr); } StretchDIBits(hdc, 0, 0, texWidth, texHeight, 0, 0, movWidth, movHeight, pvData, pbmiMovie, DIB_RGB_COLORS, SRCCOPY); pddsTex->lpVtbl->ReleaseDC(pddsTex, hdc); } else if (!paletted) { hr = pddsTex->lpVtbl->GetDC(pddsTex, &hdc); if (hr != DD_OK) { Quit("Set GetDC failed, 0x%08lX\n", hr); } // The only AVI sources currently allowed are 8bpp so if the texture // isn't paletted a conversion is necessary SetDIBitsToDevice(hdc, movX, movY, movWidth, movHeight, 0, 0, 0, movHeight, pvData, pbmiMovie, DIB_RGB_COLORS); pddsTex->lpVtbl->ReleaseDC(pddsTex, hdc); } else { UINT cbLine; int y; BYTE *pbSrc, *pbDst; HRESULT hr; hr = pddsTex->lpVtbl->Lock(pddsTex, NULL, &ddsdTex, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); if (hr != S_OK) { Quit("Unable to lock texture, 0x%08lX\n", hr); } cbLine = (movWidth+3) & ~3; pbSrc = (BYTE *)pvData; pbDst = (BYTE *)ddsdTex.lpSurface+ddsdTex.lPitch*movY+movX; #if 1 for (y = 0; y < movHeight; y++) { memcpy(pbDst, pbSrc, movWidth); pbSrc += cbLine; pbDst += ddsdTex.lPitch; } #else for (y = 0; y < movHeight; y++) { memset(pbDst, y*256/movHeight, movWidth); pbSrc += cbLine; pbDst += ddsdTex.lPitch; } #endif pddsTex->lpVtbl->Unlock(pddsTex, ddsdTex.lpSurface); } } void Animate(GLDDWINDOW gw) { if (updateMovie) { if (++curFrame == aviLength) { curFrame = 0; } FrameToTex(curFrame); } if (spin) { xrot += 2; yrot += 3; } Draw(); } void SetView(void) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0, (double)winWidth/winHeight, 0.1, 10); gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); glMatrixMode(GL_MODELVIEW); } void ToggleGl(GLenum state) { if (glIsEnabled(state)) { glDisable(state); } else { glEnable(state); } } void SetObject(int idx) { objIdx = idx; clearBits = GL_COLOR_BUFFER_BIT; if (objects[objIdx].canCull) { glFrontFace(GL_CCW); glCullFace(GL_BACK); glEnable(GL_CULL_FACE); } else { glDisable(GL_CULL_FACE); } if (objects[objIdx].needsZ) { clearBits |= GL_DEPTH_BUFFER_BIT; glEnable(GL_DEPTH_TEST); } else { glDisable(GL_DEPTH_TEST); } } void SetTexFilter(void) { GLenum filter; filter = linearFilter ? GL_LINEAR : GL_NEAREST; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); } void ClearTex(void) { DDBLTFX ddbltfx; RECT drct; HRESULT hr; drct.left = 0; drct.top = 0; drct.right = texWidth; drct.bottom = texHeight; memset(&ddbltfx, 0, sizeof(ddbltfx)); ddbltfx.dwSize = sizeof(ddbltfx); ddbltfx.dwFillColor = 0; hr = pddsTex->lpVtbl->Blt(pddsTex, &drct, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); if (hr != DD_OK) { Quit("Blt failed, 0x%08lX\n", hr); } } void Key(UINT key) { switch(key) { case VK_ESCAPE: Quit(NULL); break; case VK_SPACE: spin = !spin; break; case 'D': ToggleGl(GL_DITHER); break; case 'F': linearFilter = !linearFilter; SetTexFilter(); break; case 'H': stretch = !stretch; break; case 'M': updateMovie = !updateMovie; break; case 'O': if (++objIdx == NOBJS) { objIdx = 0; } SetObject(objIdx); break; case 'S': spin = !spin; break; case 'T': timings = !timings; frames = 0; ticks = 0; break; case 'X': ToggleGl(GL_TEXTURE_2D); break; default: break; } } BOOL Message(GLDDWINDOW gw, HWND hwnd, UINT uiMsg, WPARAM wpm, LPARAM lpm, LRESULT *plr) { switch(uiMsg) { case WM_KEYDOWN: Key((UINT)wpm); break; case WM_SIZE: winWidth = LOWORD(lpm); winHeight = HIWORD(lpm); SetView(); break; default: return FALSE; } *plr = 0; return TRUE; } void GetStreamFormat(void) { HRESULT hr; LONG fmtSize; void *pvFmt; hr = AVIStreamFormatSize(aviStream, 0, &fmtSize); if (hr != S_OK) { Quit("AVIStreamFormatSize failed, 0x%08lX\n", hr); } pvFmt = malloc(fmtSize); if (pvFmt == NULL) { Quit("Unable to allocate format buffer\n"); } hr = AVIStreamReadFormat(aviStream, 0, pvFmt, &fmtSize); if (hr != S_OK) { Quit("AVIStreamReadFormat failed, 0x%08lX\n", hr); } UpdateBmi((BITMAPINFO *)pvFmt); free(pvFmt); } void OpenMovie(void) { HRESULT hr; AVISTREAMINFO sinfo; BITMAPINFOHEADER *pbmih; AVIFileInit(); hr = AVIStreamOpenFromFile(&aviStream, aviFileName, streamtypeVIDEO, 0, OF_READ | OF_SHARE_DENY_WRITE, NULL); if (hr != S_OK) { Quit("AVIStreamOpenFromFile failed, 0x%08lX\n", hr); } aviLength = AVIStreamLength(aviStream); hr = AVIStreamInfo(aviStream, &sinfo, sizeof(sinfo)); if (hr != S_OK) { Quit("AVIStreamInfo failed, 0x%08lX\n", hr); } if (sinfo.dwFlags & AVISTREAMINFO_FORMATCHANGES) { printf("WARNING: Stream contains format changes, unhandled\n"); } GetStreamFormat(); movWidth = sinfo.rcFrame.right-sinfo.rcFrame.left; movHeight = sinfo.rcFrame.bottom-sinfo.rcFrame.top; #if 1 printf("Movie '%s' is %d x %d\n", aviFileName, movWidth, movHeight); #endif #if 0 if ((movWidth & (movWidth-1)) != 0 || (movHeight & (movHeight-1)) != 0) { Quit("Movie must have frames that are a power of two in size, " "movie is %d x %d\n", movWidth, movHeight); } #endif pbmih = &pbmiMovie->bmiHeader; memset(pbmih, 0, sizeof(BITMAPINFOHEADER)); pbmih->biSize = sizeof(BITMAPINFOHEADER); pbmih->biWidth = movWidth; pbmih->biHeight = movHeight; pbmih->biPlanes = 1; pbmih->biBitCount = 8; pbmih->biCompression = BI_RGB; aviGetFrame = AVIStreamGetFrameOpen(aviStream, pbmih); if (aviGetFrame == NULL) { Quit("AVIStreamGetFrameOpen failed\n"); } } BOOL WINAPI texCallback(LPDDSURFACEDESC pddsd, LPVOID pv) { if ((paletted && pddsd->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) || (!paletted && pddsd->ddpfPixelFormat.dwFlags == DDPF_RGB)) { ddsdTex = *pddsd; return FALSE; } else { return TRUE; } } void CreateTex(int minWidth, int minHeight) { LPDIRECTDRAW pdd; HRESULT hr; texWidth = 1; texHeight = 1; while (texWidth < minWidth && texWidth < winWidth) { texWidth *= 2; } if (texWidth > winWidth) { texWidth /= 2; } while (texHeight < minHeight && texHeight < winHeight) { texHeight *= 2; } if (texHeight > winHeight) { texHeight /= 2; } if (!wglEnumTextureFormats(texCallback, NULL)) { Quit("wglEnumTextureFormats failed, %d\n", GetLastError()); } hr = DirectDrawCreate(NULL, &pdd, NULL); if (hr != DD_OK) { Quit("DirectDrawCreate failed, 0x%08lX\n", hr); } hr = pdd->lpVtbl->SetCooperativeLevel(pdd, NULL, DDSCL_NORMAL); if (hr != DD_OK) { Quit("SetCooperativeLevel failed, 0x%08lX\n", hr); } ddsdTex.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT; ddsdTex.dwWidth = texWidth; ddsdTex.dwHeight = texHeight; ddsdTex.ddsCaps.dwCaps &= ~DDSCAPS_MIPMAP; hr = pdd->lpVtbl->CreateSurface(pdd, &ddsdTex, &pddsTex, NULL); if (hr != DD_OK) { Quit("Texture CreateSurface failed, 0x%08lX\n", hr); } ClearTex(); } void Init(void) { HDC hdc, screen; HFONT fnt; pfnColorTableEXT = (PFNGLCOLORTABLEEXTPROC) wglGetProcAddress("glColorTableEXT"); if (pfnColorTableEXT == NULL) { Quit("glColorTableEXT not supported\n"); } pfnColorSubTableEXT = (PFNGLCOLORSUBTABLEEXTPROC) wglGetProcAddress("glColorSubTableEXT"); if (pfnColorSubTableEXT == NULL) { Quit("glColorSubTableEXT not supported\n"); } pbmiMovie = (BITMAPINFO *)malloc(sizeof(BITMAPINFO)+255*sizeof(RGBQUAD)); if (pbmiMovie == NULL) { Quit("Unable to allocate pbmiMovie\n"); } OpenMovie(); // Must come after movie is open so width and height are set CreateTex(movWidth, movHeight); movX = (texWidth-movWidth)/2; movY = (texHeight-movHeight)/2; wglBindDirectDrawTexture(pddsTex); // Create texture palette if necessary if (paletted) { pfnColorTableEXT(GL_TEXTURE_2D, GL_RGB, 256, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pbmiMovie->bmiColors); } glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); linearFilter = GL_FALSE; SetTexFilter(); glEnable(GL_TEXTURE_2D); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Fill in initial movie frame curFrame = 0; FrameToTex(curFrame); // Provide letters for objects to compose themselves from screen = GetDC(NULL); hdc = CreateCompatibleDC(screen); if (hdc == NULL) { Quit("CreateCompatibleDC failed, %d\n", GetLastError()); } fnt = CreateFont(72, 0, 0, 0, FW_HEAVY, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_TT_ONLY_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, DEFAULT_PITCH | TMPF_TRUETYPE | FF_DONTCARE, "Arial"); if (fnt == NULL) { Quit("CreateFont failed, %d\n", GetLastError()); } SelectObject(hdc, fnt); letters = glGenLists(NLETTERS); if (!wglUseFontOutlines(hdc, FIRST_LETTER, NLETTERS, letters, 0.0f, 0.1f, WGL_FONT_POLYGONS, letterMetrics)) { Quit("wglUseFontOutlines failed, %d\n", GetLastError()); } DeleteDC(hdc); DeleteObject(fnt); ReleaseDC(NULL, screen); BuildLists(); SetObject(0); xrot = 0.0; yrot = 0.0; SetView(); } GLenum Args(int argc, char **argv) { GLint i; winWidth = 320; winHeight = 320; doubleBuffer = GL_TRUE; videoMemory = GL_FALSE; noSwap = GL_FALSE; noClear = GL_FALSE; fullScreen = GL_FALSE; fullWidth = 640; fullHeight = 480; fullDepth = 16; useMcd = GL_FALSE; modeX = GL_FALSE; stretch = GL_TRUE; paletted = GL_TRUE; timings = GL_FALSE; spin = GL_TRUE; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-sb") == 0) { doubleBuffer = GL_FALSE; } else if (strcmp(argv[i], "-db") == 0) { doubleBuffer = GL_TRUE; } else if (strcmp(argv[i], "-rgb") == 0) { paletted = GL_FALSE; } else if (strcmp(argv[i], "-stretch") == 0) { stretch = GL_TRUE; } else if (strcmp(argv[i], "-nostretch") == 0) { stretch = GL_FALSE; } else if (strcmp(argv[i], "-nospin") == 0) { spin = GL_FALSE; } else if (strcmp(argv[i], "-vm") == 0) { videoMemory = GL_TRUE; } else if (strcmp(argv[i], "-noswap") == 0) { noSwap = GL_TRUE; } else if (strcmp(argv[i], "-noclear") == 0) { noClear = GL_TRUE; } else if (strcmp(argv[i], "-full") == 0) { fullScreen = GL_TRUE; } else if (strcmp(argv[i], "-modex") == 0) { modeX = GL_TRUE; fullWidth = 320; fullHeight = 240; fullDepth = 8; } else if (strcmp(argv[i], "-mcd") == 0) { useMcd = GL_TRUE; } else if (strcmp(argv[i], "-surf") == 0) { if (i+2 >= argc || argv[i+1][0] == '-' || argv[i+2][0] == '-') { printf("-surf (No numbers).\n"); return GL_FALSE; } else { winWidth = atoi(argv[++i]); winHeight = atoi(argv[++i]); } } else if (strcmp(argv[i], "-fdim") == 0) { if (i+3 >= argc || argv[i+1][0] == '-' || argv[i+2][0] == '-' || argv[i+3][0] == '-') { printf("-fdim (No numbers).\n"); return GL_FALSE; } else { fullWidth = atoi(argv[++i]); fullHeight = atoi(argv[++i]); fullDepth = atoi(argv[++i]); } } else if (strcmp(argv[i], "-mov") == 0) { if (i+1 >= argc || argv[i+1][0] == '-') { printf("-mov (No filename).\n"); return GL_FALSE; } else { aviFileName = argv[++i]; } } else { printf("%s (Bad option).\n", argv[i]); return GL_FALSE; } } return GL_TRUE; } void __cdecl main(int argc, char **argv) { DWORD dwFlags; GLDDWINDOW gw; if (Args(argc, argv) == GL_FALSE) { exit(1); } dwFlags = GLDD_Z_BUFFER_16; dwFlags |= doubleBuffer ? GLDD_BACK_BUFFER : 0; dwFlags |= videoMemory ? GLDD_VIDEO_MEMORY : 0; dwFlags |= useMcd ? GLDD_GENERIC_ACCELERATED : 0; if (fullScreen) { dwFlags |= GLDD_FULL_SCREEN; dwFlags |= modeX ? GLDD_USE_MODE_X : 0; winWidth = fullWidth; winHeight = fullHeight; } gw = glddCreateWindow("Video Texture", 10, 30, winWidth, winHeight, fullDepth, dwFlags); if (gw == NULL) { printf("glddCreateWindow failed with 0x%08lX\n", glddGetLastError()); exit(1); } gwMain = gw; glddMakeCurrent(gw); Init(); glddIdleCallback(gw, Animate); glddMessageCallback(gw, Message); glddRun(gw); Quit(NULL); }