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
Based on the code you posted I can only see two points of interest without actually running it
(could you add some glue code around the code you posted to make it runnable as a standalone example?)
sphere.position.z >= camera_z
which would translate for your code intocircle.position.z <= near_z
to actually detect spheres flying behind the cameraBoth can't really explain what's happening in your second gif...
On second thought: the jumping circles in gif 2 could just be circles that get instantly reset each frame because they aren't properly reset as their z-coordinate stays the same.
In the code that you've added, you are resetting the z parameter differently than the way you initialized it.
In the first part of your code, you use
while in the for loop you use
These do not seem to be equivalent. Perhaps you should use the same parameters for both.
You should also check the way that you update your x and y positions, especially your parameters dx and dy, as these may be getting so big that your circles fly out of the screen immediately