Move to unions instead of structure headers
Using explicit pointer casts silences some compiler warnings that may introduce subtle bugs in the code. The union approach is the officially documented way of doing type punning, so there is no reason not to use it.
This commit is contained in:
parent
f23e454358
commit
9b0abbc5bb
216
hittable.c
216
hittable.c
@ -16,19 +16,102 @@ void hit_record_set_face_normal(HitRecord *record, Ray r, Vec3 outward_normal) {
|
||||
record->front_face ? outward_normal : vec3_neg(outward_normal);
|
||||
}
|
||||
|
||||
Hittable *hittable_create_hittable_list(Arena *arena) {
|
||||
Hittable *result = arena_alloc(arena, sizeof(Hittable));
|
||||
result->type = HITTABLE_LIST;
|
||||
return result;
|
||||
}
|
||||
|
||||
Hittable *hittable_create_sphere(Point3 center, double radius,
|
||||
const Material *material, Arena *arena) {
|
||||
Hittable *result = arena_alloc(arena, sizeof(Hittable));
|
||||
result->type = HITTABLE_SPHERE;
|
||||
result->sphere.center = center;
|
||||
result->sphere.radius = radius;
|
||||
result->sphere.material = material;
|
||||
return result;
|
||||
}
|
||||
|
||||
Point3 moving_sphere_center(const MovingSphere *sphere, double t) {
|
||||
Vec3 dir = point3_sub(sphere->center_end, sphere->center_start);
|
||||
double c = (t - sphere->start) / (sphere->end - sphere->start);
|
||||
return point3_add(sphere->center_start, vec3_mul(c, dir));
|
||||
}
|
||||
|
||||
typedef int BoxCompareFunc(const void *lhs, const void *rhs);
|
||||
|
||||
#define BOX_COMPARATOR(axis) \
|
||||
static int box_##axis##_compare(const void *lhs, const void *rhs) { \
|
||||
AABB lhs_box, rhs_box; \
|
||||
if (!hittable_bounding_box(*(const Hittable **)lhs, 0, 0, &lhs_box) || \
|
||||
!hittable_bounding_box(*(const Hittable **)rhs, 0, 0, &rhs_box)) { \
|
||||
fprintf(stderr, "No bounding-box in BVH node"); \
|
||||
exit(1); \
|
||||
} \
|
||||
\
|
||||
return lhs_box.min.axis < rhs_box.min.axis; \
|
||||
}
|
||||
BOX_COMPARATOR(x)
|
||||
BOX_COMPARATOR(y)
|
||||
BOX_COMPARATOR(z)
|
||||
#undef BOX_COMPARATOR
|
||||
|
||||
Hittable *hittable_create_bvh_node(const Hittable **objects, size_t start,
|
||||
size_t end, double time_start,
|
||||
double time_end, Arena *arena) {
|
||||
Hittable *result = arena_alloc(arena, sizeof(Hittable));
|
||||
result->type = HITTABLE_BVH_NODE;
|
||||
|
||||
int axis = random_int_in_range(0, 2);
|
||||
BoxCompareFunc *comparator = (axis == 0) ? box_x_compare
|
||||
: (axis == 1) ? box_y_compare
|
||||
: box_z_compare;
|
||||
|
||||
size_t object_span = end - start;
|
||||
if (object_span == 1) {
|
||||
result->bvh_node.left = result->bvh_node.right = objects[start];
|
||||
} else if (object_span == 2) {
|
||||
if (comparator(&objects[start], &objects[start + 1])) {
|
||||
result->bvh_node.left = objects[start];
|
||||
result->bvh_node.right = objects[start + 1];
|
||||
} else {
|
||||
result->bvh_node.left = objects[start + 1];
|
||||
result->bvh_node.right = objects[start];
|
||||
}
|
||||
} else {
|
||||
qsort(objects + start, object_span, sizeof(const Hittable *), comparator);
|
||||
size_t mid = start + object_span / 2;
|
||||
result->bvh_node.left = hittable_create_bvh_node(
|
||||
objects, start, mid, time_start, time_end, arena);
|
||||
result->bvh_node.right = hittable_create_bvh_node(
|
||||
objects, mid, end, time_start, time_end, arena);
|
||||
}
|
||||
|
||||
AABB left_box, right_box;
|
||||
|
||||
if (!hittable_bounding_box(result->bvh_node.left, time_start, time_end,
|
||||
&left_box) ||
|
||||
!hittable_bounding_box(result->bvh_node.right, time_start, time_end,
|
||||
&right_box)) {
|
||||
fprintf(stderr, "No bounding-box in BVH node");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
result->bvh_node.box = aabb_surrounding_box(&left_box, &right_box);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool hittable_hit(const Hittable *hittable, Ray r, double t_min, double t_max,
|
||||
HitRecord *record) {
|
||||
switch (hittable->type) {
|
||||
case HITTABLE_LIST:
|
||||
return hittable_list_hit((const HittableList *)hittable, r, t_min, t_max,
|
||||
record);
|
||||
return hittable_list_hit(&hittable->list, r, t_min, t_max, record);
|
||||
case HITTABLE_SPHERE:
|
||||
return sphere_hit((const Sphere *)hittable, r, t_min, t_max, record);
|
||||
return sphere_hit(&hittable->sphere, r, t_min, t_max, record);
|
||||
case HITTABLE_MOVING_SPHERE:
|
||||
return moving_sphere_hit((const MovingSphere *)hittable, r, t_min, t_max,
|
||||
record);
|
||||
return moving_sphere_hit(&hittable->moving_sphere, r, t_min, t_max, record);
|
||||
case HITTABLE_BVH_NODE:
|
||||
return bvh_node_hit((const BVHNode *)hittable, r, t_min, t_max, record);
|
||||
return bvh_node_hit(&hittable->bvh_node, r, t_min, t_max, record);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -37,27 +120,21 @@ bool hittable_bounding_box(const Hittable *hittable, double time_start,
|
||||
double time_end, AABB *bounding_box) {
|
||||
switch (hittable->type) {
|
||||
case HITTABLE_LIST:
|
||||
return hittable_list_bounding_box((const HittableList *)hittable,
|
||||
time_start, time_end, bounding_box);
|
||||
return hittable_list_bounding_box(&hittable->list, time_start, time_end,
|
||||
bounding_box);
|
||||
case HITTABLE_SPHERE:
|
||||
return sphere_bounding_box((const Sphere *)hittable, time_start, time_end,
|
||||
return sphere_bounding_box(&hittable->sphere, time_start, time_end,
|
||||
bounding_box);
|
||||
case HITTABLE_MOVING_SPHERE:
|
||||
return moving_sphere_bounding_box((const MovingSphere *)hittable,
|
||||
time_start, time_end, bounding_box);
|
||||
return moving_sphere_bounding_box(&hittable->moving_sphere, time_start,
|
||||
time_end, bounding_box);
|
||||
case HITTABLE_BVH_NODE:
|
||||
return bvh_node_bounding_box((const BVHNode *)hittable, time_start,
|
||||
time_end, bounding_box);
|
||||
return bvh_node_bounding_box(&hittable->bvh_node, time_start, time_end,
|
||||
bounding_box);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
HittableList *hittable_list_create(Arena *arena) {
|
||||
HittableList *list = arena_alloc(arena, sizeof(HittableList));
|
||||
list->type = HITTABLE_LIST;
|
||||
return list;
|
||||
}
|
||||
|
||||
static void hittable_list_grow(HittableList *list, size_t n, Arena *arena) {
|
||||
if (list->objects) {
|
||||
const Hittable **new_objects =
|
||||
@ -114,16 +191,6 @@ bool hittable_list_bounding_box(const HittableList *list, double time_start,
|
||||
return true;
|
||||
}
|
||||
|
||||
Sphere *sphere_create(Point3 center, double radius, const Material *material,
|
||||
Arena *arena) {
|
||||
Sphere *sphere = arena_alloc(arena, sizeof(Sphere));
|
||||
sphere->type = HITTABLE_SPHERE;
|
||||
sphere->center = center;
|
||||
sphere->radius = radius;
|
||||
sphere->material = material;
|
||||
return sphere;
|
||||
}
|
||||
|
||||
bool sphere_hit(const Sphere *sphere, Ray r, double t_min, double t_max,
|
||||
HitRecord *record) {
|
||||
Vec3 oc = point3_sub(r.origin, sphere->center);
|
||||
@ -163,25 +230,20 @@ bool sphere_bounding_box(const Sphere *sphere, double time_start,
|
||||
return true;
|
||||
}
|
||||
|
||||
MovingSphere *moving_sphere_create(Point3 center_start, Point3 center_end,
|
||||
double start, double end, double radius,
|
||||
const Material *material, Arena *arena) {
|
||||
Hittable *hittable_create_moving_sphere(Point3 center_start, Point3 center_end,
|
||||
double start, double end, double radius,
|
||||
const Material *material,
|
||||
Arena *arena) {
|
||||
assert(start <= end);
|
||||
MovingSphere *sphere = arena_alloc(arena, sizeof(MovingSphere));
|
||||
sphere->type = HITTABLE_MOVING_SPHERE;
|
||||
sphere->center_start = center_start;
|
||||
sphere->center_end = center_end;
|
||||
sphere->start = start;
|
||||
sphere->end = end;
|
||||
sphere->radius = radius;
|
||||
sphere->material = material;
|
||||
return sphere;
|
||||
}
|
||||
|
||||
Point3 moving_sphere_center(const MovingSphere *sphere, double t) {
|
||||
Vec3 dir = point3_sub(sphere->center_end, sphere->center_start);
|
||||
double c = (t - sphere->start) / (sphere->end - sphere->start);
|
||||
return point3_add(sphere->center_start, vec3_mul(c, dir));
|
||||
Hittable *result = arena_alloc(arena, sizeof(Hittable));
|
||||
result->type = HITTABLE_MOVING_SPHERE;
|
||||
result->moving_sphere.center_start = center_start;
|
||||
result->moving_sphere.center_end = center_end;
|
||||
result->moving_sphere.start = start;
|
||||
result->moving_sphere.end = end;
|
||||
result->moving_sphere.radius = radius;
|
||||
result->moving_sphere.material = material;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool moving_sphere_hit(const MovingSphere *sphere, Ray r, double t_min,
|
||||
@ -232,66 +294,6 @@ bool moving_sphere_bounding_box(const MovingSphere *sphere, double time_start,
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef int BoxCompareFunc(const void *lhs, const void *rhs);
|
||||
|
||||
#define BOX_COMPARATOR(axis) \
|
||||
static int box_##axis##_compare(const void *lhs, const void *rhs) { \
|
||||
AABB lhs_box, rhs_box; \
|
||||
if (!hittable_bounding_box(*(const Hittable **)lhs, 0, 0, &lhs_box) || \
|
||||
!hittable_bounding_box(*(const Hittable **)rhs, 0, 0, &rhs_box)) { \
|
||||
fprintf(stderr, "No bounding-box in BVH node"); \
|
||||
exit(1); \
|
||||
} \
|
||||
\
|
||||
return lhs_box.min.axis < rhs_box.min.axis; \
|
||||
}
|
||||
BOX_COMPARATOR(x)
|
||||
BOX_COMPARATOR(y)
|
||||
BOX_COMPARATOR(z)
|
||||
#undef BOX_COMPARATOR
|
||||
|
||||
BVHNode *bvh_node_create(const Hittable **objects, size_t start, size_t end,
|
||||
double time_start, double time_end, Arena *arena) {
|
||||
BVHNode *node = arena_alloc(arena, sizeof(BVHNode));
|
||||
node->type = HITTABLE_BVH_NODE;
|
||||
|
||||
int axis = random_int_in_range(0, 2);
|
||||
BoxCompareFunc *comparator = (axis == 0) ? box_x_compare
|
||||
: (axis == 1) ? box_y_compare
|
||||
: box_z_compare;
|
||||
|
||||
size_t object_span = end - start;
|
||||
if (object_span == 1) {
|
||||
node->left = node->right = objects[start];
|
||||
} else if (object_span == 2) {
|
||||
if (comparator(&objects[start], &objects[start + 1])) {
|
||||
node->left = objects[start];
|
||||
node->right = objects[start + 1];
|
||||
} else {
|
||||
node->left = objects[start + 1];
|
||||
node->right = objects[start];
|
||||
}
|
||||
} else {
|
||||
qsort(objects + start, object_span, sizeof(const Hittable *), comparator);
|
||||
size_t mid = start + object_span / 2;
|
||||
node->left = (const Hittable *)bvh_node_create(objects, start, mid,
|
||||
time_start, time_end, arena);
|
||||
node->right = (const Hittable *)bvh_node_create(
|
||||
objects, mid, end, time_start, time_end, arena);
|
||||
}
|
||||
|
||||
AABB left_box, right_box;
|
||||
|
||||
if (!hittable_bounding_box(node->left, time_start, time_end, &left_box) ||
|
||||
!hittable_bounding_box(node->right, time_start, time_end, &right_box)) {
|
||||
fprintf(stderr, "No bounding-box in BVH node");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
node->box = aabb_surrounding_box(&left_box, &right_box);
|
||||
return node;
|
||||
}
|
||||
|
||||
bool bvh_node_hit(const BVHNode *node, Ray r, double t_min, double t_max,
|
||||
HitRecord *record) {
|
||||
if (!aabb_hit(&node->box, r, t_min, t_max))
|
||||
|
||||
84
hittable.h
84
hittable.h
@ -28,23 +28,58 @@ typedef enum HittableType {
|
||||
HITTABLE_BVH_NODE,
|
||||
} HittableType;
|
||||
|
||||
typedef struct Hittable {
|
||||
typedef struct Hittable Hittable;
|
||||
|
||||
typedef struct HittableList {
|
||||
const Hittable **objects;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
} HittableList;
|
||||
|
||||
typedef struct Sphere {
|
||||
const Material *material;
|
||||
Point3 center;
|
||||
double radius;
|
||||
} Sphere;
|
||||
|
||||
typedef struct MovingSphere {
|
||||
const Material *material;
|
||||
Point3 center_start, center_end;
|
||||
double start, end;
|
||||
double radius;
|
||||
} MovingSphere;
|
||||
|
||||
typedef struct BVHNode {
|
||||
const Hittable *left;
|
||||
const Hittable *right;
|
||||
AABB box;
|
||||
} BVHNode;
|
||||
|
||||
struct Hittable {
|
||||
HittableType type;
|
||||
} Hittable;
|
||||
union {
|
||||
HittableList list;
|
||||
Sphere sphere;
|
||||
MovingSphere moving_sphere;
|
||||
BVHNode bvh_node;
|
||||
};
|
||||
};
|
||||
|
||||
Hittable *hittable_create_hittable_list(Arena *arena);
|
||||
Hittable *hittable_create_sphere(Point3 center, double radius,
|
||||
const Material *material, Arena *arena);
|
||||
Hittable *hittable_create_moving_sphere(Point3 center_start, Point3 center_end,
|
||||
double start, double end, double radius,
|
||||
const Material *material, Arena *arena);
|
||||
Hittable *hittable_create_bvh_node(const Hittable **objects, size_t start,
|
||||
size_t end, double time_start,
|
||||
double time_end, Arena *arena);
|
||||
|
||||
bool hittable_hit(const Hittable *hittable, Ray r, double t_min, double t_max,
|
||||
HitRecord *record);
|
||||
bool hittable_bounding_box(const Hittable *hittable, double time_start,
|
||||
double time_end, AABB *bounding_box);
|
||||
|
||||
typedef struct HittableList {
|
||||
HittableType type;
|
||||
const Hittable **objects;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
} HittableList;
|
||||
|
||||
HittableList *hittable_list_create(Arena *arena);
|
||||
void hittable_list_add(HittableList *list, const Hittable *hittable,
|
||||
Arena *arena);
|
||||
bool hittable_list_hit(const HittableList *list, Ray r, double t_min,
|
||||
@ -52,46 +87,17 @@ bool hittable_list_hit(const HittableList *list, Ray r, double t_min,
|
||||
bool hittable_list_bounding_box(const HittableList *list, double time_start,
|
||||
double time_end, AABB *bounding_box);
|
||||
|
||||
typedef struct Sphere {
|
||||
HittableType type;
|
||||
const Material *material;
|
||||
Point3 center;
|
||||
double radius;
|
||||
} Sphere;
|
||||
|
||||
Sphere *sphere_create(Point3 center, double radius, const Material *material,
|
||||
Arena *arena);
|
||||
bool sphere_hit(const Sphere *sphere, Ray r, double t_min, double t_max,
|
||||
HitRecord *record);
|
||||
bool sphere_bounding_box(const Sphere *sphere, double time_start,
|
||||
double time_end, AABB *bounding_box);
|
||||
|
||||
typedef struct MovingSphere {
|
||||
HittableType type;
|
||||
const Material *material;
|
||||
Point3 center_start, center_end;
|
||||
double start, end;
|
||||
double radius;
|
||||
} MovingSphere;
|
||||
|
||||
MovingSphere *moving_sphere_create(Point3 center_start, Point3 center_end,
|
||||
double start, double end, double radius,
|
||||
const Material *material, Arena *arena);
|
||||
Point3 moving_sphere_center(const MovingSphere *sphere, double t);
|
||||
bool moving_sphere_hit(const MovingSphere *sphere, Ray r, double t_min,
|
||||
double t_max, HitRecord *record);
|
||||
bool moving_sphere_bounding_box(const MovingSphere *sphere, double time_start,
|
||||
double time_end, AABB *bounding_box);
|
||||
|
||||
typedef struct BVHNode {
|
||||
HittableType type;
|
||||
const Hittable *left;
|
||||
const Hittable *right;
|
||||
AABB box;
|
||||
} BVHNode;
|
||||
|
||||
BVHNode *bvh_node_create(const Hittable **objects, size_t start, size_t end,
|
||||
double time_start, double time_end, Arena *arena);
|
||||
bool bvh_node_hit(const BVHNode *node, Ray r, double t_min, double t_max,
|
||||
HitRecord *record);
|
||||
bool bvh_node_bounding_box(const BVHNode *node, double time_start,
|
||||
|
||||
71
main.c
71
main.c
@ -35,16 +35,15 @@ static Color ray_color(Ray r, const Hittable *world, int depth) {
|
||||
}
|
||||
|
||||
static const Hittable *generate_random_scene(Arena *arena) {
|
||||
HittableList *world = hittable_list_create(arena);
|
||||
Hittable *world = hittable_create_hittable_list(arena);
|
||||
|
||||
const Lambertian *ground_material =
|
||||
lambertian_create((Color){0.5, 0.5, 0.5}, arena);
|
||||
const Sphere *ground_sphere =
|
||||
sphere_create((Point3){0.0, -1000.0, 0.0}, 1000.0,
|
||||
(const Material *)ground_material, arena);
|
||||
hittable_list_add(world, (const Hittable *)ground_sphere, arena);
|
||||
const Material *ground_material =
|
||||
material_create_lambertian((Color){0.5, 0.5, 0.5}, arena);
|
||||
const Hittable *ground_sphere = hittable_create_sphere((Point3){0.0, -1000.0, 0.0},
|
||||
1000.0, ground_material, arena);
|
||||
hittable_list_add(&world->list, ground_sphere, arena);
|
||||
|
||||
const Dielectric *glass = dielectric_create(1.5, arena);
|
||||
const Material *glass = material_create_dielectric(1.5, arena);
|
||||
|
||||
for (int a = -11; a < 11; ++a) {
|
||||
for (int b = -11; b < 11; ++b) {
|
||||
@ -54,47 +53,45 @@ static const Hittable *generate_random_scene(Arena *arena) {
|
||||
|
||||
if (vec3_length(point3_sub(center, (Point3){4.0, 0.2, 0.0})) > 0.9) {
|
||||
if (choose_material < 0.8) {
|
||||
const Lambertian *material = lambertian_create(
|
||||
const Material *material = material_create_lambertian(
|
||||
color_mul(color_random(), color_random()), arena);
|
||||
Point3 center2 = point3_add(
|
||||
center, (Vec3){0, random_double_in_range(0.0, 0.5), 0});
|
||||
const MovingSphere *sphere =
|
||||
moving_sphere_create(center, center2, 0.0, 1.0, 0.2,
|
||||
(const Material *)material, arena);
|
||||
hittable_list_add(world, (const Hittable *)sphere, arena);
|
||||
const Hittable *sphere = hittable_create_moving_sphere(
|
||||
center, center2, 0.0, 1.0, 0.2, material, arena);
|
||||
hittable_list_add(&world->list, sphere, arena);
|
||||
} else if (choose_material < 0.95) {
|
||||
const Metal *material =
|
||||
metal_create(color_random_in_range(0.5, 1),
|
||||
random_double_in_range(0.5, 1.0), arena);
|
||||
const Sphere *sphere =
|
||||
sphere_create(center, 0.2, (const Material *)material, arena);
|
||||
hittable_list_add(world, (const Hittable *)sphere, arena);
|
||||
const Material *material =
|
||||
material_create_metal(color_random_in_range(0.5, 1),
|
||||
random_double_in_range(0.5, 1.0), arena);
|
||||
const Hittable *sphere = hittable_create_sphere(center, 0.2, material, arena);
|
||||
hittable_list_add(&world->list, sphere, arena);
|
||||
} else {
|
||||
const Sphere *sphere =
|
||||
sphere_create(center, 0.2, (const Material *)glass, arena);
|
||||
hittable_list_add(world, (const Hittable *)sphere, arena);
|
||||
const Hittable *sphere = hittable_create_sphere(center, 0.2, glass, arena);
|
||||
hittable_list_add(&world->list, sphere, arena);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Lambertian *lambertian =
|
||||
lambertian_create((Color){0.4, 0.2, 0.1}, arena);
|
||||
const Metal *metal = metal_create((Color){0.7, 0.6, 0.5}, 0.0, arena);
|
||||
const Material *lambertian =
|
||||
material_create_lambertian((Color){0.4, 0.2, 0.1}, arena);
|
||||
const Material *metal =
|
||||
material_create_metal((Color){0.7, 0.6, 0.5}, 0.0, arena);
|
||||
|
||||
const Sphere *sphere1 = sphere_create((Point3){0.0, 1.0, 0.0}, 1.0,
|
||||
(const Material *)glass, arena);
|
||||
hittable_list_add(world, (const Hittable *)sphere1, arena);
|
||||
const Sphere *sphere2 = sphere_create((Point3){-4.0, 1.0, 0.0}, 1.0,
|
||||
(const Material *)lambertian, arena);
|
||||
hittable_list_add(world, (const Hittable *)sphere2, arena);
|
||||
const Sphere *sphere3 = sphere_create((Point3){4.0, 1.0, 0.0}, 1.0,
|
||||
(const Material *)metal, arena);
|
||||
hittable_list_add(world, (const Hittable *)sphere3, arena);
|
||||
const Hittable *sphere1 =
|
||||
hittable_create_sphere((Point3){0.0, 1.0, 0.0}, 1.0, glass, arena);
|
||||
hittable_list_add(&world->list, sphere1, arena);
|
||||
const Hittable *sphere2 =
|
||||
hittable_create_sphere((Point3){-4.0, 1.0, 0.0}, 1.0, lambertian, arena);
|
||||
hittable_list_add(&world->list, sphere2, arena);
|
||||
const Hittable *sphere3 =
|
||||
hittable_create_sphere((Point3){4.0, 1.0, 0.0}, 1.0, metal, arena);
|
||||
hittable_list_add(&world->list, sphere3, arena);
|
||||
|
||||
BVHNode *bvh_root =
|
||||
bvh_node_create(world->objects, 0, world->size, 0.0, 1.0, arena);
|
||||
return (const Hittable *)bvh_root;
|
||||
Hittable *bvh_root = hittable_create_bvh_node(world->list.objects, 0, world->list.size,
|
||||
0.0, 1.0, arena);
|
||||
return bvh_root;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
|
||||
43
material.c
43
material.c
@ -12,23 +12,22 @@ bool material_scatter(const Material *material, Ray r,
|
||||
Ray *scattered) {
|
||||
switch (material->type) {
|
||||
case MATERIAL_LAMBERTIAN:
|
||||
return lambertian_scatter((const Lambertian *)material, r, record,
|
||||
attenuation, scattered);
|
||||
return lambertian_scatter(&material->lambertian, r, record, attenuation,
|
||||
scattered);
|
||||
case MATERIAL_METAL:
|
||||
return metal_scatter((const Metal *)material, r, record, attenuation,
|
||||
scattered);
|
||||
return metal_scatter(&material->metal, r, record, attenuation, scattered);
|
||||
case MATERIAL_DIELECTRIC:
|
||||
return dielectric_scatter((const Dielectric *)material, r, record,
|
||||
attenuation, scattered);
|
||||
return dielectric_scatter(&material->dielectric, r, record, attenuation,
|
||||
scattered);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Lambertian *lambertian_create(Color albedo, Arena *arena) {
|
||||
Lambertian *lambertian = arena_alloc(arena, sizeof(Lambertian));
|
||||
lambertian->type = MATERIAL_LAMBERTIAN;
|
||||
lambertian->albedo = albedo;
|
||||
return lambertian;
|
||||
Material *material_create_lambertian(Color albedo, Arena *arena) {
|
||||
Material *result = arena_alloc(arena, sizeof(Material));
|
||||
result->type = MATERIAL_LAMBERTIAN;
|
||||
result->lambertian.albedo = albedo;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool lambertian_scatter(const Lambertian *lambertian, Ray r,
|
||||
@ -46,12 +45,12 @@ bool lambertian_scatter(const Lambertian *lambertian, Ray r,
|
||||
return true;
|
||||
}
|
||||
|
||||
Metal *metal_create(Color albedo, double fuzziness, Arena *arena) {
|
||||
Metal *metal = arena_alloc(arena, sizeof(Metal));
|
||||
metal->type = MATERIAL_METAL;
|
||||
metal->albedo = albedo;
|
||||
metal->fuzziness = fuzziness;
|
||||
return metal;
|
||||
Material *material_create_metal(Color albedo, double fuzziness, Arena *arena) {
|
||||
Material *result = arena_alloc(arena, sizeof(Material));
|
||||
result->type = MATERIAL_METAL;
|
||||
result->metal.albedo = albedo;
|
||||
result->metal.fuzziness = fuzziness;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool metal_scatter(const Metal *metal, Ray r, const struct HitRecord *record,
|
||||
@ -68,11 +67,11 @@ bool metal_scatter(const Metal *metal, Ray r, const struct HitRecord *record,
|
||||
return vec3_dot(scattered->direction, record->normal) > 0;
|
||||
}
|
||||
|
||||
Dielectric *dielectric_create(double eta, Arena *arena) {
|
||||
Dielectric *dielectric = arena_alloc(arena, sizeof(Dielectric));
|
||||
dielectric->type = MATERIAL_DIELECTRIC;
|
||||
dielectric->eta = eta;
|
||||
return dielectric;
|
||||
Material *material_create_dielectric(double eta, Arena *arena) {
|
||||
Material *result = arena_alloc(arena, sizeof(Material));
|
||||
result->type = MATERIAL_DIELECTRIC;
|
||||
result->dielectric.eta = eta;
|
||||
return result;
|
||||
}
|
||||
|
||||
static double schlick_reflectance(double cosine, double eta) {
|
||||
|
||||
40
material.h
40
material.h
@ -15,40 +15,42 @@ typedef enum MaterialType {
|
||||
MATERIAL_DIELECTRIC,
|
||||
} MaterialType;
|
||||
|
||||
typedef struct Lambertian {
|
||||
Color albedo;
|
||||
} Lambertian;
|
||||
|
||||
typedef struct Metal {
|
||||
Color albedo;
|
||||
double fuzziness;
|
||||
} Metal;
|
||||
|
||||
typedef struct Dielectric {
|
||||
double eta;
|
||||
} Dielectric;
|
||||
|
||||
typedef struct Material {
|
||||
MaterialType type;
|
||||
union {
|
||||
Lambertian lambertian;
|
||||
Metal metal;
|
||||
Dielectric dielectric;
|
||||
};
|
||||
} Material;
|
||||
|
||||
bool material_scatter(const Material *material, Ray r,
|
||||
const struct HitRecord *record, Color *attenuation,
|
||||
Ray *scattered);
|
||||
|
||||
typedef struct Lambertian {
|
||||
MaterialType type;
|
||||
Color albedo;
|
||||
} Lambertian;
|
||||
|
||||
Lambertian *lambertian_create(Color albedo, Arena *arena);
|
||||
Material *material_create_lambertian(Color albedo, Arena *arena);
|
||||
bool lambertian_scatter(const Lambertian *lambertian, Ray r,
|
||||
const struct HitRecord *record, Color *attenuation,
|
||||
Ray *scattered);
|
||||
|
||||
typedef struct Metal {
|
||||
MaterialType type;
|
||||
Color albedo;
|
||||
double fuzziness;
|
||||
} Metal;
|
||||
|
||||
Metal *metal_create(Color albedo, double fuzziness, Arena *arena);
|
||||
Material *material_create_metal(Color albedo, double fuzziness, Arena *arena);
|
||||
bool metal_scatter(const Metal *metal, Ray r, const struct HitRecord *record,
|
||||
Color *attenuation, Ray *scattered);
|
||||
|
||||
typedef struct Dielectric {
|
||||
MaterialType type;
|
||||
double eta;
|
||||
} Dielectric;
|
||||
|
||||
Dielectric *dielectric_create(double eta, Arena *arena);
|
||||
Material *material_create_dielectric(double eta, Arena *arena);
|
||||
bool dielectric_scatter(const Dielectric *dielectric, Ray r,
|
||||
const struct HitRecord *record, Color *attenuation,
|
||||
Ray *scattered);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user