Search code examples
pythonanimationopengl3dpyglet

Draw new sphere in front of the camera in 3D animation


With the use of Python and OpenGL, I created an optic flow animation, where a camera moves towards spheres (the circles displayed in the GIF).

enter image description here

I tried to create two conditions within the loop that updates the camera position frame by frame, and plays the animation :

near_z = -0.05;
far_z = -50.0;
nSpheres = 40;

for nframes in range(200):
   camera_z -= .7  # the camera moves with a speed of .7 on the z-axis.

1 - The first condition says that when the camera reaches the far clip plane (far_z), get the camera back to the near clip plane again (near_z). As you can see in the GIF, it is working.

camera_z = np.where(camera_z <= far_z, near_z, camera_z)

2- The second condition says that when a camera passes a sphere, redraw a new sphere in front of the camera, that way I would maintain the same number of spheres in the animation. So Every time a sphere disappears from the frame, redraw one. For some reason, it is not working. I tried to figure out why, but I am obviously failing.

if sphere.position.z >= camera_z: # if the sphere is behind the camera, so the sphere is not visible

           sphere.position.z = np.random.uniform(camera_z,far_z) # define a new position for the sphere in front of the camera.

Thanks in advance for your help!!


Solution

  • near_z respectively far_z are no absolute coordinates. This are relative distances to the current z coordinate of the camera.

    So it has to be:

    sphere.position.z = np.random.uniform(camera_z+near_z, camera_z+far_z)
    

    But be aware, if the camera is "reset", by

    camera_z = np.where(camera_z <= far_z, near_z, camera_z)
    

    then suddenly all the spheres are out of the viewing frustum and clipped by the far plane. In this case you've to translate all the spheres by the distance from the near plane to the far plane. In this context near_z and far_z are "absoulte" coordinates (for a moment).

    e.g. (instead of camera_z = np.where(camera_z <= far_z, near_z, camera_z):

    if camera_z > far_z:
        offset_z = far_z - near_z
        camera_z -= offset_z
        for sphere in spheres:
            sphere.position.z -= offset_z