| 1 | import math as m |
| 2 | import term |
| 3 | import strings |
| 4 | import time { sleep } |
| 5 | |
| 6 | const alt = '.,-~:;=!*#$@' |
| 7 | |
| 8 | fn rd(cs int, ls int, a f64, |
| 9 | b f64) { |
| 10 | tt_spacing, p_spacing := 0.07, 0.02 |
| 11 | r1, r2, k2 := 1, 2, 5 |
| 12 | k1 := cs * k2 * 2 / (20 * (r1 + r2)) |
| 13 | c_a, s_a := m.cos(a), m.sin(a) |
| 14 | c_b, s_b := m.cos(b), m.sin(b) |
| 15 | mut o := [][]rune{len: cs, init: []rune{len: ls, init: ` `}} |
| 16 | mut z_buffer := [][]f64{len: cs, init: []f64{len: ls, init: 0}} |
| 17 | for tt := f64(0); tt < 2 * m.pi; tt += tt_spacing { |
| 18 | c_tt, s_tt := m.cos(tt), m.sin(tt) |
| 19 | for phi := f64(0); phi < 2 * m.pi; phi += p_spacing { |
| 20 | c_p, s_p := m.cos(phi), m.sin(phi) |
| 21 | c_x, c_y := r2 + r1 * c_tt, r1 * s_tt |
| 22 | x := c_x * (c_b * c_p + s_a * s_b * s_p) - c_y * c_a * s_b |
| 23 | y := c_x * (s_b * c_p - s_a * c_b * s_p) + c_y * c_a * c_b |
| 24 | z := k2 + c_a * c_x * s_p + c_y * s_a |
| 25 | ooz := 1 / z |
| 26 | xp := int(cs / 2 + k1 * ooz * x) |
| 27 | yp := int(ls / 2 - k1 * ooz * y) |
| 28 | l := c_p * c_tt * s_b - c_a * c_tt * s_p - s_a * s_tt + |
| 29 | c_b * (c_a * s_tt - c_tt * s_a * s_p) |
| 30 | if l > 0 { |
| 31 | if xp < 0 || yp < 0 || xp >= cs || yp >= ls { |
| 32 | continue |
| 33 | } |
| 34 | if ooz > z_buffer[int(xp)][int(yp)] { |
| 35 | z_buffer[xp][yp] = ooz |
| 36 | lui := int(l * 8) |
| 37 | o[xp][yp] = alt[lui] |
| 38 | } |
| 39 | } |
| 40 | } |
| 41 | } |
| 42 | mut sb := strings.new_builder(ls * cs) |
| 43 | print('\x1b[H') |
| 44 | for j := 0; j < ls; j++ { |
| 45 | for i := 0; i < cs; i++ { |
| 46 | sb.write_rune(o[i][j]) |
| 47 | } |
| 48 | sb.write_rune(`\n`) |
| 49 | } |
| 50 | print(sb.str()) |
| 51 | } |
| 52 | |
| 53 | fn main() { |
| 54 | term.clear() |
| 55 | cs, ls := 80, 25 |
| 56 | mut a, mut b := f64(0), f64(0) |
| 57 | for { |
| 58 | rd(cs, ls, a, b) |
| 59 | a += 0.05 |
| 60 | b += 0.07 |
| 61 | sleep(15 * time.millisecond) |
| 62 | } |
| 63 | } |
| 64 | |