-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathSphere.cpp
101 lines (91 loc) · 3.03 KB
/
Sphere.cpp
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
#include "Sphere.h"
Sphere::Sphere(){
//unit ball at the center
}
Sphere::Sphere( Vector3f center, float radius, Material* material ) : Object3D(material){
this->center = center;
this->radius = radius;
}
Sphere::~Sphere(){
}
bool Sphere::intersect( const Ray& r, Hit& h, float tmin){
// Precompute variables
float radius2 = pow(radius, 2);
Vector3f d = r.getDirection(); // Ray Direction
Vector3f e = r.getOrigin();
Vector3f eMinusC = e - center;
float dTimesD = Vector3f::dot(d, d);
// Calculate the discriminate
float discriminate = (
pow(
Vector3f::dot(
r.getDirection(),
eMinusC
)
, 2
)
-
(
dTimesD * (
Vector3f::dot(eMinusC, eMinusC)
- radius2
)
)
);
// Check for possible intersection
// If discriminate is negative then there is no intersection
// and it is not necessary to continue calculations
if (discriminate >= 0)
{
float sqrtDiscr = sqrt(discriminate);
// Complete Quadratic Equation calculation
// Get Left-Hand-Side
float lhs = -1*Vector3f::dot(d, eMinusC);
// Calculate for positive and negative discriminate
float pos = (lhs + sqrtDiscr) / dTimesD;
float neg = (lhs - sqrtDiscr) / dTimesD;
// Check if either positive or negative discriminate solutions
// are greater than tmin
if (pos > tmin || neg > tmin) {
// Positive discriminate solution
if (pos > tmin )
{
// Check if new t is better/closer than old t
if (pos < h.getT())
{
// Closer than current t in hit
Vector3f p = r.pointAtParameter(pos);
Vector3f normal = (2*(p - center)).normalized();
h.set(pos, material, normal);
h.setTexCoord(texCoord(p));
}
}
// Negative discriminate solution
if (neg > tmin) {
// Check if new t is better/closer than old t
if (neg < h.getT()) {
// Closer than current t in hit
Vector3f p = r.pointAtParameter(neg);
Vector3f normal = (2*(p - center)).normalized();
h.set(neg, material, normal);
h.setTexCoord(texCoord(p));
}
}
return true;
}
}
// No intersection
return false;
}
Vector2f Sphere::texCoord(Vector3f p) {
float theta = acos((p.z() - center.z())/radius);
float phi = atan2(p.y() - center.y(), p.x() - center.x());
if (phi < 0) {
phi = phi + 2 * M_PI;
}
float u = phi / (2 * M_PI);
float v = (M_PI-theta)/M_PI;
Vector2f tc = Vector2f(u,v);
// tc.print();
return tc;
}