fractorb

annotate src/main.c @ 2:03e8b9a5031d

screenshot function
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 20 Nov 2017 03:53:02 +0200
parents 436f82447c44
children f440ecffc45a
rev   line source
nuclear@0 1 #include <stdio.h>
nuclear@0 2 #include <stdlib.h>
nuclear@2 3 #include <string.h>
nuclear@1 4 #include <math.h>
nuclear@2 5 #include <errno.h>
nuclear@2 6 #include <dirent.h>
nuclear@0 7 #include <GL/glew.h>
nuclear@0 8 #include <GL/glut.h>
nuclear@0 9 #include "sdr.h"
nuclear@0 10
nuclear@0 11 int init(void);
nuclear@0 12 void cleanup(void);
nuclear@0 13 void disp(void);
nuclear@0 14 void reshape(int x, int y);
nuclear@1 15 void keydown(unsigned char key, int x, int y);
nuclear@1 16 void keyup(unsigned char key, int x, int y);
nuclear@0 17 void mouse(int bn, int st, int x, int y);
nuclear@0 18 void motion(int x, int y);
nuclear@2 19 void screenshot(void);
nuclear@0 20
nuclear@1 21 static int win_width = 1280, win_height = 800;
nuclear@1 22 static float win_aspect;
nuclear@1 23 static int mouse_x = 640, mouse_y = 400;
nuclear@0 24 static unsigned int prog_mbrot;
nuclear@0 25
nuclear@1 26 static float view_center[2] = {0.7, 0.0};
nuclear@1 27 static float view_scale = 1.2;
nuclear@1 28
nuclear@1 29
nuclear@0 30 int main(int argc, char **argv)
nuclear@0 31 {
nuclear@0 32 glutInit(&argc, argv);
nuclear@0 33 glutInitWindowSize(1280, 800);
nuclear@0 34 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
nuclear@0 35 glutCreateWindow("fractorb");
nuclear@0 36
nuclear@0 37 glutDisplayFunc(disp);
nuclear@0 38 glutReshapeFunc(reshape);
nuclear@1 39 glutKeyboardFunc(keydown);
nuclear@1 40 glutKeyboardUpFunc(keyup);
nuclear@0 41 glutMouseFunc(mouse);
nuclear@0 42 glutMotionFunc(motion);
nuclear@0 43
nuclear@0 44 if(init() == -1) {
nuclear@0 45 return 1;
nuclear@0 46 }
nuclear@0 47 atexit(cleanup);
nuclear@0 48
nuclear@0 49 glutMainLoop();
nuclear@0 50 return 0;
nuclear@0 51 }
nuclear@0 52
nuclear@0 53
nuclear@0 54 int init(void)
nuclear@0 55 {
nuclear@0 56 glewInit();
nuclear@0 57
nuclear@0 58 if(!(prog_mbrot = create_program_load("vertex.glsl", "mbrot.glsl"))) {
nuclear@0 59 return -1;
nuclear@0 60 }
nuclear@0 61 return 0;
nuclear@0 62 }
nuclear@0 63
nuclear@0 64 void cleanup(void)
nuclear@0 65 {
nuclear@0 66 free_program(prog_mbrot);
nuclear@0 67 }
nuclear@0 68
nuclear@1 69 void pixel_to_complex(float *res, float px, float py)
nuclear@1 70 {
nuclear@1 71 float u = (2.0 * px / win_width - 1.0) * win_aspect;
nuclear@1 72 float v = 2.0 * py / win_height - 1.0;
nuclear@1 73 res[0] = u * view_scale - view_center[0];
nuclear@1 74 res[1] = v * view_scale - view_center[1];
nuclear@1 75 }
nuclear@1 76
nuclear@0 77 void disp(void)
nuclear@0 78 {
nuclear@1 79 int i;
nuclear@1 80 float seed[2];
nuclear@1 81 static const float verts[][2] = {{-1, -1}, {1, -1}, {1, 1}, {-1, 1}};
nuclear@1 82 static const float corners[][2] = {{0, 1}, {1, 1}, {1, 0}, {0, 0}};
nuclear@1 83
nuclear@1 84 pixel_to_complex(seed, mouse_x, mouse_y);
nuclear@1 85
nuclear@1 86 set_uniform_float2(prog_mbrot, "seed", seed[0], seed[1]);
nuclear@1 87 set_uniform_float(prog_mbrot, "view_scale", view_scale);
nuclear@1 88 set_uniform_float2(prog_mbrot, "view_center", view_center[0], view_center[1]);
nuclear@0 89 glUseProgram(prog_mbrot);
nuclear@0 90
nuclear@0 91 glBegin(GL_QUADS);
nuclear@1 92 for(i=0; i<4; i++) {
nuclear@1 93 float bv[2];
nuclear@1 94 pixel_to_complex(bv, (win_width - 1) * corners[i][0], (win_height - 1) * corners[i][1]);
nuclear@1 95 glTexCoord2f(bv[0], bv[1]);
nuclear@1 96 glVertex2f(verts[i][0], verts[i][1]);
nuclear@1 97 }
nuclear@0 98 glEnd();
nuclear@0 99
nuclear@0 100 glutSwapBuffers();
nuclear@0 101 }
nuclear@0 102
nuclear@0 103 void reshape(int x, int y)
nuclear@0 104 {
nuclear@0 105 glViewport(0, 0, x, y);
nuclear@0 106
nuclear@1 107 win_aspect = (float)x / (float)y;
nuclear@1 108 win_width = x;
nuclear@1 109 win_height = y;
nuclear@0 110 }
nuclear@0 111
nuclear@1 112 static int keystate[256];
nuclear@1 113
nuclear@1 114 void keydown(unsigned char key, int x, int y)
nuclear@0 115 {
nuclear@1 116 static int fullscreen;
nuclear@1 117 static int prev_width, prev_height;
nuclear@1 118
nuclear@1 119 switch(key) {
nuclear@1 120 case 27:
nuclear@0 121 exit(0);
nuclear@1 122
nuclear@1 123 case 'f':
nuclear@1 124 fullscreen = !fullscreen;
nuclear@1 125 if(fullscreen) {
nuclear@1 126 prev_width = win_width;
nuclear@1 127 prev_height = win_height;
nuclear@1 128 glutFullScreen();
nuclear@1 129 } else {
nuclear@1 130 glutReshapeWindow(prev_width, prev_height);
nuclear@1 131 }
nuclear@1 132 break;
nuclear@1 133
nuclear@2 134 case '`':
nuclear@2 135 screenshot();
nuclear@2 136 break;
nuclear@2 137
nuclear@1 138 default:
nuclear@1 139 break;
nuclear@0 140 }
nuclear@1 141 keystate[key] = 1;
nuclear@0 142 }
nuclear@0 143
nuclear@1 144 void keyup(unsigned char key, int x, int y)
nuclear@1 145 {
nuclear@1 146 keystate[key] = 0;
nuclear@1 147 }
nuclear@1 148
nuclear@1 149 static int prev_x, prev_y;
nuclear@1 150 static int bnstate[8];
nuclear@1 151
nuclear@0 152 void mouse(int bn, int st, int x, int y)
nuclear@0 153 {
nuclear@1 154 prev_x = x;
nuclear@1 155 prev_y = y;
nuclear@1 156 bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN ? 1 : 0;
nuclear@0 157 }
nuclear@0 158
nuclear@0 159 void motion(int x, int y)
nuclear@0 160 {
nuclear@1 161 int dx = x - prev_x;
nuclear@1 162 int dy = y - prev_y;
nuclear@1 163 prev_x = x;
nuclear@1 164 prev_y = y;
nuclear@1 165
nuclear@1 166 if(!(dx | dy)) return;
nuclear@1 167
nuclear@1 168 if(bnstate[0]) {
nuclear@1 169 if(keystate['s']) {
nuclear@1 170 mouse_x = x;
nuclear@1 171 mouse_y = y;
nuclear@1 172 } else if(keystate['z']) {
nuclear@1 173 float s = sqrt(view_scale);
nuclear@1 174 view_scale += dy * 0.01 * s;
nuclear@1 175 if(view_scale < 1e-8) view_scale = 1e-8;
nuclear@1 176 } else {
nuclear@1 177 float s = sqrt(view_scale);
nuclear@1 178 view_center[0] += 0.01 * dx * s;
nuclear@1 179 view_center[1] += 0.01 * dy * s;
nuclear@1 180 }
nuclear@1 181 glutPostRedisplay();
nuclear@1 182 }
nuclear@0 183 }
nuclear@2 184
nuclear@2 185 void screenshot(void)
nuclear@2 186 {
nuclear@2 187 FILE *fp;
nuclear@2 188 DIR *dir;
nuclear@2 189 struct dirent *dent;
nuclear@2 190 unsigned char *img;
nuclear@2 191 static int shotnum = -1;
nuclear@2 192 char fname[128];
nuclear@2 193
nuclear@2 194 if(shotnum == -1) {
nuclear@2 195 shotnum = 1;
nuclear@2 196 if((dir = opendir("."))) {
nuclear@2 197 while((dent = readdir(dir))) {
nuclear@2 198 int num;
nuclear@2 199 if(sscanf(dent->d_name, "img%d.ppm", &num) == 1) {
nuclear@2 200 if(num >= shotnum) shotnum = num + 1;
nuclear@2 201 }
nuclear@2 202 }
nuclear@2 203 closedir(dir);
nuclear@2 204 }
nuclear@2 205 } else {
nuclear@2 206 ++shotnum;
nuclear@2 207 }
nuclear@2 208
nuclear@2 209 sprintf(fname, "img%04d.ppm", shotnum > 0 ? shotnum : 0);
nuclear@2 210 if(!(fp = fopen(fname, "wb"))) {
nuclear@2 211 fprintf(stderr, "failed to open %s for writing: %s\n", fname, strerror(errno));
nuclear@2 212 return;
nuclear@2 213 }
nuclear@2 214
nuclear@2 215 if(!(img = malloc(win_width * win_height * 3))) {
nuclear@2 216 fprintf(stderr, "failed to allocate screenshot buffer\n");
nuclear@2 217 fclose(fp);
nuclear@2 218 return;
nuclear@2 219 }
nuclear@2 220
nuclear@2 221 glReadPixels(0, 0, win_width, win_height, GL_RGB, GL_UNSIGNED_BYTE, img);
nuclear@2 222
nuclear@2 223 fprintf(fp, "P6\n%d %d\n255\n", win_width, win_height);
nuclear@2 224 fwrite(img, 1, win_width * win_height * 3, fp);
nuclear@2 225 fclose(fp);
nuclear@2 226 free(img);
nuclear@2 227 return;
nuclear@2 228 }