def crear_rayo_aleatorio(ray, punto, pared):
    """Crea un rayo aleatorio a partir del rabote

    :param ray: El rayo actual
    :param punto: El punto de interseccion entre el rayo y la pared
    :param pared: La pared de interseccion
    :return: Un rayo con el origen en el punto de rebote
    """
    # Verificar especularidad
    if pared.especularidad:
        return crear_rayo_especular(ray, punto, pared)
    if pared.horizontal:
        if ray.origen.y > punto.y:
            # pared inferior
            angulo = math.radians(random.uniform(5, 175))
            return Ray(Point(punto.x, punto.y + 2), angulo)
        else:
            # pared superior
            angulo = math.radians(random.uniform(-175, -5))
            return Ray(Point(punto.x, punto.y - 2), angulo)
    else:
        if ray.origen.x < punto.x:
            # pared derecha
            angulo = math.radians(random.uniform(-270, -90))
            return Ray(Point(punto.x - 2, punto.y), angulo)
        else:
            # pared izquierda
            angulo = math.radians(random.uniform(-85, 85))
            return Ray(Point(punto.x + 2, punto.y), angulo)
    def get_ray_intersection_point(self, dist):
        """Calcular el punto de interseccion entre el rayo y el segmento

        :param dist: La distancia entre ambos puntos
        :return: El punto de interseccion entre el rayo y el segmento
        """
        pt = Point()
        pt.x = self.origen.x + self.direccion.x * dist
        pt.y = self.origen.y + self.direccion.y * dist
        return pt
示例#3
0
def vector_from_angle(angle):
    """Retorna un vector a partir de un angulo

    :param angle: El angulo que se desea utilizar
    :return: El nuevo vector
    """
    return normalize(Point(1 * math.cos(angle), 1 * math.sin(angle)))
示例#4
0
def render():
    """Renderiza la imagen con iluminacion global

    :return:
    """
    s = time.time()
    for i in range(515):

        for j in range(515):
            # Obtener punto en la imagen
            image_point = Point(i, j)
            pixel_color = 0
            for light_source in light_sources:
                # Calcular direccion a la
                direccion = light_source - image_point
                light_distance = get_vector_length(direccion)
                # Verificar con interseccion en la pared
                free = True
                for wall in segments:
                    if wall.transparencia:
                        continue
                    # Revisar interseccion
                    distancia_interseccion = ray_segment_intersect(
                        image_point, normalize(direccion), wall.point1, wall.point2)
                    # Verificar colision
                    if distancia_interseccion != -1.0 and distancia_interseccion < light_distance:
                        free = False
                        break
                # Verificar si no hay colision
                if free:
                    # Calcular intensidad
                    intensidad = (1.2 - (light_distance / 600)) ** 2
                    # Obtener color del pixel
                    valores = (imagen[int(image_point.y)]
                               [int(image_point.x)])[:3]
                    # Combinar color, fuente de luz y color de la luz
                    valores = valores * intensidad * light_color

                    # Agregar todas las fuentes de luz
                    pixel_color += valores
                # Promedia pixel y asignar valor
                canvas[int(image_point.x)][int(image_point.y)] = pixel_color // len(light_sources)
            # Realizar Monte Carlo Path tracing
            rayos_efectivos = 0
            for samples in range(0, number_samples):
                # Iniciar rayos
                initial_ray = Ray(image_point, random.uniform(0, 360))
                # Iluminacion indirecta
                incoming_color = trace_path(initial_ray)
                # Verificar si se obtiene un color
                if not isinstance(incoming_color, type(np.array([0, 0, 0]))):
                    continue
                pixel_color += incoming_color
                rayos_efectivos += 1
            #Promediar color final
            canvas[int(image_point.x)][int(image_point.y)] = pixel_color // (len(light_sources) + rayos_efectivos)
    e = time.time()
    print(e - s)
