1 | |
2 | //////////////////////////////////////////////////////////// |
3 | // Headers |
4 | //////////////////////////////////////////////////////////// |
5 | #include <SFML/Window.hpp> |
6 | #include <SFML/System/Err.hpp> |
7 | |
8 | #define GLAD_GL_IMPLEMENTATION |
9 | #include "gl.h" |
10 | |
11 | #include <X11/Xlib.h> |
12 | #include <iostream> |
13 | #include <cmath> |
14 | |
15 | |
16 | //////////////////////////////////////////////////////////// |
17 | /// Initialize OpenGL states into the specified view |
18 | /// |
19 | /// \param Window Target window to initialize |
20 | /// |
21 | //////////////////////////////////////////////////////////// |
22 | void initialize(sf::Window& window) |
23 | { |
24 | // Activate the window |
25 | window.setActive(); |
26 | |
27 | // Setup OpenGL states |
28 | // Set color and depth clear value |
29 | |
30 | #ifdef SFML_OPENGL_ES |
31 | glClearDepthf(1.f); |
32 | #else |
33 | glClearDepth(1.f); |
34 | #endif |
35 | |
36 | glClearColor(0.f, 0.5f, 0.5f, 0.f); |
37 | |
38 | // Enable Z-buffer read and write |
39 | glEnable(GL_DEPTH_TEST); |
40 | glDepthMask(GL_TRUE); |
41 | |
42 | // Setup a perspective projection |
43 | glMatrixMode(GL_PROJECTION); |
44 | glLoadIdentity(); |
45 | static const float pi = 3.141592654f; |
46 | float extent = std::tan(90.0f * pi / 360.0f); |
47 | |
48 | #ifdef SFML_OPENGL_ES |
49 | glFrustumf(-extent, extent, -extent, extent, 1.0f, 500.0f); |
50 | #else |
51 | glFrustum(-extent, extent, -extent, extent, 1.0f, 500.0f); |
52 | #endif |
53 | |
54 | // Enable position and texture coordinates vertex components |
55 | glEnableClientState(GL_VERTEX_ARRAY); |
56 | glEnableClientState(GL_COLOR_ARRAY); |
57 | } |
58 | |
59 | //////////////////////////////////////////////////////////// |
60 | /// Draw the OpenGL scene (a rotating cube) into |
61 | /// the specified view |
62 | /// |
63 | /// \param window Target window for rendering |
64 | /// \param elapsedTime Time elapsed since the last draw |
65 | /// |
66 | //////////////////////////////////////////////////////////// |
67 | void draw(sf::Window& window, float elapsedTime) |
68 | { |
69 | // Activate the window |
70 | window.setActive(); |
71 | |
72 | // Clear color and depth buffers |
73 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
74 | |
75 | // Apply some transformations |
76 | glMatrixMode(GL_MODELVIEW); |
77 | glLoadIdentity(); |
78 | glTranslatef(0.f, 0.f, -200.f); |
79 | glRotatef(elapsedTime * 10.f, 1.f, 0.f, 0.f); |
80 | glRotatef(elapsedTime * 6.f, 0.f, 1.f, 0.f); |
81 | glRotatef(elapsedTime * 18.f, 0.f, 0.f, 1.f); |
82 | |
83 | // Define a 3D cube (6 faces made of 2 triangles composed by 3 vertices) |
84 | static const GLfloat cube[] = |
85 | { |
86 | // positions // colors |
87 | -50, -50, -50, 1, 1, 0, |
88 | -50, 50, -50, 1, 1, 0, |
89 | -50, -50, 50, 1, 1, 0, |
90 | -50, -50, 50, 1, 1, 0, |
91 | -50, 50, -50, 1, 1, 0, |
92 | -50, 50, 50, 1, 1, 0, |
93 | |
94 | 50, -50, -50, 1, 1, 0, |
95 | 50, 50, -50, 1, 1, 0, |
96 | 50, -50, 50, 1, 1, 0, |
97 | 50, -50, 50, 1, 1, 0, |
98 | 50, 50, -50, 1, 1, 0, |
99 | 50, 50, 50, 1, 1, 0, |
100 | |
101 | -50, -50, -50, 1, 0, 1, |
102 | 50, -50, -50, 1, 0, 1, |
103 | -50, -50, 50, 1, 0, 1, |
104 | -50, -50, 50, 1, 0, 1, |
105 | 50, -50, -50, 1, 0, 1, |
106 | 50, -50, 50, 1, 0, 1, |
107 | |
108 | -50, 50, -50, 1, 0, 1, |
109 | 50, 50, -50, 1, 0, 1, |
110 | -50, 50, 50, 1, 0, 1, |
111 | -50, 50, 50, 1, 0, 1, |
112 | 50, 50, -50, 1, 0, 1, |
113 | 50, 50, 50, 1, 0, 1, |
114 | |
115 | -50, -50, -50, 0, 1, 1, |
116 | 50, -50, -50, 0, 1, 1, |
117 | -50, 50, -50, 0, 1, 1, |
118 | -50, 50, -50, 0, 1, 1, |
119 | 50, -50, -50, 0, 1, 1, |
120 | 50, 50, -50, 0, 1, 1, |
121 | |
122 | -50, -50, 50, 0, 1, 1, |
123 | 50, -50, 50, 0, 1, 1, |
124 | -50, 50, 50, 0, 1, 1, |
125 | -50, 50, 50, 0, 1, 1, |
126 | 50, -50, 50, 0, 1, 1, |
127 | 50, 50, 50, 0, 1, 1 |
128 | }; |
129 | |
130 | // Draw the cube |
131 | glVertexPointer(3, GL_FLOAT, 6 * sizeof(GLfloat), cube); |
132 | glColorPointer(3, GL_FLOAT, 6 * sizeof(GLfloat), cube + 3); |
133 | glDrawArrays(GL_TRIANGLES, 0, 36); |
134 | } |
135 | |
136 | |
137 | //////////////////////////////////////////////////////////// |
138 | /// Entry point of application |
139 | /// |
140 | /// \return Error code |
141 | /// |
142 | //////////////////////////////////////////////////////////// |
143 | int main() |
144 | { |
145 | // Open a connection with the X server |
146 | Display* display = XOpenDisplay(NULL); |
147 | if (!display) |
148 | return EXIT_FAILURE; |
149 | |
150 | // Get the default screen |
151 | int screen = DefaultScreen(display); |
152 | |
153 | // Let's create the main window |
154 | XSetWindowAttributes attributes; |
155 | attributes.background_pixel = BlackPixel(display, screen); |
156 | attributes.event_mask = KeyPressMask; |
157 | Window window = XCreateWindow(display, RootWindow(display, screen), |
158 | 0, 0, 650, 330, 0, |
159 | DefaultDepth(display, screen), |
160 | InputOutput, |
161 | DefaultVisual(display, screen), |
162 | CWBackPixel | CWEventMask, &attributes); |
163 | if (!window) |
164 | return EXIT_FAILURE; |
165 | |
166 | // Set the window's name |
167 | XStoreName(display, window , "SFML Window" ); |
168 | |
169 | // Let's create the windows which will serve as containers for our SFML views |
170 | Window view1 = XCreateWindow(display, window, |
171 | 10, 10, 310, 310, 0, |
172 | DefaultDepth(display, screen), |
173 | InputOutput, |
174 | DefaultVisual(display, screen), |
175 | 0, NULL); |
176 | Window view2 = XCreateWindow(display, window, |
177 | 330, 10, 310, 310, 0, |
178 | DefaultDepth(display, screen), |
179 | InputOutput, |
180 | DefaultVisual(display, screen), |
181 | 0, NULL); |
182 | |
183 | // Show our windows |
184 | XMapWindow(display, window); |
185 | XFlush(display); |
186 | |
187 | // Create our SFML views |
188 | sf::Window sfmlView1(view1); |
189 | sf::Window sfmlView2(view2); |
190 | |
191 | // Create a clock for measuring elapsed time |
192 | sf::Clock clock; |
193 | |
194 | // Load OpenGL or OpenGL ES entry points using glad |
195 | sfmlView1.setActive(); |
196 | |
197 | #ifdef SFML_OPENGL_ES |
198 | gladLoadGLES1(reinterpret_cast<GLADloadfunc>(sf::Context::getFunction)); |
199 | #else |
200 | gladLoadGL(reinterpret_cast<GLADloadfunc>(sf::Context::getFunction)); |
201 | #endif |
202 | |
203 | // Initialize our views |
204 | initialize(sfmlView1); |
205 | initialize(sfmlView2); |
206 | |
207 | // Start the event loop |
208 | bool running = true; |
209 | while (running) |
210 | { |
211 | while (XPending(display)) |
212 | { |
213 | // Get the next pending event |
214 | XEvent event; |
215 | XNextEvent(display, &event); |
216 | |
217 | // Process it |
218 | switch (event.type) |
219 | { |
220 | // Any key is pressed: quit |
221 | case KeyPress: |
222 | running = false; |
223 | break; |
224 | } |
225 | } |
226 | |
227 | // Draw something into our views |
228 | draw(sfmlView1, clock.getElapsedTime().asSeconds()); |
229 | draw(sfmlView2, clock.getElapsedTime().asSeconds() * 0.3f); |
230 | |
231 | // Display the views on screen |
232 | sfmlView1.display(); |
233 | sfmlView2.display(); |
234 | } |
235 | |
236 | // Close our SFML views before destroying the underlying window |
237 | sfmlView1.close(); |
238 | sfmlView2.close(); |
239 | |
240 | // Destroy the window |
241 | XDestroyWindow(display, window); |
242 | |
243 | // Close the display |
244 | XCloseDisplay(display); |
245 | |
246 | return EXIT_SUCCESS; |
247 | } |
248 | |