def out_dir(indir, n, mat): u = ti.Vector([1.0, 0.0, 0.0]) if mat == mat_lambertian: if abs(n[1]) < 1 - eps: u = ti.normalized(ti.cross(n, ti.Vector([0.0, 1.0, 0.0]))) v = ti.cross(n, u) phi = 2 * math.pi * ti.random() ay = ti.sqrt(ti.random()) ax = ti.sqrt(1 - ay**2) u = ax * (ti.cos(phi) * u + ti.sin(phi) * v) + ay * n elif mat == mat_metal: u = reflect(indir, n) else: # glass cos = ti.dot(indir, n) ni_over_nt = refr_idx outn = n if cos > 0.0: outn = -n cos = refr_idx * cos else: ni_over_nt = 1.0 / refr_idx cos = -cos has_refr, refr_dir = refract(indir, outn, ni_over_nt) refl_prob = 1.0 if has_refr: refl_prob = schlick(cos, refr_idx) if ti.random() < refl_prob: u = reflect(indir, n) else: u = refr_dir return ti.normalized(u)
def out_dir(n): u = ti.Vector([1.0, 0.0, 0.0]) if abs(n[1]) < 1 - eps: u = ti.normalized(ti.cross(n, ti.Vector([0.0, 1.0, 0.0]))) v = ti.cross(n, u) phi = 2 * math.pi * ti.random() ay = ti.sqrt(ti.random()) ax = ti.sqrt(1 - ay**2) return ax * (ti.cos(phi) * u + ti.sin(phi) * v) + ay * n
def sample_brdf(normal): # cosine hemisphere sampling # first, uniformly sample on a disk (r, theta) r, theta = 0.0, 0.0 sx = ti.random() * 2.0 - 1.0 sy = ti.random() * 2.0 - 1.0 if sx >= -sy: if sx > sy: # first region r = sx div = abs(sy / r) if sy > 0.0: theta = div else: theta = 7.0 + div else: # second region r = sy div = abs(sx / r) if sx > 0.0: theta = 1.0 + sx / r else: theta = 2.0 + sx / r else: if sx <= sy: # third region r = -sx div = abs(sy / r) if sy > 0.0: theta = 3.0 + div else: theta = 4.0 + div else: # fourth region r = -sy div = abs(sx / r) if sx < 0.0: theta = 5.0 + div else: theta = 6.0 + div # Malley's method u = ti.Vector([1.0, 0.0, 0.0]) if abs(normal[1]) < 1 - eps: u = ti.cross(normal, ti.Vector([0.0, 1.0, 0.0])) v = ti.cross(normal, u) theta = theta * math.pi * 0.25 costt, sintt = ti.cos(theta), ti.sin(theta) xy = (u * costt + v * sintt) * r zlen = ti.sqrt(max(0.0, 1.0 - xy.dot(xy))) return xy + zlen * normal
def voxelize_triangles(self, num_triangles: ti.i32, triangles: ti.ext_arr()): for i in range(num_triangles): jitter_scale = ti.cast(0, self.precision) if ti.static(self.precision is ti.f32): jitter_scale = 1e-4 else: jitter_scale = 1e-8 # We jitter the vertices to prevent voxel samples from lying precicely at triangle edges jitter = ti.Vector([-0.057616723909439505, -0.25608986292614977, 0.06716309129743714]) * jitter_scale a = ti.Vector([triangles[i, 0], triangles[i, 1], triangles[i, 2]]) + jitter b = ti.Vector([triangles[i, 3], triangles[i, 4], triangles[i, 5]]) + jitter c = ti.Vector([triangles[i, 6], triangles[i, 7], triangles[i, 8]]) + jitter bound_min = ti.Vector.zero(self.precision, 3) bound_max = ti.Vector.zero(self.precision, 3) for k in ti.static(range(3)): bound_min[k] = min(a[k], b[k], c[k]) bound_max[k] = max(a[k], b[k], c[k]) p_min = int(ti.floor(bound_min[0] * self.inv_dx)) p_max = int(ti.floor(bound_max[0] * self.inv_dx)) + 1 p_min = max(self.padding, p_min) p_max = min(self.res[0] - self.padding, p_max) q_min = int(ti.floor(bound_min[1] * self.inv_dx)) q_max = int(ti.floor(bound_max[1] * self.inv_dx)) + 1 q_min = max(self.padding, q_min) q_max = min(self.res[1] - self.padding, q_max) normal = ti.normalized(ti.cross(b - a, c - a)) if abs(normal[2]) < 1e-10: continue a_proj = ti.Vector([a[0], a[1]]) b_proj = ti.Vector([b[0], b[1]]) c_proj = ti.Vector([c[0], c[1]]) for p in range(p_min, p_max): for q in range(q_min, q_max): pos2d = ti.Vector([(p + 0.5) * self.dx, (q + 0.5) * self.dx]) if inside_ccw(pos2d, a_proj, b_proj, c_proj) or inside_ccw(pos2d, a_proj, c_proj, b_proj): base_voxel = ti.Vector([pos2d[0], pos2d[1], 0]) height = int( -ti.dot(normal, base_voxel - a) / normal[2] * self.inv_dx + 0.5) height = min(height, self.res[1] - self.padding) inc = 0 if normal[2] > 0: inc = 1 else: inc = -1 self.fill(p, q, height, inc)
def update_v(self, px, py, fx, fy, dt): self.velocity += ti.Vector([fx, fy]) / self.mass * dt self.angular += ti.cross(ti.Vector([px - self.centroid.x, py - self.centroid.y]), ti.Vector([fx, fy])) / self.I * dt
def paint(t: ti.f32): fin = ti.Vector([0.0, 0.0, 0.0]) # Parallized over all pixels intensity = 0.0 for i in range(n * 16): #this is parallilized for j in range(n * 9): for x in range(3): uv = ti.Vector([((i / (16 * n)) - 0.5) * (2), (j / (9 * n)) - 0.5]) starting_y = 17.0 ending_y = 5.0 motion_y = -t lookat_starting_y = 17.0 lookat_ending_y = 5.0 # motion_y = 0 ro = ti.Vector([5.0, starting_y, 1.0]) lookat = ti.Vector([5.0, lookat_starting_y, 6.0]) if starting_y + motion_y > ending_y: ro = ti.Vector([5.0, starting_y + motion_y, 1.0]) lookat = ti.Vector( [5.0, lookat_starting_y + motion_y, 6.0]) else: ro = ti.Vector([5.0, ending_y, 1.0]) lookat = ti.Vector([5.0, lookat_ending_y, 6.0]) zoom = 1.0 forward = ti.normalized(lookat - ro) right = ti.cross(ti.Vector([0.0, 1.0, 0.0]), forward) up = ti.cross(forward, right) center = ro + forward * zoom intersection = center + uv[0] * right + uv[1] * up rd = ti.normalized(intersection - ro) d, no, intersection_object, clouddO, cloud_intersection, clouddO2, cloud_intersection2, clouddO3, cloud_intersection3, sdf, sdf_inter = rayCast( ro, rd, t, frameTimeBlur * x) p = ro + rd * d light, normal = GetLight(p, t, intersection_object, no, frameTimeBlur * x, rd) if x == 0: sdf_p = ro + rd * sdf sdf_light, normal_sdf = GetLight(sdf_p, t, sdf_inter, no, frameTimeBlur * x, rd) # if (intersection_object == CAPSULE): # rd2 = reflect(rd, normal) # d2, no2, intersection_object2 = rayCast_reflection(ro + normal*.003, rd2, t+(0.03*0), 0.03*0) # p += rd2*d2 # light2, normal2 = GetLight(p, t, intersection_object2, no2, frameTimeBlur*x, rd2) # sdf_light += light2*0.30 pixels[i, j] = ti.Vector( [sdf_light[0], sdf_light[1], sdf_light[2], 1.0]) #color alpha = 0.8 alpha1 = 0.4 alpha2 = 0.2 if intersection_object == PARTICLES: if x == 0: #doing pixel = pixels + ... to add the particle color value on top of the background pixels[i, j] = pixels[i, j] * alpha + ti.Vector([ light[0], light[1], light[2], 1.0 / (1.0 - alpha) ]) * (1.0 - alpha) if x == 1: pixels[i, j] = pixels[i, j] * alpha1 + ti.Vector([ light[0], light[1], light[2], 1.0 / (1.0 - alpha1) ]) * (1.0 - alpha1) if x == 2: pixels[i, j] = pixels[i, j] * alpha2 + ti.Vector([ light[0], light[1], light[2], 1.0 / (1.0 - alpha2) ]) * (1.0 - alpha2) if x == 2: if cloud_intersection == 1: p_cloud = ro + rd * clouddO light_cloud, normal_cloud = GetLight( p_cloud, t, CLOUD, no, 0, rd) pixels[i, j] = pixels[i, j] + ti.Vector([ light_cloud[0] * 0.30, light_cloud[1] * 0.30, light_cloud[2] * 0.30, 1.0 ]) if cloud_intersection3 == 1: p_cloud3 = ro + rd * clouddO3 light_cloud3, normal_cloud3 = GetLight( p_cloud3, t, CLOUD3, no, 0, rd) pixels[i, j] = pixels[i, j] + ti.Vector([ light_cloud3[0] * 0.30, light_cloud3[1] * 0.30, light_cloud3[2] * 0.30, 1.0 ]) if cloud_intersection2 == 1: p_cloud2 = ro + rd * clouddO2 light_cloud2, normal_cloud2 = GetLight( p_cloud2, t, CLOUD2, no, 0, rd) pixels[i, j] = pixels[i, j] + ti.Vector([ light_cloud2[0] * 0.30, light_cloud2[1] * 0.30, light_cloud2[2] * 0.30, 1.0 ])
def DistLine(ro, rd, p): c = ti.cross(p - ro, rd) l_c = length(c) l_rd = length(rd) return l_c / l_rd