Compare commits

..

169 commits

Author SHA1 Message Date
Quantum e77d4661cc Require pyglet<1.4 for now 2020-05-01 02:38:44 -04:00
Quantum 7cb34c9142 Release punyverse 1.2 with better cross platform support 2018-12-01 01:27:56 -05:00
Quantum e72a3bc623 Make sky disablable, and disable by default on macOS 2018-11-27 01:44:06 -05:00
Quantum 9cdf3b8513 Make punyverse runnable on macOS 2018-11-27 01:27:59 -05:00
Guanzhong Chen 885194c7a0
Update README.md 2018-09-26 11:06:23 -04:00
Quantum 8739120036 So much legacy texture stuff can go. 2018-08-30 16:47:10 -04:00
Quantum d5297d3619 Release 1.1 with higher resolution textures.
After all, it doesn't exactly make sense for saturn's moons and mercury to have more detailed textures than larger objects like the sun or venus.

Also used one single texture to do the transparency mask for the glow, instead of having separate textures for each glowy object.
2018-08-29 17:55:06 -04:00
Quantum 4d58450429 Release punyverse 1.0. 2018-08-29 16:54:55 -04:00
Quantum 2a9eacf37e We should include shaders in the build. 2018-08-29 15:42:33 -04:00
Quantum 98b894c846 We don't actually use _model.pyx anymore.
punyverse.model was optimized to be fast enough.
2018-08-29 14:22:21 -04:00
Quantum 7c3c644a6a Set all shaders to GLSL 3.30 core profile. 2018-08-29 13:50:37 -04:00
Quantum 85d4bd4efc Outright require OpenGL 3.3.
pyglet seems to detect MESA as 3.0 even though it supports 3.3, even when I create a 3.3 context.
2018-08-29 03:10:27 -04:00
Quantum 52c1a328aa OpenGL 3.2 core profile compatibility achieved! 2018-08-29 02:29:45 -04:00
Quantum 4430eb7d75 Use VAOs for everything. 2018-08-29 02:29:45 -04:00
Quantum 8317201492 Switch non-model related drawing to use VAO. 2018-08-29 02:29:44 -04:00
Quantum b4c96ebf90 No need to deactivate shaders or anything now. 2018-08-29 02:29:44 -04:00
Quantum f70a725a58 Shader for models. Instanced asteroid belt.
Removed all instances of legacy pipeline, hopefully. (Except for using VAOs, I guess)
2018-08-29 02:29:43 -04:00
Quantum e91bc2c21c Convert orbits to shaders. 2018-08-29 02:29:43 -04:00
Quantum 674289a8b3 Turn the circle thing to use shaders.
It's for tiny things like that that immediate mode is useful.
2018-08-29 02:29:42 -04:00
Quantum 7023ed83ea Fix depth issues. 2018-08-29 02:29:42 -04:00
Quantum 9e65004128 Converted info display to use shaders. 2018-08-29 02:29:41 -04:00
Quantum 4857b5487c Converted atmosphere to shaders. 2018-08-29 02:20:39 -04:00
Quantum 91fce520b9 Converted ring to 1D texture. 2018-08-29 02:20:38 -04:00
Quantum 9d73059ad0 Sky cubemap loading progress. 2018-08-29 02:20:38 -04:00
Quantum f11e0b6fc7 Cube map sky and add constellation lines. 2018-08-29 02:20:38 -04:00
Quantum 168434ce37 Orient the sky texture more correctly. 2018-08-29 02:20:37 -04:00
Quantum d41fcb7d7f Convert rings to shaders.
Also add planet shadows onto rings.
2018-08-29 02:20:37 -04:00
Quantum 1319514cdc Add a debug flag. 2018-08-29 02:20:36 -04:00
Quantum a28074558b Create new punyverse launchers that will use dedicated graphics. 2018-08-29 02:20:36 -04:00
Quantum 9608d30462 Mostly working Intel integrated graphics compatibility. 2018-08-29 02:20:07 -04:00
Quantum f7797949d9 Switch clouds to shaders. 2018-08-29 02:18:17 -04:00
Quantum 3770ec617b Make matrices directly passable to ctypes. 2018-08-29 02:18:15 -04:00
Quantum ac7a4d0f13 Run without debugging by default. 2018-08-29 02:18:15 -04:00
Quantum 04758850f5 Add specular mapping. 2018-08-29 02:18:15 -04:00
Quantum 25e28c3c12 Add emission texture for earth. 2018-08-29 02:18:14 -04:00
Quantum c3176ce7f6 Normal mapped the earth. 2018-08-29 02:18:14 -04:00
Quantum 3f927427ae Add star shaders. 2018-08-29 02:18:13 -04:00
Quantum fbcdb4d9b0 Convert planets to use shaders. 2018-08-29 02:18:13 -04:00
Quantum 66c54a9dbb Move sky to shaders. 2018-08-29 02:18:12 -04:00
Quantum 999dc78410 Manage projection matrix directly. 2018-08-29 02:18:12 -04:00
Quantum 517a7584ca Get rid of glMatrix since we handle all matrices manually 2018-08-29 02:18:12 -04:00
Quantum 0607ab4d4c Stop using OpenGL to do modelview matrices. 2018-08-29 02:18:12 -04:00
Quantum bfdefe43ef Convert orbits to VBO 2018-08-29 02:18:11 -04:00
Quantum a2620fc3bc Converted models to VBO.
Note that this actually makes things slower... at least until we move to shaders.
2018-08-29 02:18:11 -04:00
Quantum 8b070726c3 Significantly clean up model loader.
Temporarily disabled the cython version since improvements will be later backported.
2018-08-29 02:18:10 -04:00
Quantum dde4e1541d Turned atmosphere and rings into VBOs. 2018-08-29 02:18:10 -04:00
Quantum 825e2ecf6a Use VBOs for spheres. 2018-08-24 19:37:50 -04:00
Quantum 338b7fb66c Use anisotropic filtering, if possible. 2018-08-24 17:08:55 -04:00
Quantum 1524a6f27e Use proper texture loading techniques. 2018-08-24 17:02:58 -04:00
Quantum 9193f1bc57 Get rid of GLU in _cyopengl.pxi.
Note that only libGL and not libGLu is supported by manylinux wheels.
2018-08-24 15:38:49 -04:00
Quantum 13e247bea3 Use dedicated loader window to perform loading.
This paves the way to use OpenGL core profile in the future while still using legacy to draw the simple loader.
2018-08-24 15:32:17 -04:00
Quantum e579086ec5 Move non-UI logic from game to world. 2018-08-24 15:32:17 -04:00
Quantum cbe3c3dd7e Use a proper format for main module. 2018-08-24 15:32:16 -04:00
Quantum 054721fc0f Allow travis to build tags. 2018-08-23 22:45:03 -04:00
Quantum 1b6d422447 Release punyverse 0.5, with major clean ups to the codebase. 2018-08-23 22:31:26 -04:00
Quantum b094dd8905 Clean up game loading code. 2018-08-23 22:30:37 -04:00
Quantum e33fad8bbb Make sun a real light source. 2018-08-23 22:08:47 -04:00
Quantum 13867d7fd0 Properly handle background objects. 2018-08-23 22:05:56 -04:00
Quantum b54601f9f7 We don't need a torus function... 2018-08-23 21:58:10 -04:00
Quantum a862302408 Use the faster Newton's method for eccentric anomaly.
Newton's method also converges quickly for highly eccentric orbits.
2018-08-23 21:49:38 -04:00
Quantum 2aed23c4ae Get rid of gencheap.bat when we have punyverse-small-images. 2018-08-23 21:28:44 -04:00
Quantum 3079c612f6 Clean up texture handing. 2018-08-23 21:27:19 -04:00
Quantum f9d83a2add Show better renderer information. 2018-08-23 00:38:14 -04:00
Quantum 63d42bca55 Moved drawing logic to the entities themselves. 2018-08-23 00:24:57 -04:00
Quantum 1b973b0082 Removed cheap texture hacks. 2018-08-23 00:24:57 -04:00
Quantum 50b8d39b71 Travis should only build master. 2018-08-22 22:05:46 -04:00
Quantum 2dfab195f1 Update classifiers. 2018-08-22 18:10:55 -04:00
Quantum 2baeaa5752 Fix python 2 on linux. 2018-08-22 17:42:34 -04:00
Quantum 2705dff909 Release 0.4 with Linux support. 2018-08-22 17:15:05 -04:00
Quantum f6fda9b31e Only attempt to make punyverse wheels. 2018-08-22 17:00:41 -04:00
Quantum ffd036277b Add mesa-libGL-devel, mesa-libGLU-devel so travis can build against OpenGL. 2018-08-22 16:53:30 -04:00
Quantum 951825ce87 We actually need cython in dev-requirements.txt 2018-08-22 16:48:48 -04:00
Quantum 358027eee1 We don't actually have a dev-requirements.txt 2018-08-22 16:46:16 -04:00
Quantum b26cde687a Make travis build wheels. 2018-08-22 16:37:35 -04:00
Quantum ff78a2d8a7 Fix various bugs for 64-bit and Linux. 2018-08-22 16:22:08 -04:00
Quantum b4dce48fa7 Punyverse 0.3: adding Python 3 support. 2018-08-22 04:19:04 -04:00
Quantum bb928b6c55 Release punyverse 0.2 to fix PyPI description. 2018-08-22 02:09:01 -04:00
Quantum aa9bd685ef Switch to pip install punyverse. 2018-08-22 02:00:32 -04:00
Quantum 0fea259382 Fix sky so that it works properly. 2018-08-22 00:35:15 -04:00
Quantum 6d1e52ae76 Update README.md 2017-07-23 16:49:40 -04:00
Quantum 7e40363898 Update README.md 2017-01-06 23:23:44 -05:00
Quantum 973988b911 Added collision; bounces on collision. 2014-02-21 12:45:33 -05:00
Quantum 69884816ca It is an error to use mipmapped magnification. 2014-02-02 23:21:03 -05:00
Quantum f1c961384c Rings have ripples no longer!
(Provided you don't have a 10-years-old integrated card)
2014-02-02 21:10:18 -05:00
Quantum c7659c06f7 Added culling for spheres. 2014-02-02 21:04:11 -05:00
Quantum 2348e1d275 Added hardware normal mapping, usable with -n/--normal option. 2014-02-02 18:22:45 -05:00
Quantum 83d8baeb8e Used context managers to control GL attributes and matrices. No more stray GL_BLEND, much faster! 2014-02-02 16:47:05 -05:00
Quantum 44889fbf11 Removed annoying error message in py2exe launcher. 2014-01-05 20:12:47 -05:00
Quantum af65c9cc6e Displays OpenGL configuration on loading screen. 2014-01-05 20:02:25 -05:00
Quantum f961b43675 Allowed depth buffer to be adjusted and multisample be enabled. 2014-01-05 19:23:31 -05:00
Quantum 54d9841d02 Updated main entry to have proper arguments. 2014-01-05 18:51:39 -05:00
Quantum 4151622b91 Allowed the screenshot to be saved to a file instead of clipboard. 2014-01-05 14:02:45 -05:00
Quantum 34d316726f Screenshots now go to clipboard on windows.
Note to self: temporary files is not nice.
2014-01-04 17:46:00 -05:00
Quantum 19da810af2 Added screenshot support, to ~/punyverse.png currently. 2014-01-04 17:19:04 -05:00
Quantum 2350fc7d26 Removed normal mapping and reduced asteroid count. FPS improves by an order of magnitude. 2014-01-02 23:50:46 -05:00
Quantum 678938ab10 The anti-aliasing is has little benefit but killed a card. It also makes text blurry. Added vsync back. 2013-12-24 17:16:53 -05:00
Quantum 55ee2ee3d2 Added loading screen. 2013-12-13 18:01:52 -05:00
Quantum dc6d0c6c67 Put world parsing into World constructor. 2013-12-13 16:12:40 -05:00
Quantum db61f5cb59 Fixed handling of textures without fallback.
Earth now has same colour as atmosphere without a texture.
2013-11-25 17:04:27 -05:00
Quantum 0794cad88b Permanently banned all C files from being included in the repository. 2013-11-25 16:46:28 -05:00
Quantum 6d1506926d Implemented normal mapped sphere in Cython.
Also:
 * Writes directly into the bytes object instead of malloc'ing.
 * Converted all OpenGL functions to nogil.
2013-11-25 16:34:21 -05:00
Quantum bb855ec759 Backported all of Cython model loader to Python. 2013-11-23 12:36:27 -05:00
Quantum d1599eb511 Added compression support to wavefront loader.
Removed massive generated C file.
2013-11-23 12:12:48 -05:00
Quantum 6138402b01 Used 3D rotation to calculate the normals. 2013-11-23 11:01:57 -05:00
Quantum e138e2d382 Upgraded the normal map to 2048x1024. Should look better. 2013-11-21 23:22:24 -05:00
Quantum 20b2141ffe Switched to a triangle strip, should be much faster. 2013-11-21 20:59:33 -05:00
Quantum a2198937c3 Added normal map for earth as proof of concept. 2013-11-21 20:47:29 -05:00
Quantum 1b2bd928cc Objects no longer flicker when being far (10x improvement). Close objects are not displayed very well. 2013-11-21 16:45:38 -05:00
Quantum 8416ed64e6 Added Cassini around Saturn. 2013-11-20 18:38:53 -05:00
Quantum 0198fba591 The atmosphere now always faces the camera. 2013-11-20 16:43:54 -05:00
Quantum 8900255b4d Added Hubble Space Telescope. 2013-11-17 01:09:53 -05:00
Quantum 321f0582fa Fixed world.json. Closes #100. 2013-11-12 16:43:53 -05:00
Quantum df3126e232 New asteroids and scaling. 2013-11-14 12:39:55 -05:00
Quantum 6fa6bf0429 Shrunk cursor greatly. 2013-11-09 18:57:07 -05:00
Quantum c6ba1ffdc8 gluBuild2DMipmaps doesn't seem to do anything. 2013-11-09 17:42:50 -05:00
Quantum f15af40729 Filtered cloud texture to remove noise. 2013-11-09 17:38:01 -05:00
Quantum c0f4807d88 New clouds that actually looks realistic. Closes #99. 2013-11-09 14:27:35 -05:00
Quantum 59b6f2c7c0 Removed stray glEnable(GL_BLEND). 2013-11-09 10:13:56 -05:00
Quantum 06dd46588c Simplified implementation according to issue. Refs #98. 2013-11-09 10:08:59 -05:00
Quantum d2a6230eb3 Completely rewrite of ticking which guarantees update per frame. Refs #98. 2013-11-06 22:12:58 -05:00
Quantum b3a2a9c298 Updated description. 2013-11-06 21:39:42 -05:00
Quantum 2dc3a2e0c7 Pointed launcher to new release. 2013-11-06 17:46:35 -05:00
Quantum 3361904aa4 Added argparse to launcher. 2013-11-06 17:37:17 -05:00
Quantum 08c12d3b4d Added support for older launchers. 2013-11-06 17:32:31 -05:00
Quantum 3b221e4339 Slightly better formatting. 2013-11-05 19:18:22 -05:00
Quantum 672b5c0462 Better time handling: configurable ticks per second, and no dropped movement.
Note: the original method involves moving on only when update() is called, which is called only between frames. Hence less than the ticks per second setting if it can't paint as fast. This made movement completely FPS independent.

TODO: remove update, merge into on_draw.
2013-11-04 17:00:15 -05:00
Quantum a069c94dab Removed the two most complained about asteroids. 2013-11-04 17:02:23 -05:00
Quantum a03b172aa0 Using hard code of 1024 asteroids in belt.
For that texture size kills modern computers.
2013-11-04 16:29:28 -05:00
Quantum 08f108a5fa Fixed fatal bugs that prevent time from stopping on demand. 2013-11-04 16:28:34 -05:00
Quantum 972e716d00 Added in the textures for corona and solar "atmosphere". 2013-11-02 15:17:30 -04:00
Quantum 46ca669ecb Attempt at making diffuse and corona not intersect. 2013-11-02 15:13:05 -04:00
Quantum 1c3abeeaa7 Added a diffuse texture on the sun. 2013-11-02 15:07:23 -04:00
Quantum 0ae75da2a7 Added a sort of corona effect. 2013-11-02 15:00:47 -04:00
Quantum 7e25a79968 Allowed control of displaying cloudmaps and atmospheres. 2013-11-02 12:57:10 -04:00
Quantum e5d55f125c Moved mouse and keyboard into dictionaries. 2013-11-02 12:50:48 -04:00
Quantum 5fd914438f Would you believe that the debug label drawing takes up 20% of drawing time? 2013-11-02 01:00:02 -04:00
Quantum f7ba375e22 Better sun texture. 2013-11-01 20:42:12 -04:00
Quantum 598132cfd6 Image shrinker now reads a list of files to resize, instead of using a hard coded list. This now doesn't need the launcher to be rebuilt for every new texture. 2013-11-01 19:26:25 -04:00
Quantum ad1970d2d2 Added the main asteroid belt. 2013-11-01 18:42:50 -04:00
Quantum 617d4913d7 Added mouse input support. 2013-11-01 12:30:10 -04:00
Quantum e0e1a619f0 Stops the sky from rotating.
Also: asteroids go front when you move back. Uranus rotates about the right axis.
2013-11-01 12:19:18 -04:00
Quantum 4e51fdaff3 Added Mercury and Venus. 2013-10-31 18:51:04 -04:00
Quantum 614ac617cf Added the sun.
Note that its texture is at minimum size.
2013-10-31 18:17:32 -04:00
Quantum 2c1344d799 Optimized surface division for speed. 2013-10-31 17:56:16 -04:00
Quantum a8bb6dfd34 OMG did I just break standalone python usage of punyverse? 2013-10-30 22:52:19 -04:00
Quantum c3ec78ecce Updated description. 2013-10-30 19:29:33 -04:00
Quantum b1eebd1769 Updated the launcher and its utilities. 2013-10-30 19:09:04 -04:00
Quantum 2746338e22 Made cython model loader py2exe friendly. 2013-10-30 18:48:58 -04:00
Quantum e79321c8a9 Added more automatic small image generator. 2013-10-29 23:57:49 -04:00
Quantum d1bd66f463 Added launcher generation and fixed all imports. 2013-10-29 18:52:35 -04:00
Quantum b4ef56a2c0 Added better handling of orbits. 2013-10-28 22:03:49 -04:00
Quantum 8c03a9250b Added Saturn's moons. 2013-10-28 19:20:16 -04:00
Quantum 22e17fbde6 Added forsaken phobos.obj. 2013-10-28 18:04:04 -04:00
Quantum debd37e908 Removed the hack module framedata. 2013-10-28 18:01:58 -04:00
Quantum 6176a7f8cb Added pausing and proper entity speed. 2013-10-28 17:04:14 -04:00
Quantum fb70fcf797 Added proper rotation and proper camera moving. 2013-10-27 19:51:55 -04:00
Quantum 2a7103b25d Added the Galilean moons, and fixed extreme sphere subdivision. 2013-10-27 18:29:11 -04:00
Quantum efedc3c981 Allow adjustment in speed. 2013-10-27 17:32:17 -04:00
Quantum 7c92bc1315 Now uses km as radius. 2013-10-27 16:59:23 -04:00
Quantum ada6ae9121 Fixed a nasty bug in texture loading. 2013-10-26 23:51:02 -04:00
Quantum 43636c1eb7 Used two different definitions of distance so objects can have realistic orbital speed but not huge orbits. 2013-10-26 16:35:47 -04:00
Quantum 5312c4f1dd Used mass to calculate orbital speed. Added phobos. 2013-10-26 16:25:45 -04:00
Quantum 4074118e6d Added orbital display. 2013-10-26 14:25:37 -04:00
Quantum e95e805551 Fixed loading of models with texture. 2013-10-26 14:25:18 -04:00
Quantum cc3fe078a6 The author of the texture code, I mean the original, should know better how glTexImage2D works, because the GL documentation says otherwise. 2013-10-26 12:40:06 -04:00
Quantum e8942d925c Added handling of inclination, longitude of ascending node, and argument of periapsis. 2013-10-26 11:48:58 -04:00
Quantum fc7c8601e6 Attempts to maintain the balance between correctness and appearance.
Added mip mapping due to the increase in distance.
2013-10-25 20:48:03 -04:00
Quantum 412387cc71 Added proper orbit calculations, and limited orbital plane calculations (only inclination is used). 2013-10-25 19:14:32 -04:00
Quantum f87524916e Initial version. 2013-10-22 20:38:37 -04:00
101 changed files with 28712 additions and 41699 deletions

23
.gitignore vendored
View file

@ -37,13 +37,16 @@ nosetests.xml
.idea .idea
punyverse/*.obj punyverse/*.obj
punyverse/*.c
*.html *.html
*.exp *.exp
*.lib *.lib
punyverse/assets/textures/*_medium.* /punyverse/assets/textures/*_large.*
punyverse/assets/textures/*_small.* /punyverse/assets/textures/*_medium.*
punyverse/assets/textures/*/*_medium.* /punyverse/assets/textures/*_small.*
punyverse/assets/textures/*/*_small.* /punyverse/assets/textures/*/*_large.*
/punyverse/assets/textures/*/*_medium.*
/punyverse/assets/textures/*/*_small.*
temp temp
# There is a py2exe package that can execute punyverse directly # There is a py2exe package that can execute punyverse directly
@ -51,3 +54,15 @@ library.zip
*.exe *.exe
*.log *.log
*.dll *.dll
# virtualenvs
/env
/env2
/env3
# Our special launcher
!/punyverse/launcher.c
# macOS
.DS_Store
._.DS_Store

17
.travis-wheels.sh Executable file
View file

@ -0,0 +1,17 @@
#!/bin/bash
set -e -x
# Install a system package required by our library
yum install -y atlas-devel mesa-libGL-devel mesa-libGLU-devel
# Compile wheels
for PYBIN in /opt/python/*/bin; do
"${PYBIN}/pip" install -r /io/dev-requirements.txt
"${PYBIN}/pip" wheel /io/ -w wheelhouse/
done
# Bundle external shared libraries into the wheels
for whl in wheelhouse/punyverse*.whl; do
auditwheel repair "$whl" -w /io/wheelhouse/
done

27
.travis.yml Normal file
View file

@ -0,0 +1,27 @@
branches:
only:
- master
- /^v\d+\./
matrix:
include:
- sudo: required
services:
- docker
env: DOCKER_IMAGE=quay.io/pypa/manylinux1_x86_64
- sudo: required
services:
- docker
env: DOCKER_IMAGE=quay.io/pypa/manylinux1_i686 PRE_CMD=linux32
install:
- docker pull $DOCKER_IMAGE
script:
- docker run --rm -v `pwd`:/io $DOCKER_IMAGE $PRE_CMD /io/.travis-wheels.sh
- ls wheelhouse/
deploy:
provider: releases
api_key:
secure: kNH5YcvrRmDmFI61Wu0tS4QdKrCbLIJQrVsiU5Cyzqz+hP9FG64uGVHN+J/IJ6Dbt2ny8rnk47pPln8kigfEY3EtnvvFsxexJ1JuefFqZXRPlvzqSm4BEcti5Iui7jMTHczK2eUOY6M2bjC0X4CHMa2dGh16JmfG0RAdUaAhvDCSXkbanoMkOkqyN3go7CAny7aZpyRYwv0GGBDAjXBom4kh5C8wqpXcXlVCmdvrvnmIr2EvMKzvup7FV4FlCkSr03F1APdvTK+GgIE8pLjI9sOw3zo8+tm7krwQsItbqTmPRb0TwL4CD4m2zQTREsLWtYHMy5Z+nqAhADWQqhO0mZDZSozs0TLevasmYdirsPaIufjwE3njWCud/7Mq2ahiBjDhTPHDPk1LzVyrMLo6SVpYru37Ft+Be9oWldz8m+t53RiusfFUVh6MH4+crS+FpdgL9FnQsiNiB+wpb8m6c4tDTWBvsNn2PF2w9NCTlu4u4B+EicM4QoZDK0Pmyg29d6nkEx6EI6Ts6Oz9WIE/z0ZLI3JhTZFZO7be8+xGQ8C3UrCNVS5BOlnyyjcXvnO1Vz56iXKjNLWybeLtMqw7DH58qmSBkRcPcl2+oMdqqIH53BdMHxTfSc9IoCbD1gXekpYPbfo7E2bA/9o4QiphnojWsMw1Yzxs4sXy4vMoxNY=
file_glob: true
file: wheelhouse/*
on:
tags: true

9
MANIFEST.in Normal file
View file

@ -0,0 +1,9 @@
include MANIFEST.in
include LICENSE
include README.md
include punyverse/world.json
graft punyverse/assets
include punyverse/shaders/*.glsl
include punyverse/*.c
include punyverse/*.h
exclude punyverse/*.pyx

View file

@ -1,4 +1,40 @@
punyverse # punyverse [![Linux Build Status](https://img.shields.io/travis/quantum5/punyverse.svg?logo=linux&logoColor=white)](https://travis-ci.org/quantum5/punyverse) [![Windows Build Status](https://img.shields.io/appveyor/ci/quantum5/punyverse.svg?logo=windows)](https://ci.appveyor.com/project/quantum5/punyverse) [![PyPI](https://img.shields.io/pypi/v/punyverse.svg)](https://pypi.org/project/punyverse/) [![PyPI - Format](https://img.shields.io/pypi/format/punyverse.svg)](https://pypi.org/project/punyverse/) [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/punyverse.svg)](https://pypi.org/project/punyverse/)
=========
Python simulator of a puny universe. (How many words can i stick into one?) Python simulator of a puny universe. (How many words can I stick into one?)
![Punyverse Preview](https://guanzhong.ca/assets/projects/punyverse-1.0-7e302d32fb62574e7f7a04acaf9c54e8658821614654280e26e54fab4a840254.png)
## Installation
To install, run `pip install punyverse`.
If you are on Windows, run `punyverse_make_launcher`. This should create special launchers that runs `punyverse` on
your dedicated graphics card, should it exist.
Your graphics card might not support some of the larger textures used by `punyverse`, and so startup might fail.
To solve this problem, run `punyverse_small_images`. It will do nothing if your graphics card supports all the
textures, so when in doubt, run `punyverse_small_images` after installation.
Then, run `punyverse` to launch the simulator, or `punyversew` to launch without the console.
### Summary
```bash
pip install punyverse
punyverse_make_launcher
punyverse_small_images
# Installation finished. Run:
punyverse
```
## Troubleshooting
If `punyverse` does not work, try upgrading your graphics card drivers.
If your graphics card does not appear to support OpenGL 3.3, then you cannot run the latest version of `punyverse`.
You can try `pip install -U punyverse==0.5` to install the last version of `punyverse` to support legacy devices.
You can download the wheels manually from [the PyPI page](https://pypi.org/project/punyverse/0.5/).
If the problem is unrelated to your graphics card, and it persists, try running punyverse under debug mode. To do this,
run `punyverse` as `punyverse --debug`. Then paste the entirety of the output into a new GitHub issue
[here](https://github.com/quantum5/punyverse/issues/new).

View file

@ -1,35 +0,0 @@
import pyglet
import json
import os
import sys
import uuid
import imp
def load_dll(dir, module):
name = 'punyverse.' + module
path = os.path.join(dir, 'punyverse', module + '.pyd')
if not os.path.exists(path):
path = os.path.join(dir, 'punyverse.%s.pyd' % module)
if not os.path.exists(path):
raise ImportError('No module named %s' % module)
return imp.load_dynamic(name, path)
if __name__ == '__main__':
try:
dir = os.path.dirname(sys.executable)
if sys.frozen == 'windows_exe':
sys.stderr = open(os.path.join(dir, 'punyverse.log'), 'a')
except AttributeError:
sys.exit('This is only meant to be ran frozen.')
sys.path.insert(0, dir)
# Model indirectly depends on _glgeom to handle textures
load_dll(dir, '_glgeom')
# Model path needs special handling
_model = load_dll(dir, '_model')
_model.model_base = os.path.join(dir, 'punyverse', 'assets', 'models')
with open('punyverse\__main__.py', 'r') as code:
exec(code)

1
dev-requirements.txt Normal file
View file

@ -0,0 +1 @@
cython

View file

@ -1,29 +0,0 @@
from distutils.core import setup
import py2exe
from glob import glob
import sys
import os
import shutil
if len(sys.argv) < 2:
sys.argv.append('py2exe')
parent = os.path.dirname(__file__)
join = os.path.join
setup(
console=[{'dest_base': 'punyverse_debug', 'script': 'bootloader.py'}, 'small_images.py'],
windows=[{'dest_base': 'punyverse', 'script': 'bootloader.py'}],
options={'py2exe': {
'unbuffered': True, 'optimize': 2,
'excludes': [
'_ssl', 'unittest', 'doctest', 'PIL', 'email', 'distutils',
'pyglet.window.carbon', 'pyglet.window.xlib',
'pyglet.media.drivers.alsa',
'win32wnet', 'netbios', 'pgmagick'
],
'includes': ['punyverse._model', 'punyverse._glgeom'],
'dll_excludes': ['MPR.dll', 'w9xpopen.exe'],
}
}
)

View file

@ -1,17 +1,4 @@
#!/usr/bin/python from punyverse.main import main
INITIAL_WIN_HEIGHT = 540
INITIAL_WIN_WIDTH = 700
WIN_TITLE = "Punyverse"
def main():
import pyglet
from punyverse.game import Applet
pyglet.options['shadow_window'] = False
Applet(width=INITIAL_WIN_WIDTH, height=INITIAL_WIN_HEIGHT, caption=WIN_TITLE, resizable=True, vsync=0)
pyglet.app.run()
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View file

@ -1,4 +1,4 @@
from punyverse.__main__ import main from punyverse.main import main
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View file

@ -1,8 +1,4 @@
IF UNAME_SYSNAME == "Windows": cdef extern from "glwrapper.h":
cdef extern from "windows.h":
pass
cdef extern from "GL/gl.h":
ctypedef unsigned int GLenum ctypedef unsigned int GLenum
ctypedef unsigned char GLboolean ctypedef unsigned char GLboolean
ctypedef unsigned int GLbitfield ctypedef unsigned int GLbitfield
@ -20,440 +16,372 @@ cdef extern from "GL/gl.h":
ctypedef double GLclampd ctypedef double GLclampd
# Miscellaneous # Miscellaneous
void glClearIndex(GLfloat c) void glClearIndex(GLfloat c) nogil
void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) nogil
void glClear(GLbitfield mask) void glClear(GLbitfield mask) nogil
void glIndexMask(GLuint mask) void glIndexMask(GLuint mask) nogil
void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) nogil
void glAlphaFunc(GLenum func, GLclampf ref) void glAlphaFunc(GLenum func, GLclampf ref) nogil
void glBlendFunc(GLenum sfactor, GLenum dfactor) void glBlendFunc(GLenum sfactor, GLenum dfactor) nogil
void glLogicOp(GLenum opcode) void glLogicOp(GLenum opcode) nogil
void glCullFace(GLenum mode) void glCullFace(GLenum mode) nogil
void glFrontFace(GLenum mode) void glFrontFace(GLenum mode) nogil
void glPointSize(GLfloat size) void glPointSize(GLfloat size) nogil
void glLineWidth(GLfloat width) void glLineWidth(GLfloat width) nogil
void glLineStipple(GLint factor, GLushort pattern) void glLineStipple(GLint factor, GLushort pattern) nogil
void glPolygonMode(GLenum face, GLenum mode) void glPolygonMode(GLenum face, GLenum mode) nogil
void glPolygonOffset(GLfloat factor, GLfloat units) void glPolygonOffset(GLfloat factor, GLfloat units) nogil
void glPolygonStipple(GLubyte *mask) void glPolygonStipple(GLubyte *mask) nogil
void glGetPolygonStipple(GLubyte *mask) void glGetPolygonStipple(GLubyte *mask) nogil
void glEdgeFlag(GLboolean flag) void glEdgeFlag(GLboolean flag) nogil
void glEdgeFlagv(GLboolean *flag) void glEdgeFlagv(GLboolean *flag) nogil
void glScissor(GLint x, GLint y, GLsizei width, GLsizei height) void glScissor(GLint x, GLint y, GLsizei width, GLsizei height) nogil
void glClipPlane(GLenum plane, GLdouble *equation) void glClipPlane(GLenum plane, GLdouble *equation) nogil
void glGetClipPlane(GLenum plane, GLdouble *equation) void glGetClipPlane(GLenum plane, GLdouble *equation) nogil
void glDrawBuffer(GLenum mode) void glDrawBuffer(GLenum mode) nogil
void glReadBuffer(GLenum mode) void glReadBuffer(GLenum mode) nogil
void glEnable(GLenum cap) void glEnable(GLenum cap) nogil
void glDisable(GLenum cap) void glDisable(GLenum cap) nogil
GLboolean glIsEnabled(GLenum cap) GLboolean glIsEnabled(GLenum cap)
void glEnableClientState(GLenum cap) # 1.1 void glEnableClientState(GLenum cap) nogil # 1.1
void glDisableClientState(GLenum cap) # 1.1 void glDisableClientState(GLenum cap) nogil # 1.1
void glGetBooleanv(GLenum pname, GLboolean *params) void glGetBooleanv(GLenum pname, GLboolean *params) nogil
void glGetDoublev(GLenum pname, GLdouble *params) void glGetDoublev(GLenum pname, GLdouble *params) nogil
void glGetFloatv(GLenum pname, GLfloat *params) void glGetFloatv(GLenum pname, GLfloat *params) nogil
void glGetIntegerv(GLenum pname, GLint *params) void glGetIntegerv(GLenum pname, GLint *params) nogil
void glPushAttrib(GLbitfield mask) void glPushAttrib(GLbitfield mask) nogil
void glPopAttrib() void glPopAttrib() nogil
void glPushClientAttrib(GLbitfield mask) # 1.1 void glPushClientAttrib(GLbitfield mask) nogil # 1.1
void glPopClientAttrib() # 1.1 void glPopClientAttrib() nogil # 1.1
GLint glRenderMode(GLenum mode) GLint glRenderMode(GLenum mode)
GLenum glGetError() GLenum glGetError()
GLubyte* glGetString(GLenum name) GLubyte* glGetString(GLenum name)
void glFinish() void glFinish() nogil
void glFlush() void glFlush() nogil
void glHint(GLenum target, GLenum mode) void glHint(GLenum target, GLenum mode) nogil
# Depth Buffer # Depth Buffer
void glClearDepth(GLclampd depth) void glClearDepth(GLclampd depth) nogil
void glDepthFunc(GLenum func) void glDepthFunc(GLenum func) nogil
void glDepthMask(GLboolean flag) void glDepthMask(GLboolean flag) nogil
void glDepthRange(GLclampd near_val, GLclampd far_val) void glDepthRange(GLclampd near_val, GLclampd far_val) nogil
# Accumulation Buffer # Accumulation Buffer
void glClearAccum(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) void glClearAccum(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) nogil
void glAccum(GLenum op, GLfloat value) void glAccum(GLenum op, GLfloat value) nogil
# Transformation # Transformation
void glMatrixMode(GLenum mode) void glMatrixMode(GLenum mode) nogil
void glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val) void glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val) nogil
void glFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val) void glFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val) nogil
void glViewport(GLint x, GLint y, GLsizei width, GLsizei height) void glViewport(GLint x, GLint y, GLsizei width, GLsizei height) nogil
void glPushMatrix() void glPushMatrix() nogil
void glPopMatrix() void glPopMatrix() nogil
void glLoadIdentity() void glLoadIdentity() nogil
void glLoadMatrixd(GLdouble *m) void glLoadMatrixd(GLdouble *m) nogil
void glLoadMatrixf(GLfloat *m) void glLoadMatrixf(GLfloat *m) nogil
void glMultMatrixd(GLdouble *m) void glMultMatrixd(GLdouble *m) nogil
void glMultMatrixf(GLfloat *m) void glMultMatrixf(GLfloat *m) nogil
void glRotated(GLdouble angle, GLdouble x, GLdouble y, GLdouble z) void glRotated(GLdouble angle, GLdouble x, GLdouble y, GLdouble z) nogil
void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) nogil
void glScaled(GLdouble x, GLdouble y, GLdouble z) void glScaled(GLdouble x, GLdouble y, GLdouble z) nogil
void glScalef(GLfloat x, GLfloat y, GLfloat z) void glScalef(GLfloat x, GLfloat y, GLfloat z) nogil
void glTranslated(GLdouble x, GLdouble y, GLdouble z) void glTranslated(GLdouble x, GLdouble y, GLdouble z) nogil
void glTranslatef(GLfloat x, GLfloat y, GLfloat z) void glTranslatef(GLfloat x, GLfloat y, GLfloat z) nogil
# Display Lists # Display Lists
GLboolean glIsList(GLuint list) GLboolean glIsList(GLuint list)
void glDeleteLists(GLuint list, GLsizei range) void glDeleteLists(GLuint list, GLsizei range) nogil
GLuint glGenLists(GLsizei range) GLuint glGenLists(GLsizei range)
void glNewList(GLuint list, GLenum mode) void glNewList(GLuint list, GLenum mode) nogil
void glEndList() void glEndList() nogil
void glCallList(GLuint list) void glCallList(GLuint list) nogil
void glCallLists(GLsizei n, GLenum type, GLvoid *lists) void glCallLists(GLsizei n, GLenum type, GLvoid *lists) nogil
void glListBase(GLuint base) void glListBase(GLuint base) nogil
# Drawing Functions # Drawing Functions
void glBegin(GLenum mode) void glBegin(GLenum mode) nogil
void glEnd() void glEnd() nogil
void glVertex2d(GLdouble x, GLdouble y) void glVertex2d(GLdouble x, GLdouble y) nogil
void glVertex2f(GLfloat x, GLfloat y) void glVertex2f(GLfloat x, GLfloat y) nogil
void glVertex2i(GLint x, GLint y) void glVertex2i(GLint x, GLint y) nogil
void glVertex2s(GLshort x, GLshort y) void glVertex2s(GLshort x, GLshort y) nogil
void glVertex3d(GLdouble x, GLdouble y, GLdouble z) void glVertex3d(GLdouble x, GLdouble y, GLdouble z) nogil
void glVertex3f(GLfloat x, GLfloat y, GLfloat z) void glVertex3f(GLfloat x, GLfloat y, GLfloat z) nogil
void glVertex3i(GLint x, GLint y, GLint z) void glVertex3i(GLint x, GLint y, GLint z) nogil
void glVertex3s(GLshort x, GLshort y, GLshort z) void glVertex3s(GLshort x, GLshort y, GLshort z) nogil
void glVertex4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w) void glVertex4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w) nogil
void glVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) void glVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) nogil
void glVertex4i(GLint x, GLint y, GLint z, GLint w) void glVertex4i(GLint x, GLint y, GLint z, GLint w) nogil
void glVertex4s(GLshort x, GLshort y, GLshort z, GLshort w) void glVertex4s(GLshort x, GLshort y, GLshort z, GLshort w) nogil
void glVertex2dv(GLdouble *v) void glVertex2dv(GLdouble *v) nogil
void glVertex2fv(GLfloat *v) void glVertex2fv(GLfloat *v) nogil
void glVertex2iv(GLint *v) void glVertex2iv(GLint *v) nogil
void glVertex2sv(GLshort *v) void glVertex2sv(GLshort *v) nogil
void glVertex3dv(GLdouble *v) void glVertex3dv(GLdouble *v) nogil
void glVertex3fv(GLfloat *v) void glVertex3fv(GLfloat *v) nogil
void glVertex3iv(GLint *v) void glVertex3iv(GLint *v) nogil
void glVertex3sv(GLshort *v) void glVertex3sv(GLshort *v) nogil
void glVertex4dv(GLdouble *v) void glVertex4dv(GLdouble *v) nogil
void glVertex4fv(GLfloat *v) void glVertex4fv(GLfloat *v) nogil
void glVertex4iv(GLint *v) void glVertex4iv(GLint *v) nogil
void glVertex4sv(GLshort *v) void glVertex4sv(GLshort *v) nogil
void glNormal3b(GLbyte nx, GLbyte ny, GLbyte nz) void glNormal3b(GLbyte nx, GLbyte ny, GLbyte nz) nogil
void glNormal3d(GLdouble nx, GLdouble ny, GLdouble nz) void glNormal3d(GLdouble nx, GLdouble ny, GLdouble nz) nogil
void glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz) void glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz) nogil
void glNormal3i(GLint nx, GLint ny, GLint nz) void glNormal3i(GLint nx, GLint ny, GLint nz) nogil
void glNormal3s(GLshort nx, GLshort ny, GLshort nz) void glNormal3s(GLshort nx, GLshort ny, GLshort nz) nogil
void glNormal3bv(GLbyte *v) void glNormal3bv(GLbyte *v) nogil
void glNormal3dv(GLdouble *v) void glNormal3dv(GLdouble *v) nogil
void glNormal3fv(GLfloat *v) void glNormal3fv(GLfloat *v) nogil
void glNormal3iv(GLint *v) void glNormal3iv(GLint *v) nogil
void glNormal3sv(GLshort *v) void glNormal3sv(GLshort *v) nogil
void glIndexd(GLdouble c) void glIndexd(GLdouble c) nogil
void glIndexf(GLfloat c) void glIndexf(GLfloat c) nogil
void glIndexi(GLint c) void glIndexi(GLint c) nogil
void glIndexs(GLshort c) void glIndexs(GLshort c) nogil
void glIndexub(GLubyte c) # 1.1 void glIndexub(GLubyte c) nogil # 1.1
void glIndexdv(GLdouble *c) void glIndexdv(GLdouble *c) nogil
void glIndexfv(GLfloat *c) void glIndexfv(GLfloat *c) nogil
void glIndexiv(GLint *c) void glIndexiv(GLint *c) nogil
void glIndexsv(GLshort *c) void glIndexsv(GLshort *c) nogil
void glIndexubv(GLubyte *c) # 1.1 void glIndexubv(GLubyte *c) nogil # 1.1
void glColor3b(GLbyte red, GLbyte green, GLbyte blue) void glColor3b(GLbyte red, GLbyte green, GLbyte blue) nogil
void glColor3d(GLdouble red, GLdouble green, GLdouble blue) void glColor3d(GLdouble red, GLdouble green, GLdouble blue) nogil
void glColor3f(GLfloat red, GLfloat green, GLfloat blue) void glColor3f(GLfloat red, GLfloat green, GLfloat blue) nogil
void glColor3i(GLint red, GLint green, GLint blue) void glColor3i(GLint red, GLint green, GLint blue) nogil
void glColor3s(GLshort red, GLshort green, GLshort blue) void glColor3s(GLshort red, GLshort green, GLshort blue) nogil
void glColor3ub(GLubyte red, GLubyte green, GLubyte blue) void glColor3ub(GLubyte red, GLubyte green, GLubyte blue) nogil
void glColor3ui(GLuint red, GLuint green, GLuint blue) void glColor3ui(GLuint red, GLuint green, GLuint blue) nogil
void glColor3us(GLushort red, GLushort green, GLushort blue) void glColor3us(GLushort red, GLushort green, GLushort blue) nogil
void glColor4b(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha) void glColor4b(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha) nogil
void glColor4d(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha) void glColor4d(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha) nogil
void glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) void glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) nogil
void glColor4i(GLint red, GLint green, GLint blue, GLint alpha) void glColor4i(GLint red, GLint green, GLint blue, GLint alpha) nogil
void glColor4s(GLshort red, GLshort green, GLshort blue, GLshort alpha) void glColor4s(GLshort red, GLshort green, GLshort blue, GLshort alpha) nogil
void glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) void glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) nogil
void glColor4ui(GLuint red, GLuint green, GLuint blue, GLuint alpha) void glColor4ui(GLuint red, GLuint green, GLuint blue, GLuint alpha) nogil
void glColor4us(GLushort red, GLushort green, GLushort blue, GLushort alpha) void glColor4us(GLushort red, GLushort green, GLushort blue, GLushort alpha) nogil
void glColor3bv(GLbyte *v) void glColor3bv(GLbyte *v) nogil
void glColor3dv(GLdouble *v) void glColor3dv(GLdouble *v) nogil
void glColor3fv(GLfloat *v) void glColor3fv(GLfloat *v) nogil
void glColor3iv(GLint *v) void glColor3iv(GLint *v) nogil
void glColor3sv(GLshort *v) void glColor3sv(GLshort *v) nogil
void glColor3ubv(GLubyte *v) void glColor3ubv(GLubyte *v) nogil
void glColor3uiv(GLuint *v) void glColor3uiv(GLuint *v) nogil
void glColor3usv(GLushort *v) void glColor3usv(GLushort *v) nogil
void glColor4bv(GLbyte *v) void glColor4bv(GLbyte *v) nogil
void glColor4dv(GLdouble *v) void glColor4dv(GLdouble *v) nogil
void glColor4fv(GLfloat *v) void glColor4fv(GLfloat *v) nogil
void glColor4iv(GLint *v) void glColor4iv(GLint *v) nogil
void glColor4sv(GLshort *v) void glColor4sv(GLshort *v) nogil
void glColor4ubv(GLubyte *v) void glColor4ubv(GLubyte *v) nogil
void glColor4uiv(GLuint *v) void glColor4uiv(GLuint *v) nogil
void glColor4usv(GLushort *v) void glColor4usv(GLushort *v) nogil
void glTexCoord1d(GLdouble s) void glTexCoord1d(GLdouble s) nogil
void glTexCoord1f(GLfloat s) void glTexCoord1f(GLfloat s) nogil
void glTexCoord1i(GLint s) void glTexCoord1i(GLint s) nogil
void glTexCoord1s(GLshort s) void glTexCoord1s(GLshort s) nogil
void glTexCoord2d(GLdouble s, GLdouble t) void glTexCoord2d(GLdouble s, GLdouble t) nogil
void glTexCoord2f(GLfloat s, GLfloat t) void glTexCoord2f(GLfloat s, GLfloat t) nogil
void glTexCoord2i(GLint s, GLint t) void glTexCoord2i(GLint s, GLint t) nogil
void glTexCoord2s(GLshort s, GLshort t) void glTexCoord2s(GLshort s, GLshort t) nogil
void glTexCoord3d(GLdouble s, GLdouble t, GLdouble r) void glTexCoord3d(GLdouble s, GLdouble t, GLdouble r) nogil
void glTexCoord3f(GLfloat s, GLfloat t, GLfloat r) void glTexCoord3f(GLfloat s, GLfloat t, GLfloat r) nogil
void glTexCoord3i(GLint s, GLint t, GLint r) void glTexCoord3i(GLint s, GLint t, GLint r) nogil
void glTexCoord3s(GLshort s, GLshort t, GLshort r) void glTexCoord3s(GLshort s, GLshort t, GLshort r) nogil
void glTexCoord4d(GLdouble s, GLdouble t, GLdouble r, GLdouble q) void glTexCoord4d(GLdouble s, GLdouble t, GLdouble r, GLdouble q) nogil
void glTexCoord4f(GLfloat s, GLfloat t, GLfloat r, GLfloat q) void glTexCoord4f(GLfloat s, GLfloat t, GLfloat r, GLfloat q) nogil
void glTexCoord4i(GLint s, GLint t, GLint r, GLint q) void glTexCoord4i(GLint s, GLint t, GLint r, GLint q) nogil
void glTexCoord4s(GLshort s, GLshort t, GLshort r, GLshort q) void glTexCoord4s(GLshort s, GLshort t, GLshort r, GLshort q) nogil
void glTexCoord1dv(GLdouble *v) void glTexCoord1dv(GLdouble *v) nogil
void glTexCoord1fv(GLfloat *v) void glTexCoord1fv(GLfloat *v) nogil
void glTexCoord1iv(GLint *v) void glTexCoord1iv(GLint *v) nogil
void glTexCoord1sv(GLshort *v) void glTexCoord1sv(GLshort *v) nogil
void glTexCoord2dv(GLdouble *v) void glTexCoord2dv(GLdouble *v) nogil
void glTexCoord2fv(GLfloat *v) void glTexCoord2fv(GLfloat *v) nogil
void glTexCoord2iv(GLint *v) void glTexCoord2iv(GLint *v) nogil
void glTexCoord2sv(GLshort *v) void glTexCoord2sv(GLshort *v) nogil
void glTexCoord3dv(GLdouble *v) void glTexCoord3dv(GLdouble *v) nogil
void glTexCoord3fv(GLfloat *v) void glTexCoord3fv(GLfloat *v) nogil
void glTexCoord3iv(GLint *v) void glTexCoord3iv(GLint *v) nogil
void glTexCoord3sv(GLshort *v) void glTexCoord3sv(GLshort *v) nogil
void glTexCoord4dv(GLdouble *v) void glTexCoord4dv(GLdouble *v) nogil
void glTexCoord4fv(GLfloat *v) void glTexCoord4fv(GLfloat *v) nogil
void glTexCoord4iv(GLint *v) void glTexCoord4iv(GLint *v) nogil
void glTexCoord4sv(GLshort *v) void glTexCoord4sv(GLshort *v) nogil
void glRasterPos2d(GLdouble x, GLdouble y) void glRasterPos2d(GLdouble x, GLdouble y) nogil
void glRasterPos2f(GLfloat x, GLfloat y) void glRasterPos2f(GLfloat x, GLfloat y) nogil
void glRasterPos2i(GLint x, GLint y) void glRasterPos2i(GLint x, GLint y) nogil
void glRasterPos2s(GLshort x, GLshort y) void glRasterPos2s(GLshort x, GLshort y) nogil
void glRasterPos3d(GLdouble x, GLdouble y, GLdouble z) void glRasterPos3d(GLdouble x, GLdouble y, GLdouble z) nogil
void glRasterPos3f(GLfloat x, GLfloat y, GLfloat z) void glRasterPos3f(GLfloat x, GLfloat y, GLfloat z) nogil
void glRasterPos3i(GLint x, GLint y, GLint z) void glRasterPos3i(GLint x, GLint y, GLint z) nogil
void glRasterPos3s(GLshort x, GLshort y, GLshort z) void glRasterPos3s(GLshort x, GLshort y, GLshort z) nogil
void glRasterPos4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w) void glRasterPos4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w) nogil
void glRasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) void glRasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) nogil
void glRasterPos4i(GLint x, GLint y, GLint z, GLint w) void glRasterPos4i(GLint x, GLint y, GLint z, GLint w) nogil
void glRasterPos4s(GLshort x, GLshort y, GLshort z, GLshort w) void glRasterPos4s(GLshort x, GLshort y, GLshort z, GLshort w) nogil
void glRasterPos2dv(GLdouble *v) void glRasterPos2dv(GLdouble *v) nogil
void glRasterPos2fv(GLfloat *v) void glRasterPos2fv(GLfloat *v) nogil
void glRasterPos2iv(GLint *v) void glRasterPos2iv(GLint *v) nogil
void glRasterPos2sv(GLshort *v) void glRasterPos2sv(GLshort *v) nogil
void glRasterPos3dv(GLdouble *v) void glRasterPos3dv(GLdouble *v) nogil
void glRasterPos3fv(GLfloat *v) void glRasterPos3fv(GLfloat *v) nogil
void glRasterPos3iv(GLint *v) void glRasterPos3iv(GLint *v) nogil
void glRasterPos3sv(GLshort *v) void glRasterPos3sv(GLshort *v) nogil
void glRasterPos4dv(GLdouble *v) void glRasterPos4dv(GLdouble *v) nogil
void glRasterPos4fv(GLfloat *v) void glRasterPos4fv(GLfloat *v) nogil
void glRasterPos4iv(GLint *v) void glRasterPos4iv(GLint *v) nogil
void glRasterPos4sv(GLshort *v) void glRasterPos4sv(GLshort *v) nogil
void glRectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2) void glRectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2) nogil
void glRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) void glRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) nogil
void glRecti(GLint x1, GLint y1, GLint x2, GLint y2) void glRecti(GLint x1, GLint y1, GLint x2, GLint y2) nogil
void glRects(GLshort x1, GLshort y1, GLshort x2, GLshort y2) void glRects(GLshort x1, GLshort y1, GLshort x2, GLshort y2) nogil
void glRectdv(GLdouble *v1, GLdouble *v2) void glRectdv(GLdouble *v1, GLdouble *v2) nogil
void glRectfv(GLfloat *v1, GLfloat *v2) void glRectfv(GLfloat *v1, GLfloat *v2) nogil
void glRectiv(GLint *v1, GLint *v2) void glRectiv(GLint *v1, GLint *v2) nogil
void glRectsv(GLshort *v1, GLshort *v2) void glRectsv(GLshort *v1, GLshort *v2) nogil
# Lighting # Lighting
void glShadeModel(GLenum mode) void glShadeModel(GLenum mode) nogil
void glLightf(GLenum light, GLenum pname, GLfloat param) void glLightf(GLenum light, GLenum pname, GLfloat param) nogil
void glLighti(GLenum light, GLenum pname, GLint param) void glLighti(GLenum light, GLenum pname, GLint param) nogil
void glLightfv(GLenum light, GLenum pname, GLfloat *params) void glLightfv(GLenum light, GLenum pname, GLfloat *params) nogil
void glLightiv(GLenum light, GLenum pname, GLint *params) void glLightiv(GLenum light, GLenum pname, GLint *params) nogil
void glGetLightfv(GLenum light, GLenum pname, GLfloat *params) void glGetLightfv(GLenum light, GLenum pname, GLfloat *params) nogil
void glGetLightiv(GLenum light, GLenum pname, GLint *params) void glGetLightiv(GLenum light, GLenum pname, GLint *params) nogil
void glLightModelf(GLenum pname, GLfloat param) void glLightModelf(GLenum pname, GLfloat param) nogil
void glLightModeli(GLenum pname, GLint param) void glLightModeli(GLenum pname, GLint param) nogil
void glLightModelfv(GLenum pname, GLfloat *params) void glLightModelfv(GLenum pname, GLfloat *params) nogil
void glLightModeliv(GLenum pname, GLint *params) void glLightModeliv(GLenum pname, GLint *params) nogil
void glMaterialf(GLenum face, GLenum pname, GLfloat param) void glMaterialf(GLenum face, GLenum pname, GLfloat param) nogil
void glMateriali(GLenum face, GLenum pname, GLint param) void glMateriali(GLenum face, GLenum pname, GLint param) nogil
void glMaterialfv(GLenum face, GLenum pname, GLfloat *params) void glMaterialfv(GLenum face, GLenum pname, GLfloat *params) nogil
void glMaterialiv(GLenum face, GLenum pname, GLint *params) void glMaterialiv(GLenum face, GLenum pname, GLint *params) nogil
void glGetMaterialfv(GLenum face, GLenum pname, GLfloat *params) void glGetMaterialfv(GLenum face, GLenum pname, GLfloat *params) nogil
void glGetMaterialiv(GLenum face, GLenum pname, GLint *params) void glGetMaterialiv(GLenum face, GLenum pname, GLint *params) nogil
void glColorMaterial(GLenum face, GLenum mode) void glColorMaterial(GLenum face, GLenum mode) nogil
# Raster functions # Raster functions
void glPixelZoom(GLfloat xfactor, GLfloat yfactor) void glPixelZoom(GLfloat xfactor, GLfloat yfactor) nogil
void glPixelStoref(GLenum pname, GLfloat param) void glPixelStoref(GLenum pname, GLfloat param) nogil
void glPixelStorei(GLenum pname, GLint param) void glPixelStorei(GLenum pname, GLint param) nogil
void glPixelTransferf(GLenum pname, GLfloat param) void glPixelTransferf(GLenum pname, GLfloat param) nogil
void glPixelTransferi(GLenum pname, GLint param) void glPixelTransferi(GLenum pname, GLint param) nogil
void glPixelMapfv(GLenum map, GLint mapsize, GLfloat *values) void glPixelMapfv(GLenum map, GLint mapsize, GLfloat *values) nogil
void glPixelMapuiv(GLenum map, GLint mapsize, GLuint *values) void glPixelMapuiv(GLenum map, GLint mapsize, GLuint *values) nogil
void glPixelMapusv(GLenum map, GLint mapsize, GLushort *values) void glPixelMapusv(GLenum map, GLint mapsize, GLushort *values) nogil
void glGetPixelMapfv(GLenum map, GLfloat *values) void glGetPixelMapfv(GLenum map, GLfloat *values) nogil
void glGetPixelMapuiv(GLenum map, GLuint *values) void glGetPixelMapuiv(GLenum map, GLuint *values) nogil
void glGetPixelMapusv(GLenum map, GLushort *values) void glGetPixelMapusv(GLenum map, GLushort *values) nogil
void glBitmap(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, GLubyte *bitmap) void glBitmap(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, GLubyte *bitmap) nogil
void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) nogil
void glDrawPixels(GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) void glDrawPixels(GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) nogil
void glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type) void glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type) nogil
# Stenciling # Stenciling
void glStencilFunc(GLenum func, GLint ref, GLuint mask) void glStencilFunc(GLenum func, GLint ref, GLuint mask) nogil
void glStencilMask(GLuint mask) void glStencilMask(GLuint mask) nogil
void glStencilOp(GLenum fail, GLenum zfail, GLenum zpass) void glStencilOp(GLenum fail, GLenum zfail, GLenum zpass) nogil
void glClearStencil(GLint s) void glClearStencil(GLint s) nogil
# Texture mapping # Texture mapping
void glTexGend(GLenum coord, GLenum pname, GLdouble param) void glTexGend(GLenum coord, GLenum pname, GLdouble param) nogil
void glTexGenf(GLenum coord, GLenum pname, GLfloat param) void glTexGenf(GLenum coord, GLenum pname, GLfloat param) nogil
void glTexGeni(GLenum coord, GLenum pname, GLint param) void glTexGeni(GLenum coord, GLenum pname, GLint param) nogil
void glTexGendv(GLenum coord, GLenum pname, GLdouble *params) void glTexGendv(GLenum coord, GLenum pname, GLdouble *params) nogil
void glTexGenfv(GLenum coord, GLenum pname, GLfloat *params) void glTexGenfv(GLenum coord, GLenum pname, GLfloat *params) nogil
void glTexGeniv(GLenum coord, GLenum pname, GLint *params) void glTexGeniv(GLenum coord, GLenum pname, GLint *params) nogil
void glGetTexGendv(GLenum coord, GLenum pname, GLdouble *params) void glGetTexGendv(GLenum coord, GLenum pname, GLdouble *params) nogil
void glGetTexGenfv(GLenum coord, GLenum pname, GLfloat *params) void glGetTexGenfv(GLenum coord, GLenum pname, GLfloat *params) nogil
void glGetTexGeniv(GLenum coord, GLenum pname, GLint *params) void glGetTexGeniv(GLenum coord, GLenum pname, GLint *params) nogil
void glTexEnvf(GLenum target, GLenum pname, GLfloat param) void glTexEnvf(GLenum target, GLenum pname, GLfloat param) nogil
void glTexEnvi(GLenum target, GLenum pname, GLint param) void glTexEnvi(GLenum target, GLenum pname, GLint param) nogil
void glTexEnvfv(GLenum target, GLenum pname, GLfloat *params) void glTexEnvfv(GLenum target, GLenum pname, GLfloat *params) nogil
void glTexEnviv(GLenum target, GLenum pname, GLint *params) void glTexEnviv(GLenum target, GLenum pname, GLint *params) nogil
void glGetTexEnvfv(GLenum target, GLenum pname, GLfloat *params) void glGetTexEnvfv(GLenum target, GLenum pname, GLfloat *params) nogil
void glGetTexEnviv(GLenum target, GLenum pname, GLint *params) void glGetTexEnviv(GLenum target, GLenum pname, GLint *params) nogil
void glTexParameterf(GLenum target, GLenum pname, GLfloat param) void glTexParameterf(GLenum target, GLenum pname, GLfloat param) nogil
void glTexParameteri(GLenum target, GLenum pname, GLint param) void glTexParameteri(GLenum target, GLenum pname, GLint param) nogil
void glTexParameterfv(GLenum target, GLenum pname, GLfloat *params) void glTexParameterfv(GLenum target, GLenum pname, GLfloat *params) nogil
void glTexParameteriv(GLenum target, GLenum pname, GLint *params) void glTexParameteriv(GLenum target, GLenum pname, GLint *params) nogil
void glGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params) void glGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params) nogil
void glGetTexParameteriv(GLenum target, GLenum pname, GLint *params) void glGetTexParameteriv(GLenum target, GLenum pname, GLint *params) nogil
void glGetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat *params) void glGetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat *params) nogil
void glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params) void glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params) nogil
void glTexImage1D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLint border, GLenum format, GLenum type, GLvoid *pixels) void glTexImage1D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLint border, GLenum format, GLenum type, GLvoid *pixels) nogil
void glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLvoid *pixels) void glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLvoid *pixels) nogil
void glGetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels) void glGetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels) nogil
# Evaluators # Evaluators
void glMap1d(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, GLdouble *points) void glMap1d(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, GLdouble *points) nogil
void glMap1f(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, GLfloat *points) void glMap1f(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, GLfloat *points) nogil
void glMap2d(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble *points) void glMap2d(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble *points) nogil
void glMap2f(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat *points) void glMap2f(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat *points) nogil
void glGetMapdv(GLenum target, GLenum query, GLdouble *v) void glGetMapdv(GLenum target, GLenum query, GLdouble *v) nogil
void glGetMapfv(GLenum target, GLenum query, GLfloat *v) void glGetMapfv(GLenum target, GLenum query, GLfloat *v) nogil
void glGetMapiv(GLenum target, GLenum query, GLint *v) void glGetMapiv(GLenum target, GLenum query, GLint *v) nogil
void glEvalCoord1d(GLdouble u) void glEvalCoord1d(GLdouble u) nogil
void glEvalCoord1f(GLfloat u) void glEvalCoord1f(GLfloat u) nogil
void glEvalCoord1dv(GLdouble *u) void glEvalCoord1dv(GLdouble *u) nogil
void glEvalCoord1fv(GLfloat *u) void glEvalCoord1fv(GLfloat *u) nogil
void glEvalCoord2d(GLdouble u, GLdouble v) void glEvalCoord2d(GLdouble u, GLdouble v) nogil
void glEvalCoord2f(GLfloat u, GLfloat v) void glEvalCoord2f(GLfloat u, GLfloat v) nogil
void glEvalCoord2dv(GLdouble *u) void glEvalCoord2dv(GLdouble *u) nogil
void glEvalCoord2fv(GLfloat *u) void glEvalCoord2fv(GLfloat *u) nogil
void glMapGrid1d(GLint un, GLdouble u1, GLdouble u2) void glMapGrid1d(GLint un, GLdouble u1, GLdouble u2) nogil
void glMapGrid1f(GLint un, GLfloat u1, GLfloat u2) void glMapGrid1f(GLint un, GLfloat u1, GLfloat u2) nogil
void glMapGrid2d(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2) void glMapGrid2d(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2) nogil
void glMapGrid2f(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2) void glMapGrid2f(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2) nogil
void glEvalPoint1(GLint i) void glEvalPoint1(GLint i) nogil
void glEvalPoint2(GLint i, GLint j) void glEvalPoint2(GLint i, GLint j) nogil
void glEvalMesh1(GLenum mode, GLint i1, GLint i2) void glEvalMesh1(GLenum mode, GLint i1, GLint i2) nogil
void glEvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2) void glEvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2) nogil
# Fog # Fog
void glFogf(GLenum pname, GLfloat param) void glFogf(GLenum pname, GLfloat param) nogil
void glFogi(GLenum pname, GLint param) void glFogi(GLenum pname, GLint param) nogil
void glFogfv(GLenum pname, GLfloat *params) void glFogfv(GLenum pname, GLfloat *params) nogil
void glFogiv(GLenum pname, GLint *params) void glFogiv(GLenum pname, GLint *params) nogil
# Selection and Feedback # Selection and Feedback
void glFeedbackBuffer(GLsizei size, GLenum type, GLfloat *buffer) void glFeedbackBuffer(GLsizei size, GLenum type, GLfloat *buffer) nogil
void glPassThrough(GLfloat token) void glPassThrough(GLfloat token) nogil
void glSelectBuffer(GLsizei size, GLuint *buffer) void glSelectBuffer(GLsizei size, GLuint *buffer) nogil
void glInitNames() void glInitNames() nogil
void glLoadName(GLuint name) void glLoadName(GLuint name) nogil
void glPushName(GLuint name) void glPushName(GLuint name) nogil
void glPopName() void glPopName() nogil
# 1.1 functions # 1.1 functions
# texture objects # texture objects
void glGenTextures(GLsizei n, GLuint *textures) void glGenTextures(GLsizei n, GLuint *textures) nogil
void glDeleteTextures(GLsizei n, GLuint *textures) void glDeleteTextures(GLsizei n, GLuint *textures) nogil
void glBindTexture(GLenum target, GLuint texture) void glBindTexture(GLenum target, GLuint texture) nogil
void glPrioritizeTextures(GLsizei n, GLuint *textures, GLclampf *priorities) void glPrioritizeTextures(GLsizei n, GLuint *textures, GLclampf *priorities) nogil
GLboolean glAreTexturesResident(GLsizei n, GLuint *textures, GLboolean *residences) GLboolean glAreTexturesResident(GLsizei n, GLuint *textures, GLboolean *residences)
GLboolean glIsTexture(GLuint texture) GLboolean glIsTexture(GLuint texture)
# texture mapping # texture mapping
void glTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, GLvoid *pixels) void glTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, GLvoid *pixels) nogil
void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) nogil
void glCopyTexImage1D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border) void glCopyTexImage1D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border) nogil
void glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) void glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) nogil
void glCopyTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) void glCopyTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) nogil
void glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) void glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) nogil
# vertex arrays # vertex arrays
void glVertexPointer(GLint size, GLenum type, GLsizei stride, GLvoid *ptr) void glVertexPointer(GLint size, GLenum type, GLsizei stride, GLvoid *ptr) nogil
void glNormalPointer(GLenum type, GLsizei stride, GLvoid *ptr) void glNormalPointer(GLenum type, GLsizei stride, GLvoid *ptr) nogil
void glColorPointer(GLint size, GLenum type, GLsizei stride, GLvoid *ptr) void glColorPointer(GLint size, GLenum type, GLsizei stride, GLvoid *ptr) nogil
void glIndexPointer(GLenum type, GLsizei stride, GLvoid *ptr) void glIndexPointer(GLenum type, GLsizei stride, GLvoid *ptr) nogil
void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, GLvoid *ptr) void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, GLvoid *ptr) nogil
void glEdgeFlagPointer(GLsizei stride, GLvoid *ptr) void glEdgeFlagPointer(GLsizei stride, GLvoid *ptr) nogil
void glGetPointerv(GLenum pname, GLvoid **params) void glGetPointerv(GLenum pname, GLvoid **params) nogil
void glArrayElement(GLint i) void glArrayElement(GLint i) nogil
void glDrawArrays(GLenum mode, GLint first, GLsizei count) void glDrawArrays(GLenum mode, GLint first, GLsizei count) nogil
void glDrawElements(GLenum mode, GLsizei count, GLenum type, GLvoid *indices) void glDrawElements(GLenum mode, GLsizei count, GLenum type, GLvoid *indices) nogil
void glInterleavedArrays(GLenum format, GLsizei stride, GLvoid *pointer) void glInterleavedArrays(GLenum format, GLsizei stride, GLvoid *pointer) nogil
cdef extern from "stddef.h":
ctypedef unsigned int wchar_t
cdef extern from "GL/glu.h":
ctypedef struct GLUnurbs:
pass
ctypedef struct GLUquadric:
pass
ctypedef struct GLUtesselator:
pass
ctypedef GLUnurbs GLUnurbsObj
ctypedef GLUquadric GLUquadricObj
ctypedef GLUtesselator GLUtesselatorObj
ctypedef GLUtesselator GLUtriangulatorObj
void gluBeginCurve(GLUnurbs* nurb)
void gluBeginPolygon(GLUtesselator* tess)
void gluBeginSurface(GLUnurbs* nurb)
void gluBeginTrim(GLUnurbs* nurb)
GLint gluBuild1DMipmaps(GLenum target, GLint internalFormat, GLsizei width, GLenum format, GLenum type, void *data)
GLint gluBuild2DMipmaps(GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, void *data)
void gluCylinder(GLUquadric* quad, GLdouble base, GLdouble top, GLdouble height, GLint slices, GLint stacks)
void gluDeleteNurbsRenderer(GLUnurbs* nurb)
void gluDeleteQuadric(GLUquadric* quad)
void gluDeleteTess(GLUtesselator* tess)
void gluDisk(GLUquadric* quad, GLdouble inner, GLdouble outer, GLint slices, GLint loops)
void gluEndCurve(GLUnurbs* nurb)
void gluEndPolygon(GLUtesselator* tess)
void gluEndSurface(GLUnurbs* nurb)
void gluEndTrim(GLUnurbs* nurb)
GLubyte * gluErrorString(GLenum error)
wchar_t * gluErrorUnicodeStringEXT(GLenum error)
void gluGetNurbsProperty(GLUnurbs* nurb, GLenum property, GLfloat* data)
GLubyte * gluGetString(GLenum name)
void gluGetTessProperty(GLUtesselator* tess, GLenum which, GLdouble* data)
void gluLoadSamplingMatrices(GLUnurbs* nurb, GLfloat *model, GLfloat *perspective, GLint *view)
void gluLookAt(GLdouble eyeX, GLdouble eyeY, GLdouble eyeZ, GLdouble centerX, GLdouble centerY, GLdouble centerZ, GLdouble upX, GLdouble upY, GLdouble upZ)
GLUnurbs* gluNewNurbsRenderer()
GLUquadric* gluNewQuadric()
GLUtesselator* gluNewTess()
void gluNextContour(GLUtesselator* tess, GLenum type)
void gluNurbsCurve(GLUnurbs* nurb, GLint knotCount, GLfloat *knots, GLint stride, GLfloat *control, GLint order, GLenum type)
void gluNurbsProperty(GLUnurbs* nurb, GLenum property, GLfloat value)
void gluNurbsSurface(GLUnurbs* nurb, GLint sKnotCount, GLfloat* sKnots, GLint tKnotCount, GLfloat* tKnots, GLint sStride, GLint tStride, GLfloat* control, GLint sOrder, GLint tOrder, GLenum type)
void gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top)
void gluPartialDisk(GLUquadric* quad, GLdouble inner, GLdouble outer, GLint slices, GLint loops, GLdouble start, GLdouble sweep)
void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
void gluPickMatrix(GLdouble x, GLdouble y, GLdouble delX, GLdouble delY, GLint *viewport)
GLint gluProject(GLdouble objX, GLdouble objY, GLdouble objZ, GLdouble *model, GLdouble *proj, GLint *view, GLdouble* winX, GLdouble* winY, GLdouble* winZ)
void gluPwlCurve(GLUnurbs* nurb, GLint count, GLfloat* data, GLint stride, GLenum type)
void gluQuadricDrawStyle(GLUquadric* quad, GLenum draw)
void gluQuadricNormals(GLUquadric* quad, GLenum normal)
void gluQuadricOrientation(GLUquadric* quad, GLenum orientation)
void gluQuadricTexture(GLUquadric* quad, GLboolean texture)
GLint gluScaleImage(GLenum format, GLsizei wIn, GLsizei hIn, GLenum typeIn, void *dataIn, GLsizei wOut, GLsizei hOut, GLenum typeOut, GLvoid* dataOut)
void gluSphere(GLUquadric* quad, GLdouble radius, GLint slices, GLint stacks)
void gluTessBeginContour(GLUtesselator* tess)
void gluTessBeginPolygon(GLUtesselator* tess, GLvoid* data)
void gluTessEndContour(GLUtesselator* tess)
void gluTessEndPolygon(GLUtesselator* tess)
void gluTessNormal(GLUtesselator* tess, GLdouble valueX, GLdouble valueY, GLdouble valueZ)
void gluTessProperty(GLUtesselator* tess, GLenum which, GLdouble data)
void gluTessVertex(GLUtesselator* tess, GLdouble *location, GLvoid* data)
GLint gluUnProject(GLdouble winX, GLdouble winY, GLdouble winZ, GLdouble *model, GLdouble *proj, GLint *view, GLdouble* objX, GLdouble* objY, GLdouble* objZ)
GLint gluUnProject4(GLdouble winX, GLdouble winY, GLdouble winZ, GLdouble clipW, GLdouble *model, GLdouble *proj, GLint *view, GLdouble nearVal, GLdouble farVal, GLdouble* objX, GLdouble* objY, GLdouble* objZ, GLdouble* objW)
cdef enum: cdef enum:
GL_FALSE = 0x0 GL_FALSE = 0x0
@ -1057,153 +985,3 @@ cdef enum:
GL_CLIENT_VERTEX_ARRAY_BIT = 0x00000002 GL_CLIENT_VERTEX_ARRAY_BIT = 0x00000002
GL_ALL_CLIENT_ATTRIB_BITS = 0xFFFFFFFF GL_ALL_CLIENT_ATTRIB_BITS = 0xFFFFFFFF
GL_CLIENT_ALL_ATTRIB_BITS = 0xFFFFFFFF GL_CLIENT_ALL_ATTRIB_BITS = 0xFFFFFFFF
# Boolean
GLU_FALSE = 0
GLU_TRUE = 1
# StringName
GLU_VERSION = 100800
GLU_EXTENSIONS = 100801
# ErrorCode
GLU_INVALID_ENUM = 100900
GLU_INVALID_VALUE = 100901
GLU_OUT_OF_MEMORY = 100902
GLU_INVALID_OPERATION = 100904
# NurbsDisplay
# GLU_FILL
GLU_OUTLINE_POLYGON = 100240
GLU_OUTLINE_PATCH = 100241
# NurbsError
GLU_NURBS_ERROR1 = 100251
GLU_NURBS_ERROR2 = 100252
GLU_NURBS_ERROR3 = 100253
GLU_NURBS_ERROR4 = 100254
GLU_NURBS_ERROR5 = 100255
GLU_NURBS_ERROR6 = 100256
GLU_NURBS_ERROR7 = 100257
GLU_NURBS_ERROR8 = 100258
GLU_NURBS_ERROR9 = 100259
GLU_NURBS_ERROR10 = 100260
GLU_NURBS_ERROR11 = 100261
GLU_NURBS_ERROR12 = 100262
GLU_NURBS_ERROR13 = 100263
GLU_NURBS_ERROR14 = 100264
GLU_NURBS_ERROR15 = 100265
GLU_NURBS_ERROR16 = 100266
GLU_NURBS_ERROR17 = 100267
GLU_NURBS_ERROR18 = 100268
GLU_NURBS_ERROR19 = 100269
GLU_NURBS_ERROR20 = 100270
GLU_NURBS_ERROR21 = 100271
GLU_NURBS_ERROR22 = 100272
GLU_NURBS_ERROR23 = 100273
GLU_NURBS_ERROR24 = 100274
GLU_NURBS_ERROR25 = 100275
GLU_NURBS_ERROR26 = 100276
GLU_NURBS_ERROR27 = 100277
GLU_NURBS_ERROR28 = 100278
GLU_NURBS_ERROR29 = 100279
GLU_NURBS_ERROR30 = 100280
GLU_NURBS_ERROR31 = 100281
GLU_NURBS_ERROR32 = 100282
GLU_NURBS_ERROR33 = 100283
GLU_NURBS_ERROR34 = 100284
GLU_NURBS_ERROR35 = 100285
GLU_NURBS_ERROR36 = 100286
GLU_NURBS_ERROR37 = 100287
# NurbsProperty
GLU_AUTO_LOAD_MATRIX = 100200
GLU_CULLING = 100201
GLU_SAMPLING_TOLERANCE = 100203
GLU_DISPLAY_MODE = 100204
GLU_PARAMETRIC_TOLERANCE = 100202
GLU_SAMPLING_METHOD = 100205
GLU_U_STEP = 100206
GLU_V_STEP = 100207
# NurbsSampling
GLU_PATH_LENGTH = 100215
GLU_PARAMETRIC_ERROR = 100216
GLU_DOMAIN_DISTANCE = 100217
# NurbsTrim
GLU_MAP1_TRIM_2 = 100210
GLU_MAP1_TRIM_3 = 100211
# QuadricDrawStyle
GLU_POINT = 100010
GLU_LINE = 100011
GLU_FILL = 100012
GLU_SILHOUETTE = 100013
# QuadricCallback
GLU_ERROR = 100103
# QuadricNormal
GLU_SMOOTH = 100000
GLU_FLAT = 100001
GLU_NONE = 100002
# QuadricOrientation
GLU_OUTSIDE = 100020
GLU_INSIDE = 100021
# TessCallback
GLU_TESS_BEGIN = 100100
GLU_BEGIN = 100100
GLU_TESS_VERTEX = 100101
GLU_VERTEX = 100101
GLU_TESS_END = 100102
GLU_END = 100102
GLU_TESS_ERROR = 100103
GLU_TESS_EDGE_FLAG = 100104
GLU_EDGE_FLAG = 100104
GLU_TESS_COMBINE = 100105
GLU_TESS_BEGIN_DATA = 100106
GLU_TESS_VERTEX_DATA = 100107
GLU_TESS_END_DATA = 100108
GLU_TESS_ERROR_DATA = 100109
GLU_TESS_EDGE_FLAG_DATA = 100110
GLU_TESS_COMBINE_DATA = 100111
# TessContour
GLU_CW = 100120
GLU_CCW = 100121
GLU_INTERIOR = 100122
GLU_EXTERIOR = 100123
GLU_UNKNOWN = 100124
# TessProperty
GLU_TESS_WINDING_RULE = 100140
GLU_TESS_BOUNDARY_ONLY = 100141
GLU_TESS_TOLERANCE = 100142
# TessError
GLU_TESS_ERROR1 = 100151
GLU_TESS_ERROR2 = 100152
GLU_TESS_ERROR3 = 100153
GLU_TESS_ERROR4 = 100154
GLU_TESS_ERROR5 = 100155
GLU_TESS_ERROR6 = 100156
GLU_TESS_ERROR7 = 100157
GLU_TESS_ERROR8 = 100158
GLU_TESS_MISSING_BEGIN_POLYGON = 100151
GLU_TESS_MISSING_BEGIN_CONTOUR = 100152
GLU_TESS_MISSING_END_POLYGON = 100153
GLU_TESS_MISSING_END_CONTOUR = 100154
GLU_TESS_COORD_TOO_LARGE = 100155
GLU_TESS_NEED_COMBINE_CALLBACK = 100156
# TessWinding
GLU_TESS_WINDING_ODD = 100130
GLU_TESS_WINDING_NONZERO = 100131
GLU_TESS_WINDING_POSITIVE = 100132
GLU_TESS_WINDING_NEGATIVE = 100133
GLU_TESS_WINDING_ABS_GEQ_TWO = 100134
cdef float GLU_TESS_MAX_COORD = 1.0e150

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,4 @@
from libc.math cimport sin, cos, sqrt
from libc.stdlib cimport malloc, free
from libc.string cimport memcpy from libc.string cimport memcpy
cimport cython
include "_cyopengl.pxi" include "_cyopengl.pxi"
cdef float PI = 3.1415926535897932324626 cdef float PI = 3.1415926535897932324626
@ -11,73 +8,32 @@ cdef extern from "Python.h":
object PyBytes_FromStringAndSize(const char *s, Py_ssize_t len) object PyBytes_FromStringAndSize(const char *s, Py_ssize_t len)
const char* PyBytes_AsString(bytes o) const char* PyBytes_AsString(bytes o)
@cython.cdivision(True)
cpdef torus(float major_radius, float minor_radius, int n_major, int n_minor, tuple material, int shininess=125):
"""
Torus function from the OpenGL red book.
"""
glPushAttrib(GL_CURRENT_BIT)
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, [material[0], material[1], material[2], material[3]])
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, [1, 1, 1, 1])
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess)
assert n_major > 0 and n_minor > 0 cpdef bytes bgr_to_rgb(bytes buffer, int width, int height, bint alpha=0):
assert minor_radius > 0 and major_radius > 0
cdef float major_s, minor_s
major_s = TWOPI / n_major
minor_s = TWOPI / n_minor
cdef float a0, a1, x0, y0, x1, y1, b, c, r, z, m, x, y, z2
cdef int i, j
for i in xrange(n_major):
a0 = i * major_s
a1 = a0 + major_s
x0 = cos(a0)
y0 = sin(a0)
x1 = cos(a1)
y1 = sin(a1)
glBegin(GL_TRIANGLE_STRIP)
for j in xrange(n_minor + 1):
b = j * minor_s
c = cos(b)
r = minor_radius * c + major_radius
z = minor_radius * sin(b)
x = x0 * c
y = y0 * c
z2 = z / minor_radius
m = 1.0 / sqrt(x * x + y * y + z2 * z2)
glNormal3f(x * m, y * z, z2 * m)
glVertex3f(x0 * r, y0 * r, z)
x = x1 * c
y = y1 * c
m = 1.0 / sqrt(x * x + y * y + z2 * z2)
glNormal3f(x * m, y * z, z2 * m)
glVertex3f(x1 * r, y1 * r, z)
glEnd()
glPopAttrib()
cpdef bytes bgr_to_rgb(bytes buffer, int width, int height, bint alpha=0, bint bottom_up=1):
cdef int length = len(buffer) cdef int length = len(buffer)
cdef int depth = length / (width * height) cdef int depth = length / (width * height)
cdef int depth2 = depth - alpha cdef int depth2 = depth - alpha
cdef char *result = <char*>malloc(length) cdef object final = PyBytes_FromStringAndSize(NULL, length)
cdef char *result = PyBytes_AsString(final)
cdef const char *source = PyBytes_AsString(buffer) cdef const char *source = PyBytes_AsString(buffer)
cdef int x, y, ioffset, ooffset, i, row = width * depth cdef int x, y, offset, i, row = width * depth
for y in xrange(height): for y in xrange(height):
for x in xrange(width): for x in xrange(width):
ioffset = y * width * depth + x * depth offset = y * row + x * depth
ooffset = (height - y - 1 if bottom_up else y) * row + x * depth
for i in xrange(depth2): for i in xrange(depth2):
result[ooffset+i] = source[ioffset+depth2-i-1] result[offset+i] = source[offset+depth2-i-1]
if alpha: if alpha:
result[ooffset+depth2] = source[ioffset+depth2] result[offset+depth2] = source[offset+depth2]
cdef object final = PyBytes_FromStringAndSize(result, length) return final
free(result)
cpdef bytes flip_vertical(bytes buffer, int width, int height):
cdef int length = len(buffer)
cdef object final = PyBytes_FromStringAndSize(NULL, length)
cdef char *result = PyBytes_AsString(final)
cdef const char *source = PyBytes_AsString(buffer)
cdef int y1, y2, row = length / height
for y1 in xrange(height):
y2 = height - y1 - 1
memcpy(result + y1 * row, source + y2 * row, row)
return final return final

File diff suppressed because it is too large Load diff

View file

@ -1,357 +0,0 @@
from libc.string cimport strcmp, strlen
from libc.stdlib cimport malloc, free, atof
from libc.stdio cimport fopen, fclose, fgets, FILE
cimport cython
from punyverse.texture import load_texture
include "_cyopengl.pxi"
from uuid import uuid4
import os
cdef enum:
FACE_TRIANGLES
FACE_QUADS
cdef class Face(object):
cdef public int type
cdef public list verts, norms, texs, vertices, normals, textures
def __init__(self, int type, list verts, list norms, list texs,
list vertices, list normals, list textures):
self.type = type
self.verts = verts
self.norms = norms
self.texs = texs
self.vertices = vertices
self.normals = normals
self.textures = textures
cdef class Material(object):
cdef public str name, texture
cdef public tuple Ka, Kd, Ks
cdef public double shininess
def __init__(self, str name, str texture=None, tuple Ka=(0, 0, 0),
tuple Kd=(0, 0, 0), tuple Ks=(0, 0, 0), double shininess=0.0):
self.name = name
self.texture = texture
self.Ka = Ka
self.Kd = Kd
self.Ks = Ks
self.shininess = shininess
cdef class Group(object):
cdef public str name
cdef public tuple min
cdef public Material material
cdef public list faces, indices, vertices, normals, textures
cdef public int idx_count
def __init__(self, str name=None):
if name is None:
self.name = str(uuid4())
else:
self.name = name
self.min = ()
self.material = None
self.faces = []
self.indices = []
self.vertices = []
self.normals = []
self.textures = []
self.idx_count = 0
def pack(self):
min_x, min_y, min_z = 0, 0, 0
for face in self.faces:
for x, y, z in face.vertices:
min_x = max(min_x, abs(x))
min_y = max(min_y, abs(y))
min_z = max(min_x, abs(z))
self.min = (min_x, min_y, min_z)
cdef class WavefrontObject(object):
cdef unicode root
cdef public list vertices, normals, textures, groups
cdef public dict materials
cdef unicode path
cdef Material current_material
cdef Group current_group
def __init__(self, unicode path):
self.path = path
self.root = os.path.abspath(os.path.dirname(path))
self.vertices = []
self.normals = []
self.textures = []
self.groups = []
self.materials = {}
self.perform_io(self.path)
cdef void new_material(self, list words):
material = Material(words[1])
self.materials[words[1]] = material
self.current_material = material
cdef void Ka(self, list words):
self.current_material.Ka = (float(words[1]), float(words[2]), float(words[3]))
cdef void Kd(self, list words):
self.current_material.Kd = (float(words[1]), float(words[2]), float(words[3]))
cdef void Ks(self, list words):
self.current_material.Ks = (float(words[1]), float(words[2]), float(words[3]))
cdef void material_shininess(self, list words):
self.current_material.shininess = min(float(words[1]), 125)
cdef void material_texture(self, list words):
self.current_material.texture = words[-1]
@cython.nonecheck(False)
cdef void vertex(self, list words):
self.vertices.append((float(words[1]), float(words[2]), float(words[3])))
@cython.nonecheck(False)
cdef void normal(self, list words):
self.normals.append((float(words[1]), float(words[2]), float(words[3])))
cdef void texture(self, list words):
cdef int l = len(words)
cdef object x = 0, y = 0, z = 0
if l >= 2:
x = float(words[1])
if l >= 3:
# OBJ origin is at upper left, OpenGL origin is at lower left
y = 1 - float(words[2])
if l >= 4:
z = float(words[3])
self.textures.append((x, y, z))
cdef void face(self, list words):
cdef int l = len(words)
cdef int type = -1
cdef int vertex_count = l - 1
cdef list face_vertices = [], face_normals = [], face_textures = []
if vertex_count == 3:
type = FACE_TRIANGLES
else:
type = FACE_QUADS
cdef int current_value = -1, texture_len = len(self.textures)
cdef list raw_faces, vindices = [], nindices = [], tindices = []
for i in xrange(1, vertex_count + 1):
raw_faces = words[i].split('/')
l = len(raw_faces)
current_value = int(raw_faces[0])
vindices.append(current_value - 1)
face_vertices.append(self.vertices[current_value - 1])
if l == 1:
continue
if l >= 2 and raw_faces[1]:
current_value = int(raw_faces[1])
if current_value <= texture_len:
tindices.append(current_value - 1)
face_textures.append(self.textures[current_value - 1])
if l >= 3 and raw_faces[2]:
current_value = int(raw_faces[2])
nindices.append(current_value - 1)
face_normals.append(self.normals[current_value - 1])
cdef Group group
if self.current_group is None:
self.current_group = group = Group()
self.groups.append(group)
else:
group = self.current_group
group.vertices += face_vertices
group.normals += face_normals
group.textures += face_textures
idx_count = group.idx_count
group.indices += (idx_count + 1, idx_count + 2, idx_count + 3)
group.idx_count += 3
group.faces.append(Face(type, vindices, nindices, tindices, face_vertices, face_normals, face_textures))
cdef void material(self, list words):
self.perform_io(os.path.join(self.root, words[1]))
cdef void use_material(self, list words):
mat = words[1]
try:
self.current_group.material = self.materials[mat]
except KeyError:
print "Warning: material %s undefined, only %s defined." % (mat, self.materials)
except AttributeError:
print "Warning: no group"
cdef void group(self, list words):
name = words[1]
group = Group(name)
if self.groups:
self.current_group.pack()
self.groups.append(group)
self.current_group = group
cdef inline void perform_io(self, unicode file):
mbcsfile = file.encode('mbcs')
cdef char* fname = mbcsfile
cdef FILE* cfile
cfile = fopen(fname, 'rb')
if cfile == NULL:
raise IOError(2, "No such file or directory: '%s'" % file)
cdef size_t bufsize = 2048
cdef char *buf = <char*>malloc(bufsize)
cdef ssize_t read
cdef char *type
cdef list words
cdef int hash, length
while fgets(buf, bufsize, cfile):
if buf[0] in (0, 10, 13, 35):
continue # Empty or comment
words = buf.split()
type = words[0]
length = strlen(type)
if not length:
continue
elif length < 3:
hash = type[0] << 8 | type[1]
if hash == 0x7600: # v\0
self.vertex(words)
elif hash == 0x766e: # vn
self.normal(words)
elif hash == 0x7674: # vt
self.texture(words)
elif hash == 0x6600: # f
self.face(words)
elif hash == 0x6700: # g
self.group(words)
elif hash == 0x6f00: # o
self.group(words)
elif hash == 0x4b61: # Ka
self.Ka(words)
elif hash == 0x4b64: # Kd
self.Kd(words)
elif hash == 0x4b73: # Ks
self.Ks(words)
elif hash == 0x4e73: # Ns
self.material_shininess(words)
elif strcmp(type, b'mtllib') == 0:
self.material(words)
elif strcmp(type, b'usemtl') == 0:
self.use_material(words)
elif strcmp(type, b'newmtl') == 0:
self.new_material(words)
elif strcmp(type, b'map_Kd') == 0:
self.material_texture(words)
free(buf)
fclose(cfile)
import sys
if hasattr(sys, 'frozen'):
model_base = os.path.dirname(sys.executable)
else:
model_base = os.path.join(os.path.dirname(__file__), 'assets', 'models')
del sys
def load_model(path):
if not os.path.isabs(path):
path = os.path.join(model_base, path)
if not isinstance(path, unicode):
path = path.decode('mbcs')
return WavefrontObject(path)
@cython.nonecheck(False)
cdef inline void point(Face f, WavefrontObject m, int tex_id, float sx, float sy, float sz, int n):
cdef float x, y, z
cdef tuple normal, texture
if f.norms:
normal = m.normals[f.norms[n]]
glNormal3f(normal[0], normal[1], normal[2])
if tex_id:
texture = m.textures[f.texs[n]]
glTexCoord2f(texture[0], texture[1])
x, y, z = m.vertices[f.verts[n]]
glVertex3f(x * sx, y * sy, z * sz)
cpdef int model_list(WavefrontObject model, float sx=1, float sy=1, float sz=1, object rotation=(0, 0, 0)):
for m, text in model.materials.iteritems():
if text.texture:
load_texture(os.path.join(model.root, text.texture))
cdef int display = glGenLists(1)
glNewList(display, GL_COMPILE)
glPushMatrix()
glPushAttrib(GL_CURRENT_BIT)
cdef float pitch, yaw, roll
cdef float kx, ky, kz
pitch, yaw, roll = rotation
glPushAttrib(GL_TRANSFORM_BIT)
glRotatef(pitch, 1, 0, 0)
glRotatef(yaw, 0, 1, 0)
glRotatef(roll, 0, 0, 1)
glPopAttrib()
cdef Face f
cdef Group g
cdef int tex_id
for g in model.groups:
tex_id = load_texture(os.path.join(model.root, g.material.texture)) if (g.material and g.material.texture) else 0
if tex_id:
glEnable(GL_TEXTURE_2D)
glBindTexture(GL_TEXTURE_2D, tex_id)
else:
glBindTexture(GL_TEXTURE_2D, 0)
glDisable(GL_TEXTURE_2D)
if g.material is not None:
if g.material.texture is not None:
tex_id = load_texture(os.path.join(model.root, g.material.texture))
if g.material.Ka:
kx, ky, kz = g.material.Ka
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, [kx, ky, kz, 1])
if g.material.Kd:
kx, ky, kz = g.material.Kd
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, [kx, ky, kz, 1])
if g.material.Ks:
kx, ky, kz = g.material.Ks
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, [kx, ky, kz, 1])
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, g.material.shininess)
glBegin(GL_TRIANGLES)
for f in g.faces:
point(f, model, tex_id, sx, sy, sz, 0)
point(f, model, tex_id, sx, sy, sz, 1)
point(f, model, tex_id, sx, sy, sz, 2)
if f.type == FACE_QUADS:
point(f, model, tex_id, sx, sy, sz, 2)
point(f, model, tex_id, sx, sy, sz, 3)
point(f, model, tex_id, sx, sy, sz, 0)
glEnd()
if tex_id:
glBindTexture(GL_TEXTURE_2D, 0)
glDisable(GL_TEXTURE_2D)
glPopAttrib()
glPopMatrix()
glEndList()
return display

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,11 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl Material
Ns 92.156863
Ka 0.000000 0.000000 0.000000
Kd 0.389517 0.389517 0.389517
Ks 0.303197 0.303197 0.303197
Ni 1.000000
d 1.000000
illum 2

View file

@ -0,0 +1,188 @@
# Blender v2.68 (sub 0) OBJ File: 'mainbeltastroid.blend'
# www.blender.org
mtllib mainbelt.mtl
g Cube
v 0.290193 -0.983926 0.474791
v 0.437387 -1.185402 -0.058906
v -0.278179 0.795311 -0.169923
v -0.176207 0.961698 -0.576060
v -0.749408 0.677473 -0.403865
v -0.843249 1.101376 0.368964
v 0.921024 0.543359 -0.373421
v 1.228522 0.313481 -0.796992
v 1.413710 0.491171 0.016800
v 0.824964 -0.186862 -0.430968
v 0.169830 0.339481 0.955115
v 0.788238 0.224175 0.864338
v 0.579672 -0.319492 0.985489
v -0.850858 0.163566 0.318706
v 0.631733 -0.588108 -0.649624
v -0.094402 -0.322324 -1.249913
v -0.249124 -1.065447 -0.286061
v -0.020992 -0.954752 -0.765611
v -0.632247 -1.107953 -0.512581
v 0.124837 1.315392 0.134372
v 0.577110 0.882123 0.035559
v 0.730517 0.855449 0.648931
v -0.248585 0.742805 0.757662
v 0.897809 -0.004470 0.247323
v 0.947047 -0.715323 0.120538
v 0.998978 -0.476379 0.574922
v -0.353813 -0.204947 1.105379
v -0.981584 -0.532307 0.798081
v -0.690767 0.347252 0.944776
v -1.260799 -0.267750 -0.576518
v -0.903255 -0.554117 -0.072930
v -0.873585 -0.350903 -0.897106
v -1.083754 0.162032 -0.623495
v -0.679472 0.071680 -0.834524
v -0.150468 0.605678 -1.224164
v -0.292701 -0.962443 0.791399
v 0.496173 1.124109 -0.437672
v 0.278706 -0.267373 1.389388
vn 0.529098 -0.735317 0.423514
vn 0.695321 -0.606928 -0.384925
vn 0.383061 -0.662029 0.644190
vn 0.511064 -0.783451 0.353579
vn -0.138461 0.908731 -0.393746
vn 0.593966 0.354629 -0.722110
vn -0.359523 0.891682 0.275039
vn 0.500172 0.865296 0.033023
vn 0.619478 -0.019645 -0.784768
vn 0.619649 0.775456 -0.121254
vn 0.983189 0.132696 0.125425
vn 0.171122 0.151303 0.973563
vn 0.197398 0.332706 0.922139
vn -0.945107 0.286186 0.157704
vn -0.676128 0.735533 -0.042912
vn 0.472294 -0.437683 -0.765096
vn 0.304249 0.044783 -0.951539
vn 0.283559 0.913995 -0.290184
vn 0.830567 -0.515214 0.211455
vn -0.311526 -0.600264 -0.736637
vn 0.483338 -0.690051 -0.538714
vn -0.198815 -0.976318 0.085294
vn -0.529631 -0.847817 -0.026400
vn -0.165780 0.630247 0.758489
vn 0.699114 0.677982 0.227114
vn 0.259894 0.628514 0.733093
vn 0.677448 -0.097416 0.729091
vn 0.987177 0.091683 -0.130671
vn 0.891772 -0.211464 -0.400032
vn -0.233827 -0.388331 0.891361
vn -0.437396 -0.005360 0.899253
vn 0.072347 -0.376917 0.923417
vn -0.408216 0.016368 0.912739
vn -0.926227 -0.356903 -0.121344
vn -0.988224 0.122316 -0.091933
vn -0.501469 0.749738 -0.431766
vn -0.483647 -0.150069 -0.862302
vn -0.612900 0.611035 -0.500988
vn -0.774342 0.425106 -0.468699
vn 0.338886 -0.661704 0.668808
vn 0.178682 -0.903205 0.390248
vn -0.801728 0.596145 0.042935
vn -0.110776 0.869208 -0.481877
vn -0.805509 0.589632 0.059074
vn 0.018409 0.877560 -0.479114
vn 0.759682 -0.149805 0.632805
vn 0.713637 -0.691918 0.109416
vn 0.786427 0.594041 0.169258
vn 0.282085 0.931005 -0.231641
vn 0.583533 -0.247678 0.773398
vn 0.732741 0.478045 0.484317
vn -0.004524 0.581410 0.813598
vn -0.006905 0.433901 0.900934
vn -0.991584 0.014936 -0.128596
vn -0.563344 -0.039656 0.825270
vn -0.858666 0.466868 0.211488
vn 0.423569 -0.519252 -0.742271
vn 0.187865 -0.972846 -0.135191
vn -0.222629 -0.496977 -0.838719
vn -0.081738 -0.961894 -0.260919
vn 0.052827 -0.993867 0.097149
vn -0.766365 -0.585261 0.264864
vn 0.669742 0.730079 -0.135756
vn 0.981787 0.097127 -0.163283
vn 0.963043 0.258645 0.075174
vn -0.116467 -0.992337 0.041265
vn -0.385386 -0.892604 -0.233959
vn -0.546778 0.362906 -0.754541
vn -0.849251 -0.203792 0.487075
vn -0.445795 0.086256 -0.890970
vn -0.893227 0.392020 0.220152
vn -0.412489 0.000355 -0.910963
usemtl Material
s off
f 1//1 2//1 25//1
f 2//2 15//2 25//2
f 1//3 26//3 13//3
f 1//4 25//4 26//4
f 20//5 37//5 4//5
f 37//6 7//6 35//6
f 4//7 5//7 3//7
f 3//8 6//8 23//8
f 7//9 9//9 10//9
f 7//10 21//10 22//10
f 22//11 12//11 24//11
f 11//12 13//12 12//12
f 11//13 12//13 22//13
f 14//14 28//14 29//14
f 14//15 29//15 23//15
f 16//16 8//16 15//16
f 16//17 35//17 8//17
f 35//18 7//18 8//18
f 15//19 8//19 10//19
f 16//20 18//20 32//20
f 18//21 15//21 2//21
f 17//22 2//22 36//22
f 36//23 28//23 31//23
f 20//24 11//24 22//24
f 21//25 37//25 20//25
f 20//26 23//26 11//26
f 26//27 12//27 13//27
f 24//28 25//28 10//28
f 25//29 15//29 10//29
f 27//30 28//30 36//30
f 27//31 29//31 28//31
f 36//32 13//32 27//32
f 27//33 38//33 29//33
f 32//34 19//34 31//34
f 31//35 28//35 14//35
f 35//36 5//36 4//36
f 34//37 33//37 35//37
f 35//38 33//38 5//38
f 34//39 35//39 32//39
f 36//40 1//40 13//40
f 2//41 1//41 36//41
f 3//42 20//42 4//42
f 4//43 37//43 35//43
f 20//44 3//44 23//44
f 3//45 5//45 6//45
f 8//46 7//46 10//46
f 9//47 24//47 10//47
f 21//48 7//48 37//48
f 9//49 7//49 22//49
f 9//50 22//50 24//50
f 11//51 38//51 13//51
f 38//52 11//52 29//52
f 11//53 23//53 29//53
f 5//54 14//54 6//54
f 6//55 14//55 23//55
f 14//56 5//56 33//56
f 15//57 18//57 16//57
f 17//58 19//58 18//58
f 18//59 19//59 32//59
f 17//60 18//60 2//60
f 19//61 17//61 36//61
f 19//62 36//62 31//62
f 21//63 20//63 22//63
f 25//64 24//64 26//64
f 26//65 24//65 12//65
f 38//66 27//66 13//66
f 31//67 30//67 32//67
f 30//68 34//68 32//68
f 30//69 31//69 14//69
f 30//70 33//70 34//70
f 30//71 14//71 33//71
f 35//72 16//72 32//72

View file

@ -0,0 +1,103 @@
# Blender v2.66 (sub 1) OBJ File: ''
# www.blender.org
mtllib mainbelt.mtl
g Cube.002
v -0.289079 -0.829861 0.215310
v 0.057641 -0.817976 -0.343786
v 0.543391 -0.663372 0.025647
v -0.097897 -0.384127 -0.766643
v 0.545964 -0.487153 -0.565775
v 0.504985 -0.681732 0.425810
v 0.124050 -0.113115 0.938530
v -0.706349 -0.467985 0.350889
v -0.654122 -0.523922 -0.388949
v 0.176965 0.828195 -0.359842
v -0.383487 0.292923 -0.693979
v -0.738214 0.373419 -0.411660
v -0.714335 0.466863 0.124949
v -0.398389 0.720367 0.469422
v 0.451232 0.721178 0.355306
v 0.882521 0.137464 -0.019655
v 0.520709 0.162782 -0.672326
v 0.692252 0.151771 0.606789
v 0.088118 0.461316 0.717918
v -0.701579 0.121702 0.577301
v 0.132479 0.283880 -0.909159
vn 0.220116 -0.968562 0.115914
vn 0.121188 -0.670211 -0.732209
vn 0.190171 -0.981386 -0.026776
vn -0.062026 -0.690971 0.720217
vn -0.653070 -0.757215 0.011149
vn -0.323725 0.721233 -0.612393
vn -0.462979 0.861322 -0.209224
vn 0.018021 0.989816 0.141208
vn 0.872936 -0.045704 -0.485690
vn 0.912617 -0.392863 -0.113086
vn 0.731293 0.657305 -0.182098
vn 0.733716 0.559838 -0.385022
vn 0.919930 -0.268686 0.285545
vn 0.580622 -0.295204 0.758771
vn 0.400075 0.506643 0.763710
vn -0.295046 0.312154 0.903055
vn -0.794843 0.471399 0.382109
vn -0.998990 0.017376 0.041429
vn -0.999351 -0.005584 0.035599
vn -0.993512 -0.094698 -0.062975
vn -0.266191 0.695397 -0.667507
vn 0.273402 -0.145262 -0.950868
vn -0.385081 -0.063621 -0.920687
vn 0.461921 -0.850540 -0.251416
vn -0.256648 -0.720214 -0.644534
vn -0.357494 -0.902317 -0.240879
vn 0.550017 0.570541 -0.609888
vn -0.434722 0.890284 -0.135687
vn 0.084553 0.767893 0.634973
vn 0.848402 0.468199 0.246991
vn 0.919967 -0.385585 0.070604
vn 0.342132 0.355460 0.869824
vn -0.299721 0.325644 0.896730
vn -0.275650 -0.599397 0.751492
vn -0.454304 -0.316110 0.832876
vn -0.547764 -0.072427 -0.833492
vn 0.416633 -0.324827 -0.849061
vn -0.637398 -0.188684 -0.747076
usemtl Material
s off
f 1//1 2//1 3//1
f 4//2 5//2 2//2
f 6//3 1//3 3//3
f 7//4 1//4 6//4
f 1//5 8//5 9//5
f 10//6 11//6 12//6
f 10//7 13//7 14//7
f 10//8 14//8 15//8
f 16//9 5//9 17//9
f 3//10 5//10 16//10
f 16//11 10//11 15//11
f 16//12 17//12 10//12
f 16//13 18//13 6//13
f 7//14 6//14 18//14
f 19//15 18//15 15//15
f 19//16 14//16 20//16
f 20//17 14//17 13//17
f 20//18 13//18 12//18
f 20//19 12//19 8//19
f 12//20 9//20 8//20
f 11//21 10//21 21//21
f 17//22 5//22 4//22
f 21//23 4//23 11//23
f 3//24 2//24 5//24
f 2//25 9//25 4//25
f 2//26 1//26 9//26
f 21//27 10//27 17//27
f 13//28 10//28 12//28
f 15//29 14//29 19//29
f 18//30 16//30 15//30
f 3//31 16//31 6//31
f 7//32 18//32 19//32
f 20//33 7//33 19//33
f 1//34 7//34 8//34
f 7//35 20//35 8//35
f 9//36 12//36 4//36
f 4//37 21//37 17//37
f 11//38 4//38 12//38

View file

@ -0,0 +1,125 @@
# Blender MTL File: 'Cassini_tiny.blend'
# Material Count: 13
newmtl None
Ns 0.000000
Ka 0.000000 0.000000 0.000000
Kd 0.640000 0.640000 0.640000
Ks 0.800000 0.800000 0.800000
Ni 1.000000
d 1.000000
illum 2
newmtl aluminum
Ns 92.156863
Ka 0.000000 0.000000 0.000000
Kd 0.317021 0.317021 0.317021
Ks 1.000000 1.000000 1.000000
Ni 1.000000
d 1.000000
illum 2
newmtl black_krinkle
Ns 92.156863
Ka 0.000000 0.000000 0.000000
Kd 0.117961 0.117961 0.117961
Ks 0.500000 0.500000 0.500000
Ni 1.000000
d 1.000000
illum 2
map_Kd cassini/foil.jpg
newmtl black_krinkle_NONE
Ns 92.156863
Ka 0.000000 0.000000 0.000000
Kd 0.117961 0.117961 0.117961
Ks 0.500000 0.500000 0.500000
Ni 1.000000
d 1.000000
illum 2
map_Kd cassini/foil.jpg
newmtl black_krinkle_cassini_01_.psd.001
Ns 92.156863
Ka 0.000000 0.000000 0.000000
Kd 0.117961 0.117961 0.117961
Ks 0.500000 0.500000 0.500000
Ni 1.000000
d 1.000000
illum 2
newmtl dish_AO
Ns 92.156863
Ka 0.000000 0.000000 0.000000
Kd 0.512000 0.512000 0.512000
Ks 0.500000 0.500000 0.500000
Ni 1.000000
d 1.000000
illum 2
newmtl dish_AO_dish_AO.png
Ns 92.156863
Ka 0.000000 0.000000 0.000000
Kd 0.512000 0.512000 0.512000
Ks 0.500000 0.500000 0.500000
Ni 1.000000
d 1.000000
illum 2
newmtl foil_gold
Ns 92.156863
Ka 0.000000 0.000000 0.000000
Kd 1.0 1.0 1.0
Ks 0.5 0.5 0.5
Ni 1.000000
d 1.000000
illum 2
map_Kd cassini/tex.jpg
newmtl foil_gold_2
Ns 92.156863
Ka 0.000000 0.000000 0.000000
Kd 1.0 1.0 1.0
Ks 0.5 0.5 0.5
Ni 1.000000
d 1.000000
illum 2
map_Kd cassini/tex.jpg
newmtl plastic_dark
Ns 92.156863
Ka 0.000000 0.000000 0.000000
Kd 0.132862 0.132862 0.132862
Ks 0.500000 0.500000 0.500000
Ni 1.000000
d 1.000000
illum 2
newmtl plastic_white
Ns 92.156863
Ka 0.000000 0.000000 0.000000
Kd 0.593267 0.593267 0.593267
Ks 0.500000 0.500000 0.500000
Ni 1.000000
d 1.000000
illum 2
newmtl tex_01
Ns 92.156863
Ka 0.000000 0.000000 0.000000
Kd 0.512000 0.512000 0.512000
Ks 0.500000 0.500000 0.500000
Ni 1.000000
d 1.000000
illum 2
map_Kd cassini/tex.jpg
newmtl tex_01_NONE
Ns 92.156863
Ka 0.000000 0.000000 0.000000
Kd 0.512000 0.512000 0.512000
Ks 0.500000 0.500000 0.500000
Ni 1.000000
d 1.000000
illum 2
map_Kd cassini/tex.jpg

File diff suppressed because it is too large Load diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View file

@ -0,0 +1,52 @@
# Blender MTL File: 'None'
# Material Count: 5
newmtl hbltel_1
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.467451 0.467451 0.467451
Ks 0.449020 0.449020 0.449020
Ni 1.000000
d 1.000000
illum 2
map_Kd hbltel_1.jpg
newmtl hbltel_2
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.467451 0.467451 0.467451
Ks 0.449020 0.449020 0.449020
Ni 1.000000
d 1.000000
illum 2
map_Kd hbltel_2.jpg
newmtl hbltel_3
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.467451 0.467451 0.467451
Ks 0.449020 0.449020 0.449020
Ni 1.000000
d 1.000000
illum 2
map_Kd hbltel_3.jpg
newmtl hbltel_4
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.467451 0.467451 0.467451
Ks 0.449020 0.449020 0.449020
Ni 1.000000
d 1.000000
illum 2
map_Kd hbltel_4.jpg
newmtl hbltel_wfc_1
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.467451 0.467451 0.467451
Ks 0.449020 0.449020 0.449020
Ni 1.000000
d 1.000000
illum 2
map_Kd hbltel_w.jpg

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,34 @@
# This file contains all the textures that is bigger than the minimum OpenGL texture size
# and hence may need to be resized depending on the machine
sun.jpg
mercury.jpg
venus.jpg
earth.jpg
earth_normal.jpg
earth_emission.jpg
earth_specular.jpg
cloudmap.jpg
moon.jpg
mars.jpg
jupiter.jpg
saturn.jpg
uranus.jpg
neptune.jpg
sky_px.jpg
sky_py.jpg
sky_pz.jpg
sky_nx.jpg
sky_ny.jpg
sky_nz.jpg
moons/io.jpg
moons/europa.jpg
moons/ganymede.jpg
moons/callisto.jpg
moons/titan.jpg
moons/rhea.jpg
moons/iapetus.jpg
moons/dione.jpg
moons/tethys.jpg
moons/enceladus.jpg
moons/mimas.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 176 KiB

After

Width:  |  Height:  |  Size: 981 KiB

View file

@ -1,4 +1,9 @@
from math import sin, cos, radians from __future__ import division
from math import sin, cos, radians, hypot, tan
from punyverse.glgeom import Matrix4f
from punyverse.utils import cached_property
class Camera(object): class Camera(object):
@ -10,12 +15,23 @@ class Camera(object):
self.yaw = yaw self.yaw = yaw
self.roll = roll self.roll = roll
self.fov = radians(45)
self.aspect = 1
self.znear = 1
self.zfar = 3000000
self.speed = 0
self.roll_left = False
self.roll_right = False
def move(self, speed): def move(self, speed):
dx, dy, dz = self.direction() dx, dy, dz = self.direction()
self.x += dx * speed self.x += dx * speed
self.y += dy * speed self.y += dy * speed
self.z += dz * speed self.z += dz * speed
self.view_matrix = None
def mouse_move(self, dx, dy): def mouse_move(self, dx, dy):
if self.pitch > 90 or self.pitch < -90: if self.pitch > 90 or self.pitch < -90:
dx = -dx dx = -dx
@ -32,6 +48,8 @@ class Camera(object):
elif self.pitch > 180: elif self.pitch > 180:
self.pitch -= 360 self.pitch -= 360
self.view_matrix = None
def direction(self): def direction(self):
m = cos(radians(self.pitch)) m = cos(radians(self.pitch))
@ -39,3 +57,33 @@ class Camera(object):
dx = cos(radians(self.yaw - 90)) * m dx = cos(radians(self.yaw - 90)) * m
dz = sin(radians(self.yaw - 90)) * m dz = sin(radians(self.yaw - 90)) * m
return dx, dy, dz return dx, dy, dz
def update(self, dt, move):
if self.roll_left:
self.roll -= 4 * dt * 10
self.view_matrix = None
if self.roll_right:
self.roll += 4 * dt * 10
self.view_matrix = None
if move:
self.move(self.speed * 10 * dt)
def reset_roll(self):
self.roll = 0
self.view_matrix = None
def distance(self, x, y, z):
return hypot(hypot(x - self.x, y - self.y), z - self.z)
@cached_property
def view_matrix(self):
return Matrix4f.from_angles((self.x, self.y, self.z), (self.pitch, self.yaw, self.roll), view=True)
def projection_matrix(self):
scale_y = 1 / tan(self.fov / 2)
scale_x = scale_y / self.aspect
frustrum = self.znear - self.zfar
return Matrix4f([scale_x, 0, 0, 0,
0, scale_y, 0, 0,
0, 0, (self.znear + self.zfar) / frustrum, -1,
0, 0, (2 * self.znear * self.zfar) / frustrum, 0])

View file

@ -1,115 +1,597 @@
from punyverse.orbit import KeplerOrbit import random
from math import sqrt, pi
from pyglet.gl import * from pyglet.gl import *
# noinspection PyUnresolvedReferences
from six.moves import range
from punyverse.glgeom import *
from punyverse.model import load_model, WavefrontVBO
from punyverse.orbit import KeplerOrbit
from punyverse.texture import get_best_texture, load_alpha_mask, get_cube_map, load_texture_1d
from punyverse.utils import cached_property
G = 6.67384e-11 # Gravitation Constant
class Entity(object): class Entity(object):
def __init__(self, id, location, rotation=(0, 0, 0), direction=(0, 0, 0), background=False): background = False
self.id = id
def __init__(self, world, name, location, rotation=(0, 0, 0), direction=(0, 0, 0)):
self.world = world
self.name = name
self.location = location self.location = location
self.rotation = rotation self.rotation = rotation
self.direction = direction self.direction = direction
self.background = background
@cached_property
def model_matrix(self):
return Matrix4f.from_angles(self.location, self.rotation)
@cached_property
def mv_matrix(self):
return self.world.view_matrix() * self.model_matrix
@cached_property
def mvp_matrix(self):
return self.world.vp_matrix * self.model_matrix
def update(self): def update(self):
self.model_matrix = None
self.mv_matrix = None
self.mvp_matrix = None
x, y, z = self.location x, y, z = self.location
dx, dy, dz = self.direction dx, dy, dz = self.direction
self.location = x + dx, y + dy, z + dz self.location = x + dx, y + dy, z + dz
def collides(self, x, y, z):
return False
def draw(self, options):
raise NotImplementedError()
class Asteroid(Entity): class Asteroid(Entity):
def __init__(self, *args, **kwargs): def __init__(self, world, model, location, direction):
super(Asteroid, self).__init__(*args, **kwargs) super(Asteroid, self).__init__(world, 'Asteroid', location, direction=direction)
self.model = model
def update(self): def update(self):
super(Asteroid, self).update() super(Asteroid, self).update()
rx, ry, rz = self.rotation rx, ry, rz = self.rotation
# Increment all axis to 'spin' # Increment all axis to 'spin'
self.rotation = rx + 1, ry + 1, rz + 1 self.rotation = rx + 1, ry + 1, rz + 1
def draw(self, options):
shader = self.world.activate_shader('model')
shader.uniform_mat4('u_mvpMatrix', self.mvp_matrix)
shader.uniform_mat4('u_mvMatrix', self.mv_matrix)
shader.uniform_mat4('u_modelMatrix', self.model_matrix)
self.model.draw(shader)
class AsteroidManager(object):
def __init__(self, world):
self.world = world
self.asteroids = []
def __bool__(self):
return bool(self.asteroids)
__nonzero__ = __bool__
def load(self, file):
shader = self.world.activate_shader('model')
self.asteroids.append(WavefrontVBO(load_model(file), shader, 5, 5, 5))
def new(self, location, direction):
return Asteroid(self.world, random.choice(self.asteroids), location, direction)
class Belt(Entity):
def __init__(self, name, world, info):
x = world.evaluate(info.get('x', 0))
y = world.evaluate(info.get('y', 0))
z = world.evaluate(info.get('z', 0))
radius = world.evaluate(info.get('radius', 0))
cross = world.evaluate(info.get('cross', 0))
count = int(world.evaluate(info.get('count', 0)))
scale = info.get('scale', 1)
longitude = info.get('longitude', 0)
inclination = info.get('inclination', 0)
argument = info.get('argument', 0)
rotation = info.get('period', 31536000)
models = info['model']
self.rotation_angle = 360.0 / rotation if rotation else 0
shader = world.activate_shader('belt')
if not isinstance(models, list):
models = [models]
self.belt = BeltVBO(radius, cross, len(models), count)
self.objects = [
WavefrontVBO(load_model(model), shader, info.get('sx', scale),
info.get('sy', scale), info.get('sz', scale))
for model in models
]
def callback():
glBindBuffer(GL_ARRAY_BUFFER, vbo)
shader.vertex_attribute('a_translate', self.belt.location_size, self.belt.type, GL_FALSE,
self.belt.stride, self.belt.location_offset, divisor=1)
shader.vertex_attribute('a_scale', self.belt.scale_size, self.belt.type, GL_FALSE,
self.belt.stride, self.belt.scale_offset, divisor=1)
glBindBuffer(GL_ARRAY_BUFFER, 0)
for model, vbo, count in zip(self.objects, self.belt.vbo, self.belt.sizes):
model.additional_attributes(callback)
super(Belt, self).__init__(world, name, (x, y, z), (inclination, longitude, argument))
def update(self):
super(Belt, self).update()
pitch, yaw, roll = self.rotation
self.rotation = pitch, self.world.tick * self.rotation_angle % 360, roll
def draw(self, options):
shader = self.world.activate_shader('belt')
shader.uniform_mat4('u_mvpMatrix', self.mvp_matrix)
shader.uniform_mat4('u_mvMatrix', self.mv_matrix)
shader.uniform_mat4('u_modelMatrix', self.model_matrix)
for object, vbo, count in zip(self.objects, self.belt.vbo, self.belt.sizes):
object.draw(shader, instances=count)
class Sky(Entity):
background = True
def __init__(self, world, info, callback=None):
pitch = world.evaluate(info.get('pitch', 0))
yaw = world.evaluate(info.get('yaw', 0))
roll = world.evaluate(info.get('roll', 0))
super(Sky, self).__init__(world, 'Sky', (0, 0, 0), [pitch, yaw, roll])
self.texture = get_best_texture(info['texture'], loader=get_cube_map, callback=callback)
self.constellation = get_cube_map(info['constellation'])
self.cube = Cube()
self.vao = VAO()
shader = self.world.activate_shader('sky')
with self.vao:
glBindBuffer(GL_ARRAY_BUFFER, self.cube.vbo)
shader.vertex_attribute('a_direction', self.cube.direction_size, self.cube.type, GL_FALSE,
self.cube.stride, self.cube.direction_offset)
glBindBuffer(GL_ARRAY_BUFFER, 0)
def draw(self, options):
cam = self.world.cam
shader = self.world.activate_shader('sky')
shader.uniform_mat4('u_mvpMatrix', self.world.projection_matrix() *
Matrix4f.from_angles(rotation=(cam.pitch, cam.yaw, cam.roll)) *
Matrix4f.from_angles(rotation=self.rotation))
glBindTexture(GL_TEXTURE_CUBE_MAP, self.texture)
shader.uniform_texture('u_skysphere', 0)
glActiveTexture(GL_TEXTURE1)
glBindTexture(GL_TEXTURE_CUBE_MAP, self.constellation)
shader.uniform_texture('u_constellation', 1)
shader.uniform_bool('u_lines', options.constellations)
with self.vao:
glDrawArrays(GL_TRIANGLES, 0, self.cube.vertex_count)
glActiveTexture(GL_TEXTURE0)
class Body(Entity): class Body(Entity):
def __init__(self, *args, **kwargs): def __init__(self, name, world, info, parent=None):
self.rotation_angle = kwargs.pop('rotation_angle', 5) self.parent = parent
self.atmosphere = kwargs.pop('atmosphere', 0) self.satellites = []
self.cloudmap = kwargs.pop('cloudmap', 0)
self.last_tick = 0 x = world.evaluate(info.get('x', 0))
self.mass = kwargs.pop('mass', None) y = world.evaluate(info.get('y', 0))
self.world = kwargs.pop('world') z = world.evaluate(info.get('z', 0))
orbit_distance = kwargs.pop('orbit_distance', 40000) + .0 pitch = world.evaluate(info.get('pitch', 0))
yaw = world.evaluate(info.get('yaw', 0))
roll = world.evaluate(info.get('roll', 0))
rotation = world.evaluate(info.get('rotation', 86400))
self.mass = info.get('mass')
orbit_distance = float(world.evaluate(info.get('orbit_distance', world.au)))
self.orbit_show = orbit_distance * 1.25 self.orbit_show = orbit_distance * 1.25
self.orbit_blend = orbit_distance / 4 self.orbit_blend = orbit_distance / 4
self.orbit_opaque = orbit_distance self.orbit_opaque = orbit_distance
super(Body, self).__init__(*args, **kwargs)
self.initial_roll = self.rotation[2] super(Body, self).__init__(world, name, (x, y, z), (pitch, yaw, roll))
self.initial_roll = roll
self.orbit = None
self.orbit_speed = None
if parent:
# Semi-major axis when actually displayed in virtual space
distance = world.evaluate(info.get('distance', 100))
# Semi-major axis used to calculate orbital speed
sma = world.evaluate(info.get('sma', distance))
if hasattr(parent, 'mass') and parent.mass is not None:
period = 2 * pi * sqrt((sma * 1000) ** 3 / (G * parent.mass))
self.orbit_speed = 360.0 / period
if not rotation: # Rotation = 0 assumes tidal lock
rotation = period
else:
self.orbit_speed = info.get('orbit_speed', 1)
self.orbit = KeplerOrbit(distance / world.length, info.get('eccentricity', 0), info.get('inclination', 0),
info.get('longitude', 0), info.get('argument', 0))
self.rotation_angle = 360.0 / rotation if rotation else 0
# Orbit calculation
self.orbit_vbo = None
self.orbit_vao = None
self.orbit_cache = None
@cached_property
def orbit_matrix(self):
return self.world.view_matrix() * Matrix4f.from_angles(self.location)
def update(self): def update(self):
super(Body, self).update() super(Body, self).update()
if self.last_tick != self.world.tick: if self.rotation_angle:
self.last_tick = self.world.tick
pitch, yaw, roll = self.rotation pitch, yaw, roll = self.rotation
roll = (self.initial_roll + self.world.tick * self.rotation_angle) % 360 roll = (self.initial_roll + self.world.tick * self.rotation_angle) % 360
self.rotation = pitch, yaw, roll self.rotation = pitch, yaw, roll
if self.orbit:
px, py, pz = self.parent.location
x, z, y = self.orbit.orbit(self.world.tick * self.orbit_speed % 360)
self.location = (x + px, y + py, z + pz)
self.orbit_matrix = None
class Satellite(Body): for satellite in self.satellites:
def __init__(self, *args, **kwargs): satellite.update()
self.parent = kwargs.pop('parent')
self.orbit_speed = kwargs.pop('orbit_speed', 1)
# Semi-major axis and eccentricity defines orbit def get_orbit(self, shader):
distance = kwargs.pop('distance', 100) if not self.orbit:
eccentricity = kwargs.pop('eccentricity', 0) return
# Inclination, longitude of ascending node, and argument of periapsis defines orbital plane
inclination = kwargs.pop('inclination', 0)
longitude = kwargs.pop('longitude', 0)
argument = kwargs.pop('argument', 0)
# Orbit calculation
self.orbit_id = None
self.orbit_cache = None
self.theta = 0
# OpenGL's z-axis is reversed
self.orbit = KeplerOrbit(distance, eccentricity, inclination, longitude, argument)
super(Satellite, self).__init__(*args, **kwargs)
def get_orbit(self):
# Cache key is the three orbital plane parameters and eccentricity # Cache key is the three orbital plane parameters and eccentricity
cache = (self.orbit.eccentricity, self.orbit.longitude, self.orbit.inclination, self.orbit.argument) cache = (self.orbit.eccentricity, self.orbit.longitude, self.orbit.inclination, self.orbit.argument)
if self.orbit_cache == cache: if self.orbit_cache == cache:
return self.orbit_id return self.orbit_vbo, self.orbit_vao
if self.orbit_id is not None: if self.orbit_vbo is not None:
glDeleteLists(self.orbit_id, 1) self.orbit_vbo.close()
id = glGenLists(1) if self.orbit_vao is not None:
glNewList(id, GL_COMPILE) self.orbit_vao.close()
glBegin(GL_LINE_LOOP)
for theta in xrange(360): self.orbit_vbo = OrbitVBO(self.orbit)
x, z, y = self.orbit.orbit(theta) self.orbit_vao = VAO()
glVertex3f(x, y, z)
glEnd() with self.orbit_vao:
glEndList() glBindBuffer(GL_ARRAY_BUFFER, self.orbit_vbo.vbo)
shader.vertex_attribute('a_position', self.orbit_vbo.position_size, self.orbit_vbo.type, GL_FALSE,
self.orbit_vbo.stride, self.orbit_vbo.position_offset)
self.orbit_id = id
self.orbit_cache = cache self.orbit_cache = cache
return id return self.orbit_vbo, self.orbit_vao
def update(self): def _draw_orbits(self, distance):
super(Body, self).update() # Notice how the parent class is skipped shader = self.world.activate_shader('line')
solid = distance < self.parent.orbit_opaque
alpha = 1 if solid else (1 - (distance - self.parent.orbit_opaque) / self.parent.orbit_blend)
shader.uniform_vec4('u_color', 1, 1, 1, alpha)
shader.uniform_mat4('u_mvpMatrix', self.world.projection_matrix() * self.parent.orbit_matrix)
if not solid:
glEnable(GL_BLEND)
vbo, vao = self.get_orbit(shader)
with vao:
glDrawArrays(GL_LINE_LOOP, 0, vbo.vertex_count)
if not solid:
glDisable(GL_BLEND)
def draw(self, options):
self._draw(options)
if options.orbit and self.orbit:
dist = self.world.cam.distance(*self.parent.location)
if dist < self.parent.orbit_show:
self._draw_orbits(dist)
for satellite in self.satellites:
satellite.draw(options)
def _draw(self, options):
raise NotImplementedError()
def collides(self, x, y, z):
return self._collides(x, y, z) or any(satellite.collides(x, y, z) for satellite in self.satellites)
def _collides(self, x, y, z):
return False
class SphericalBody(Body):
_sphere_cache = {}
@classmethod
def _get_sphere(cls, division, tangent=True):
if (division, tangent) in cls._sphere_cache:
return cls._sphere_cache[division, tangent]
cls._sphere_cache[division, tangent] = sphere = \
(TangentSphere if tangent else SimpleSphere)(division, division)
return sphere
def __init__(self, name, world, info, parent=None):
super(SphericalBody, self).__init__(name, world, info, parent)
self.radius = world.evaluate(info.get('radius', world.length)) / world.length
division = info.get('division', max(min(int(self.radius / 8), 60), 10))
self.light_source = info.get('light_source', False)
self.shininess = info.get('shininess', 0)
self.type = info.get('type', 'planet')
self.texture = get_best_texture(info['texture'])
self.normal_texture = None
self.specular_texture = None
self.emission_texture = None
self.sphere = self._get_sphere(division, tangent=self.type == 'planet')
self.vao = VAO()
if self.type == 'planet':
shader = self.world.activate_shader('planet')
with self.vao:
glBindBuffer(GL_ARRAY_BUFFER, self.sphere.vbo)
shader.vertex_attribute('a_normal', self.sphere.direction_size, self.sphere.type, GL_FALSE,
self.sphere.stride, self.sphere.direction_offset)
shader.vertex_attribute('a_tangent', self.sphere.tangent_size, self.sphere.type, GL_FALSE,
self.sphere.stride, self.sphere.tangent_offset)
shader.vertex_attribute('a_uv', self.sphere.uv_size, self.sphere.type, GL_FALSE,
self.sphere.stride, self.sphere.uv_offset)
glBindBuffer(GL_ARRAY_BUFFER, 0)
elif self.type == 'star':
shader = self.world.activate_shader('star')
with self.vao:
glBindBuffer(GL_ARRAY_BUFFER, self.sphere.vbo)
shader.vertex_attribute('a_normal', self.sphere.direction_size, self.sphere.type, GL_FALSE,
self.sphere.stride, self.sphere.direction_offset)
shader.vertex_attribute('a_uv', self.sphere.uv_size, self.sphere.type, GL_FALSE,
self.sphere.stride, self.sphere.uv_offset)
glBindBuffer(GL_ARRAY_BUFFER, 0)
else:
raise ValueError('Invalid type: %s' % self.type)
self.atmosphere = None
self.clouds = None
self.ring = 0
if 'normal_map' in info:
self.normal_texture = get_best_texture(info['normal_map'])
if 'specular_map' in info:
self.specular_texture = get_best_texture(info['specular_map'])
if 'emission_map' in info:
self.emission_texture = get_best_texture(info['emission_map'])
if 'atmosphere' in info:
atmosphere_data = info['atmosphere']
atm_size = world.evaluate(atmosphere_data.get('glow_size', None))
atm_texture = atmosphere_data.get('glow_texture', None)
atm_color = atmosphere_data.get('glow_color', None)
cloud_texture = atmosphere_data.get('cloud_texture', None)
if cloud_texture is not None:
self.cloud_transparency = get_best_texture(cloud_texture, loader=load_alpha_mask)
self.cloud_radius = self.radius + 2
self.clouds = self._get_sphere(division, tangent=False)
self.cloud_vao = VAO()
shader = self.world.activate_shader('clouds')
with self.cloud_vao:
glBindBuffer(GL_ARRAY_BUFFER, self.clouds.vbo)
shader.vertex_attribute('a_normal', self.clouds.direction_size, self.clouds.type, GL_FALSE,
self.clouds.stride, self.clouds.direction_offset)
shader.vertex_attribute('a_uv', self.clouds.uv_size, self.clouds.type, GL_FALSE,
self.clouds.stride, self.clouds.uv_offset)
glBindBuffer(GL_ARRAY_BUFFER, 0)
if atm_texture is not None and atm_color is not None:
self.atm_texture = load_texture_1d(atm_texture, clamp=True)
self.atm_color = atm_color
self.atmosphere = Disk(self.radius, self.radius + atm_size, 30)
self.atmosphere_vao = VAO()
shader = self.world.activate_shader('atmosphere')
with self.atmosphere_vao:
glBindBuffer(GL_ARRAY_BUFFER, self.atmosphere.vbo)
shader.vertex_attribute('a_position', self.atmosphere.position_size, self.atmosphere.type, GL_FALSE,
self.atmosphere.stride, self.atmosphere.position_offset)
shader.vertex_attribute('a_u', self.atmosphere.u_size, self.atmosphere.type, GL_FALSE,
self.atmosphere.stride, self.atmosphere.u_offset)
glBindBuffer(GL_ARRAY_BUFFER, 0)
if 'ring' in info:
distance = world.evaluate(info['ring'].get('distance', self.radius * 1.2))
size = world.evaluate(info['ring'].get('size', self.radius / 2))
if self.last_tick != self.world.tick:
self.last_tick = self.world.tick
pitch, yaw, roll = self.rotation pitch, yaw, roll = self.rotation
roll = (self.initial_roll + self.world.tick * self.rotation_angle) % 360 pitch = world.evaluate(info['ring'].get('pitch', pitch))
self.rotation = pitch, yaw, roll yaw = world.evaluate(info['ring'].get('yaw', yaw))
roll = world.evaluate(info['ring'].get('roll', roll))
self.ring_rotation = pitch, yaw, roll
self.parent.update() self.ring_texture = load_texture_1d(info['ring'].get('texture'), clamp=True)
px, py, pz = self.parent.location self.ring = Disk(distance, distance + size, 30)
self.theta = self.world.tick * self.orbit_speed % 360
x, z, y = self.orbit.orbit(self.theta)
self.location = (x + px, y + py, z + pz)
self.ring_vao = VAO()
shader = self.world.activate_shader('ring')
with self.ring_vao:
glBindBuffer(GL_ARRAY_BUFFER, self.ring.vbo)
shader.vertex_attribute('a_position', self.ring.position_size, self.ring.type, GL_FALSE,
self.ring.stride, self.ring.position_offset)
shader.vertex_attribute('a_u', self.ring.u_size, self.ring.type, GL_FALSE,
self.ring.stride, self.ring.u_offset)
glBindBuffer(GL_ARRAY_BUFFER, 0)
def _draw_planet(self):
shader = self.world.activate_shader('planet')
shader.uniform_float('u_radius', self.radius)
shader.uniform_mat4('u_modelMatrix', self.model_matrix)
shader.uniform_mat4('u_mvMatrix', self.mv_matrix)
shader.uniform_mat4('u_mvpMatrix', self.mvp_matrix)
glBindTexture(GL_TEXTURE_2D, self.texture)
shader.uniform_texture('u_planet.diffuseMap', 0)
shader.uniform_bool('u_planet.hasNormal', self.normal_texture)
if self.normal_texture:
glActiveTexture(GL_TEXTURE1)
glBindTexture(GL_TEXTURE_2D, self.normal_texture)
shader.uniform_texture('u_planet.normalMap', 1)
shader.uniform_bool('u_planet.hasSpecular', self.specular_texture)
if self.specular_texture:
glActiveTexture(GL_TEXTURE2)
glBindTexture(GL_TEXTURE_2D, self.specular_texture)
shader.uniform_texture('u_planet.specularMap', 2)
shader.uniform_vec3('u_planet.specular', 1, 1, 1)
shader.uniform_float('u_planet.shininess', 10)
else:
shader.uniform_vec3('u_planet.specular', 0, 0, 0)
shader.uniform_float('u_planet.shininess', 0)
shader.uniform_bool('u_planet.hasEmission', self.emission_texture)
if self.emission_texture:
glActiveTexture(GL_TEXTURE3)
glBindTexture(GL_TEXTURE_2D, self.emission_texture)
shader.uniform_texture('u_planet.emissionMap', 3)
shader.uniform_vec3('u_planet.ambient', 0, 0, 0)
shader.uniform_vec3('u_planet.emission', 1, 1, 1)
else:
shader.uniform_vec3('u_planet.ambient', 1, 1, 1)
shader.uniform_vec3('u_planet.emission', 0, 0, 0)
shader.uniform_vec3('u_planet.diffuse', 1, 1, 1)
with self.vao:
glDrawArrays(GL_TRIANGLE_STRIP, 0, self.sphere.vertex_count)
glActiveTexture(GL_TEXTURE0)
def _draw_star(self):
shader = self.world.activate_shader('star')
shader.uniform_float('u_radius', self.radius)
shader.uniform_mat4('u_mvpMatrix', self.mvp_matrix)
glBindTexture(GL_TEXTURE_2D, self.texture)
shader.uniform_texture('u_emission', 0)
with self.vao:
glDrawArrays(GL_TRIANGLE_STRIP, 0, self.sphere.vertex_count)
def _draw_sphere(self):
if self.type == 'planet':
self._draw_planet()
elif self.type == 'star':
self._draw_star()
def _draw_atmosphere(self):
glEnable(GL_BLEND)
glDisable(GL_CULL_FACE)
shader = self.world.activate_shader('atmosphere')
mv = self.mv_matrix.matrix
matrix = Matrix4f([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, mv[12], mv[13], mv[14], 1])
shader.uniform_mat4('u_mvpMatrix', self.world.projection_matrix() * matrix)
glBindTexture(GL_TEXTURE_1D, self.atm_texture)
shader.uniform_texture('u_transparency', 0)
shader.uniform_vec3('u_color', *self.atm_color)
with self.atmosphere_vao:
glDrawArrays(GL_TRIANGLE_STRIP, 0, self.atmosphere.vertex_count)
glDisable(GL_BLEND)
glEnable(GL_CULL_FACE)
def _draw_clouds(self):
glEnable(GL_BLEND)
shader = self.world.activate_shader('clouds')
shader.uniform_float('u_radius', self.cloud_radius)
shader.uniform_mat4('u_modelMatrix', self.model_matrix)
shader.uniform_mat4('u_mvpMatrix', self.mvp_matrix)
glBindTexture(GL_TEXTURE_2D, self.cloud_transparency)
shader.uniform_texture('u_transparency', 0)
shader.uniform_vec3('u_diffuse', 1, 1, 1)
shader.uniform_vec3('u_ambient', 0.1, 0.1, 0.1)
with self.cloud_vao:
glDrawArrays(GL_TRIANGLE_STRIP, 0, self.clouds.vertex_count)
glDisable(GL_BLEND)
def _draw_rings(self):
glEnable(GL_BLEND)
glDisable(GL_CULL_FACE)
shader = self.world.activate_shader('ring')
shader.uniform_mat4('u_modelMatrix', self.model_matrix)
shader.uniform_mat4('u_mvpMatrix', self.mvp_matrix)
shader.uniform_vec3('u_planet', *self.location)
shader.uniform_vec3('u_sun', 0, 0, 0)
shader.uniform_float('u_planetRadius', self.radius)
shader.uniform_float('u_ambient', 0.1)
glBindTexture(GL_TEXTURE_1D, self.ring_texture)
shader.uniform_texture('u_texture', 0)
with self.ring_vao:
glDrawArrays(GL_TRIANGLE_STRIP, 0, self.ring.vertex_count)
glDisable(GL_BLEND)
glEnable(GL_CULL_FACE)
def _draw(self, options):
self._draw_sphere()
if options.atmosphere and self.atmosphere:
self._draw_atmosphere()
if options.cloud and self.clouds:
self._draw_clouds()
if self.ring:
self._draw_rings()
def _collides(self, x, y, z):
ox, oy, oz = self.location
dx, dy, dz = x - ox, y - oy, z - oz
distance = sqrt(dx * dx + dy * dy + dz * dz)
return distance <= self.radius
class ModelBody(Body):
def __init__(self, name, world, info, parent=None):
super(ModelBody, self).__init__(name, world, info, parent)
scale = info.get('scale', 1)
shader = world.activate_shader('model')
self.vbo = WavefrontVBO(load_model(info['model']), shader, info.get('sx', scale),
info.get('sy', scale), info.get('sz', scale))
def _draw(self, options):
shader = self.world.activate_shader('model')
shader.uniform_mat4('u_mvpMatrix', self.mvp_matrix)
shader.uniform_mat4('u_mvMatrix', self.mv_matrix)
shader.uniform_mat4('u_modelMatrix', self.model_matrix)
self.vbo.draw(shader)

View file

@ -1,354 +0,0 @@
#!/usr/bin/python
from operator import attrgetter
from math import hypot, sqrt, atan2, degrees
from time import clock
import time
import random
from punyverse.camera import Camera
from punyverse.world import load_world
from punyverse.glgeom import *
from punyverse.entity import Asteroid
from punyverse import texture
try:
from punyverse._model import model_list, load_model
except ImportError:
from punyverse.model import model_list, load_model
from pyglet.gl import *
from pyglet.window import key
import pyglet
INITIAL_SPEED = 0 # The initial speed of the player
TICKS_PER_SECOND = 20 # How many times to update game per second
MOUSE_SENSITIVITY = 0.3 # Mouse sensitivity, 0..1, none...hyperspeed
MAX_DELTA = 5
SEED = int(time.time())
def entity_distance(x0, y0, z0):
def distance(entity):
x1, y1, z1 = entity.location
return hypot(hypot(x1 - x0, y1 - y0), z1 - z0)
return distance
class Applet(pyglet.window.Window):
def update(self, dt):
cam = self.cam
if self.exclusive:
if key.A in self.keys:
cam.roll += 4
if key.S in self.keys:
cam.roll -= 4
cam.move(self.speed)
if self.running:
self.world.tick += self.tick
for entity in self.world.tracker:
entity.update()
def __init__(self, *args, **kwargs):
super(Applet, self).__init__(*args, **kwargs)
l = clock()
self.fps = 0
self.world = load_world("world.json")
self.speed = INITIAL_SPEED
self.keys = set()
self.info = True
self.debug = False
self.orbit = True
self.running = True
self.tick = self.world.tick_length
# On standard world: 10x is one day per second, 100x is 10 days, 300x is a month
# 900x is a quarter, 1825 is a half year, 3650 is a year, 36500 is a decade, 365000 is a century
# and yes the individual hours and seconds look ugly
self.ticks = [20, 40, 60, # Second range
120, 300, 600, 1200, 1800, 2700, 3600, # Minute range
7200, 14400, 21600, 43200, 86400, # Hour range
172800, 432000, 604800, # 2, 5, 7 days
1209600, 2592000, # 2 week, 1 month
5270400, 7884000, 15768000, 31536000, # 2, 3, 6, 12 months
63072000, 157680000, 315360000, # 2, 5, 10 years
630720000, 1576800000, 3153600000, # 20, 50, 100 years
]
self.ticks = [i / 20 for i in self.ticks]
self.__time_per_second_cache = None
self.__time_per_second_value = None
self.label = pyglet.text.Label('', font_name='Consolas', font_size=12, x=10, y=self.height - 20,
color=(255,) * 4, multiline=True, width=600)
self.cam = Camera()
self.exclusive = False
pyglet.clock.schedule_interval(self.update, 1.0 / TICKS_PER_SECOND)
def update_fps(dt):
self.fps = pyglet.clock.get_fps()
pyglet.clock.schedule_interval(update_fps, 1)
glClearColor(0, 0, 0, 1)
glClearDepth(1.0)
texture.init()
if not texture.badcard:
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glEnable(GL_LINE_SMOOTH)
glEnable(GL_POLYGON_SMOOTH)
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST)
glAlphaFunc(GL_GEQUAL, 0.9)
glDepthFunc(GL_LEQUAL)
glEnable(GL_DEPTH_TEST)
glShadeModel(GL_SMOOTH)
glMatrixMode(GL_MODELVIEW)
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_LIGHT1)
glEnable(GL_POLYGON_OFFSET_FILL)
fv4 = GLfloat * 4
glLightfv(GL_LIGHT0, GL_POSITION, fv4(.5, .5, 1, 0))
glLightfv(GL_LIGHT0, GL_SPECULAR, fv4(.5, .5, 1, 1))
glLightfv(GL_LIGHT0, GL_DIFFUSE, fv4(1, 1, 1, 1))
glLightfv(GL_LIGHT1, GL_POSITION, fv4(1, 0, .5, 0))
glLightfv(GL_LIGHT1, GL_DIFFUSE, fv4(.5, .5, .5, 1))
glLightfv(GL_LIGHT1, GL_SPECULAR, fv4(1, 1, 1, 1))
self.asteroid_ids = [model_list(load_model(r"asteroids\01.obj"), 5, 5, 5, (0, 0, 0)),
model_list(load_model(r"asteroids\02.obj"), 5, 5, 5, (0, 0, 0)),
model_list(load_model(r"asteroids\03.obj"), 5, 5, 5, (0, 0, 0)),
model_list(load_model(r"asteroids\04.obj"), 5, 5, 5, (0, 0, 0)),
model_list(load_model(r"asteroids\05.obj"), 5, 5, 5, (0, 0, 0))]
c = self.cam
c.x, c.y, c.z = self.world.start
c.pitch, c.yaw, c.roll = self.world.direction
for entity in self.world.tracker:
entity.update()
print "Loaded in %s seconds." % (clock() - l)
def set_exclusive_mouse(self, exclusive):
super(Applet, self).set_exclusive_mouse(exclusive) # Pass to parent
self.exclusive = exclusive # Toggle flag
def on_mouse_press(self, x, y, button, modifiers):
if not self.exclusive:
self.set_exclusive_mouse(True)
def on_mouse_motion(self, x, y, dx, dy):
if self.exclusive: # Only handle camera movement if mouse is grabbed
self.cam.mouse_move(dx * MOUSE_SENSITIVITY, dy * MOUSE_SENSITIVITY)
def on_key_press(self, symbol, modifiers):
if self.exclusive: # Only handle keyboard input if mouse is grabbed
if symbol == key.ESCAPE:
pyglet.app.exit()
elif symbol == key.E:
self.set_exclusive_mouse(False) # Escape mouse
elif symbol == key.F:
self.set_fullscreen(not self.fullscreen)
elif symbol == key.NUM_ADD:
self.speed += 1
elif symbol == key.NUM_SUBTRACT:
self.speed -= 1
elif symbol == key.NUM_MULTIPLY:
self.speed += 10
elif symbol == key.NUM_DIVIDE:
self.speed -= 10
elif symbol == key.PAGEUP:
self.speed += 100
elif symbol == key.PAGEDOWN:
self.speed -= 100
elif symbol == key.HOME:
self.speed += 1000
elif symbol == key.END:
self.speed -= 1000
elif symbol == key.I:
self.info = not self.info
elif symbol == key.D:
self.debug = not self.debug
elif symbol == key.O:
self.orbit = not self.orbit
elif symbol == key.ENTER:
self.running = not self.running
elif symbol == key.INSERT:
index = self.ticks.index(self.tick) + 1
if index < len(self.ticks):
self.tick = self.ticks[index]
elif symbol == key.DELETE:
index = self.ticks.index(self.tick) - 1
if index >= 0:
self.tick = self.ticks[index]
elif symbol == key.SPACE:
c = self.cam
dx, dy, dz = c.direction()
speed = self.speed * 1.1 + 5
dx *= speed
dy *= speed
dz *= speed
self.world.tracker.append(
Asteroid(random.choice(self.asteroid_ids), (c.x, c.y - 3, c.z + 5), direction=(dx, dy, dz)))
else:
self.keys.add(symbol)
def on_key_release(self, symbol, modifiers):
if symbol in self.keys:
self.keys.remove(symbol)
def on_resize(self, width, height):
height = max(height, 1) # Prevent / by 0
self.label.y = height - 20
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
# A field of view of 45
gluPerspective(45.0, width / float(height), 0.1, 50000000.0)
glMatrixMode(GL_MODELVIEW)
def get_time_per_second(self):
if self.__time_per_second_cache == self.tick:
return self.__time_per_second_value
time = self.tick * TICKS_PER_SECOND + .0
unit = 'seconds'
for size, name in ((60, 'minutes'), (60, 'hours'), (24, 'days'), (365, 'years')):
if time < size:
break
time /= size
unit = name
result = '%s %s' % (round(time, 1), unit)
self.__time_per_second_cache = self.tick
self.__time_per_second_value = result
return result
def on_draw(self):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
c = self.cam
x, y, z = c.x, c.y, c.z
glRotatef(c.pitch, 1, 0, 0)
glRotatef(c.yaw, 0, 1, 0)
glRotatef(c.roll, 0, 0, 1)
glTranslatef(-x, -y, -z)
glEnable(GL_LIGHTING)
glEnable(GL_BLEND)
world = self.world
get_distance = entity_distance(x, y, z)
if x != world.x or y != world.y or z != world.z:
world.tracker.sort(key=get_distance, reverse=True)
world.tracker.sort(key=attrgetter('background'), reverse=True)
world.x, world.y, world.z = x, y, z
for entity in world.tracker:
x, y, z = entity.location
pitch, yaw, roll = entity.rotation
glPushMatrix()
glTranslatef(x, y, z)
glRotatef(pitch, 1, 0, 0)
glRotatef(yaw, 0, 1, 0)
glRotatef(roll, 0, 0, 1)
glPushAttrib(GL_CURRENT_BIT)
glCallList(entity.id)
if self.debug:
glPushMatrix()
glLineWidth(0.25)
glPolygonOffset(1, 1)
glDisable(GL_LIGHTING)
glDisable(GL_TEXTURE_2D)
glColor3f(0, 1, 0)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
glCallList(entity.id)
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
glEnable(GL_LIGHTING)
glEnable(GL_TEXTURE_2D)
glPopMatrix()
glPopAttrib()
glPopMatrix()
if hasattr(entity, 'atmosphere') and entity.atmosphere:
glPushMatrix()
x0, y0, z0 = entity.location
dx, dy, dz = x - x0, y - y0, z - z0
distance = sqrt(dz * dz + dx * dx)
pitch = (360 - degrees(atan2(dy, distance)))
yaw = degrees(atan2(dx, dz))
glTranslatef(x0, y0, z0)
glRotatef(pitch, 1, 0, 0)
glRotatef(yaw, 0, 1, 0)
glCallList(entity.atmosphere)
glPopMatrix()
if hasattr(entity, "cloudmap") and entity.cloudmap:
glPushMatrix()
glEnable(GL_ALPHA_TEST)
glTranslatef(*entity.location)
pitch, yaw, roll = entity.rotation
glRotatef(pitch, 1, 0, 0)
glRotatef(yaw, 0, 1, 0)
glRotatef(roll, 0, 0, 1)
glCallList(entity.cloudmap)
glDisable(GL_ALPHA_TEST)
glPopMatrix()
if self.orbit and hasattr(entity, 'get_orbit') and hasattr(entity, 'parent'):
parent = entity.parent
distance = get_distance(parent)
if distance < parent.orbit_show:
glPushMatrix()
glTranslatef(*entity.parent.location)
glDisable(GL_LIGHTING)
glPushAttrib(GL_LINE_BIT | GL_CURRENT_BIT)
glColor4f(1, 1, 1, 1 if distance < parent.orbit_opaque else
(1 - (distance - parent.orbit_opaque) / parent.orbit_blend))
glLineWidth(1)
glCallList(entity.get_orbit())
glPopAttrib()
glEnable(GL_LIGHTING)
glPopMatrix()
glColor4f(1, 1, 1, 1)
glDisable(GL_TEXTURE_2D)
width, height = self.get_size()
if self.info:
ortho(width, height)
self.label.text = ('%d FPS @ (x=%.2f, y=%.2f, z=%.2f) @ %s, %s/s\n'
'Direction(pitch=%.2f, yaw=%.2f, roll=%.2f)\nTick: %d' %
(self.fps, c.x, c.y, c.z, self.speed, self.get_time_per_second(),
c.pitch, c.yaw, c.roll, self.world.tick))
self.label.draw()
glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT)
glLineWidth(2)
cx, cy = width / 2, height / 2
glColor3f(0, 0, 1)
crosshair(15, (cx, cy))
glColor4f(0, 1, 0, 1)
circle(20, 30, (cx, cy))
glPopAttrib()
frustrum()

View file

@ -1,28 +0,0 @@
@echo off
cd %~dp0assets\textures
call :convert earth.jpg earth_medium.jpg 2048x1024
call :convert earth.jpg earth_small.jpg 1024x512
call :convert moon.jpg moon_medium.jpg 2048x1024
call :convert moon.jpg moon_small.jpg 1024x512
call :convert mars.jpg mars_medium.jpg 2048x1024
call :convert mars.jpg mars_small.jpg 1024x512
call :convert jupiter.jpg jupiter_medium.jpg 2048x1024
call :convert jupiter.jpg jupiter_small.jpg 1024x512
call :convert saturn.jpg saturn_medium.jpg 2048x1024
call :convert saturn.jpg saturn_small.jpg 1024x512
call :convert moons\io.jpg moons\io_small.jpg 1024x512
call :convert moons\europa.jpg moons\europa_small.jpg 1024x512
call :convert moons\ganymede.jpg moons\ganymede_small.jpg 1024x512
call :convert moons\callisto.jpg moons\callisto_small.jpg 1024x512
call :convert moons\titan.jpg moons\titan_small.jpg 1024x512
call :convert moons\rhea.jpg moons\rhea_small.jpg 1024x512
call :convert moons\iapetus.jpg moons\iapetus_small.jpg 1024x512
call :convert moons\dione.jpg moons\dione_small.jpg 1024x512
call :convert moons\tethys.jpg moons\tethys_small.jpg 1024x512
call :convert moons\enceladus.jpg moons\enceladus_small.jpg 1024x512
call :convert moons\mimas.jpg moons\mimas_small.jpg 1024x512
goto :eof
:convert
echo Converting %1 to %2, size %3...
if not exist %2 gm convert %1 -resize %3 %2

View file

@ -1,167 +1,349 @@
from __future__ import division
from array import array
from ctypes import c_int, c_float, byref, cast, POINTER, c_uint, c_short, c_ushort
from math import * from math import *
from random import random, gauss, choice
from pyglet.gl import * from pyglet.gl import *
# noinspection PyUnresolvedReferences
from six.moves import range
TWOPI = pi * 2 TWOPI = pi * 2
__all__ = ['compile', 'ortho', 'frustrum', 'crosshair', 'circle', 'disk', 'sphere', 'colourball', 'torus'] __all__ = ['FontEngine', 'Matrix4f', 'Disk', 'OrbitVBO', 'SimpleSphere',
'TangentSphere', 'Cube', 'Circle', 'BeltVBO', 'VAO']
def compile(pointer, *args, **kwargs): def array_to_ctypes(arr):
display = glGenLists(1) return cast(arr.buffer_info()[0], POINTER({
glNewList(display, GL_COMPILE) 'f': c_float,
pointer(*args, **kwargs) 'i': c_int,
glEndList() 'I': c_uint,
return display 'h': c_short,
'H': c_ushort,
}[arr.typecode]))
def ortho(width, height): def array_to_gl_buffer(buffer):
glDisable(GL_LIGHTING) vbo = c_uint()
glDisable(GL_DEPTH_TEST) glGenBuffers(1, byref(vbo))
glMatrixMode(GL_PROJECTION) glBindBuffer(GL_ARRAY_BUFFER, vbo.value)
glPushMatrix() glBufferData(GL_ARRAY_BUFFER, buffer.itemsize * len(buffer), array_to_ctypes(buffer), GL_STATIC_DRAW)
glLoadIdentity() glBindBuffer(GL_ARRAY_BUFFER, 0)
glOrtho(0, width, 0, height, -1, 1) return vbo.value
glMatrixMode(GL_MODELVIEW)
glPushMatrix()
glLoadIdentity()
def frustrum(): def list_to_gl_buffer(buffer, array_type='f'):
glMatrixMode(GL_PROJECTION) return array_to_gl_buffer(array(array_type, buffer))
glPopMatrix()
glMatrixMode(GL_MODELVIEW)
glPopMatrix()
glEnable(GL_LIGHTING)
glEnable(GL_DEPTH_TEST)
def crosshair(size, (cx, cy)): class Matrix4f(object):
glBegin(GL_LINES) def __init__(self, matrix):
glVertex2f(cx - size, cy) self.matrix = array('f', matrix)
glVertex2f(cx + size, cy) assert len(self.matrix) == 16
glVertex2f(cx, cy - size)
glVertex2f(cx, cy + size) @classmethod
glEnd() def from_angles(cls, location=(0, 0, 0), rotation=(0, 0, 0), view=False):
m = [0] * 16
x, y, z = location
pitch, yaw, roll = rotation
sp, sy, sr = sin(radians(pitch)), sin(radians(yaw)), sin(radians(roll))
cp, cy, cr = cos(radians(pitch)), cos(radians(yaw)), cos(radians(roll))
m[0x0] = cy * cr
m[0x1] = sp * sy * cr + cp * sr
m[0x2] = sp * sr - cp * sy * cr
m[0x3] = 0
m[0x4] = -cy * sr
m[0x5] = cp * cr - sp * sy * sr
m[0x6] = cp * sy * sr + sp * cr
m[0x7] = 0
m[0x8] = sy
m[0x9] = -sp * cy
m[0xA] = cp * cy
m[0xB] = 0
if view:
m[0xC] = m[0x0] * -x + m[0x4] * -y + m[0x8] * -z
m[0xD] = m[0x1] * -x + m[0x5] * -y + m[0x9] * -z
m[0xE] = m[0x2] * -x + m[0x6] * -y + m[0xA] * -z
else:
m[0xC] = x
m[0xD] = y
m[0xE] = z
m[0xF] = 1
return cls(m)
@property
def _as_parameter_(self):
return array_to_ctypes(self.matrix)
@property
def bytes(self):
return self.matrix.itemsize * 16
def __mul__(self, other):
if not isinstance(other, Matrix4f):
return NotImplemented
rows = ((0, 4, 8, 12), (1, 5, 9, 13), (2, 6, 10, 14), (3, 7, 11, 15))
cols = ((0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11), (12, 13, 14, 15))
a, b = self.matrix, other.matrix
return type(self)(sum(a[i] * b[j] for i, j in zip(r, c)) for c in cols for r in rows)
def circle(r, seg, (cx, cy)): class Circle(object):
glBegin(GL_LINE_LOOP) type = GL_FLOAT
for i in xrange(seg): stride = 2 * 4
theta = TWOPI * i / seg position_offset = 0
glVertex2f(cx + cos(theta) * r, cy + sin(theta) * r) position_size = 2
glEnd()
def __init__(self, r, segs, shader):
self.vertex_count = segs
buffer = segs * 2 * [0]
delta = 2 * pi / segs
for i in range(segs):
theta = delta * i
buffer[2*i:2*i+2] = [cos(theta) * r, sin(theta) * r]
self.vbo = list_to_gl_buffer(buffer)
self.vao = VAO()
with self.vao:
glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
shader.vertex_attribute('a_position', self.position_size, self.type, GL_FALSE,
self.stride, self.position_offset)
glBindBuffer(GL_ARRAY_BUFFER, 0)
def disk(rinner, router, segs, tex): class Disk(object):
glEnable(GL_TEXTURE_2D) type = GL_FLOAT
glDisable(GL_LIGHTING) stride = 3 * 4
glBindTexture(GL_TEXTURE_2D, tex) position_offset = 0
res = segs * 5 position_size = 2
u_offset = position_size * 4
u_size = 1
glBegin(GL_TRIANGLE_STRIP) def __init__(self, rinner, router, segs):
texture = 0 res = segs * 5
factor = TWOPI / res delta = 2 * pi / res
theta = 0 self.vertex_count = (res + 1) * 2
for n in xrange(res + 1): # Need padding to make the last vertex render correctly... why?
theta += factor buffer = self.vertex_count * 3 * [0]
x = cos(theta) for i in range(res):
y = sin(theta) theta = delta * i
glTexCoord2f(0, texture) x, y = cos(theta), sin(theta)
glVertex2f(rinner * x, rinner * y) buffer[6*i:6*i+6] = [rinner * x, rinner * y, 0, router * x, router * y, 1]
glTexCoord2f(1, texture) buffer[6*res:6*res+6] = buffer[:6]
glVertex2f(router * x, router * y) self.vbo = list_to_gl_buffer(buffer)
texture ^= 1
glEnd()
glEnable(GL_LIGHTING)
glDisable(GL_TEXTURE_2D)
def sphere(r, lats, longs, tex, lighting=True, fv4=GLfloat * 4): class SimpleSphere(object):
""" type = GL_FLOAT
Sphere function from the OpenGL red book. stride = 5 * 4
""" direction_offset = 0
sphere = gluNewQuadric() direction_size = 3
gluQuadricDrawStyle(sphere, GLU_FILL) uv_offset = direction_size * 4
gluQuadricTexture(sphere, True) uv_size = 2
if lighting:
gluQuadricNormals(sphere, GLU_SMOOTH)
glEnable(GL_TEXTURE_2D) def __init__(self, lats, longs):
if lighting: tau = pi * 2
glDisable(GL_BLEND) phi_div = tau / longs
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, fv4(1, 1, 1, 0)) theta_div = pi / lats
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, fv4(1, 1, 1, 0))
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 125)
else:
glDisable(GL_LIGHTING)
glBindTexture(GL_TEXTURE_2D, tex)
gluSphere(sphere, r, lats, longs) self.vertex_count = (lats + 1) * (longs + 1) * 2
buffer = self.vertex_count * 5 * [0]
index = 0
reverse = False
for i in range(longs + 1):
phi1, phi2 = i * phi_div, (i + 1) * phi_div
if reverse:
phi1, phi2 = phi2, phi1
for j in range(lats + 1):
theta = j * theta_div
if reverse:
theta = pi - theta
sine = sin(theta)
dz = cos(theta)
t = 1 - theta / pi
buffer[index:index + 10] = [sine * cos(phi2), sine * sin(phi2), dz, phi2 / tau, t,
sine * cos(phi1), sine * sin(phi1), dz, phi1 / tau, t]
index += 10
reverse ^= True
glBindTexture(GL_TEXTURE_2D, 0) self.vbo = list_to_gl_buffer(buffer)
glDisable(GL_TEXTURE_2D)
glEnable(GL_LIGHTING)
glEnable(GL_BLEND)
gluDeleteQuadric(sphere)
def colourball(r, lats, longs, colour, fv4=GLfloat * 4): class TangentSphere(object):
""" type = GL_FLOAT
Sphere function from the OpenGL red book. stride = 7 * 4
""" direction_offset = 0
sphere = gluNewQuadric() direction_size = 3
tangent_offset = direction_size * 4
tangent_size = 2
uv_offset = tangent_offset + tangent_size * 4
uv_size = 2
glDisable(GL_BLEND) def __init__(self, lats, longs):
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, fv4(*colour)) tau = pi * 2
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, fv4(1, 1, 1, 1)) phi_div = tau / longs
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 125) theta_div = pi / lats
gluSphere(sphere, r, lats, longs) self.vertex_count = (lats + 1) * (longs + 1) * 2
buffer = self.vertex_count * 8 * [0]
glEnable(GL_BLEND) index = 0
gluDeleteQuadric(sphere) reverse = False
for i in range(longs + 1):
phi1, phi2 = i * phi_div, (i + 1) * phi_div
if reverse:
phi1, phi2 = phi2, phi1
for j in range(lats + 1):
theta = j * theta_div
if reverse:
theta = pi - theta
sine = sin(theta)
dz = cos(theta)
t = 1 - theta / pi
sphi2, cphi2 = sin(phi2), cos(phi2)
sphi1, cphi1 = sin(phi1), cos(phi1)
buffer[index:index + 14] = [
sine * cphi2, sine * sphi2, dz, sine * -sphi2, sine * cphi2, phi2 / tau, t,
sine * cphi1, sine * sphi1, dz, sine * -sphi1, sine * cphi1, phi1 / tau, t,
]
index += 14
reverse ^= True
self.vbo = list_to_gl_buffer(buffer)
try: class Cube(object):
from _glgeom import torus type = GL_SHORT
except ImportError: stride = 3 * 2
def torus(major_radius, minor_radius, n_major, n_minor, material, shininess=125, fv4=GLfloat * 4): direction_offset = 0
""" direction_size = 3
Torus function from the OpenGL red book. vertex_count = 36
"""
glPushAttrib(GL_CURRENT_BIT)
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, fv4(*material))
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, fv4(1, 1, 1, 1))
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess)
major_s = TWOPI / n_major def __init__(self):
minor_s = TWOPI / n_minor self.vbo = list_to_gl_buffer([
-1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1,
-1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1,
1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1,
-1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1
], 'h')
def n(x, y, z):
m = 1.0 / sqrt(x * x + y * y + z * z)
return x * m, y * m, z * m
for i in xrange(n_major): class OrbitVBO(object):
a0 = i * major_s type = GL_FLOAT
a1 = a0 + major_s stride = 3 * 4
x0 = cos(a0) position_offset = 0
y0 = sin(a0) position_size = 3
x1 = cos(a1) vertex_count = 360
y1 = sin(a1)
glBegin(GL_TRIANGLE_STRIP) def __init__(self, orbit):
buffer = 360 * 3 * [0]
for theta in range(360):
x, z, y = orbit.orbit(theta)
buffer[3*theta:3*theta+3] = [x, y, z]
for j in xrange(n_minor + 1): self.vbo = list_to_gl_buffer(buffer)
b = j * minor_s
c = cos(b)
r = minor_radius * c + major_radius
z = minor_radius * sin(b)
glNormal3f(*n(x0 * c, y0 * c, z / minor_radius)) def close(self):
glVertex3f(x0 * r, y0 * r, z) if self.vbo is not None:
vbo = c_uint(self.vbo)
glDeleteBuffers(1, byref(vbo))
self.vbo = None
glNormal3f(*n(x1 * c, y1 * c, z / minor_radius)) def __del__(self):
glVertex3f(x1 * r, y1 * r, z) self.close()
glEnd()
glPopAttrib() class FontEngine(object):
type = GL_SHORT
stride = 4 * 2
position_offset = 0
position_size = 2
tex_offset = position_size * 2
tex_size = 2
def __init__(self, shader, max_length=256):
self.storage = array('h', max_length * 24 * [0])
vbo = GLuint()
glGenBuffers(1, byref(vbo))
self.vbo = vbo.value
self.vertex_count = None
self.vao = VAO()
with self.vao:
glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
shader.vertex_attribute('a_rc', self.position_size, self.type, GL_FALSE,
self.stride, self.position_offset)
shader.vertex_attribute('a_tex', self.tex_size, self.type, GL_FALSE,
self.stride, self.tex_offset)
glBindBuffer(GL_ARRAY_BUFFER, 0)
def draw(self, string):
index = 0
row = 0
col = 0
for c in string:
if c == '\n':
row += 1
col = 0
continue
o = ord(c)
if 32 <= o < 128:
self.storage[24*index:24*index+24] = array('h', [
row, col, o - 32, 1,
row + 1, col, o - 32, 0,
row + 1, col + 1, o - 31, 0,
row, col, o - 32, 1,
row + 1, col + 1, o - 31, 0,
row, col + 1, o - 31, 1,
])
index += 1
col += 1
self.vertex_count = index * 6
glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
glBufferData(GL_ARRAY_BUFFER, self.storage.itemsize * len(self.storage),
array_to_ctypes(self.storage), GL_STREAM_DRAW)
glBindBuffer(GL_ARRAY_BUFFER, 0)
class BeltVBO(object):
type = GL_FLOAT
stride = 4 * 4
location_offset = 0
location_size = 3
scale_offset = location_size * 4
scale_size = 1
def __init__(self, radius, cross, objects, count):
arrays = [array('f') for i in range(objects)]
for i in range(count):
theta = TWOPI * random()
r = gauss(radius, cross)
x, y, z = cos(theta) * r, gauss(0, cross), sin(theta) * r
scale = gauss(1, 0.5)
if scale < 0:
scale = 1
choice(arrays).extend((x, y, z, scale))
self.vbo = []
self.sizes = []
for a in arrays:
self.vbo.append(array_to_gl_buffer(a))
self.sizes.append(len(a) // 4)
class VAO(object):
def __init__(self):
buffer = GLuint()
glGenVertexArrays(1, byref(buffer))
self.vao = buffer
def __enter__(self):
glBindVertexArray(self.vao)
def __exit__(self, exc_type, exc_val, exc_tb):
glBindVertexArray(0)

9
punyverse/glwrapper.h Normal file
View file

@ -0,0 +1,9 @@
#ifdef _MSC_VER
# include <windows.h>
#endif
#ifdef __APPLE__
# include <OpenGL/gl.h>
#else
# include <GL/gl.h>
#endif

28
punyverse/launcher.c Normal file
View file

@ -0,0 +1,28 @@
#include <stdlib.h>
#include <Windows.h>
#include <Python.h>
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 0x00000001;
#ifdef GUI
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
#else
int main()
#endif
{
#if PY_MAJOR_VERSION >= 3
int argc;
LPWSTR *argv = CommandLineToArgvW(GetCommandLineW(), &argc);
#else
int argc = __argc;
char **argv = __argv;
#endif
Py_SetProgramName(argv[0]);
Py_Initialize();
PySys_SetArgvEx(argc, argv, 0);
PyRun_SimpleString("from punyverse.main import main; main()");
Py_Finalize();
return 0;
}

31
punyverse/launcher.py Normal file
View file

@ -0,0 +1,31 @@
import os
import shutil
import sys
def main():
if os.name != 'nt':
print('Not on Windows. Nothing to do.')
return
source_dir = os.path.dirname(__file__)
dest_dir = os.path.join(sys.prefix, 'Scripts')
launcher_exe = os.path.join(source_dir, 'launcher.exe')
launcherw_exe = os.path.join(source_dir, 'launcherw.exe')
punyverse_exe = os.path.join(dest_dir, 'punyverse.exe')
punyversew_exe = os.path.join(dest_dir, 'punyversew.exe')
assert os.path.isfile(launcher_exe)
assert os.path.isfile(launcherw_exe)
assert os.path.isfile(punyverse_exe)
assert os.path.isfile(punyversew_exe)
def copy(src, dst):
print('Copying %s to %s...' % (src, dst))
shutil.copy(src, dst)
copy(launcher_exe, punyverse_exe)
copy(launcherw_exe, punyversew_exe)
if __name__ == '__main__':
main()

190
punyverse/loader.py Normal file
View file

@ -0,0 +1,190 @@
from __future__ import print_function
import os
import sys
import time
import pyglet
from pyglet.gl import *
from six.moves import zip_longest
from punyverse.world import World
class glContext(object):
def __init__(self, context):
self.new_context = context
def __enter__(self):
self.old_context = get_current_context()
self.new_context.set_current()
def __exit__(self, exc_type, exc_val, exc_tb):
self.old_context.set_current()
class glSection(object):
def __init__(self, type):
self.type = type
def __enter__(self):
glBegin(self.type)
def __exit__(self, exc_type, exc_val, exc_tb):
glEnd()
def progress_bar(x, y, width, height, filled):
glPushAttrib(GL_ENABLE_BIT)
glDisable(GL_TEXTURE_2D)
glDisable(GL_BLEND)
x1 = x
x2 = x + width
y1 = y
y2 = y - height
y3 = 0.65 * y1 + 0.35 * y2
y4 = 0.25 * y1 + 0.75 * y2
glColor3f(0.6, 0.6, 0.6)
with glSection(GL_LINE_LOOP):
glVertex2f(x1, y1)
glVertex2f(x1, y2)
glVertex2f(x2, y2)
glVertex2f(x2, y1)
x1 += 1
y1 -= 1
x2 = x + width * filled - 1
with glSection(GL_TRIANGLE_STRIP):
glColor3f(0.81, 1, 0.82)
glVertex2f(x1, y1)
glVertex2f(x2, y1)
glColor3f(0, 0.83, 0.16)
glVertex2f(x1, y3)
glVertex2f(x2, y3)
glVertex2f(x1, y4)
glVertex2f(x2, y4)
glColor3f(0.37, 0.92, 0.43)
glVertex2f(x1, y2)
glVertex2f(x2, y2)
glPopAttrib()
def get_context_info(context):
info = [' %-22s %s' % (key + ':', value)
for key, value in context.config.get_gl_attributes()]
info = ['%-30s %-30s' % group for group in
zip_longest(info[::2], info[1::2], fillvalue='')]
with glContext(context):
gl_info.remove_active_context()
gl_info.set_active_context()
return '\n'.join([
'Graphics Vendor: ' + gl_info.get_vendor(),
'Graphics Version: ' + gl_info.get_version(),
'Graphics Renderer: ' + gl_info.get_renderer(),
]) + '\n\n' + 'OpenGL configuration:\n' + '\n'.join(info)
class LoaderWindow(pyglet.window.Window):
MONOSPACE = ('Consolas', 'Droid Sans Mono', 'Courier', 'Courier New', 'Dejavu Sans Mono')
def __init__(self, *args, **kwargs):
super(LoaderWindow, self).__init__(*args, **kwargs)
# work around pyglet bug: decoding font names as utf-8 instead of mbcs when using EnumFontsA.
stderr = sys.stderr
sys.stderr = open(os.devnull, 'w')
pyglet.font.have_font(self.MONOSPACE[0])
sys.stderr = stderr
self.loading_phase = pyglet.text.Label(
font_name=self.MONOSPACE, font_size=20, x=10, y=self.height - 50,
color=(255, 255, 255, 255), width=self.width - 20, align='center',
multiline=True, text='Punyverse is starting...'
)
self.loading_label = pyglet.text.Label(
font_name=self.MONOSPACE, font_size=16, x=10, y=self.height - 120,
color=(255, 255, 255, 255), width=self.width - 20, align='center',
multiline=True
)
self.info_label = pyglet.text.Label(
font_name=self.MONOSPACE, font_size=13, x=10, y=self.height - 220,
color=(255, 255, 255, 255), width=self.width - 20,
multiline=True
)
self.progress = 0
self._main_context = None
def set_main_context(self, context):
self._main_context = context
self.info_label.text = get_context_info(context)
print(self.info_label.text)
def _load_callback(self, phase, message, progress):
print(message)
with glContext(self.context):
self.loading_phase.text = phase
self.loading_label.text = message
self.progress = progress
self.on_draw()
self.flip()
self.dispatch_events()
def load(self, **kwargs):
start = time.clock()
with glContext(self._main_context):
world = World('world.json', self._load_callback, **kwargs)
print('Loaded in %s seconds.' % (time.clock() - start))
return world
def on_draw(self):
glClear(GL_COLOR_BUFFER_BIT)
glLoadIdentity()
self.loading_phase.draw()
self.loading_label.draw()
progress_bar(10, self.height - 140, self.width - 20, 50, self.progress)
self.info_label.draw()
def main_is_initializing(self):
self._load_callback('Loading main window...', '', 0)
class LoaderConsole(object):
def __init__(self):
from ctypes import windll
self._own_console = False
if windll.kernel32.AllocConsole():
self._own_console = True
self._output = open('CONOUT$', 'w')
else:
self._output = sys.stdout
self._main_context = None
def _load_callback(self, phase, message, progress):
print(message, file=self._output)
def load(self, **kwargs):
start = time.clock()
with glContext(self._main_context):
world = World('world.json', self._load_callback, **kwargs)
print('Loaded in %s seconds.' % (time.clock() - start), file=self._output)
return world
def set_main_context(self, context):
self._main_context = context
print(get_context_info(context), file=self._output)
print('=' * 79, file=self._output)
print("You cannot see the normal loading screen because you are using Intel integrated graphics.",
file=self._output)
print('Please attempt to set python to execute with your dedicated graphics, if available.', file=self._output)
print('=' * 79, file=self._output)
def close(self):
if self._own_console:
self._output.close()
from ctypes import windll
windll.kernel32.FreeConsole()

87
punyverse/main.py Normal file
View file

@ -0,0 +1,87 @@
import argparse
import sys
import pyglet
INITIAL_WIN_HEIGHT = 540
INITIAL_WIN_WIDTH = 700
DEBUG = False
def main():
macos = sys.platform == 'darwin'
parser = argparse.ArgumentParser(prog='punyverse', description='''
Python simulator of a puny universe.
''')
parser.set_defaults(sky=not macos)
parser.add_argument('-D', '--debug', help='Enable pyglet OpenGL debugging', action='store_true')
parser.add_argument('-d', '--high-depth', help='Use a larger depth buffer',
const=32, default=24, dest='depth', nargs='?', type=int)
parser.add_argument('-m', '--multisample', help='Use multisampled image, optional samples',
const=2, default=0, nargs='?', type=int)
parser.add_argument('-v', '--no-vsync', help='Disables vsync',
action='store_false', dest='vsync')
parser.add_argument('-n', '--normal', help='Enables the use of normal maps',
action='store_true')
parser.add_argument('-s', '--sky', help='Enables the sky', dest='sky',
action='store_true')
parser.add_argument('-S', '--no-sky', help='Disables the sky', dest='sky',
action='store_false')
args = parser.parse_args()
versioning = dict(major_version=3, minor_version=3)
pyglet.options['debug_gl'] = args.debug
if macos:
pyglet.options['shadow_window'] = False
versioning = dict(major_version=4, minor_version=1, forward_compatible=True)
template = pyglet.gl.Config(depth_size=args.depth, double_buffer=True,
sample_buffers=args.multisample > 1,
samples=args.multisample, **versioning)
platform = pyglet.window.get_platform()
display = platform.get_default_display()
screen = display.get_default_screen()
try:
config = screen.get_best_config(template)
except pyglet.window.NoSuchConfigException:
raise SystemExit('Graphics configuration not supported.')
create_args = dict(width=INITIAL_WIN_WIDTH, height=INITIAL_WIN_HEIGHT,
caption='Punyverse', resizable=True, vsync=args.vsync, visible=False)
from pyglet.gl import gl_info
from punyverse.loader import LoaderWindow, LoaderConsole
from punyverse.ui import Punyverse
if pyglet.compat_platform in ('win32', 'cygwin') and gl_info.get_vendor() == 'Intel':
# pyglet has some code that tries to create without ARB on Intel.
# Of course, all that achieves is the message that you can't create OpenGL 3 contexts.
# So we force create an ARB context.
from pyglet.gl.win32 import Win32ARBContext
context = Win32ARBContext(config, None)
# We use the console loader since using the GUI loader makes all sorts of wonderful things happen on Intel:
# Access violations, mouse events going nowhere, you name it.
loader = LoaderConsole()
punyverse = Punyverse(context=context, **create_args)
else:
context = config.create_context(None)
loader = LoaderWindow(width=INITIAL_WIN_WIDTH, height=INITIAL_WIN_HEIGHT,
caption='Punyverse is loading...')
punyverse = Punyverse(context=context, **create_args)
loader.context.set_current()
loader.set_main_context(punyverse.context)
world = loader.load(sky=args.sky)
punyverse.context.set_current()
punyverse.initialize(world)
loader.close()
punyverse.set_visible(True)
pyglet.app.run()
if __name__ == '__main__':
main()

View file

@ -1,288 +1,346 @@
from time import clock import bz2
import os.path import gzip
import os
import zipfile
from collections import defaultdict
import six
from pyglet.gl import * from pyglet.gl import *
# noinspection PyUnresolvedReferences
from six.moves import range, zip
from punyverse.glgeom import list_to_gl_buffer, VAO
from punyverse.texture import load_texture from punyverse.texture import load_texture
FACE_TRIANGLES = 0
FACE_QUADS = 1
def zip_open(file):
zip = zipfile.ZipFile(file)
return zip.open(zip.namelist()[0])
def model_list(model, sx=1, sy=1, sz=1, rotation=(0, 0, 0)): openers = {
for m, text in model.materials.iteritems(): 'gz': gzip.open,
if text.texture: 'bz2': bz2.BZ2File,
load_texture(os.path.join(model.root, text.texture)) 'zip': zip_open,
}
display = glGenLists(1)
glNewList(display, GL_COMPILE)
glPushMatrix()
glPushAttrib(GL_CURRENT_BIT)
pitch, yaw, roll = rotation
glPushAttrib(GL_TRANSFORM_BIT)
glRotatef(pitch, 1, 0, 0)
glRotatef(yaw, 0, 1, 0)
glRotatef(roll, 0, 0, 1)
glPopAttrib()
vertices = model.vertices
textures = model.textures
normals = model.normals
for g in model.groups:
material = g.material
tex_id = load_texture(os.path.join(model.root, material.texture)) if (material and material.texture) else 0
if tex_id:
glEnable(GL_TEXTURE_2D)
glBindTexture(GL_TEXTURE_2D, tex_id)
else:
glBindTexture(GL_TEXTURE_2D, 0)
glDisable(GL_TEXTURE_2D)
if material:
fv4 = GLfloat * 4
if material.Ka:
kx, ky, kz = material.Ka
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, fv4(kx, ky, kz, 1))
if material.Kd:
kx, ky, kz = material.Kd
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, fv4(kx, ky, kz, 1))
if material.Ks:
kx, ky, kz = material.Ks
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, fv4(kx, ky, kz, 1))
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, material.shininess)
type = -1
def point(f, vertices, normals, textures, n):
if f.norms:
glNormal3f(*normals[f.norms[n]])
if tex_id:
glTexCoord2f(*textures[f.texs[n]][:2])
x, y, z = vertices[f.verts[n]]
glVertex3f(x * sx, y * sy, z * sz)
for f in g.faces:
if type != f.type:
if type != -1:
glEnd()
glBegin(GL_TRIANGLES)
type = f.type
point(f, vertices, normals, textures, 0)
point(f, vertices, normals, textures, 1)
point(f, vertices, normals, textures, 2)
if type == FACE_QUADS:
point(f, vertices, normals, textures, 2)
point(f, vertices, normals, textures, 3)
point(f, vertices, normals, textures, 0)
glEnd()
glPopAttrib()
glPopMatrix()
glEndList()
return display
def load_model(path):
path = os.path.join(os.path.dirname(__file__), "assets", "models", path)
root = os.path.dirname(path)
vertices = []
normals = []
textures = []
groups = []
materials = {}
# Allez au diable, Python
current_group = [None]
current_material = [None]
def dispatch(p, commands):
with open(p, 'r') as file:
for line in file:
line = line.strip()
if not line or line[0] == '#':
continue # Empty or comment
words = line.split()
type = words[0]
if type in commands:
commands[type](words)
def newmtl(words):
material = Material(words[1])
materials[words[1]] = material
current_material[0] = material
def Ka(words):
current_material[0].Ka = (float(words[1]), float(words[2]), float(words[3]))
def Kd(words):
current_material[0].Kd = (float(words[1]), float(words[2]), float(words[3]))
def Ks(words):
current_material[0].Ks = (float(words[1]), float(words[2]), float(words[3]))
def Ns(words):
current_material[0].shininess = min(float(words[1]), 125) # Seems to sometimes be > 125. TODO: find out why
def map_Kd(words):
current_material[0].texture = words[-1]
def v(words):
vertices.append((float(words[1]), float(words[2]), float(words[3])))
def vn(words):
normals.append((float(words[1]), float(words[2]), float(words[3])))
def vt(words):
l = len(words)
x, y, z = 0, 0, 0
if l >= 2:
x = float(words[1])
if l >= 3:
# OBJ origin is at upper left, OpenGL origin is at lower left
y = 1 - float(words[2])
if l >= 4:
z = float(words[3])
textures.append((x, y, z))
def f(words):
l = len(words)
type = -1
face_vertices = []
face_normals = []
face_textures = []
vertex_count = l - 1
if vertex_count == 3:
type = FACE_TRIANGLES
else:
type = FACE_QUADS
raw_faces = []
current_value = -1
vindices = []
nindices = []
tindices = []
for i in xrange(1, vertex_count + 1):
raw_faces = words[i].split('/')
l = len(raw_faces)
current_value = int(raw_faces[0])
vindices.append(current_value - 1)
face_vertices.append(vertices[current_value - 1])
if l == 1:
continue
if l >= 2 and raw_faces[1]:
current_value = int(raw_faces[1])
if current_value <= len(textures):
tindices.append(current_value - 1)
face_textures.append(textures[current_value - 1])
if l >= 3 and raw_faces[2]:
current_value = int(raw_faces[2])
nindices.append(current_value - 1)
face_normals.append(normals[current_value - 1])
if not groups:
group = Group()
groups.append(group)
else:
group = groups[-1]
group.vertices += face_vertices
group.normals += face_normals
group.textures += face_textures
idx_count = group.idx_count
group.indices += (idx_count + 1, idx_count + 2, idx_count + 3)
group.idx_count += 3
group.faces.append(Face(type, vindices, nindices, tindices, face_vertices, face_normals, face_textures))
mtllib = lambda words: dispatch(os.path.join(root, words[1]), obj)
def usemtl(words):
mat = words[1]
if mat in materials:
groups[-1].material = materials[mat]
else:
print "Warning: material %s undefined." % mat
g = lambda words: groups.append(Group(words[1]))
obj = {
'v': v,
'vn': vn,
'vt': vt,
'f': f,
'mtllib': mtllib,
'usemtl': usemtl,
'g': g,
'o': g, # TODO: o is not really g
'newmtl': newmtl,
'Ka': Ka,
'Kd': Kd,
'Ks': Ks,
'Ns': Ns,
'map_Kd': map_Kd
}
dispatch(path, obj)
return WavefrontObject(root, vertices, normals, textures, groups, materials)
class WavefrontObject(object):
def __init__(self, root, vertices=None, normals=None, textures=None, groups=None, materials=None):
self.root = root
self.vertices = vertices or []
self.normals = normals or []
self.textures = textures or []
self.groups = groups or []
self.materials = materials or []
class Group(object):
def __init__(self, name=None):
if not name:
name = clock()
self.name = name
self.material = None
self.faces = []
self.indices = []
self.vertices = []
self.normals = []
self.textures = []
self.idx_count = 0
class Face(object): class Face(object):
def __init__(self, type, verts, norms, texs, vertices, normals, textures): __slots__ = ('verts', 'norms', 'texs', 'size')
self.type = type
def __init__(self, verts, norms, texs):
self.verts = verts self.verts = verts
self.norms = norms self.norms = norms
self.texs = texs self.texs = texs
self.vertices = vertices self.size = len(verts)
self.normals = normals
self.textures = textures
class Material(object): class Material(object):
def __init__(self, name, texture=None, Ka=0, Kd=0, Ks=0, shininess=0.0): __slots__ = ('name', 'texture', 'Ka', 'Kd', 'Ks', 'shininess')
def __init__(self, name, texture=None, Ka=(0, 0, 0), Kd=(0, 0, 0), Ks=(0, 0, 0), shininess=0.0):
self.name = name self.name = name
self.texture = texture self.texture = texture
self.Ka = Ka self.Ka = Ka
self.Kd = Kd self.Kd = Kd
self.Ks = Ks self.Ks = Ks
self.shininess = shininess self.shininess = shininess
class Group(object):
__slots__ = ('material', 'faces')
def __init__(self, material=None, faces=None):
self.material = material
self.faces = faces or []
class WavefrontObject(object):
def __init__(self, path):
self.path = path
self.root = os.path.abspath(os.path.dirname(path))
self.vertices = []
self.normals = []
self.textures = []
self.groups = []
self.materials = {}
self.perform_io(self.path)
def new_material(self, words):
name = words[1].decode('utf-8')
material = Material(name)
self.materials[name] = material
self.current_material = material
def Ka(self, words):
self.current_material.Ka = (float(words[1]), float(words[2]), float(words[3]))
def Kd(self, words):
self.current_material.Kd = (float(words[1]), float(words[2]), float(words[3]))
def Ks(self, words):
self.current_material.Ks = (float(words[1]), float(words[2]), float(words[3]))
def material_shininess(self, words):
self.current_material.shininess = min(float(words[1]), 125)
def material_texture(self, words):
self.current_material.texture = words[-1].decode('utf-8')
def vertex(self, words):
self.vertices.append((float(words[1]), float(words[2]), float(words[3])))
def normal(self, words):
self.normals.append((float(words[1]), float(words[2]), float(words[3])))
def texture(self, words):
l = len(words)
u, v = 0, 0
if l >= 2:
u = float(words[1])
if l >= 3:
# OBJ origin is at upper left, OpenGL origin is at lower left
v = 1 - float(words[2])
self.textures.append((u, v))
def face(self, words):
l = len(words)
vertex_count = l - 1
vindices = []
nindices = []
tindices = []
for i in range(1, vertex_count + 1):
raw_faces = words[i].split(b'/')
l = len(raw_faces)
vindices.append(int(raw_faces[0]) - 1)
if l >= 2 and raw_faces[1]:
tindices.append(int(raw_faces[1]) - 1)
else:
tindices.append(None)
if l >= 3 and raw_faces[2]:
nindices.append(int(raw_faces[2]) - 1)
else:
nindices.append(None)
if self.current_group is None:
self.current_group = group = Group()
self.groups.append(group)
else:
group = self.current_group
group.faces.append(Face(vindices, nindices, tindices))
def material(self, words):
self.perform_io(os.path.join(self.root, words[1].decode('utf-8')))
def use_material(self, words):
mat = words[1].decode('utf-8')
try:
self.current_group.material = self.materials[mat]
except KeyError:
print("Warning: material %s undefined, only %s defined." % (mat, self.materials))
except AttributeError:
print("Warning: no group")
def group(self, words):
group = Group()
self.groups.append(group)
self.current_group = group
def perform_io(self, file):
ext = os.path.splitext(file)[1].lstrip('.')
reader = openers.get(ext, lambda x: open(x, 'rb'))(file)
dispatcher = {
b'v': self.vertex,
b'vn': self.normal,
b'vt': self.texture,
b'f': self.face,
b'mtllib': self.material,
b'usemtl': self.use_material,
b'g': self.group,
b'o': self.group,
b'newmtl': self.new_material,
b'Ka': self.Ka,
b'Kd': self.Kd,
b'Ks': self.Ks,
b'Ns': self.material_shininess,
b'map_Kd': self.material_texture,
}
default = lambda words: None
with reader:
for buf in reader:
if not buf or buf.startswith((b'\r', b'\n', b'#')):
continue # Empty or comment
words = buf.split()
type = words[0]
dispatcher.get(type, default)(words)
return True
model_base = os.path.join(os.path.dirname(__file__), 'assets', 'models')
def load_model(path):
if not os.path.isabs(path):
path = os.path.join(model_base, path)
if isinstance(path, six.binary_type):
path = path.decode('mbcs' if os.name == 'nt' else 'utf8')
return WavefrontObject(path)
class ModelVBO(object):
__slots__ = ('has_normal', 'has_texture', 'data_buf', 'index_buf', 'offset_type', 'vertex_count', 'vao')
def __init__(self):
self.vao = VAO()
def build_vao(self, shader):
stride = (3 + self.has_normal * 3 + self.has_texture * 2) * 4
with self.vao:
glBindBuffer(GL_ARRAY_BUFFER, self.data_buf)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.index_buf)
shader.vertex_attribute('a_position', 3, GL_FLOAT, GL_FALSE, stride, 0)
if self.has_normal:
shader.vertex_attribute('a_normal', 3, GL_FLOAT, GL_FALSE, stride, 3 * 4)
if self.has_texture:
shader.vertex_attribute('a_uv', 2, GL_FLOAT, GL_FALSE, stride, (6 if self.has_normal else 3) * 4)
glBindBuffer(GL_ARRAY_BUFFER, 0)
def draw(self, shader, instances=None):
with self.vao:
if not self.has_normal:
shader.vertex_attribute_vec3('a_normal', 0, 0, 0)
if not self.has_texture:
shader.vertex_attribute_vec2('a_uv', 0, 0)
if instances:
glDrawElementsInstanced(GL_TRIANGLES, self.vertex_count, self.offset_type, 0, instances)
else:
glDrawElements(GL_TRIANGLES, self.vertex_count, self.offset_type, 0)
class WavefrontVBO(object):
def __init__(self, model, shader, sx=1, sy=1, sz=1):
self._tex_cache = {}
self.vbos = []
self.scale = (sx, sy, sz)
for m, material in six.iteritems(model.materials):
if material.texture and material.texture not in self._tex_cache:
self._tex_cache[material.texture] = load_texture(os.path.join(model.root, material.texture))
vertices = model.vertices
textures = model.textures
normals = model.normals
for group in self.merge_groups(model):
processed = self.process_group(group, vertices, normals, textures)
self.vbos.append((group.material, processed))
processed.build_vao(shader)
def additional_attributes(self, callback):
for _, group in self.vbos:
with group.vao:
callback()
def draw(self, shader, instances=None):
for mat, vbo in self.vbos:
tex_id = self._tex_cache[mat.texture] if mat and mat.texture else 0
if tex_id:
glBindTexture(GL_TEXTURE_2D, tex_id)
shader.uniform_bool('u_material.hasDiffuse', True)
shader.uniform_texture('u_material.diffuseMap', 0)
else:
shader.uniform_bool('u_material.hasDiffuse', False)
if mat and mat.Ka:
shader.uniform_vec3('u_material.ambient', *mat.Ka)
else:
shader.uniform_vec3('u_material.ambient', 0.2, 0.2, 0.2)
if mat and mat.Kd:
shader.uniform_vec3('u_material.diffuse', *mat.Kd)
else:
shader.uniform_vec3('u_material.diffuse', 0.8, 0.8, 0.8)
if mat and mat.Ks:
shader.uniform_vec3('u_material.specular', *mat.Ks)
else:
shader.uniform_vec3('u_material.specular', 0, 0, 0)
if mat:
shader.uniform_float('u_material.shininess', mat.shininess)
else:
shader.uniform_float('u_material.shininess', 0)
vbo.draw(shader, instances=instances)
def merge_groups(self, model):
by_mat = defaultdict(list)
for g in model.groups:
if g.faces:
by_mat[g.material].append(g)
groups = []
for mat, gs in six.iteritems(by_mat):
faces = []
for g in gs:
faces += g.faces
groups.append(Group(mat, faces))
return groups
def process_group(self, group, vertices, normals, textures):
sx, sy, sz = self.scale
max_texture = len(textures)
has_texture = bool(textures) and any(any(n is not None for n in f.texs) for f in group.faces)
has_normal = bool(normals) and any(any(n is not None for n in f.norms) for f in group.faces)
buffer = []
indices = []
offsets = {}
for f in group.faces:
verts = []
for v, n, t in zip(f.verts, f.norms, f.texs):
# Blender defines texture coordinates on faces even without textures.
if t is not None and t >= max_texture:
t = None
if (v, n, t) in offsets:
verts.append(offsets[v, n, t])
else:
index = len(offsets)
verts.append(index)
x, y, z = vertices[v]
item = [sx * x, sy * y, sz * z]
if has_normal:
item += [0, 0, 0] if n is None else list(normals[n])
if has_texture:
item += [0, 0] if t is None else list(textures[t])
offsets[v, n, t] = index
buffer += item
for a, b in zip(verts[1:], verts[2:]):
indices += [verts[0], a, b]
result = ModelVBO()
result.has_normal = has_normal
result.has_texture = has_texture
result.offset_type = GL_UNSIGNED_SHORT if len(offsets) < 65536 else GL_UNSIGNED_INT
result.data_buf = list_to_gl_buffer(buffer, 'f')
result.index_buf = list_to_gl_buffer(indices, {
GL_UNSIGNED_SHORT: 'H',
GL_UNSIGNED_INT: 'I',
}[result.offset_type])
result.vertex_count = len(indices)
return result

View file

@ -66,10 +66,11 @@ class KeplerOrbit(object):
self.__cos_argument = cos(self._argument) self.__cos_argument = cos(self._argument)
def eccentric_anomaly(self, mean_anomaly): def eccentric_anomaly(self, mean_anomaly):
e1 = mean_anomaly e1 = 0
e2 = mean_anomaly + self.eccentricity * sin(e1) e2 = mean_anomaly
while abs(e1 - e2) > 0.000001: while abs(e1 - e2) > 0.000001:
e1, e2 = e2, mean_anomaly + self.eccentricity * sin(e2) e1, e2 = e2, e2 - ((e2 - mean_anomaly - self.eccentricity * sin(e2)) /
(1 - self.eccentricity * cos(e2)))
return e2 return e2
def true_anomaly(self, mean_anomaly): def true_anomaly(self, mean_anomaly):

127
punyverse/shader.py Normal file
View file

@ -0,0 +1,127 @@
from __future__ import print_function
import os
import sys
from ctypes import pointer, byref, create_string_buffer, POINTER, cast
from pyglet.gl import *
# noinspection PyUnresolvedReferences
from six.moves import range
SHADERS_DIR = os.path.join(os.path.dirname(__file__), 'shaders')
class CompileError(ValueError):
pass
class glShader(object):
def __init__(self, type):
self.type = type
def __enter__(self):
self.shader = glCreateShader(self.type)
return self.shader
def __exit__(self, exc_type, exc_val, exc_tb):
glDeleteShader(self.shader)
class Program(object):
@classmethod
def load_file(cls, file):
with open(os.path.join(SHADERS_DIR, file), 'rb') as f:
return f.read()
@classmethod
def compile_shader(cls, shader, source):
buffer = create_string_buffer(source)
glShaderSource(shader, 1, cast(pointer(pointer(buffer)), POINTER(POINTER(GLchar))), None)
glCompileShader(shader)
succeeded = GLint()
log_length = GLint()
glGetShaderiv(shader, GL_COMPILE_STATUS, byref(succeeded))
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, byref(log_length))
buffer = create_string_buffer(log_length.value + 1)
glGetShaderInfoLog(shader, log_length.value, None, buffer)
if not succeeded:
raise CompileError(buffer.value.decode('utf-8'))
elif log_length.value:
print('Warning:', file=sys.stderr)
print(buffer.value.decode('utf-8'), file=sys.stderr)
def __init__(self, vertex_file, fragment_file):
with glShader(GL_VERTEX_SHADER) as vertex_shader, glShader(GL_FRAGMENT_SHADER) as fragment_shader:
self.compile_shader(vertex_shader, self.load_file(vertex_file))
self.compile_shader(fragment_shader, self.load_file(fragment_file))
program = glCreateProgram()
glAttachShader(program, vertex_shader)
glAttachShader(program, fragment_shader)
glLinkProgram(program)
succeeded = GLint()
log_length = GLint()
glGetProgramiv(program, GL_LINK_STATUS, byref(succeeded))
if not succeeded:
glGetProgramiv(program, GL_INFO_LOG_LENGTH, byref(log_length))
buffer = create_string_buffer(log_length.value + 1)
glGetProgramInfoLog(program, log_length.value, None, buffer)
glDeleteProgram(program)
raise CompileError(buffer.value)
glDetachShader(program, vertex_shader)
glDetachShader(program, fragment_shader)
self.program = program
self.attributes = self._variable_locations(GL_ACTIVE_ATTRIBUTES, glGetActiveAttrib, glGetAttribLocation)
self.uniforms = self._variable_locations(GL_ACTIVE_UNIFORMS, glGetActiveUniform, glGetUniformLocation)
def vertex_attribute(self, name, size, type, normalized, stride, offset, divisor=None):
location = self.attributes[name]
glVertexAttribPointer(location, size, type, normalized, stride, offset)
glEnableVertexAttribArray(location)
if divisor:
glVertexAttribDivisor(location, divisor)
def vertex_attribute_vec2(self, name, a, b):
glVertexAttrib2f(self.attributes[name], a, b)
def vertex_attribute_vec3(self, name, a, b, c):
glVertexAttrib3f(self.attributes[name], a, b, c)
def uniform_mat4(self, name, matrix):
glUniformMatrix4fv(self.uniforms[name], 1, GL_FALSE, matrix)
def uniform_texture(self, name, index):
glUniform1i(self.uniforms[name], index)
def uniform_float(self, name, value):
glUniform1f(self.uniforms[name], value)
def uniform_bool(self, name, value):
glUniform1i(self.uniforms[name], bool(value))
def uniform_vec2(self, name, a, b):
glUniform2f(self.uniforms[name], a, b)
def uniform_vec3(self, name, a, b, c):
glUniform3f(self.uniforms[name], a, b, c)
def uniform_vec4(self, name, a, b, c, d):
glUniform4f(self.uniforms[name], a, b, c, d)
def _variable_locations(self, count_type, get_func, loc_func):
variables = {}
count = GLint()
glGetProgramiv(self.program, count_type, byref(count))
buffer = create_string_buffer(256)
size = GLint()
type = GLenum()
for index in range(count.value):
get_func(self.program, index, 256, None, byref(size), byref(type), buffer)
variables[buffer.value.decode('ascii')] = loc_func(self.program, buffer)
return variables

View file

@ -0,0 +1,12 @@
#version 330 core
in float v_u;
out vec4 o_fragColor;
uniform vec3 u_color;
uniform sampler1D u_transparency;
void main() {
o_fragColor = vec4(u_color, texture(u_transparency, v_u).r);
}

View file

@ -0,0 +1,13 @@
#version 330 core
in vec2 a_position;
in float a_u;
out float v_u;
uniform mat4 u_mvpMatrix;
void main() {
gl_Position = u_mvpMatrix * vec4(a_position, 0, 1);
v_u = a_u;
}

View file

@ -0,0 +1,28 @@
#version 330 core
in vec3 a_position;
in vec3 a_normal;
in vec2 a_uv;
in vec3 a_translate;
in float a_scale;
out vec2 v_uv;
out vec3 v_normal;
out vec3 v_position;
out vec3 v_camDirection;
uniform mat4 u_mvpMatrix;
uniform mat4 u_mvMatrix;
uniform mat4 u_modelMatrix;
void main() {
mat4 matrix = mat4(mat3(a_scale));
matrix[3].xyz = a_translate;
mat4 modelMatrix = u_modelMatrix * matrix;
gl_Position = u_mvpMatrix * matrix * vec4(a_position, 1);
v_normal = normalize(vec3(modelMatrix * vec4(a_normal, 0)));
v_uv = a_uv;
v_position = (modelMatrix * vec4(a_position, 1)).xyz;
v_camDirection = (u_mvMatrix * matrix * vec4(a_position, 1)).xyz;
}

View file

@ -0,0 +1,19 @@
#version 330 core
in vec2 v_uv;
in vec3 v_normal;
in vec3 v_position;
out vec4 o_fragColor;
uniform vec3 u_ambient;
uniform vec3 u_diffuse;
uniform vec3 u_sun;
uniform sampler2D u_transparency;
void main() {
vec3 incident = normalize(u_sun - v_position);
vec3 diffuse = u_diffuse * clamp(dot(v_normal, incident) + 0.2, 0.0, 1.0);
o_fragColor = vec4(u_ambient + diffuse, texture(u_transparency, v_uv).r);
}

View file

@ -0,0 +1,20 @@
#version 330 core
in vec3 a_normal;
in vec2 a_uv;
out vec2 v_uv;
out vec3 v_normal;
out vec3 v_position;
uniform float u_radius;
uniform mat4 u_mvpMatrix;
uniform mat4 u_modelMatrix;
void main() {
vec3 position = u_radius * a_normal;
v_uv = a_uv;
v_normal = (u_modelMatrix * vec4(a_normal, 0)).xyz;
v_position = (u_modelMatrix * vec4(position, 1)).xyz;
gl_Position = u_mvpMatrix * vec4(position, 1);
}

View file

@ -0,0 +1,8 @@
#version 330 core
out vec4 o_fragColor;
uniform vec4 u_color;
void main() {
o_fragColor = u_color;
}

View file

@ -0,0 +1,8 @@
#version 330 core
in vec3 a_position;
uniform mat4 u_mvpMatrix;
void main() {
gl_Position = u_mvpMatrix * vec4(a_position, 1);
}

View file

@ -0,0 +1,43 @@
#version 330 core
in vec2 v_uv;
in vec3 v_normal;
in vec3 v_position;
in vec3 v_camDirection;
out vec4 o_fragColor;
struct Material {
bool hasDiffuse;
sampler2D diffuseMap;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float shininess;
};
struct Sun {
vec3 ambient;
vec3 diffuse;
vec3 specular;
vec3 position;
float intensity;
};
uniform Sun u_sun;
uniform Material u_material;
void main() {
vec3 incident = normalize(u_sun.position - v_position);
vec3 reflected = normalize(reflect(-incident, v_normal));
float diffuseIntensity = max(dot(v_normal, incident), 0.0);
float shininess = pow(max(dot(normalize(v_camDirection), reflected), 0), u_material.shininess);
vec3 diffuse = u_material.hasDiffuse ? texture(u_material.diffuseMap, v_uv).rgb : vec3(1);
vec3 ambient = u_material.ambient * u_sun.ambient * diffuse;
vec3 specular = u_material.specular * u_sun.specular * max(shininess, 0) * diffuseIntensity;
diffuse *= u_material.diffuse * u_sun.diffuse * diffuseIntensity;
o_fragColor = vec4((ambient + diffuse + specular) * u_sun.intensity, 1);
}

View file

@ -0,0 +1,22 @@
#version 330 core
in vec3 a_position;
in vec3 a_normal;
in vec2 a_uv;
out vec2 v_uv;
out vec3 v_normal;
out vec3 v_position;
out vec3 v_camDirection;
uniform mat4 u_mvpMatrix;
uniform mat4 u_mvMatrix;
uniform mat4 u_modelMatrix;
void main() {
gl_Position = u_mvpMatrix * vec4(a_position, 1);
v_normal = normalize(vec3(u_modelMatrix * vec4(a_normal, 0)));
v_uv = a_uv;
v_position = (u_modelMatrix * vec4(a_position, 1)).xyz;
v_camDirection = (u_mvMatrix * vec4(a_position, 1)).xyz;
}

View file

@ -0,0 +1,55 @@
#version 330 core
in vec2 v_uv;
in vec3 v_normal;
in vec3 v_position;
in vec3 v_camDirection;
in mat3 v_TBN;
out vec4 o_fragColor;
struct Surface {
sampler2D diffuseMap;
bool hasNormal;
sampler2D normalMap;
bool hasSpecular;
sampler2D specularMap;
bool hasEmission;
sampler2D emissionMap;
vec3 ambient;
vec3 diffuse;
vec3 specular;
vec3 emission;
float shininess;
};
struct Sun {
vec3 ambient;
vec3 diffuse;
vec3 specular;
vec3 position;
float intensity;
};
uniform Sun u_sun;
uniform Surface u_planet;
void main() {
vec3 normal = u_planet.hasNormal ? normalize(v_TBN * texture(u_planet.normalMap, v_uv).rgb * 2 - 1) : v_normal;
vec3 diffuse = texture(u_planet.diffuseMap, v_uv).rgb;
vec3 specular = u_planet.hasSpecular ? texture(u_planet.specularMap, v_uv).rgb : vec3(1);
vec3 emission = u_planet.hasEmission ? texture(u_planet.emissionMap, v_uv).rgb : vec3(1);
vec3 incident = normalize(u_sun.position - v_position);
vec3 reflected = normalize(reflect(-incident, normal));
float diffuseIntensity = max(dot(normal, incident), 0.0);
float shininess = pow(max(dot(normalize(v_camDirection), reflected), 0), u_planet.shininess);
vec3 ambient = u_planet.ambient * u_sun.ambient * diffuse;
diffuse *= u_planet.diffuse * u_sun.diffuse * diffuseIntensity;
emission *= u_planet.emission * (1 - min(diffuseIntensity * 2, 1));
specular *= u_planet.specular * u_sun.specular * max(shininess, 0) * diffuseIntensity;
o_fragColor = vec4((ambient + diffuse + emission + specular) * u_sun.intensity, 1);
}

View file

@ -0,0 +1,30 @@
#version 330 core
in vec3 a_normal;
in vec2 a_tangent;
in vec2 a_uv;
out vec2 v_uv;
out vec3 v_normal;
out vec3 v_position;
out vec3 v_camDirection;
out mat3 v_TBN;
uniform float u_radius;
uniform mat4 u_mvpMatrix;
uniform mat4 u_mvMatrix;
uniform mat4 u_modelMatrix;
void main() {
vec3 position = u_radius * a_normal;
gl_Position = u_mvpMatrix * vec4(position, 1);
v_normal = normalize(vec3(u_modelMatrix * vec4(a_normal, 0)));
v_uv = a_uv;
v_position = (u_modelMatrix * vec4(position, 1)).xyz;
v_camDirection = (u_mvMatrix * vec4(position, 1)).xyz;
vec3 tangent = normalize((u_modelMatrix * vec4(a_tangent, a_normal.z, 0)).xyz);
v_TBN = mat3(tangent, cross(tangent, v_normal), v_normal);
}

View file

@ -0,0 +1,22 @@
#version 330 core
in vec3 v_position;
in float v_u;
out vec4 o_fragColor;
uniform vec3 u_sun;
uniform vec3 u_planet;
uniform float u_planetRadius;
uniform float u_ambient;
uniform sampler1D u_texture;
void main() {
vec3 incident = v_position - u_sun;
vec3 plane_normal = u_planet - u_sun;
vec3 plane_intersect = dot(plane_normal, plane_normal) / dot(incident, plane_normal) * incident;
o_fragColor = texture(u_texture, v_u);
if (length(plane_intersect) < length(incident) &&
distance(plane_intersect, plane_normal) <= u_planetRadius)
o_fragColor.rgb *= u_ambient;
}

View file

@ -0,0 +1,16 @@
#version 330 core
in vec2 a_position;
in float a_u;
out vec3 v_position;
out float v_u;
uniform mat4 u_mvpMatrix;
uniform mat4 u_modelMatrix;
void main() {
gl_Position = u_mvpMatrix * vec4(a_position, 0, 1);
v_position = (u_modelMatrix * vec4(a_position, 0, 1)).xyz;
v_u = a_u;
}

View file

@ -0,0 +1,13 @@
#version 330 core
in vec3 v_direction;
out vec4 o_fragColor;
uniform bool u_lines;
uniform samplerCube u_skysphere;
uniform samplerCube u_constellation;
void main() {
o_fragColor = texture(u_skysphere, v_direction);
if (u_lines)
o_fragColor += texture(u_constellation, v_direction);
}

View file

@ -0,0 +1,10 @@
#version 330 core
in vec3 a_direction;
out vec3 v_direction;
uniform mat4 u_mvpMatrix;
void main() {
gl_Position = (u_mvpMatrix * vec4(a_direction, 1)).xyww;
v_direction = a_direction;
}

View file

@ -0,0 +1,9 @@
#version 330 core
in vec2 v_uv;
out vec4 o_fragColor;
uniform sampler2D u_emission;
void main() {
o_fragColor = vec4(texture(u_emission, v_uv).rgb, 1);
}

View file

@ -0,0 +1,14 @@
#version 330 core
in vec3 a_normal;
in vec2 a_uv;
out vec2 v_uv;
uniform float u_radius;
uniform mat4 u_mvpMatrix;
void main() {
gl_Position = u_mvpMatrix * vec4(u_radius * a_normal, 1);
v_uv = a_uv;
}

View file

@ -0,0 +1,12 @@
#version 330 core
in vec2 v_uv;
out vec4 o_fragColor;
uniform sampler2D u_alpha;
uniform vec3 u_color;
void main() {
o_fragColor = vec4(u_color, texture(u_alpha, v_uv).r);
}

View file

@ -0,0 +1,14 @@
#version 330 core
in vec2 a_rc;
in vec2 a_tex;
out vec2 v_uv;
uniform mat4 u_projMatrix;
uniform vec2 u_start;
void main() {
gl_Position = u_projMatrix * vec4(a_rc.y * 8 + u_start.x, a_rc.x * 16 + u_start.y, 0, 1);
v_uv = vec2(a_tex.x * 8 / 1024, a_tex.y);
}

95
punyverse/small_images.py Normal file
View file

@ -0,0 +1,95 @@
from __future__ import print_function, division
import os
from PIL import Image
from punyverse.texture import max_texture_size
max_texture = max_texture_size()
def resize(width, height, target):
factor = target / max(width, height)
return int(width * factor), int(height * factor)
def fits(width, height):
return width <= max_texture and height <= max_texture
def make_name(image, suffix):
name, ext = os.path.splitext(image)
return '%s_%s%s' % (name, suffix, ext)
def shrink(file):
image = Image.open(file)
width, height = image.size
if fits(width, height):
print('no need')
return
for attempt, new_size in [(4096, 'large'), (2048, 'medium')]:
width, height = resize(width, height, attempt)
if fits(width, height):
size = new_size
break
else:
width, height = resize(width, height, 1024) # 1024 is minimum
size = 'small'
print('size %s, %dx%d...' % (size, width, height), end=' ')
name = make_name(file, size)
if not os.path.exists(name):
original_width, original_height = image.size
if width * 3 < original_width and height * 3 < original_height:
image = image.resize((width * 2, height * 2))
image.resize((width, height), Image.ANTIALIAS).save(name)
print('saved to:', os.path.basename(name))
else:
print('already there')
textures = [
'mercury.jpg',
'earth.jpg',
'moon.jpg',
'mars.jpg',
'jupiter.jpg',
'saturn.jpg',
'moons/io.jpg',
'moons/europa.jpg',
'moons/ganymede.jpg',
'moons/callisto.jpg',
'moons/titan.jpg',
'moons/rhea.jpg',
'moons/iapetus.jpg',
'moons/dione.jpg',
'moons/tethys.jpg',
'moons/enceladus.jpg',
'moons/mimas.jpg',
]
def main():
punyverse = os.path.dirname(__file__)
try:
with open(os.path.join(punyverse, 'assets', 'textures.txt')) as f:
files = [i.strip() for i in f if not i.startswith('#') and i.strip()]
except IOError:
files = textures
texture = os.path.join(punyverse, 'assets', 'textures')
for file in files:
print('Resizing %s:' % file, end=' ')
file = os.path.join(texture, file.replace('/', os.sep))
if os.path.exists(file):
shrink(file)
else:
print('exists not')
if __name__ == '__main__':
main()

View file

@ -1,116 +1,93 @@
from pyglet import image from __future__ import print_function
from pyglet.gl import *
from ctypes import c_int, byref, c_ulong
import os.path import os.path
import struct import struct
from ctypes import c_int, byref
from io import BytesIO
import six
from pyglet import image
from pyglet.gl import *
from six.moves import range
try: try:
from _glgeom import bgr_to_rgb from ._glgeom import bgr_to_rgb, flip_vertical
except ImportError: except ImportError:
import warnings import warnings
warnings.warn('Compile _glgeom.c, or double the start up time.') warnings.warn('Compile _glgeom.c, or double the start up time.')
# Use magick when _glgeom is not compiled (is actually slower)
try:
from pgmagick import Blob, Image
except ImportError:
magick = False
else:
magick = True
def bgr_to_rgb(source, width, height, alpha=False, bottom_up=True):
def bgr_to_rgb(source, width, height, alpha=False):
length = len(source) length = len(source)
depth = length / (width * height) depth = length // (width * height)
depth2 = depth - alpha depth2 = depth - alpha
result = bytearray(length) result = bytearray(length)
row = width * depth row = width * depth
for y in xrange(height): for y in range(height):
for x in xrange(width): for x in range(width):
ioffset = y * width * depth + x * depth offset = y * row + x * depth
ooffset = (height - y - 1 if bottom_up else y) * row + x * depth for i in range(depth2):
for i in xrange(depth2): result[offset + i] = source[offset + depth2 - i - 1]
result[ooffset+i] = source[ioffset+depth2-i-1]
if alpha: if alpha:
result[ooffset+depth2] = source[ioffset+depth2] result[offset + depth2] = source[offset + depth2]
return str(result) return six.binary_type(result)
else:
magick = False
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
__all__ = ['load_texture'] def flip_vertical(source, width, height):
length = len(source)
row = length // height
result = bytearray(length)
for y1 in range(height):
y2 = height - y1 - 1
result[y1 * row:y1 * row + row] = source[y2 * row:y2 * row + row]
return six.binary_type(result)
__all__ = ['load_texture', 'load_alpha_mask', 'load_image', 'get_best_texture', 'max_texture_size',
'get_cube_map', 'load_texture_1d']
id = 0 id = 0
cache = {} cache = {}
max_texture = None
power_of_two = None
badcard = False
bgra = False
def is_power2(num):
def init(): return num != 0 and ((num & (num - 1)) == 0)
global max_texture, power_of_two, badcard, bgra, magick
if max_texture is None:
buf = c_int()
glGetIntegerv(GL_MAX_TEXTURE_SIZE, byref(buf))
max_texture = buf.value
badcard = gl_info.get_renderer() in ('GDI Generic',)
if badcard:
import warnings
warnings.warn('Please update your graphics drivers if possible')
#extensions = gl_info.get_extensions()
#bgra = 'GL_EXT_bgra' in extensions
#if bgra and magick:
# magick = False # Disable magick because BGRA needs it not
if power_of_two is None:
power_of_two = gl_info.have_version(2) or gl_info.have_extension('GL_ARB_texture_non_power_of_two')
is_power2 = lambda num: num != 0 and ((num & (num - 1)) == 0)
def image_info(data): def image_info(data):
data = str(data) data = six.binary_type(data)
size = len(data) size = len(data)
height = -1 height = -1
width = -1 width = -1
content_type = '' content_type = ''
# handle GIFs # handle GIFs
if (size >= 10) and data[:6] in ('GIF87a', 'GIF89a'): if size >= 10 and data[:6] in (b'GIF87a', b'GIF89a'):
# Check to see if content_type is correct # Check to see if content_type is correct
content_type = 'image/gif' content_type = 'image/gif'
w, h = struct.unpack("<HH", data[6:10]) w, h = struct.unpack('<HH', data[6:10])
width = int(w) width = int(w)
height = int(h) height = int(h)
# See PNG 2. Edition spec (http://www.w3.org/TR/PNG/) # See PNG 2. Edition spec (http://www.w3.org/TR/PNG/)
# Bytes 0-7 are below, 4-byte chunk length, then 'IHDR' # Bytes 0-7 are below, 4-byte chunk length, then 'IHDR'
# and finally the 4-byte width, height # and finally the 4-byte width, height
elif ((size >= 24) and data.startswith('\211PNG\r\n\032\n') elif size >= 24 and data.startswith(b'\211PNG\r\n\032\n') and data[12:16] == b'IHDR':
and (data[12:16] == 'IHDR')):
content_type = 'image/png' content_type = 'image/png'
w, h = struct.unpack(">LL", data[16:24]) w, h = struct.unpack('>LL', data[16:24])
width = int(w) width = int(w)
height = int(h) height = int(h)
# Maybe this is for an older PNG version. # Maybe this is for an older PNG version.
elif (size >= 16) and data.startswith('\211PNG\r\n\032\n'): elif size >= 16 and data.startswith(b'\211PNG\r\n\032\n'):
# Check to see if we have the right content type
content_type = 'image/png' content_type = 'image/png'
w, h = struct.unpack(">LL", data[8:16]) w, h = struct.unpack('>LL', data[8:16])
width = int(w) width = int(w)
height = int(h) height = int(h)
# handle JPEGs # handle JPEGs
elif (size >= 2) and data.startswith('\377\330'): elif size >= 2 and data.startswith(b'\377\330'):
content_type = 'image/jpeg' content_type = 'image/jpeg'
jpeg = StringIO(data) jpeg = BytesIO(data)
jpeg.read(2) jpeg.read(2)
b = jpeg.read(1) b = jpeg.read(1)
try: try:
@ -121,13 +98,11 @@ def image_info(data):
b = jpeg.read(1) b = jpeg.read(1)
if 0xC0 <= ord(b) <= 0xC3: if 0xC0 <= ord(b) <= 0xC3:
jpeg.read(3) jpeg.read(3)
h, w = struct.unpack(">HH", jpeg.read(4)) height, width = struct.unpack('>HH', jpeg.read(4))
break break
else: else:
jpeg.read(int(struct.unpack(">H", jpeg.read(2))[0])-2) jpeg.read(int(struct.unpack('>H', jpeg.read(2))[0]) - 2)
b = jpeg.read(1) b = jpeg.read(1)
width = int(w)
height = int(h)
except struct.error: except struct.error:
pass pass
except ValueError: except ValueError:
@ -136,87 +111,209 @@ def image_info(data):
return content_type, width, height return content_type, width, height
def glGetInteger(index):
buf = c_int()
glGetIntegerv(index, byref(buf))
return buf.value
def max_texture_size():
size = glGetInteger(GL_MAX_TEXTURE_SIZE)
if gl_info.get_vendor() == 'Intel':
# Intel can't seem to handle more than 4096
size = min(size, 4096)
return size
def check_size(width, height): def check_size(width, height):
init() max_texture = max_texture_size()
if width > max_texture or height > max_texture: if width > max_texture or height > max_texture:
print 'too large' print('too large')
raise ValueError('Texture too large') raise ValueError('Texture too large')
elif not power_of_two:
if not is_power2(width) or not is_power2(height):
print 'not power of two'
raise ValueError('Texture not power of two')
def load_texture(file): def load_image(file, path):
if os.path.isabs(file): print('Loading image %s...' % file, end=' ')
path = file
file = os.path.basename(path)
else:
path = os.path.join(os.path.dirname(__file__), "assets", "textures", file)
if path in cache:
return cache[path]
print "Loading image %s..." % file,
try: try:
file = open(path, 'rb') file = open(path, 'rb')
except IOError: except IOError:
print 'exists not' print('does not exist')
raise ValueError('Texture exists not') raise ValueError('Texture does not exist')
type, width, height = image_info(file.read(8192))
type, width, height = image_info(file.read(65536))
file.seek(0, 0) file.seek(0, 0)
if type: if type:
check_size(width, height) check_size(width, height)
if magick: try:
file.close() raw = image.load(path, file=file)
file = Image(path.encode('mbcs' if os.name == 'nt' else 'utf8')) except Exception:
geo = file.size() print('cannot be loaded')
check_size(geo.width(), geo.height()) raise ValueError('cannot be loaded')
print
blob = Blob()
file.flip()
file.write(blob, 'RGBA')
texture = blob.data
mode = GL_RGBA
else:
try:
raw = image.load(path, file=file)
except IOError:
print 'exists not'
raise ValueError('Texture exists not')
width, height = raw.width, raw.height width, height = raw.width, raw.height
check_size(width, height) check_size(width, height)
print print()
mode = GL_RGBA if 'A' in raw.format else GL_RGB mode = GL_RGBA if 'A' in raw.format else GL_RGB
# Flip from BGR to RGB
# I hate you too, Pyglet... # Flip from BGR to RGB
# REGULAR EXPRESSIONS ARE NOT MEANT TO PARSE BINARY DATA!!! if raw.format in ('BGR', 'BGRA'):
#texture = raw.get_data('RGBA', width * 4) if safe else raw.data[::-1] if 'BGR' in raw.format else raw.data if gl_info.have_extension('GL_EXT_bgra'):
if raw.format in ('BGR', 'BGRA'): mode = GL_BGRA if 'A' in raw.format else GL_BGR
if bgra:
mode = {GL_RGBA: GL_BGRA, GL_RGB: GL_BGR}[mode]
texture = raw.data
else:
texture = bgr_to_rgb(raw.data, width, height, 'A' in raw.format)
elif raw.format in ('RGB', 'RGBA'):
texture = raw.data texture = raw.data
else: else:
texture = raw.get_data('RGBA', width * 4) texture = bgr_to_rgb(raw.data, width, height, 'A' in raw.format)
elif raw.format in ('RGB', 'RGBA'):
texture = raw.data
else:
texture = raw.get_data('RGBA', width * 4)
buffer = c_ulong() return path, width, height, len(raw.format), mode, flip_vertical(texture, width, height)
def get_file_path(file):
if os.path.isabs(file):
path = file
file = os.path.basename(path)
else:
path = os.path.join(os.path.dirname(__file__), 'assets', 'textures', file)
return path, file
def create_texture():
buffer = GLuint()
glGenTextures(1, byref(buffer))
id = buffer.value
return id
def delete_texture(id):
buffer = GLuint(id)
glDeleteTextures(1, byref(buffer))
def get_internal_mode(mode):
return {
GL_RGB: GL_RGB8,
GL_BGR: GL_RGB8,
GL_RGBA: GL_RGBA8,
GL_BGRA: GL_RGBA8,
}[mode]
def load_texture(file, clamp=False):
path, file = get_file_path(file)
if path in cache:
return cache[path]
path, width, height, depth, mode, texture = load_image(file, path)
id = create_texture()
glBindTexture(GL_TEXTURE_2D, id)
glTexImage2D(GL_TEXTURE_2D, 0, get_internal_mode(mode), width, height, 0, mode, GL_UNSIGNED_BYTE, texture)
glGenerateMipmap(GL_TEXTURE_2D)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
if clamp:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
if gl_info.have_extension('GL_EXT_texture_filter_anisotropic'):
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, glGetInteger(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT))
cache[path] = id
return id
def load_texture_1d(file, clamp=False):
path, file = get_file_path(file)
path, width, height, depth, mode, texture = load_image(file, path)
id = create_texture()
glBindTexture(GL_TEXTURE_1D, id)
glTexImage1D(GL_TEXTURE_1D, 0, get_internal_mode(mode), width, 0, mode, GL_UNSIGNED_BYTE, texture)
glGenerateMipmap(GL_TEXTURE_1D)
if clamp:
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
if gl_info.have_extension('GL_EXT_texture_filter_anisotropic'):
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAX_ANISOTROPY_EXT, glGetInteger(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT))
return id
def load_alpha_mask(file, clamp=False):
path, file = get_file_path(file)
path, width, height, depth, mode, texture = load_image(file, path)
if depth != 1:
texture = texture[::depth]
buffer = GLuint()
glGenTextures(1, byref(buffer)) glGenTextures(1, byref(buffer))
id = buffer.value id = buffer.value
glBindTexture(GL_TEXTURE_2D, id) glBindTexture(GL_TEXTURE_2D, id)
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, texture)
glGenerateMipmap(GL_TEXTURE_2D)
filter = GL_NEAREST if badcard else GL_LINEAR glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter)
gluBuild2DMipmaps(GL_TEXTURE_2D, len(raw.format), width, height, mode, GL_UNSIGNED_BYTE, texture)
cache[path] = id if clamp:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
return id if gl_info.have_extension('GL_EXT_texture_filter_anisotropic'):
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, glGetInteger(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT))
return id
def get_cube_map(files, callback=None):
assert len(files) == 6
callback = callback or (lambda index, file: None)
id = create_texture()
glBindTexture(GL_TEXTURE_CUBE_MAP, id)
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0)
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0)
for index, (file, part) in enumerate(zip(files, [
GL_TEXTURE_CUBE_MAP_POSITIVE_X,
GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
])):
try:
path, file = get_file_path(file)
callback(index, file)
path, width, height, depth, mode, texture = load_image(file, path)
except Exception:
delete_texture(id)
raise
glTexImage2D(part, 0, get_internal_mode(mode), width, height, 0, mode, GL_UNSIGNED_BYTE, texture)
return id
def get_best_texture(info, loader=load_texture, optional=False, **kwargs):
if isinstance(info, list):
for item in info:
try:
return loader(item, **kwargs)
except ValueError:
pass
else:
return loader(info, **kwargs)
if not optional:
raise ValueError('No texture found')

279
punyverse/ui.py Normal file
View file

@ -0,0 +1,279 @@
#!/usr/bin/python
from __future__ import division
import os
import time
from math import hypot
from operator import attrgetter
import pyglet
import six
from pyglet.gl import *
from pyglet.window import key, mouse
from punyverse.glgeom import *
MOUSE_SENSITIVITY = 0.3 # Mouse sensitivity, 0..1, none...hyperspeed
MAX_DELTA = 5
SEED = int(time.time())
def entity_distance(x0, y0, z0):
def distance(entity):
x1, y1, z1 = entity.location
return hypot(hypot(x1 - x0, y1 - y0), z1 - z0)
return distance
class Punyverse(pyglet.window.Window):
def __init__(self, *args, **kwargs):
super(Punyverse, self).__init__(*args, **kwargs)
self.fps = 0
self.info = True
self.debug = False
self.orbit = True
self.running = True
self.moving = True
self.info_precise = False
self.atmosphere = True
self.cloud = True
self.constellations = False
self.ticks = [
1, 2, 5, 10, 20, 40, 60, # Second range
120, 300, 600, 1200, 1800, 2700, 3600, # Minute range
7200, 14400, 21600, 43200, 86400, # Hour range
172800, 432000, 604800, # 2, 5, 7 days
1209600, 2592000, # 2 week, 1 month
5270400, 7884000, 15768000, 31536000, # 2, 3, 6, 12 months
63072000, 157680000, 315360000, # 2, 5, 10 years
630720000, 1576800000, 3153600000, # 20, 50, 100 years
]
self.key_handler = {}
self.mouse_press_handler = {}
self.exclusive = False
self.modifiers = 0
self.world = None
def initialize(self, world):
self.world = world
def speed_incrementer(object, increment):
def incrementer():
object.speed += increment
return incrementer
def attribute_toggler(object, attribute):
getter = attrgetter(attribute)
def toggler():
setattr(object, attribute, not getter(object))
return toggler
def increment_tick():
index = self.ticks.index(self.world.tick_length) + 1
if index < len(self.ticks):
self.world.tick_length = self.ticks[index]
def decrement_tick():
index = self.ticks.index(self.world.tick_length) - 1
if index >= 0:
self.world.tick_length = self.ticks[index]
self.key_handler = {
key.ESCAPE: pyglet.app.exit,
key.NUM_ADD: speed_incrementer(self.world.cam, 1),
key.NUM_SUBTRACT: speed_incrementer(self.world.cam, -1),
key.NUM_MULTIPLY: speed_incrementer(self.world.cam, 10),
key.NUM_DIVIDE: speed_incrementer(self.world.cam, -10),
key.PAGEUP: speed_incrementer(self.world.cam, 100),
key.PAGEDOWN: speed_incrementer(self.world.cam, -100),
key.HOME: speed_incrementer(self.world.cam, 1000),
key.END: speed_incrementer(self.world.cam, -1000),
key.R: self.world.cam.reset_roll,
key.I: attribute_toggler(self, 'info'),
key.D: attribute_toggler(self, 'debug'),
key.O: attribute_toggler(self, 'orbit'),
key.P: attribute_toggler(self, 'info_precise'),
key.C: attribute_toggler(self, 'cloud'),
key.X: attribute_toggler(self, 'atmosphere'),
key.L: attribute_toggler(self, 'constellations'),
key.ENTER: attribute_toggler(self, 'running'),
key.INSERT: increment_tick,
key.DELETE: decrement_tick,
key.SPACE: self.world.spawn_asteroid,
key.E: lambda: self.set_exclusive_mouse(False),
key.F: lambda: self.set_fullscreen(not self.fullscreen),
}
self.mouse_press_handler = {
mouse.LEFT: self.world.spawn_asteroid,
mouse.RIGHT: attribute_toggler(self, 'moving'),
}
glClearColor(0, 0, 0, 1)
glClearDepth(1.0)
glDepthFunc(GL_LEQUAL)
glEnable(GL_DEPTH_TEST)
glShadeModel(GL_SMOOTH)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
self.info_engine = FontEngine(self.world.activate_shader('text'))
self.circle = Circle(10, 20, self.world.activate_shader('line'))
pyglet.clock.schedule(self.update)
self.on_resize(self.width, self.height) # On resize handler does nothing unless it's loaded
def screenshot(self):
image = pyglet.image.get_buffer_manager().get_color_buffer()
if hasattr(self, '_hwnd') and not self.modifiers & key.MOD_CTRL:
from ctypes import windll
from PIL import Image
import tempfile
CF_BITMAP = 2
image = Image.frombytes(image.format, (image.width, image.height), image.get_image_data().data)
image = image.convert('RGB').transpose(Image.FLIP_TOP_BOTTOM)
fd, filename = tempfile.mkstemp('.bmp')
try:
with os.fdopen(fd, 'wb') as file:
image.save(file, 'BMP')
if isinstance(filename, six.binary_type):
filename = filename.decode('mbcs' if os.name == 'nt' else 'utf8')
image = windll.user32.LoadImageW(None, filename, 0, 0, 0, 0x10)
windll.user32.OpenClipboard(self._hwnd)
windll.user32.EmptyClipboard()
windll.user32.SetClipboardData(CF_BITMAP, image)
windll.user32.CloseClipboard()
finally:
os.remove(filename)
else:
image.save(os.path.expanduser('~/punyverse.png'))
def set_exclusive_mouse(self, exclusive):
super(Punyverse, self).set_exclusive_mouse(exclusive)
self.exclusive = exclusive
def on_mouse_press(self, x, y, button, modifiers):
self.modifiers = modifiers
if not self.exclusive:
self.set_exclusive_mouse(True)
else:
if button in self.mouse_press_handler:
self.mouse_press_handler[button]()
def on_mouse_motion(self, x, y, dx, dy):
if self.exclusive: # Only handle camera movement if mouse is grabbed
self.world.cam.mouse_move(dx * MOUSE_SENSITIVITY, dy * MOUSE_SENSITIVITY)
def on_key_press(self, symbol, modifiers):
self.modifiers = modifiers
if symbol == key.Q:
self.screenshot()
if self.exclusive: # Only handle keyboard input if mouse is grabbed
if symbol in self.key_handler:
self.key_handler[symbol]()
elif symbol == key.A:
self.world.cam.roll_left = True
elif symbol == key.S:
self.world.cam.roll_right = True
def on_key_release(self, symbol, modifiers):
if symbol == key.A:
self.world.cam.roll_left = False
elif symbol == key.S:
self.world.cam.roll_right = False
def on_resize(self, width, height):
if not width or not height:
# Sometimes this happen for no reason?
return
if hasattr(self, 'get_viewport_size'):
width, height = self.get_viewport_size()
glViewport(0, 0, width, height)
self.world.resize(width, height)
def on_mouse_scroll(self, x, y, scroll_x, scroll_y):
self.world.cam.speed += scroll_y * 50 + scroll_x * 500
def get_time_per_second(self):
time = self.world.tick_length
unit = 'seconds'
for size, name in ((60, 'minutes'), (60, 'hours'), (24, 'days'), (365, 'years')):
if time < size:
break
time /= size
unit = name
result = '%s %s' % (round(time, 1), unit)
return result
def update(self, dt):
self.world.update(dt, move=self.exclusive and self.moving, tick=self.running)
def on_draw(self):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
c = self.world.cam
x, y, z = c.x, c.y, c.z
world = self.world
get_distance = entity_distance(x, y, z)
if x != world.x or y != world.y or z != world.z:
world.tracker.sort(key=get_distance, reverse=True)
world.tracker.sort(key=attrgetter('background'), reverse=True)
world.x, world.y, world.z = x, y, z
for entity in world.tracker:
entity.draw(self)
if self.info:
width, height = self.get_size()
projection = Matrix4f([
2 / width, 0, 0, 0,
0, -2 / height, 0, 0,
0, 0, -1, 0,
-1, 1, 0, 1,
])
if self.info_precise:
info = ('%d FPS @ (x=%.2f, y=%.2f, z=%.2f) @ %s, %s/s\n'
'Direction(pitch=%.2f, yaw=%.2f, roll=%.2f)\nTick: %d' %
(pyglet.clock.get_fps(), c.x, c.y, c.z, self.world.cam.speed, self.get_time_per_second(),
c.pitch, c.yaw, c.roll, self.world.tick))
else:
info = ('%d FPS @ (x=%.2f, y=%.2f, z=%.2f) @ %s, %s/s\n' %
(pyglet.clock.get_fps(), c.x, c.y, c.z, self.world.cam.speed, self.get_time_per_second()))
glEnable(GL_BLEND)
shader = self.world.activate_shader('text')
shader.uniform_mat4('u_projMatrix', projection)
glBindTexture(GL_TEXTURE_2D, self.world.font_tex)
shader.uniform_texture('u_alpha', 0)
shader.uniform_vec3('u_color', 1, 1, 1)
shader.uniform_vec2('u_start', 10, 10)
self.info_engine.draw(info)
with self.info_engine.vao:
glDrawArrays(GL_TRIANGLES, 0, self.info_engine.vertex_count)
glDisable(GL_BLEND)
glLineWidth(2)
mvp = projection * Matrix4f.from_angles((width / 2, height /2, 0))
shader = self.world.activate_shader('line')
shader.uniform_vec4('u_color', 0, 1, 0, 1)
shader.uniform_mat4('u_mvpMatrix', mvp)
with self.circle.vao:
glDrawArrays(GL_LINE_LOOP, 0, self.circle.vertex_count)
glLineWidth(1)

18
punyverse/utils.py Normal file
View file

@ -0,0 +1,18 @@
class cached_property(object):
def __init__(self, func, name=None):
self.func = func
self.name = name or func.__name__
self.__doc__ = getattr(func, '__doc__')
def __get__(self, instance, owner=None):
if instance is None:
return self
result = instance.__dict__[self.name] = self.func(instance)
return result
def __set__(self, instance, value):
if value is None:
if self.name in instance.__dict__:
del instance.__dict__[self.name]
else:
instance.__dict__[self.name] = value

View file

@ -7,15 +7,48 @@
"distance": "virtual distance to look better, in km", "distance": "virtual distance to look better, in km",
"sma": "semi-major axis used with mass of parent to calculate orbit, in km", "sma": "semi-major axis used with mass of parent to calculate orbit, in km",
"mass": "mass in kg", "mass": "mass in kg",
"texture": "a group of texture to use, tried in that order. a list means a colour", "texture": "a group of texture to use, tried in that order",
"model": "used to load a wavefront object instead of a textured sphere" "model": "used to load a wavefront object instead of a textured sphere"
}, },
"au": 10000, "au": 10000,
"tick": 180, "tick": 3600,
"length": 63.7, "length": 63.7,
"bodies": { "bodies": {
"sun": {
"texture": ["sun.jpg"],
"radius": 80000,
"pitch": -90,
"yaw": 7.25,
"mass": 1.9891e+30,
"rotation": 2164320,
"light_source": true,
"type": "star",
"atmosphere": {
"glow_color": [0.92, 0.92, 0.82],
"glow_texture": "glow.png",
"glow_size": 300
}
},
"mercury": {
"texture": ["mercury.jpg", "mercury_small.jpg"],
"radius": 2439.7,
"z": "0.466697 * AU",
"pitch": -90,
"yaw": 0.35,
"division": 30,
"rotation": 5067014
},
"venus": {
"texture": ["venus.jpg"],
"radius": 6051.8,
"z": "0.723327 * AU",
"pitch": -90,
"yaw": 177.36,
"division": 30,
"rotation": -20996798
},
"earth": { "earth": {
"texture": ["earth.jpg", "earth_medium.jpg", "earth_small.jpg", [0, 0.28, 1, 1]], "texture": ["earth.jpg", "earth_large.jpg", "earth_medium.jpg", "earth_small.jpg"],
"radius": 6378.1, "radius": 6378.1,
"z": "AU", "z": "AU",
"pitch": -90, "pitch": -90,
@ -23,18 +56,24 @@
"roll": -90, "roll": -90,
"mass": 5.97219e+24, "mass": 5.97219e+24,
"rotation": 86400, "rotation": 86400,
"division": 90,
"normal_map": ["earth_normal.jpg", "earth_normal_small.jpg"],
"specular_map": ["earth_specular.jpg", "earth_specular_small.jpg"],
"emission_map": ["earth_emission.jpg", "earth_emission_medium.jpg", "earth_emission_small.jpg"],
"atmosphere": { "atmosphere": {
"cloud_texture": "cloudmap.png", "cloud_texture": ["cloudmap.jpg", "cloudmap_small.jpg"],
"diffuse_texture": "atmosphere_earth.png", "glow_color": [0.11, 0.32, 0.43],
"diffuse_size": 30 "glow_texture": "glow.png",
"glow_size": 30
}, },
"orbit_distance": "AU", "orbit_distance": "AU",
"satellites": { "satellites": {
"moon": { "moon": {
"texture": ["moon.jpg", "moon_medium.jpg", "moon_small.jpg", [0.53, 0.53, 0.53, 1]], "texture": ["moon.jpg", "moon_medium.jpg", "moon_small.jpg"],
"radius": 1738.14, "radius": 1738.14,
"distance": 38439, "distance": 38439,
"sma": 384399, "sma": 384399,
"division": 30,
"eccentricity": 0.0549, "eccentricity": 0.0549,
"inclination": 5.145, "inclination": 5.145,
"rotation": 0, "rotation": 0,
@ -47,11 +86,17 @@
"inclination": 51.65, "inclination": 51.65,
"distance": 6800, "distance": 6800,
"scale": 5 "scale": 5
},
"hst": {
"model": "satellites/hst.obj",
"inclination": 28.5,
"distance": 6937,
"scale": 5
} }
} }
}, },
"mars": { "mars": {
"texture": ["mars.jpg", "mars_small.jpg", "mars_medium.jpg", [0.85, 0.47, 0.2, 1]], "texture": ["mars.jpg", "mars_large.jpg", "mars_medium.jpg", "mars_small.jpg"],
"radius": 3396.2, "radius": 3396.2,
"z": "1.524 * AU", "z": "1.524 * AU",
"pitch": -90, "pitch": -90,
@ -59,6 +104,7 @@
"mass": 6.4185e+23, "mass": 6.4185e+23,
"rotation": 88643, "rotation": 88643,
"orbit_distance": "AU", "orbit_distance": "AU",
"division": 30,
"satellites": { "satellites": {
"phobos": { "phobos": {
"distance": 9377, "distance": 9377,
@ -69,7 +115,7 @@
} }
}, },
"jupiter": { "jupiter": {
"texture": ["jupiter.jpg", "jupiter_medium.jpg", "jupiter_small.jpg", [0.65, 0.36, 0.19, 1]], "texture": ["jupiter.jpg", "jupiter_medium.jpg", "jupiter_small.jpg"],
"radius": 71492, "radius": 71492,
"mass": 1.8986e+27, "mass": 1.8986e+27,
"z": "5.2 * AU", "z": "5.2 * AU",
@ -80,7 +126,7 @@
"orbit_distance": "3 * AU", "orbit_distance": "3 * AU",
"satellites": { "satellites": {
"io": { "io": {
"texture": ["moons/io.jpg", "moons/io_small.jpg", [0.62, 0.56, 0.35, 1]], "texture": ["moons/io.jpg", "moons/io_small.jpg"],
"radius": "1821.3 * 5", "radius": "1821.3 * 5",
"distance": 126510, "distance": 126510,
"sma": 421700, "sma": 421700,
@ -90,7 +136,7 @@
"eccentricity": 0.0041 "eccentricity": 0.0041
}, },
"europa": { "europa": {
"texture": ["moons/europa.jpg", "moons/europa_small.jpg", [0.77, 0.74, 0.65, 1]], "texture": ["moons/europa.jpg", "moons/europa_small.jpg"],
"radius": "1560.8 * 5", "radius": "1560.8 * 5",
"distance": 201270, "distance": 201270,
"sma": 670900, "sma": 670900,
@ -100,7 +146,7 @@
"eccentricity": 0.009 "eccentricity": 0.009
}, },
"ganymede": { "ganymede": {
"texture": ["moons/ganymede.jpg", "moons/ganymede_small.jpg", [0.52, 0.47, 0.46, 1]], "texture": ["moons/ganymede.jpg", "moons/ganymede_small.jpg"],
"radius": "2634.1 * 5", "radius": "2634.1 * 5",
"distance": 321120, "distance": 321120,
"sma": 1070400, "sma": 1070400,
@ -110,7 +156,7 @@
"eccentricity": 0.0013 "eccentricity": 0.0013
}, },
"callisto": { "callisto": {
"texture": ["moons/callisto.jpg", "moons/callisto_small.jpg", [0.49, 0.43, 0.34, 1]], "texture": ["moons/callisto.jpg", "moons/callisto_small.jpg"],
"radius": "2410.3 * 5", "radius": "2410.3 * 5",
"distance": 564810, "distance": 564810,
"sma": 1882700, "sma": 1882700,
@ -122,7 +168,7 @@
} }
}, },
"saturn": { "saturn": {
"texture": ["saturn.jpg", "saturn_medium.jpg", "saturn_small.jpg", [0.9, 0.8, 0.64, 1]], "texture": ["saturn.jpg", "saturn_medium.jpg", "saturn_small.jpg"],
"radius": 60268, "radius": 60268,
"mass": 5.6846e+26, "mass": 5.6846e+26,
"z": "9.58 * AU", "z": "9.58 * AU",
@ -137,7 +183,7 @@
"orbit_distance": "4 * AU", "orbit_distance": "4 * AU",
"satellites": { "satellites": {
"titan": { "titan": {
"texture": ["moons/titan.jpg", "moons/titan_small.jpg", [0.52, 0.39, 0.23, 1]], "texture": ["moons/titan.jpg", "moons/titan_small.jpg"],
"radius": "2576 * 10", "radius": "2576 * 10",
"distance": "1221870 / 3 + 200000", "distance": "1221870 / 3 + 200000",
"sma": 1221870, "sma": 1221870,
@ -147,7 +193,7 @@
"eccentricity": 0.0288 "eccentricity": 0.0288
}, },
"rhea": { "rhea": {
"texture": ["moons/rhea.jpg", "moons/rhea_small.jpg", [0.62, 0.60, 0.59, 1]], "texture": ["moons/rhea.jpg", "moons/rhea_small.jpg"],
"radius": "763.8 * 10", "radius": "763.8 * 10",
"distance": "527108 / 3 + 200000", "distance": "527108 / 3 + 200000",
"sma": 527108, "sma": 527108,
@ -157,7 +203,7 @@
"eccentricity": 0.0012583 "eccentricity": 0.0012583
}, },
"iapetus": { "iapetus": {
"texture": ["moons/iapetus.jpg", "moons/iapetus_small.jpg", [0.62, 0.60, 0.59, 1]], "texture": ["moons/iapetus.jpg", "moons/iapetus_small.jpg"],
"radius": "734.5 * 10", "radius": "734.5 * 10",
"distance": "3560820 / 3 + 200000", "distance": "3560820 / 3 + 200000",
"sma": 3560820, "sma": 3560820,
@ -167,7 +213,7 @@
"eccentricity": 0.0286125 "eccentricity": 0.0286125
}, },
"dione": { "dione": {
"texture": ["moons/dione.jpg", "moons/dione_small.jpg", [0.46, 0.46, 0.46, 1]], "texture": ["moons/dione.jpg", "moons/dione_small.jpg"],
"radius": "561.4 * 10", "radius": "561.4 * 10",
"distance": "377396 / 3 + 200000", "distance": "377396 / 3 + 200000",
"sma": 377396, "sma": 377396,
@ -177,7 +223,7 @@
"eccentricity": 0.0022 "eccentricity": 0.0022
}, },
"tethys": { "tethys": {
"texture": ["moons/tethys.jpg", "moons/tethys_small.jpg", [0.68, 0.68, 0.66, 1]], "texture": ["moons/tethys.jpg", "moons/tethys_small.jpg"],
"radius": "531.1 * 10", "radius": "531.1 * 10",
"distance": "294619 / 3 + 200000", "distance": "294619 / 3 + 200000",
"sma": 294619, "sma": 294619,
@ -187,7 +233,7 @@
"eccentricity": 0.0001 "eccentricity": 0.0001
}, },
"enceladus": { "enceladus": {
"texture": ["moons/enceladus.jpg", "moons/enceladus_small.jpg", [0.74, 0.74, 0.74, 1]], "texture": ["moons/enceladus.jpg", "moons/enceladus_small.jpg"],
"radius": "252.1 * 10", "radius": "252.1 * 10",
"distance": "237948 / 3 + 200000", "distance": "237948 / 3 + 200000",
"sma": 237948, "sma": 237948,
@ -197,7 +243,7 @@
"eccentricity": 0.0047 "eccentricity": 0.0047
}, },
"mimas": { "mimas": {
"texture": ["moons/mimas.jpg", "moons/mimas_small.jpg", [0.47, 0.47, 0.47, 1]], "texture": ["moons/mimas.jpg", "moons/mimas_small.jpg"],
"radius": "198.2 * 10", "radius": "198.2 * 10",
"distance": "181902 / 3 + 200000", "distance": "181902 / 3 + 200000",
"sma": 181902, "sma": 181902,
@ -205,16 +251,23 @@
"rotation": 0, "rotation": 0,
"inclination": 28.304, "inclination": 28.304,
"eccentricity": 0.0196 "eccentricity": 0.0196
},
"cassini": {
"model": "satellites/cassini.obj",
"inclination": 51.65,
"eccentricity": 0.5,
"distance": "1221870 / 3 + 200000",
"sma": 1221870,
"scale": 100
} }
} }
}, },
"uranus": { "uranus": {
"texture": ["uranus.jpg", [0, 0.53, 0.84, 1]], "texture": ["uranus.jpg"],
"radius": 25559, "radius": 25559,
"mass": 8.6810e+25, "mass": 8.6810e+25,
"z": "19.23 * AU", "z": "19.23 * AU",
"pitch": -90, "pitch": 7.77,
"yaw": 97.77,
"rotation": -62064, "rotation": -62064,
"orbit_distance": "6 * AU", "orbit_distance": "6 * AU",
"ring": { "ring": {
@ -227,7 +280,7 @@
} }
}, },
"neptune": { "neptune": {
"texture": ["neptune.jpg", [0.31, 0.49, 0.59, 1]], "texture": ["neptune.jpg"],
"radius": 24764, "radius": 24764,
"mass": 1.0243e+26, "mass": 1.0243e+26,
"z": "30.5 * AU", "z": "30.5 * AU",
@ -235,19 +288,33 @@
"rotation": 57996, "rotation": 57996,
"pitch": -90, "pitch": -90,
"yaw": 28.32 "yaw": 28.32
},
"sky": {
"texture": "sky.jpg",
"optional": true,
"lighting": false,
"radius": 190000,
"pitch": 90,
"yaw": 30,
"roll": 180,
"delta": 0,
"background": true
} }
}, },
"belts": {
"main": {
"model": ["asteroids/mainbelt.obj", "asteroids/mainbelt2.obj"],
"radius": "2.362 * AU",
"cross": 1000,
"scale": 30,
"count": 4096,
"rotation": 114536500
}
},
"sky": {
"texture": [
["sky_px.jpg", "sky_nx.jpg", "sky_py.jpg", "sky_ny.jpg", "sky_pz.jpg", "sky_nz.jpg"]
],
"constellation": [
"constellation_px.png", "constellation_nx.png", "constellation_py.png",
"constellation_ny.png", "constellation_pz.png", "constellation_nz.png"
],
"rotation": 0,
"division": 30,
"pitch": -119.3,
"yaw": -97
},
"asteroids": ["asteroids/01.obj", "asteroids/02.obj", "asteroids/03.obj"],
"font": "font.png",
"start": { "start": {
"z": "AU - 400", "z": "AU - 400",
"yaw": 180 "yaw": 180

View file

@ -1,186 +1,218 @@
from __future__ import division
import json
import os
from collections import OrderedDict from collections import OrderedDict
import os.path
try: import six
import json
except ImportError:
try:
import simplejson as json
except ImportError:
raise SystemExit('No JSON module found')
try: from punyverse import texture
from punyverse._model import model_list, load_model from punyverse.camera import Camera
except ImportError:
from punyverse.model import model_list, load_model
from punyverse.glgeom import *
from punyverse.entity import * from punyverse.entity import *
from punyverse.texture import * from punyverse.shader import Program
from math import pi, sqrt
G = 6.67384e-11 # Gravitation Constant
def get_best_texture(info, optional=False): def load_world(file, callback=lambda message, completion: None):
cheap = False return World(file, callback)
skip = False
texture = None
if isinstance(info, list):
for item in info:
if isinstance(item, list):
if len(item) == 4:
cheap = True
texture = item
break
continue
try:
texture = load_texture(item)
except ValueError:
pass
else:
break
else:
try:
texture = load_texture(info)
except ValueError:
if optional:
skip = True
else:
cheap = True
texture = [1, 1, 1, 1]
return cheap, skip, texture
def load_world(file):
with open(os.path.join(os.path.dirname(__file__), file)) as f:
root = json.load(f, object_pairs_hook=OrderedDict)
world = World()
au = root.get('au', 2000)
e = lambda x: eval(str(x), {'__builtins__': None}, {'AU': au})
tick = root.get('tick', 4320) # How many second is a tick?
length = root.get('length', 4320) # Satellite distance is in km, divide by this gets in world units
world.tick_length = tick
if 'start' in root:
info = root['start']
x = e(info.get('x', 0))
y = e(info.get('y', 0))
z = e(info.get('z', 0))
pitch = e(info.get('pitch', 0))
yaw = e(info.get('yaw', 0))
roll = e(info.get('roll', 0))
world.start = (x, y, z)
world.direction = (pitch, yaw, roll)
def body(name, info, parent=None):
lighting = info.get('lighting', True)
x = e(info.get('x', 0))
y = e(info.get('y', 0))
z = e(info.get('z', 0))
pitch = e(info.get('pitch', 0))
yaw = e(info.get('yaw', 0))
roll = e(info.get('roll', 0))
rotation = e(info.get('rotation', 86400))
radius = e(info.get('radius', length)) / length
background = info.get('background', False)
orbit_distance = e(info.get('orbit_distance', au))
if 'texture' in info:
cheap, skip, texture = get_best_texture(info['texture'], optional=info.get('optional', False))
if skip:
return
division = min(int(radius / 2), 100)
if cheap:
object_id = compile(colourball, radius, division, division, texture)
else:
object_id = compile(sphere, radius, division, division, texture, lighting=lighting)
elif 'model' in info:
scale = info.get('scale', 1)
object_id = model_list(load_model(info['model']), info.get('sx', scale), info.get('sy', scale),
info.get('sz', scale), (0, 0, 0))
else:
print 'Nothing to load for %s.' % name
return
params = {'world': world, 'orbit_distance': orbit_distance}
if parent is None:
type = Body
else:
x, y, z = parent.location
distance = e(info.get('distance', 100)) # Semi-major axis when actually displayed in virtual space
sma = e(info.get('sma', distance)) # Semi-major axis used to calculate orbital speed
if hasattr(parent, 'mass') and parent.mass is not None:
period = 2 * pi * sqrt((sma * 1000) ** 3 / (G * parent.mass))
speed = 360 / (period + .0)
if not rotation: # Rotation = 0 assumes tidal lock
rotation = period
else:
speed = info.get('orbit_speed', 1)
type = Satellite
params.update(parent=parent, orbit_speed=speed,
distance=distance / length, eccentricity=info.get('eccentricity', 0),
inclination=info.get('inclination', 0), longitude=info.get('longitude', 0),
argument=info.get('argument', 0))
if 'mass' in info:
params['mass'] = info['mass']
atmosphere_id = 0
cloudmap_id = 0
if 'atmosphere' in info:
atmosphere_data = info['atmosphere']
size = e(atmosphere_data.get('diffuse_size', None))
atm_texture = atmosphere_data.get('diffuse_texture', None)
cloud_texture = atmosphere_data.get('cloud_texture', None)
cheap, _, cloud_texture = get_best_texture(cloud_texture)
if not cheap:
division = min(int(radius / 2), 100)
cloudmap_id = compile(sphere, radius + 2, division, division, cloud_texture,
lighting=False)
cheap, _, atm_texture = get_best_texture(atm_texture)
if not cheap:
atmosphere_id = compile(disk, radius, radius + size, 30, atm_texture)
object = type(object_id, (x, y, z), (pitch, yaw, roll), rotation_angle=360 / (rotation + .0),
atmosphere=atmosphere_id, cloudmap=cloudmap_id, background=background, **params)
world.tracker.append(object)
if 'ring' in info:
ring_data = info['ring']
texture = ring_data.get('texture', None)
distance = e(ring_data.get('distance', radius * 1.2))
size = e(ring_data.get('size', radius / 2))
pitch = e(ring_data.get('pitch', pitch))
yaw = e(ring_data.get('yaw', yaw))
roll = e(ring_data.get('roll', roll))
cheap, _, texture = get_best_texture(texture)
if not cheap:
world.tracker.append(
type(compile(disk, distance, distance + size, 30, texture), (x, y, z),
(pitch, yaw, roll), **params))
for satellite, info in info.get('satellites', {}).iteritems():
print "Loading %s, satellite of %s." % (satellite, name)
body(satellite, info, object)
for planet, info in root['bodies'].iteritems():
print "Loading %s." % planet
body(planet, info)
return world
class World(object): class World(object):
def __init__(self): PROGRAMS = {
'sky': ('sky.vertex.glsl', 'sky.fragment.glsl'),
'planet': ('planet.vertex.glsl', 'planet.fragment.glsl'),
'clouds': ('clouds.vertex.glsl', 'clouds.fragment.glsl'),
'star': ('star.vertex.glsl', 'star.fragment.glsl'),
'ring': ('ring.vertex.glsl', 'ring.fragment.glsl'),
'atmosphere': ('atmosphere.vertex.glsl', 'atmosphere.fragment.glsl'),
'text': ('text.vertex.glsl', 'text.fragment.glsl'),
'line': ('line.vertex.glsl', 'line.fragment.glsl'),
'model': ('model.vertex.glsl', 'model.fragment.glsl'),
'belt': ('belt.vertex.glsl', 'model.fragment.glsl'),
}
def __init__(self, file, callback, sky=True):
self.tracker = [] self.tracker = []
self.start = (0, 0, 0)
self.direction = (0, 0, 0)
self.x = None self.x = None
self.y = None self.y = None
self.z = None self.z = None
self.tick_length = 1 self.tick_length = 0
self.tick = 0 self.tick = 0
self.asteroids = AsteroidManager(self)
self.cam = Camera()
self._sky = sky
self._program = None
self.callback = callback
self.programs = self._load_programs()
self._parse(file)
del self.callback # So it can't be used after loading finishes
self._time_accumulate = 0
self._projection_matrix = self.cam.projection_matrix()
for entity in self.tracker:
entity.update()
for name in ('planet', 'model', 'belt'):
shader = self.activate_shader(name)
shader.uniform_vec3('u_sun.ambient', 0.1, 0.1, 0.1)
shader.uniform_vec3('u_sun.diffuse', 1, 1, 1)
shader.uniform_vec3('u_sun.specular', 0.5, 0.5, 0.5)
shader.uniform_vec3('u_sun.position', 0, 0, 0)
shader.uniform_float('u_sun.intensity', 1)
shader = self.activate_shader('clouds')
shader.uniform_vec3('u_sun', 0, 0, 0)
self.activate_shader(None)
def _load_programs(self):
programs = {}
count = len(self.PROGRAMS)
for i, (name, (vertex, fragment)) in enumerate(six.iteritems(self.PROGRAMS)):
self.callback('Loading shaders (%d of %d)...' % (i, count),
'Loading shader "%s" (%s, %s).' % (name, vertex, fragment), i / count)
programs[name] = Program(vertex, fragment)
return programs
def evaluate(self, value):
return eval(str(value), {'__builtins__': None}, self._context)
@property
def length(self):
return self._length
@property
def au(self):
return self._au
def _parse(self, file):
self.callback('Parsing configuration...', 'Loading configuration file...', 0)
with open(os.path.join(os.path.dirname(__file__), file)) as f:
root = json.load(f, object_pairs_hook=OrderedDict)
self._au = root.get('au', 2000)
self._length = root.get('length', 4320)
self._context = {'AU': self._au, 'TEXTURE': texture.max_texture_size(), 'KM': 1.0 / self._length}
self.tick_length = root.get('tick', 4320) # How many second is a tick?
# Need to know how many objects are being loaded
self._objects = 0
self._current_object = 0
def count_objects(bodies):
for body in six.itervalues(bodies):
self._objects += 1
count_objects(body.get('satellites', {}))
count_objects(root['bodies'])
if 'start' in root:
info = root['start']
self.cam.x = self.evaluate(info.get('x', 0))
self.cam.y = self.evaluate(info.get('y', 0))
self.cam.z = self.evaluate(info.get('z', 0))
self.cam.pitch = self.evaluate(info.get('pitch', 0))
self.cam.yaw = self.evaluate(info.get('yaw', 0))
self.cam.roll = self.evaluate(info.get('roll', 0))
for planet, info in six.iteritems(root['bodies']):
self.callback('Loading objects (%d of %d)...' % (self._current_object, self._objects),
'Loading %s.' % planet, self._current_object / self._objects)
self._body(planet, info)
self._current_object += 1
if 'belts' in root:
belt_count = len(root['belts'])
for i, (name, info) in enumerate(six.iteritems(root['belts']), 1):
self.callback('Loading belts (%d of %d)...' % (i, belt_count),
'Loading %s.' % name, i / belt_count)
self.tracker.append(Belt(name, self, info))
if 'sky' in root and self._sky:
def callback(index, file):
self.callback('Loading sky...', 'Loading %s.' % file, index / 6)
self.tracker.append(Sky(self, root['sky'], callback))
if 'asteroids' in root:
asteroids = root['asteroids']
for i, file in enumerate(asteroids):
self.callback('Loading asteroids...', 'Loading %s...' % file, i / len(asteroids))
self.asteroids.load(file)
self.font_tex = load_alpha_mask(root['font'], clamp=True)
def _body(self, name, info, parent=None):
if 'texture' in info:
body = SphericalBody(name, self, info, parent)
elif 'model' in info:
body = ModelBody(name, self, info, parent)
else:
raise ValueError('Nothing to load for %s.' % name)
if parent:
parent.satellites.append(body)
else:
self.tracker.append(body)
for satellite, info in six.iteritems(info.get('satellites', {})):
self.callback('Loading objects (%d of %d)...' % (self._current_object, self._objects),
'Loading %s, satellite of %s.' % (satellite, name), self._current_object / self._objects)
self._body(satellite, info, body)
self._current_object += 1
def spawn_asteroid(self):
if self.asteroids:
c = self.cam
dx, dy, dz = c.direction()
speed = abs(self.cam.speed) * 1.1 + 5
self.tracker.append(self.asteroids.new((c.x, c.y - 3, c.z + 5), (dx * speed, dy * speed, dz * speed)))
def update(self, dt, move, tick):
c = self.cam
c.update(dt, move)
self.vp_matrix = None
if tick:
delta = self.tick_length * dt
update = int(delta + self._time_accumulate + 0.5)
if update:
self._time_accumulate = 0
self.tick += update
for entity in self.tracker:
entity.update()
collision = entity.collides(c.x, c.y, c.z)
if collision:
c.speed *= -1
c.move(c.speed * 12 * dt)
else:
self._time_accumulate += delta
def view_matrix(self):
return self.cam.view_matrix
def projection_matrix(self):
return self._projection_matrix
@cached_property
def vp_matrix(self):
return self._projection_matrix * self.cam.view_matrix
def resize(self, width, height):
self.cam.aspect = width / max(height, 1)
self._projection_matrix = self.cam.projection_matrix()
self.vp_matrix = None
def activate_shader(self, name):
program = None
if self._program != name:
if name is None:
glUseProgram(0)
else:
program = self.programs[name]
glUseProgram(program.program)
self._program = name
elif self._program is not None:
program = self.programs[self._program]
return program

179
setup.py Normal file
View file

@ -0,0 +1,179 @@
from __future__ import print_function
import os
import sys
from setuptools import setup, Extension
from setuptools.command.build_ext import build_ext
from setuptools.extension import Library
has_pyx = os.path.exists(os.path.join(os.path.dirname(__file__), 'punyverse', '_glgeom.pyx'))
try:
from Cython.Build import cythonize
except ImportError:
if has_pyx:
print('You need to install cython first before installing punyverse.', file=sys.stderr)
print('Run: pip install cython', file=sys.stderr)
print('Or if you do not have pip: easy_install cython', file=sys.stderr)
sys.exit(1)
cythonize = lambda x: x
if has_pyx:
pyx_path = lambda x: x
else:
pyx_path = lambda x: x.replace('.pyx', '.c')
if os.name == 'nt':
gl_libs = ['opengl32']
elif sys.platform == 'darwin':
gl_libs = []
else:
gl_libs = ['GL']
if sys.platform == 'darwin':
extra_compile_args = extra_link_args = ['-framework', 'OpenGL']
else:
extra_compile_args = extra_link_args = []
with open(os.path.join(os.path.dirname(__file__), 'README.md')) as f:
long_description = f.read()
if os.name == 'nt':
class SimpleExecutable(Library, object):
executable_names = set()
def __init__(self, name, *args, **kwargs):
super(SimpleExecutable, self).__init__(name, *args, **kwargs)
self.executable_names.add(name)
if '.' in name:
self.executable_names.add(name.split('.')[-1])
def link_shared_object(
self, objects, output_libname, output_dir=None, libraries=None,
library_dirs=None, runtime_library_dirs=None, export_symbols=None,
debug=0, extra_preargs=None, extra_postargs=None, build_temp=None,
target_lang=None):
self.link(
self.EXECUTABLE, objects, output_libname,
output_dir, libraries, library_dirs, runtime_library_dirs,
export_symbols, debug, extra_preargs, extra_postargs,
build_temp, target_lang
)
def make_manifest_get_embed_info(old_func):
def manifest_get_embed_info(self, target_desc, ld_args):
temp_manifest, mfid = old_func(target_desc, ld_args)
if not os.path.exists(temp_manifest):
return None
return temp_manifest, mfid
return manifest_get_embed_info.__get__(old_func.__self__)
class build_ext_exe(build_ext, object):
def get_ext_filename(self, fullname):
ext = self.ext_map[fullname]
if isinstance(ext, SimpleExecutable):
return fullname.replace('.', os.sep) + '.exe'
return super(build_ext_exe, self).get_ext_filename(fullname)
def get_export_symbols(self, ext):
if isinstance(ext, SimpleExecutable):
return ext.export_symbols
return super(build_ext_exe, self).get_export_symbols(ext)
def build_extension(self, ext):
if isinstance(ext, SimpleExecutable):
old = self.shlib_compiler.link_shared_object
self.shlib_compiler.link_shared_object = link_shared_object.__get__(self.shlib_compiler)
patched = False
if hasattr(self.shlib_compiler, 'manifest_get_embed_info'):
self.shlib_compiler.manifest_get_embed_info = \
make_manifest_get_embed_info(self.shlib_compiler.manifest_get_embed_info)
patched = True
super(build_ext_exe, self).build_extension(ext)
self.shlib_compiler.link_shared_object = old
if patched:
del self.shlib_compiler.manifest_get_embed_info
else:
super(build_ext_exe, self).build_extension(ext)
extra_libs = [
SimpleExecutable('punyverse.launcher', sources=['punyverse/launcher.c'], libraries=['shell32']),
SimpleExecutable('punyverse.launcherw', sources=['punyverse/launcher.c'],
libraries=['shell32'], define_macros=[('GUI', 1)]),
]
build_ext = build_ext_exe
else:
extra_libs = []
setup(
name='punyverse',
version='1.2',
packages=['punyverse'],
package_data={
'punyverse': [
'world.json',
'shaders/*.glsl',
'assets/textures.txt',
'assets/textures/*.jpg',
'assets/textures/*.png',
'assets/textures/moons/*',
'assets/models/asteroids/*',
'assets/models/satellites/*.mtl',
'assets/models/satellites/*.obj',
'assets/models/satellites/*.jpg',
'assets/models/satellites/*.png',
'assets/models/satellites/cassini/*',
],
},
ext_modules=cythonize([
Extension('punyverse._glgeom', sources=[pyx_path('punyverse/_glgeom.pyx')], libraries=gl_libs,
extra_compile_args=extra_compile_args, extra_link_args=extra_link_args),
]) + extra_libs,
cmdclass={'build_ext': build_ext},
entry_points={
'console_scripts': [
'punyverse = punyverse.main:main',
'punyverse_make_launcher = punyverse.launcher:main',
'punyverse_small_images = punyverse.small_images:main',
],
'gui_scripts': [
'punyversew = punyverse.main:main'
]
},
install_requires=['pyglet<1.4', 'Pillow', 'six'],
author='quantum',
author_email='quantum2048@gmail.com',
url='https://github.com/quantum5/punyverse',
description='Python simulator of a puny universe.',
long_description=long_description,
long_description_content_type='text/markdown',
keywords='universe simulator',
classifiers=[
'Development Status :: 4 - Beta',
'Environment :: Win32 (MS Windows)',
'Environment :: X11 Applications',
'Intended Audience :: End Users/Desktop',
'License :: OSI Approved :: GNU General Public License v2 (GPLv2)',
'Operating System :: Microsoft :: Windows',
'Operating System :: POSIX :: Linux',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Topic :: Games/Entertainment :: Simulation',
'Topic :: Multimedia :: Graphics :: 3D Rendering',
'Topic :: Scientific/Engineering :: Visualization',
],
)

Some files were not shown because too many files have changed in this diff Show more