Skip to main content

A lightweight 3D wireframe renderer built from scratch using Pygame

Project description

Aiden3DRenderer

A lightweight 3D wireframe renderer built with Pygame featuring custom projection, first-person camera controls, and 15+ procedural terrain generators.

Features

  • Custom 3D projection - Perspective projection without using external 3D libraries
  • First-person camera - Full 6-DOF camera movement with mouse look
  • 15+ procedural generators - Mountains, cities, fractals, and mathematical surfaces
  • Real-time rendering - 60 FPS wireframe rendering
  • Animated terrains - Several terrains feature time-based animations
  • Extensible API - Easy to create and register custom shapes with decorators
  • Multiple Object Support - render multiple shapes at the same time

Gallery

Ripple Animation
Ripple Effect
Expanding waves from center
Mandelbulb Fractal
Mandelbulb Slice
3D fractal cross-section
Turning Spiral
Turning Spiral
Screw like shape spinning
Simple City (laggy when solid render)
Simple City (laggy when solid render)
City preset in solid render
Tree Mesh
Tree Mesh
Tree render from tree_example.py in examples
Tree Solid Render
Tree Solid Render
Tree render from tree_example.py in examples

Installation

pip install aiden3drenderer

Requires Python 3.11+ and automatically installs Pygame 2.6.0+ (only tested with Python 3.11)

Quick Start

Running the Demo

Original Demo

from aiden3drenderer import Renderer3D

# Create and run the renderer with all built-in shapes
renderer = Renderer3D()
renderer.camera.position = [0, 0 ,0]
# is_mesh = True for mesh, False for solid colors
renderer.is_mesh = False
renderer.run()

Looped Demo

from aiden3drenderer import Renderer3D

# Create and run the renderer with all built-in shapes
renderer = Renderer3D()
renderer.camera.position = [0, 0 ,0]
# is_mesh = True for mesh, False for solid colors
renderer.is_mesh = False

while True:
    renderer.loopable_run()

Looped Run Usage Example

from aiden3drenderer import Renderer3D

# Create and run the renderer with all built-in shapes
# Simple gravity with set floor height
renderer = Renderer3D()
renderer.camera.position = [0, 0 ,0]
renderer.is_mesh = False
gravity = 0.05
floor_height = 0.1
camera_height = 2

while True:
    if renderer.camera.position[1] <= floor_height + camera_height:
        renderer.camera.position[1] = floor_height + camera_height
    else:
        renderer.camera.position[1] -= gravity
    renderer.loopable_run()

Creating Custom Shapes

To create custom shapes compatible with this 3D mesh renderer, you must write Python functions decorated with @register_shape, each returning a "vertex matrix"—a list of rows, where each row is a list of 3D coordinate tuples (x, y, z). Each row represents a contiguous horizontal strip of points on your 3D shape, stacked along the "y" (vertical) dimension. All rows in the matrix must have the same number of points (columns); do not generate jagged matrices or append rows of different lengths, as the renderer expects a perfect rectangle to traverse for drawing wireframes and faces.

Points are usually arranged such that matrix[row][col] gives the (x, y, z) of the point at column col in row row. Loops that fill your matrix should ensure that each sub-list (row) is always the full width—pad with None or duplicate valid coordinates if needed, but empty or missing values will cause indexing errors. Avoid using polar or arbitrary arrangements for each row: either fill every cell with an (x, y, z) tuple, or, if the shape doesn't naturally fit a rectangle (e.g., cones/canopies), pad shorter rows to the full length to maintain a perfect rectangle.

Your function should accept at least the two arguments grid_size (which determines the overall scale and discretization) and frame (for animation support; ignored if not animating), and always return the correctly-sized 2D matrix ready for rendering. If any row in your matrix is shorter than the others, or you index cells that do not exist, you will get IndexError: list index out of range. Review your logic to ensure each row always contains the expected number of vertices, and debug with simple cubes or grids first to be confident in your shape's layout.

To render multiple shapes at the same time, simply have the shapes use the same key press activation as another shape.

Simple Shapes

from aiden3drenderer import Renderer3D, register_shape
import pygame

