Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Sphere of spheres, stress test for my ray tracer from "The Ray Tracer Challenge" (C implementation)
#include <stdio.h> /* file */
#include <stdlib.h> /* free */
#include <math.h> /* M_PI, cos, sin */
#include <limits.h> /* INT_MAX */
#include "rtc/camera.h"
#include "rtc/shapes/shape.h"
#include "rtc/shapes/sphere.h"
#include "rtc/shapes/group.h"
#include "rtc/shapes/plane.h"
#include "rtc/material.h"
#include "rtc/parallel.h"
#define SCALE ( 1 )
#define MAX_SPHERES ( 2000 )
#define RADIUS ( 12.0 )
#define frand() (1.0 * rand() / INT_MAX)
void glass_material(RTCMaterial *m, RTCTuple *color) {
rtc_material(m);
rtc_tuple_copy(&m->color, color);
m->diffuse = 0.1;
m->ambient = 0.0;
m->specular = 0.5;
m->shininess = 100;
m->reflective = 0.9;
m->transparency = 0.9;
m->refractive_index = 1.5;
}
void metal_material(RTCMaterial *m, RTCTuple *color) {
rtc_material(m);
rtc_tuple_copy(&m->color, color);
m->diffuse = 0.6;
m->ambient = 0.1;
m->specular = 0.4;
m->shininess = 7;
m->reflective = 0.1;
}
RTCTuple *random_color(RTCTuple *color) {
color->r = 0.5 + frand() * 0.5;
color->g = 0.5 + frand() * 0.5;
color->b = 0.5 + frand() * 0.5;
return color;
}
RTCMaterial *random_material(RTCMaterial *m) {
RTCTuple color;
if (rand() % 10 == 0)
glass_material(m, random_color(&color));
else
metal_material(m, random_color(&color));
return m;
}
int main(void) {
RTCWorld* world = rtc_world_create();
srand(1);
/* === LIGHT =================== */
rtc_world_add_light(world, rtc_point_light(1.0, 1.0, 1.0, -100, 100, -100));
rtc_world_add_light(world, rtc_point_light(0.2, 0.2, 0.2, 150, 30, -50));
rtc_world_add_light(world, rtc_point_light(0.5, 0.5, 0.5, 0, 0, 0));
/* === SPHERES =================== */
struct {
double x, y, z, r;
} spheres[MAX_SPHERES];
int sphere_count = 0;
RTCShape *group = rtc_group_create();
rtc_world_add_object(world, group);
RTCMaterial material;
spheres[0].x = 0.0;
spheres[0].y = RADIUS;
spheres[0].z = 0.0;
spheres[0].r = 1.0;
sphere_count++;
RTCShape *sphere = rtc_shape_describe(RTC_SPHERE,
RTC_ARG_TRANSLATE, 0.0, RADIUS, 0.0,
RTC_ARG_MATERIAL, random_material(&material),
RTC_ARG_END);
rtc_group_add(group, sphere);
int attempts = 0;
while (sphere_count < MAX_SPHERES && attempts < 10000) {
double min_r = 0.5;
double max_r = 1.5;
if (attempts > 1000) {
min_r *= 0.5;
max_r *= 0.5;
} else if (attempts > 3000) {
min_r *= 0.25;
max_r *= 0.25;
} else if (attempts > 5000) {
min_r *= 0.125;
max_r *= 0.125;
}
double theta = frand() * M_PI;
double phi = frand() * M_PI * 2;
double r = min_r + (frand() * (max_r - min_r));
double x = RADIUS * sin(theta) * cos(phi);
double y = RADIUS * cos(theta);
double z = RADIUS * sin(theta) * sin(phi);
int ok = 1;
for(int j = 0; j < sphere_count; j++) {
double x2 = spheres[j].x;
double y2 = spheres[j].y;
double z2 = spheres[j].z;
double r2 = spheres[j].r;
double xd = x - x2;
double yd = y - y2;
double zd = z - z2;
double rd = r + r2;
ok = (xd * xd + yd * yd + zd * zd > rd * rd);
if (!ok) break;
}
if (ok) {
spheres[sphere_count].x = x;
spheres[sphere_count].y = y;
spheres[sphere_count].z = z;
spheres[sphere_count].r = r;
sphere_count++;
sphere = rtc_shape_describe(RTC_SPHERE,
RTC_ARG_SCALE, r, r, r,
RTC_ARG_TRANSLATE, x, y, z,
RTC_ARG_MATERIAL, random_material(&material),
RTC_ARG_END);
rtc_group_add(group, sphere);
attempts = 0;
printf("spheres: %d (latest @ %f,%f,%f <%f>)\n", sphere_count, x, y, z, r);
} else {
attempts++;
}
}
rtc_group_subdivide(group, 25);
/* === CAMERA =================== */
RTCCamera camera;
RTCTuple from, to, up;
rtc_camera(&camera, 250*SCALE, 250*SCALE, M_PI/6);
rtc_point(&from, 50, 15, -50);
rtc_point(&to, 0, 0, 0);
rtc_vector(&up, 0, 1, 0);
rtc_matrix_view(&camera.transform, &from, &to, &up);
//camera.aa_subsamples = 3;
/* === RENDER =================== */
RTCCanvas* canvas = rtc_camera_render_parallel(&camera, world, 32);
char *ppm = rtc_canvas_to_ppm(canvas);
rtc_canvas_destroy(&canvas);
rtc_world_destroy(&world);
FILE *f = fopen("sphere-sphere.ppm", "wt");
fputs(ppm, f);
fclose(f);
free(ppm);
printf("wrote image to sphere-sphere.ppm\n");
return 0;
}
@wndxlori

This comment has been minimized.

Copy link

@wndxlori wndxlori commented Dec 30, 2018

This is probably the most readable chunk of C I’ve seen in 10 years. 👏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.