def randomLessThan(throttle: ti.template()): if ti.static(isinstance(throttle, (int, float))): if ti.static(throttle == 1): return True if ti.static(throttle == 0): return False return ti.random() < throttle
def Reset(): for i in range(n_particles): x[i] = [ (ti.random() - 0.5) * init_particle_size_x + init_particle_center_x, (ti.random() - 0.5) * init_particle_size_y + init_particle_center_y, ] v[i] = [0, 0] F[i] = ti.Matrix([[1, 0], [0, 1]]) Jp[i] = 1 C[i] = ti.Matrix.zero(float, 2, 2) gravity[None] = [0, -9.81] capsule_translation[None] = [init_capsule_center_x, init_capsule_center_y] capsule_trans_vel[None] = [0, init_capsule_vel_y] capsule_rotation[None] = [0.0]
def test_periodic(a, burn_in, target_orbit_length, max_orbit_length): x_nought = ti.random(real) x_curr = x_nought # allow the initial condition to settle into an orbit for idx in range(burn_in): x_curr = a * x_curr * (1 - x_curr) # save first point in the possible orbit x_final = x_curr period_length = 0 period_found = False # print("x_final", x_final) for idx in range(max_orbit_length): x_curr = a * x_curr * (1 - x_curr) if not period_found: period_length += 1 if (x_curr == x_final): period_found = True # if (period_length >= target_orbit_length): # print("Period of length", period_length, "found - a:", a) if not period_found: period_length = 0 return period_length
def sample_ray_dir(indir, normal, hit_pos, mat): u = ti.Vector([0.0, 0.0, 0.0]) pdf = 1.0 if mat == mat_lambertian: u = sample_brdf(normal) pdf = max(eps, compute_brdf_pdf(normal, u)) elif mat == mat_specular: u = reflect(indir, normal) elif mat == mat_glass: cos = indir.dot(normal) ni_over_nt = refr_idx outn = normal if cos > 0.0: outn = -normal 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, normal) else: u = refr_dir return u.normalized(), pdf
def reset(mode: ti.i32): # enforce initial velocity field for i in range(n_particles): x[i] = [ti.random() * 0.6 + 0.2, ti.random() * 0.6 + 0.2] if mode == 0: v[i] = [1, 0] elif mode == 1: v[i] = [x[i][1] - 0.5, 0.5 - x[i][0]] elif mode == 2: v[i] = [0, x[i][0] - 0.5] elif mode == 3: v[i] = [0, x[i][1] - 0.5] else: # Incompressibility is not ensured. Cannot do biaxial?? if x[i][1] > 0.75: v[i] = [0, -0.3]
def init_particle(): group_size = n_particle // 3 for i in particle_position: group_id = i // group_size particle_material[i] = group_id particle_position[i] = ( ti.Vector([ti.random(), ti.random()]) * 0.25 + 0.1 + group_id * 0.26) * length particle_velocity[i] = ti.Vector([0.0, -1.0]) particle_F[i] = ti.Matrix([[1, 0], [0, 1]]) particle_J[i] = 1.0
def step(phase: ti.i32): # move for i in position: pos, ang = position[i], heading[i] l = sense(phase, pos, ang - SENSE_ANGLE) c = sense(phase, pos, ang) r = sense(phase, pos, ang + SENSE_ANGLE) if l < c < r: ang += MOVE_ANGLE elif l > c > r: ang -= MOVE_ANGLE elif c < l and c < r: ang += MOVE_ANGLE * (2 * (ti.random() < 0.5) - 1) pos += ti.Vector([ti.cos(ang), ti.sin(ang)]) * MOVE_STEP position[i], heading[i] = pos, ang # deposit for i in position: ipos = position[i].cast(int) % GRID_SIZE grid[phase, ipos] += 1.0 # diffuse for i, j in ti.ndrange(GRID_SIZE, GRID_SIZE): a = 0.0 for di in ti.static(range(-1, 2)): for dj in ti.static(range(-1, 2)): a += grid[phase, (i + di) % GRID_SIZE, (j + dj) % GRID_SIZE] a *= EVAPORATION / 9.0 grid[1 - phase, i, j] = a
def seed_from_voxels(self, material: ti.i32, color: ti.i32, sample_density: ti.i32): for i, j, k in self.voxelizer.voxels: inside = 1 for d in ti.static(range(3)): inside = inside and self.padding <= i and i < self.res[ d] - self.padding if inside and self.voxelizer.voxels[i, j, k] > 0: for l in range(sample_density): x = ti.Vector( [ti.random() + i, ti.random() + j, ti.random() + k]) * self.dx p = ti.atomic_add(self.n_particles[None], 1) self.seed_particle(p, x, material, color, self.source_velocity[None])
def sample(self, dir, N, t, i, j, mat_buf, mat_id): next_dir = ti.Vector([0.0, 0.0, 0.0]) w_out = dir cos_theta_i = w_out.dot(N) ior = UF.get_material_ior(mat_buf, mat_id) eta = ior probability = ti.random() f_or_b = 1.0 R = probability + 1.0 extinction = 1.0 if (cos_theta_i > 0.0): N = -N extinction = ti.exp(-0.1*t) else: cos_theta_i = -cos_theta_i eta = 1.0 /ior next_dir,suc = self.refract(w_out, N, eta) if suc > 0.0: R = self.schlick(cos_theta_i, ior) if (probability < R): next_dir = ts.reflect(w_out, N) else: f_or_b = -1.0 return next_dir, f_or_b*extinction
def fill(): for i in range(n): for j in range(n): v = ti.random(precision) if precision == ti.i32: x[i, j] = (float(v) + float(2**31)) / float(2**32) else: x[i, j] = (float(v) + float(2**63)) / float(2**64)
def create_new_form(): for i in range(particle_width): for j in range(particle_height): b[i, j] = a[i, j] if(ti.random(type) >0.98): b[i, j] = a[i, j]*(-1) normalize(b) new_hamiltonian[None] = Hamiltonian(b)
def radiance(self): outdir = ts.vec3(0.0) clr = ts.vec3(0.0) if ti.random() < self.emission: clr = ts.vec3(self.emission_color) elif ti.random() < self.specular: clr = ts.vec3(self.specular_color) outdir = ts.reflect(self.indir, self.normal) elif ti.random() < self.diffuse: clr = ts.vec3(self.diffuse_color) outdir = ts.randUnit3D() if outdir.dot(self.normal) < 0: outdir = -outdir #s = ti.random() #outdir = ts.vec3(ti.sqrt(1 - s**2) * ts.randUnit2D(), s) #outdir = ti.Matrix.cols([self.tangent, self.bitangent, self.normal]) @ outdir return self.pos, outdir, clr
def init(): up[None] = [0.0, 1.0, 0.0] lookat[None] = [0.0, 0.0, 0.0] fov[None] = math.pi / 3 cam_r[None] = 2.0 cam_theta[None] = math.pi / 4 cam_phi[None] = math.pi / 4 dir_l_theta[None] = math.pi / 4 dir_l_phi[None] = math.pi / 4 for i in range(sphere_num): sphere_origin_list[i] = ti.Vector( [ti.random() * 2 - 1, ti.random() * 2 - 1, ti.random() * 2 - 1]) sphere_radius_list[i] = 0.03 sphere_material_color_list[i] = ti.Vector([1, 1, 1])
def rand_unit_3d(): ''' Uniformly samples a vector on a 3D unit sphere. ''' u = rand_unit_2d() s = ti.random() * 2 - 1 c = ti.sqrt(1 - s**2) return ti.Vector([c * u[0], c * u[1], s])
def init(): vortex[0] = ti.Vector([0, 1]) vortex[1] = ti.Vector([0, -1]) vortex[2] = ti.Vector([0, 0.3]) vortex[3] = ti.Vector([0, -0.3]) vortex[4] = ti.Vector([0, 0.65]) vortex[5] = ti.Vector([0, -0.65]) sign[0] = 1 sign[1] = -1 sign[2] = 1 sign[3] = -1 sign[4] = 1 sign[5] = -1 for i in range(particle_num): particles[i] = ti.Vector([ti.random() * 3 - 1.5, ti.random() - 0.5])
def random_point_in_unit_sphere(self): ret = ti.Vector.zero(ti.f32, n=self.dim) while True: for i in ti.static(range(self.dim)): ret[i] = ti.random(ti.f32) * 2 - 1 if ret.norm_sqr() <= 1: break return ret
def initialize(): for i in range(n_particles): x[i] = [ti.random() * 0.3 + 0.3, ti.random() * 0.3 + 0.25] # x[i] = [ti.random() * 0.6 + 0.2, ti.random() * 0.45 + 0.45 ] material[i] = 0 # 0: fluid, 1: jelly, 2: snow v[i] = ti.Matrix([0, 0]) F[i] = ti.Matrix([[1, 0], [0, 1]]) Jp[i] = 1 for i in range(n_lines): # add horizontal or vertical lines if i == 0: lines1[i] = [0.25, 0.15] lines2[i] = [0.25, 0.5] elif i == 1: lines1[i] = [0.25, 0.15] lines2[i] = [0.75, 0.15] elif i == 2: lines1[i] = [0.75, 0.15] lines2[i] = [0.75, 0.5]
def Def(minval, maxval): ''' Name: random_generator Category: texture Inputs: minval:f maxval:f Output: result:a ''' return lambda pars: minval + ti.random() * (maxval - minval)
def init(): for i in range(particle_width): for j in range(particle_height): a[i, j] = ti.Vector([0.0,ti.random(type)-0.5]) b[i, j] = a[i, j] normalize(a) B[None] = ti.Vector([0.0,magnetic_field]) old_hamiltonian[None] = Hamiltonian(a) Magnitude[None]=M(a)
def color(o, d): rst = ti.Vector([1.0, 1.0, 1.0]) count = 0 while True: if count > 10: break hit, p, n, index = hit_spheres(o, d, 0.001, 1e10) if hit: #命中点是下一条光线的起点 o = p if spheres[index][4] <= 1.0: albedo = ti.Vector( [spheres[index][5], spheres[index][6], spheres[index][7]]) rst = rst * albedo #漫反射 if spheres[index][4] == 0.0: d = unit_vector(n + random_in_unit_sphere()) #镜面反射 elif spheres[index][4] == 1.0: # d = unit_vector(reflect(d, n) + random_in_unit_sphere() * 0.03) d = reflect(d, n) if n.dot(d) < 0: rst = ti.Vector([0.0, 0.0, 0.0]) break #折射 else: outward_n = n #折射率比值 ni_over_nt = spheres[index][5] cosine = 0.0 #从球体内部往外部 if (d.dot(n)) > 0: outward_n = -n cosine = ni_over_nt * d.dot(n) #从球体外部到内部 else: ni_over_nt = 1.0 / ni_over_nt cosine = -d.dot(n) succ, refracted = refract(d, outward_n, ni_over_nt) if succ: #一定概率折射或者反射 reflect_prob = schlick(cosine, spheres[index][5]) if ti.random() < reflect_prob: d = reflect(d, n) else: d = refracted #完全反射 else: d = reflect(d, n) count += 1 else: t = 0.5 * (d[1] + 1.0) skycolor = (1.0 - t) * ti.Vector([1.0, 1.0, 1.0]) + t * ti.Vector( [0.5, 0.7, 1.0]) rst = rst * skycolor break return rst
def init_particles(): for i in range(num_particles): delta = h * 0.8 offs = ti.Vector([(boundary[0] - delta * num_particles_x) * 0.5, boundary[1] * 0.02]) positions[i] = ti.Vector([i % num_particles_x, i // num_particles_x ]) * delta + offs for c in ti.static(range(dim)): velocities[i][c] = (ti.random() - 0.5) * 4 board_states[None] = ti.Vector([boundary[0] - epsilon, -0.0])
def render(): for u, v in color_buffer: aspect_ratio = res[0] / res[1] pos = camera_pos cur_iter = count_var[0] str_x, str_y = (cur_iter / stratify_res), (cur_iter % stratify_res) ray_dir = ti.Vector([ (2 * fov * (u + (str_x + ti.random()) * inv_stratify) / res[1] - fov * aspect_ratio - 1e-5), (2 * fov * (v + (str_y + ti.random()) * inv_stratify) / res[1] - fov - 1e-5), -1.0, ]) ray_dir = ray_dir.normalized() acc_color = ti.Vector([0.0, 0.0, 0.0]) throughput = ti.Vector([1.0, 1.0, 1.0]) depth = 0 while depth < max_ray_depth: closest, hit_normal, hit_color, mat = intersect_scene(pos, ray_dir) if mat == mat_none: break hit_pos = pos + closest * ray_dir hit_light = (mat == mat_light) if hit_light: acc_color += throughput * light_color break elif mat == mat_lambertian: acc_color += throughput * sample_direct_light( hit_pos, hit_normal, hit_color) depth += 1 ray_dir, pdf = sample_ray_dir(ray_dir, hit_normal, hit_pos, mat) pos = hit_pos + 1e-4 * ray_dir if mat == mat_lambertian: throughput *= lambertian_brdf * hit_color * dot_or_zero( hit_normal, ray_dir) / pdf else: throughput *= hit_color color_buffer[u, v] += acc_color count_var[0] = (count_var[0] + 1) % (stratify_res * stratify_res)
def seed_from_voxels(self, material: ti.i32, color: ti.i32, sample_density: ti.i32): for i, j, k in self.voxelizer.voxels: inside = 1 for d in ti.static(range(3)): inside = inside and -self.grid_size // 2 + self.padding <= i and i < self.grid_size // 2 - self.padding if inside and self.voxelizer.voxels[i, j, k] > 0: s = sample_density / self.voxelizer_super_sample**self.dim for l in range(sample_density + 1): if ti.random() + l < s: x = ti.Vector([ ti.random() + i, ti.random() + j, ti.random() + k ]) * (self.dx / self.voxelizer_super_sample ) + self.source_bound[0] p = ti.atomic_add(self.n_particles[None], 1) self.seed_particle(p, x, material, color, self.source_velocity[None])
def seed(self, new_particles: ti.i32, new_material: ti.i32, color: ti.i32): for i in range(self.n_particles[None], self.n_particles[None] + new_particles): self.material[i] = new_material x = ti.Vector.zero(ti.f32, self.dim) for k in ti.static(range(self.dim)): x[k] = self.source_bound[0][k] + ti.random( ) * self.source_bound[1][k] self.seed_particle(i, x, new_material, color, self.source_velocity[None])
def seed(self, num_original_particles: ti.i32, new_particles: ti.i32, new_material: ti.i32): for i in range(num_original_particles, num_original_particles + new_particles): self.material[i] = new_material for k in ti.static(range(self.dim)): self.x[i][k] = self.source_bound[0][k] + ti.random( ) * self.source_bound[1][k] self.v[i] = ti.Vector.zero(ti.f32, self.dim) self.F[i] = ti.Matrix.identity(ti.f32, self.dim) self.Jp[i] = 1
def apply_force(velocities:ti.template(), colors:ti.template(), pre_mouse_pos:ti.ext_arr(), cur_mouse_pos:ti.ext_arr()): p = ti.Vector([cur_mouse_pos[0], cur_mouse_pos[1]]) pre_p = ti.Vector([pre_mouse_pos[0], pre_mouse_pos[1]]) dp = p - pre_p dp = dp / max(1e-5, dp.norm()) color = (ti.Vector([ti.random(), ti.random(), ti.random()]) * 0.7 + ti.Vector([0.1, 0.1, 0.1]) * 0.3) for i, j in velocities: d2 = (ti.Vector([(i+stagger.x)*dx, (j+stagger.y)*dx]) - p).norm_sqr() radius = 0.0001 velocities[i, j] = velocities[i, j] + dp * dt * ti.exp(-d2/radius) * 40 if dp.norm() > 0.5: colors[i, j] = colors[i, j] + ti.exp(-d2 * (4 / (1 / 15)**2)) * color
def init(): vortex[0] = ti.Vector([0, 1]) vortex[1] = ti.Vector([0, -1]) vortex[2] = ti.Vector([0, 0.3]) vortex[3] = ti.Vector([0, -0.3]) vortex[4] = ti.Vector([0, 0.65]) vortex[5] = ti.Vector([0, -0.65]) sign[0] = 1 sign[1] = -1 sign[2] = 1 sign[3] = -1 sign[4] = 1 sign[5] = -1 for i in range(particle_num): x = ti.random() y = ti.random() particles[i] = ti.Vector([x * 3 - 1.5, y - 0.5]) # colors[i] = ti.Vector([x, y, y]) colors[i] = ti.Vector([x + 0.3, y + 0.3, 0.0])
def init_markers(self): self.total_mk[None] = 0 for I in ti.grouped(self.cell_type): if self.cell_type[I] == utils.FLUID: for offset in ti.static( ti.grouped(ti.ndrange(*((0, 2), ) * self.dim))): num = ti.atomic_add(self.total_mk[None], 1) self.p_x[num] = ( I + (offset + [ti.random() for _ in ti.static(range(self.dim))]) / 2) * self.dx
def add_random_particles(angular_velocity: ti.f32): num = ti.static(1) particle_id = alloc_particle() if ti.static(kDim == 2): particle_pos[particle_id] = rand_disk_2d() * 0.2 + 0.5 velocity = (particle_pos[particle_id] - 0.5) * angular_velocity * 250 particle_vel[particle_id] = ti.Vector([-velocity.y, velocity.x]) else: particle_pos[particle_id] = rand_unit_3d() * 0.2 + 0.5 velocity = (ti.Vector( [particle_pos[particle_id].x, particle_pos[particle_id].y]) - 0.5) * angular_velocity * 180 particle_vel[particle_id] = ti.Vector([-velocity.y, velocity.x, 0.0]) particle_mass[particle_id] = 1.5 * ti.random()
def sample_brdf(normal): # cosine hemisphere sampling # Uniformly sample on a disk using concentric sampling(r, theta) # https://www.pbr-book.org/3ed-2018/Monte_Carlo_Integration/2D_Sampling_with_Multidimensional_Transformations#CosineSampleHemisphere r, theta = 0.0, 0.0 sx = ti.random() * 2.0 - 1.0 sy = ti.random() * 2.0 - 1.0 if sx != 0 or sy != 0: if abs(sx) > abs(sy): r = sx theta = np.pi / 4 * (sy / sx) else: r = sy theta = np.pi / 4 * (2 - sx / sy) # Apply Malley's method to project disk to hemisphere u = ti.Vector([1.0, 0.0, 0.0]) if abs(normal[1]) < 1 - eps: u = normal.cross(ti.Vector([0.0, 1.0, 0.0])) v = normal.cross(u) costt, sintt = ti.cos(theta), ti.sin(theta) xy = (u * costt + v * sintt) * r zlen = ti.sqrt(ti.max(0.0, 1.0 - xy.dot(xy))) return xy + zlen * normal