
    lj                       d dl mZ d dlZd dlZd dlZd dlZd dlmZ d dlm	Z	m
Z
mZ d dlZd dlZd dlmZ d dlmZ d dlmZ d dlmZmZ d d	lmZmZ d d
lmZ d dlmZmZ d dlm Z  d dl!m"Z" d dl#m$Z$ d dl%m&Z& ddl'T ddl(m)Z) ddl*m+Z+ ddl,m-Z- ddl.m/Z/m0Z0m1Z1m2Z2m3Z3 ddl4m5Z5m6Z6 ddl7m8Z8m9Z9 e	r@d dl:m;Z; d dlmZ d dl<m=Z= d dl>m?Z?m@Z@ d dlAmBZB d dlmCZCmDZDmEZEmFZFmGZG d dlHmIZI d d lJmKZK dd!lLmMZM d"d#gZN G d$ d"e          ZO G d% d#          ZPdS )&    )annotationsN)cached_property)TYPE_CHECKINGAnySelf)Framebuffer)Image)override)configlogger)OpenGLMobjectOpenGLPoint)OpenGLVMobject)MatrixMNPoint3D)handle_caching_play)color_to_rgba)EndSceneEarlyException)straight_path   )*)SceneFileWriter)opengl)clip)angle_of_vectorquaternion_from_angle_axisquaternion_multrotation_matrix_transpose)rotation_matrix_transpose_from_quaternion   )MeshShader)%render_opengl_vectorized_mobject_fill'render_opengl_vectorized_mobject_stroke)Iterable)r   )	Animation)Mobject_AnimationBuilder)Scene)	FloatRGBAPathFuncTypePoint3DLikeRGBAPixelArrayVector3DLike)ParsableManimColor)FlattenedMatrix4x4WindowOpenGLCameraOpenGLRendererc            	      T    e Zd ZdZdddddde dz  edz  df	dE fdZdFdZdGdZedHd            Z	edId!            Z
dJd"ZdKd#ZdJd$ZeedfdLd)            Z	 	 	 dMdNd.ZdOd/ZdPd0ZdQd1ZdRd3ZdSd5ZdTd7ZdUd9ZdFd:ZdVd;ZdVd<ZdVd=Ze e            fdW fdD            Z xZS )Xr3   a  
    An OpenGL-based camera for 3D scene rendering.


    Attributes
    ----------
    frame_shape : tuple[float, float]
        The width and height of the camera frame.
    center_point : np.ndarray
        The center point of the camera in 3D space.
    euler_angles : np.ndarray
        The Euler angles (theta, phi, gamma) representing the camera's orientation.
    focal_distance : float
        The focal distance of the camera.
    light_source_position : np.ndarray
        The position of the light source in 3D space.
    orthographic : bool
        Whether the camera uses orthographic projection instead of perspective.
    minimum_polar_angle : float
        The minimum polar angle for camera rotation.
    maximum_polar_angle : float
        The maximum polar angle for camera rotation.
    inverse_rotation_matrix : np.ndarray
        The inverse rotation matrix of the camera.
    Ng       @Fr   frame_shapetuple[float, float] | Nonecenter_pointPoint3DLike | Noneeuler_anglesfocal_distancefloatlight_source_positionorthographicboolminimum_polar_anglemaximum_polar_anglemodel_matrixMatrixMN | Nonekwargsr   returnNonec
                H   d| _         d| _        || _        || _        || _        | j        r3t          j                    | _        t          j        d          | _        n2t          j	                    | _        t          j	        d          | _        | t          d         t          d         f| _        n|| _        |t          | _        n t          j        |t                     | _        |	t          j        d	d	d
          }	|| _        t          j        |pg dt                     | _        t)          | j                  | _        |	| _         t/                      j        d|	dd|
 t          j        |pg dt                     }|| _        |                                  dS )u`  
        Initializes an OpenGLCamera instance.

        Parameters
        ----------
        frame_shape : tuple[float, float], optional
            The width and height of the camera frame. If not provided, defaults to
            the global manim config values `frame_width` and `frame_height`.
        center_point : Point3DLike, optional
            The center point of the camera in 3D space.
            If not provided, defaults to the origin (0, 0, 0).
        euler_angles : Point3DLike, optional
            The Euler angles (theta, phi, gamma) representing the camera's orientation.
            If not provided, defaults to (0, 0, 0) (i.e., no rotation).
        focal_distance : float, optional
            The focal distance of the camera. Default is 2.0.
        light_source_position : Point3DLike, optional
            The position of the light source in 3D space.
            If not provided, defaults to (-10, 10, 10).
        orthographic : bool, optional
            Whether the camera uses orthographic projection instead of perspective.
            Default is False (perspective).
        minimum_polar_angle : float, optional
            The minimum polar angle in radian for camera rotation. Default is -π/2,
            i.e. no restriction.
        maximum_polar_angle : float, optional
            The maximum polar angle in radian for camera rotation. Default is π/2,
            i.e. no restriction.
        model_matrix : MatrixMN, optional
            The initial model matrix [1]_ for the camera. If not provided,
            defaults to a translation matrix that positions the camera at (0, 0, 11).
        **kwargs : Any
            Additional keyword arguments passed to the OpenGLMobject constructor.

        References
        ----------
        .. [1] Wikipedia, "Camera matrix",
               https://en.wikipedia.org/wiki/Camera_matrix
        T<   F)format_Nframe_widthframe_heightdtyper      )i
   rO   )rB   should_render)r   r   r    )use_z_index
frame_rater>   r@   rA   r   orthographic_projection_matrixprojection_matrixunformatted_projection_matrixperspective_projection_matrixr   r6   ORIGINr8   npasarrayr<   translation_matrixr;   r=   r   light_sourcedefault_model_matrixsuper__init__r:   refresh_rotation_matrix)selfr6   r8   r:   r;   r=   r>   r@   rA   rB   rD   	__class__s              Y/home/agentuser/manim-venv/lib/python3.11/site-packages/manim/renderer/opengl_renderer.pyr_   zOpenGLCamera.__init___   s   j  (#6 #6  		%+%J%L%LD"171V2 2 2D.. &,%I%K%KD"171U2 2 2D.  &} 5vn7MND*D &D "
<u E E ED!4Q2>>L,%'Z!2]]]%&
 &
 &
" ((BCC$0!Rl%RR6RRRz,";)))5III%1$$&&&&&    r   c                4    | j         dddf         dd         S )z+Retrieve the camera's position in 3D space.N   rB   ra   s    rc   get_positionzOpenGLCamera.get_position   s!     A&rr**rd   positionr   c                2    || j         dddf         dd<   | S )z&Set the camera's position in 3D space.Nrf   rg   )ra   rj   s     rc   set_positionzOpenGLCamera.set_position   s%    &.!!!Q$#rd   r0   c                4    t          j        | j                  S )z+The formatted view matrix for shader input.)r   matrix_to_shader_inputunformatted_view_matrixrh   s    rc   formatted_view_matrixz"OpenGLCamera.formatted_view_matrix   s     ,T-IJJJrd   r   c                z    t          j        t          t          j                            | j                            S N)typingcastr   rY   linalginvrB   rh   s    rc   ro   z$OpenGLCamera.unformatted_view_matrix   s%    {8RY]]43D%E%EFFFrd   c                (   |                      t          t          t          t          t
          g           |                     | j        d         d           |                     | j        d         d           | 	                    | j
                   dS )zEInitialize the camera's points based on frame shape and center point.r   T)stretchr    N)
set_pointsrX   LEFTRIGHTDOWNUP	set_widthr6   
set_heightmove_tor8   rh   s    rc   init_pointszOpenGLCamera.init_points   sv    udB7888t'*D999(+T:::T&'''''rd   c                    |                                   |                     t          d                    |                     t          d                    |                     ddd           | j        | _        | S )zlReset the camera to its default state
        (config frame size, centered at origin, no rotation).
        rK   rJ   r   )centerr   r   r~   set_euler_anglesr]   rB   rh   s    rc   to_default_statezOpenGLCamera.to_default_state   sg     	~.///vm,---aA&&& 5rd   c           	        | j         \  }}}t          t          |t          d          t          |t          d          t          |t          d                    }t          t          j        |t                              | _	        dS )zGRefresh the camera's inverse rotation matrix based on its Euler angles.T)axis_normalizedrL   N)
r:   r   r   OUTr{   r   rY   rZ   r<   inverse_rotation_matrix)ra   thetaphigammaquats        rc   r`   z$OpenGLCamera.refresh_rotation_matrix   s     !-sE&uc4HHH&sE4HHH&uc4HHH
 

 (QJt5)))(
 (
$$$rd   angleaxisr.   about_pointc                   | j         }t          ||          }t          j        ||          }|d         }t          j        |d                   }	t          |dd                   t          dz  z   }
t          j        t          |	t                    t          |
t                              }t          t          j        ||j	                  dddf                   }| 
                    |
|	|           | S )a  
        Rotate the camera by a given angle around a specified axis.

        Parameters
        ----------
        angle : float
            The angle in radians to rotate the camera.
        axis : Vector3DLike, optional
            The axis around which to rotate the camera. Default is OUT (z-axis).
        about_point : Point3DLike, optional
            Ignored. For OpenGLCamera, rotation is always about the camera's center.

        **kwargs : Any
            Not used for OpenGLCamera. Passing additional keyword arguments
            has no effect.

        Returns
        -------
        Self
            The rotated camera instance. Returned for chaining.
        r   Nr   )r   r   rY   dotarccosr   PIr{   r   Tr   )ra   r   r   r   rD   
curr_rot_Tadded_rot_T	new_rot_TFzr   r   partial_rot_Tr   s                rc   rotatezOpenGLCamera.rotate   s    : 1
/t<<F:{33	q\i12A2''"q&0%c511%eS11
 
  }ik B B111a4 HIIeS%000rd   r   float | Noner   r   c                v    |
|| j         d<   |
|| j         d<   |
|| j         d<   |                                  | S )a  
        Set the camera's Euler angles [1]_ (theta, phi, gamma).

        Parameters
        ----------
        theta : float | None, optional
            The angle in radians for rotation around the OUT (z) axis.
            If None, the current theta value is retained.
        phi : float | None, optional
            The angle in radians for rotation around the RIGHT (x) axis.
            If None, the current phi value is retained.
        gamma : float | None, optional
            The angle in radians for rotation around the OUT (z) axis.
            If None, the current gamma value is retained.

        Returns
        -------
        Self
            The camera instance with updated Euler angles. Returned for chaining.

        See Also
        --------
        set_theta : Set the theta Euler angle.
        set_phi : Set the phi Euler angle.
        set_gamma : Set the gamma Euler angle.

        References
        ----------
        .. [1] Wikipedia, "Euler angles",
               https://en.wikipedia.org/wiki/Euler_angles
        Nr   r    r   r:   r`   )ra   r   r   r   s       rc   r   zOpenGLCamera.set_euler_angles  sT    J #(Da ?#&Da #(Da $$&&&rd   c                .    |                      |          S )z
        Set the camera's theta Euler angle (in radians).

        See Also
        --------
        set_euler_angles : Set all Euler angles at once.
        set_phi : Set the phi Euler angle.
        set_gamma : Set the gamma Euler angle.
        )r   r   )ra   r   s     rc   	set_thetazOpenGLCamera.set_thetaK       $$5$111rd   c                .    |                      |          S )z
        Set the camera's phi Euler angle (in radians).

        See Also
        --------
        set_euler_angles : Set all Euler angles at once.
        set_theta : Set the theta Euler angle.
        set_gamma : Set the gamma Euler angle.
        )r   r   )ra   r   s     rc   set_phizOpenGLCamera.set_phiW  s     $$$---rd   c                .    |                      |          S )z
        Set the camera's gamma Euler angle (in radians).

        See Also
        --------
        set_euler_angles : Set all Euler angles at once.
        set_theta : Set the theta Euler angle.
        set_phi : Set the phi Euler angle.
        )r   r   )ra   r   s     rc   	set_gammazOpenGLCamera.set_gammac  r   rd   dthetac                X    | j         dxx         |z  cc<   |                                  | S )z
        Increment the camera's theta Euler angle by a given amount (in radians).

        See Also
        --------
        set_euler_angles : Set all Euler angles at once.
        set_theta : Set the theta Euler angle.
        r   r   )ra   r   s     rc   increment_thetazOpenGLCamera.increment_thetao  :     	!&$$&&&rd   dphic                    | j         d         }t          ||z   t           dz  t          dz            }|| j         d<   |                                  | S )z
        Increment the camera's phi Euler angle by a given amount (in radians).

        See Also
        --------
        set_euler_angles : Set all Euler angles at once.
        set_phi : Set the phi Euler angle.
        r    r   )r:   r   r   r`   )ra   r   r   new_phis       rc   increment_phizOpenGLCamera.increment_phi|  sT     "sTzB37BF33&!$$&&&rd   dgammac                X    | j         dxx         |z  cc<   |                                  | S )z
        Increment the camera's gamma Euler angle by a given amount (in radians).

        See Also
        --------
        set_euler_angles : Set all Euler angles at once.
        set_gamma : Set the gamma Euler angle.
        r   r   )ra   r   s     rc   increment_gammazOpenGLCamera.increment_gamma  r   rd   tuple[float, float]c                R    |                                  |                                 fS )z2Retrieve the width and height of the camera frame.)	get_width
