Repository: ManimCommunity/manim

Issue:
Rendering bug in 3D with OpenGL circles 
## Description of bug / unexpected behavior
<!-- Add a clear and concise description of the problem you encountered. -->

When rendering a line and a circle, the circle's 'corners' flash in and out.

What's interesting is that these corners flash in and out when the camera is rotating (first five seconds) but don't when the object itself is rotating. When the camera freezes, all the corners look correct, and then when the object crosses the XY plane (at about 0:08) all the corners look incorrect.

https://user-images.githubusercontent.com/1994318/112022480-95349480-8aef-11eb-8308-8f4a9dbd14e6.mp4

## Expected behavior
<!-- Add a clear and concise description of what you expected to happen. -->

No flashes, the circle does not appera to have corners, and the line appears to go through the circle.


## How to reproduce the issue
<!-- Provide a piece of code illustrating the undesired behavior. -->

<details><summary>Code for reproducing the problem</summary>

```py

from manim import *
from manim.opengl import *


class Foobar(Scene):
    def construct(self):
        frame = self.renderer.camera
        frame.set_euler_angles(
            theta=-30 * DEGREES,
            phi=70 * DEGREES,
        )

        line = OpenGLLine(2*LEFT, 2*RIGHT, color=WHITE, depth_test=True)
        circle = OpenGLCircle(fill_opacity=1, fill=RED, depth_test=True)
        circle.rotate(TAU/4, UP)
        self.add(line, circle)

        circle.add_updater(
            lambda x: frame.increment_theta(TAU/180)
        )

        self.wait(5)

        circle.clear_updaters()
        self.wait(2)
        self.play(Rotating(circle, UP, TAU/2, run_time=3))

```

</details>


## Additional media files
<!-- Paste in the files manim produced on rendering the code above. Note that GitHub doesn't allow posting videos, so you may need to convert it to a GIF or use the `-i` rendering option. -->

<details><summary>Images/GIFs</summary>

<!-- PASTE MEDIA HERE -->

</details>


## Logs
<details><summary>Terminal output</summary>
<!-- Add "-v DEBUG" when calling manim to generate more detailed logs -->

```
PASTE HERE OR PROVIDE LINK TO https://pastebin.com/ OR SIMILAR
```

<!-- Insert screenshots here (only when absolutely necessary, we prefer copy/pasted output!) -->

</details>


## System specifications

<details><summary>System Details</summary>

- OS: Ubuntu 18.04.5
- RAM:
- Python version (`python/py/python3 --version`):
- Installed modules (provide output from `pip list`):
```
PASTE HERE
```
</details>

<details><summary>LaTeX details</summary>

+ LaTeX distribution (e.g. TeX Live 2020):
+ Installed LaTeX packages:
<!-- output of `tlmgr list --only-installed` for TeX Live or a screenshot of the Packages page for MikTeX -->
</details>

<details><summary>FFMPEG</summary>

Output of `ffmpeg -version`:

```
PASTE HERE
```
</details>

## Additional comments
<!-- Add further context that you think might be relevant for this issue here. -->



Discussion:
If I disable depth_test for the circle, then the shape at the end is a filled octagon - not the octagon with little slits cut out. Huh.

Whether the line or the circle is updating the camera doesn't matter.

The flashing only happens when the circle is pointing directly out (TAU/4) - if it changes even slightly, like TAU/4 + 0.01, then the flashing doesn't happen (but it's still weird sometimes).

If I don't set the camera position (leaving it the default, where it looks down at the origin) the circle looks fine to start, but once it rotates itself, it has those spikes and slits again.
My current best guess is that this has something to do with the circle's normals - they're never updated and they always remain the OUT direction. That would explain all the behavior so far.

Resolving patch:
diff --git a/manim/mobject/types/opengl_vectorized_mobject.py b/manim/mobject/types/opengl_vectorized_mobject.py
--- a/manim/mobject/types/opengl_vectorized_mobject.py
+++ b/manim/mobject/types/opengl_vectorized_mobject.py
@@ -82,7 +82,7 @@ def __init__(
         flat_stroke=True,
         render_primitive=moderngl.TRIANGLES,
         triangulation_locked=False,
-        **kwargs
+        **kwargs,
     ):
         self.fill_color = fill_color
         self.fill_opacity = fill_opacity
@@ -880,7 +880,7 @@ def get_triangulation(self, normal_vector=None):
     def triggers_refreshed_triangulation(func):
         @wraps(func)
         def wrapper(self, *args, **kwargs):
-            old_points = self.get_points()
+            old_points = self.get_points().copy()
             func(self, *args, **kwargs)
             if not np.all(self.get_points() == old_points):
                 self.refresh_triangulation()
@@ -906,6 +906,11 @@ def apply_function(self, function, make_smooth=False, **kwargs):
             self.make_approximately_smooth()
         return self
 
+    @triggers_refreshed_triangulation
+    def apply_points_function(self, *args, **kwargs):
+        super().apply_points_function(*args, **kwargs)
+        return self
+
     @triggers_refreshed_triangulation
     def flip(self, *args, **kwargs):
         super().flip(*args, **kwargs)
@@ -1054,7 +1059,7 @@ def __init__(
         stroke_width=0,
         artificial_width=0.01,
         artificial_height=0.01,
-        **kwargs
+        **kwargs,
     ):
         self.artificial_width = artificial_width
         self.artificial_height = artificial_height


Test patch: