I have created a 3D animation with a perspective projection of white circles moving randomly in a fake 3D space projected on a 2D computer screen (GIF 1).
Since I need to keep the same number of visible circles, every time a circle disappears from the frame, I have to create a new visible one within the frame. To do so, I have written this piece of code:
First I created initial coordinates and the two angles of movements (spherical coordinates):
for circle in circles: circle.position.xy = np.random.uniform(-25, 25, size=2) z = np.random.uniform(near_z, far_z) circle.position.z = z circle.position.x *= z/-50 circle.position.y *= z/-50 circle.theta_deg = np.random.rand(1) * 360 circle.phi_deg = np.random.rand(1) * 360 theta_rad = circle.theta_deg * np.pi / 180 phi_rad = circle.phi_deg* np.pi / 180 circle.dx = speed * np.sin(-phi_rad - theta_rad) / frameRate circle.dy = -speed * np.cos(phi_rad + theta_rad) / frameRate circle.dz = -speed * np.cos(theta_rad) / frameRate
Then, in the loop that plays the animation, and updates the position of each circle, I have put this condition following the same answer that was provided to the same kind of issue here:
max_dist = max(abs(circle.position.x),abs(circle.position.y)) limit_dist = 25 * abs((circle.position.z-near_z) / far_z) z_rel = np.random.uniform(near_z,far_z) if max_dist > limit_dist: circle.position.x = np.random.uniform(-25, 25) * z_rel/far_z circle.position.y = np.random.uniform(-25, 25) * z_rel/far_z
I got a weird result as shown in GIF 2
What is wrong with my condition and how can I detect a circle that disappears from the frame and recreate one inside the frame?
Following the suggestion of @Fabian N. (answer below), I have reset the z-coordinates along with the x and y coordinates as follows:
max_dist = max(abs(circle.position.x), abs(circle.position.y)) # Find maximum distance of a circle to the center of the view:
limit_dist = 25 * abs((circle.position.z-near_z) / far_z)
if circle.position.z <= near_z or max_dist > limit_dist:
z_rel = np.random.uniform(near_z,far_z)
circle.position.z = z_rel + near_z
circle.position.x = np.random.uniform(-25, 25) * z_rel/far_z
circle.position.y = np.random.uniform(-25, 25) * z_rel/far_z
And I got this result: