Exemple #1
0
    def march(self) -> int:
        r_n = 0

        for I in ti.grouped(ti.ndrange(*[[1, self.N - 1]] * self.dim)):
            id = 0
            if ti.static(self.dim == 2):
                i, j = I
                if self.m[i, j] > 1: id |= 1
                if self.m[i + 1, j] > 1: id |= 2
                if self.m[i, j + 1] > 1: id |= 4
                if self.m[i + 1, j + 1] > 1: id |= 8
            else:
                i, j, k = I
                if self.m[i, j, k] > 1: id |= 1
                if self.m[i + 1, j, k] > 1: id |= 2
                if self.m[i + 1, j + 1, k] > 1: id |= 4
                if self.m[i, j + 1, k] > 1: id |= 8
                if self.m[i, j, k + 1] > 1: id |= 16
                if self.m[i + 1, j, k + 1] > 1: id |= 32
                if self.m[i + 1, j + 1, k + 1] > 1: id |= 64
                if self.m[i, j + 1, k + 1] > 1: id |= 128

            for m in range(self.et.shape[1]):
                if self.et[id, m][0] == -1:
                    break

                n = ti.atomic_add(r_n, 1)
                for l in ti.static(range(self.dim)):
                    e = self.et[id, m][l]
                    R = float(I)

                    if ti.static(self.dim == 2):
                        i, j = I
                        # (.5, 0), (0, .5), (1, .5), (.5, 1)
                        if e == 0:
                            p = (1 - self.m[i, j]) / (self.m[i + 1, j] -
                                                      self.m[i, j])
                            R = [i + p, j]
                        elif e == 1:
                            p = (1 - self.m[i, j]) / (self.m[i, j + 1] -
                                                      self.m[i, j])
                            R = [i, j + p]
                        elif e == 2:
                            p = (1 - self.m[i + 1, j]) / (
                                self.m[i + 1, j + 1] - self.m[i + 1, j])
                            R = [i + 1, j + p]
                        elif e == 3:
                            p = (1 - self.m[i, j + 1]) / (
                                self.m[i + 1, j + 1] - self.m[i, j + 1])
                            R = [i + p, j + 1]
                    else:
                        i, j, k = I
                        # (.5, 0, 0), (1, .5, 0), (.5, 1, 0), (0, .5, 0)
                        # (.5, 0, 1), (1, .5, 1), (.5, 1, 1), (0, .5, 1)
                        # (0, 0, .5), (1, 0, .5), (1, 1, .5), (0, 1, .5)
                        if e == 0:
                            p = (1 - self.m[i, j, k]) / (self.m[i + 1, j, k] -
                                                         self.m[i, j, k])
                            R = [i + p, j, k]
                        elif e == 1:
                            p = (1 - self.m[i + 1, j, k]) / (
                                self.m[i + 1, j + 1, k] - self.m[i + 1, j, k])
                            R = [i + 1, j + p, k]
                        elif e == 2:
                            p = (1 - self.m[i, j + 1, k]) / (
                                self.m[i + 1, j + 1, k] - self.m[i, j + 1, k])
                            R = [i + p, j + 1, k]
                        elif e == 3:
                            p = (1 - self.m[i, j, k]) / (self.m[i, j + 1, k] -
                                                         self.m[i, j, k])
                            R = [i, j + p, k]
                        elif e == 4:
                            p = (1 - self.m[i, j, k + 1]) / (
                                self.m[i + 1, j, k + 1] - self.m[i, j, k + 1])
                            R = [i + p, j, k + 1]
                        elif e == 5:
                            p = (1 - self.m[i + 1, j, k + 1]) / (
                                self.m[i + 1, j + 1, k + 1] -
                                self.m[i + 1, j, k + 1])
                            R = [i + 1, j + p, k + 1]
                        elif e == 6:
                            p = (1 - self.m[i, j + 1, k + 1]) / (
                                self.m[i + 1, j + 1, k + 1] -
                                self.m[i, j + 1, k + 1])
                            R = [i + p, j + 1, k + 1]
                        elif e == 7:
                            p = (1 - self.m[i, j, k + 1]) / (
                                self.m[i, j + 1, k + 1] - self.m[i, j, k + 1])
                            R = [i, j + p, k + 1]
                        elif e == 8:
                            p = (1 - self.m[i, j, k]) / (self.m[i, j, k + 1] -
                                                         self.m[i, j, k])
                            R = [i, j, k + p]
                        elif e == 9:
                            p = (1 - self.m[i + 1, j, k]) / (
                                self.m[i + 1, j, k + 1] - self.m[i + 1, j, k])
                            R = [i + 1, j, k + p]
                        elif e == 10:
                            p = (1 - self.m[i + 1, j + 1, k]) / (
                                self.m[i + 1, j + 1, k + 1] -
                                self.m[i + 1, j + 1, k])
                            R = [i + 1, j + 1, k + p]
                        elif e == 11:
                            p = (1 - self.m[i, j + 1, k]) / (
                                self.m[i, j + 1, k + 1] - self.m[i, j + 1, k])
                            R = [i, j + 1, k + p]
                    self.r[n, l] = R

        return r_n
