blob: 23fb10a5eb7746e8443b4f339ac064c4aeaf6d2c [file] [log] [blame]
#ifndef CONSTANT_MEDIUM_H
#define CONSTANT_MEDIUM_H
//==============================================================================================
// Originally written in 2016 by Peter Shirley <ptrshrl@gmail.com>
//
// To the extent possible under law, the author(s) have dedicated all copyright
// and related and neighboring rights to this software to the public domain
// worldwide. This software is distributed without any warranty.
//
// You should have received a copy (see file COPYING.txt) of the CC0 Public
// Domain Dedication along with this software. If not, see
// <http://creativecommons.org/publicdomain/zero/1.0/>.
//
// The original source code is from
// https://github.com/RayTracing/raytracing.github.io/tree/release/src/TheNextWeek
//
// Changes to the original code follow the following license.
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//==============================================================================================
#include "rtweekend.h"
#include "hittable.h"
#include "material.h"
#include "texture.h"
class constant_medium : public hittable {
public:
__host__ __device__ constant_medium(SharedPtr<hittable> b, double d,
SharedPtr<rt_texture> a)
: boundary(b), neg_inv_density(-1 / d),
phase_function(makeShared<isotropic>(a)) {}
__host__ __device__ constant_medium(SharedPtr<hittable> b, double d,
color c)
: boundary(b), neg_inv_density(-1 / d),
phase_function(makeShared<isotropic>(c)) {}
__host__ __device__ bool hit(const ray &r, interval ray_t, hit_record &rec,
unsigned &rng) const override {
// Print occasional samples when debugging. To enable, set enableDebug
// true.
#if DEBUG
const bool enableDebug = false;
const bool debugging = enableDebug && random_double(rng) < 0.00001;
#endif
hit_record rec1, rec2;
if (!boundary->hit(r, interval::universe, rec1, rng))
return false;
if (!boundary->hit(r, interval(rec1.t + 0.0001, infinity), rec2, rng))
return false;
#if DEBUG
if (debugging)
std::clog << "\nt_min=" << rec1.t << ", t_max=" << rec2.t << '\n';
#endif
if (rec1.t < ray_t.min)
rec1.t = ray_t.min;
if (rec2.t > ray_t.max)
rec2.t = ray_t.max;
if (rec1.t >= rec2.t)
return false;
if (rec1.t < 0)
rec1.t = 0;
auto ray_length = r.direction().length();
auto distance_inside_boundary = (rec2.t - rec1.t) * ray_length;
auto hit_distance = neg_inv_density * log(random_double(rng));
if (hit_distance > distance_inside_boundary)
return false;
rec.t = rec1.t + hit_distance / ray_length;
rec.p = r.at(rec.t);
#if DEBUG
if (debugging) {
std::clog << "hit_distance = " << hit_distance << '\n'
<< "rec.t = " << rec.t << '\n'
<< "rec.p = " << rec.p << '\n';
}
#endif
rec.normal = vec3(1, 0, 0); // arbitrary
rec.front_face = true; // also arbitrary
rec.mat = phase_function;
return true;
}
__host__ __device__ aabb bounding_box() const override {
return boundary->bounding_box();
}
private:
SharedPtr<hittable> boundary;
double neg_inv_density;
SharedPtr<material> phase_function;
};
#endif