-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Bug in handling of z_index #327
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Sorry to see this issue too late. I found the cause of this problem. It's not because I am fixing this bug, I will open a pull request after I finish it. Thank you for your feedback. The following are some relevant actions during testing (you can find log files and output videos on them): |
I have a little trouble fixing this bug. You can find a video of the results of my just experiment here: btw, I am about to start a new week of busy learning, so I may have to wait a week before trying to fix this bug again. And as for the problem you mentioned in this issue, you can just self.play(FadeIn(circle), FadeIn(square)) instead of: self.play(FadeIn(VGroup(circle, square))) |
@tony031218 , thanks for looking into this and for providing alternatives. Something tells me that we'll have to think long and hard about this one! |
Solve the problem in ManimCommunity/manim#327
Changing the library codes will cause inelegant repeat flag variables and introduce strange bugs. I think the easiest way is sorting the objects when add them into a VGroup. class SquareToCircle(Scene):
def construct(self):
circle = Circle().set_fill(RED, opacity=1)
square = Square(side_length=1.7).set_fill(BLUE, opacity=1)
square.z_index = circle.z_index - 1
self.play(FadeIn(VGroup(*sorted([circle, square],
key=lambda m: m.z_index))))
self.play(ApplyMethod(circle.shift, UP))
self.wait() If you want to add other elements to the group, you can use the following method: class GroupLayerTest(Scene):
def construct(self):
circle = Circle().set_fill(ORANGE, opacity=0.5)
square = Square().set_fill(BLUE, opacity=1)
circle2 = Circle().scale(2).set_fill(RED, opacity=1)
circle.z_index = 1
square.z_index = 0
circle2.z_index = -1
group = VGroup(*sorted([circle, square],
key=lambda m: m.z_index))
self.play(FadeIn(group))
group.add(circle2)
group.submobjects = sorted(group.submobjects,
key=lambda m : m.z_index)
self.play(FadeIn(circle2))
self.play(group.shift, UP)
self.wait() |
This kind of makes me wonder whether adding the z-index attribute was ever the right choice to begin with. After all each mobject actually has a z-coordinate, so we could just use But even that leaves ambiguity in how to render since you could do something like
and it doesn't answer the question as to how to render mobjects with the same z-coordinate at all. |
In my opinion, the best way to render the scene is to render objects according to the z coordinate. Objects with the same z coordinate should be rendered according to the order that they are added to the scene. |
A few things to consider:
|
I agree we should probably find a solution that uses the Z coordinate instead of a z index, or some other arbitrary ordering. For 3D scenes, we will have the problem of occlusion (which is already documented in other issues). Cairo can handle objects whose points have different Z coordinates just fine. What it cannot handle is one object occluding only part of some other object. But that's a Cairo limitation, not manim's. |
By changing diff --git a/manim/utils/family.py b/manim/utils/family.py
--- a/manim/utils/family.py
+++ b/manim/utils/family.py
@@ -28,6 +28,7 @@ def extract_mobject_family_members(
method = Mobject.family_members_with_points
else:
method = Mobject.get_family
+ extracted_mobjects = remove_list_redundancies(list(it.chain(*[method(m) for m in mobjects])))
if use_z_index:
- mobjects = sorted(mobjects, key=lambda m: m.z_index)
- return remove_list_redundancies(list(it.chain(*[method(m) for m in mobjects])))
+ return sorted(extracted_mobjects, key=lambda m: m.z_index)
+ return extracted_mobjects I get What is the drawback of reordering the list of extracted mobjects? The sorting is stable, i.e., doesn't change the order of mobjects with the same |
* sort all extracted mobjects w.r.t. z_index * add test for z_index (from #327) * more complex z_index test * black * propagate z_index from MathTex to TexSymbol
* toying around with a graph using networkx layouting * basic implementation and documentation of a class for undirected graphs * import graph module into global namespace * add graph module to documentation * poetry: add networkx as a dependency * remove some debug prints * sort all extracted mobjects w.r.t. z_index * add test for z_index (from #327) * more complex z_index test * black * improve imports * use z_index to have edges below vertices * add type hints * rename some tests to make space for graph tests * fix problem with manual positioning * add test * black * new animate syntax * document label_fill_color
Here's a Scene
And here's the output:
As you can see, the square comes on top of the circle at the end of the second animation. I was expecting the square to remain behind the circle throughout the video because of the line
square.z_index = circle.z_index - 1
. Is this intended behavior? Is this a known issue?FWIW, I think currently there are two different systems living in manim. First, the
Scene
andCamera
classes try to keep the mobjects in order, and then the order of rendering on screen is (or, used to be) taken from that order. But after the introduction ofz_index
in #122, all of that bookkeeping to try to maintain the order is unnecessary since at the last minute the mobjects are being sorted by theirz_index
. I believe it is the interaction of these two things that is causing the bug. We can perhaps take this opportunity to deprecate all of those bookkeeping operations and stick to the z_index.cc @tony031218 as author of #122
The text was updated successfully, but these errors were encountered: