From aec971d94292c9a14ed5ba2271c9ffa51f975804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E4=BA=8E=E6=96=8C?= <1931127624@qq.com> Date: Sat, 19 Sep 2020 08:55:41 +0800 Subject: [PATCH] [Example] Add mciso.py and mciso_advanced.py for marching cube (#1835) * [Example] Add mciso.py and mciso_advanced.py for marching cube * [skip ci] enforce code format * [skip ci] self nit * [skip ci] enforce code format * [skip ci] update example images in public_files * [skip ci] raw/master Co-authored-by: Taichi Gardener --- README.md | 8 +- examples/mciso.py | 93 ++++++++ examples/mciso_advanced.py | 427 +++++++++++++++++++++++++++++++++++++ examples/physarum.py | 75 +++---- misc/examples.md | 16 +- 5 files changed, 571 insertions(+), 48 deletions(-) create mode 100644 examples/mciso.py create mode 100644 examples/mciso_advanced.py diff --git a/README.md b/README.md index cd4e82a75fe66..48a48b65c0a57 100644 --- a/README.md +++ b/README.md @@ -23,10 +23,10 @@ Advanced features of Taichi include [spatially sparse computing](https://taichi. ## Examples ([More...](misc/examples.md)) - - - - + + + + ## Installation [![Downloads](https://pepy.tech/badge/taichi/month)](https://pepy.tech/project/taichi/month) diff --git a/examples/mciso.py b/examples/mciso.py new file mode 100644 index 0000000000000..8fa4bb4e9c7d4 --- /dev/null +++ b/examples/mciso.py @@ -0,0 +1,93 @@ +import taichi as ti +import numpy as np +ti.init() + +N = 128 + +_et = np.array( + [ + [[-1, -1], [-1, -1]], # + [[0, 1], [-1, -1]], #a + [[0, 2], [-1, -1]], #b + [[1, 2], [-1, -1]], #ab + [[1, 3], [-1, -1]], #c + [[0, 3], [-1, -1]], #ca + [[2, 3], [0, 1]], #cb + [[2, 3], [-1, -1]], #cab + [[2, 3], [-1, -1]], #d + [[2, 3], [0, 1]], #da + [[0, 3], [-1, -1]], #db + [[1, 3], [-1, -1]], #dab + [[1, 2], [-1, -1]], #dc + [[0, 2], [-1, -1]], #dca + [[0, 1], [-1, -1]], #dcb + [[-1, -1], [-1, -1]], #dcab + ], + np.int32) + +m = ti.field(float, (N, N)) # field value of voxels + +r = ti.Vector.field(2, float, (N**2, 2)) # generated edges +et = ti.Vector.field(2, int, _et.shape[:2]) # edge table (constant) +et.from_numpy(_et) + + +@ti.func +def gauss(x): + return ti.exp(-6 * x**2) + + +@ti.kernel +def touch(mx: float, my: float): + for i, j in m: + p = ti.Vector([i, j]) / N + a = gauss((p - 0.5).norm() / 0.25) + p.x -= mx - 0.5 / N + p.y -= my - 0.5 / N + b = gauss(p.norm() / 0.25) + m[i, j] = (a + b) * 3 + + +@ti.func +def list_subscript(a, + i): # magic method to subscript a list with dynamic index + ret = sum(a) * 0 + for j in ti.static(range(len(a))): + if i == j: + ret = a[j] + return ret + + +@ti.kernel +def march() -> int: + r_n = 0 + + for i, j in ti.ndrange(N - 1, N - 1): + id = 0 + if m[i, j] > 1: id |= 1 + if m[i + 1, j] > 1: id |= 2 + if m[i, j + 1] > 1: id |= 4 + if m[i + 1, j + 1] > 1: id |= 8 + + E = [ti.Vector(_) + .5 for _ in [(.5, 0), (0, .5), (1, .5), (.5, 1)]] + + for k in range(2): + if et[id, k][0] == -1: + break + + n = ti.atomic_add(r_n, 1) + for l in ti.static(range(2)): + e = et[id, k][l] + r[n, l] = ti.Vector([i, j]) + list_subscript(E, e) + + return r_n + + +gui = ti.GUI('Marching rect') +while gui.running and not gui.get_event(gui.ESCAPE): + touch(*gui.get_cursor_pos()) + ret_len = march() + ret = r.to_numpy()[:ret_len] / N + gui.set_image(ti.imresize(m, *gui.res)) + gui.lines(ret[:, 0], ret[:, 1], color=0xff66cc, radius=1.5) + gui.show() diff --git a/examples/mciso_advanced.py b/examples/mciso_advanced.py new file mode 100644 index 0000000000000..4c113a8871ac0 --- /dev/null +++ b/examples/mciso_advanced.py @@ -0,0 +1,427 @@ +import taichi as ti +import numpy as np + + +@ti.func +def list_subscript(a, i): + ret = sum(a) * 0 + for j in ti.static(range(len(a))): + if i == j: + ret = a[j] + return ret + + +@ti.data_oriented +class MCISO: + et2 = np.array( + [ + [[-1, -1], [-1, -1]], # + [[0, 1], [-1, -1]], #a + [[0, 2], [-1, -1]], #b + [[1, 2], [-1, -1]], #ab + [[1, 3], [-1, -1]], #c + [[0, 3], [-1, -1]], #ca + [[2, 3], [0, 1]], #cb + [[2, 3], [-1, -1]], #cab + [[2, 3], [-1, -1]], #d + [[2, 3], [0, 1]], #da + [[0, 3], [-1, -1]], #db + [[1, 3], [-1, -1]], #dab + [[1, 2], [-1, -1]], #dc + [[0, 2], [-1, -1]], #dca + [[0, 1], [-1, -1]], #dcb + [[-1, -1], [-1, -1]], #dcab + ], + np.int32) + et3 = np.array( + [ # {{{ + # https://www.cnblogs.com/shushen/p/5542131.html + [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1], + [3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1], + [3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1], + [3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1], + [9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1], + [1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1], + [9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1], + [2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1], + [8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1], + [9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1], + [4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1], + [3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1], + [1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1], + [4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1], + [4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1], + [9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1], + [1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1], + [5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1], + [2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1], + [9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1], + [0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1], + [2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1], + [10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1], + [4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1], + [5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1], + [5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1], + [9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1], + [0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1], + [1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1], + [10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1], + [8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1], + [2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1], + [7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1], + [9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1], + [2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1], + [11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1], + [9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1], + [5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1], + [11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1], + [11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1], + [1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1], + [9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1], + [5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1], + [2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1], + [0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1], + [5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1], + [6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1], + [0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1], + [3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1], + [6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1], + [5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1], + [1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1], + [10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1], + [6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1], + [1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1], + [8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1], + [7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1], + [3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1], + [5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1], + [0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1], + [9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1], + [8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1], + [5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1], + [0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1], + [6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1], + [10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1], + [10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1], + [8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1], + [1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1], + [3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1], + [0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1], + [10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1], + [0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1], + [3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1], + [6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1], + [9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1], + [8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1], + [3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1], + [6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1], + [0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1], + [10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1], + [10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1], + [1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1], + [2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1], + [7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1], + [7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1], + [2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1], + [1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1], + [11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1], + [8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1], + [0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1], + [7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1], + [10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1], + [2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1], + [6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1], + [7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1], + [2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1], + [1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1], + [10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1], + [10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1], + [0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1], + [7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1], + [6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1], + [8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1], + [9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1], + [6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1], + [1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1], + [4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1], + [10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1], + [8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1], + [0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1], + [1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1], + [8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1], + [10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1], + [4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1], + [10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1], + [5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1], + [11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1], + [9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1], + [6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1], + [7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1], + [3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1], + [7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1], + [9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1], + [3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1], + [6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1], + [9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1], + [1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1], + [4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1], + [7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1], + [6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1], + [3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1], + [0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1], + [6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1], + [1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1], + [0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1], + [11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1], + [6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1], + [5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1], + [9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1], + [1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1], + [1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1], + [10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1], + [0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1], + [5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1], + [10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1], + [11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1], + [0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1], + [9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1], + [7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1], + [2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1], + [8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1], + [9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1], + [9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1], + [1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1], + [9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1], + [9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1], + [5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1], + [0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1], + [10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1], + [2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1], + [0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1], + [0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1], + [9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1], + [5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1], + [3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1], + [5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1], + [8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1], + [0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1], + [9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1], + [0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1], + [1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1], + [3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1], + [4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1], + [9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1], + [11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1], + [11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1], + [2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1], + [9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1], + [3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1], + [1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1], + [4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1], + [4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1], + [0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1], + [3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1], + [3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1], + [0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1], + [9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1], + [1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1], + ], + np.int32)[:, :15].reshape(256, 5, 3) # }}} + + E2 = [(.5, 0), (0, .5), (1, .5), (.5, 1)] + E3 = [(.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)] + + def __init__(self, N=64, dim=3, blk_size=None): + + self.N = N + self.dim = dim + self.use_sparse = blk_size is not None + self.blk_size = blk_size + + et = [self.et2, self.et3][dim - 2] + + self.m = ti.field(float) + indices = [ti.ij, ti.ijk][dim - 2] + if self.use_sparse: + ti.root.pointer(indices, self.N // self.blk_size).dense( + indices, self.blk_size).place(self.m) + else: + ti.root.dense(indices, self.N).place(self.m) + + self.r = ti.Vector.field(dim, float, (self.N**self.dim, self.dim)) + self.et = ti.Vector.field(dim, int, et.shape[:2]) + self.et.from_numpy(et) + + @ti.kernel + def march(self) -> int: + r_n = 0 + + for I in ti.grouped(ti.ndrange(*[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 + + E = [ti.Vector(_) + .5 for _ in [self.E2, self.E3][self.dim - 2]] + + for k in range(self.et.shape[1]): + if self.et[id, k][0] == -1: + break + + n = ti.atomic_add(r_n, 1) + for l in ti.static(range(self.dim)): + e = self.et[id, k][l] + self.r[n, l] = I + list_subscript(E, e) + + return r_n + + +class MCISO_Example(MCISO): + @ti.func + def gauss(self, x): + return ti.exp(-6 * x**2) + + @ti.kernel + def touch(self, mx: float, my: float): + for o in ti.grouped(ti.ndrange(*[self.N] * self.dim)): + p = o / self.N + a = self.gauss((p - 0.5).norm() / 0.25) + p.x -= mx - 0.5 / self.N + p.y -= my - 0.5 / self.N + if ti.static(self.dim == 3): + p.z -= 0.5 + b = self.gauss(p.norm() / 0.25) + r = max(a + b - 0.08, 0) + if r <= 0: + continue + self.m[o] = r * 3 + + def main(self, export_result=None): + gui = ti.GUI('Marching cube') + while gui.running and not gui.get_event(gui.ESCAPE): + if self.use_sparse: + ti.root.deactivate_all() + else: + self.m.fill(0) + self.touch(*gui.get_cursor_pos()) + ret_len = self.march() + ret = self.r.to_numpy()[:ret_len] / self.N + if self.dim == 2: + gui.set_image(ti.imresize(self.m, *gui.res)) + gui.lines(ret[:, 0], ret[:, 1], color=0xff66cc, radius=1.5) + else: + gui.triangles(ret[:, 0, 0:2], + ret[:, 1, 0:2], + ret[:, 2, 0:2], + color=0xffcc66) + gui.lines(ret[:, 0, 0:2], + ret[:, 1, 0:2], + color=0xff66cc, + radius=0.5) + gui.lines(ret[:, 1, 0:2], + ret[:, 2, 0:2], + color=0xff66cc, + radius=0.5) + gui.lines(ret[:, 2, 0:2], + ret[:, 0, 0:2], + color=0xff66cc, + radius=0.5) + if export_result is not None: + num = ret.shape[0] + writer = ti.PLYWriter(num_vertices=num * 3, num_faces=num) + vertices = ret.reshape(num * 3, 3) * 2 - 1 + writer.add_vertex_pos(vertices[:, 0], vertices[:, 1], + vertices[:, 2]) + indices = np.arange(0, num * 3) + writer.add_faces(indices) + writer.export_frame(gui.frame, export_result) + gui.show() + + +if __name__ == '__main__': + ti.init(arch=ti.gpu) + main = MCISO_Example() + main.main() + #main.main(export_result='/tmp/marching_cube.ply') diff --git a/examples/physarum.py b/examples/physarum.py index 62ce943c3256a..3d4b6c827c994 100644 --- a/examples/physarum.py +++ b/examples/physarum.py @@ -8,10 +8,10 @@ PARTICLE_N = 1024 GRID_SIZE = 512 -SENSE_ANGLE = 0.20*np.pi +SENSE_ANGLE = 0.20 * np.pi SENSE_DIST = 4.0 EVAPORATION = 0.95 -MOVE_ANGLE = 0.1*np.pi +MOVE_ANGLE = 0.1 * np.pi MOVE_STEP = 2.0 grid = ti.field(dtype=ti.f32, shape=[2, GRID_SIZE, GRID_SIZE]) @@ -21,47 +21,50 @@ @ti.kernel def init(): - for p in ti.grouped(grid): - grid[p] = 0.0 - for i in position: - position[i] = ti.Vector([ti.random(), ti.random()]) * GRID_SIZE - heading[i] = ti.random()*np.pi*2.0 + for p in ti.grouped(grid): + grid[p] = 0.0 + for i in position: + position[i] = ti.Vector([ti.random(), ti.random()]) * GRID_SIZE + heading[i] = ti.random() * np.pi * 2.0 + @ti.func def sense(phase, pos, ang): - p = pos + ti.Vector([ti.cos(ang), ti.sin(ang)]) * SENSE_DIST - return grid[phase, p.cast(int)%GRID_SIZE] + p = pos + ti.Vector([ti.cos(ang), ti.sin(ang)]) * SENSE_DIST + return grid[phase, p.cast(int) % GRID_SIZE] + @ti.kernel 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 + # 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 - # 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 - # 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 print("[Hint] Press A/Z to change the simulation speed.") gui = ti.GUI('Physarum') @@ -70,7 +73,7 @@ def step(phase: ti.i32): step_per_frame = gui.slider('step_per_frame', 1, 100, 1) while gui.running and not gui.get_event(gui.ESCAPE): for _ in range(int(step_per_frame.value)): - step(i%2) + step(i % 2) i += 1 gui.set_image(grid.to_numpy()[0]) gui.show() diff --git a/misc/examples.md b/misc/examples.md index 1bf7887473ff5..4c25b75f27999 100644 --- a/misc/examples.md +++ b/misc/examples.md @@ -1,11 +1,11 @@ # More examples - - - - + + + + - - - - + + + +