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 }
|