gradtool

annotate gradtool.c @ 0:960cea2731c4

gradtool hg import (used to be in subversion, fuck subversion)
author John Tsiombikas <nuclear@mutantstargoat.com>
date Tue, 19 Jun 2012 05:30:45 +0300
parents
children c438411b801b
rev   line source
nuclear@0 1 #include <stdio.h>
nuclear@0 2 #include <stdlib.h>
nuclear@0 3 #include <GL/glut.h>
nuclear@0 4
nuclear@0 5 #define MAX_POS 512
nuclear@0 6
nuclear@0 7 typedef struct key {
nuclear@0 8 int pos;
nuclear@0 9 float val;
nuclear@0 10 struct key *next;
nuclear@0 11 } key_t;
nuclear@0 12
nuclear@0 13 struct track {
nuclear@0 14 key_t *keys;
nuclear@0 15 int count;
nuclear@0 16 };
nuclear@0 17
nuclear@0 18 void redraw(void);
nuclear@0 19 void draw_curves(void);
nuclear@0 20 void draw_grad(void);
nuclear@0 21
nuclear@0 22 void set_val(struct track *track, float pos, float val);
nuclear@0 23 void rm_val(struct track *track, float pos);
nuclear@0 24 float get_val(struct track *track, float pos);
nuclear@0 25
nuclear@0 26 void save(void);
nuclear@0 27
nuclear@0 28 void key_handler(unsigned char key, int x, int y);
nuclear@0 29 void skey_handler(int key, int x, int y);
nuclear@0 30 void mbutton_handler(int bn, int state, int x, int y);
nuclear@0 31 void drag_handler(int x, int y);
nuclear@0 32 void reshape_handler(int x, int y);
nuclear@0 33
nuclear@0 34 int view_xsz = 640;
nuclear@0 35 int view_ysz = 480;
nuclear@0 36
nuclear@0 37 struct track tred, tgreen, tblue;
nuclear@0 38
nuclear@0 39 int main(int argc, char **argv)
nuclear@0 40 {
nuclear@0 41 glutInit(&argc, argv);
nuclear@0 42 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
nuclear@0 43 glutInitWindowSize(view_xsz, view_ysz);
nuclear@0 44 glutCreateWindow("Mindlapse gradiant editor");
nuclear@0 45
nuclear@0 46 glutDisplayFunc(redraw);
nuclear@0 47 glutKeyboardFunc(key_handler);
nuclear@0 48 glutSpecialFunc(skey_handler);
nuclear@0 49 glutMouseFunc(mbutton_handler);
nuclear@0 50 glutMotionFunc(drag_handler);
nuclear@0 51 glutReshapeFunc(reshape_handler);
nuclear@0 52
nuclear@0 53 glClearColor(0, 0, 0, 0);
nuclear@0 54 glEnable(GL_POINT_SMOOTH);
nuclear@0 55
nuclear@0 56 glMatrixMode(GL_PROJECTION);
nuclear@0 57 glOrtho(0, 1, 0, 1, -1, 1);
nuclear@0 58 glMatrixMode(GL_MODELVIEW);
nuclear@0 59
nuclear@0 60 tred.keys = malloc(sizeof *tred.keys);
nuclear@0 61 tred.keys->next = 0;
nuclear@0 62
nuclear@0 63 tgreen.keys = malloc(sizeof *tgreen.keys);
nuclear@0 64 tgreen.keys->next = 0;
nuclear@0 65
nuclear@0 66 tblue.keys = malloc(sizeof *tblue.keys);
nuclear@0 67 tblue.keys->next = 0;
nuclear@0 68
nuclear@0 69 glutMainLoop();
nuclear@0 70 return 0;
nuclear@0 71 }
nuclear@0 72
nuclear@0 73 void redraw(void)
nuclear@0 74 {
nuclear@0 75 glClear(GL_COLOR_BUFFER_BIT);
nuclear@0 76
nuclear@0 77 draw_curves();
nuclear@0 78
nuclear@0 79 draw_grad();
nuclear@0 80
nuclear@0 81 glutSwapBuffers();
nuclear@0 82 }
nuclear@0 83
nuclear@0 84 void draw_curves(void)
nuclear@0 85 {
nuclear@0 86 int i;
nuclear@0 87 key_t *ptr;
nuclear@0 88
nuclear@0 89 glLoadIdentity();
nuclear@0 90 glTranslatef(0, 0.25, 0);
nuclear@0 91 glScalef(1, 0.75, 1);
nuclear@0 92
nuclear@0 93 glBegin(GL_LINES);
nuclear@0 94 /* draw grid */
nuclear@0 95 glColor3f(0.5, 0.5, 0.5);
nuclear@0 96 glVertex2f(0, 0); glVertex2f(0, 1);
nuclear@0 97 glVertex2f(1, 0); glVertex2f(1, 1);
nuclear@0 98 glVertex2f(0, 0); glVertex2f(1, 0);
nuclear@0 99 glVertex2f(0, 1); glVertex2f(1, 1);
nuclear@0 100
nuclear@0 101 glVertex2f(0, 0.25); glVertex2f(1, 0.25);
nuclear@0 102 glVertex2f(0, 0.5); glVertex2f(1, 0.5);
nuclear@0 103 glVertex2f(0, 0.75); glVertex2f(1, 0.75);
nuclear@0 104
nuclear@0 105 glVertex2f(0.25, 0); glVertex2f(0.25, 1);
nuclear@0 106 glVertex2f(0.5, 0); glVertex2f(0.5, 1);
nuclear@0 107 glVertex2f(0.75, 0); glVertex2f(0.75, 1);
nuclear@0 108 glEnd();
nuclear@0 109
nuclear@0 110 glEnable(GL_BLEND);
nuclear@0 111 glBlendFunc(GL_ONE, GL_ONE);
nuclear@0 112
nuclear@0 113 glBegin(GL_LINES);
nuclear@0 114 for(i=0; i<3; i++) {
nuclear@0 115 glColor3f(i == 0, i == 1, i == 2);
nuclear@0 116 ptr = (i == 0 ? tred.keys->next : (i == 1 ? tgreen.keys->next : tblue.keys->next));
nuclear@0 117
nuclear@0 118 if(ptr && ptr->pos > 0) {
nuclear@0 119 glVertex2f(0, ptr->val);
nuclear@0 120 glVertex2f(ptr->pos / (float)MAX_POS, ptr->val);
nuclear@0 121 }
nuclear@0 122
nuclear@0 123 while(ptr && ptr->next) {
nuclear@0 124 glVertex2f(ptr->pos / (float)MAX_POS, ptr->val);
nuclear@0 125 glVertex2f(ptr->next->pos / (float)MAX_POS, ptr->next->val);
nuclear@0 126 ptr = ptr->next;
nuclear@0 127 }
nuclear@0 128
nuclear@0 129 if(ptr && ptr->pos != MAX_POS) {
nuclear@0 130 glVertex2f(ptr->pos / (float)MAX_POS, ptr->val);
nuclear@0 131 glVertex2f(1, ptr->val);
nuclear@0 132 }
nuclear@0 133 }
nuclear@0 134 glEnd();
nuclear@0 135
nuclear@0 136 glPointSize(5);
nuclear@0 137 glBegin(GL_POINTS);
nuclear@0 138 for(i=0; i<3; i++) {
nuclear@0 139 glColor3f(i == 0, i == 1, i == 2);
nuclear@0 140 ptr = (i == 0 ? tred.keys->next : (i == 1 ? tgreen.keys->next : tblue.keys->next));
nuclear@0 141
nuclear@0 142 while(ptr) {
nuclear@0 143 glVertex2f(ptr->pos / (float)MAX_POS, ptr->val);
nuclear@0 144 ptr = ptr->next;
nuclear@0 145 }
nuclear@0 146 }
nuclear@0 147 glEnd();
nuclear@0 148
nuclear@0 149 glDisable(GL_BLEND);
nuclear@0 150 }
nuclear@0 151
nuclear@0 152 #define GRAD_SAMPLES MAX_POS
nuclear@0 153 void draw_grad(void)
nuclear@0 154 {
nuclear@0 155 int i;
nuclear@0 156
nuclear@0 157 glLoadIdentity();
nuclear@0 158 glScalef(1, 0.25, 1);
nuclear@0 159
nuclear@0 160 glBegin(GL_QUADS);
nuclear@0 161 for(i=0; i<GRAD_SAMPLES-1; i++) {
nuclear@0 162 float t = (float)i / (float)GRAD_SAMPLES;
nuclear@0 163 glColor3f(get_val(&tred, t), get_val(&tgreen, t), get_val(&tblue, t));
nuclear@0 164 glVertex2f(t, 0);
nuclear@0 165 glVertex2f(t, 1);
nuclear@0 166
nuclear@0 167 t = (float)(i + 1) / (float)GRAD_SAMPLES;
nuclear@0 168 glColor3f(get_val(&tred, t), get_val(&tgreen, t), get_val(&tblue, t));
nuclear@0 169 glVertex2f(t, 1);
nuclear@0 170 glVertex2f(t, 0);
nuclear@0 171 }
nuclear@0 172 glEnd();
nuclear@0 173 }
nuclear@0 174
nuclear@0 175 void set_val(struct track *tr, float pos, float val)
nuclear@0 176 {
nuclear@0 177 key_t *nkey;
nuclear@0 178 key_t *ptr = tr->keys;
nuclear@0 179 int ipos = (int)(pos * MAX_POS);
nuclear@0 180
nuclear@0 181 if(!ptr->next || ptr->next->pos > ipos) {
nuclear@0 182 nkey = malloc(sizeof *nkey);
nuclear@0 183 nkey->pos = ipos;
nuclear@0 184 nkey->val = val;
nuclear@0 185 nkey->next = ptr->next;
nuclear@0 186 ptr->next = nkey;
nuclear@0 187 return;
nuclear@0 188 }
nuclear@0 189
nuclear@0 190 while(ptr->next && ptr->next->pos < ipos) {
nuclear@0 191 ptr = ptr->next;
nuclear@0 192 }
nuclear@0 193
nuclear@0 194 if(ptr->pos == ipos) {
nuclear@0 195 ptr->val = val;
nuclear@0 196 } else {
nuclear@0 197 nkey = malloc(sizeof *nkey);
nuclear@0 198 nkey->pos = ipos;
nuclear@0 199 nkey->val = val;
nuclear@0 200 nkey->next = ptr->next;
nuclear@0 201 ptr->next = nkey;
nuclear@0 202 }
nuclear@0 203 }
nuclear@0 204
nuclear@0 205 void rm_val(struct track *tr, float pos)
nuclear@0 206 {
nuclear@0 207 key_t *ptr = tr->keys;
nuclear@0 208 int ipos = (int)(pos * MAX_POS);
nuclear@0 209
nuclear@0 210 while(ptr->next && ptr->next->pos <= ipos) {
nuclear@0 211 if(ptr->next->pos == ipos) {
nuclear@0 212 key_t *tmp = ptr->next;
nuclear@0 213 ptr->next = ptr->next->next;
nuclear@0 214 free(tmp);
nuclear@0 215 return;
nuclear@0 216 }
nuclear@0 217 ptr = ptr->next;
nuclear@0 218 }
nuclear@0 219 }
nuclear@0 220
nuclear@0 221 float get_val(struct track *tr, float pos)
nuclear@0 222 {
nuclear@0 223 float t;
nuclear@0 224 key_t *ptr = tr->keys->next;
nuclear@0 225 int ipos = (int)(pos * MAX_POS);
nuclear@0 226
nuclear@0 227 if(!ptr) {
nuclear@0 228 return 0.0;
nuclear@0 229 }
nuclear@0 230
nuclear@0 231 while(ptr && ptr->pos <= ipos) {
nuclear@0 232 if(ptr->pos == ipos || !ptr->next) {
nuclear@0 233 return ptr->val;
nuclear@0 234 }
nuclear@0 235
nuclear@0 236 if(ptr->next->pos > ipos) {
nuclear@0 237 t = (float)(ipos - ptr->pos) / (float)(ptr->next->pos - ptr->pos);
nuclear@0 238 return ptr->val + (ptr->next->val - ptr->val) * t;
nuclear@0 239 }
nuclear@0 240
nuclear@0 241 ptr = ptr->next;
nuclear@0 242 }
nuclear@0 243
nuclear@0 244 return tr->keys->next->val;
nuclear@0 245 }
nuclear@0 246
nuclear@0 247 void clear_track(struct track *tr)
nuclear@0 248 {
nuclear@0 249 key_t *ptr = tr->keys->next;
nuclear@0 250 while(ptr) {
nuclear@0 251 key_t *tmp = ptr;
nuclear@0 252 ptr = ptr->next;
nuclear@0 253 free(tmp);
nuclear@0 254 }
nuclear@0 255 tr->keys->next = 0;
nuclear@0 256 }
nuclear@0 257
nuclear@0 258
nuclear@0 259 #define IMG_X 256
nuclear@0 260 #define FNAME "grad.ppm"
nuclear@0 261 void save(void)
nuclear@0 262 {
nuclear@0 263 int i;
nuclear@0 264 FILE *fp;
nuclear@0 265
nuclear@0 266 if(!(fp = fopen(FNAME, "wb"))) {
nuclear@0 267 perror("failed to write " FNAME);
nuclear@0 268 return;
nuclear@0 269 }
nuclear@0 270
nuclear@0 271 fprintf(fp, "P6\n%d %d\n255\n", IMG_X, 1);
nuclear@0 272
nuclear@0 273 for(i=0; i<IMG_X; i++) {
nuclear@0 274 float t = (float)i / (float)IMG_X;
nuclear@0 275 int r = get_val(&tred, t) * 255.0;
nuclear@0 276 int g = get_val(&tgreen, t) * 255.0;
nuclear@0 277 int b = get_val(&tblue, t) * 255.0;
nuclear@0 278
nuclear@0 279 fputc(r, fp);
nuclear@0 280 fputc(g, fp);
nuclear@0 281 fputc(b, fp);
nuclear@0 282 }
nuclear@0 283
nuclear@0 284 fclose(fp);
nuclear@0 285 }
nuclear@0 286
nuclear@0 287
nuclear@0 288 void key_handler(unsigned char key, int x, int y)
nuclear@0 289 {
nuclear@0 290 skey_handler(key, x, y);
nuclear@0 291 }
nuclear@0 292
nuclear@0 293 void skey_handler(int key, int x, int y)
nuclear@0 294 {
nuclear@0 295 switch(key) {
nuclear@0 296 case 27:
nuclear@0 297 exit(0);
nuclear@0 298
nuclear@0 299 case 's':
nuclear@0 300 case 'S':
nuclear@0 301 save();
nuclear@0 302 break;
nuclear@0 303
nuclear@0 304 case 'c':
nuclear@0 305 clear_track(&tred);
nuclear@0 306 clear_track(&tgreen);
nuclear@0 307 clear_track(&tblue);
nuclear@0 308 glutPostRedisplay();
nuclear@0 309 break;
nuclear@0 310
nuclear@0 311 default:
nuclear@0 312 break;
nuclear@0 313 }
nuclear@0 314 }
nuclear@0 315
nuclear@0 316 static int px, py;
nuclear@0 317 static float ppos, pval;
nuclear@0 318 static struct track *tr;
nuclear@0 319
nuclear@0 320 void mbutton_handler(int bn, int state, int x, int y)
nuclear@0 321 {
nuclear@0 322 float pos, val;
nuclear@0 323
nuclear@0 324 pos = (float)x / (float)view_xsz;
nuclear@0 325 val = 1.0 - (float)y / (float)(view_ysz - view_ysz / 4.0);
nuclear@0 326
nuclear@0 327 if(bn == GLUT_LEFT_BUTTON) {
nuclear@0 328 tr = &tred;
nuclear@0 329 } else if(bn == GLUT_MIDDLE_BUTTON) {
nuclear@0 330 tr = &tgreen;
nuclear@0 331 } else if(bn == GLUT_RIGHT_BUTTON) {
nuclear@0 332 tr = &tblue;
nuclear@0 333 } else {
nuclear@0 334 return;
nuclear@0 335 }
nuclear@0 336
nuclear@0 337 if(glutGetModifiers() & GLUT_ACTIVE_CTRL) {
nuclear@0 338 tr = 0;
nuclear@0 339 }
nuclear@0 340
nuclear@0 341 if(state == 0) {
nuclear@0 342 px = x;
nuclear@0 343 py = y;
nuclear@0 344 ppos = pos;
nuclear@0 345 pval = val;
nuclear@0 346 } else {
nuclear@0 347 if(px == -1 || abs(x - px) > 2 || abs(y - py) > 2) {
nuclear@0 348 return;
nuclear@0 349 }
nuclear@0 350 if(val < 0.0 || val > 1.0) return;
nuclear@0 351
nuclear@0 352
nuclear@0 353 if(glutGetModifiers() & GLUT_ACTIVE_SHIFT) {
nuclear@0 354 if(tr) {
nuclear@0 355 rm_val(tr, pos);
nuclear@0 356 } else {
nuclear@0 357 rm_val(&tred, pos);
nuclear@0 358 rm_val(&tgreen, pos);
nuclear@0 359 rm_val(&tblue, pos);
nuclear@0 360 }
nuclear@0 361 } else {
nuclear@0 362 if(tr) {
nuclear@0 363 set_val(tr, pos, val);
nuclear@0 364 } else {
nuclear@0 365 set_val(&tred, pos, val);
nuclear@0 366 set_val(&tgreen, pos, val);
nuclear@0 367 set_val(&tblue, pos, val);
nuclear@0 368 }
nuclear@0 369 }
nuclear@0 370
nuclear@0 371 px = -1;
nuclear@0 372 py = -1;
nuclear@0 373 glutPostRedisplay();
nuclear@0 374 }
nuclear@0 375 }
nuclear@0 376
nuclear@0 377 void drag_handler(int x, int y)
nuclear@0 378 {
nuclear@0 379 float pos = (float)x / (float)view_xsz;
nuclear@0 380 float val = 1.0 - (float)y / (float)(view_ysz - view_ysz / 4.0);
nuclear@0 381
nuclear@0 382 if(pos < 0.0) pos = 0.0;
nuclear@0 383 if(pos > 1.0) pos = 1.0;
nuclear@0 384 if(val < 0.0) val = 0.0;
nuclear@0 385 if(val > 1.0) val = 1.0;
nuclear@0 386
nuclear@0 387 if(tr) {
nuclear@0 388 rm_val(tr, ppos);
nuclear@0 389 rm_val(tr, ppos - 1.0 / (float)view_xsz);
nuclear@0 390 rm_val(tr, ppos + 1.0 / (float)view_xsz);
nuclear@0 391 set_val(tr, pos, val);
nuclear@0 392 } else {
nuclear@0 393 rm_val(&tred, ppos);
nuclear@0 394 rm_val(&tgreen, ppos);
nuclear@0 395 rm_val(&tblue, ppos);
nuclear@0 396 rm_val(&tred, ppos - 1.0 / (float)view_xsz);
nuclear@0 397 rm_val(&tgreen, ppos - 1.0 / (float)view_xsz);
nuclear@0 398 rm_val(&tblue, ppos - 1.0 / (float)view_xsz);
nuclear@0 399 rm_val(&tred, ppos + 1.0 / (float)view_xsz);
nuclear@0 400 rm_val(&tgreen, ppos + 1.0 / (float)view_xsz);
nuclear@0 401 rm_val(&tblue, ppos + 1.0 / (float)view_xsz);
nuclear@0 402 set_val(&tred, pos, val);
nuclear@0 403 set_val(&tgreen, pos, val);
nuclear@0 404 set_val(&tblue, pos, val);
nuclear@0 405 }
nuclear@0 406
nuclear@0 407 ppos = pos;
nuclear@0 408 pval = val;
nuclear@0 409
nuclear@0 410 glutPostRedisplay();
nuclear@0 411 }
nuclear@0 412
nuclear@0 413 void reshape_handler(int x, int y)
nuclear@0 414 {
nuclear@0 415 view_xsz = x;
nuclear@0 416 view_ysz = y;
nuclear@0 417
nuclear@0 418 glViewport(0, 0, x, y);
nuclear@0 419 }