Exemple #2
0
def substep():
    for i, j in grid_m:
        grid_v[i, j] = [0, 0]
        grid_m[i, j] = 0
    for p in x:  # Particle state update and scatter to grid (P2G)
        base = (x[p] * inv_dx - 0.5).cast(int)
        fx = x[p] * inv_dx - base.cast(float)
        # Quadratic kernels  [http://mpm.graphics   Eqn. 123, with x=fx, fx-1,fx-2]
        w = [
            0.5 * ti.sqr(1.5 - fx), 0.75 - ti.sqr(fx - 1),
            0.5 * ti.sqr(fx - 0.5)
        ]
        F[p] = (ti.Matrix.identity(ti.f32, 2) +
                dt * C[p]) @ F[p]  # deformation gradient update
        h = max(0.1, min(5, ti.exp(10 * (1.0 - Jp[p])))
                )  # Hardening coefficient: snow gets harder when compressed
        if material[p] == 1:  # jelly, make it softer
            h = 0.3
        mu, la = mu_0 * h, lambda_0 * h
        if material[p] == 0:  # liquid
            mu = 0.0
        U, sig, V = ti.svd(F[p])
        J = 1.0
        for d in ti.static(range(2)):
            new_sig = sig[d, d]
            if material[p] == 2:  # Snow
                new_sig = min(max(sig[d, d], 1 - 2.5e-2),
                              1 + 4.5e-3)  # Plasticity
            Jp[p] *= sig[d, d] / new_sig
            sig[d, d] = new_sig
            J *= new_sig
        if material[
                p] == 0:  # Reset deformation gradient to avoid numerical instability
            F[p] = ti.Matrix.identity(ti.f32, 2) * ti.sqrt(J)
        elif material[p] == 2:
            F[p] = U @ sig @ V.T(
            )  # Reconstruct elastic deformation gradient after plasticity
        stress = 2 * mu * (F[p] - U @ V.T()) @ F[p].T() + ti.Matrix.identity(
            ti.f32, 2) * la * J * (J - 1)
        stress = (-dt * p_vol * 4 * inv_dx * inv_dx) * stress
        affine = stress + p_mass * C[p]
        for i, j in ti.static(ti.ndrange(
                3, 3)):  # Loop over 3x3 grid node neighborhood
            offset = ti.Vector([i, j])
            dpos = (offset.cast(float) - fx) * dx
            weight = w[i][0] * w[j][1]
            grid_v[base + offset] += weight * (p_mass * v[p] + affine @ dpos)
            grid_m[base + offset] += weight * p_mass
    for i, j in grid_m:
        if grid_m[i, j] > 0:  # No need for epsilon here
            grid_v[i,
                   j] = (1 / grid_m[i, j]) * grid_v[i,
                                                    j]  # Momentum to velocity
            grid_v[i, j] += dt * gravity[None] * 30  # gravity
            dist = attractor_pos[None] - dx * ti.Vector([i, j])
            grid_v[i, j] += dist / (
                0.01 + dist.norm()) * attractor_strength[None] * dt * 100
            if i < 3 and grid_v[i, j][0] < 0:
                grid_v[i, j][0] = 0  # Boundary conditions
            if i > n_grid - 3 and grid_v[i, j][0] > 0: grid_v[i, j][0] = 0
            if j < 3 and grid_v[i, j][1] < 0: grid_v[i, j][1] = 0
            if j > n_grid - 3 and grid_v[i, j][1] > 0: grid_v[i, j][1] = 0
    for p in x:  # grid to particle (G2P)
        base = (x[p] * inv_dx - 0.5).cast(int)
        fx = x[p] * inv_dx - base.cast(float)
        w = [
            0.5 * ti.sqr(1.5 - fx), 0.75 - ti.sqr(fx - 1.0),
            0.5 * ti.sqr(fx - 0.5)
        ]
        new_v = ti.Vector.zero(ti.f32, 2)
        new_C = ti.Matrix.zero(ti.f32, 2, 2)
        for i, j in ti.static(ti.ndrange(
                3, 3)):  # loop over 3x3 grid node neighborhood
            dpos = ti.Vector([i, j]).cast(float) - fx
            g_v = grid_v[base + ti.Vector([i, j])]
            weight = w[i][0] * w[j][1]
            new_v += weight * g_v
            new_C += 4 * inv_dx * weight * ti.outer_product(g_v, dpos)
        v[p], C[p] = new_v, new_C
        x[p] += dt * v[p]  # advection