get_heightrh   s    rc   	get_shapezOpenGLCamera.get_shape  s!      $//"3"344rd   c                L    t          j        t          | j        d                   S )z
        Retrieve the center point of the camera in 3D space.

        Notes
        -----
        The center point is assumed to be the first point in the camera's points array.
        r   )rs   rt   r   pointsrh   s    rc   
get_centerzOpenGLCamera.get_center  s     {7DKN333rd   c                P    | j         }|d         |d         z
  }t          |          S )z'Retrieve the width of the camera frame.)r   r   )r    r   r   r<   ra   r   outs      rc   r   zOpenGLCamera.get_width  '    TlVD\)Szzrd   c                P    | j         }|d         |d         z
  }t          |          S )z(Retrieve the height of the camera frame.)   r    )rf   r    r   r   s      rc   r   zOpenGLCamera.get_height  r   rd   c                :    | j         |                                 z  S )z*Retrieve the focal distance of the camera.)r;   r   rh   s    rc   get_focal_distancezOpenGLCamera.get_focal_distance  s    "T__%6%666rd   mobject1r   mobject2alpha	path_funcr+   c                x    t                                          ||||           |                                  | S rr   )r^   interpolater`   )ra   r   r   r   r   rb   s        rc   r   zOpenGLCamera.interpolate  s:     	HhyAAA$$&&&rd   )r6   r7   r8   r9   r:   r9   r;   r<   r=   r9   r>   r?   r@   r<   rA   r<   rB   rC   rD   r   rE   rF   )rE   r   )rj   r   rE   r   )rE   r0   )rE   r   rE   rF   )rE   r   )
