erebus

annotate 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
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 }