Exemple #3
0
 def func():
     for i in x:
         for j in ti.static(range(3)):
             y[i] += x[i]
         y[i] += x[i] * 42
Exemple #4
0
 def test():
     for i, v in ti.static(enumerate(range(8))):
         pass
     print(i)
Exemple #5
0
 def static():
     if ti.static(x[0]):
         x[0] = 1
     else:
         x[0] = 0
Exemple #6
0
 def run(self):
     for I in ti.static(self.dst):
         self.dst[I] += self.src[I]
def point_aabb_distance2(box_min, box_max, o):
  p = ti.Vector([0.0, 0.0, 0.0])
  for i in ti.static(range(3)):
    p[i] = ti.max(ti.min(o[i], box_max[i]), box_min[i])
  return ti.Matrix.norm_sqr(p - o)
Exemple #8
0
def compute_center(t: ti.i32):
    for _ in range(1):
        c = ti.Vector([0.0, 0.0])
        for i in ti.static(range(n_objects)):
            c += x[t, i]
        center[t] = (1.0 / n_objects) * c
    def p2g(self, dt: ti.f32):
        ti.no_activate(self.particle)
        ti.block_dim(256)
        ti.block_local(*self.grid_v.entries)
        ti.block_local(self.grid_m)
        for I in ti.grouped(self.pid):
            p = self.pid[I]
            base = ti.floor(self.x[p] * self.inv_dx - 0.5).cast(int)
            for D in ti.static(range(self.dim)):
                base[D] = ti.assume_in_range(base[D], I[D], 0, 1)

            fx = self.x[p] * self.inv_dx - base.cast(float)
            # Quadratic kernels  [http://mpm.graphics   Eqn. 123, with x=fx, fx-1,fx-2]
            w = [0.5 * (1.5 - fx)**2, 0.75 - (fx - 1)**2, 0.5 * (fx - 0.5)**2]
            # deformation gradient update
            self.F[p] = (ti.Matrix.identity(ti.f32, self.dim) +
                         dt * self.C[p]) @ self.F[p]
            # Hardening coefficient: snow gets harder when compressed
            h = ti.exp(10 * (1.0 - self.Jp[p]))
            if self.material[
                    p] == self.material_elastic:  # jelly, make it softer
                h = 0.3
            mu, la = self.mu_0 * h, self.lambda_0 * h
            if self.material[p] == self.material_water:  # liquid
                mu = 0.0
            U, sig, V = ti.svd(self.F[p])
            J = 1.0
            if self.material[p] != self.material_sand:
                for d in ti.static(range(self.dim)):
                    new_sig = sig[d, d]
                    if self.material[p] == self.material_snow:  # Snow
                        new_sig = min(max(sig[d, d], 1 - 2.5e-2),
                                      1 + 4.5e-3)  # Plasticity
                    self.Jp[p] *= sig[d, d] / new_sig
                    sig[d, d] = new_sig
                    J *= new_sig
            if self.material[p] == self.material_water:
                # Reset deformation gradient to avoid numerical instability
                new_F = ti.Matrix.identity(ti.f32, self.dim)
                new_F[0, 0] = J
                self.F[p] = new_F
            elif self.material[p] == self.material_snow:
                # Reconstruct elastic deformation gradient after plasticity
                self.F[p] = U @ sig @ V.transpose()

            stress = ti.Matrix.zero(ti.f32, self.dim, self.dim)

            if self.material[p] != self.material_sand:
                stress = 2 * mu * (
                    self.F[p] - U @ V.transpose()) @ self.F[p].transpose(
                    ) + ti.Matrix.identity(ti.f32, self.dim) * la * J * (J - 1)
            else:
                sig = self.sand_projection(sig, p)
                self.F[p] = U @ sig @ V.transpose()
                log_sig_sum = 0.0
                center = ti.Matrix.zero(ti.f32, self.dim, self.dim)
                for i in ti.static(range(self.dim)):
                    log_sig_sum += ti.log(sig[i, i])
                    center[i, i] = 2.0 * self.mu_0 * ti.log(
                        sig[i, i]) * (1 / sig[i, i])
                for i in ti.static(range(self.dim)):
                    center[i,
                           i] += self.lambda_0 * log_sig_sum * (1 / sig[i, i])
                stress = U @ center @ V.transpose() @ self.F[p].transpose()

            stress = (-dt * self.p_vol * 4 * self.inv_dx**2) * stress
            affine = stress + self.p_mass * self.C[p]

            # Loop over 3x3 grid node neighborhood
            for offset in ti.static(ti.grouped(self.stencil_range())):
                dpos = (offset.cast(float) - fx) * self.dx
                weight = 1.0
                for d in ti.static(range(self.dim)):
                    weight *= w[offset[d]][d]
                self.grid_v[base +
                            offset] += weight * (self.p_mass * self.v[p] +
                                                 affine @ dpos)
                self.grid_m[base + offset] += weight * self.p_mass
