using AbstractPlotting function cartesian(ll) return Point3f0( cos(ll[1]) * sin(ll[2]), sin(ll[1]) * sin(ll[2]), cos(ll[2]) ) end fract(x) = x - floor(x) function calcpositions(rings, index, time, audio) movement, radius, speed, spin = 1, 2, 3, 4; position = Point3f0(0.0) precision = 0.2f0 for ring in rings position += ring[radius] * cartesian( precision * index * Point2f0(ring[spin] + Point2f0(sin(time * ring[speed]), cos(time * ring[speed])) * ring[movement]) ) end amplitude = audio[round(Int, clamp(fract(position[1] * 0.1), 0, 1) * (25000-1)) + 1]; # index * 0.002 position *= 1.0 + amplitude * 0.5; position end rings = [(0.1f0, 1.0f0, 0.00001f0, Point2f0(0.2, 0.1)), (0.1f0, 0.0f0, 0.0002f0, Point2f0(0.052, 0.05))] N2 = 25000 t_audio = sin.(range(0, stop = 10pi, length = N2)) .+ (cos.(range(-3, stop = 7pi, length = N2)) .* 0.6) .+ (rand(Float32, N2) .* 0.1) ./ 2f0 start = time() t = (time() - start) * 100 pos = calcpositions.((rings,), 1:N2, t, (t_audio,)) scene = lines( pos, color = RGBAf0.(to_colormap(:RdBu, N2), 0.6), thickness = 0.6f0, show_axis = false, transparency = true ) linesegments!( scene, FRect3D(Vec3f0(-1.5), Vec3f0(3)), raw = true, linewidth = 3, linestyle = :dot ) eyepos = Vec3f0(5, 1.5, 0.5) lookat = Vec3f0(0) update_cam!(scene, eyepos, lookat) scene.center = false # prevent scene from recentering on display l = scene[1] N = 150 record(scene, "output.mp4", 1:N) do i t = (time() - start) * 700 pos .= calcpositions.((rings,), 1:N2, t, (t_audio,)) l[1] = pos # update argument 1 rotate_cam!(scene, 0.0, 0.01, 0.01) end