WUT_Computer_Science/sightpy/ray.py
JZduns ee46879048
Statistics (#6)
* ray tracing statistics

* ray counter

* photonmapping ray counter

* rays change

* newline fix

---------

Co-authored-by: Jakub <01149663@pw.edu.pl>
2025-01-19 17:52:23 +01:00

114 lines
4.3 KiB
Python

from .utils.constants import *
from .utils.vector3 import vec3, extract, rgb
import numpy as np
from functools import reduce as reduce
RAYS = 0
PRIMARY_RAYS = 0
class Ray:
"""Info of the ray and the media it's travelling"""
def __init__(self,origin, dir, depth, n, reflections, transmissions, diffuse_reflections):
self.origin = origin # the point where the ray comes from
self.dir = dir # direction of the ray
self.depth = depth # ray_depth is the number of the refrections + transmissions/refractions, starting at zero for camera rays
self.n = n # ray_n is the index of refraction of the media in which the ray is travelling
# Instead of defining a index of refraction (n) for each wavelenght (computationally expensive) we aproximate defining the index of refraction
# using a vec3 for red = 630 nm, green 555 nm, blue 475 nm, the most sensitive wavelenghts of human eye.
# Index a refraction is a complex number.
# The real part is involved in how much light is reflected and model refraction direction via Snell Law.
# The imaginary part of n is involved in how much light is reflected and absorbed. For non-transparent materials like metals is usually between (0.1j,3j)
# and for transparent materials like glass is usually between (0.j , 1e-7j)
self.reflections = reflections #reflections is the number of the refrections, starting at zero for camera rays
self.transmissions = transmissions #transmissions is the number of the transmissions/refractions, starting at zero for camera rays
self.diffuse_reflections = diffuse_reflections #reflections is the number of the refrections, starting at zero for camera rays
global RAYS
RAYS += 1
if self.reflections == 0 and self.transmissions == 0 and self.diffuse_reflections == 0:
global PRIMARY_RAYS
PRIMARY_RAYS += 1
def extract(self,hit_check):
return Ray(self.origin.extract(hit_check), self.dir.extract(hit_check), self.depth, self.n.extract(hit_check), self.reflections, self.transmissions,self.diffuse_reflections)
class Hit:
"""Info of the ray-surface intersection"""
def __init__(self, distance, orientation, material, collider,surface):
self.distance = distance
self.orientation = orientation
self.material = material
self.collider = collider
self.surface = surface
self.u = None
self.v = None
self.N = None
self.point = None
def get_uv(self):
if self.u is None: #this is for prevent multiple computations of u,v
self.u, self.v = self.collider.assigned_primitive.get_uv(self)
return self.u, self.v
def get_normal(self):
if self.N is None: #this is for prevent multiple computations of normal
self.N = self.collider.get_N(self)
return self.N
def get_raycolor(ray, scene):
inters = [s.intersect(ray.origin, ray.dir) for s in scene.collider_list]
distances, hit_orientation = zip(*inters)
# get the shortest distance collision
nearest = reduce(np.minimum, distances)
color = rgb(0., 0., 0.)
for (coll, dis , orient) in zip(scene.collider_list, distances, hit_orientation):
hit_check = (nearest != FARAWAY) & (dis == nearest)
if np.any(hit_check):
material = coll.assigned_primitive.material
hit_info = Hit(extract(hit_check,dis) , extract(hit_check,orient), material, coll, coll.assigned_primitive)
cc = material.get_color(scene, ray.extract(hit_check), hit_info)
color += cc.place(hit_check)
return color
def get_distances(ray, scene): #Used for debugging ray-surface collisions. Return a grey map of objects distances.
inters = [s.intersect(ray.origin, ray.dir) for s in scene.collider_list]
distances, hit_orientation = zip(*inters)
# get the shortest distance collision
nearest = reduce(np.minimum, distances)
max_r_distance = 10
r_distance = np.where(nearest <= max_r_distance, nearest, max_r_distance)
norm_r_distance = r_distance/max_r_distance
return rgb(norm_r_distance, norm_r_distance, norm_r_distance)
def get_rays():
return RAYS, PRIMARY_RAYS