r   r<   r   r.   r   r9   rD   r   rE   r   )NNN)r   r   r   r   r   r   rE   r   )r   r<   rE   r   )r   r<   rE   r   )r   r<   rE   r   )r   r<   rE   r   )r   r<   rE   r   )r   r<   rE   r   )rE   r   )rE   r<   )
r   r   r   r   r   r<   r   r+   rE   r   ) __name__
__module____qualname____doc__r   r_   ri   rl   r   rp   ro   r   r   r`   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   __classcell__)rb   s   @rc   r3   r3   D   s        8 37+/+/ #48"&(S1W%'!V(,`' `' `' `' `' `' `'D+ + + +   
 K K K _K G G G _G( ( ( (	 	 	 	
 
 
 
  !*.	( ( ( ( X(X # "	, , , , ,\
2 
2 
2 
2
. 
. 
. 
.
2 
2 
2 
2         5 5 5 5	4 	4 	4 	4      7 7 7 7  #0-//	 	 	 	 	 	 X	 	 	 	 	rd   c                     e Zd ZdZedfdHd	ZdIdZdJdZdKdZdLdZ	dMdZ
dNdZdOdZdPdZedQd!            ZdPd"ZdRd'ZdId(ZdId)ZdJd*ZdSd,ZdTd/Z	 dUdVd5ZdWdXd9ZdYd;Z	 dZd[dAZed\dC            Zej        d]dF            ZdGS )^r4   a  
    An OpenGL-based renderer.

    Attributes
    ----------
    animation_elapsed_time : float
        The elapsed time of the current animation.
    animation_start_time : float
        The start time of the current animation.
    animations_hashes : list[str | None]
        List of animation hashes for caching.
    anti_alias_width : float
        The width used for anti-aliasing in pixel units.
    background_color : FloatRGBA
        The background color of the renderer.
    camera : OpenGLCamera
        The camera used for rendering.
    num_plays : float
        The number of animation plays executed.
    path_to_texture_id : dict[str, int]
        Mapping from texture file paths to OpenGL texture IDs.
    pressed_keys : set[int]
        Set of currently pressed key codes.
    skip_animations : bool
        Whether animations are currently being skipped.
    time : float
        The total elapsed time for the renderer.
    window : Window | None
        The window used for previewing, if any.
    Ffile_writer_classtype[SceneFileWriter]skip_animationsr?   rE   rF   c                   d| _         || _        || _        || _        d| _        d| _        d| _        g | _        d| _        t                      | _
        t                      | _        d| _        i | _        t          d         | _        dS )aQ  Initializes the OpenGLRenderer.

        Parameters
        ----------
        file_writer_class : type[SceneFileWriter], optional
            The class to use for writing scene files, by default SceneFileWriter.
        skip_animations : bool, optional
            Whether to skip animations during rendering, by default False.
        g      ?        r   Nbackground_color)anti_alias_width_file_writer_class_original_skipping_statusr   animation_start_timeanimation_elapsed_timetimeanimations_hashes	num_playsr3   camerasetpressed_keyswindowpath_to_texture_idr   r   )ra   r   r   s      rc   r_   zOpenGLRenderer.__init__  s     !$"3)8&.$'!&)#	35"nn&)ee%)24 &'9 :rd   scener)   c                *   g | _         |                     | |j        j                  | _        || _        t          d         | _        |                                 rFddl	m
}  ||           | _        | j        j        | _        | j                                        | _        n	 t!          j        d          | _        n+# t$          $ r t!          j        dd          | _        Y nw xY w|                     | j        d          | _        | j                                         | j                            t           j                   t          d	         | j        _        t           j        t           j        t           j        t           j        f| j        _        d
S )aW  
        Initializes the OpenGL rendering context and related resources
        for the given scene.

        Set up:
        - the file writer
        - the background color
        - the OpenGL context
        - the window (if needed)

        Parameters
        ----------
        scene : Scene
            The scene to be rendered
        r   r    r1   T)
standaloneegl)r   backendr   enable_wireframeN)partial_movie_filesr   rb   r   file_writerr   r   r   should_create_windowopengl_renderer_windowr2   r   ctxcontextdetect_framebufferframe_buffer_objectmodernglcreate_context	Exceptionget_frame_buffer_objectuseenableBLEND	wireframe	SRC_ALPHAONE_MINUS_SRC_ALPHAONE
blend_func)ra   r   r2   s      rc   
init_scenezOpenGLRenderer.init_scene  s{     68 ,0,C,CO$-
 -
 
 &'9 :$$&& 	+666666 &,,DK;?DL'+|'F'F'H'HD$$'6$GGG   '6#!     
 (,'C'CDLRS'T'TD$$((***HN+++!'(:!;(LL	#
s   !B< <%C$#C$c                    t           d         rt          j        d           dS t           d         o7t           d          o)t           d          ot           d          ot           d          S )	z
        Determine whether a window should be created for rendering
        based on the current configuration.

        Notes
        -----
        A windows is always created if the 'force_window' configuration is enabled.
        force_windowz}'--force_window' is enabled, this is intended for debugging purposes and may impact performance if used when outputting filesTpreviewsave_last_frameformatwrite_to_moviedry_run)r   r   warningrh   s    rc   r   z#OpenGLRenderer.should_create_window7  s     .! 	NK   49 &,--&8$$& +,,& 9%%	
rd   tuple[int, int] | Nonec                L    t          | dd          }|dS |j        \  }}}}||fS )a  
        Retrieve the pixel dimensions of the current frame buffer object (2D).

        Returns
        -------
        width : int
            The width of the frame buffer in pixels.
        height : int
            The height of the frame buffer in pixels.
        r   N)getattrviewport)ra   frame_buffer_pixel_widthpixel_heights        rc   get_pixel_shapezOpenGLRenderer.get_pixel_shapeN  s>     ,349NPT+U+U4*6*?'1k<L((rd   r   r3   c                8   |                                  }|d}t          |          |\  }}|                                \  }}| j        ||z  z  }|j        }	|j                                        }
