-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsphere.h
108 lines (86 loc) · 3.2 KB
/
sphere.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
#ifndef __SPHERE_H__
#define __SPHERE_H__
#include "globals.h"
#include "hittable.h"
#include "hittablevector.h"
class sphere : public hittable {
public:
sphere() {}
sphere(vec3f c0, vec3f c1,
float time0, float time1,
float r, shared_ptr<material> m) : center0(c0), center1(c1),
t0(time0), t1(time1),
radius(r), matPtr(m) {};
virtual bool hit(const ray &ray, float tMin, float tMax, hitRecord &record) const override;
virtual bool boundingBox(float time0, float time1, aabb& outputBox) const override;
virtual void calcTangentBasis(const vec3f& normal, vec3f& tangent, vec3f& bitangent) const override;
virtual int populateVector(shared_ptr<class hittableVector> hittableVector) const override {
int index = hittableVector->objects.size();
hittableVector->objects.emplace_back();
//hittableVector->objects[index].positions[0] = vec4f(999.0f, 999.0f, 999.0f, 1.0f);
hittableVector->objects[index].UVs[0] = vec4f(0, 0, 255.0f, 255.0f);
return index;
}
vec3f center(float time) const;
private:
static void getSphereUV(const vec3f& p, vec2f& uv) {
auto theta = acosf(-p(1));
auto phi = atan2f(-p(2), p(0)) + pi;
uv(0) = phi / (2.0f * pi);
uv(1) = theta / pi;
}
public:
vec3f center0, center1;
float t0, t1;
float radius;
shared_ptr<material> matPtr;
};
vec3f sphere::center(float time) const {
if (center0 != center1)
return center0 + ((time - t0) / (t1 - t0)) * (center1 - center0);
else
return center0;
}
bool sphere::hit(const ray &ray, float tMin, float tMax, hitRecord &record) const {
vec3f oc = ray.o - center(ray.time);
auto a = lengthSquared(ray.dir);
auto halfB = oc.dot(ray.dir);
auto c = lengthSquared(oc) - radius * radius;
auto discriminant = halfB * halfB - a * c;
if (discriminant < 0.0f)
return false;
auto sqrtd = sqrtf(discriminant);
// find nearest root in range
auto root = (-halfB - sqrtd) / a;
if (root < tMin || root > tMax) {
root = (-halfB + sqrtd) / a;
if (root < tMin || root > tMax)
return false;
}
record.t = root;
record.p = ray.at(record.t);
vec3f outwardNormal = unitVector(record.p - center(ray.time));// / radius;
record.setFaceNormal(ray, outwardNormal);
getSphereUV(outwardNormal, record.uv);
record.matPtr = matPtr;
calcTangentBasis(outwardNormal, record.tangent, record.bitangent);
return true;
}
bool sphere::boundingBox(float time0, float time1, aabb& outputBox) const {
aabb box0(center(time0) - vec3f(radius, radius, radius),
center(time0) + vec3f(radius, radius, radius));
aabb box1(center(time1) - vec3f(radius, radius, radius),
center(time1) + vec3f(radius, radius, radius));
outputBox = surroundingBox(box0, box1);
return true;
}
void sphere::calcTangentBasis(const vec3f& normal, vec3f& tangent, vec3f& bitangent) const {
vec3f b;
if (1.0f - (fabsf(normal.dot(vec3f::UnitY()))) < epsilon)
b = -vec3f::UnitZ();
else
b = vec3f::UnitY();
tangent = unitVector(b.cross(normal));
bitangent = unitVector(normal.cross(tangent));
}
#endif