rev |
line source |
nuclear@2
|
1 #include <stdio.h>
|
nuclear@2
|
2 #include <stdlib.h>
|
nuclear@2
|
3 #include <assert.h>
|
nuclear@29
|
4 #include <signal.h>
|
nuclear@19
|
5 #include <vector>
|
nuclear@26
|
6 #include <chrono>
|
nuclear@29
|
7 #include <imago2.h>
|
nuclear@2
|
8 #include "opengl.h"
|
nuclear@4
|
9 #include "erebus.h"
|
nuclear@2
|
10
|
nuclear@26
|
11 using namespace std::chrono;
|
nuclear@26
|
12
|
nuclear@23
|
13 #define SCALE 2
|
nuclear@23
|
14
|
nuclear@2
|
15 static bool init();
|
nuclear@2
|
16 static void cleanup();
|
nuclear@2
|
17 static void resize_rtarget(int xsz, int ysz);
|
nuclear@2
|
18 static void update_rect(int x, int y, int xsz, int ysz, float *pixels);
|
nuclear@4
|
19 static void idle();
|
nuclear@2
|
20 static void display();
|
nuclear@29
|
21 static void save_image(const char *fname = 0);
|
nuclear@2
|
22 static void reshape(int x, int y);
|
nuclear@2
|
23 static void keyb(unsigned char key, int x, int y);
|
nuclear@9
|
24 static void keyb_up(unsigned char key, int x, int y);
|
nuclear@2
|
25 static void mouse(int bn, int st, int x, int y);
|
nuclear@9
|
26 static void motion(int x, int y);
|
nuclear@9
|
27 static void sball_button(int bn, int st);
|
nuclear@9
|
28 static void sball_motion(int x, int y, int z);
|
nuclear@2
|
29 static int next_pow2(int x);
|
nuclear@29
|
30 static void sighandler(int s);
|
nuclear@2
|
31
|
nuclear@2
|
32 static int width, height, rtex_width, rtex_height;
|
nuclear@2
|
33 static unsigned int rtex;
|
nuclear@2
|
34
|
nuclear@4
|
35 static erebus *erb;
|
nuclear@4
|
36 static bool render_pending;
|
nuclear@4
|
37
|
nuclear@19
|
38 static std::vector<char*> sfiles;
|
nuclear@4
|
39
|
nuclear@2
|
40 int main(int argc, char **argv)
|
nuclear@2
|
41 {
|
nuclear@2
|
42 glutInitWindowSize(1024, 600);
|
nuclear@2
|
43 glutInit(&argc, argv);
|
nuclear@19
|
44
|
nuclear@19
|
45 for(int i=1; i<argc; i++) {
|
nuclear@19
|
46 sfiles.push_back(argv[i]);
|
nuclear@19
|
47 }
|
nuclear@19
|
48
|
nuclear@2
|
49 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
|
nuclear@2
|
50 glutCreateWindow("erebus OpenGL frontend");
|
nuclear@2
|
51
|
nuclear@2
|
52 glutDisplayFunc(display);
|
nuclear@2
|
53 glutReshapeFunc(reshape);
|
nuclear@2
|
54 glutKeyboardFunc(keyb);
|
nuclear@9
|
55 glutKeyboardUpFunc(keyb_up);
|
nuclear@2
|
56 glutMouseFunc(mouse);
|
nuclear@9
|
57 glutMotionFunc(motion);
|
nuclear@9
|
58 glutSpaceballButtonFunc(sball_button);
|
nuclear@9
|
59 glutSpaceballMotionFunc(sball_motion);
|
nuclear@2
|
60
|
nuclear@2
|
61 if(!init()) {
|
nuclear@2
|
62 return 1;
|
nuclear@2
|
63 }
|
nuclear@2
|
64 atexit(cleanup);
|
nuclear@29
|
65 signal(SIGINT, sighandler);
|
nuclear@29
|
66 signal(SIGSEGV, sighandler);
|
nuclear@29
|
67 signal(SIGILL, sighandler);
|
nuclear@29
|
68 signal(SIGTERM, sighandler);
|
nuclear@29
|
69 signal(SIGFPE, sighandler);
|
nuclear@2
|
70
|
nuclear@2
|
71 glutMainLoop();
|
nuclear@2
|
72 }
|
nuclear@2
|
73
|
nuclear@2
|
74 static bool init()
|
nuclear@2
|
75 {
|
nuclear@23
|
76 width = glutGet(GLUT_WINDOW_WIDTH) / SCALE;
|
nuclear@23
|
77 height = glutGet(GLUT_WINDOW_HEIGHT) / SCALE;
|
nuclear@5
|
78
|
nuclear@4
|
79 if(!(erb = erb_init())) {
|
nuclear@4
|
80 return false;
|
nuclear@4
|
81 }
|
nuclear@4
|
82 erb_setopti(erb, ERB_OPT_WIDTH, width);
|
nuclear@4
|
83 erb_setopti(erb, ERB_OPT_HEIGHT, height);
|
nuclear@4
|
84
|
nuclear@19
|
85 for(size_t i=0; i<sfiles.size(); i++) {
|
nuclear@19
|
86 printf("loading scene file: %s\n", sfiles[i]);
|
nuclear@19
|
87 if(erb_load_scene(erb, sfiles[i]) == -1) {
|
nuclear@19
|
88 return false;
|
nuclear@19
|
89 }
|
nuclear@4
|
90 }
|
nuclear@4
|
91
|
nuclear@21
|
92 if(!sfiles.empty()) {
|
nuclear@21
|
93 printf("begin rendering\n");
|
nuclear@21
|
94 render_pending = true;
|
nuclear@21
|
95 glutIdleFunc(idle);
|
nuclear@21
|
96 erb_begin_frame(erb, 0);
|
nuclear@21
|
97 }
|
nuclear@4
|
98
|
nuclear@8
|
99 glEnable(GL_TEXTURE_2D);
|
nuclear@2
|
100 return true;
|
nuclear@2
|
101 }
|
nuclear@2
|
102
|
nuclear@2
|
103 static void cleanup()
|
nuclear@2
|
104 {
|
nuclear@29
|
105 save_image("final.png");
|
nuclear@4
|
106 erb_destroy(erb);
|
nuclear@2
|
107 }
|
nuclear@2
|
108
|
nuclear@2
|
109 static void resize_rtarget(int xsz, int ysz)
|
nuclear@2
|
110 {
|
nuclear@2
|
111 static unsigned char *defpix;
|
nuclear@2
|
112
|
nuclear@23
|
113 width = xsz / SCALE;
|
nuclear@23
|
114 height = ysz / SCALE;
|
nuclear@2
|
115
|
nuclear@8
|
116 if(width <= rtex_width && height <= rtex_height) {
|
nuclear@2
|
117 return;
|
nuclear@2
|
118 }
|
nuclear@8
|
119 rtex_width = next_pow2(width);
|
nuclear@8
|
120 rtex_height = next_pow2(height);
|
nuclear@2
|
121
|
nuclear@2
|
122 printf("resizing framebuffer texture: %dx%d\n", rtex_width, rtex_height);
|
nuclear@2
|
123
|
nuclear@2
|
124 if(!rtex) {
|
nuclear@2
|
125 glGenTextures(1, &rtex);
|
nuclear@2
|
126 }
|
nuclear@2
|
127
|
nuclear@2
|
128 delete [] defpix;
|
nuclear@2
|
129 defpix = new unsigned char[rtex_width * rtex_height * 4];
|
nuclear@2
|
130 unsigned char *ptr = defpix;
|
nuclear@2
|
131 for(int i=0; i<rtex_height; i++) {
|
nuclear@2
|
132 for(int j=0; j<rtex_width; j++) {
|
nuclear@2
|
133 bool chess = ((i >> 4) & 1) == ((j >> 4) & 1);
|
nuclear@2
|
134
|
nuclear@2
|
135 int val = chess ? 64 : 48;
|
nuclear@2
|
136
|
nuclear@2
|
137 *ptr++ = val;
|
nuclear@2
|
138 *ptr++ = val;
|
nuclear@2
|
139 *ptr++ = val;
|
nuclear@2
|
140 *ptr++ = 255;
|
nuclear@2
|
141 }
|
nuclear@2
|
142 }
|
nuclear@2
|
143
|
nuclear@2
|
144 glBindTexture(GL_TEXTURE_2D, rtex);
|
nuclear@2
|
145 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
nuclear@2
|
146 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
nuclear@2
|
147 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, rtex_width, rtex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, defpix);
|
nuclear@2
|
148 }
|
nuclear@2
|
149
|
nuclear@2
|
150 static void update_rect(int x, int y, int xsz, int ysz, float *pixels)
|
nuclear@2
|
151 {
|
nuclear@2
|
152 glBindTexture(GL_TEXTURE_2D, rtex);
|
nuclear@2
|
153 glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, xsz, ysz, GL_RGBA, GL_FLOAT, pixels);
|
nuclear@2
|
154 }
|
nuclear@2
|
155
|
nuclear@4
|
156 static void idle()
|
nuclear@4
|
157 {
|
nuclear@4
|
158 glutPostRedisplay();
|
nuclear@4
|
159 }
|
nuclear@4
|
160
|
nuclear@2
|
161 static void display()
|
nuclear@2
|
162 {
|
nuclear@4
|
163 if(render_pending) {
|
nuclear@8
|
164 if(erb_render(erb, 64) == 0) {
|
nuclear@4
|
165 render_pending = false;
|
nuclear@4
|
166 glutIdleFunc(0);
|
nuclear@4
|
167 }
|
nuclear@4
|
168 update_rect(0, 0, width, height, erb_get_framebuffer(erb));
|
nuclear@4
|
169 }
|
nuclear@4
|
170
|
nuclear@2
|
171 float maxu = (float)width / (float)rtex_width;
|
nuclear@2
|
172 float maxv = (float)height / (float)rtex_height;
|
nuclear@2
|
173
|
nuclear@2
|
174 glBegin(GL_QUADS);
|
nuclear@2
|
175 glTexCoord2f(0, maxv); glVertex2f(-1, -1);
|
nuclear@2
|
176 glTexCoord2f(maxu, maxv); glVertex2f(1, -1);
|
nuclear@2
|
177 glTexCoord2f(maxu, 0); glVertex2f(1, 1);
|
nuclear@2
|
178 glTexCoord2f(0, 0); glVertex2f(-1, 1);
|
nuclear@2
|
179 glEnd();
|
nuclear@2
|
180
|
nuclear@2
|
181 glutSwapBuffers();
|
nuclear@2
|
182 assert(glGetError() == GL_NO_ERROR);
|
nuclear@2
|
183 }
|
nuclear@2
|
184
|
nuclear@29
|
185 static void save_image(const char *fname)
|
nuclear@29
|
186 {
|
nuclear@29
|
187 float *fb = erb_get_framebuffer(erb);
|
nuclear@29
|
188
|
nuclear@29
|
189 if(img_save_pixels(fname ? fname : "output.png", fb, width, height, IMG_FMT_RGBAF) == -1) {
|
nuclear@29
|
190 fprintf(stderr, "failed to save image\n");
|
nuclear@29
|
191 }
|
nuclear@29
|
192 }
|
nuclear@29
|
193
|
nuclear@2
|
194 static void reshape(int x, int y)
|
nuclear@2
|
195 {
|
nuclear@2
|
196 glViewport(0, 0, x, y);
|
nuclear@2
|
197 resize_rtarget(x, y);
|
nuclear@4
|
198
|
nuclear@4
|
199 erb_setopti(erb, ERB_OPT_WIDTH, width);
|
nuclear@4
|
200 erb_setopti(erb, ERB_OPT_HEIGHT, height);
|
nuclear@2
|
201 }
|
nuclear@2
|
202
|
nuclear@2
|
203 static void keyb(unsigned char key, int x, int y)
|
nuclear@2
|
204 {
|
nuclear@2
|
205 switch(key) {
|
nuclear@2
|
206 case 27:
|
nuclear@2
|
207 exit(0);
|
nuclear@4
|
208
|
nuclear@4
|
209 case ' ':
|
nuclear@4
|
210 printf("begin rendering\n");
|
nuclear@4
|
211 render_pending = true;
|
nuclear@4
|
212 glutIdleFunc(idle);
|
nuclear@4
|
213 erb_begin_frame(erb, 0);
|
nuclear@4
|
214 break;
|
nuclear@29
|
215
|
nuclear@29
|
216 case '`':
|
nuclear@29
|
217 printf("saving image.\n");
|
nuclear@29
|
218 save_image();
|
nuclear@29
|
219 break;
|
nuclear@2
|
220 }
|
nuclear@9
|
221
|
nuclear@10
|
222 if(erb_input_keyboard(erb, key, true)) {
|
nuclear@9
|
223 glutPostRedisplay();
|
nuclear@9
|
224 }
|
nuclear@9
|
225 }
|
nuclear@9
|
226
|
nuclear@9
|
227 static void keyb_up(unsigned char key, int x, int y)
|
nuclear@9
|
228 {
|
nuclear@10
|
229 if(erb_input_keyboard(erb, key, false)) {
|
nuclear@9
|
230 glutPostRedisplay();
|
nuclear@9
|
231 }
|
nuclear@2
|
232 }
|
nuclear@2
|
233
|
nuclear@2
|
234 static void mouse(int bn, int st, int x, int y)
|
nuclear@2
|
235 {
|
nuclear@10
|
236 if(erb_input_mouse_button(erb, bn - GLUT_LEFT_BUTTON, st == GLUT_DOWN, x, y)) {
|
nuclear@9
|
237 glutPostRedisplay();
|
nuclear@9
|
238 }
|
nuclear@9
|
239 }
|
nuclear@9
|
240
|
nuclear@9
|
241 static void motion(int x, int y)
|
nuclear@9
|
242 {
|
nuclear@15
|
243 if(erb_input_mouse_motion(erb, x, y)) {
|
nuclear@9
|
244 glutPostRedisplay();
|
nuclear@9
|
245 }
|
nuclear@9
|
246 }
|
nuclear@9
|
247
|
nuclear@9
|
248 static void sball_button(int bn, int state)
|
nuclear@9
|
249 {
|
nuclear@10
|
250 if(erb_input_6dof_button(erb, bn, state == GLUT_DOWN)) {
|
nuclear@9
|
251 glutPostRedisplay();
|
nuclear@9
|
252 }
|
nuclear@9
|
253 }
|
nuclear@9
|
254
|
nuclear@9
|
255 static void sball_motion(int x, int y, int z)
|
nuclear@9
|
256 {
|
nuclear@10
|
257 if(erb_input_6dof_motion(erb, x / 65536.0, y / 65536.0, z / 65536.0)) {
|
nuclear@9
|
258 glutPostRedisplay();
|
nuclear@9
|
259 }
|
nuclear@2
|
260 }
|
nuclear@2
|
261
|
nuclear@2
|
262 static int next_pow2(int x)
|
nuclear@2
|
263 {
|
nuclear@2
|
264 int res = 2;
|
nuclear@2
|
265 while(res < x) {
|
nuclear@2
|
266 res <<= 1;
|
nuclear@2
|
267 }
|
nuclear@2
|
268 return res;
|
nuclear@2
|
269 }
|
nuclear@29
|
270
|
nuclear@29
|
271 static void sighandler(int s)
|
nuclear@29
|
272 {
|
nuclear@29
|
273 exit(0);
|
nuclear@29
|
274 }
|