t          j        |	|
          }
|                                |t          |
                                          t          t          j        |	          j                                                  t          |
          |                                d| _        dS )a  
        Update the perspective-related uniform variables used in the
        OpenGL renderer based on the current camera settings.

        Parameters
        ----------
        camera : OpenGLCamera
            The camera object from which to extract perspective and lighting information.

        Raises
        ------
        ValueError
            If the renderer's pixel shape is not available.
        Nz9Pixel shape is None, cannot refresh perspective uniforms.)r6   r   camera_centercamera_rotationr=   r;   )r  
ValueErrorr   r   r   r\   get_locationrY   r   tupler   arrayr   flattenr   perspective_uniforms)ra   r   pixel_shapemsgr  r  rJ   rK   r   rotation	light_poss              rc   refresh_perspective_uniformsz+OpenGLRenderer.refresh_perspective_uniforms_  s    **,,MCS//!$/!\$*$4$4$6$6!\  0L<4OP1#0==??	F8Y//	 "++-- 0"6#4#4#6#677$RXh%7%7%9%A%A%C%CDD%*9%5%5$7799%
 %
!!!rd   mobjectOpenGLMobject | OpenGLVMobjectc                   t          |t                    r:t          d         rt          | |           t          d         rt	          | |           |                                }|D ]}}|j        }t          | j        |t          |          nd          }|j
                                        D ]\  }}|                     t          |                    }|j        |         }	t          |	t          j        t          j        f          s!dt#          |	           }
t%          |
          ||	_        t)          j        |j                                        | j                                                  D ]L\  }}t1          j        t4                    5  |                    ||           ddd           n# 1 swxY w Y   M	 t9          j        d| j        j                  }|                    d|j                    |                    d|j!                   n# t4          $ r Y nw xY w|j"        r%| j        #                    t          j$                   n$| j        %                    t          j$                   |j&        }tO          ||j(        |tS          j*        |          nd|j"        |j+        	          }|,                    |            |-                                 dS )
a  
        Render an OpenGL mobject (either OpenGLMobject or OpenGLVMobject)
        using the appropriate shaders and rendering pipeline.

        Parameters
        ----------
        mobject : OpenGLMobject | OpenGLVMobject
            The mobject to render. Must be an instance of OpenGLMobject or OpenGLVMobject.

        Raises
        ------
        TypeError
            If a shader texture is not a moderngl.Uniform or moderngl.UniformBlock.
        use_projection_fill_shadersuse_projection_stroke_shadersN)r   namez&Shader texture must be a uniform, got r3   u_view_matrixu_projection_matrix)indicesuse_depth_test	primitive).
isinstancer   r   r#   r$   get_shader_wrapper_listshader_folderr"   r   strtexture_pathsitemsget_texture_idshader_programr   UniformUniformBlocktype	TypeErrorvalueitchainuniformsr  
contextlibsuppressKeyErrorset_uniformrs   rt   r   r   rp   rU   
depth_testr   
DEPTH_TESTdisablevert_indicesr!   	vert_datarY   rZ   render_primitiveset_uniformsrender)ra   r  shader_wrapper_listshader_wrapperfoldershaderr"  pathtidshader_texturer  r4  camr?  meshs                  rc   render_mobjectzOpenGLRenderer.render_mobject  s=    g~.. 	G34 E5dGDDD56 G7gFFF%==??1 3	 3	N#1F&:L3v;;;RV  F
 -:@@BB 
+ 
+
d))#d))44!'!6t!<!"X%5x7L$M  ) XnAUAUWW  $C..('*$$  "x'--//)//11    4 4e  (22 4 4&&tU3334 4 4 4 4 4 4 4 4 4 4 4 4 4 4 k.$*2CDD""?C4MNNN""#8#:OPPPP    ( :##H$78888$$X%8999 *6L(4@4L
<000RV-8!2  D d###KKMMMMg3	 3	s%   F77F;>F;AH
H'&H'rH  r+  intc                X    || j         v r| j         |         n|                     |          S )a  
        Retrieves the OpenGL texture ID associated with the given image file path.

        Automatically creates a new texture it it has not been loaded before.

        Parameters
        ----------
        path : str
            The file path to the texture image.

        Returns
        -------
        int
            The OpenGL texture ID corresponding to the given path.
        )r   _create_texture)ra   rH  s     rc   r.  zOpenGLRenderer.get_texture_id  s8    $ t... #D))%%d++	
rd   
image_pathc                   t          j        |          5 }t          | j                  }|j        dk    rd}d}n|                    d          }d}d}| j                            |j        ||	                                          }ddd           n# 1 swxY w Y   d|_
        d|_        t          j        t          j        f|_        ||_        |                    |	           || j        |<   |S )
a  
        Create an OpenGL texture from the given image file path, get its texture ID,
        and store it in `self.path_to_texture_id[image_path]`.

        Parameters
        ----------
        image_path : str
            The file path to the image to be loaded as a texture.

        Returns
        -------
        int
            The texture ID assigned to the newly created texture.
        Lr    RRR1RGBAr   )size
componentsdataNF)location)r	   openlenr   modeconvertr   texturerV  tobytesrepeat_xrepeat_yr   NEARESTfilterswizzler   )ra   rQ  imgrI  rW  rd  r^  s          rc   rP  zOpenGLRenderer._create_texture  s,    Z
## 	sd-..C x3
  kk&))
 l**X%[[]] +  G	 	 	 	 	 	 	 	 	 	 	 	 	 	 	$ ! "*H,<=!S!!!.1
+
s   A2BBBc                   | j         j        d         j        rd| _        t          j        dk    r| j        t          j        k     rd| _        t          j        dk    r*| j        t          j        k    rd| _        t                      dS dS )a^  
        Check and update the skipping status for the current animation
        (self.skip_animations flag) based on the configuration settings.

        Parameters
        ----------
        None

        Raises
        ------
        EndSceneEarlyException
            If the number of played animations exceeds the configured upper bound.
        Tr   N)r   sectionsr   r   from_animation_numberr   upto_animation_numberr   rh   s    rc   update_skipping_statusz%OpenGLRenderer.update_skipping_status  s     $R(8 	(#'D (1,,!===#'D (A--!===#'D (***	 .-==rd   
animations'Animation | Mobject | _AnimationBuilderrD   r   c                ,   t          j                     | _        | j                            | j                     |j        |i | |                                 |                                r|                     |           | j        s;| j        	                    | t          t          j        |j        z                       | j        b| j                                         t          j                     | j        z
  |j        k     r%	 t          j                     | j        z
  |j        k     %|j        | _        n|                                 | j                            | j                    | xj         |j        z  c_         | xj        dz  c_        dS )aj  
        Plays the given animations or mobjects in the specified scene.

        "Playing" here refers to the process of compiling animation data,
        beginning the animations, updating frames, and finalizing the animation
        in the context of the renderer.

        Parameters
        ----------
        scene Scene
            The scene in which to play the animations.
        *animations Animation | Mobject | _AnimationBuilder
            The animations, mobjects, or animation builders to play.
        **kwargs Any
            Additional keyword arguments to pass to the animation compilation.
        )
num_framesNr    )r   r   r   begin_animationr   compile_animation_databegin_animations!is_current_animation_frozen_frameupdate_framewrite_framerN  r   rS   durationr   swap_buffersr   play_internalend_animationr   )ra   r   rl  rD   s       rc   playzOpenGLRenderer.play/  s   0 %)IKK!((T-A)ABBB$$j;F;;;   2244 	"e$$$'  ,,S):U^)K%L%L -    {&((***ikkD$==NN ikkD$==NN*/.D'' !!!&&4+?'?@@@		U^#		!rd   c                r     | j         j        | j          | j        dS | j                                         dS )z
        Clears the current frame buffer and updates the display window
        accordingly.

        The screen is cleared using the background color specified
        in the renderer.
        N)r   clearr   r   rw  rh   s    rc   clear_screenzOpenGLRenderer.clear_screena  sA     	' &(=>>;F  """""rd   frame_offsetr<   moving_mobjectslist[Mobject]c                F   |                      |           | j        rdS | j                            |            | j        _| j                                         | j        |k     r=|                      |           | j                                         | j        |k     9dS dS dS )a  
        Renders a single frame of the given scene using OpenGL.

        Parameters
        ----------
        scene : Scene
            The scene to render.
        frame_offset : float
            The time offset for the current frame in seconds. If no window is present,
            this parameter is ignored, and a frame is a true snapshot of
            the scene at the current time.
        moving_mobjects : list[Mobject]
            List of mobjects that are currently moving and need to be updated.
            Not used at all, kept for compatibility with other renderers.

        Notes
        -----
        - Updates the frame for the scene.
        - If animations are skipped, the method returns early.
        - Writes the current frame using the file writer.
        - If a window is present, swaps buffers and continues
          updating frames until the animation elapsed time reaches the frame offset.
        N)rt  r   r   ru  r   rw  r   )ra   r   r~  r  s       rc   rC  zOpenGLRenderer.rendern  s    4 	%    	F$$T***;"K$$&&&-<<!!%(((((*** -<<<< #"<<rd   c                    | j         j        | j          t          j        d|j                  }|                     |           |j        D ]4}|j        s
t          j        d|          }| 	                    |           5|j
        D ]B}|                                D ]+}|                    |            |                                 ,Ct          j                    | j        z
  | _        dS )aE  
        Update and render the current frame for the given scene.

        Performs the following steps:
        1. Clear the frame buffer with the background color.
        2. Refresh camera perspective uniforms for rendering.
        3. Iterate through all mobjects in the scene, rendering those marked for display.
        4. Iterate through all mesh objects in the scene, setting their uniforms and rendering them.
        5. Update the elapsed animation time.

        Parameters
        ----------
        scene : Scene
            The scene to render the frame for.
        r3   r  N)r   r|  r   rs   rt   r   r  mobjectsrP   rM  meshes
