forked from thiago-souzaf/python-ray-tracing
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsphere.py
More file actions
54 lines (48 loc) · 2.28 KB
/
Copy pathsphere.py
File metadata and controls
54 lines (48 loc) · 2.28 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
import math
from point import Point
class Sphere:
def __init__(self, center: "Point", radius, color):
self.center = center
self.radius = radius
self.color = color
def __str__(self):
return f"Sphere: {self.center} {self.radius} {self.color}"
def intersect(self, ray):
"""Intersect Method"""
# Intersecção de raios com esferas é dado por
# equação de esfera: (x - cx)** 2 + (y - cy)**2 + (z - cz)**2 = r**2
# equação paramétrica do raio: R(t) = O + t * D
# Substituindo a equação do raio na esfera:
# (ox + t*dx - cx)** 2 + (oy + t*dy - cy)**2 + (oz + t*dz - cz)**2 = r**2
# Equação quadrática:
# A*t**2 + B*t + C = 0
# A = dx**2 + dy**2 + dz**2
# B = 2 ((ox - cx)*dx + (oy - cy)*dy + (oz - cz)*dz )
# C = (ox - cx)**2 + (oy - cy)**2 + (oz - cz)**2 - r**2
oc = ray.origin - self.center # (ox - cx, oy - cy, oz - cz)
a = ray.direction.dot_product(ray.direction) # dx**2 + dy**2 + dz**2
b = 2 * (oc.dot_product(ray.direction)) # 2 ((ox - cx)*dx + (oy - cy)*dy + (oz - cz)*dz )
c = oc.dot_product(oc) - self.radius * self.radius # (ox - cx)**2 + (oy - cy)**2 + (oz - cz)**2 - r**2
discriminant = (b * b) - (4 * a * c) # delta = B**2 - 4AC
epsilon = 1e-6 # Tolerância para comparação de ponto flutuante
# Pontos de intersecção
# Nesse caso não há intersecção entre o raio e a esfera
if discriminant < 0:
return None
# Nesse caso o raio tangencia a esfera
elif discriminant < epsilon:
t = -b / (2 * a) # -B/2A
return t
else:
# Se delta > 0 o raio intersecta a esfera em dois ponto
t1 = (-b + math.sqrt(discriminant)) / (2.0 * a) # (-B + raiz(delta))/2A
t2 = (-b - math.sqrt(discriminant)) / (2.0 * a) # (-B - raiz(delta))/2A
# Escolher o menor t positivo para retornar ao Ray Tracing
if t1 > 0 and t2 > 0:
return min(t1,t2) # Retorna o menor valor entre t1 e t2
elif t1 > 0: #
return t1
elif t2 > 0:
return t2
else:
return None # Ambas as intersecções estão atrás da câmera