erebus

view src/main.cc @ 29:fb20e3855740

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