Building a Breathing Quantum Web: O(N²) Proximity Algorithms in Py5
2026/7/30
Visualizing complex, shifting networks—like neural pathways or quantum entanglement matrices—requires a delicate balance between chaotic motion and structured connectivity. In this project, the goal was to simulate a 3D network of glowing nodes drifting organically through a dark void. As these nodes pass close to one another, luminous connections spontaneously form and break, creating a dynamic, breathing web of light.Python, coupled with the Py5 generative art library, offers an ideal platform for this kind of simulation. It allows us to combine straightforward object-oriented programming for our data structures with high-performance 3D rendering to bring the mathematical concepts to life visually.
Visual and Aesthetic Approach
The cinematic quality of the piece is achieved primarily through additive color blending (py5.blend_mode(py5.ADD)). By rendering semi-transparent lines against a near-black background, overlapping connections naturally accumulate brightness, creating intense glowing hot-spots where the network is most dense.The entire structure slowly rotates on multiple axes, revealing the depth of the 3D space. The lines themselves are not statically colored; their hue and opacity shift dynamically based on the distance between the connected nodes and the overall elapsed time. This produces a fluid, bioluminescent aesthetic where the web appears to pulse and breathe as it reorganizes itself.Code and Technical BreakdownThe foundation of the sketch is a simple Node class that stores a base 3D coordinate. In the setup phase, 300 of these nodes are randomly distributed within a 3D volume.During the draw loop, we don't just move these coordinates linearly. Instead, we use 3D OpenSimplex noise to organically displace each node from its base position.
t = py5.frame_count * 0.05
# Calculate current positions based on noise
current_positions = []
for node in nodes:
nx = py5.os_noise(node.base_x * 0.01, t * 0.2) * 400 - 200
ny = py5.os_noise(node.base_y * 0.01 + 100, t * 0.2) * 400 - 200
nz = py5.os_noise(node.base_z * 0.01 + 200, t * 0.2) * 400 - 200
current_positions.append((node.base_x + nx, node.base_y + ny, node.base_z + nz))By feeding the node's base coordinates and the current time t into py5.os_noise, we ensure that each node follows a smooth, continuous, and unique path that still feels physically connected to the space around it.The most computationally intensive part of the sketch is determining which nodes should be connected. Because any node could potentially connect to any other node, we must perform an $O(N^2)$ distance check.
# Connect nearby nodes
max_dist = 250
for i in range(len(current_positions)):
p1 = current_positions[i]
# Draw the node itself
py5.stroke(200, 80, 100, 80)
py5.point(*p1)
for j in range(i + 1, len(current_positions)):
p2 = current_positions[j]
d = py5.dist(*p1, *p2)
if d < max_dist:
# Color and alpha based on distance
alpha = py5.remap(d, 0, max_dist, 100, 0)
hue = (200 + d * 0.5 + t * 10) % 360
py5.stroke(hue, 90, 100, alpha)
py5.line(*p1, *p2)To optimize this, the inner loop starts at i + 1. This prevents us from checking the distance between the same two points twice (or checking a point against itself), effectively cutting the number of calculations in half.When a distance d is found to be less than our max_dist threshold, we calculate a dynamic alpha value using py5.remap(). As the nodes drift further apart, the line connecting them smoothly fades to zero opacity before breaking entirely. The hue is also tied to the distance and time, giving shorter connections a slightly different color profile than longer ones, adding immense visual depth to the web.
