Problem: use separate GLUT windows with own callbacks and drawing functions.
Example: written on C++, freeglut.
Languages:
EN,
RU
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
|
Created window inherits OS's windows style.
At pictures it is running on Ubuntu 16.04LTS.
Addition: GLUT is a powerful but simple windows manager. We can not make some
OS-like operations like hiding window's header or keep window always on top of
other windows.
We initializing two windows sequently. For each write own display function.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
|
Generally, problem is solved. But in future we may want to have more than two
windows and with more harder callbacks logic. Let's try encapsulate window
managment inside class for more scalability.
Make step backward to single window problem and implement class with same usage.
class GLView { | |
public: | |
GLView(const char* title); | |
private: | |
static void display(); | |
}; |
Header of our class has all that we need. User choose window title only. Now main function use single line for create similar window. In sight of class user it is easy to use without care about internal implementation.
int main(int argc, char** argv) { | |
GLView glview("Single view"); | |
glutMainLoop(); | |
return 0; | |
} |
In sight of class we just encpsulated existing usage inside corresponding methods. Note that functions is static. It is required for registering callbacks.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
|
We need to provide few windows management. Due to display function is static, it
is same for different class objects. But we need to separate displaying.
Let's make display as abstract function that will be implemented inside
an inherited classes. As callback we calling each display of created window.
class GLView { | |
public: | |
GLView(const char* title); | |
protected: | |
virtual void display() = 0; | |
private: | |
static void display_all(); | |
static std::vector<GLView*> glviews; | |
int window_id; | |
}; |
We will see that display_all function is registered as callback for each window i.e. in case of single display request we redisplay every other window.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
|
void GLView::display_all() { | |
for (int i = 0; i < glviews.size(); ++i) { | |
glutSetWindow(glviews[i]->window_id); | |
glviews[i]->display(); | |
} | |
} |
For new window we implements class with own display.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
|
In addition let's try merge two windows inside single window. But each subwindow
has own callbacks.
GLUT has method glutCreateSubWindow(..) which creates new window in space of
existing parent window.
GLView::GLView(const char* title, GLView* parent) { | |
if (glviews.empty()) { | |
int argc = 0; | |
glutInit(&argc, 0); // GLUT initialization. | |
} | |
// Window initialization. | |
if (parent != 0) { | |
// Receive parent's id, x, y, width and height. Subwindows has not titles. | |
window_id = glutCreateSubWindow(parent->window_id, 0, 0, 128, 128); | |
} else { | |
glutInitWindowSize(324, 324); // Width, height of window. | |
glutInitWindowPosition(0, 0); // (x, y) position of window from top-left. | |
window_id = glutCreateWindow(title); | |
} | |
glviews.push_back(this); | |
glutDisplayFunc(display_all); // Set callback. | |
} |
Addition: subwindow has constant shape although parent size changes. If needed, we can make own child reshape using relative coordinates and parent's reshape callback.