-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathintersect.py
More file actions
81 lines (58 loc) · 1.89 KB
/
intersect.py
File metadata and controls
81 lines (58 loc) · 1.89 KB
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
from operator import attrgetter
from collections import namedtuple
class intersect:
"""
The intersect class stores data about a single intersection
between a surface and a ray.
"""
def __init__(self, t, obj):
self.t = t
self.object = obj
def prepare_computations(self, ray):
"""
Create a namedtuple for storing precomputed values relating
to the intersection.
"""
Comps = namedtuple('Comps', 't object point eyev normalv inside over_point reflectv')
point = ray.position(self.t)
normalv = self.object.normal_at(point)
inside = normalv.dot(-ray.direction) < 0
if inside:
normalv = -normalv
EPSILON = 0.00001
over_point = point + normalv * EPSILON
reflectv = ray.direction.reflect(normalv)
comps = Comps(
# Retain the intersection's properties for convenience
t=self.t,
object=self.object,
# Store some useful values
point=point,
eyev=-ray.direction,
normalv=normalv,
inside=inside,
over_point=over_point,
reflectv=reflectv
)
return comps
class intersects:
def __init__(self, *_intersects):
self._intersects = sorted(_intersects, key=attrgetter('t'))
def __iter__(self):
return iter(self._intersects)
def __bool__(self):
return bool(self.count)
@property
def count(self):
return len(self._intersects)
@property
def hit(self):
"""
Returns the lowest non-negative intersect in intersects, or None
"""
# todo: should it be > 0 or >= 0?
positive_t = [i for i in self if i.t > 0]
if positive_t:
return min(positive_t, key=attrgetter('t'))
def __getitem__(self, key):
return self._intersects[key]