get_meshesrB  rC  r   r   r   )ra   r   rK  r  mobjobjrL  s          rc   rt  zOpenGLRenderer.update_frame  s      	' &(=>> k.%,77))#...~ 	& 	&G(  ;?IID%%%%< 	 	C((  !!$''' '+ikkD4M&M###rd   c                \   | j         dk    r| j                                         n#| j         dk    rt          j        rdt          _        |                                 rOdt          _        |                     |           | j                            | 	                                           dS dS )aJ  
        Handle the finalization process after a scene has finished rendering.

        Performs the following actions:
        - If any plays (animations) have occurred, finalizes the file writing process.
        - If no plays have occurred but movie writing is enabled, disables
          movie writing to avoid creating an empty movie file.
        - If the configuration requires saving the last frame,
          updates and saves the final image of the scene.

        Parameters
        ----------
        scene : Scene
            The scene that has finished rendering.
        r   FTN)
r   r   finishr   r  should_save_last_framer  rt  
save_image	get_image)ra   r   s     rc   scene_finishedzOpenGLRenderer.scene_finished  s    $ >A##%%%%^q  V%: $)F!&&(( 	:%)F"e$$$''(8(899999	: 	:rd   c                R    t           d         rdS | j        j        rdS | j        dk    S )a2  
        Determine whether the last frame of the scene should be saved,
        i.e. if one of the following conditions is met:
        - The configuration option 'save_last_frame' is enabled.
        - The scene is not in interactive mode.
        - This is the first play (i.e., num_plays == 0).
        r  TFr   )r   r   interactive_moder   rh   s    rc   r  z%OpenGLRenderer.should_save_last_frame  s6     #$ 	4:& 	5~""rd   Image.Imagec           	         |                                  }|                                 }|d}t          |          t          j        d||dddd          }|S )a  
        Get the current OpenGL frame buffer as a PIL Image.

        Returns
        -------
        Image.Image
            The image representation of the current frame buffer.

        Raises
        ------
        ValueError
            If the pixel shape cannot be determined.

        Notes
        -----
        The image is constructed from raw RGBA buffer data, with the
        origin at the bottom-left.
        Nz&Pixel shape is None, cannot get image.rU  rawr   rg  ) get_raw_frame_buffer_object_datar  r  r	   	frombytes)ra   raw_buffer_datar  r  images        rc   r  zOpenGLRenderer.get_image  sj    & ??AA**,,:CS//!	
 	
 rd   static_mobjectsIterable[Mobject]c                    d S rr   rQ   )ra   r   r  s      rc   save_static_frame_dataz%OpenGLRenderer.save_static_frame_data  s	     	rd   r   r   moderngl.Contextsamplesr   c                    t           d         }t           d         }d}|                    |                    ||f||          |                    ||f|                    S )a  
        Creates and returns a framebuffer object configured with color
        and depth attachments.

        Parameters
        ----------
        context : moderngl.Context
            The ModernGL context used to create the framebuffer and
            its attachments.
        samples : int, optional
            The number of samples for multisample anti-aliasing (MSAA)[1]_.
            Default is 0 (no MSAA).

        Returns
        -------
        Framebuffer
            A framebuffer object with a color texture attachment and
            a depth renderbuffer attachment, both sized according to
            the current configuration's pixel width and height.

        Notes
        -----
        Framebuffer's color attachment is supposed RGBA.
        Pixel dimensions are taken from the global config of Manim.

        References
        ----------
        .. [1] Wikipedia, "Multisample anti-aliasing",
               https://en.wikipedia.org/wiki/Multisample_anti-aliasing
        r  r  r   )rW  r  )r  )color_attachmentsdepth_attachment)r   framebufferr^  depth_renderbuffer)ra   r   r  r  r  num_channelss         rc   r   z&OpenGLRenderer.get_frame_buffer_object  s    B ]+n-""%ool+' .  
 %77l+ 8   # 

 

 
	
rd   f1rM   bytesc                X    d}| j                             | j         j        ||          }|S )a  
        Get the raw data from the current frame buffer object as bytes.

        This method reads the pixel data from the frame buffer object using the specified data type.
        The data is read with 4 color channels (typically RGBA).

        Args:
            dtype (str, optional): The data type to use when reading the buffer.
            Defaults to "f1" (i.e., float with 1 byte).

        Returns:
            bytes: The raw pixel data from the frame buffer object.
        r   )r	  rW  rM   )r   readr	  )ra   rM   r  rets       rc   r  z/OpenGLRenderer.get_raw_frame_buffer_object_data@  s<    * -22-6# 3 
 

 
rd   r-   c                   |                      d          }|                                 }|d}t          |          |d         |d         df}t          j        |d                              |          }t          j        |          }|S )	a}  
        Get the current frame buffer as a Numpy array of RGBA pixel values.

        Returns
        -------
        RGBAPixelArray
            A Numpy array of shape (height, width, 4) containing the
            RGBA pixel data of the current frame, with dtype uint8.

        Raises
        ------
        ValueError
            If the pixel shape cannot be determined.
        r  rL   Nz&Pixel shape is None, cannot get frame.r    r   r   uint8)r  r  r  rY   
