mirror of
https://github.com/kuhyx/WUT_Computer_Science.git
synced 2026-07-04 22:43:11 +02:00
* works for cornell now, will be extended to import others * works for all scenes * can load environments and blur them * minor cleanup * Example commands added to README.md
104 lines
4.0 KiB
Python
104 lines
4.0 KiB
Python
from .utils.constants import *
|
|
from .utils.vector3 import vec3, extract, rgb
|
|
import numpy as np
|
|
from functools import reduce as reduce
|
|
|
|
|
|
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
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
|
|
|