-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSphere.cpp
110 lines (96 loc) · 2.95 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
102
103
104
105
106
107
108
109
110
/*
Sphere.cpp
*/
#include <iostream>
#include <math.h>
#include "Sphere.h"
typedef glm::dmat3 mat3;
typedef glm::dmat4 mat4;
typedef glm::dvec3 vec3;
typedef glm::dvec4 vec4;
Sphere::Sphere(double x, double y, double z, double radius)
{
this->posit = vec3(x,y,z);
this->radius = radius;
this->isMoving = false;
}
Sphere::~Sphere()
{
}
void Sphere::setEndPosition(double x, double y, double z)
{
if (x != this->posit.x || y != this->posit.y || z != this->posit.z) {
this->endposit = vec3(x,y,z);
this->isMoving = true;
}
}
int Sphere::getIntersectionPoint(const Ray& ray, Intersection& intersection, const double dt)
{
vec3 currentPosition;
if (isMoving) {
currentPosition = this->posit*(1.0 - dt) + this->endposit*(dt);
} else {
currentPosition = this->posit;
}
vec3 dir = vec3(ray.direction[0],ray.direction[1],ray.direction[2]);
vec3 pos = vec3(ray.position[0],ray.position[1],ray.position[2]);
double A = glm::dot(dir,dir);
double B = 2 * glm::dot(dir, (pos - currentPosition));
double C = glm::dot(pos - currentPosition, pos - currentPosition) - radius*radius;
double disc = B*B - 4*A*C;
int ret = 1;
if (disc < 0) {
return 0;
} else {
double q0 = (-B + sqrt(disc)) / (2*A);
double q1 = (-B - sqrt(disc)) / (2*A);
double t;
if (q0 > 0 && q1 > 0) {
t = q0 >= q1 ? q1 : q0; // pick the minimum
} else if (q0 == q1) {
return 0;
} else {
t = q0 > 0 ? q0 : q1; // pick the positive one
ret = -1; // inside sphere!
}
vec3 position = pos + dir*t;
vec3 normal = glm::normalize(position - currentPosition);
intersection.position = vec4(position,1);
intersection.normal = vec4(normal,0);
intersection.t = t;
}
return ret;
}
bool Sphere::doesRayIntersect(const Ray& ray, const double tmax, const double dt)
{
vec3 currentPosition;
if (isMoving) {
currentPosition = this->posit*(1.0 - dt) + this->endposit*(dt);
} else {
currentPosition = this->posit;
}
vec3 dir = vec3(ray.direction[0],ray.direction[1],ray.direction[2]);
vec3 pos = vec3(ray.position[0],ray.position[1],ray.position[2]);
double A = glm::dot(dir,dir);
double B = 2 * glm::dot(dir, (pos - currentPosition));
double C = glm::dot(pos - currentPosition, pos - currentPosition) - radius*radius;
double disc = B*B - 4*A*C;
double t;
if (disc < 0) {
return false;
} else {
double q0 = (-B + sqrt(disc)) / (2*A);
double q1 = (-B - sqrt(disc)) / (2*A);
if (q0 > 0 && q1 > 0) {
t = q0 >= q1 ? q1 : q0; // pick the minimum
} else if (q0 == q1) {
return false;
} else {
t = q0 > 0 ? q0 : q1; // pick the positive one
}
if (t >= tmax || t < 0.0) {
return false;
}
}
return true;
}