# Register a custom shape with a decorator
@register_shape("My Plane", key=pygame.K_p, is_animated=False)
def generate_pyramid(grid_size=40, frame=0):
  """Generate a simple plane."""
  matrix = [
    [(1,1,1), (2,1,1), (3,1,1)],
    [(1,1,2), (2,1,2), (3,1,2)],
    [(1,1,3), (2,1,3), (3,1,3)]
]
  return matrix

# Run the renderer (your shape will be available on 'P' key)
renderer = Renderer3D()
renderer.run()

Complex Shapes

from aiden3drenderer import Renderer3D, register_shape
import pygame

# Register a custom shape with a decorator
@register_shape("My Pyramid", key=pygame.K_p, is_animated=False)
def generate_pyramid(grid_size=40, frame=0):
  """Generate a simple pyramid."""
  matrix = []
  center = grid_size / 2
    
  for x in range(grid_size):
    row = []
    for y in range(grid_size):
      # Distance from center
      dx = abs(x - center)
      dy = abs(y - center)
      max_dist = max(dx, dy)
            
      # Height decreases with distance
      height = max(0, 10 - max_dist)
      row.append(height)
    matrix.append(row)
    
  return matrix

# Run the renderer (your shape will be available on 'P' key)
renderer = Renderer3D()
renderer.run()

Controls

Camera Movement

  • W/A/S/D - Move forward/left/backward/right
  • Space - Move up
  • Left Shift - Move down
  • Left Ctrl - Speed boost (2x)
  • Arrow Keys - Fine pitch/yaw adjustment
  • Right Mouse + Drag - Look around (pitch and yaw)

Terrain Selection

  • 1 - Mountain terrain
  • 2 - Animated sine waves
  • 3 - Ripple effect
  • 4 - Canyon valley
  • 5 - Stepped pyramid
  • 6 - Spiral surface
  • 7 - Torus (donut)
  • 8 - Sphere
  • 9 - Möbius strip
  • 0 - Megacity (80×80 procedural city)
  • Q - Alien landscape
  • E - Double helix (DNA-like)
  • R - Mandelbulb fractal slice
  • T - Klein bottle
  • Y - Trefoil knot

Other

  • Escape - Quit application

Terrain Descriptions

Static Terrains

Mountain (1) - Smooth parabolic mountain with radial falloff

Canyon (4) - U-shaped valley with sinusoidal variations

Pyramid (5) - Stepped pyramid using Chebyshev distance

Torus (7) - Classic donut shape using parametric equations

Sphere (8) - UV sphere using spherical coordinates

Möbius Strip (9) - Non-orientable surface with a single side

Megacity (0) - 80×80 grid with hundreds of procedurally generated buildings

  • Buildings get taller toward the center
  • 8×8 block system with roads
  • Random antenna towers on some buildings
  • Most complex terrain (6400 vertices)

Mandelbulb (R) - 2D slice of 3D Mandelbulb fractal

  • Uses power-8 formula
  • Height based on iteration count

Klein Bottle (T) - 4D object projected into 3D

  • Non-orientable surface
  • No inside or outside

Trefoil Knot (Y) - Mathematical knot in 3D space

  • Classic topology example
  • Tube follows trefoil path

Animated Terrains

Waves (2) - Multiple overlapping sine waves

  • Three different wave frequencies
  • Constantly flowing motion

Ripple (3) - Expanding ripple from center

  • Exponential amplitude decay
  • Simulates water drop impact

Spiral (6) - Rotating spiral pattern

  • Polar coordinate mathematics
  • Hypnotic rotation

Alien Landscape (Q) - Complex multi-feature terrain

  • Crater with parabolic profile
  • Crystalline spike formations
  • Rolling hills
  • Procedural "vegetation" spikes
  • Pulsating energy field

Double Helix (E) - DNA-like structure

  • Two intertwined strands
  • 180° phase offset between strands
  • Rotates over time

Technical Details

3D Projection Pipeline

  1. World coordinates - Raw vertex positions
  2. Camera translation - Subtract camera position
  3. Camera rotation - Apply yaw, pitch, roll transformations
  4. Perspective projection - Divide by Z-depth with FOV
  5. Screen mapping - Convert to pixel coordinates

