-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvolume_convex.h
More file actions
94 lines (69 loc) · 2.53 KB
/
volume_convex.h
File metadata and controls
94 lines (69 loc) · 2.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#ifndef RAYTRACINGWEEKEND_VOLUME_CONVEX_H
#define RAYTRACINGWEEKEND_VOLUME_CONVEX_H
#include "hittable.h"
#include "primitives/materials/mat_volumetric.h"
class volume_convex : public hittable
{
public:
hittable_type get_type() const override { return hittable_type::volume; }
/// UI Constructor
volume_convex(std::string name, shared_ptr<hittable> obj, shared_ptr<material> mat) : volume_convex(obj, 1.0, mat)
{
this->name = name;
}
volume_convex(shared_ptr<hittable> boundary, double density, const shared_ptr<material> material)
: boundary(boundary), neg_inv_density(-1/density), phase_function(material)
{
name = boundary->name + " (Volume)";
}
bool hit(const ray& r, interval ray_t, hit_record& rec) const override
{
hit_record rec1, rec2;
if (!boundary->hit(r, interval::universe, rec1))
return false;
if (!boundary->hit(r, interval(rec1.t+0.0001, infinity), rec2))
return false;
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_in_boundary = (rec2.t - rec1.t) * ray_length;
auto hit_distance = neg_inv_density * std::log(rand_double()); // dampening
if (hit_distance > distance_in_boundary)
return false;
rec.t = rec1.t + hit_distance / ray_length;
rec.p = r.at(rec.t);
rec.normal = vec3::right; // arbitrary
rec.front_face = true; // arbitrary
rec.mat = phase_function;
// std::wclog << "WTF";
return true;
}
aabb bounding_box() const override { return boundary->bounding_box(); }
bool inspector_ui(viewport& _viewport, scene& _scene) override
{
bool modified = false;
modified += hittable_slot("Shape", boundary, *this, _scene);
ImGui::SetItemTooltip("The volume will be in this object\'s shape. Please do not make circular references.");
double density = -1.0 / neg_inv_density;
if (ImGui::DragDouble("Density", &density, 0.1, 0.0001, 200) && density > 0.0001)
{
modified = true;
neg_inv_density = -1/density;
}
ImGui::SetItemTooltip("The density of the object is set here, not in materials. Density must be over 0.");
modified += material_slot("Material", phase_function, _scene);
ImGui::SetItemTooltip("Using a non-volumetric material will lead to unexpected results.");
if (modified)
_viewport.mark_scene_dirty();
return modified;
}
private:
shared_ptr<hittable> boundary;
double neg_inv_density;
shared_ptr<material> phase_function;
};
#endif //RAYTRACINGWEEKEND_VOLUME_CONVEX_H