Un rayo pregunta qué objeto ve primero
Un rayo es una recta que sale de la cámara y atraviesa un píxel. Saber dónde toca ese rayo a una esfera permite decidir de qué color pintar el píxel.
Esta idea se llama trazado de rayos, y empieza con una ecuación de segundo grado.
Al final de esta lección
Nota
Puedo calcular dónde un rayo toca una esfera.
Palabras clave
| Palabra | Qué significa |
|---|---|
| Rayo | una recta con un origen y una dirección |
| Parámetro t | cuánto avanzas por el rayo desde su origen |
| Esfera | los puntos que están a un radio de un centro |
| Discriminante | el número que dice cuántas veces corta el rayo |
| Impacto | el punto donde el rayo toca la esfera |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Un rayo es un origen y una dirección
Un rayo tiene un punto de salida o y una dirección d. Sus puntos son o + t * d, con t mayor o igual que 0.
Con t = 0 estás en el origen. Con t = 1 has avanzado una dirección entera. Con t = 2, dos. Cuanto mayor es t, más lejos estás.
Ejemplo resuelto: un rayo hacia delante
| t | Punto del rayo (origen 0, 0, 0 y dirección 0, 0, 1) | Distancia al centro (0, 0, 5) |
|---|---|---|
| 0 | (0, 0, 0) | 5 |
| 2 | (0, 0, 2) | 3 |
| 4 | (0, 0, 4) | 1, justo el radio: es el impacto |
| 5 | (0, 0, 5) | 0, el centro |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
El impacto sale de una ecuación cuadrática
Quieres los t para los que o + t * d está a un radio del centro. Sea oc = o - centro. Calcula tres números: a = d · d, b = oc · d y k = oc · oc - radio * radio.
El punto · es el producto escalar: multiplicas coordenada a coordenada y sumas. El discriminante es b * b - a * k, y los impactos son (-b - raíz) / a y (-b + raíz) / a.
Ejemplo resuelto: tres rayos, tres resultados
| Caso | a | b | k | Discriminante | Qué pasa |
|---|---|---|---|---|---|
| Hacia una esfera de centro (0, 0, 5) | 1 | -5 | 24 | 1 | Da en t = 4 y en t = 6 |
| Hacia una esfera de centro (0, 1, 5) | 1 | -5 | 25 | 0 | La roza en t = 5 |
| Hacia arriba, dirección (0, 1, 0) | 1 | 0 | 24 | -24 | No da: es negativo |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Calcula el discriminante de tres rayos
docker exec jupyter python3 -c "d = lambda o, v, c, r: (lambda oc: sum(p * q for p, q in zip(oc, v)) ** 2 - sum(q * q for q in v) * (sum(p * p for p in oc) - r * r))(tuple(a - b for a, b in zip(o, c))); print(d((0, 0, 0), (0, 0, 1), (0, 0, 5), 1), d((0, 0, 0), (0, 0, 1), (0, 1, 5), 1), d((0, 0, 0), (0, 1, 0), (0, 0, 5), 1))"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Qué dicen los tres discriminantes
Imprime 1 0 -24, los tres de la tabla. El primero es positivo: el rayo atraviesa la esfera y la corta en dos puntos. El segundo es 0: la roza en uno solo.
El tercero es negativo y no tiene raíz cuadrada real: el rayo pasa de largo. Basta mirar el signo para saber si hay impacto.
Calcula el primer impacto
# Un rayo desde (0, 0, 0) hacia delante y una esfera de centro (0, 0, 5) y radio 1.
import math
origen = (0, 0, 0)
direccion = (0, 0, 1)
centro = (0, 0, 5)
radio = 1
oc = (origen[0] - centro[0], origen[1] - centro[1], origen[2] - centro[2])
a = direccion[0] * direccion[0] + direccion[1] * direccion[1] + direccion[2] * direccion[2]
b = oc[0] * direccion[0] + oc[1] * direccion[1] + oc[2] * direccion[2]
k = oc[0] * oc[0] + oc[1] * oc[1] + oc[2] * oc[2] - radio * radio
disc = b * b - a * k
print("discriminante:", disc)
if disc >= 0:
print("primer impacto en t =", (-b - math.sqrt(disc)) / a)
# Cambia centro a (0, 1, 5): el rayo solo roza la esfera.
Solo vale un t positivo
De los dos impactos te interesa el menor que sea positivo: el primero que ve la cámara. Si los dos son negativos, la esfera está detrás del origen y no se ve.
Si el origen está dentro de la esfera, uno es negativo y el otro positivo. Entonces vale el positivo.
Un error muy común
Advertencia
Mucha gente cree que un discriminante positivo siempre significa que la esfera se ve. No basta: con la esfera detrás de la cámara el discriminante también es positivo, pero los dos t son negativos. Comprueba siempre el signo de t.
Dibuja la silueta de una esfera con rayos
docker exec jupyter python3 -c "print('\n'.join(''.join('#' if 2400 ** 2 - (x * x + y * y + 1600) * 3276 > 0 else '.' for x in range(-13, 14)) for y in range(-12, 13, 2)))"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Cómo se lee la silueta de la esfera
La cámara está en el origen. La esfera tiene su centro en (0, 0, 60) y radio 18. Cada rayo lleva la dirección (x, y, 40). Cada # es un píxel cuyo rayo tiene discriminante positivo.
Imprime 13 filas. La primera y la última tienen 7 # y las tres del medio tienen 25. Se ve un círculo: la silueta de la esfera.
Para ir más lejos: cambia el radio
Ejecuta de nuevo el comando de la silueta y cambia el 3276 por 2000. Ese número es la distancia al centro al cuadrado menos el radio al cuadrado: 3600 menos 324.
Con 2000 el radio de la esfera sale de 40 y no de 18. Verás que la silueta llena toda la ventana, sin ningún punto. Calcula antes por qué.