Gloopy is an experimental Python demo of creating 3D polyhedra and rendering them using OpenGL.
See these two blog posts for screenshots of the output:
It uses Pyglet for windowing and events, PyOpenGL for most OpenGL bindings, but pyglet.gl for performance critical OpenGL calls.
1 2 3 4 5 6 Basic shapes
Q W E R T Y U Compound shapes
Z X C Hi count compound spheres
V Invaders
up / down Zoom in/out (or pageup / pagedown)
backspace Delete selected (last added) shape
Ctrl M Move selected shape away from origin
Space Toggle highlight of selected shape / faces
- + Select subset of faces
0 Select all faces
del Select no faces (huh?)
Ctrl Q W E R Extrude
Ctrl U I O P Stellate
Ctrl N Normalize
Ctrl S Subdivide (good with '5')
-
Originally written on Windows, run occasionally on OSX, and all recent development on Ubuntu.
-
Python 3.6
This project does not use pip. Instead we track our dependencies using
the newer 'Pipenv', built
on top of pip. So instead of pip install ...
, it should just be a pipenv install
, but:
-
Our Python dependencies (PyOpenGL, etc) aren't available as pre-compiled wheels, so installing them requires you are able to compile and link:
# On Ubuntu sudo apt-get update sudo apt-get install build-essential
and requires Python C headers & shared libraries:
# On Ubuntu, if your Python3 was installed using 'apt', then: sudo apt install python3.6-dev
-
Then you can install Python dependencies, as specified in 'Pipfile':
pip install --user pipenv pipenv install
Execute run.py
from within the gloopy virtualenv, eg:
pipenv run ./run.py
You should be presented with an orange fullscreen window.
If you have multiple monitors, Gloopy prints them to stdout, and chooses the first one it discovers. To change the monitor it chooses, modify the source code in run.py, create_window(), modifying the integer index into the 'screens' list. It would be nice to add a key to change from one screen to another at runtime.
Pressing keys makes things happen:
Keys | Description |
---|---|
1 to 7 |
Create Platonic solids and some variations on them. |
Keys | Description |
---|---|
backspace |
Remove the most recently created shape. |
ctrl-m |
Move the most recently created shape (to make room for new ones.) |
up / down |
Move camera nearer / further away. |
esc |
Exit. |
Keys | Description |
---|---|
q to u |
Create some compound shapes, each formed from a collection of Platonic solids rendered using a single OpenGL draw call. Try u a bunch of times to generate a series of rings. |
z to c |
Massive compound shapes (zoom out to see them.) |
v |
Space invader, generated dynamically from a loaded bitmap. |
b |
Fractaline tetrahedron (at a scale comparable to the Platonic solids, zoom in to see it.) (see 'generating geometry' below.) |
Modification affects the most recently created shape, ie. the one that
has flashing highlights when space
is pressed.
Due to some silly decisions of mine, modifying only works on basic shapes at the moment, not on compounds.
Where ^x
means press 'x' while holding 'ctrl'.
Keys | Description |
---|---|
^n |
Normalise vertices, ie. move all vertices onto a unit sphere. |
space | Toggle flashing highlight of the selected object. |
- / = |
Select a subset of faces on the selected object. This limits the following operations to just the highlighted faces. |
^c |
Recolor faces |
^q to ^r |
Extrude faces by various amounts. |
^s |
Subdivide faces into smaller polygons. |
^u / ^i |
Stellate faces inwards |
^o / ^p |
Stellate faces outwards |
Hence, for example:
5
to create a polygon^s
a few times to subdivide all the faces^n
to normalize the vertices to the unit sphere.
The vertices are distributed fairly evenly, compared to, points of lat/long, for example, which cluster around the poles. This means, for example, that textures or per-vertex lighting calculations are distributed evenly over the surface.
- Any number 1-5 to create a polygon
^r
to extrude the faces by a large amountspace
to highlight the whole shape=
twice, to highlight just the tips of the branches^p
to stellate the tips into pyramids^e
to extrude the pyramid faces by a medium amount=
again to select just the new branch tips.
And so on, with various lengths of extrusion.
Gloopy provides the following services:
- Creation and manipulation of 3D, flat-surfaced, polyhedra, using the Shape class.
- Factory functions to produce particular shapes, such as Cube or Icosahedron.
- Some basic algorithms to modify existing shapes, such as by subdividing or extruding their surfaces.
- Conversion of shapes into Glyph instances, which manage vertex arrays stored in a VBO.
- A simple Render class which renders glyphs with given positions and orientations.
- A camera attribute on the single Gloopy instance, that can be positioned, oriented, or told to look at a particular item or position.
- A fragment and vertex shader are installed to perform basic lighting calculations.
Gloopy is released under the terms of the New BSD, as specified in LICENSE.txt.
It works for me, but has not been used on any real projects. The API is a mess, as is much of the code, and may change substantially in later releases.
No issue tracker is currently maintained, but the major shortfalls as I percieve them are:
- Some algorithmic modifiers, such as face subdivision, extrusion, stellation, do not currently work on MultiShapes. This is because these modifiers rely on modifying attributes of the given shape in place, such as by inserting new entries in the .faces collection. However, MultiShapes provide many of these attributes by using generators to form a composite stream of their children. I guess I ought to make all shape modifiers functional.
- No attempt is made to handle textures. All faces are plain colors.
- We don't currently handle multiple shaders within a single scene.
PyWeek <http://pyweek.org>
_ participants 'Scav' and 'Threads' for showing me
how it should be done, and PyWeek message board users donal.h, Cosmologicon,
RB[0], PyTM30, Tee and saluk for cajoling me into accepting the merit of
allowing people to bring pre-existing codebases into PyWeek so long as they
are public.