fractorb

view src/main.c @ 1:436f82447c44

pan/scale and min orbit distance from point drawing
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 19 Nov 2017 00:57:39 +0200
parents 6e849d7377ff
children 03e8b9a5031d
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <math.h>
4 #include <GL/glew.h>
5 #include <GL/glut.h>
6 #include "sdr.h"
8 int init(void);
9 void cleanup(void);
10 void disp(void);
11 void reshape(int x, int y);
12 void keydown(unsigned char key, int x, int y);
13 void keyup(unsigned char key, int x, int y);
14 void mouse(int bn, int st, int x, int y);
15 void motion(int x, int y);
17 static int win_width = 1280, win_height = 800;
18 static float win_aspect;
19 static int mouse_x = 640, mouse_y = 400;
20 static unsigned int prog_mbrot;
22 static float view_center[2] = {0.7, 0.0};
23 static float view_scale = 1.2;
26 int main(int argc, char **argv)
27 {
28 glutInit(&argc, argv);
29 glutInitWindowSize(1280, 800);
30 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
31 glutCreateWindow("fractorb");
33 glutDisplayFunc(disp);
34 glutReshapeFunc(reshape);
35 glutKeyboardFunc(keydown);
36 glutKeyboardUpFunc(keyup);
37 glutMouseFunc(mouse);
38 glutMotionFunc(motion);
40 if(init() == -1) {
41 return 1;
42 }
43 atexit(cleanup);
45 glutMainLoop();
46 return 0;
47 }
50 int init(void)
51 {
52 glewInit();
54 if(!(prog_mbrot = create_program_load("vertex.glsl", "mbrot.glsl"))) {
55 return -1;
56 }
57 return 0;
58 }
60 void cleanup(void)
61 {
62 free_program(prog_mbrot);
63 }
65 void pixel_to_complex(float *res, float px, float py)
66 {
67 float u = (2.0 * px / win_width - 1.0) * win_aspect;
68 float v = 2.0 * py / win_height - 1.0;
69 res[0] = u * view_scale - view_center[0];
70 res[1] = v * view_scale - view_center[1];
71 }
73 void disp(void)
74 {
75 int i;
76 float seed[2];
77 static const float verts[][2] = {{-1, -1}, {1, -1}, {1, 1}, {-1, 1}};
78 static const float corners[][2] = {{0, 1}, {1, 1}, {1, 0}, {0, 0}};
80 pixel_to_complex(seed, mouse_x, mouse_y);
82 set_uniform_float2(prog_mbrot, "seed", seed[0], seed[1]);
83 set_uniform_float(prog_mbrot, "view_scale", view_scale);
84 set_uniform_float2(prog_mbrot, "view_center", view_center[0], view_center[1]);
85 glUseProgram(prog_mbrot);
87 glBegin(GL_QUADS);
88 for(i=0; i<4; i++) {
89 float bv[2];
90 pixel_to_complex(bv, (win_width - 1) * corners[i][0], (win_height - 1) * corners[i][1]);
91 glTexCoord2f(bv[0], bv[1]);
92 glVertex2f(verts[i][0], verts[i][1]);
93 }
94 glEnd();
96 glutSwapBuffers();
97 }
99 void reshape(int x, int y)
100 {
101 glViewport(0, 0, x, y);
103 win_aspect = (float)x / (float)y;
104 win_width = x;
105 win_height = y;
106 }
108 static int keystate[256];
110 void keydown(unsigned char key, int x, int y)
111 {
112 static int fullscreen;
113 static int prev_width, prev_height;
115 switch(key) {
116 case 27:
117 exit(0);
119 case 'f':
120 fullscreen = !fullscreen;
121 if(fullscreen) {
122 prev_width = win_width;
123 prev_height = win_height;
124 glutFullScreen();
125 } else {
126 glutReshapeWindow(prev_width, prev_height);
127 }
128 break;
130 default:
131 break;
132 }
133 keystate[key] = 1;
134 }
136 void keyup(unsigned char key, int x, int y)
137 {
138 keystate[key] = 0;
139 }
141 static int prev_x, prev_y;
142 static int bnstate[8];
144 void mouse(int bn, int st, int x, int y)
145 {
146 prev_x = x;
147 prev_y = y;
148 bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN ? 1 : 0;
149 }
151 void motion(int x, int y)
152 {
153 int dx = x - prev_x;
154 int dy = y - prev_y;
155 prev_x = x;
156 prev_y = y;
158 if(!(dx | dy)) return;
160 if(bnstate[0]) {
161 if(keystate['s']) {
162 mouse_x = x;
163 mouse_y = y;
164 } else if(keystate['z']) {
165 float s = sqrt(view_scale);
166 view_scale += dy * 0.01 * s;
167 if(view_scale < 1e-8) view_scale = 1e-8;
168 } else {
169 float s = sqrt(view_scale);
170 view_center[0] += 0.01 * dx * s;
171 view_center[1] += 0.01 * dy * s;
172 }
173 glutPostRedisplay();
174 }
175 }