Alright so I'm just trying to open a basic window with GLFW, and while it opens and get's cleared to black, it hangs and the circle waiting cursor appears. The GUI is unusable and the whole program just freezes.
Any help?
EDIT is there a way to manually create a window and have glfw attach to that window?
Code:
// Attempt to start up GLFW
f1("Attempting to start up GLFW");
if(!glfwInit())
{
e("Could not start up GLFW!");
SetVError(V_ERR_OGL_GLFWINIT);
return false;
}
// Create window hints
f1("Setting window hints");
glfwOpenWindowHint(GLFW_FSAA_SAMPLES, V_OGL_ANTIALIAS);
glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3); // We want 4.0!
glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 2);
glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Create the window
f1("Creating main window");
if(!glfwOpenWindow(V_OGL_WINDOW_W, V_OGL_WINDOW_H, 0, 0, 0, 0, 0, 0, GLFW_WINDOW))
{
e("Could not create main window!");
SetVError(V_ERR_OGL_WINDOW);
return false;
}
// Attempt to start up Glew
f1("Attempting to startup Glew");
if(glewInit() != GLEW_OK)
{
// Error and return
e("Could not instantiate Glew!");
SetVError(V_ERR_OGL_GLEWINIT);
return false;
}
// Set the window's title
f1("Setting window title");
glfwSetWindowTitle(V_WINDOW_TITLE);
// Clear the screen / set BG color
f1("Clearing background");
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
// Lastly, setup basic sticky keys
f1("Enabling sticky keys");
glfwEnable(GLFW_STICKY_KEYS);
Main code:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevious, LPSTR lpComString, int nShowCmd)
{
// Generate logger instance (instantiate logging)
VLogInit();
// Log Title + Version
i("VOGL Test "V_FULLVERSION);
// Init OpenGL/Graphics
if(!OGLStartup())
return GetLastVError();
else // Log that we succeeded
f1("OGLStartup succeeded!");
// Fork thread for window events
hMainWindow = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&tcbMainWindow, NULL, 0, thMainWindow);
// Alloc statuc
DWORD status;
// Wait for all threads to return
while(true)
{
// Main Window
GetExitCodeThread(hMainWindow, &status);
if(status != STILL_ACTIVE)
break;
// Sleep for a little bit
Sleep(10);
}
// All okay!
f1("Terminating Program");
return V_SUCCESS;
}
DWORD tcbMainWindow(LPVOID lpdwThreadParam)
{
// Begin window loop
do
{
} // Escape key or window closed
while(glfwGetKey(GLFW_KEY_ESC) != GLFW_PRESS && glfwGetWindowParam(GLFW_OPENED));
// Success!
return V_SUCCESS;
}
And yes, everything is logging correctly.
http://pastebin.com/sQ2pw2wN
You must swap the back and front framebuffers in your main loop, like this:
// Begin window loop
do
{
glfwSwapBuffers(); // <<<
} // Escape key or window closed
while(glfwGetKey(GLFW_KEY_ESC) != GLFW_PRESS
&& glfwGetWindowParam(GLFW_OPENED));
Why it freeze?
glfw manage operating system events (like refreshing the window, key that get pressed, ...) when you call glfwSwapBuffers (usually).
Related
I'm trying to attach a glfw window to an electron one.
I've succesfully retrieved the electron window handle (electronWindow.getNativeWindowHandle()) in my glfw app, and then used win32 api to try and attach them to one another :
GLFWwindow* createWindow(HWND parentWindow)
{
// Create an invisible window
fprintf(stdout, "Creating window as child of window 0x%016x\n", parentWindow);
glfwDefaultWindowHints();
glfwWindowHint(GLFW_RESIZABLE, FALSE);
glfwWindowHint(GLFW_DECORATED, GLFW_FALSE);
glfwWindowHint(GLFW_VISIBLE, GLFW_TRUE);
GLFWwindow* window = glfwCreateWindow(800, 600, "", nullptr, nullptr);
// That we attach as a child to an other one
HWND hw = glfwGetWin32Window(window);
HWND previousParent = SetParent(hw, parentWindow);
if (!previousParent) {
fprintf(stderr, "Couldn't set window parent: %s\n", lastWindowsError().c_str());
glfwDestroyWindow(window);
return nullptr;
}
ShowWindow(hw, SW_SHOW);
return window;
}
The SetParent call doesn't fail so I'm assuming the connection is made.
Then I have my (very classical) main glfw loop like this :
while (!glfwWindowShouldClose(window))
{
glClearColor(0.3, 0.4, 0.8, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glfwPollEvents();
glfwSwapBuffers(window);
}
So the "faulty" behavior I've got is the following :
The electron app freezes. Nothing moves, the process is "not responding"
My glfw window doesn't show up anywhere
I haven't done an win32 event handling on glfw side, could this be the issue ? Like some specific event I have to take care of ?
Is this an issue with the electron app not passing events to the glfw window, hence blocking everything ?
Note: I'm doing this because I want to display native opengl using a pre-existing engine we've got.
I've tried naively doing glfwSetWindowPos each time the electron window moves, but it's sluggish as hell (probably Windows preventing this behavior) so I'm trying other approaches (here : attaching the opengl window as a child of electron).
So it seems it's not a very good idea haha + I'm not that good with win32 api so I can't really tell what's not working (cf. #iinspectable comments)
I delved into this issue on electron's github : https://github.com/electron/electron/issues/10547 and found a way to display an OpenGL frame on top of an Electron window.
I circumvented the issue by creating the window as a child process of the electron app with the HWND as startup argument :
const { app, BrowserWindow } = require('electron')
const { endianness } = require('os')
const { spawn } = require('child_process')
const nativeExecutablePath = 'src/overlay/build/Release/kf-overlay.exe'
const indexPath = 'src/ui/html/index.html'
const startChildProcess = (hwnd, target) => {
const data = endianness() == 'LE'
? hwnd.readInt32LE()
: hwnd.readInt32BE()
const p = spawn(target, [data], { cwd: process.cwd() })
p.stdout.on('data', data => console.log(`[native] ${data}`))
p.stderr.on('data', data => console.log(`[native] ${data}`))
}
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600
})
// win.loadFile(indexPath)
win.loadURL('https://www.google.com')
win.webContents.setFrameRate(60)
console.log(`Starting child process ${nativeExecutablePath}`)
const hwnd = win.getNativeWindowHandle()
startChildProcess(hwnd, nativeExecutablePath)
}
app.whenReady().then(() => {
createWindow()
})
Then creating the window as a child from C++ side :
HWND createChildWindow(HWND parent)
{
RECT rect;
GetWindowRect(parent, &rect);
int parentWidth = rect.right - rect.left;
int parentHeight = rect.bottom - rect.top;
DWORD style = WS_VISIBLE | WS_CHILD | WS_POPUP;
auto child = CreateWindowEx(
WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_COMPOSITED,
WINDOW_CLASS_NAME,
nullptr,
style,
parentWidth / 2 - 512,
parentHeight / 2 - 512,
512,
512,
parent,
nullptr,
nullptr,
nullptr
);
SetParent(child, parent);
return child;
}
Finally I could create the OpenGL context through wglCreateContext calls, and render a frame with OpenGL calls :)
I am porting my application to Linux, and I am using the XCB library for window handling. I need to detect when the window closes, so that the application can exit. However, the system cannot block on the main window loop due to the way the system is designed. This is easy in Windows, since you just use PeekMessage. However, xcb does not seem to work when I try to detect XCB_CLIENT_MESSAGE using xcb_poll_for_event. The close button on the window in fact has no functionality when I try to inject the WM_DELETE_WINDOW protocol.
Window setup:
// initialize XCB
this->connection = xcb_connect(NULL, NULL);
this->screen = xcb_setup_roots_iterator(xcb_get_setup(this->connection)).data;;
// create window
u32 mask = 0;
u32 values[1];
this->window = xcb_generate_id(this->connection);
mask = XCB_CW_EVENT_MASK;
values[0] = XCB_EVENT_MASK_EXPOSURE;
xcb_create_window(this->connection, 0, this->window, this->screen->root, 0, 0, width, height, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, this->screen->root_visual, mask, values);
// setup close handler event
xcb_intern_atom_cookie_t protocolCookie = xcb_intern_atom_unchecked(this->connection, 1, 12, "WM_PROTOCOLS");
xcb_intern_atom_reply_t* protocolReply = xcb_intern_atom_reply(this->connection, protocolCookie, 0);
xcb_intern_atom_cookie_t closeCookie = xcb_intern_atom_unchecked(this->connection, 0, 16, "WM_DELETE_WINDOW");
this->m_closeReply = xcb_intern_atom_reply(this->connection, closeCookie, 0);
xcb_change_property(this->connection, XCB_PROP_MODE_REPLACE, this->window, protocolReply->atom, 4, 32, 1, &(this->m_closeReply->atom));
free(protocolReply);
// map and flush
xcb_map_window(this->connection, this->window);
xcb_flush(this->connection);
Message loop:
// handle all incoming messages
xcb_generic_event_t* e;
while(e = xcb_poll_for_event(connection))
{
// take action from message
switch(e->response_type & ~0x80)
{
case XCB_EXPOSE:
// invalidated
xcb_flush(connection);
break;
case XCB_CLIENT_MESSAGE:
// close window
if(((xcb_client_message_event_t*)e)->data.data32[0] == (*this->m_closeReply).atom)
return false;
break;
}
// cleanup
free(e);
}
Window closing works flawlessly when I replace xcb_poll_for_event with xcb_wait_for_event, but then the window loop is blocked on waiting for messages. I just need to know what I am doing wrong for the event to never get detected when using xcb_poll_for_event.
In my current project I am working on I would like to make the opengl viewport window resize from when the user resizes the drag window ("SizeBox"), I planned on using the windows "ENTERSIZEMOVE" function from the windows.h window api to get the signal to redraw the viewport.I would then call "UpdateRender" to update my viewport.
On running my program I only seem to get one update call to resize the window (even if I stop and start dragging again),I also have a cube in the scene which is rotating it is entered (0.0f,0.0f,10.of). I wanted the cube to move along with the window "resizing" instead of it getting covered over by the window,Since the cube is set to the centre of the viewport so if I am correct I should not need to move it via a gltransform.
If anyone has any thoughts on why I am not getting a constant viewport "refresh" from the window being dragged it would be much appreciated.
Message loop handler (snippet)
{ case WM_ENTERSIZEMOVE:
render->UpdateRender();
break;
}
Update Render
void Render::UpdateRender()
{
int update_x = rect.right - rect.left;
int update_y = rect.bottom - rect.top;
glViewport(0,0 ,update_y/2,update_x/2);
}
Create Window
int window::Wincreate(HINSTANCE hInstance, char *winname, int winwidth, int winheight)
{
Hwnd = CreateWindow("Game Engine", winname, WS_VISIBLE | WS_SYSMENU | WS_SIZEBOX | WS_MAXIMIZEBOX | WS_MAXIMIZE, 0, 0, winwidth , winheight , 0, 0, hInstance, 0);
if (!Hwnd)
{
MessageBox(0, "Error: Could not Create Window", "Error", MB_OK);
}
Engine->EnableOGLAPI();
Draw->Initalize();
return 0;
}
Main application Loop
int window::Winloop(MSG msg)
{
while (running)
{
if (PeekMessage(&msg,0,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
angle++;
Draw->MainRender();
SwapBuffers(hDC);
}
}
return 0;
}
This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 6 years ago.
Here's my (O.K. not my :)) code:
/*
* This Code Was Created By Jeff Molofee 2000
* A HUGE Thanks To Fredric Echols For Cleaning Up
* And Optimizing This Code, Making It More Flexible!
* If You've Found This Code Useful, Please Let Me Know.
* Visit My Site At nehe.gamedev.net
*/
#include <windows.h> // Header File For Windows
#include <gl\gl.h> // Header File For The OpenGL32 Library
#include <gl\glu.h> // Header File For The GLu32 Library
#include <gl\GLaux.h> // Header File For The Glaux Library
HDC hDC=NULL; // Private GDI Device Context
HGLRC hRC=NULL; // Permanent Rendering Context
HWND hWnd=NULL; // Holds Our Window Handle
HINSTANCE hInstance; // Holds The Instance Of The Application
bool keys[256]; // Array Used For The Keyboard Routine
bool active=TRUE; // Window Active Flag Set To TRUE By Default
bool fullscreen=TRUE; // Fullscreen Flag Set To Fullscreen Mode By Default
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc
GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize And Initialize The GL Window
{
if (height==0) // Prevent A Divide By Zero By
{
height=1; // Making Height Equal One
}
glViewport(0,0,width,height); // Reset The Current Viewport
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix
// Calculate The Aspect Ratio Of The Window
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glLoadIdentity(); // Reset The Modelview Matrix
}
int InitGL(GLvoid) // All Setup For OpenGL Goes Here
{
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
return TRUE; // Initialization Went OK
}
int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
glLoadIdentity(); // Reset The Current Modelview Matrix
return TRUE; // Everything Went OK
}
GLvoid KillGLWindow(GLvoid) // Properly Kill The Window
{
if (fullscreen) // Are We In Fullscreen Mode?
{
ChangeDisplaySettings(NULL,0); // If So Switch Back To The Desktop
ShowCursor(TRUE); // Show Mouse Pointer
}
if (hRC) // Do We Have A Rendering Context?
{
if (!wglMakeCurrent(NULL,NULL)) // Are We Able To Release The DC And RC Contexts?
{
MessageBox(NULL,TEXT("Release Of DC And RC Failed."),TEXT("SHUTDOWN ERROR"),MB_OK | MB_ICONINFORMATION);
}
if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC?
{
MessageBox(NULL,TEXT("Release Rendering Context Failed."),TEXT("SHUTDOWN ERROR"),MB_OK | MB_ICONINFORMATION);
}
hRC=NULL; // Set RC To NULL
}
if (hDC && !ReleaseDC(hWnd,hDC)) // Are We Able To Release The DC
{
MessageBox(NULL,TEXT("Release Device Context Failed."),TEXT("SHUTDOWN ERROR"),MB_OK | MB_ICONINFORMATION);
hDC=NULL; // Set DC To NULL
}
if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window?
{
MessageBox(NULL,TEXT("Could Not Release hWnd."),TEXT("SHUTDOWN ERROR"),MB_OK | MB_ICONINFORMATION);
hWnd=NULL; // Set hWnd To NULL
}
if (!UnregisterClass(TEXT("OpenGL"),hInstance)) // Are We Able To Unregister Class
{
MessageBox(NULL,TEXT("Could Not Unregister Class."),TEXT("SHUTDOWN ERROR"),MB_OK | MB_ICONINFORMATION);
hInstance=NULL; // Set hInstance To NULL
}
}
/* This Code Creates Our OpenGL Window. Parameters Are: *
* title - Title To Appear At The Top Of The Window *
* width - Width Of The GL Window Or Fullscreen Mode *
* height - Height Of The GL Window Or Fullscreen Mode *
* bits - Number Of Bits To Use For Color (8/16/24/32) *
* fullscreenflag - Use Fullscreen Mode (TRUE) Or Windowed Mode (FALSE) */
BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
{
GLuint PixelFormat; // Holds The Results After Searching For A Match
WNDCLASS wc; // Windows Class Structure
DWORD dwExStyle; // Window Extended Style
DWORD dwStyle; // Window Style
RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values
WindowRect.left=(long)0; // Set Left Value To 0
WindowRect.right=(long)width; // Set Right Value To Requested Width
WindowRect.top=(long)0; // Set Top Value To 0
WindowRect.bottom=(long)height; // Set Bottom Value To Requested Height
fullscreen=fullscreenflag; // Set The Global Fullscreen Flag
hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Size, And Own DC For Window.
wc.lpfnWndProc = (WNDPROC) WndProc; // WndProc Handles Messages
wc.cbClsExtra = 0; // No Extra Window Data
wc.cbWndExtra = 0; // No Extra Window Data
wc.hInstance = hInstance; // Set The Instance
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load The Default Icon
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load The Arrow Pointer
wc.hbrBackground = NULL; // No Background Required For GL
wc.lpszMenuName = NULL; // We Don't Want A Menu
wc.lpszClassName = TEXT("OpenGL"); // Set The Class Name
if (!RegisterClass(&wc)) // Attempt To Register The Window Class
{
MessageBox(NULL,TEXT("Failed To Register The Window Class."),TEXT("ERROR"),MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if (fullscreen) // Attempt Fullscreen Mode?
{
DEVMODE dmScreenSettings; // Device Mode
memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared
dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure
dmScreenSettings.dmPelsWidth = width; // Selected Screen Width
dmScreenSettings.dmPelsHeight = height; // Selected Screen Height
dmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per Pixel
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,TEXT("The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?"),TEXT("NeHe GL"),MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
{
fullscreen=FALSE; // Windowed Mode Selected. Fullscreen = FALSE
}
else
{
// Pop Up A Message Box Letting User Know The Program Is Closing.
MessageBox(NULL,TEXT("Program Will Now Close."),TEXT("ERROR"),MB_OK|MB_ICONSTOP);
return FALSE; // Return FALSE
}
}
}
if (fullscreen) // Are We Still In Fullscreen Mode?
{
dwExStyle=WS_EX_APPWINDOW; // Window Extended Style
dwStyle=WS_POPUP; // Windows Style
ShowCursor(FALSE); // Hide Mouse Pointer
}
else
{
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended Style
dwStyle=WS_OVERLAPPEDWINDOW; // Windows Style
}
AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requested Size
// Create The Window
if (!(hWnd=CreateWindowEx( dwExStyle, // Extended Style For The Window
TEXT("OpenGL"), // Class Name
TEXT("title"), // Window Title
dwStyle | // Defined Window Style
WS_CLIPSIBLINGS | // Required Window Style
WS_CLIPCHILDREN, // Required Window Style
0, 0, // Window Position
WindowRect.right-WindowRect.left, // Calculate Window Width
WindowRect.bottom-WindowRect.top, // Calculate Window Height
NULL, // No Parent Window
NULL, // No Menu
hInstance, // Instance
NULL))) // Dont Pass Anything To WM_CREATE
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,TEXT("Window Creation Error."),TEXT("ERROR"),MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be
{
sizeof(PIXELFORMATDESCRIPTOR), // 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
};
if (!(hDC=GetDC(hWnd))) // Did We Get A Device Context?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,TEXT("Can't Create A GL Device Context."),TEXT("ERROR"),MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) // Did Windows Find A Matching Pixel Format?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,TEXT("Can't Find A Suitable PixelFormat."),TEXT("ERROR"),MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if(!SetPixelFormat(hDC,PixelFormat,&pfd)) // Are We Able To Set The Pixel Format?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,TEXT("Can't Set The PixelFormat."),TEXT("ERROR"),MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if (!(hRC=wglCreateContext(hDC))) // Are We Able To Get A Rendering Context?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,TEXT("Can't Create A GL Rendering Context."),TEXT("ERROR"),MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if(!wglMakeCurrent(hDC,hRC)) // Try To Activate The Rendering Context
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,TEXT("Can't Activate The GL Rendering Context."),TEXT("ERROR"),MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
ShowWindow(hWnd,SW_SHOW); // Show The Window
SetForegroundWindow(hWnd); // Slightly Higher Priority
SetFocus(hWnd); // Sets Keyboard Focus To The Window
ReSizeGLScene(width, height); // Set Up Our Perspective GL Screen
if (!InitGL()) // Initialize Our Newly Created GL Window
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,TEXT("Initialization Failed."),TEXT("ERROR"),MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
return TRUE; // Success
}
LRESULT CALLBACK WndProc( HWND hWnd, // Handle For This Window
UINT uMsg, // Message For This Window
WPARAM wParam, // Additional Message Information
LPARAM lParam) // Additional Message Information
{
switch (uMsg) // Check For Windows Messages
{
case WM_ACTIVATE: // Watch For Window Activate Message
{
if (!HIWORD(wParam)) // Check Minimization State
{
active=TRUE; // Program Is Active
}
else
{
active=FALSE; // Program Is No Longer Active
}
return 0; // Return To The Message Loop
}
case WM_SYSCOMMAND: // Intercept System Commands
{
switch (wParam) // Check System Calls
{
case SC_SCREENSAVE: // Screensaver Trying To Start?
case SC_MONITORPOWER: // Monitor Trying To Enter Powersave?
return 0; // Prevent From Happening
}
break; // Exit
}
case WM_CLOSE: // Did We Receive A Close Message?
{
PostQuitMessage(0); // Send A Quit Message
return 0; // Jump Back
}
case WM_KEYDOWN: // Is A Key Being Held Down?
{
keys[wParam] = TRUE; // If So, Mark It As TRUE
return 0; // Jump Back
}
case WM_KEYUP: // Has A Key Been Released?
{
keys[wParam] = FALSE; // If So, Mark It As FALSE
return 0; // Jump Back
}
case WM_SIZE: // Resize The OpenGL Window
{
ReSizeGLScene(LOWORD(lParam),HIWORD(lParam)); // LoWord=Width, HiWord=Height
return 0; // Jump Back
}
}
// Pass All Unhandled Messages To DefWindowProc
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
int WINAPI WinMain( HINSTANCE hInstance, // Instance
HINSTANCE hPrevInstance, // Previous Instance
LPSTR lpCmdLine, // Command Line Parameters
int nCmdShow) // Window Show State
{
MSG msg; // Windows Message Structure
BOOL done=FALSE; // Bool Variable To Exit Loop
// Ask The User Which Screen Mode They Prefer
if (MessageBox(NULL,TEXT("Would You Like To Run In Fullscreen Mode?"), TEXT("Start FullScreen?"),MB_YESNO|MB_ICONQUESTION)==IDNO)
{
fullscreen=FALSE; // Windowed Mode
}
// Create Our OpenGL Window
if (!CreateGLWindow("NeHe's OpenGL Framework",640,480,16,fullscreen))
{
return 0; // Quit If Window Was Not Created
}
while(!done) // Loop That Runs While done=FALSE
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) // Is There A Message Waiting?
{
if (msg.message==WM_QUIT) // Have We Received A Quit Message?
{
done=TRUE; // If So done=TRUE
}
else // If Not, Deal With Window Messages
{
TranslateMessage(&msg); // Translate The Message
DispatchMessage(&msg); // Dispatch The Message
}
}
else // If There Are No Messages
{
// Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()
if (active) // Program Active?
{
if (keys[VK_ESCAPE]) // Was ESC Pressed?
{
done=TRUE; // ESC Signalled A Quit
}
else // Not Time To Quit, Update Screen
{
DrawGLScene(); // Draw The Scene
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
}
}
if (keys[VK_F1]) // Is F1 Being Pressed?
{
keys[VK_F1]=FALSE; // If So Make Key FALSE
KillGLWindow(); // Kill Our Current Window
fullscreen=!fullscreen; // Toggle Fullscreen / Windowed Mode
// Recreate Our OpenGL Window
if (!CreateGLWindow("NeHe's OpenGL Framework",640,480,16,fullscreen))
{
return 0; // Quit If Window Was Not Created
}
}
}
}
// Shutdown
KillGLWindow(); // Kill The Window
return (msg.wParam); // Exit The Program
}
How I can solve problem with unresolved externals?
I can't post image so here's link to image with some errors what my VC++ Express wrote: http://i.stack.imgur.com/2v2US.png
Unresolved externals usually means you did not input the correct libraries. In your project settings, what OpenGL libraries did you include? Standard is
opengl32.lib
glu32.lib
in your project linker settings.
Well, I'm trying to make the day/night cycle in a scene using opengl with c++. I've tried glutTimerFunc. Although I 've bounded the time slice to be 10000 ms = 10 s, it gave me a very fast flipping effect.
Here is what I have done.
void turn (int value){
if(night)
{
glDisable(GL_LIGHT0);
glEnable(GL_LIGHT1);
night=!night;
}
else
{
glDisable(GL_LIGHT1);
glEnable(GL_LIGHT0);
night=!night;
}
//glutPostRedisplay();
glutTimerFunc(10000,&turn,2);
}
And in DrawGLScene function I 've called that function. And here is the WinMain function:
int WINAPI WinMain( HINSTANCE hInstance, // Instance
HINSTANCE hPrevInstance, // Previous Instance
LPSTR lpCmdLine, // Command Line Parameters
int nCmdShow) // Window Show State
{
MSG msg; // Windows Message Structure
BOOL done=FALSE; // Bool Variable To Exit Loop
// 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; // Windowed Mode
//}
// Create Our OpenGL Window
if (!CreateGLWindow("day night",700,500,16,fullscreen))
{
return 0; // Quit If Window Was Not Created
}
glutTimerFunc(10000,&turn,2);
//turn(1);
while(!done) // Loop That Runs While done=FALSE
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) // Is There A Message Waiting?
{
if (msg.message==WM_QUIT) // Have We Received A Quit Message?
{
done=TRUE; // If So done=TRUE
}
else // If Not, Deal With Window Messages
{
TranslateMessage(&msg); // Translate The Message
DispatchMessage(&msg); // Dispatch The Message
}
}
else // If There Are No Messages
{
// Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()
if (active) // Program Active?
{
if (keys[VK_ESCAPE]) // Was ESC Pressed?
{
done=TRUE; // ESC Signalled A Quit
}
else // Not Time To Quit, Update Screen
{
DrawGLScene(); // Draw The Scene
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
}
}
if (keys[VK_F1]) // Is F1 Being Pressed?
{
keys[VK_F1]=FALSE; // If So Make Key FALSE
KillGLWindow(); // Kill Our Current Window
fullscreen=!fullscreen; // Toggle Fullscreen / Windowed Mode
// Recreate Our OpenGL Window
if (!CreateGLWindow("day night",700,500,16,fullscreen))
{
return 0; // Quit If Window Was Not Created
}
}
}
}
// Shutdown
KillGLWindow(); // Kill The Window
return (msg.wParam); // Exit The Program
}
If your DrawGLScene has been registered using glutDisplayFunc and is therefore called to draw each frame then you'll also be (re)registering your timer function every time you redraw the frame, i.e. every time you call glutPostRedisplay().
To start the timer sequence you should just call glutTimerFunc once, before you call glutMainLoop, and not call it in DrawGLScene.
It's still necessary to call glutTimerFunc within the timer function to initiate the next flip.
EDIT I see you're not even using glutMainLoop. This means that your call to glutTimerFunc isn't doing anything. GLUT based handlers only work when they're dispatched by the glutMainLoop function.
The only reason your code is doing anything at all is because you're calling DrawGLScene within a Windows event loop which then directly calls your timer function in each pass through the Windows event loop. This is the source of the unexpectedly high frequency.
If you intend to stick with using the Windows event model then you'd be better off just using standard Windows timer events (i.e. SetTimer) to handle the flips.
Alternatively rewrite your code to use glutMainLoop and have all of the keypresses and other events handled by GLUT.
This is because real day/night is not a boolean, it is a gradual change between day and night. In addition, only 10 seconds is a very short day/night cycle- you usually want a few minutes at least.