98 lines
2.5 KiB
C
98 lines
2.5 KiB
C
#pragma once
|
|
|
|
#include "lights.h"
|
|
#include "spheres.h"
|
|
#include "transformations.h"
|
|
#include "intersections_shapes.h"
|
|
#include "rays.h"
|
|
#include "materials.h"
|
|
#include "lighting.h"
|
|
|
|
#define WORLD_MAX_OBJECTS 128
|
|
|
|
struct world {
|
|
struct light light;
|
|
int object_count;
|
|
struct shape objects[WORLD_MAX_OBJECTS];
|
|
};
|
|
|
|
inline static struct world world()
|
|
{
|
|
return (struct world){
|
|
.light = (struct light){{{{0}}}},
|
|
.object_count = 0,
|
|
};
|
|
}
|
|
|
|
inline static struct world world_default()
|
|
{
|
|
struct shape s1 = sphere();
|
|
s1.material.color = color(0.8f, 1.0f, 0.6f);
|
|
s1.material.diffuse = 0.7f;
|
|
s1.material.specular = 0.2f;
|
|
struct shape s2 = sphere();
|
|
s2.transform = scaling(0.5f, 0.5f, 0.5f);
|
|
|
|
return (struct world){
|
|
.light = point_light(point(-10.0f, 10.0f, -10.0f), color(1.0f, 1.0f, 1.0f)),
|
|
.object_count = 2,
|
|
.objects = { s1, s2 }
|
|
};
|
|
}
|
|
|
|
inline static void world_intersect(struct world * world, struct ray ray, struct intersections * intersections)
|
|
{
|
|
intersections->count = 0;
|
|
for (int i = 0; i < world->object_count; i++) {
|
|
intersect(&world->objects[i], ray, intersections);
|
|
}
|
|
intersections_sort(intersections);
|
|
}
|
|
|
|
inline static bool world_is_shadowed(struct world * world, struct tuple point)
|
|
{
|
|
struct tuple v = tuple_sub(world->light.position, point);
|
|
|
|
float distance = tuple_magnitude(v);
|
|
struct tuple direction = tuple_normalize(v);
|
|
|
|
struct ray r = ray(point, direction);
|
|
struct intersections xs;
|
|
world_intersect(world, r, &xs);
|
|
|
|
struct intersection * h = hit(&xs);
|
|
if (h != NULL && h->t < distance) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
inline static struct tuple world_shade_hit(struct world * world, struct computations * computations)
|
|
{
|
|
bool is_shadowed = world_is_shadowed(world, computations->over_point);
|
|
|
|
struct tuple color = lighting(computations->object->material,
|
|
computations->object,
|
|
world->light,
|
|
computations->point,
|
|
computations->eyev,
|
|
computations->normalv,
|
|
is_shadowed);
|
|
return color;
|
|
}
|
|
|
|
inline static struct tuple world_color_at(struct world * world, struct ray ray)
|
|
{
|
|
struct intersections xs;
|
|
world_intersect(world, ray, &xs);
|
|
struct intersection * i = hit(&xs);
|
|
if (i != NULL) {
|
|
struct computations computations = prepare_computations(*i, ray);
|
|
struct tuple color = world_shade_hit(world, &computations);
|
|
return color;
|
|
} else {
|
|
return color(0.0f, 0.0f, 0.0f);
|
|
}
|
|
}
|