Exemple #10
0
def fill_vbo(vbo: template(), value: template(), offset: template(),
             num_components: template()):
    for i in vbo:
        for c in ti.static(range(num_components)):
            vbo[i][offset + c] = value
Exemple #11
0
def substep():
    for i, j in grid_m:
        grid_v[i, j] = [0, 0]
        grid_m[i, j] = 0
    for p in x:
        base = (x[p] * inv_dx - 0.5).cast(int)
        fx = x[p] * inv_dx - base.cast(float)
        w = [
            0.5 * ti.sqr(1.5 - fx), 0.75 - ti.sqr(fx - 1),
            0.5 * ti.sqr(fx - 0.5)
        ]
        F[p] = (ti.Matrix.identity(ti.f32, 2) + dt * C[p]) @ F[p]
        h = ti.exp(10 * (1.0 - Jp[p]))
        if material[p] == 0:
            h = 0.3
        mu, la = mu_0 * h, lambda_0 * h
        U, sig, V = ti.svd(F[p])
        J = 1.0
        for d in ti.static(range(2)):
            new_sig = sig[d, d]
            if material[p] == 1:
                new_sig = min(max(sig[d, d], 1 - 2.5e-2), 1 + 4.5e-3)
            Jp[p] *= sig[d, d] / new_sig
            sig[d, d] = new_sig
            J *= new_sig
        if material[p] == 1:
            F[p] = U @ sig @ V.T()
        stress = 2 * mu * (F[p] - U @ V.T()) @ F[p].T() + ti.Matrix.identity(
            ti.f32, 2) * la * J * (J - 1)
        stress = (-dt * p_vol * 4 * inv_dx * inv_dx) * stress
        affine = stress + p_mass * C[p]
        for i, j in ti.static(ti.ndrange(3, 3)):
            offset = ti.Vector([i, j])
            dpos = (offset.cast(float) - fx) * dx
            weight = w[i][0] * w[j][1]
            grid_v[base + offset] += weight * (p_mass * v[p] + affine @ dpos)
            grid_m[base + offset] += weight * p_mass
    for i, j in grid_m:
        if grid_m[i, j] > 0:
            grid_v[i, j] = (1 / grid_m[i, j]) * grid_v[i, j]
            grid_v[i, j][1] -= dt * 50
            if i < 3 and grid_v[i, j][0] < 0: grid_v[i, j][0] = 0
            if i > n_grid - 3 and grid_v[i, j][0] > 0: grid_v[i, j][0] = 0
            if j < 3 and grid_v[i, j][1] < 0: grid_v[i, j][1] = 0
            if j > n_grid - 3 and grid_v[i, j][1] > 0: grid_v[i, j][1] = 0
    for p in x:
        base = (x[p] * inv_dx - 0.5).cast(int)
        fx = x[p] * inv_dx - base.cast(float)
        w = [
            0.5 * ti.sqr(1.5 - fx), 0.75 - ti.sqr(fx - 1.0),
            0.5 * ti.sqr(fx - 0.5)
        ]
        new_v = ti.Vector.zero(ti.f32, 2)
        new_C = ti.Matrix.zero(ti.f32, 2, 2)
        for i, j in ti.static(ti.ndrange(3, 3)):
            dpos = ti.Vector([i, j]).cast(float) - fx
            g_v = grid_v[base + ti.Vector([i, j])]
            weight = w[i][0] * w[j][1]
            new_v += weight * g_v
            new_C += 4 * inv_dx * weight * ti.outer_product(g_v, dpos)
        v[p], C[p] = new_v, new_C
        x[p] += dt * v[p]
