added scene loading
[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 static const char *in_fname;
20
21 int main(int argc, char **argv)
22 {
23         csg_object *oa, *ob, *oc, *obj;
24         float *pixels;
25
26         if(parse_opt(argc, argv) == -1) {
27                 return 1;
28         }
29
30         if(csg_init() == -1) {
31                 return 1;
32         }
33
34         if(csg_load(in_fname) == -1) {
35                 return 1;
36         }
37
38         if(!(pixels = malloc(width * height * 3 * sizeof *pixels))) {
39                 perror("failed to allocate framebuffer");
40                 return 1;
41         }
42
43         /*
44         csg_view(0, 0, 5, 0, 0, 0);
45
46         oa = csg_sphere(0, 0, 0, 1);
47         csg_color(oa, 1, 0.1, 0.05);
48         csg_roughness(oa, 0.3);
49         ob = csg_sphere(0.3, 0.7, 0.7, 0.7);
50         csg_color(ob, 0.2, 0.3, 1);
51         csg_roughness(ob, 0.3);
52         oc = csg_subtraction(oa, ob);
53
54         oa = oc;
55
56         ob = csg_sphere(-0.9, -0.1, 0.7, 0.5);
57         csg_color(ob, 1, 0.9, 0.2);
58         csg_roughness(ob, 0.3);
59
60         oc = csg_subtraction(oa, ob);
61
62         csg_add_object(oc);
63
64         obj = csg_plane(0, -1, 0, 0, 1, 0);
65         csg_color(obj, 0.4, 0.7, 0.4);
66         csg_add_object(obj);
67
68         obj = csg_null(-4, 10, 10);
69         csg_emission(obj, 80, 80, 80);
70         csg_add_object(obj);
71         */
72
73         csg_render_image(pixels, width, height);
74         save_image(out_fname, pixels, width, height);
75
76         csg_destroy();
77         return 0;
78 }
79
80 static int save_image(const char *fname, float *pix, int xsz, int ysz)
81 {
82         int i;
83         FILE *fp;
84
85         if(!(fp = fopen(fname, "wb"))) {
86                 fprintf(stderr, "failed to open %s for writing: %s\n", fname, strerror(errno));
87                 return -1;
88         }
89
90         fprintf(fp, "P6\n%d %d\n255\n", xsz, ysz);
91
92         for(i=0; i<xsz * ysz; i++) {
93                 unsigned int r = pow(*pix++, inv_gamma) * 255.0f;
94                 unsigned int g = pow(*pix++, inv_gamma) * 255.0f;
95                 unsigned int b = pow(*pix++, inv_gamma) * 255.0f;
96
97                 if(r > 255) r = 255;
98                 if(g > 255) g = 255;
99                 if(b > 255) b = 255;
100
101                 fputc(r, fp);
102                 fputc(g, fp);
103                 fputc(b, fp);
104         }
105         fclose(fp);
106         return 0;
107 }
108
109 static void print_usage(const char *argv0)
110 {
111         printf("Usage: %s [options] <csg file>\n", argv0);
112         printf("Options:\n");
113         printf(" -s <WxH>   output image resolution (default: %dx%d)\n", DFL_WIDTH, DFL_HEIGHT);
114         printf(" -g <gamma> set output gamma (default: %g)\n", DFL_GAMMA);
115         printf(" -o <file>  output image file (default: %s)\n", DFL_OUTFILE);
116         printf(" -h         print usage information and exit\n");
117 }
118
119 static int parse_opt(int argc, char **argv)
120 {
121         int i;
122
123         for(i=1; i<argc; i++) {
124                 if(argv[i][0] == '-') {
125                         if(argv[i][2] == 0) {
126                                 switch(argv[i][1]) {
127                                 case 's':
128                                         if(sscanf(argv[++i], "%dx%d", &width, &height) != 2) {
129                                                 fprintf(stderr, "-s must be followed by WIDTHxHEIGHT\n");
130                                                 return -1;
131                                         }
132                                         break;
133
134                                 case 'g':
135                                         if((inv_gamma = atof(argv[++i])) == 0.0f) {
136                                                 fprintf(stderr, "-g must be followed by a non-zero gamma value\n");
137                                                 return -1;
138                                         }
139                                         inv_gamma = 1.0f / inv_gamma;
140                                         break;
141
142                                 case 'o':
143                                         out_fname = argv[++i];
144                                         break;
145
146                                 case 'h':
147                                         print_usage(argv[0]);
148                                         exit(0);
149
150                                 default:
151                                         fprintf(stderr, "invalid option: %s\n", argv[i]);
152                                         return -1;
153                                 }
154                         } else {
155                                 fprintf(stderr, "invalid option: %s\n", argv[i]);
156                                 return -1;
157                         }
158                 } else {
159                         if(in_fname) {
160                                 fprintf(stderr, "unexpected argument: %s\n", argv[i]);
161                                 return -1;
162                         }
163                         in_fname = argv[i];
164                 }
165         }
166
167         if(!in_fname) {
168                 fprintf(stderr, "you need to pass a scene file to read\n");
169                 return -1;
170         }
171
172         return 0;
173 }