Skip to content
Sample of Super-Ellipsoid Mesh

toxi_toxiclibs · SuperEllipsoid

Super-Ellipsoid Mesh

A super-ellipsoid is a 3D primitive that smoothly interpolates between a sphere, a box, and a pinched pillow via two shape parameters e1 (longitude exponent) and e2 (latitude exponent). The toxiclibs.geom.SuperEllipsoid class samples the implicit formula as a mesh of N×M vertices with computed face normals. Karsten used it as the headline example at the 2010 Processing Paris workshop and as the basis for the SuperShapeThread (SST) that drives his ProceduralTypography work. Generalizes: e1=e2=1 → sphere; e1, e2 large → box; e1<1, e2<1 → pinched astroid-like shape; e1=0.5, e2=1 → 'lemon'; e1=1, e2=0.5 → 'egg'. Famously appears in the original Macintosh 'S' icon (e1≈e2≈4).

Original: https://web.archive.org/web/2011/http://toxiclibs.org/2010/04/processing-paris-workshop/

▶ Try the live demo (JS port) ▶ Run reference.py via Pyodide 10 formulas have instant JS ports. The Pyodide path runs the actual Python in your browser — first load is ~6 MB, then instant.

Family
toxi_toxiclibs
Source
toxi_toxiclibs
Evolution
geometric
Render
shaded_mesh_3d
Complexity
low
Agents
0
Year
2010
Author
Heinrich Piening / Karsten Schmidt (toxi / postspectacular, 2010)

Math essence

Parametric: x(η, ω) = sign(cos(η)) * |cos(η)|^e1 * sign(cos(ω)) * |cos(ω)|^e2; y(η, ω) = sign(cos(η)) * |cos(η)|^e1 * sign(sin(ω)) * |sin(ω)|^e2; z(η, ω) = sign(sin(η)) * |sin(η)|^e1; for η ∈ [-π/2, π/2] (latitude) and ω ∈ [-π, π] (longitude). Mesh resolution M (longitude steps) × N (latitude steps). Per-vertex normal from analytical derivatives of the implicit form (or numerical finite differences).

Parameters

Name Type Default Range Description
e1 float 1 0.1–4 Longitude exponent (η-direction). Sphere=1, box=4.
e2 float 1 0.1–4 Latitude exponent (ω-direction). Sphere=1, box=4.
M int 64 8–256 Longitude resolution.
N int 32 4–128 Latitude resolution.
scale float 1 0.1–5 Mesh scale.
e1_speed float 0.5 -2–2 Animation rate of e1 (e.g. for morphing).
e2_speed float 0.3 -2–2 Animation rate of e2.
palette str iron — Shading palette.

Reference

First 60 lines of reference.py. Full source: library_external/toxi_toxiclibs/SuperEllipsoid/reference.py

"""SuperEllipsoid — parametric 3D primitive (sphere ↔ box morph).

A pure-numpy port of Karsten Schmidt's toxiclibs.geom.SuperEllipsoid
(2010). The implicit form uses two shape parameters (e1, e2) to morph
between a sphere, a box, a pillow, an astroid, and other shapes.

  x(η, ω) = sign(cos(η)) * |cos(η)|^e1 * sign(cos(ω)) * |cos(ω)|^e2
  y(η, ω) = sign(cos(η)) * |cos(η)|^e1 * sign(sin(ω)) * |sin(ω)|^e2
  z(η, ω) = sign(sin(η)) * |sin(η)|^e1

  η ∈ [-π/2, π/2]   (latitude)
  ω ∈ [-π, π]       (longitude)

  e1 = e2 = 1   →   sphere
  e1 = e2 = 4   →   box (rounded)
  e1 < 1, e2 < 1 → pinched / astroid
  e1 = 0.5, e2 = 1 → lemon
  e1 = 1, e2 = 0.5 → egg

This is the same parameterization used in Ken Perlin's 1980s
'Ken-ipercival' supershapes and the original Macintosh 'S' icon
(Susan Kare, 1984, e1 ≈ e2 ≈ 4).
"""
from __future__ import annotations

import numpy as np


def superellipsoid_points(e1, e2, M, N, scale=1.0):
    """Return (M*N, 3) vertex array for a super-ellipsoid."""
    omega = np.linspace(-np.pi, np.pi, M, endpoint=False)
    eta = np.linspace(-np.pi / 2, np.pi / 2, N)
    O, E = np.meshgrid(omega, eta, indexing='xy')
    # sign-preserving power: sign(x) * |x|^e
    def spow(x, e):
        return np.sign(x) * np.abs(x) ** e
    cx, sx = spow(np.cos(E), e1), spow(np.sin(E), e1)
    cox, sox = spow(np.cos(O), e2), spow(np.sin(O), e2)
    x = cx * cox
    y = cx * sox
    z = sx
    verts = np.stack([x.ravel(), y.ravel(), z.ravel()], axis=1) * scale
    return verts, O, E


def superellipsoid_faces(M, N):
    """Return triangulated face index list (M*N, 3) sized."""
    faces = []
    for j in range(N - 1):
        for i in range(M - 1):
            a = j * M + i
            b = j * M + (i + 1)
            c = (j + 1) * M + (i + 1)
            d = (j + 1) * M + i
            faces.append([a, b, c])
            faces.append([a, c, d])
    # Wrap the longitude seam
    for j in range(N - 1):
        a = j * M + (M - 1)
        b = j * M

Try running it locally

The reference implementation is self-contained Python with numpy. Install the package and run:

python library_external/toxi_toxiclibs/SuperEllipsoid/reference.py

Need help? See Learn for the standard environment setup, or Playground for an in-browser sketchbook.

More from toxi_toxiclibs

See all toxi_toxiclibs artworks →