Exemple #12
0
def copy_to_vbo(vbo: template(), src: template(), offset: template(),
                num_components: template()):
    for i in src:
        for c in ti.static(range(num_components)):
            vbo[i][offset + c] = src[i][c]
Exemple #13
0
def render():
    ti.parallelize(6)
    for u, v in color_buffer:
        pos = camera_pos
        d = ti.Vector([(2 * fov * (u + ti.random(ti.f32)) / res[1] -
                        fov * aspect_ratio - 1e-5),
                       2 * fov * (v + ti.random(ti.f32)) / res[1] - fov - 1e-5,
                       -1.0])
        d = ti.Matrix.normalized(d)
        t = (ti.random() - 0.5) * shutter_time

        contrib = ti.Vector([0.0, 0.0, 0.0])
        throughput = ti.Vector([1.0, 1.0, 1.0])

        depth = 0
        hit_sky = 1
        ray_depth = 0

        while depth < max_ray_depth:
            closest, normal, c = next_hit(pos, d, t)
            hit_pos = pos + closest * d
            depth += 1
            ray_depth = depth
            if normal.norm() != 0:
                d = out_dir(normal)
                pos = hit_pos + 1e-4 * d
                throughput *= c

                if ti.static(use_directional_light):
                    dir_noise = ti.Vector([
                        ti.random() - 0.5,
                        ti.random() - 0.5,
                        ti.random() - 0.5
                    ]) * light_direction_noise
                    direct = ti.Matrix.normalized(
                        ti.Vector(light_direction) + dir_noise)
                    dot = direct.dot(normal)
                    if dot > 0:
                        dist, _, _ = next_hit(pos, direct, t)
                        if dist > dist_limit:
                            contrib += throughput * ti.Vector(
                                light_color) * dot
            else:  # hit sky
                hit_sky = 1
                depth = max_ray_depth

            max_c = throughput.max()
            if ti.random() > max_c:
                depth = max_ray_depth
                throughput = [0, 0, 0]
            else:
                throughput /= max_c

        if hit_sky:
            if ray_depth != 1:
                # contrib *= max(d[1], 0.05)
                pass
            else:
                # directly hit sky
                pass
        else:
            throughput *= 0

        # contrib += throughput
        color_buffer[u, v] += contrib
