File size: 2,064 Bytes
f92c150
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
class Collider:
	def __init__(self, pos1 = (None,) * 3, pos2 = (None,) * 3):
		# pos1: position of the collider vertex in the -X, -Y, -Z direction
		# pos2: position of the collider vertex in the +X, +Y, +Z direction

		self.x1, self.y1, self.z1 = pos1
		self.x2, self.y2, self.z2 = pos2
	
	def __add__(self, pos):
		x, y, z = pos

		return Collider(
			(self.x1 + x, self.y1 + y, self.z1 + z),
			(self.x2 + x, self.y2 + y, self.z2 + z)
		)
	
	def __and__(self, collider):
		x = min(self.x2, collider.x2) - max(self.x1, collider.x1)
		y = min(self.y2, collider.y2) - max(self.y1, collider.y1)
		z = min(self.z2, collider.z2) - max(self.z1, collider.z1)

		return x > 0 and y > 0 and z > 0
	
	def collide(self, collider, velocity):
		# self: the dynamic collider, which moves
		# collider: the static collider, which stays put

		no_collision = 1, None

		# find entry & exit times for each axis

		vx, vy, vz = velocity

		time = lambda x, y: x / y if y else float('-' * (x > 0) + "inf")

		x_entry = time(collider.x1 - self.x2 if vx > 0 else collider.x2 - self.x1, vx)
		x_exit  = time(collider.x2 - self.x1 if vx > 0 else collider.x1 - self.x2, vx)

		y_entry = time(collider.y1 - self.y2 if vy > 0 else collider.y2 - self.y1, vy)
		y_exit  = time(collider.y2 - self.y1 if vy > 0 else collider.y1 - self.y2, vy)

		z_entry = time(collider.z1 - self.z2 if vz > 0 else collider.z2 - self.z1, vz)
		z_exit  = time(collider.z2 - self.z1 if vz > 0 else collider.z1 - self.z2, vz)

		# make sure we actually got a collision

		if x_entry < 0 and y_entry < 0 and z_entry < 0:
			return no_collision

		if x_entry > 1 or y_entry > 1 or z_entry > 1:
			return no_collision
		
		# on which axis did we collide first?

		entry = max(x_entry, y_entry, z_entry)
		exit_ = min(x_exit,  y_exit,  z_exit )

		if entry > exit_:
			return no_collision
		
		# find normal of surface we collided with

		nx = (0, -1 if vx > 0 else 1)[entry == x_entry]
		ny = (0, -1 if vy > 0 else 1)[entry == y_entry]
		nz = (0, -1 if vz > 0 else 1)[entry == z_entry]

		return entry, (nx, ny, nz)