Skip to content

New Feature: Implicit Surface#4640

Open
BillyLjm wants to merge 6 commits intoManimCommunity:mainfrom
BillyLjm:ImplicitSurface
Open

New Feature: Implicit Surface#4640
BillyLjm wants to merge 6 commits intoManimCommunity:mainfrom
BillyLjm:ImplicitSurface

Conversation

@BillyLjm
Copy link
Copy Markdown

@BillyLjm BillyLjm commented Mar 15, 2026

Overview: What does this pull request change?

Motivation and Explanation: Why and how do your changes improve the library?

New ImplicitSurface Class

This adds a new ImplicitSurface class to plot surfaces specified by implicit equations of f(x,y,z)=0.
This allows plotting of complex surfaces like gyroids which are otherwise difficult to specify via parametric equations.

Example: Gyroid ImplicitGyroidDemo_ManimCE_v0 20 1
from manim import *

class ImplicitGyroidDemo(ThreeDScene):
    def construct(self):
        axes = ThreeDAxes()
        gyroid = ImplicitSurface(
            lambda x, y, z: np.cos(x) * np.sin(y) + np.cos(y) * np.sin(z) + np.cos(z) * np.sin(x),
            x_range=(-np.pi, np.pi),
            y_range=(-np.pi, np.pi),
            z_range=(-np.pi, np.pi),
            checkerboard_colors=False
        )
        self.set_camera_orientation(phi=75 * DEGREES, theta=30 * DEGREES)
        self.add(axes, gyroid)
Example: Sphere ImplicitSphereDemo_ManimCE_v0 20 1
from manim import *

class ImplicitSphereDemo(ThreeDScene):
    def construct(self):
        axes = ThreeDAxes()
        sphere = ImplicitSurface(
            lambda x, y, z: x**2 + y**2 + z**2 - 1,
            x_range=(-1.5, 1.5),
            y_range=(-1.5, 1.5),
            z_range=(-1.5, 1.5),
            checkerboard_colors=False
        )
        self.set_camera_orientation(phi=75 * DEGREES, theta=30 * DEGREES)
        self.add(axes, sphere)

Checkerboard Coloring Fix

This also fixes an existing bug with checkerboard coloring of Surface which was discovered during refactoring.

After Fix ParaSphereDemo_ManimCE_v0 20 1
Before Fix og_ParaSphereDemo_ManimCE_v0 20 1
Code for reproducing the problem
from manim import *

class ParaSphereDemo(ThreeDScene):
    def construct(self):
        axes = ThreeDAxes()
        sphere = Surface(
            lambda u, v: axes.c2p(
                *np.array([
                    np.sin(u) * np.cos(v),
                    np.sin(u) * np.sin(v),
                    np.cos(u)
                ])
            ),
            u_range=(-np.pi, np.pi),
            v_range=(-np.pi, np.pi),
            checkerboard_colors=False
        )
        self.set_camera_orientation(phi=75 * DEGREES, theta=30 * DEGREES)
        self.add(axes, sphere)

Misc Housekeeping

  • This also refactors the Surface class since it shares common methods with the new ImplicitSurface, keeping things tidy.
  • This also removes ThreeDVMobject which is deprecated with the refactoring.
  • Added a test for the new ImplicitSurface and regenerated the tests associated with Surface

Links to added or changed documentation pages

Further Information and Comments

This uses the existing isosurface package that is already being used in manim.

Reviewer Checklist

  • The PR title is descriptive enough for the changelog, and the PR is labeled correctly
  • If applicable: newly added non-private functions and classes have a docstring including a short summary and a PARAMETERS section
  • If applicable: newly added functions and classes are tested

@BillyLjm BillyLjm changed the title Implicit surface New Feature: Implicit Surface Mar 15, 2026
@BillyLjm BillyLjm force-pushed the ImplicitSurface branch 4 times, most recently from 5f6f940 to 48a6d08 Compare March 15, 2026 09:09
Copy link
Copy Markdown
Member

@behackl behackl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi! Thanks for the nice refactor, I generally like this cleaned up version quite a bit. There are some things I'd need you to take a second look at though:

  • You have implemented the new surface using the ConvertToOpenGL metaclass meaning that when users run this with the opengl renderer, some of the mobject's inheritance trees get swapped (its super ugly and somewhat temporary). However, when constructing there are at least two places where you use plain VMobjects or a VGroup; doing that breaks this mechanism.
    • You can use self.get_group_class() instead of VGroup to make the grouping renderer-independent,
    • and in the other place you would have to do something like VMobject if config.renderer == "cairo" else OpenGLVMobject, given that you have replaced the ThreeDVMobject which was able to switch to OpenGL-logic itself.
  • except Exception isn't great, and it would be better to at least re-raise the context of the last exception, or just actually catch expected exceptions, as far as possible.

Again, thank you very much for your effort!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Surface has incorrect checkerboard coloring Feature Request: Add ImplicitSurface for visualizing f(x, y, z) = 0

2 participants