#include "../marcher.h" #include "../images/images.h" #include static Image* current_image; static Scene* current_scene; static Camera* current_camera; Color march_ray(Point origin, Point direction, Scene* scene); void camera_iter_callback(Point direction, int x, int y); Scene scene_new(unsigned int width, unsigned int height, int obj_count) { Scene scene; scene.height = height; scene.width = width; scene.max_steps = 32; scene.threshold = 0.02; scene.object_count = 0; scene.objects = malloc(obj_count * sizeof(SceneObject)); scene.allocated_space = obj_count; scene.background = color_new(0,0,0); return scene; } void scene_add_obj(Scene* scene, SceneObject object) { if (scene->object_count >= scene->allocated_space) return; // limit reached // TODO realloc scene->objects[scene->object_count] = object; // link containing scene scene->objects[scene->object_count].scene = scene; scene->object_count++; } // render out the scene with threads // creates a shared image, so destroy with image_destroy_shared then free struct with free_shared_memory Image* render_scene(Scene *scene, Camera *camera, unsigned int threads) { current_image = malloc(sizeof(Image)); current_scene = scene; current_camera= camera; // initialize shared pixel buffer image_new_shared(scene->width, scene->height, current_image); // iterate over the rays camera_iterate_rays_const_dist(*camera, scene->width, scene->height, threads, camera_iter_callback); // or camera_iterate_rays_const_angle for lense distortion (this might not work correctly tho) // return the drawn image return current_image; } // march the ray, set the color. repeated for each direction generated by the camera void camera_iter_callback(Point direction, int x, int y) { Color c = march_ray(current_camera->location, direction, current_scene); image_set_px_c(*current_image, x, y, c); } Color march_ray(Point origin, Point direction, Scene* scene) { // some local variables Point pos = origin; double closest_encounter = DBL_MAX; double dist = closest_encounter; // the closest object we have SceneObject* closest_obj = scene->objects; // get steps, threshold from scene int steps = scene->max_steps; double threshold = scene->threshold; // as long as we did not max out steps, or got very close to an object while (steps > 0 && dist > threshold) { dist = 100; // find distance to closest object for(int i = 0; i < scene->object_count; i++) { // get pointer to scene obj SceneObject* obj = scene->objects + i; double curr_dist = scene->objects[i].distance(pos, obj); // if we are close if (curr_dist < dist) { dist = curr_dist; closest_obj = obj; } } // write down our closest encounter if (dist < closest_encounter) closest_encounter = dist; // scale direction vector to distance, then add it to our position Point step_vector = pt_scale(direction, dist); pt_add(&pos, step_vector); // one step taken... steps--; } // check for a hit if (dist <= threshold) { // a hit! double f = (steps / (double) scene->max_steps); f = f * f * f * f; Color c = closest_obj->get_color(pos, direction, closest_obj); return color_mix(c, color_new(0,0,0), f); } else { // a miss :( // this should be 0! return scene->background; } } void scene_destroy(Scene scene) { for (int i = 0; i < scene.object_count; i++) { // free args memory free(scene.objects[i].args); } free(scene.objects); }