def crear_rayo_especular(ray, punto, pared):
    """Crea un rayo especular

    :param ray: El rayo saliente
    :param punto: El punto de interseccion del rayo
    :param pared: La pared de interseccion
    :return: El rayo especular
    """
    # Obtener angulo
    angulo = np.rad2deg(
        get_angle_between(Segment(ray.origen, punto, False, False), pared))
    if pared.horizontal:
        # Por arriba
        if ray.origen.y > punto.y:
            # Por la derecha
            if ray.origen.x > punto.x:
                return Ray(Point(punto.x, punto.y + 2),
                           math.radians(2 * (90 - angulo) + angulo))
            else:
                return Ray(Point(punto.x, punto.y + 2), math.radians(-angulo))
            # Por la derecha
        else:
            # Por abajo
            if ray.origen.x > punto.x:
                return Ray(Point(punto.x, punto.y - 2),
                           math.radians(180 - angulo))
            else:

                return Ray(Point(punto.x, punto.y - 2),
                           math.radians(-(180 + (angulo - 180))))
    else:
        # Vertical y por la derecha
        if ray.origen.x > punto.x:
            # Por arriba
            if ray.origen.y > punto.y:
                return Ray(Point(punto.x + 2, punto.y),
                           math.radians(-(90 - angulo)))
            # Por abajo
            else:
                print(angulo)
                return Ray(Point(punto.x + 2, punto.y),
                           math.radians(-(90 - angulo)))
        else:
            # Por abajo
            if ray.origen.y > punto.y:
                return Ray(Point(punto.x - 2, punto.y),
                           math.radians(angulo + 90))
            # Por arriba
            else:
                return Ray(Point(punto.x - 2, punto.y),
                           math.radians(angulo + 90))
    def ray_segment_intersect(self, segmento):
        """Calcula la distancia entre el punto de interseccion y el origen del rayo

        :param segmento: El segmento que se desea verificar
        :return: La distancia entre ambos puntos
        """
        # calculate vectors
        v1 = self.origen - segmento.point1
        v2 = segmento.point2 - segmento.point1
        v3 = Point(-self.direccion.y, self.direccion.x)
        dot = v2.dot(v3)
        if abs(dot) < 0.000001:
            return -1.0
        t1 = v2.cross(v1) / dot
        t2 = v1.dot(v3) / dot
        if t1 >= 0.0 and (t2 >= 0.0 and t2 <= 1.0):
            return t1
        return -1.0
示例#7
0
def ray_segment_intersect(origen, direccion, point1, point2):
    """Determina la interseccion entre un rayo y un segmento

    :param origen: El origen del rayo
    :param direccion: La direccion del rayo
    :param point1: El primer punto del rayo
    :param point2: El segundo punto del rayo
    :return: La distancia entre el origen del rayo y el segmento
    """
    # Calcular vectores
    v1 = origen - point1
    v2 = point2 - point1
    v3 = Point(-direccion.y, direccion.x)

    dot = v2.dot(v3)
    if abs(dot) < 0.000001:
        return -1.0
    t1 = v2.cross(v1) / dot
    t2 = v1.dot(v3) / dot
    if t1 >= 0.0 and (t2 >= 0.0 and t2 <= 1.0):
        return t1
    return -1.0
示例#8
0
    border = 50
    pygame.init()
    screen = pygame.display.set_mode(
        (WIDTH + (2 * border), HEIGHT + (2 * border)))
    # Segmentos y fuentes
    pygame.display.set_caption("Path Tracer")
    done = False
    clock = pygame.time.Clock()
    # Init random
    random.seed()
    blank = Image.new("RGB", (516, 516), (0, 0, 0))
    canvas = np.array(blank)
    # Load image file
    img_file = Image.open("assets/EscenaProgra.png")
    imagen = np.array(img_file)
    light_sources = [Point(47, 303), Point(47, 142), Point(475, 76)]
    # Color de la luz
    light_color = np.array([1, 1, 0.75])
    segments = [
        # Segment(Point(180, 135), Point(215, 135), True, False),
        # Segment(Point(285, 135), Point(320, 135), True, False),
        # Segment(Point(320, 135), Point(320, 280), False, False),
        # Segment(Point(320, 320), Point(320, 355), False, False),
        # Segment(Point(320, 355), Point(215, 355), True, False),
        # Segment(Point(180, 390), Point(180, 286), False, False),
        # Segment(Point(180, 286), Point(140, 286), True, False,True),
        # Segment(Point(320, 320), Point(360, 320), True, False),
        # Segment(Point(180, 250), Point(180, 135), False, False),


        #Escena rpgmaker