-
Notifications
You must be signed in to change notification settings - Fork 0
/
Sphere.cc
66 lines (59 loc) · 1.71 KB
/
Sphere.cc
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
#include "Sphere.h"
#include "BoundingBox.h"
#include "RenderContext.h"
#include "Material.h"
#include "HitRecord.h"
#include "Point.h"
#include "Ray.h"
#include "Vector.h"
#include <math.h>
#include <map>
Sphere::Sphere(Material* material, Animation<Point>& center, Animation<double> radius)
: Primitive(material), center(center), radius(radius)
{
}
void Sphere::preprocess(int maxTime)
{
center.preprocess(maxTime);
radius.preprocess(maxTime);
if(inv_radius.isEmpty())
{
for(int i = 0; i <= maxTime; i++)
inv_radius.addFrame(i, 1./radius(i));
}
inv_radius.preprocess(maxTime);
matl->preprocess(maxTime);
}
void Sphere::getBounds(BoundingBox& bbox, const RenderContext& context) const
{
double time = context.time();
double radiusT = radius(time);
Point centerT = center(time);
Vector diag(radiusT, radiusT, radiusT);
bbox.extend(centerT+diag);
bbox.extend(centerT-diag);
}
void Sphere::intersect(HitRecord& hit, const RenderContext& context, const Ray& ray) const
{
double time = context.time();
double radiusT = radius(time);
Vector O(ray.origin()-center(time));
const Vector& V(ray.direction());
double b = Dot(O, V);
double c = Dot(O, O)-radiusT*radiusT;
double disc = b*b-c;
if(disc > 0){
double sdisc = sqrt(disc);
double root1 = (-b - sdisc);
if(!hit.hit(root1, this, matl)){
double root2 = (-b + sdisc);
hit.hit(root2, this, matl);
}
}
}
void Sphere::normal(Vector& normal, const RenderContext& context, const Point& hitpos,
const Ray& ray, const HitRecord& hit) const
{
double time = context.time();
normal = (hitpos-center(time))*inv_radius(time);
}