-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhit.py
More file actions
124 lines (94 loc) · 5.33 KB
/
hit.py
File metadata and controls
124 lines (94 loc) · 5.33 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
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import math
HIT_RANGE = 3
class Hit_ray:
def __init__(self, world, rotation, starting_position):
self.world = world
# ray extending from camera is q
# Make unit direction vector u, <cos(Rx)*cos(Ry), sin(Ry), sin(Rx)*cos(Ry)>
# unit vectors have a length of 1, so we can change length to translate points different distances
self.vector = (
math.cos(rotation[0]) * math.cos(rotation[1]),
math.sin(rotation[1]),
math.sin(rotation[0]) * math.cos(rotation[1])
)
# Position of tracing point P
self.position = list(starting_position)
# get block surrounding our raycast point; works because blocks are 1 unit wide, centered on integer coords
self.block = tuple(map(lambda x: int(round(x)), self.position))
self.distance = 0
def check(self, hit_callback, distance, current_block, next_block):
if self.world.get_block_number(next_block):
hit_callback(current_block, next_block)
return True
self.position = list(map(lambda x: self.position[x] + self.vector[x] * distance, range(3)))
self.block = next_block
self.distance += distance
return False
def step(self, hit_callback):
block_x, block_y, block_z = self.block
# takes point position and subtracts block from it
#L = <Px-Bx, Py-By, Pz-Bz>
local_position = list(map(lambda x: self.position[x] - self.block[x], range(3)))
# disregard all negative faces, instead flip around origin in center of block
# takes absolute value of vector, so we don't have to worry about sign for intersection
sign = [1, 1, 1] # 1=pos, -1=neg
absolute_vector = list(self.vector)
for component in range(3):
if self.vector[component] < 0:
sign[component] = -1
absolute_vector[component] = -absolute_vector[component]
local_position[component] = -local_position[component]
lx, ly, lz = local_position
vx, vy, vz = absolute_vector
# absolute vector v = <|Ux|,|Uy|,|Uz|>
# Nearest intersection to L between r and our three faces
# r = Parametric, (1/vector x)(x - point x) and so on
# r = (x-Lx/vx) = (y-Ly/vy) = (z-Lz/vz)
# F = faces, Fx, Fy, Fz
# Intersection of Face F with r, is plane of F (p) intersection with r
# x = 1/2 because plane is axis aligned, 1/2 to either side
#System: x=1/2 and (x-Lx/vx) = (y-Ly/vy) = (z-Lz/vz)
# so x = 1/2
# so y = (1/2-Lx/vx)vy + Ly
# so y = (1/2-Lx/vx)vz + Lz
# if vx = 0, r and Fx = p are parallel, not perpendicular, and so don't intersect,
# since vector is on yz plane
if vx:
x = 0.5
y = (((0.5 - lx) / vx) * vy) + ly
z = (((0.5 - lx) / vx) * vz) + lz
# now we know where in space the intersection with the plane is
# check if intersection is situated inside our face
# (x coordinate may be valid, but is it out of the y or z bounds?)
if (y >= -0.5 and y <= 0.5 and z >= -0.5 and z <= 0.5):
# take magnitude of vector, which is distance between two points
# distance between point of intersection and L, so we know how much to move P along q
distance = math.sqrt((x-lx) ** 2 + (y-ly) ** 2 + (z-lz) ** 2)
# distance, block, adjacent block either left or right depending on sign of face
return self.check(hit_callback, distance, self.block, (block_x + sign[0], block_y, block_z))
if vy:
x = (((0.5 - ly) / vy) * vx) + lx
y = 0.5
z = (((0.5 - ly) / vy) * vz) + lz
# now we know where in space the intersection with the plane is
# check if intersection is situated inside our face
# (y coordinate may be valid, but is it out of the x or z bounds?)
if (x >= -0.5 and x <= 0.5 and z >= -0.5 and z <= 0.5):
# take magnitude of vector, which is distance between two points
# distance between point of intersection and L, so we know how much to move P along q
distance = math.sqrt((x-lx) ** 2 + (y-ly) ** 2 + (z-lz) ** 2)
# distance, block, adjacent block either up or down depending on sign of face
return self.check(hit_callback, distance, self.block, (block_x, block_y + sign[1], block_z))
if vz:
x = (((0.5 - lz) / vz) * vx) + lx
y = (((0.5 - lz) / vz) * vy) + ly
z = 0.5
# now we know where in space the intersection with the plane is
# check if intersection is situated inside our face
# (z coordinate may be valid, but is it out of the x or y bounds?)
if (x >= -0.5 and x <= 0.5 and y >= -0.5 and y <= 0.5):
# take magnitude of vector, which is distance between two points
# distance between point of intersection and L, so we know how much to move P along q
distance = math.sqrt((x-lx) ** 2 + (y-ly) ** 2 + (z-lz) ** 2)
# distance, block, adjacent block either up or down depending on sign of face
return self.check(hit_callback, distance, self.block, (block_x, block_y, block_z + sign[2]))