# Homework0: MultiBarnsleyFern

1. 将矩阵乘法和加法用`ti.Matrix()``ti.Vector()`包装了一下
2. 不同于原作者随着时间"舞动"的BarnsleyFern,本程序展现了BarnsleyFern生成的过程
3. 加入另外两只BarnsleyFern,调整了其颜色和相位差

### code

``````import taichi as ti
import math
import time

ti.init(arch=ti.gpu)

width_one = 660
height = 1000
width = width_one * 3
pixels = ti.var(dt=ti.f32, shape=(width, height, 3))
next_point = ti.Vector(2, dt=ti.f32, shape=(1,))
mat = ti.Matrix(2, 2, dt=ti.f32, shape=(4,))
vec = ti.Vector(2, dt=ti.f32, shape=(4,))

@ti.func
def generatePoint(x, y, t):
r = ti.random()
i = 0

next_point[0] = ti.Vector([[x], [y]])
mat[0] = ti.Matrix([[0.0, 0.0], [0.0, 0.16]])
mat[1] = ti.Matrix([[0.85, 0.04+t], [-0.04-t, 0.85]])
mat[2] = ti.Matrix([[0.20+t, -0.26-t], [0.23+t, 0.22-t]])
mat[3] = ti.Matrix([[-0.15, 0.28], [0.26, 0.24]])

vec[0] = ti.Vector([[0.0], [0.0]])
vec[1] = ti.Vector([[0.0], [1.6]])
vec[2] = ti.Vector([[0.0], [1.6]])
vec[3] = ti.Vector([[0.0], [0.44]])

if(r < 0.01):
i = 0
elif(r < 0.86):
i = 1
elif(r < 0.93):
i = 2
else:
i = 3
next_point[0] = mat[i] @ next_point[0] + vec[i]
return next_point[0][0, 0], next_point[0][1, 0]

@ti.kernel
def drawPoint(t: ti.f32, n: ti.i32, c: ti.i32):
for i in range(0, 100000):
x = 0.0
y = 0.0
for j in range(0, n):
x, y = generatePoint(x, y, t)
if c == 1:
pixels[(int)((x/6+0.5)*width_one), (int)(y*height/12), 0] += 0.01
pixels[(int)((x/6+0.5)*width_one), (int)(y*height/12), 1] += 0.02
pixels[(int)((x/6+0.5)*width_one), (int)(y*height/12), 2] += 0.005
elif c == 2:
pixels[(int)((x/6+1.5)*width_one), (int)(y*height/12), 0] += 0.01
pixels[(int)((x/6+1.5)*width_one), (int)(y*height/12), 1] += 0.01
pixels[(int)((x/6+1.5)*width_one), (int)(y*height/12), 2] += 0.005
elif c == 3:
pixels[(int)((x/6+2.5)*width_one), (int)(y*height/12), 0] += 0.01
pixels[(int)((x/6+2.5)*width_one), (int)(y*height/12), 1] += 0.005
pixels[(int)((x/6+2.5)*width_one), (int)(y*height/12), 2] += 0.01

gui = ti.GUI("BarnsleyFern", (width, height))
timer = 0.0

while(True):
pixels_fresh = pixels
for c in range(1, 4):
for i in range(0, 20):
time.sleep(0.1)
drawPoint(math.sin(timer)*0.03, i, c)
pixels_img = pixels.to_numpy()
gui.set_image(pixels_img)
gui.show()
# gui.show(f'frame/{ts:04d}.png')
if i == 40:
pixels_fresh = pixels
pixels = pixels_fresh
time.sleep(1)
timer += 2.4
pixels.fill(0)
``````

6 Likes