subtraction seems to work now
[csgray] / src / main.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <math.h>
5 #include <errno.h>
6 #include "csgray.h"
7
8 #define DFL_WIDTH       800
9 #define DFL_HEIGHT      600
10 #define DFL_GAMMA       2.2f
11 #define DFL_OUTFILE     "output.ppm"
12
13 static int save_image(const char *fname, float *pix, int xsz, int ysz);
14 static int parse_opt(int argc, char **argv);
15
16 static int width = DFL_WIDTH, height = DFL_HEIGHT;
17 static float inv_gamma = 1.0f / DFL_GAMMA;
18 static const char *out_fname = DFL_OUTFILE;
19
20 int main(int argc, char **argv)
21 {
22         csg_object *oa, *ob, *oc, *obj;
23         float *pixels;
24
25         if(parse_opt(argc, argv) == -1) {
26                 return 1;
27         }
28
29         if(csg_init() == -1) {
30                 return 1;
31         }
32
33         if(!(pixels = malloc(width * height * 3 * sizeof *pixels))) {
34                 perror("failed to allocate framebuffer");
35                 return 1;
36         }
37
38         csg_view(0, 0, 5, 0, 0, 0);
39
40         oa = csg_sphere(0, 0, 0, 1);
41         csg_color(oa, 1, 0.1, 0.05);
42         ob = csg_sphere(0.3, 0.7, 0.7, 0.7);
43         csg_color(ob, 0.2, 0.3, 1);
44         oc = csg_subtraction(oa, ob);
45         csg_add_object(oc);
46
47         obj = csg_plane(0, -1, 0, 0, 1, 0);
48         csg_color(obj, 0.4, 0.7, 0.4);
49         csg_add_object(obj);
50
51         obj = csg_null(-4, 10, 10);
52         csg_emission(obj, 80, 80, 80);
53         csg_add_object(obj);
54
55         csg_render_image(pixels, width, height);
56         save_image(out_fname, pixels, width, height);
57
58         csg_destroy();
59         return 0;
60 }
61
62 static int save_image(const char *fname, float *pix, int xsz, int ysz)
63 {
64         int i;
65         FILE *fp;
66
67         if(!(fp = fopen(fname, "wb"))) {
68                 fprintf(stderr, "failed to open %s for writing: %s\n", fname, strerror(errno));
69                 return -1;
70         }
71
72         fprintf(fp, "P6\n%d %d\n255\n", xsz, ysz);
73
74         for(i=0; i<xsz * ysz; i++) {
75                 unsigned int r = pow(*pix++, inv_gamma) * 255.0f;
76                 unsigned int g = pow(*pix++, inv_gamma) * 255.0f;
77                 unsigned int b = pow(*pix++, inv_gamma) * 255.0f;
78
79                 if(r > 255) r = 255;
80                 if(g > 255) g = 255;
81                 if(b > 255) b = 255;
82
83                 fputc(r, fp);
84                 fputc(g, fp);
85                 fputc(b, fp);
86         }
87         fclose(fp);
88         return 0;
89 }
90
91 static void print_usage(const char *argv0)
92 {
93         printf("Usage: %s [options] <csg file>\n", argv0);
94         printf("Options:\n");
95         printf(" -s <WxH>   output image resolution (default: %dx%d)\n", DFL_WIDTH, DFL_HEIGHT);
96         printf(" -g <gamma> set output gamma (default: %g)\n", DFL_GAMMA);
97         printf(" -o <file>  output image file (default: %s)\n", DFL_OUTFILE);
98         printf(" -h         print usage information and exit\n");
99 }
100
101 static int parse_opt(int argc, char **argv)
102 {
103         int i;
104
105         for(i=1; i<argc; i++) {
106                 if(argv[i][0] == '-') {
107                         if(argv[i][2] == 0) {
108                                 switch(argv[i][1]) {
109                                 case 's':
110                                         if(sscanf(argv[++i], "%dx%d", &width, &height) != 2) {
111                                                 fprintf(stderr, "-s must be followed by WIDTHxHEIGHT\n");
112                                                 return -1;
113                                         }
114                                         break;
115
116                                 case 'g':
117                                         if((inv_gamma = atof(argv[++i])) == 0.0f) {
118                                                 fprintf(stderr, "-g must be followed by a non-zero gamma value\n");
119                                                 return -1;
120                                         }
121                                         inv_gamma = 1.0f / inv_gamma;
122                                         break;
123
124                                 case 'o':
125                                         out_fname = argv[++i];
126                                         break;
127
128                                 case 'h':
129                                         print_usage(argv[0]);
130                                         exit(0);
131
132                                 default:
133                                         fprintf(stderr, "invalid option: %s\n", argv[i]);
134                                         return -1;
135                                 }
136                         } else {
137                                 fprintf(stderr, "invalid option: %s\n", argv[i]);
138                                 return -1;
139                         }
140                 } else {
141                         fprintf(stderr, "unexpected argument: %s\n", argv[i]);
142                         return -1;
143                 }
144         }
145         return 0;
146 }