fractorb

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