Fundamentals 10 min read

Create a 3D Lantern with Python: Step‑by‑Step Tutorial Using NumPy, Pillow, and WxGL

This tutorial shows how to build a rotating 3D lantern using Python, NumPy, Pillow, and the WxGL library, covering required materials, environment setup, code for constructing the cylindrical skeleton, applying the lantern paper, adding a propeller, lighting, and rendering the final animation.

Python Crawling & Data Mining
Python Crawling & Data Mining
Python Crawling & Data Mining
Create a 3D Lantern with Python: Step‑by‑Step Tutorial Using NumPy, Pillow, and WxGL

1 Introduction

The article presents a fun project to create a 3D lantern (a traditional Chinese lantern) using Python and 3D visualization techniques, suitable for programmers who want to apply their coding skills to artistic visualizations.

2 Materials

2.1 Lantern paper

You can use any image file as the lantern paper, optionally adding your own patterns or text.

2.2 Python environment and modules

A computer with Python installed and the following modules is required:

numpy

pillow

wxgl

Install them with:

pip install numpy
pip install pillow
pip install wxgl

NumPy and Pillow are common scientific‑computing and image‑processing libraries; WxGL is a 3‑D visualization library based on PyOpenGL with a wx backend.

3 Construction Process

The lantern can be built with about thirty lines of code, which can be executed interactively in the Python IDLE.

3.1 Import modules

import numpy as np
from PIL import Image
import wxgl.wxplot as plt

3.2 Open lantern paper image

fn = r'D:\temp\light0115\res\paper.png'
im = np.array(Image.open(fn)) / 255
im.shape  # (400, 942, 3)

The image is loaded as a NumPy array and normalized to the range 0‑1, matching WxGL’s interface requirements.

3.3 Create cylindrical skeleton

rows, cols, deep = im.shape
r = 1
h = 2 * np.pi * rows / cols
theta = np.linspace(0, 2*np.pi, cols)
x = r * np.cos(theta)
y = r * np.sin(theta)
z = np.linspace(0, h, rows)
xs = np.tile(x, (rows, 1))
ys = np.tile(y, (rows, 1))
zs = z.repeat(cols).reshape((rows, cols))

This builds a cylinder with radius 1 and height ≈2.668 units, representing the lantern’s “spine”.

3.4 Mesh skeleton with paper

plt.mesh(xs, ys, zs, im)
plt.show()

If the paper appears upside‑down, reverse the image direction:

plt.mesh(xs, ys, zs, im[::-1])
plt.show()

3.5 Create rotating propeller

theta = np.linspace(0, 2*np.pi, 18, endpoint=False)
x = r * np.cos(theta)
y = r * np.sin(theta)
# reshape to form six blades
x[2::3] = x[1::3]
x[1::3] = 0
y[2::3] = y[1::3]
y[1::3] = 0
z = np.ones(18) * h * 0.9
vs = np.stack((x, y, z), axis=1)
plt.surface(vs, color='#C03000', method='T', mode='FCBC', alpha=0.8)

3.6 Add lighting sphere and support line

plt.sphere((0, 0, h*0.4), 0.4, '#FFFFFF', slices=60, mode='FCBC')
plt.plot((0,0), (0,0), (0.4*h, 1.5*h), width=3.0, style='solid', cmap='hsv', caxis='z')

3.7 Rotate lantern

plt.show(rotation='h-')

The final animated lantern looks like this:

4 Full source code

# -*- coding: utf-8 -*-
import numpy as np
from PIL import Image
import wxgl.wxplot as plt

im = np.array(Image.open('res/paper.png')) / 255
rows, cols, deep = im.shape
r, h = 1, 2*np.pi*rows/cols
theta = np.linspace(0, 2*np.pi, cols)
x = r*np.cos(theta)
y = r*np.sin(theta)
z = np.linspace(0, h, rows)
xs = np.tile(x, (rows,1))
ys = np.tile(y, (rows,1))
zs = z.repeat(cols).reshape((rows,cols))

theta = np.linspace(0, 2*np.pi, 18, endpoint=False)
x = r*np.cos(theta)
y = r*np.sin(theta)
x[2::3] = x[1::3]
x[1::3] = 0
y[2::3] = y[1::3]
y[1::3] = 0
z = np.ones(18) * h * 0.9
vs = np.stack((x,y,z), axis=1)

plt.mesh(xs, ys, zs, im[::-1])
plt.surface(vs, color='#C03000', method='T', mode='FCBC', alpha=0.8)
plt.sphere((0,0,h*0.4), 0.4, '#FFFFFF', slices=60, mode='FCBC')
plt.plot((0,0),(0,0),(0.4*h,1.5*h), width=3.0, style='solid', cmap='hsv', caxis='z')
plt.show(rotation='h-')
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

PythonTutorialNumPy3d-visualizationpillowwxgl
Python Crawling & Data Mining
Written by

Python Crawling & Data Mining

Life's short, I code in Python. This channel shares Python web crawling, data mining, analysis, processing, visualization, automated testing, DevOps, big data, AI, cloud computing, machine learning tools, resources, news, technical articles, tutorial videos and learning materials. Join us!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.