frombufferreshapeflipud)ra   r  r  r  result_dimensionsnp_bufs         rc   	get_framezOpenGLRenderer.get_frame]  s      33$3??**,,:CS//!(^[^Q?s'222::;LMM6""rd   pxpyrelativetop_leftr   c                   |                                  }|.t          j        t          t	          j        g d                    S |\  }}t          d         }| j                                        }	|r dt	          j        ||z  ||z  dg          z  S ||z  }
|rdnd}t          j        t          |	|
t	          j        ||dz  z
  |||dz  z
  z  dg          z  z             S )	a  
        Converts pixel coordinates to space (scene) coordinates.

        top_left flag should be set to True when using a GUI framework
        where the (0,0) is at the top left: e.g. PySide6.

        Parameters
        ----------
        px : float
            The x-coordinate in pixel space.
        py : float
            The y-coordinate in pixel space.
        relative : bool, optional
            If True, returns coordinates relative to the frame (normalized to [-1, 1]).
            If False, returns absolute space coordinates. Default is False.
        top_left : bool, optional
            If True, treats the origin (0, 0) as the top-left corner of the pixel space.
            If False, treats the origin as the bottom-left. Default is False.

        Returns
        -------
        Point3D
            The corresponding coordinates in space as a NumPy array of shape (3,).

        Notes
        -----
        If the pixel shape is not available, returns the origin [0, 0, 0].
        N)r   r   r   rK   r   r   rg  r    r   )	r  rs   rt   r   rY   r  r   r   r   )ra   r  r  r  r  r  r  r  rK   frame_centerscaley_directions               rc   pixel_coords_to_space_coordsz+OpenGLRenderer.pixel_coords_to_space_coords{  s   > **,,;w(A(ABBB$/!\n-{--// 	Jrxk!123Da HIIII|+$+bb!{h{Q&\A=M8M)NPST 
 
 	
rd   r*   c                    | j         S )z3The background color of the renderer (RGBA format).)_background_colorrh   s    rc   r   zOpenGLRenderer.background_color  s     %%rd   r4  r/   c                0    t          |d          | _        d S )Ng      ?)r   r  )ra   r4  s     rc   r   zOpenGLRenderer.background_color  s    !.uc!:!:rd   N)r   r   r   r?   rE   rF   )r   r)   rE   rF   )rE   r?   )rE   r  )r   r3   rE   rF   )r  r  rE   rF   )rH  r+  rE   rN  )rQ  r+  rE   rN  r   )r   r)   rl  rm  rD   r   rE   rF   )r   r)   r~  r<   r  r  rE   rF   )rE   r  )r   r)   r  r  rE   rF   )r   )r   r  r  rN  rE   r   )r  )rM   r+  rE   r  )rE   r-   )FF)
r  r<   r  r<   r  r?   r  r?   rE   r   )rE   r*   )r4  r/   rE   rF   )r   r   r   r   r   r_   r   r   r  r  rM  r.  rP  rk  r   rz  r}  rC  rt  r  r  r  r  r   r  r  r  propertyr   setterrQ   rd   rc   r4   r4     sP        B 4C %; ; ; ; ;@0
 0
 0
 0
d
 
 
 
.) ) ) )"%
 %
 %
 %
NK K K KZ
 
 
 
,' ' ' 'R+ + + +: / / / /b# # # #%+ %+ %+ %+N%N %N %N %NN: : : :8# # # ## # # #J    9:.
 .
 .
 .
 .
`    :   > NS3
 3
 3
 3
 3
j & & & X& ; ; ; ; ; ;rd   )Q
__future__r   r8  	itertoolsr5  r   rs   	functoolsr   r   r   r   r   numpyrY   r   PILr	   typing_extensionsr
   manimr   r   #manim.mobject.opengl.opengl_mobjectr   r   .manim.mobject.opengl.opengl_vectorized_mobjectr   manim.typingr   r   manim.utils.cachingr   manim.utils.colorr   manim.utils.exceptionsr   manim.utils.pathsr   	constantsscene.scene_file_writerr   utilsr   utils.simple_functionsr   utils.space_opsr   r   r   r   r   rG  r!   r"   vectorized_mobject_renderingr#   r$   collections.abcr%   manim.animation.animationr&   manim.mobject.mobjectr'   r(   manim.scene.scener)   r*   r+   r,   r-   r.   manim.utils.color.corer/   manim.utils.openglr0   r   r2   __all__r3   r4   rQ   rd   rc   <module>r     s   " " " " " "           % % % % % % + + + + + + + + + +                        & & & & & &                        J I I I I I * * * * * * * * 3 3 3 3 3 3 + + + + + + 9 9 9 9 9 9 + + + + + +     5 5 5 5 5 5       ) ) ) ) ) )              !                     
  /((((((333333@@@@@@@@''''''              :99999555555...... +
,~ ~ ~ ~ ~= ~ ~ ~Br; r; r; r; r; r; r; r; r; r;rd   