Repository: ManimCommunity/manim
File: manim/scene/three_d_scene.py (Python)

Code before:
        ----------
        *mobjects : Mobject
            The Mobject(s) whose orientation must be fixed.

        **kwargs
            Some valid kwargs are
                use_static_center_func : bool
                center_func : function
        """
        if config.renderer != "opengl":
            self.add(*mobjects)
            self.renderer.camera.add_fixed_orientation_mobjects(*mobjects, **kwargs)
        else:

            def face_camera(mob: OpenGLMobject):
                def update_func(
                    m: OpenGLMobject,
                    copy: OpenGLMobject,
                    center: np.ndarray,
                ):
                    camera: OpenGLCamera = self.camera
                    theta, phi, _ = camera.euler_angles
                    theta -= PI / 2

                    m.become(
                        copy.copy()
                        .rotate(PI / 2)
                        .apply_matrix(
                            z_to_vector(spherical_to_cartesian([1, theta, phi])),
                        ),
                    ).move_to(center)

                copy, center = mob.copy(), mob.get_center()
                mob.fixed_orientation: bool = True
                return mob.add_updater(lambda m=mob: update_func(m, copy, center))

            for mob in mobjects:
                mob: OpenGLMobject
                mob.save_state()
                self.add(face_camera(mob))

    def add_fixed_in_frame_mobjects(self, *mobjects):
        """
        This method is used to prevent the rotation and movement
        of mobjects as the camera moves around. The mobject is
        essentially overlaid, and is not impacted by the camera's
        movement in any way.

        Parameters
        ----------
        *mobjects : Mobjects

Review comment (performance):
This would create a copy for each update right? I am wondering if there is a way to avoid it, as it seems expensive, for example can we just take the attributes we need from the copy and assign them rather than using become?

Code after:
        This method is used to prevent the rotation and tilting
        of mobjects as the camera moves around. The mobject can
        still move in the x,y,z directions, but will always be
        at the angle (relative to the camera) that it was at
        when it was passed through this method.)

        Parameters
        ----------
        *mobjects : Mobject
            The Mobject(s) whose orientation must be fixed.

        **kwargs
            Some valid kwargs are
                use_static_center_func : bool
                center_func : function
        """
        if config.renderer != "opengl":
            self.add(*mobjects)
            self.renderer.camera.add_fixed_orientation_mobjects(*mobjects, **kwargs)
        else:
            for mob in mobjects:
                mob: OpenGLMobject
                mob.fix_orientation()
                self.add(mob)

    def add_fixed_in_frame_mobjects(self, *mobjects):
        """
        This method is used to prevent the rotation and movement
        of mobjects as the camera moves around. The mobject is
        essentially overlaid, and is not impacted by the camera's
        movement in any way.

        Parameters
        ----------
        *mobjects : Mobjects
            The Mobjects whose orientation must be fixed.
        """
        if config.renderer != "opengl":
            self.add(*mobjects)
            self.camera: ThreeDCamera
            self.camera.add_fixed_in_frame_mobjects(*mobjects)
        else:
            for mob in mobjects:
                mob: OpenGLMobject
                mob.fix_in_frame()
                self.add(mob)

    def remove_fixed_orientation_mobjects(self, *mobjects):
        """
        This method "unfixes" the orientation of the mobjects
        passed, meaning they will no longer be at the same angle