9 static void calc_primary_ray(struct ray *ray, int x, int y, int w, int h, float aspect);
10 static int ray_trace(struct ray *ray, float *col);
11 static void shade(float *col, struct ray *ray, struct hit *hit);
12 static void background(float *col, struct ray *ray);
13 static int find_intersection(struct ray *ray, struct hit *best);
15 static struct camera cam;
16 static csg_object *oblist;
21 csg_view(0, 0, 5, 0, 0, 0);
27 void csg_destroy(void)
30 csg_object *o = oblist;
31 oblist = oblist->ob.next;
37 void csg_view(float x, float y, float z, float tx, float ty, float tz)
47 void csg_fov(float fov)
49 cam.fov = M_PI * fov / 180.0f;
53 int csg_load(const char *fname)
58 int csg_save(const char *fname)
63 void csg_add_object(csg_object *o)
69 int csg_remove_object(csg_object *o)
73 dummy.ob.next = oblist;
78 n->ob.next = o->ob.next;
86 void csg_free_object(csg_object *o)
94 static union csg_object *alloc_object(int type)
98 if(!(o = calloc(sizeof *o, 1))) {
102 mat4_identity(o->ob.xform);
103 mat4_identity(o->ob.inv_xform);
105 csg_emission(o, 0, 0, 0);
106 csg_color(o, 1, 1, 1);
113 csg_object *csg_null(float x, float y, float z)
115 return alloc_object(OB_NULL);
118 csg_object *csg_sphere(float x, float y, float z, float r)
122 if(!(o = alloc_object(OB_SPHERE))) {
127 mat4_translation(o->ob.xform, x, y, z);
128 mat4_copy(o->ob.inv_xform, o->ob.xform);
129 mat4_inverse(o->ob.inv_xform);
133 csg_object *csg_cylinder(float x0, float y0, float z0, float x1, float y1, float z1, float r)
139 if(!(o = alloc_object(OB_CYLINDER))) {
147 if(fabs(dx) > fabs(dy) && fabs(dx) > fabs(dz)) {
149 } else if(fabs(dy) > fabs(dz)) {
156 mat4_lookat(o->ob.xform, x0, y0, z0, x1, y1, z1, 0, major == 2 ? 1 : 0, major == 2 ? 0 : 1);
157 mat4_copy(o->ob.inv_xform, o->ob.xform);
158 mat4_inverse(o->ob.inv_xform);
162 csg_object *csg_plane(float x, float y, float z, float nx, float ny, float nz)
167 if(!(o = alloc_object(OB_PLANE))) {
171 len = sqrt(nx * nx + ny * ny + nz * nz);
173 float s = 1.0f / len;
182 o->plane.d = x * nx + y * ny + z * nz;
186 csg_object *csg_box(float x, float y, float z, float xsz, float ysz, float zsz)
191 csg_object *csg_union(csg_object *a, csg_object *b)
195 if(!(o = alloc_object(OB_UNION))) {
203 csg_object *csg_intersection(csg_object *a, csg_object *b)
207 if(!(o = alloc_object(OB_INTERSECTION))) {
215 csg_object *csg_subtraction(csg_object *a, csg_object *b)
219 if(!(o = alloc_object(OB_SUBTRACTION))) {
228 void csg_emission(csg_object *o, float r, float g, float b)
235 void csg_color(csg_object *o, float r, float g, float b)
242 void csg_roughness(csg_object *o, float r)
247 void csg_opacity(csg_object *o, float p)
253 void csg_render_pixel(int x, int y, int width, int height, float aspect, float *color)
257 calc_primary_ray(&ray, x, y, width, height, aspect);
258 ray_trace(&ray, color);
261 void csg_render_image(float *pixels, int width, int height)
264 float aspect = (float)width / (float)height;
266 for(i=0; i<height; i++) {
267 for(j=0; j<width; j++) {
268 csg_render_pixel(j, i, width, height, aspect, pixels);
274 static void calc_primary_ray(struct ray *ray, int x, int y, int w, int h, float aspect)
278 px = aspect * ((float)x / (float)w * 2.0f - 1.0f);
279 py = 1.0f - (float)y / (float)h * 2.0f;
285 ray->dx = ray->dy = 0.0f;
289 static int ray_trace(struct ray *ray, float *col)
293 if(!find_intersection(ray, &hit)) {
294 background(col, ray);
298 shade(col, ray, &hit);
302 static void shade(float *col, struct ray *ray, struct hit *hit)
305 col[1] = col[2] = 0.0f;
308 static void background(float *col, struct ray *ray)
310 col[0] = col[1] = col[2] = 0.0f;
313 static int find_intersection(struct ray *ray, struct hit *best)
323 if((hit = ray_intersect(ray, o)) && hit->t < best->t) {