gradtool
changeset 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 |
files | .hgignore Makefile gradtool.c |
diffstat | 3 files changed, 443 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/.hgignore Tue Jun 19 05:30:45 2012 +0300 1.3 @@ -0,0 +1,3 @@ 1.4 +\.swp$ 1.5 +\.o$ 1.6 +^gradtool$
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/Makefile Tue Jun 19 05:30:45 2012 +0300 2.3 @@ -0,0 +1,21 @@ 2.4 +PREFIX = /usr/local 2.5 +obj = gradtool.o 2.6 +bin = gradtool 2.7 + 2.8 +CFLAGS = -std=c89 -pedantic -Wall -g 2.9 +LDFLAGS = -lglut -lGL 2.10 + 2.11 +$(bin): $(obj) 2.12 + $(CC) -o $@ $(obj) $(LDFLAGS) 2.13 + 2.14 +.PHONY: clean 2.15 +clean: 2.16 + rm -f $(obj) $(bin) 2.17 + 2.18 +.PHONY: install 2.19 +install: $(bin) 2.20 + cp $(bin) $(PREFIX)/bin/$(bin) 2.21 + 2.22 +.PHONY: uninstall 2.23 +uninstall: 2.24 + rm -f $(PREFIX)/bin/$(bin)
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/gradtool.c Tue Jun 19 05:30:45 2012 +0300 3.3 @@ -0,0 +1,419 @@ 3.4 +#include <stdio.h> 3.5 +#include <stdlib.h> 3.6 +#include <GL/glut.h> 3.7 + 3.8 +#define MAX_POS 512 3.9 + 3.10 +typedef struct key { 3.11 + int pos; 3.12 + float val; 3.13 + struct key *next; 3.14 +} key_t; 3.15 + 3.16 +struct track { 3.17 + key_t *keys; 3.18 + int count; 3.19 +}; 3.20 + 3.21 +void redraw(void); 3.22 +void draw_curves(void); 3.23 +void draw_grad(void); 3.24 + 3.25 +void set_val(struct track *track, float pos, float val); 3.26 +void rm_val(struct track *track, float pos); 3.27 +float get_val(struct track *track, float pos); 3.28 + 3.29 +void save(void); 3.30 + 3.31 +void key_handler(unsigned char key, int x, int y); 3.32 +void skey_handler(int key, int x, int y); 3.33 +void mbutton_handler(int bn, int state, int x, int y); 3.34 +void drag_handler(int x, int y); 3.35 +void reshape_handler(int x, int y); 3.36 + 3.37 +int view_xsz = 640; 3.38 +int view_ysz = 480; 3.39 + 3.40 +struct track tred, tgreen, tblue; 3.41 + 3.42 +int main(int argc, char **argv) 3.43 +{ 3.44 + glutInit(&argc, argv); 3.45 + glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); 3.46 + glutInitWindowSize(view_xsz, view_ysz); 3.47 + glutCreateWindow("Mindlapse gradiant editor"); 3.48 + 3.49 + glutDisplayFunc(redraw); 3.50 + glutKeyboardFunc(key_handler); 3.51 + glutSpecialFunc(skey_handler); 3.52 + glutMouseFunc(mbutton_handler); 3.53 + glutMotionFunc(drag_handler); 3.54 + glutReshapeFunc(reshape_handler); 3.55 + 3.56 + glClearColor(0, 0, 0, 0); 3.57 + glEnable(GL_POINT_SMOOTH); 3.58 + 3.59 + glMatrixMode(GL_PROJECTION); 3.60 + glOrtho(0, 1, 0, 1, -1, 1); 3.61 + glMatrixMode(GL_MODELVIEW); 3.62 + 3.63 + tred.keys = malloc(sizeof *tred.keys); 3.64 + tred.keys->next = 0; 3.65 + 3.66 + tgreen.keys = malloc(sizeof *tgreen.keys); 3.67 + tgreen.keys->next = 0; 3.68 + 3.69 + tblue.keys = malloc(sizeof *tblue.keys); 3.70 + tblue.keys->next = 0; 3.71 + 3.72 + glutMainLoop(); 3.73 + return 0; 3.74 +} 3.75 + 3.76 +void redraw(void) 3.77 +{ 3.78 + glClear(GL_COLOR_BUFFER_BIT); 3.79 + 3.80 + draw_curves(); 3.81 + 3.82 + draw_grad(); 3.83 + 3.84 + glutSwapBuffers(); 3.85 +} 3.86 + 3.87 +void draw_curves(void) 3.88 +{ 3.89 + int i; 3.90 + key_t *ptr; 3.91 + 3.92 + glLoadIdentity(); 3.93 + glTranslatef(0, 0.25, 0); 3.94 + glScalef(1, 0.75, 1); 3.95 + 3.96 + glBegin(GL_LINES); 3.97 + /* draw grid */ 3.98 + glColor3f(0.5, 0.5, 0.5); 3.99 + glVertex2f(0, 0); glVertex2f(0, 1); 3.100 + glVertex2f(1, 0); glVertex2f(1, 1); 3.101 + glVertex2f(0, 0); glVertex2f(1, 0); 3.102 + glVertex2f(0, 1); glVertex2f(1, 1); 3.103 + 3.104 + glVertex2f(0, 0.25); glVertex2f(1, 0.25); 3.105 + glVertex2f(0, 0.5); glVertex2f(1, 0.5); 3.106 + glVertex2f(0, 0.75); glVertex2f(1, 0.75); 3.107 + 3.108 + glVertex2f(0.25, 0); glVertex2f(0.25, 1); 3.109 + glVertex2f(0.5, 0); glVertex2f(0.5, 1); 3.110 + glVertex2f(0.75, 0); glVertex2f(0.75, 1); 3.111 + glEnd(); 3.112 + 3.113 + glEnable(GL_BLEND); 3.114 + glBlendFunc(GL_ONE, GL_ONE); 3.115 + 3.116 + glBegin(GL_LINES); 3.117 + for(i=0; i<3; i++) { 3.118 + glColor3f(i == 0, i == 1, i == 2); 3.119 + ptr = (i == 0 ? tred.keys->next : (i == 1 ? tgreen.keys->next : tblue.keys->next)); 3.120 + 3.121 + if(ptr && ptr->pos > 0) { 3.122 + glVertex2f(0, ptr->val); 3.123 + glVertex2f(ptr->pos / (float)MAX_POS, ptr->val); 3.124 + } 3.125 + 3.126 + while(ptr && ptr->next) { 3.127 + glVertex2f(ptr->pos / (float)MAX_POS, ptr->val); 3.128 + glVertex2f(ptr->next->pos / (float)MAX_POS, ptr->next->val); 3.129 + ptr = ptr->next; 3.130 + } 3.131 + 3.132 + if(ptr && ptr->pos != MAX_POS) { 3.133 + glVertex2f(ptr->pos / (float)MAX_POS, ptr->val); 3.134 + glVertex2f(1, ptr->val); 3.135 + } 3.136 + } 3.137 + glEnd(); 3.138 + 3.139 + glPointSize(5); 3.140 + glBegin(GL_POINTS); 3.141 + for(i=0; i<3; i++) { 3.142 + glColor3f(i == 0, i == 1, i == 2); 3.143 + ptr = (i == 0 ? tred.keys->next : (i == 1 ? tgreen.keys->next : tblue.keys->next)); 3.144 + 3.145 + while(ptr) { 3.146 + glVertex2f(ptr->pos / (float)MAX_POS, ptr->val); 3.147 + ptr = ptr->next; 3.148 + } 3.149 + } 3.150 + glEnd(); 3.151 + 3.152 + glDisable(GL_BLEND); 3.153 +} 3.154 + 3.155 +#define GRAD_SAMPLES MAX_POS 3.156 +void draw_grad(void) 3.157 +{ 3.158 + int i; 3.159 + 3.160 + glLoadIdentity(); 3.161 + glScalef(1, 0.25, 1); 3.162 + 3.163 + glBegin(GL_QUADS); 3.164 + for(i=0; i<GRAD_SAMPLES-1; i++) { 3.165 + float t = (float)i / (float)GRAD_SAMPLES; 3.166 + glColor3f(get_val(&tred, t), get_val(&tgreen, t), get_val(&tblue, t)); 3.167 + glVertex2f(t, 0); 3.168 + glVertex2f(t, 1); 3.169 + 3.170 + t = (float)(i + 1) / (float)GRAD_SAMPLES; 3.171 + glColor3f(get_val(&tred, t), get_val(&tgreen, t), get_val(&tblue, t)); 3.172 + glVertex2f(t, 1); 3.173 + glVertex2f(t, 0); 3.174 + } 3.175 + glEnd(); 3.176 +} 3.177 + 3.178 +void set_val(struct track *tr, float pos, float val) 3.179 +{ 3.180 + key_t *nkey; 3.181 + key_t *ptr = tr->keys; 3.182 + int ipos = (int)(pos * MAX_POS); 3.183 + 3.184 + if(!ptr->next || ptr->next->pos > ipos) { 3.185 + nkey = malloc(sizeof *nkey); 3.186 + nkey->pos = ipos; 3.187 + nkey->val = val; 3.188 + nkey->next = ptr->next; 3.189 + ptr->next = nkey; 3.190 + return; 3.191 + } 3.192 + 3.193 + while(ptr->next && ptr->next->pos < ipos) { 3.194 + ptr = ptr->next; 3.195 + } 3.196 + 3.197 + if(ptr->pos == ipos) { 3.198 + ptr->val = val; 3.199 + } else { 3.200 + nkey = malloc(sizeof *nkey); 3.201 + nkey->pos = ipos; 3.202 + nkey->val = val; 3.203 + nkey->next = ptr->next; 3.204 + ptr->next = nkey; 3.205 + } 3.206 +} 3.207 + 3.208 +void rm_val(struct track *tr, float pos) 3.209 +{ 3.210 + key_t *ptr = tr->keys; 3.211 + int ipos = (int)(pos * MAX_POS); 3.212 + 3.213 + while(ptr->next && ptr->next->pos <= ipos) { 3.214 + if(ptr->next->pos == ipos) { 3.215 + key_t *tmp = ptr->next; 3.216 + ptr->next = ptr->next->next; 3.217 + free(tmp); 3.218 + return; 3.219 + } 3.220 + ptr = ptr->next; 3.221 + } 3.222 +} 3.223 + 3.224 +float get_val(struct track *tr, float pos) 3.225 +{ 3.226 + float t; 3.227 + key_t *ptr = tr->keys->next; 3.228 + int ipos = (int)(pos * MAX_POS); 3.229 + 3.230 + if(!ptr) { 3.231 + return 0.0; 3.232 + } 3.233 + 3.234 + while(ptr && ptr->pos <= ipos) { 3.235 + if(ptr->pos == ipos || !ptr->next) { 3.236 + return ptr->val; 3.237 + } 3.238 + 3.239 + if(ptr->next->pos > ipos) { 3.240 + t = (float)(ipos - ptr->pos) / (float)(ptr->next->pos - ptr->pos); 3.241 + return ptr->val + (ptr->next->val - ptr->val) * t; 3.242 + } 3.243 + 3.244 + ptr = ptr->next; 3.245 + } 3.246 + 3.247 + return tr->keys->next->val; 3.248 +} 3.249 + 3.250 +void clear_track(struct track *tr) 3.251 +{ 3.252 + key_t *ptr = tr->keys->next; 3.253 + while(ptr) { 3.254 + key_t *tmp = ptr; 3.255 + ptr = ptr->next; 3.256 + free(tmp); 3.257 + } 3.258 + tr->keys->next = 0; 3.259 +} 3.260 + 3.261 + 3.262 +#define IMG_X 256 3.263 +#define FNAME "grad.ppm" 3.264 +void save(void) 3.265 +{ 3.266 + int i; 3.267 + FILE *fp; 3.268 + 3.269 + if(!(fp = fopen(FNAME, "wb"))) { 3.270 + perror("failed to write " FNAME); 3.271 + return; 3.272 + } 3.273 + 3.274 + fprintf(fp, "P6\n%d %d\n255\n", IMG_X, 1); 3.275 + 3.276 + for(i=0; i<IMG_X; i++) { 3.277 + float t = (float)i / (float)IMG_X; 3.278 + int r = get_val(&tred, t) * 255.0; 3.279 + int g = get_val(&tgreen, t) * 255.0; 3.280 + int b = get_val(&tblue, t) * 255.0; 3.281 + 3.282 + fputc(r, fp); 3.283 + fputc(g, fp); 3.284 + fputc(b, fp); 3.285 + } 3.286 + 3.287 + fclose(fp); 3.288 +} 3.289 + 3.290 + 3.291 +void key_handler(unsigned char key, int x, int y) 3.292 +{ 3.293 + skey_handler(key, x, y); 3.294 +} 3.295 + 3.296 +void skey_handler(int key, int x, int y) 3.297 +{ 3.298 + switch(key) { 3.299 + case 27: 3.300 + exit(0); 3.301 + 3.302 + case 's': 3.303 + case 'S': 3.304 + save(); 3.305 + break; 3.306 + 3.307 + case 'c': 3.308 + clear_track(&tred); 3.309 + clear_track(&tgreen); 3.310 + clear_track(&tblue); 3.311 + glutPostRedisplay(); 3.312 + break; 3.313 + 3.314 + default: 3.315 + break; 3.316 + } 3.317 +} 3.318 + 3.319 +static int px, py; 3.320 +static float ppos, pval; 3.321 +static struct track *tr; 3.322 + 3.323 +void mbutton_handler(int bn, int state, int x, int y) 3.324 +{ 3.325 + float pos, val; 3.326 + 3.327 + pos = (float)x / (float)view_xsz; 3.328 + val = 1.0 - (float)y / (float)(view_ysz - view_ysz / 4.0); 3.329 + 3.330 + if(bn == GLUT_LEFT_BUTTON) { 3.331 + tr = &tred; 3.332 + } else if(bn == GLUT_MIDDLE_BUTTON) { 3.333 + tr = &tgreen; 3.334 + } else if(bn == GLUT_RIGHT_BUTTON) { 3.335 + tr = &tblue; 3.336 + } else { 3.337 + return; 3.338 + } 3.339 + 3.340 + if(glutGetModifiers() & GLUT_ACTIVE_CTRL) { 3.341 + tr = 0; 3.342 + } 3.343 + 3.344 + if(state == 0) { 3.345 + px = x; 3.346 + py = y; 3.347 + ppos = pos; 3.348 + pval = val; 3.349 + } else { 3.350 + if(px == -1 || abs(x - px) > 2 || abs(y - py) > 2) { 3.351 + return; 3.352 + } 3.353 + if(val < 0.0 || val > 1.0) return; 3.354 + 3.355 + 3.356 + if(glutGetModifiers() & GLUT_ACTIVE_SHIFT) { 3.357 + if(tr) { 3.358 + rm_val(tr, pos); 3.359 + } else { 3.360 + rm_val(&tred, pos); 3.361 + rm_val(&tgreen, pos); 3.362 + rm_val(&tblue, pos); 3.363 + } 3.364 + } else { 3.365 + if(tr) { 3.366 + set_val(tr, pos, val); 3.367 + } else { 3.368 + set_val(&tred, pos, val); 3.369 + set_val(&tgreen, pos, val); 3.370 + set_val(&tblue, pos, val); 3.371 + } 3.372 + } 3.373 + 3.374 + px = -1; 3.375 + py = -1; 3.376 + glutPostRedisplay(); 3.377 + } 3.378 +} 3.379 + 3.380 +void drag_handler(int x, int y) 3.381 +{ 3.382 + float pos = (float)x / (float)view_xsz; 3.383 + float val = 1.0 - (float)y / (float)(view_ysz - view_ysz / 4.0); 3.384 + 3.385 + if(pos < 0.0) pos = 0.0; 3.386 + if(pos > 1.0) pos = 1.0; 3.387 + if(val < 0.0) val = 0.0; 3.388 + if(val > 1.0) val = 1.0; 3.389 + 3.390 + if(tr) { 3.391 + rm_val(tr, ppos); 3.392 + rm_val(tr, ppos - 1.0 / (float)view_xsz); 3.393 + rm_val(tr, ppos + 1.0 / (float)view_xsz); 3.394 + set_val(tr, pos, val); 3.395 + } else { 3.396 + rm_val(&tred, ppos); 3.397 + rm_val(&tgreen, ppos); 3.398 + rm_val(&tblue, ppos); 3.399 + rm_val(&tred, ppos - 1.0 / (float)view_xsz); 3.400 + rm_val(&tgreen, ppos - 1.0 / (float)view_xsz); 3.401 + rm_val(&tblue, ppos - 1.0 / (float)view_xsz); 3.402 + rm_val(&tred, ppos + 1.0 / (float)view_xsz); 3.403 + rm_val(&tgreen, ppos + 1.0 / (float)view_xsz); 3.404 + rm_val(&tblue, ppos + 1.0 / (float)view_xsz); 3.405 + set_val(&tred, pos, val); 3.406 + set_val(&tgreen, pos, val); 3.407 + set_val(&tblue, pos, val); 3.408 + } 3.409 + 3.410 + ppos = pos; 3.411 + pval = val; 3.412 + 3.413 + glutPostRedisplay(); 3.414 +} 3.415 + 3.416 +void reshape_handler(int x, int y) 3.417 +{ 3.418 + view_xsz = x; 3.419 + view_ysz = y; 3.420 + 3.421 + glViewport(0, 0, x, y); 3.422 +}