Exemple #14
0
def dda_particle(eye_pos, d, t):
    grid_res = particle_grid_res

    bbox_min = bbox[0]
    bbox_max = bbox[1]

    hit_pos = ti.Vector([0.0, 0.0, 0.0])
    normal = ti.Vector([0.0, 0.0, 0.0])
    c = ti.Vector([0.0, 0.0, 0.0])
    for i in ti.static(range(3)):
        if abs(d[i]) < 1e-6:
            d[i] = 1e-6

    inter, near, far = ray_aabb_intersection(bbox_min, bbox_max, eye_pos, d)
    near = max(0, near)

    closest_intersection = inf

    if inter:
        pos = eye_pos + d * (near + eps)

        rinv = 1.0 / d
        rsign = ti.Vector([0, 0, 0])
        for i in ti.static(range(3)):
            if d[i] > 0:
                rsign[i] = 1
            else:
                rsign[i] = -1

        o = grid_res * pos
        ipos = ti.Matrix.floor(o).cast(int)
        dis = (ipos - o + 0.5 + rsign * 0.5) * rinv
        running = 1
        while running:
            inside = inside_particle_grid(ipos)

            if inside:
                num_particles = voxel_has_particle[ipos]
                if num_particles != 0:
                    num_particles = ti.length(pid.parent(), ipos)
                for k in range(num_particles):
                    p = pid[ipos[0], ipos[1], ipos[2], k]
                    v = particle_v[p]
                    x = particle_x[p] + t * v
                    color = particle_color[p]
                    dist, poss = intersect_sphere(eye_pos, d, x, sphere_radius)
                    hit_pos = poss
                    if dist < closest_intersection and dist > 0:
                        hit_pos = eye_pos + dist * d
                        closest_intersection = dist
                        normal = ti.Matrix.normalized(hit_pos - x)
                        c = color
            else:
                running = 0
                normal = [0, 0, 0]

            if closest_intersection < inf:
                running = 0
            else:
                # hits nothing. Continue ray marching
                mm = ti.Vector([0, 0, 0])
                if dis[0] <= dis[1] and dis[0] <= dis[2]:
                    mm[0] = 1
                elif dis[1] <= dis[0] and dis[1] <= dis[2]:
                    mm[1] = 1
                else:
                    mm[2] = 1
                dis += mm * rsign * rinv
                ipos += mm * rsign

    return closest_intersection, normal, c
Exemple #15
0
 def run(self):
     for I in ti.static(self.src):
         self.buf[I] = self.src[I]
 def copy_dynamic_nd(self, np_x: ti.ext_arr(), input_x: ti.template()):
     for i in self.x:
         for j in ti.static(range(self.dim)):
             np_x[i, j] = input_x[i][j]
Exemple #17
0
 def _run(self, nxt: ti.template(), src: ti.template()):
     for I in ti.static(src):
         nxt[I] = src[I]
Exemple #18
0
 def util_vector_to_plain_array(self, v: ti.template()) -> ti.template():
     ### used .mat of Proxy object, PROBLEM?
     return list([v[i] for i in ti.static(range(v.mat.n))])
Exemple #19
0
def update():
    for i in ti.static(range(number_coeffs)):
        coeffs[i] -= learning_rate * coeffs.grad[i]
Exemple #20
0
 def util_matrix_to_plain_array(self, v: ti.template()) -> ti.template():
     ### used .mat of Proxy object, PROBLEM?
     return list([[v[n, m] for m in ti.static(range(v.mat.m))]
                  for n in ti.static(range(v.mat.n))])
Exemple #21
0
 def test():
     for i in ti.static(range(8)):
         pass
     print(i)
Exemple #22
0
 def cook_coor(self, I, camera):
     scale = ti.static(2 / min(*camera.img.shape()))
     coor = (I - ts.vec2(*camera.img.shape()) / 2) * scale
     return coor
Exemple #23
0
 def static():
     if ti.static(val > 0.5):
         x[0] = 1
     else:
         x[0] = 0
Exemple #24
0
 def uncook_coor(self, coor, camera):
     scale = ti.static(min(*camera.img.shape()) / 2)
     I = coor.xy * scale + ts.vec2(*camera.img.shape()) / 2
     return I
Exemple #25
0
 def neighbor_sum(self, x, I):
     ret = 0.0
     for i in ti.static(range(self.dim)):
         offset = ti.Vector.unit(self.dim, i)
         ret += x[I + offset] + x[I - offset]
     return ret
Exemple #26
0
 def func():
     for i in ti.static(ti.static(range(1))):
         pass
 def func():
     for i in range(ti.static(N // 2 + 3), N):
         x[i] = ti.abs(y[i])
Exemple #28
0
 def test():
     for I in ti.static(ti.grouped(val)):
         pass
Exemple #29
0
def clamp(p):
    for d in ti.static(range(p.n)):
        p[d] = min(1 - 1e-4 - dx + stagger[d] * dx, max(p[d], stagger[d] * dx))
    return p
Exemple #30
0
def clamp( val , low , high):
    if ti.static(is_scalar(val)):
        return clamp
    else:
        return clamp_vector(val , low , high)