def sdLine(u, v, p): pu = p - u vp = v - p vu = v - u puXvu = pu.cross(vu) puOvu = pu.dot(vu) vpOvu = vp.dot(vu) ret = 0.0 if puOvu < 0: ret = ts.length(pu) elif vpOvu < 0: ret = ts.length(vp) else: ret = puXvu * ts.invLength(vu) return ret
def paintArrow(img: ti.template(), orig, dir, color=1, width=3, max_size=12, min_scale=0.4): res = ts.vec(*img.shape) I = orig * res D = dir * res J = I + D DL = ts.length(D) S = min(max_size, DL * min_scale) DS = D / (DL + 1e-4) * S SW = S + width D1 = ti.Matrix.rotation2d(+math.pi * 3 / 4) @ DS D2 = ti.Matrix.rotation2d(-math.pi * 3 / 4) @ DS bmin, bmax = ti.floor(max(0, min(I, J) - SW)), ti.ceil( min(res - 1, max(I, J) + SW)) for P in ti.grouped(ti.ndrange((bmin.x, bmax.x), (bmin.y, bmax.y))): c0 = ts.smoothstep(abs(sdLine(I, J, P)), width, width / 2) c1 = ts.smoothstep(abs(sdLine(J, J + D1, P)), width, width / 2) c2 = ts.smoothstep(abs(sdLine(J, J + D2, P)), width, width / 2) ti.atomic_max(img[P], max(c0, c1, c2) * color)
def do_render(self): model = self.model scene = model.scene L2W = model.L2W a = scene.camera.untrans_pos(L2W @ self.vertex(0).pos) b = scene.camera.untrans_pos(L2W @ self.vertex(1).pos) c = scene.camera.untrans_pos(L2W @ self.vertex(2).pos) A = scene.uncook_coor(a) B = scene.uncook_coor(b) C = scene.uncook_coor(c) B_A = B - A C_B = C - B A_C = A - C ilB_A = 1 / ts.length(B_A) ilC_B = 1 / ts.length(C_B) ilA_C = 1 / ts.length(A_C) B_A *= ilB_A C_B *= ilC_B A_C *= ilA_C BxA = ts.cross(B, A) * ilB_A CxB = ts.cross(C, B) * ilC_B AxC = ts.cross(A, C) * ilA_C normal = ts.normalize(ts.cross(a - c, a - b)) light_dir = scene.camera.untrans_dir(scene.light_dir[None]) pos = (a + b + c) / 3 color = scene.opt.render_func(pos, normal, ts.vec3(0.0), light_dir) color = scene.opt.pre_process(color) Ak = 1 / (ts.cross(A, C_B) + CxB) Bk = 1 / (ts.cross(B, A_C) + AxC) Ck = 1 / (ts.cross(C, B_A) + BxA) W = 1 M, N = int(ti.floor(min(A, B, C) - W)), int(ti.ceil(max(A, B, C) + W)) for X in ti.grouped(ti.ndrange((M.x, N.x), (M.y, N.y))): AB = ts.cross(X, B_A) + BxA BC = ts.cross(X, C_B) + CxB CA = ts.cross(X, A_C) + AxC if AB <= 0 and BC <= 0 and CA <= 0: zindex = pos.z #(Ak * a.z * BC + Bk * b.z * CA + Ck * c.z * AB) zstep = zindex - ti.atomic_max(scene.zbuf[X], zindex) if zstep >= 0: scene.img[X] = color
def do_render(self, scene): a = scene.camera.untrans_pos(self.a) b = scene.camera.untrans_pos(self.b) c = scene.camera.untrans_pos(self.c) A = scene.uncook_coor(a) B = scene.uncook_coor(b) C = scene.uncook_coor(c) B_A = B - A C_B = C - B A_C = A - C ilB_A = 1 / ts.length(B_A) ilC_B = 1 / ts.length(C_B) ilA_C = 1 / ts.length(A_C) B_A *= ilB_A C_B *= ilC_B A_C *= ilA_C BxA = ts.cross(B, A) * ilB_A CxB = ts.cross(C, B) * ilC_B AxC = ts.cross(A, C) * ilA_C normal = ts.normalize(ts.cross(a - c, a - b)) light_dir = scene.camera.untrans_dir(scene.light_dir[None]) pos = (a + b + c) * (1 / 3) dir = ts.vec3(0.0) color = scene.opt.render_func(pos, normal, dir, light_dir) color = scene.opt.pre_process(color) W = 0.4 M, N = int(ti.floor(min(A, B, C) - W)), int(ti.ceil(max(A, B, C) + W)) for X in ti.grouped(ti.ndrange((M.x, N.x), (M.y, N.y))): AB = ts.cross(X, B_A) + BxA BC = ts.cross(X, C_B) + CxB CA = ts.cross(X, A_C) + AxC udf = max(AB, BC, CA) if udf < 0: scene.img[X] = color elif udf < W: t = ts.smoothstep(udf, W, 0) ti.atomic_max(scene.img[X], t * color)
def mandelbox(z): offset = z dz = 1.0 for _ in range(0, 10): # box fold z = ts.clamp(z, -1.0, 1.0) * 2.0 - z # ball fold r2 = ts.dot(z, z) if r2 < min_radius[None]: tmp = (fix_radius[None] / min_radius[None]) z *= tmp dz *= tmp elif r2 < fix_radius[None]: tmp = fix_radius[None] / r2 z *= tmp dz *= tmp z = scale * z + offset dz = dz * ti.abs(scale) + 1.0 return ts.length(z) / ti.abs(dz)
def plane(pos): return ts.length(ti.max(ti.abs(pos) - ts.vec(12.0, 0.5, 12.0), 0.0))