-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathround_box.h
125 lines (106 loc) · 3.46 KB
/
round_box.h
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#pragma once
#include <xlocmon>
#include "hittable.h"
namespace Tmpl8 {
class round_box : public hittable
{
public:
round_box() = default;
round_box(vec3 p_size, float p_rad, std::shared_ptr<material> p_mat_ptr): rad(p_rad), mat_ptr(p_mat_ptr) { center = p_size; }
bool hit(const ray& r, float t_min, float t_max, hit_record& rec) const override;
bool boundingBox(float t0, float t1, aabb& box) const override;
private:
float rad;
std::shared_ptr<material> mat_ptr;
};
inline bool round_box::hit(const ray& r, float t_min, float t_max, hit_record& rec) const
{
rec.ellipsoidSize = 1.f;
// bounding box
vec3 m = vec3(1.0) / r.direction();
vec3 n = m * r.origin();
vec3 k = abs3(m) * (center + rad);
vec3 t1 = -n - k;
vec3 t2 = -n + k;
float tN = ffmax(ffmax(t1.x, t1.y), t1.z);
float tF = ffmin(ffmin(t2.x, t2.y), t2.z);
if (tN > tF || tF < 0.0) return false;
float t = tN;
// convert to first octant
vec3 pos = r.origin() + t * r.direction();
vec3 s = sgnv3(pos);
r.origin() *= s;
r.direction() *= s;
pos *= s;
// faces
pos -= center;
pos = ffmax(pos, vec3(pos.y, pos.z, pos.x));
if (ffmin(ffmin(pos.x, pos.y), pos.z) < 0.0) return false;
// some precomputation
vec3 oc = r.origin() - center;
vec3 dd = r.direction() * r.direction();
vec3 oo = oc * oc;
vec3 od = oc * r.direction();
float ra2 = rad * rad;
t = infinity;
// corner
{
float b = od.x + od.y + od.z;
float c = oo.x + oo.y + oo.z - ra2;
float h = b * b - c;
if (h > 0.0) t = -b - sqrt(h);
}
// edge X
{
float a = dd.y + dd.z;
float b = od.y + od.z;
float c = oo.y + oo.z - ra2;
float h = b * b - a * c;
if (h > 0.0)
{
h = (-b - sqrt(h)) / a;
if (h > 0.0 && h < t && abs(r.origin().x + r.direction().x * h) < center.x) t = h;
}
}
// edge Y
{
float a = dd.z + dd.x;
float b = od.z + od.x;
float c = oo.z + oo.x - ra2;
float h = b * b - a * c;
if (h > 0.0)
{
h = (-b - sqrt(h)) / a;
if (h > 0.0 && h < t && abs(r.origin().y + r.direction().y * h) < center.y) t = h;
}
}
// edge Z
{
float a = dd.x + dd.y;
float b = od.x + od.y;
float c = oo.x + oo.y - ra2;
float h = b * b - a * c;
if (h > 0.0)
{
h = (-b - sqrt(h)) / a;
if (h > 0.0 && h < t && abs(r.origin().z + r.direction().z * h) < center.z) t = h;
}
}
if (t > 1e19) t = -1.0;
rec.t = t;
rec.p = r.origin() + rec.t * r.direction();
const vec3 outward_normal = sgnv3(pos) * normalize(abs3(pos) - center);
rec.normal = outward_normal;
rec.set_face_normal(r, outward_normal);
//get_sphere_uv(outward_normal, rec.u, rec.v);
rec.mat_ptr = mat_ptr;
return t;
}
inline bool round_box::boundingBox(float t0, float t1, aabb& box) const
{
box = aabb(
center - vec3(rad, rad, rad),
center + vec3(rad, rad, rad));
return true;
}
}