static void DestroyCrt(void) { _CrtRender.Destroy(); DestroyGLWindow(); }
void eglWindow::OnClose(WPARAM wParam, LPARAM lParam) { DestroyGLWindow(); PostQuitMessage(0); }
BOOL eglWindow::Create(BOOL fullscreen, const char *title, int width, int height, int bits,LPTSTR menu) { if(!eglWindow::RegisterWindow(mHInstance)) return FALSE; GLuint PixelFormat; // Holds The Results After Searching For A Match DWORD dwExStyle; // Window Extended Style DWORD dwStyle; // Window Style RECT ClientRect; ClientRect.left = (long)0; ClientRect.right = (long)width; ClientRect.top = (long)0; ClientRect.bottom = (long)height; mFullscreen = fullscreen; if(mFullscreen) { DEVMODE dm; // Device Mode memset(&dm, 0, sizeof(dm)); // Makes Sure Memory's Cleared dm.dmSize = sizeof(dm); // Size Of The Devmode Structure dm.dmPelsHeight = height; // Selected Screen Height dm.dmPelsWidth = width; // Selected Screen Width dm.dmBitsPerPel = bits; // Selected Bits Per Pixel dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; if(ChangeDisplaySettings(&dm, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) { if(MessageBox(NULL, TEXT("ÇöÀçÀÇ ºñµð¿ÀÄ«µå¿¡¼ Ç®½ºÅ©¸°À» Áö¿øÇÏÁö ¾Ê½À´Ï´Ù. º¸ÅëȸéÀ¸·Î º¸½Ã°Ú½À´Ï±î?"), TEXT("¿À·ù"), MB_YESNO | MB_ICONEXCLAMATION) == IDYES) { mFullscreen = FALSE; } else { MessageBox(NULL, TEXT("ÇÁ·Î±×·¥À» Á¾·áÇÕ´Ï´Ù"), TEXT("¾Ë¸²"), MB_OK | MB_ICONSTOP); PostQuitMessage(0); return FALSE; //exit } } } if(mFullscreen) { dwExStyle = WS_EX_APPWINDOW; dwStyle = WS_POPUP; //ShowCursor(false); } else { dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; dwStyle = WS_OVERLAPPEDWINDOW; } AdjustWindowRectEx(&ClientRect, dwStyle, false, dwExStyle); // Adjust Window To true Requested Size mHWnd = CreateWindowEx( dwExStyle, "eglWindow", title, dwStyle|WS_CLIPSIBLINGS|WS_CLIPCHILDREN, 0, 0, ClientRect.right-ClientRect.left, ClientRect.bottom-ClientRect.top, (HWND)NULL, (HMENU)((!fullscreen) ? LoadMenu(mHInstance, menu) : NULL), mHInstance, (LPVOID)this); //¸Þ¼¼Áö¸ÊÀ» À§ÇÏ¿© this Æ÷ÀÎÅ͸¦ ³Ñ±ä´Ù. if(!mHWnd) { MessageBox(NULL, TEXT("À©µµ¿ì¸¦ »ý¼ºÇϴµ¥ ½ÇÆÐÇß½Àˆ•"), TEXT("¿À·ù"), MB_OK | MB_ICONEXCLAMATION); return FALSE; } static PIXELFORMATDESCRIPTOR pfd = { sizeof(pfd), // Size Of This Pixel Format Descriptor 1, // Version Number PFD_DRAW_TO_WINDOW | // Format Must Support Window PFD_SUPPORT_OPENGL | // Format Must Support OpenGL PFD_DOUBLEBUFFER, // Must Support Double Buffering PFD_TYPE_RGBA, // Request An RGBA Format bits, // Select Our 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, // Accumulation Bits Ignored 16, // 16Bit Z-Buffer (Depth Buffer) 0, // No Stencil Buffer 0, // No Auxiliary Buffer PFD_MAIN_PLANE, // Main Drawing Layer 0, // Reserved 0, 0, 0 // Layer Masks Ignored }; // Did We Get A Device Context? if(!(mDC = GetDC(mHWnd))) { DestroyGLWindow(); MessageBox(NULL, TEXT("GL Device Context ¸¦ »ý¼ºÇÒ ¼ö ¾ø½À´Ï´Ù"), TEXT("¿À·ù"), MB_OK | MB_ICONEXCLAMATION); return FALSE; } // Did Windows Find A Matching Pixel Format? if (!(PixelFormat = ChoosePixelFormat(mDC, &pfd))) { DestroyGLWindow(); MessageBox(NULL, TEXT("ÀåÄ¡¿¡ ¸Â´Â Çȼ¿Çü½ÄÀ» ãÁö ¸øÇß½À´Ï´Ù"), TEXT("¿À·ù"), MB_OK | MB_ICONEXCLAMATION); return FALSE; } // Are We Able To Set The Pixel Format? if(!SetPixelFormat(mDC, PixelFormat, &pfd)) { DestroyGLWindow(); MessageBox(NULL, TEXT("Çȼ¿Çü½ÄÀ» ¼³Á¤ÇÒ ¼ö ¾ø½À´Ï´Ù"), TEXT("¿À·ù"), MB_OK | MB_ICONEXCLAMATION); return FALSE; } // Are We Able To Get A Rendering Context? if (!(mRC=wglCreateContext(mDC))) { DestroyGLWindow(); MessageBox(NULL, TEXT("GL Rendering Context ¸¦ »ý¼ºÇÒ ¼ö ¾ø½À´Ï´Ù"), TEXT("¿À·ù"), MB_OK | MB_ICONEXCLAMATION); return FALSE; // Return false } // Try To Activate The Rendering Context if(!wglMakeCurrent(mDC, mRC)) { DestroyGLWindow(); MessageBox(NULL, TEXT("GL Rendering Context ¸¦ »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù"), TEXT("¿À·ù"), MB_OK | MB_ICONEXCLAMATION); return FALSE; // Return false } ShowWindow(mHWnd, SW_SHOW); // Show The Window SetForegroundWindow(mHWnd); // Slightly Higher Priority SetFocus(mHWnd); // Sets Keyboard Focus To The Window OnSize(0, MAKELPARAM(width, height)); //ÀÌÇÔ¼ö¸¦ È£ÃâÇÏÁö ¾ÊÀ¸¸é FULLSCREEN ¿¡¼ ±×¸²ÀÌ ±×·ÁÁöÁö ¾Ê´Â´Ù. // Initialize Our Newly Created GL Window if (!InitGL()) { DestroyGLWindow(); MessageBox(NULL, TEXT("ÃʱâÈ¿¡ ½ÇÆÐÇß½À´Ï´Ù"), TEXT("¿À·ù"), MB_OK | MB_ICONEXCLAMATION); return FALSE; } return TRUE; }
BOOL CreateGLWindow(CrtChar* title, CrtInt32 width, CrtInt32 height, CrtInt32 bits, bool fullscreenflag) { GLuint PixelFormat; WNDCLASS wc; DWORD dwExStyle; DWORD dwStyle; RECT WindowRect; WindowRect.left=(long)0; WindowRect.right=(long)width; WindowRect.top=(long)0; WindowRect.bottom=(long)height; fullscreen=fullscreenflag; hInstance = GetModuleHandle(NULL); wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wc.lpfnWndProc = (WNDPROC) WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = "OpenGL"; if (!RegisterClass(&wc)) { MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; } if (fullscreen) { DEVMODE dmScreenSettings; memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); dmScreenSettings.dmSize=sizeof(dmScreenSettings); dmScreenSettings.dmPelsWidth = width; dmScreenSettings.dmPelsHeight = height; dmScreenSettings.dmBitsPerPel = bits; dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; // Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar. if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL) { // If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode. if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","COLLADA_RT GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES) { fullscreen=FALSE; } else { // Pop Up A Message Box Letting User Know The Program Is Closing. MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP); return FALSE; } } } if (fullscreen) { dwExStyle=WS_EX_APPWINDOW; dwStyle=WS_POPUP; ShowCursor(FALSE); } else { dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; dwStyle=WS_OVERLAPPEDWINDOW; } AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Create The Window hWnd=CreateWindowEx( dwExStyle, "OpenGL", title, dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, 0, WindowRect.right-WindowRect.left, WindowRect.bottom-WindowRect.top, NULL, NULL, hInstance, NULL); if (!hWnd) { DestroyGLWindow(); MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; } static PIXELFORMATDESCRIPTOR pfd= { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, (BYTE)bits, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0 }; hDC=GetDC(hWnd); if (!hDC) { DestroyGLWindow(); MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; } PixelFormat=ChoosePixelFormat(hDC,&pfd); if (!PixelFormat) { DestroyGLWindow(); MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; } if(!SetPixelFormat(hDC,PixelFormat,&pfd)) { DestroyGLWindow(); MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; } hRC=wglCreateContext(hDC); if (!hRC) { DestroyGLWindow(); MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; } if(!wglMakeCurrent(hDC,hRC)) { DestroyGLWindow(); MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; } ShowWindow(hWnd,SW_SHOW); SetForegroundWindow(hWnd); SetFocus(hWnd); ResizeGLScreen(width, height); if (!InitGL()) { DestroyGLWindow(); MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; } return TRUE; }
//---------------------------------------------------------------------------------------------------- // Standard windows mainline, this is the program entry point // CrtInt32 WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, CrtInt32 nCmdShow) { (void)hPrevInstance; // Avoid warnings (void)nCmdShow; // Avoid warnings (void)hInstance; // Avoid warnings #ifndef NO_DEVIL ilInit(); #endif MSG msg; BOOL done=FALSE; // Avoid warnings later msg.wParam = 0; // Turns on windows heap debugging #if HEAP_DEBUG _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_CHECK_CRT_DF /*| _CRTDBG_DELAY_FREE_MEM_DF*/); #endif // Ask The User Which Screen Mode They Prefer // if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO) { fullscreen=FALSE; } // Set the default screen size _CrtRender.SetScreenWidth( 640); _CrtRender.SetScreenHeight( 480); // Create an OpenGL Window if (!CreateGLWindow("Collada Viewer for PC", _CrtRender.GetScreenWidth(), _CrtRender.GetScreenHeight(),32,fullscreen)) { return 0; } // Turn data dumping (debug) off //CrtBool dumpData = CrtFalse; // Initialize the renderer // !!!GAC for compatibility with the new COLLADA_FX code, Init now forces UsingCg and UsingVBOs to // !!!GAC false. It also calls CrtInitCg, creating the CG context and calling cgGLRegisterStates. // !!!GAC All these things are currently required for the cfx rendering path to work, changing them // !!!GAC may cause problems. This is work in progress and will be much cleaner when the refactor is done. _CrtRender.Init(); //_CrtRender.SetRenderDebug( CrtTrue ); // !!!GAC kept for reference, changing these may cause problems with the cfx include path //_CrtRender.SetUsingCg( CrtFalse ); // Turn off VBOs (the GL skinning path doesn't work with VBOs yet) _CrtRender.SetUsingVBOs( CrtTrue ); _CrtRender.SetUsingNormalMaps( CrtTrue ); //_CrtRender.SetRenderDebug( CrtTrue ); //_CrtRender.SetUsingShadowMaps(CrtTrue); // We might get a windows-style path on the command line, this can mess up the DOM which expects // all paths to be URI's. This block of code does some conversion to try and make the input // compliant without breaking the ability to accept a properly formatted URI. Right now this only // displays the first filename char file[512], *in = lpCmdLine, *out = file; *out = NULL; // If the first character is a ", skip it (filenames with spaces in them are quoted) if(*in == '\"') { in++; } if(*(in+1) == ':') { // Second character is a :, assume we have a path with a drive letter and add a slash at the beginning *(out++) = '/'; } int i; for(i =0; i<512; i++) { // If we hit a null or a quote, stop copying. This will get just the first filename. if(*in == NULL || *in == '\"') break; // Copy while swapping backslashes for forward ones if(*in == '\\') { *out = '/'; } else { *out = *in; } in++; out++; } // Should throw an error if i>= 512, but we don't have error dialongs in the code yet so just let it try to load and fail if(i < 511) *out = NULL; time_t seconds = time (NULL); clock_t clocka = clock (); cleaned_file_name = file; // Load the file name provided on the command line if ( !_CrtRender.Load( cleaned_file_name )) { exit(0); } time_t loadtime = time (NULL) - seconds; int clockload = (int) clock () - clocka; CrtPrint("\nLOAD TIME OF %s\n", file); CrtPrint("IS %d SECONDS\n", loadtime); CrtPrint("IS %d CLOCK TICKS\n\n", clockload); // This block of code shows how to enumerate all the effects, get their parameters and then // get their UI information. #if 1 { // Get the scene and setup to iterate over all the effects stored in the cfxLoader CrtScene *scene = _CrtRender.GetScene(); std::map<std::string, cfxEffect*>::iterator effectIterator; effectIterator = scene->cfxEffects.begin(); // Iterate over all the effects while(effectIterator != scene->cfxEffects.end()) { // This is the effect name you would use in a UI CrtPrint("Effect name %s\n", effectIterator->first.c_str()); cfxEffect *thiscfxEffect = effectIterator->second; CGeffect thisCGEffect = thiscfxEffect->getEffect(); CGparameter thisCGParameter = cgGetFirstEffectParameter(thisCGEffect); while(thisCGParameter != NULL) { // This is the parameter name you would use in the UI const char *parameterName = cgGetParameterName(thisCGParameter); // This is for the example of how to tweek a parameter (doesn't work yet) if(CrtCmp(parameterName, "Amplitude")) { // Capture the parameter and save it in a global, in a GUI you would // save this handle in the widget so it would know what to tweek. amplitudeGlobalParameter = thisCGParameter; } #if 0 // This is here for debugging, it iterates over all the annotations and prints them out // so you can see what's in them. Normally this code will be turned off. CrtPrint(" Parameter name %s\n",parameterName); CGannotation dbgCGAnnotation = cgGetFirstParameterAnnotation(thisCGParameter); while(dbgCGAnnotation != NULL) { const char *annotationName = cgGetAnnotationName(dbgCGAnnotation); CrtPrint(" Annotation: %s",annotationName); if(cgGetAnnotationType(dbgCGAnnotation) == CG_STRING) { const char *annotationString = cgGetStringAnnotationValue(dbgCGAnnotation); CrtPrint(" value: %s\n",annotationString); } else if(cgGetAnnotationType(dbgCGAnnotation) == CG_FLOAT) { int nvalues; const float *value = cgGetFloatAnnotationValues(dbgCGAnnotation, &nvalues); CrtPrint(" value: %f\n",*value); // Assume there is one value } else { CrtPrint("\n"); } dbgCGAnnotation = cgGetNextAnnotation(dbgCGAnnotation); } #endif // This code looks at the parameter annotations to see if they specify some kind of UI // cgGetNamedParameterAnnotation isn't used for this because it is case sensitive and at // least some of the annotations FXcomposer uses for UI appear to NOT be case sensitive. // This method should collect the parameter values regardless of case, but it has to scan // ALL the parameters and do case-blind compares on each one, which is slower. // This code currently only collects the annotation values for defining sliders and color pickers. const char *UIName = "unknown"; const char *UIWidget = "unknown"; float UIMin = -99999.0f; float UIMax = 99999.0f; float UIStep = 0.0f; int nvalues; CGannotation thisCGAnnotation = cgGetFirstParameterAnnotation(thisCGParameter); // Iterate over all the annotations while(thisCGAnnotation != NULL) { // Get the name of this annotation const char *annotationName = cgGetAnnotationName(thisCGAnnotation); // Do case-blind compares to see if the annotation is one of the ones used to make UI // and save the value if it is. if(CrtICmp("UIWidget",annotationName)) { // This is the widget type UIWidget = cgGetStringAnnotationValue(thisCGAnnotation); } if(CrtICmp("UIName",annotationName)) { // This is the name to attach to the widget UIName = cgGetStringAnnotationValue(thisCGAnnotation); } if(CrtICmp("UIMin",annotationName)) { // This is the minimum value for a slider widget const float *value = cgGetFloatAnnotationValues(thisCGAnnotation, &nvalues); if(nvalues == 1) UIMin = *value; } if(CrtICmp("UIMax",annotationName)) { // This is the maximum value for a slider widget const float *value = cgGetFloatAnnotationValues(thisCGAnnotation, &nvalues); if(nvalues == 1) UIMax = *value; } if(CrtICmp("UIStep",annotationName)) { // This is the step (minimum change) for a slider widget const float *value = cgGetFloatAnnotationValues(thisCGAnnotation, &nvalues); if(nvalues == 1) UIStep = *value; } // Get the next annotation thisCGAnnotation = cgGetNextAnnotation(thisCGAnnotation); } // Is the UIWidget a type that we recognize? (just slider and color picker for now) // Replace the CrtPrint with the code that generates the UI, remember the UI needs to // store thisCGParameter someplace so it can use it to change the parameter later. if(CrtICmp("slider", UIWidget)) { CrtPrint("Parameter %s needs a slider named %s going from %f to %f with step %f\n",parameterName,UIName,UIMin,UIMax, UIStep ); } if(CrtICmp("color", UIWidget)) { CrtPrint("Parameter %s needs a color picker named %s\n",parameterName,UIName); } // Move on to the next parameter thisCGParameter = cgGetNextParameter(thisCGParameter); } // Move on to the next effect effectIterator++; } } #endif while(!done) { if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { if (msg.message==WM_QUIT) { done=TRUE; } else { TranslateMessage(&msg); DispatchMessage(&msg); } } else { // Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene() if ((active && !DrawGLScene()) || keys[VK_ESCAPE]) // Active? Was There A Quit Received? { done=TRUE; } else { SwapBuffers(hDC); ProcessInput( keys ); } } } _CrtRender.Destroy(); // Shutdown #ifndef NO_DEVIL ilShutDown(); #endif DestroyGLWindow(); return (int)(msg.wParam); }
// Call ProcessInput once per frame to process input keys void ProcessInput( bool keys[] ) { // These keys we don't want to auto-repeat, so we clear them in "keys" after handling them once if (keys['E'] && amplitudeGlobalParameter) { float value; cgGetParameterValuefc(amplitudeGlobalParameter, 1, &value); value += 0.1f; cgSetParameter1f(amplitudeGlobalParameter, value); keys['E'] = false; } if (keys['R'] && amplitudeGlobalParameter) { float value; cgGetParameterValuefc(amplitudeGlobalParameter,1, &value); value -= 0.1f; cgSetParameter1f(amplitudeGlobalParameter, value); keys['R'] = false; } if (keys[VK_TAB] ) { // When 'C' is pressed, change cameras _CrtRender.SetNextCamera(); keys[VK_TAB] = false; } if ( keys['M'] ) { // Speed up UI by 25% AdjustUISpeed(1.25f); keys['M'] = false; } if ( keys['N'] ) { // Slow down UI by 25% AdjustUISpeed(0.75f); // Go 25% slower keys['N'] = false; } if (keys['Q']) { if (togglewireframe) { glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); togglewireframe = FALSE; } else { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); togglewireframe = TRUE; } keys['Q'] = false; } if (keys['K']) { if (togglehiearchy) { _CrtRender.SetShowHiearchy(CrtTrue); togglehiearchy = FALSE; } else { _CrtRender.SetShowHiearchy(CrtFalse); togglehiearchy = TRUE; } keys['K'] = false; } if (keys['L']) { if (togglelighting) { glDisable(GL_LIGHTING); togglelighting = FALSE; } else { glEnable(GL_LIGHTING); togglelighting = TRUE; } keys['L'] = false; } if (keys['P'] ) { if (sAnimationEnable) { _CrtRender.SetAnimationPaused( CrtTrue ); sAnimationEnable = false; } else { _CrtRender.SetAnimationPaused( CrtFalse ); sAnimationEnable = true; } keys['P'] = false; } if (keys[VK_F1]) { keys[VK_F1]=FALSE; _CrtRender.Destroy(); DestroyGLWindow(); fullscreen=!fullscreen; // Recreate Our OpenGL Window if (!CreateGLWindow("Collada Viewer for PC", _CrtRender.GetScreenWidth(), _CrtRender.GetScreenHeight(),32,fullscreen)) { exit(1); } if ( !_CrtRender.Load( cleaned_file_name )) { exit(0); } keys[VK_F1] = false; } // These keys that do a function as long as they are held down, so we don't clear "keys". // Remember to scale these functions by time! if (keys['S']) { // UI code to move the camera closer _CrtRender.ActiveInstanceCamera->MoveTransform(_CrtRender.GetAnimDelta() * KeyboardTranslateSpeed *0.5f, 0.0f, 0.0f); } if (keys['W']) { // UI code to move the camera farther away _CrtRender.ActiveInstanceCamera->MoveTransform(- _CrtRender.GetAnimDelta() * KeyboardTranslateSpeed * 0.5f, 0.0f, 0.0f); } if (keys[VK_SPACE]) { // UI code to move the camera farther up _CrtRender.ActiveInstanceCamera->MoveTransform(0.0f, 0.0f, _CrtRender.GetAnimDelta() * KeyboardTranslateSpeed); } if (keys['X']) { // UI code to move the camera farther down _CrtRender.ActiveInstanceCamera->MoveTransform(0.0f, 0.0f, - _CrtRender.GetAnimDelta() * KeyboardTranslateSpeed); } if (keys['D']) { // UI code to move the camera farther right _CrtRender.ActiveInstanceCamera->MoveTransform(0.0f, - _CrtRender.GetAnimDelta() * KeyboardTranslateSpeed, 0.0f); } if (keys['A']) { // UI code to move the camera farther left _CrtRender.ActiveInstanceCamera->MoveTransform(0.0f, _CrtRender.GetAnimDelta() * KeyboardTranslateSpeed, 0.0f); } if (keys['F']) { if(togglecullingface == 0) { // turn it front glEnable( GL_CULL_FACE ); glCullFace(GL_FRONT); togglecullingface = 1; } else if(togglecullingface == 1) { // turn it both glDisable( GL_CULL_FACE ); togglecullingface = 2; } else { // turn it back glEnable( GL_CULL_FACE ); glCullFace(GL_BACK); togglecullingface = 0; } keys['F'] = false; } }