Rotation Matrices

Yaw (Y-axis):

x' = x·cos(θ) + z·sin(θ)
z' = -x·sin(θ) + z·cos(θ)

Pitch (X-axis):

y' = y·cos(φ) - z·sin(φ)
z' = y·sin(φ) + z·cos(φ)

Roll (Z-axis):

x' = x·cos(ψ) - y·sin(ψ)
y' = x·sin(ψ) + y·cos(ψ)

Culling

Points behind the camera (z ≤ 0.1) are set to None to prevent rendering artifacts and negative depth division.

Performance

  • 60 FPS stable on most terrains
  • Megacity (6400 vertices) - Largest terrain, still maintains 60 FPS (wireframe mesh only)
  • Wireframe rendering and filled polygons from triangle partitions

API Reference

Renderer3D

Main renderer class that handles the 3D projection and rendering loop.

from aiden3drenderer import Renderer3D

renderer = Renderer3D(
    width=1200,      # Window width in pixels
    height=800,      # Window height in pixels
    fov=800          # Field of view (higher = less perspective)
)
renderer.run()

Camera

Camera class for position and rotation control (automatically created by Renderer3D).

from aiden3drenderer import Camera

# Access camera through renderer
renderer = Renderer3D()
camera = renderer.cam

# Camera attributes
camera.pos          # [x, y, z] position
camera.facing       # [yaw, pitch, roll] in radians
camera.speed        # Movement speed (default: 0.5)

register_shape Decorator

Register custom shape generators that appear in the renderer.

@register_shape(name, key=None, is_animated=False)
def generate_function(grid_size=40, frame=0):
    """
    Args:
        name (str): Display name for the shape
        key (pygame.K_*): Keyboard key to trigger shape (optional)
        is_animated (bool): Whether shape changes over time
        
    Returns:
        list[list[float]]: grid_size x grid_size matrix of heights
    """
    return matrix

Package Structure

aiden3drenderer/
├── __init__.py          # Package exports
├── renderer.py          # Renderer3D class and projection
├── camera.py            # Camera class for movement/rotation
└── shapes.py            # 15+ built-in shape generators

examples/
├── basic_usage.py       # Simple demo
└── custom_shape_example.py  # Custom shape tutorial

Development

Running from Source

git clone https://github.com/AidenKielby/3D-mesh-Renderer
cd 3D-mesh-Renderer
pip install -e .
python examples/basic_usage.py

Building the Package

pip install build twine
python -m build
python -m twine upload dist/*

Credits

Created by Aiden. Procedural generation functions created with AI assistance (the things like mountain and megacity). All rendering, projection, and camera code written manually.

License

Free to use and modify.

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aiden3drenderer-0.1.5.tar.gz (17.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

aiden3drenderer-0.1.5-py3-none-any.whl (13.4 kB view details)

Uploaded Python 3

File details

Details for the file aiden3drenderer-0.1.5.tar.gz.

File metadata

  • Download URL: aiden3drenderer-0.1.5.tar.gz
  • Upload date:
  • Size: 17.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for aiden3drenderer-0.1.5.tar.gz
Algorithm Hash digest
SHA256 bfb715cdd559421ebb18d42b73ba4bb2194bc9eda69f0f54f4491722d4ac12bc
MD5 f6a0048b163853ab5264c2510aae3ef4
BLAKE2b-256 553c08432af06dec8966b1b4e6b11de75b5fe963020d18db07ee23322ad7e1b9

See more details on using hashes here.

File details

Details for the file aiden3drenderer-0.1.5-py3-none-any.whl.

File metadata

File hashes

Hashes for aiden3drenderer-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 0bb078e6212e2f8b304f99f41823acb97cc840e791c0045e2eb6068d59ae82a5
MD5 2c1538f0d2cc02f98eefddc168f3fed5
BLAKE2b-256 2a0a16ece1de3b777ba6bc20d8675d552bf47272a7d69a098e54c31aacd4f11e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page