gradtool

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