OpenGLContext 3.0.0a1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- OpenGLContext/__init__.py +151 -0
- OpenGLContext/arrays.py +2 -0
- OpenGLContext/atlas.py +300 -0
- OpenGLContext/audio/__init__.py +32 -0
- OpenGLContext/audio/scene.py +130 -0
- OpenGLContext/audio/settings.py +82 -0
- OpenGLContext/bin/__init__.py +0 -0
- OpenGLContext/bin/choosecontext.py +224 -0
- OpenGLContext/bin/choosefonts.py +209 -0
- OpenGLContext/bin/gltest.py +121 -0
- OpenGLContext/bin/gltf_demo.py +492 -0
- OpenGLContext/bin/gltf_regression.py +645 -0
- OpenGLContext/bin/gltf_view.py +30 -0
- OpenGLContext/bin/keyboardevents.py +93 -0
- OpenGLContext/bin/lorentz.py +109 -0
- OpenGLContext/bin/physics_cook.py +81 -0
- OpenGLContext/bin/profile_view.py +38 -0
- OpenGLContext/bin/terrain_view.py +581 -0
- OpenGLContext/bin/tiles_view.py +39 -0
- OpenGLContext/bin/ui_demo.py +228 -0
- OpenGLContext/bin/view.py +341 -0
- OpenGLContext/bin/vrml_view.py +42 -0
- OpenGLContext/capture.py +125 -0
- OpenGLContext/context.py +1253 -0
- OpenGLContext/contextconfig.py +177 -0
- OpenGLContext/contextdefinition.py +275 -0
- OpenGLContext/debug/__init__.py +6 -0
- OpenGLContext/debug/bufferimage.py +80 -0
- OpenGLContext/debug/leaks.py +13 -0
- OpenGLContext/debug/logcontext.py +9 -0
- OpenGLContext/debug/logs.py +15 -0
- OpenGLContext/debug/state.py +329 -0
- OpenGLContext/displaylist.py +69 -0
- OpenGLContext/doinchildmatrix.py +34 -0
- OpenGLContext/drawcube.py +58 -0
- OpenGLContext/events/__init__.py +10 -0
- OpenGLContext/events/default_config.py +29 -0
- OpenGLContext/events/event.py +65 -0
- OpenGLContext/events/eventhandlermixin.py +214 -0
- OpenGLContext/events/eventmanager.py +269 -0
- OpenGLContext/events/fxevents.py +90 -0
- OpenGLContext/events/glfwevents.py +424 -0
- OpenGLContext/events/glutevents.py +184 -0
- OpenGLContext/events/inputstate.py +129 -0
- OpenGLContext/events/internaltime.py +161 -0
- OpenGLContext/events/keyboardevents.py +153 -0
- OpenGLContext/events/mouseevents.py +473 -0
- OpenGLContext/events/pygameevents.py +162 -0
- OpenGLContext/events/systemtime.py +12 -0
- OpenGLContext/events/timeeventgeneratormanager.py +40 -0
- OpenGLContext/events/timeevents.py +143 -0
- OpenGLContext/events/timer.py +170 -0
- OpenGLContext/events/tkevents.py +172 -0
- OpenGLContext/events/wxevents.py +185 -0
- OpenGLContext/extensionmanager.py +158 -0
- OpenGLContext/framecounter.py +74 -0
- OpenGLContext/frustum.py +135 -0
- OpenGLContext/glfwcontext.py +395 -0
- OpenGLContext/glfwinteractivecontext.py +34 -0
- OpenGLContext/glfwvrmlcontext.py +11 -0
- OpenGLContext/glutcontext.py +224 -0
- OpenGLContext/glutinteractivecontext.py +24 -0
- OpenGLContext/gluttestingcontext.py +11 -0
- OpenGLContext/glutvrmlcontext.py +25 -0
- OpenGLContext/glutvrmltestingcontext.py +48 -0
- OpenGLContext/hud.py +404 -0
- OpenGLContext/interactivecontext.py +29 -0
- OpenGLContext/loaders/__init__.py +1 -0
- OpenGLContext/loaders/base.py +84 -0
- OpenGLContext/loaders/cc0.py +137 -0
- OpenGLContext/loaders/gltf/__init__.py +71 -0
- OpenGLContext/loaders/gltf/accessors.py +255 -0
- OpenGLContext/loaders/gltf/animation.py +611 -0
- OpenGLContext/loaders/gltf/draco.py +166 -0
- OpenGLContext/loaders/gltf/environment_sky.py +416 -0
- OpenGLContext/loaders/gltf/loader.py +80 -0
- OpenGLContext/loaders/gltf/materials.py +298 -0
- OpenGLContext/loaders/gltf/meshes.py +292 -0
- OpenGLContext/loaders/gltf/samples.py +162 -0
- OpenGLContext/loaders/gltf/scene.py +673 -0
- OpenGLContext/loaders/gltf/specular_glossiness.py +154 -0
- OpenGLContext/loaders/gltf/textures.py +155 -0
- OpenGLContext/loaders/gltf/transforms.py +261 -0
- OpenGLContext/loaders/gltf_demos.py +511 -0
- OpenGLContext/loaders/hdr.py +228 -0
- OpenGLContext/loaders/hdri.py +83 -0
- OpenGLContext/loaders/loader.py +255 -0
- OpenGLContext/loaders/obj.py +299 -0
- OpenGLContext/loaders/resolver.py +536 -0
- OpenGLContext/loaders/tiles3d/__init__.py +9 -0
- OpenGLContext/loaders/tiles3d/boundingvolume.py +120 -0
- OpenGLContext/loaders/tiles3d/dem.py +71 -0
- OpenGLContext/loaders/tiles3d/fetch.py +102 -0
- OpenGLContext/loaders/tiles3d/foliage.py +786 -0
- OpenGLContext/loaders/tiles3d/frustum.py +70 -0
- OpenGLContext/loaders/tiles3d/geomorph.py +57 -0
- OpenGLContext/loaders/tiles3d/gltf_uploader.py +246 -0
- OpenGLContext/loaders/tiles3d/loadmanager.py +121 -0
- OpenGLContext/loaders/tiles3d/physics_colliders.py +78 -0
- OpenGLContext/loaders/tiles3d/procedural.py +355 -0
- OpenGLContext/loaders/tiles3d/residency.py +102 -0
- OpenGLContext/loaders/tiles3d/runtime.py +168 -0
- OpenGLContext/loaders/tiles3d/sample.py +212 -0
- OpenGLContext/loaders/tiles3d/scatter.py +77 -0
- OpenGLContext/loaders/tiles3d/screenspaceerror.py +31 -0
- OpenGLContext/loaders/tiles3d/tileset.py +390 -0
- OpenGLContext/loaders/tiles3d/traversal.py +108 -0
- OpenGLContext/loaders/tiles3d/vegetation.py +361 -0
- OpenGLContext/loaders/vrml97.py +133 -0
- OpenGLContext/looptrace.py +307 -0
- OpenGLContext/move/__init__.py +0 -0
- OpenGLContext/move/bindingstore.py +232 -0
- OpenGLContext/move/direct.py +156 -0
- OpenGLContext/move/dragwatcher.py +42 -0
- OpenGLContext/move/examinemanager.py +100 -0
- OpenGLContext/move/followcam.py +121 -0
- OpenGLContext/move/modes.py +522 -0
- OpenGLContext/move/movementmanager.py +74 -0
- OpenGLContext/move/navigation.py +137 -0
- OpenGLContext/move/physicsplatform.py +203 -0
- OpenGLContext/move/physicswalk.py +469 -0
- OpenGLContext/move/smooth.py +68 -0
- OpenGLContext/move/terrainwalk.py +451 -0
- OpenGLContext/move/trackball.py +92 -0
- OpenGLContext/move/viewplatform.py +283 -0
- OpenGLContext/move/viewplatformmixin.py +335 -0
- OpenGLContext/nav/__init__.py +13 -0
- OpenGLContext/nav/navmesh.py +476 -0
- OpenGLContext/passes/__init__.py +0 -0
- OpenGLContext/passes/_flat.py +1317 -0
- OpenGLContext/passes/asyncpick.py +216 -0
- OpenGLContext/passes/bloom.py +257 -0
- OpenGLContext/passes/flatcompat.py +246 -0
- OpenGLContext/passes/flatcore.py +198 -0
- OpenGLContext/passes/flateffects.py +372 -0
- OpenGLContext/passes/ibl.py +711 -0
- OpenGLContext/passes/instancing.py +775 -0
- OpenGLContext/passes/pbrpass.py +829 -0
- OpenGLContext/passes/renderpass.py +79 -0
- OpenGLContext/passes/renderstats.py +55 -0
- OpenGLContext/passes/rendervisitor.py +60 -0
- OpenGLContext/passes/selection.py +450 -0
- OpenGLContext/passes/selectionbuffers.py +442 -0
- OpenGLContext/passes/shaderpass.py +1018 -0
- OpenGLContext/passes/shaderpass_shadow.py +197 -0
- OpenGLContext/passes/shadersource.py +121 -0
- OpenGLContext/passes/shadowcaps.py +182 -0
- OpenGLContext/passes/shadowmap.py +330 -0
- OpenGLContext/passes/shadowmath.py +290 -0
- OpenGLContext/passes/shadowmixin.py +906 -0
- OpenGLContext/passes/shadowpool.py +186 -0
- OpenGLContext/passes/transmission.py +124 -0
- OpenGLContext/physics/__init__.py +16 -0
- OpenGLContext/physics/debugdraw.py +370 -0
- OpenGLContext/physics/demo.py +157 -0
- OpenGLContext/physics/gltf_world.py +185 -0
- OpenGLContext/physics/manager.py +84 -0
- OpenGLContext/physics/threaded.py +93 -0
- OpenGLContext/plugins.py +61 -0
- OpenGLContext/pygamecontext.py +178 -0
- OpenGLContext/pygameinteractivecontext.py +36 -0
- OpenGLContext/pygametestingcontext.py +10 -0
- OpenGLContext/pygamevrmlcontext.py +13 -0
- OpenGLContext/quaternion.py +190 -0
- OpenGLContext/renderoptions.py +280 -0
- OpenGLContext/resources/__init__.py +36 -0
- OpenGLContext/resources/available_contexts.txt +4 -0
- OpenGLContext/resources/available_contexts_txt.py +9 -0
- OpenGLContext/resources/context_icon_png.py +46 -0
- OpenGLContext/resources/context_icon_small_png.py +21 -0
- OpenGLContext/resources/disk_icon_hi_png.py +14 -0
- OpenGLContext/resources/disk_icon_png.py +15 -0
- OpenGLContext/resources/environment/pimbackground_BK.jpg +0 -0
- OpenGLContext/resources/environment/pimbackground_DN.jpg +0 -0
- OpenGLContext/resources/environment/pimbackground_FR.jpg +0 -0
- OpenGLContext/resources/environment/pimbackground_LF.jpg +0 -0
- OpenGLContext/resources/environment/pimbackground_RT.jpg +0 -0
- OpenGLContext/resources/environment/pimbackground_UP.jpg +0 -0
- OpenGLContext/resources/environment/studio_BK.jpg +0 -0
- OpenGLContext/resources/environment/studio_DN.jpg +0 -0
- OpenGLContext/resources/environment/studio_FR.jpg +0 -0
- OpenGLContext/resources/environment/studio_LF.jpg +0 -0
- OpenGLContext/resources/environment/studio_RT.jpg +0 -0
- OpenGLContext/resources/environment/studio_UP.jpg +0 -0
- OpenGLContext/resources/environment/studiobright_BK.jpg +0 -0
- OpenGLContext/resources/environment/studiobright_DN.jpg +0 -0
- OpenGLContext/resources/environment/studiobright_FR.jpg +0 -0
- OpenGLContext/resources/environment/studiobright_LF.jpg +0 -0
- OpenGLContext/resources/environment/studiobright_RT.jpg +0 -0
- OpenGLContext/resources/environment/studiobright_UP.jpg +0 -0
- OpenGLContext/resources/green_arrow_right_png.py +47 -0
- OpenGLContext/resources/legacy_lighting.vert.txt +37 -0
- OpenGLContext/resources/legacy_lighting_vert_txt.py +18 -0
- OpenGLContext/resources/lights.vert.txt +107 -0
- OpenGLContext/resources/lights_vert_txt.py +23 -0
- OpenGLContext/resources/phongprecalc_vert.py +30 -0
- OpenGLContext/resources/phongweights_frag.py +47 -0
- OpenGLContext/resources/pygame_icon_png.py +47 -0
- OpenGLContext/resources/red_arrow_right_png.py +50 -0
- OpenGLContext/resources/simpleshader.frag.txt +3 -0
- OpenGLContext/resources/simpleshader.vert.txt +3 -0
- OpenGLContext/resources/simpleshader_frag_txt.py +9 -0
- OpenGLContext/resources/simpleshader_vert_txt.py +10 -0
- OpenGLContext/scenegraph/__init__.py +19 -0
- OpenGLContext/scenegraph/appearance.py +107 -0
- OpenGLContext/scenegraph/arraygeometry.py +238 -0
- OpenGLContext/scenegraph/audio.py +632 -0
- OpenGLContext/scenegraph/background.py +108 -0
- OpenGLContext/scenegraph/basenodes.py +50 -0
- OpenGLContext/scenegraph/billboard.py +14 -0
- OpenGLContext/scenegraph/boundingvolume.py +494 -0
- OpenGLContext/scenegraph/box.py +180 -0
- OpenGLContext/scenegraph/collision.py +14 -0
- OpenGLContext/scenegraph/coordinate.py +20 -0
- OpenGLContext/scenegraph/coordinatebounded.py +18 -0
- OpenGLContext/scenegraph/cubebackground.py +207 -0
- OpenGLContext/scenegraph/extrusions.py +275 -0
- OpenGLContext/scenegraph/fog.py +123 -0
- OpenGLContext/scenegraph/gear.py +323 -0
- OpenGLContext/scenegraph/group.py +20 -0
- OpenGLContext/scenegraph/grouping.py +140 -0
- OpenGLContext/scenegraph/hdrbackground.py +384 -0
- OpenGLContext/scenegraph/ifscompiler.py +633 -0
- OpenGLContext/scenegraph/imagetexture.py +365 -0
- OpenGLContext/scenegraph/indexedfaceset.py +238 -0
- OpenGLContext/scenegraph/indexedlineset.py +418 -0
- OpenGLContext/scenegraph/indexedpolygons.py +422 -0
- OpenGLContext/scenegraph/inline.py +79 -0
- OpenGLContext/scenegraph/instancedgl.py +187 -0
- OpenGLContext/scenegraph/interpolators.py +122 -0
- OpenGLContext/scenegraph/light.py +213 -0
- OpenGLContext/scenegraph/lod.py +22 -0
- OpenGLContext/scenegraph/material.py +96 -0
- OpenGLContext/scenegraph/material_fields.py +50 -0
- OpenGLContext/scenegraph/mouseover.py +43 -0
- OpenGLContext/scenegraph/nodepath.py +52 -0
- OpenGLContext/scenegraph/nurbs.py +637 -0
- OpenGLContext/scenegraph/nurbssampling.py +101 -0
- OpenGLContext/scenegraph/nurbstess.py +316 -0
- OpenGLContext/scenegraph/nurbstrim.py +54 -0
- OpenGLContext/scenegraph/particles.py +786 -0
- OpenGLContext/scenegraph/pbrmaterial.py +229 -0
- OpenGLContext/scenegraph/pbrmesh.py +558 -0
- OpenGLContext/scenegraph/physicsbody.py +72 -0
- OpenGLContext/scenegraph/pointset.py +257 -0
- OpenGLContext/scenegraph/polygon.py +166 -0
- OpenGLContext/scenegraph/polygonsort.py +119 -0
- OpenGLContext/scenegraph/polygontessellator.py +213 -0
- OpenGLContext/scenegraph/quadrics.py +494 -0
- OpenGLContext/scenegraph/scenegraph.py +21 -0
- OpenGLContext/scenegraph/shadergeometry.py +403 -0
- OpenGLContext/scenegraph/shaders.py +812 -0
- OpenGLContext/scenegraph/shape.py +243 -0
- OpenGLContext/scenegraph/simplebackground.py +34 -0
- OpenGLContext/scenegraph/spherebackground.py +462 -0
- OpenGLContext/scenegraph/switch.py +75 -0
- OpenGLContext/scenegraph/teapot.py +439 -0
- OpenGLContext/scenegraph/teapot_nurbs.py +291 -0
- OpenGLContext/scenegraph/teapot_nurbs_data.py +384 -0
- OpenGLContext/scenegraph/terrain/__init__.py +12 -0
- OpenGLContext/scenegraph/terrain/heightfield.py +172 -0
- OpenGLContext/scenegraph/terrain/splat.py +224 -0
- OpenGLContext/scenegraph/tessellationlod.py +97 -0
- OpenGLContext/scenegraph/text/__init__.py +1 -0
- OpenGLContext/scenegraph/text/_toolsfont.py +200 -0
- OpenGLContext/scenegraph/text/font.py +452 -0
- OpenGLContext/scenegraph/text/fontprovider.py +193 -0
- OpenGLContext/scenegraph/text/fonts/__init__.py +75 -0
- OpenGLContext/scenegraph/text/fonts/font_atlas_10.py +133 -0
- OpenGLContext/scenegraph/text/fonts/font_atlas_12.py +158 -0
- OpenGLContext/scenegraph/text/fonts/font_atlas_14.py +176 -0
- OpenGLContext/scenegraph/text/fonts/font_atlas_16.py +204 -0
- OpenGLContext/scenegraph/text/fonts/font_atlas_18.py +222 -0
- OpenGLContext/scenegraph/text/fonts/font_atlas_20.py +244 -0
- OpenGLContext/scenegraph/text/fonts/font_atlas_24.py +294 -0
- OpenGLContext/scenegraph/text/fonts/font_atlas_28.py +339 -0
- OpenGLContext/scenegraph/text/fonts/font_atlas_32.py +390 -0
- OpenGLContext/scenegraph/text/fontstyle3d.py +62 -0
- OpenGLContext/scenegraph/text/glutfont.py +186 -0
- OpenGLContext/scenegraph/text/pygamefont.py +213 -0
- OpenGLContext/scenegraph/text/shaderfont.py +340 -0
- OpenGLContext/scenegraph/text/shadertext.py +433 -0
- OpenGLContext/scenegraph/text/text.py +75 -0
- OpenGLContext/scenegraph/text/toolsfont.py +819 -0
- OpenGLContext/scenegraph/text/ttfregistry.py +135 -0
- OpenGLContext/scenegraph/text/wglfont.py +228 -0
- OpenGLContext/scenegraph/text/wglfontprovider.py +37 -0
- OpenGLContext/scenegraph/text/wxfont.py +314 -0
- OpenGLContext/scenegraph/texturetransform.py +66 -0
- OpenGLContext/scenegraph/tilesterrain.py +95 -0
- OpenGLContext/scenegraph/timesensor.py +51 -0
- OpenGLContext/scenegraph/transform.py +180 -0
- OpenGLContext/scenegraph/vegetation/__init__.py +20 -0
- OpenGLContext/scenegraph/vegetation/base.py +96 -0
- OpenGLContext/scenegraph/vegetation/billboards.py +145 -0
- OpenGLContext/scenegraph/vegetation/clumps.py +260 -0
- OpenGLContext/scenegraph/vegetation/grid.py +112 -0
- OpenGLContext/scenegraph/vegetation/nearmesh.py +185 -0
- OpenGLContext/scenegraph/vertex.py +54 -0
- OpenGLContext/scenegraph/viewpoint.py +42 -0
- OpenGLContext/scenegraph/winding.py +49 -0
- OpenGLContext/shaders/_brdf_inc.glsl +124 -0
- OpenGLContext/shaders/_common_inc.glsl +24 -0
- OpenGLContext/shaders/_cubemap_inc.glsl +26 -0
- OpenGLContext/shaders/_lights_inc.glsl +32 -0
- OpenGLContext/shaders/_objectid_inc.glsl +14 -0
- OpenGLContext/shaders/_shadow_inc.glsl +254 -0
- OpenGLContext/shaders/_vrml97_lighting_inc.glsl +78 -0
- OpenGLContext/shaders/hdr_background.frag +32 -0
- OpenGLContext/shaders/hdr_background.vert +15 -0
- OpenGLContext/shaders/ibl_brdf.frag +78 -0
- OpenGLContext/shaders/ibl_env.frag +53 -0
- OpenGLContext/shaders/ibl_equirect.frag +19 -0
- OpenGLContext/shaders/ibl_fullscreen.vert +11 -0
- OpenGLContext/shaders/ibl_irradiance.frag +40 -0
- OpenGLContext/shaders/ibl_prefilter.frag +56 -0
- OpenGLContext/shaders/particle.frag +42 -0
- OpenGLContext/shaders/particle.vert +52 -0
- OpenGLContext/shaders/pbr.frag +906 -0
- OpenGLContext/shaders/pbr.vert +70 -0
- OpenGLContext/shaders/shadow_depth.frag +4 -0
- OpenGLContext/shaders/shadow_depth.vert +18 -0
- OpenGLContext/shaders/terrain_splat.frag +80 -0
- OpenGLContext/shaders/terrain_splat.vert +16 -0
- OpenGLContext/shaders/veg_billboard.frag +35 -0
- OpenGLContext/shaders/veg_billboard.vert +17 -0
- OpenGLContext/shaders/veg_clump.frag +27 -0
- OpenGLContext/shaders/veg_mesh.frag +26 -0
- OpenGLContext/shaders/veg_mesh.vert +17 -0
- OpenGLContext/shaders/vrml97_background.frag +17 -0
- OpenGLContext/shaders/vrml97_background.vert +24 -0
- OpenGLContext/shaders/vrml97_lighting.frag +111 -0
- OpenGLContext/shaders/vrml97_lighting.vert +50 -0
- OpenGLContext/shaders/vrml97_line.frag +23 -0
- OpenGLContext/shaders/vrml97_line.vert +24 -0
- OpenGLContext/shaders/vrml97_point.frag +36 -0
- OpenGLContext/shaders/vrml97_point.vert +21 -0
- OpenGLContext/shaders/vrml97_unlit.frag +59 -0
- OpenGLContext/shaders/vrml97_unlit.vert +18 -0
- OpenGLContext/shaders/vrml97_vertex_color.frag +85 -0
- OpenGLContext/shaders/vrml97_vertex_color.vert +34 -0
- OpenGLContext/stalltrace.py +637 -0
- OpenGLContext/testing/__init__.py +67 -0
- OpenGLContext/testing/display.py +30 -0
- OpenGLContext/testing/event_injector.py +564 -0
- OpenGLContext/testing/framebuffer_comparison.py +842 -0
- OpenGLContext/testing/gl_env.py +39 -0
- OpenGLContext/testing/paths.py +23 -0
- OpenGLContext/testing/process_exit.py +30 -0
- OpenGLContext/testing/report_generator.py +594 -0
- OpenGLContext/testing/subprocess_runner.py +411 -0
- OpenGLContext/testingcontext.py +36 -0
- OpenGLContext/tests/test_atlas.py +62 -0
- OpenGLContext/tests/test_configs.py +27 -0
- OpenGLContext/tests/test_polygonsort.py +45 -0
- OpenGLContext/tests/test_utilities.py +84 -0
- OpenGLContext/tests/test_viewplatform.py +39 -0
- OpenGLContext/texture.py +449 -0
- OpenGLContext/texturecache.py +37 -0
- OpenGLContext/triangleutilities.py +89 -0
- OpenGLContext/ui/__init__.py +39 -0
- OpenGLContext/ui/bindings.py +243 -0
- OpenGLContext/ui/console.py +339 -0
- OpenGLContext/ui/debugoverlay.py +519 -0
- OpenGLContext/ui/dialogs.py +124 -0
- OpenGLContext/ui/draw.py +617 -0
- OpenGLContext/ui/gallery.py +425 -0
- OpenGLContext/ui/generate.py +195 -0
- OpenGLContext/ui/geometry.py +88 -0
- OpenGLContext/ui/hudwidgets.py +1053 -0
- OpenGLContext/ui/layout.py +263 -0
- OpenGLContext/ui/metrics.py +218 -0
- OpenGLContext/ui/overlay.py +412 -0
- OpenGLContext/ui/panel.py +459 -0
- OpenGLContext/ui/pictures.py +261 -0
- OpenGLContext/ui/screen.py +177 -0
- OpenGLContext/ui/scroll.py +297 -0
- OpenGLContext/ui/session.py +329 -0
- OpenGLContext/ui/settings.py +273 -0
- OpenGLContext/ui/skin.py +330 -0
- OpenGLContext/ui/widgets.py +1199 -0
- OpenGLContext/userpaths.py +48 -0
- OpenGLContext/utilities.py +94 -0
- OpenGLContext/vectorutilities.py +101 -0
- OpenGLContext/viewer/__init__.py +60 -0
- OpenGLContext/viewer/adapters/__init__.py +150 -0
- OpenGLContext/viewer/adapters/base.py +157 -0
- OpenGLContext/viewer/adapters/gltf.py +31 -0
- OpenGLContext/viewer/adapters/obj.py +20 -0
- OpenGLContext/viewer/adapters/scenegraph.py +71 -0
- OpenGLContext/viewer/adapters/tiles.py +296 -0
- OpenGLContext/viewer/adapters/vrml.py +25 -0
- OpenGLContext/viewer/asyncscene.py +117 -0
- OpenGLContext/viewer/caption.py +126 -0
- OpenGLContext/viewer/capture.py +77 -0
- OpenGLContext/viewer/debug.py +78 -0
- OpenGLContext/viewer/environment.py +131 -0
- OpenGLContext/viewer/framing.py +111 -0
- OpenGLContext/viewer/library.py +235 -0
- OpenGLContext/viewer/menu.py +218 -0
- OpenGLContext/viewer/options.py +150 -0
- OpenGLContext/viewer/overlay.py +63 -0
- OpenGLContext/viewer/sceneviewer.py +1056 -0
- OpenGLContext/viewer/screens.py +172 -0
- OpenGLContext/viewer/source.py +56 -0
- OpenGLContext/visitor.py +68 -0
- OpenGLContext/vrmlcontext.py +72 -0
- OpenGLContext/wxcontext.py +424 -0
- OpenGLContext/wxinteractivecontext.py +25 -0
- OpenGLContext/wxtestingcontext.py +9 -0
- OpenGLContext/wxvrmlcontext.py +13 -0
- openglcontext-3.0.0a1.dist-info/METADATA +650 -0
- openglcontext-3.0.0a1.dist-info/RECORD +417 -0
- openglcontext-3.0.0a1.dist-info/WHEEL +5 -0
- openglcontext-3.0.0a1.dist-info/entry_points.txt +11 -0
- openglcontext-3.0.0a1.dist-info/licenses/license.txt +89 -0
- openglcontext-3.0.0a1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
'''Rendering contexts for various GUI libraries, scene graph
|
|
2
|
+
geometry objects, and PyOpenGL testing code
|
|
3
|
+
|
|
4
|
+
The OpenGLContext project provides a simplified environment
|
|
5
|
+
for writing OpenGL code with PyOpenGL. This simplified
|
|
6
|
+
environment abstracts the GUI library interfaces for a
|
|
7
|
+
large number of GUI libraries to allow the easy creation of
|
|
8
|
+
cross platform and cross-GUI-OpenGL programs.
|
|
9
|
+
|
|
10
|
+
The project also provides simplified geometry display
|
|
11
|
+
primitives to allow new developers to concentrate on the
|
|
12
|
+
particular task in which they are interested rather than
|
|
13
|
+
forcing them to re-implement basic geometry display
|
|
14
|
+
mechanisms.
|
|
15
|
+
|
|
16
|
+
Taking advantage of this simplified environment, we have
|
|
17
|
+
provided a number of testing modules. These testing
|
|
18
|
+
modules should operate under any of the fully functional
|
|
19
|
+
GUI contexts (note that there are unfinished contexts).
|
|
20
|
+
'''
|
|
21
|
+
|
|
22
|
+
__version__ = "3.0.0a1"
|
|
23
|
+
__author__ = "Michael Colin Fletcher"
|
|
24
|
+
__license__ = "BSD-Style, see license.txt for details and exceptions"
|
|
25
|
+
|
|
26
|
+
from OpenGLContext.plugins import Context,InteractiveContext,VRMLContext,Loader,Node,Adapter
|
|
27
|
+
|
|
28
|
+
Context( 'pygame', 'OpenGLContext.pygamecontext.PyGameContext' )
|
|
29
|
+
Context( 'wx', 'OpenGLContext.wxcontext.wxContext' )
|
|
30
|
+
Context( 'glut', 'OpenGLContext.glutcontext.GLUTContext' )
|
|
31
|
+
Context( 'glfw', 'OpenGLContext.glfwcontext.GLFWContext' )
|
|
32
|
+
InteractiveContext( 'pygame', 'OpenGLContext.pygameinteractivecontext.PygameInteractiveContext' )
|
|
33
|
+
InteractiveContext( 'wx', 'OpenGLContext.wxinteractivecontext.wxInteractiveContext' )
|
|
34
|
+
InteractiveContext( 'glut', 'OpenGLContext.glutinteractivecontext.GLUTInteractiveContext' )
|
|
35
|
+
InteractiveContext( 'glfw', 'OpenGLContext.glfwinteractivecontext.GLFWInteractiveContext' )
|
|
36
|
+
VRMLContext( 'pygame', 'OpenGLContext.pygamevrmlcontext.VRMLContext' )
|
|
37
|
+
VRMLContext( 'wx', 'OpenGLContext.wxvrmlcontext.VRMLContext' )
|
|
38
|
+
VRMLContext( 'glut', 'OpenGLContext.glutvrmlcontext.VRMLContext' )
|
|
39
|
+
VRMLContext( 'glfw', 'OpenGLContext.glfwvrmlcontext.VRMLContext' )
|
|
40
|
+
|
|
41
|
+
try:
|
|
42
|
+
import OpenGLContext_qt
|
|
43
|
+
except ImportError as err:
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
Loader( 'vrml97', 'OpenGLContext.loaders.vrml97.defaultHandler', ['.wrl','.wrz','.vrml','model/vrml','x-world/x-vrml','.wrl.gz'] )
|
|
47
|
+
Loader( 'obj', 'OpenGLContext.loaders.obj.defaultHandler', ['.obj'] )
|
|
48
|
+
|
|
49
|
+
# What `oglc-view` can open, keyed by file suffix and content type. One viewer
|
|
50
|
+
# serves every format; the adapter is chosen from the source itself.
|
|
51
|
+
Adapter( 'gltf', 'OpenGLContext.viewer.adapters.gltf.GLTFAdapter', ['.gltf','.glb','model/gltf+json','model/gltf-binary'] )
|
|
52
|
+
Adapter( 'vrml97', 'OpenGLContext.viewer.adapters.vrml.VRMLAdapter', ['.wrl','.wrz','.vrml','.wrl.gz','model/vrml','x-world/x-vrml'] )
|
|
53
|
+
Adapter( 'obj', 'OpenGLContext.viewer.adapters.obj.OBJAdapter', ['.obj','.obj.gz','model/obj'] )
|
|
54
|
+
# A tileset is any .json, so the registry only claims the conventional name; a
|
|
55
|
+
# document under another name is recognised by its content (adapters._sniff).
|
|
56
|
+
Adapter( 'tiles3d', 'OpenGLContext.viewer.adapters.tiles.TilesAdapter', ['tileset.json'] )
|
|
57
|
+
|
|
58
|
+
Node( 'Anchor', 'vrml.vrml97.basenodes.Anchor' )
|
|
59
|
+
Node( 'Appearance', 'OpenGLContext.scenegraph.appearance.Appearance' )
|
|
60
|
+
Node( 'AudioEmitter', 'OpenGLContext.scenegraph.audio.AudioEmitter' )
|
|
61
|
+
Node( 'AudioSource', 'OpenGLContext.scenegraph.audio.AudioSource' )
|
|
62
|
+
Node( 'AudioClip', 'vrml.vrml97.basenodes.AudioClip' )
|
|
63
|
+
Node( 'Background', 'OpenGLContext.scenegraph.background.Background' )
|
|
64
|
+
Node( 'Billboard', 'OpenGLContext.scenegraph.billboard.Billboard' )
|
|
65
|
+
Node( 'Box', 'OpenGLContext.scenegraph.box.Box' )
|
|
66
|
+
Node( 'Collision', 'OpenGLContext.scenegraph.collision.Collision' )
|
|
67
|
+
Node( 'Color', 'vrml.vrml97.basenodes.Color' )
|
|
68
|
+
Node( 'ColorInterpolator', 'OpenGLContext.scenegraph.interpolators.ColorInterpolator' )
|
|
69
|
+
Node( 'Cone', 'OpenGLContext.scenegraph.quadrics.Cone' )
|
|
70
|
+
Node( 'Coordinate', 'OpenGLContext.scenegraph.coordinate.Coordinate' )
|
|
71
|
+
Node( 'CoordinateInterpolator', 'OpenGLContext.scenegraph.interpolators.CoordinateInterpolator' )
|
|
72
|
+
Node( 'Cylinder', 'OpenGLContext.scenegraph.quadrics.Cylinder' )
|
|
73
|
+
Node( 'CylinderSensor', 'vrml.vrml97.basenodes.CylinderSensor' )
|
|
74
|
+
Node( 'DirectionalLight', 'OpenGLContext.scenegraph.light.DirectionalLight' )
|
|
75
|
+
Node( 'ElevationGrid', 'vrml.vrml97.basenodes.ElevationGrid' )
|
|
76
|
+
Node( 'Extrusion', 'vrml.vrml97.basenodes.Extrusion' )
|
|
77
|
+
Node( 'Fog', 'OpenGLContext.scenegraph.fog.Fog' )
|
|
78
|
+
Node( 'FontStyle', 'OpenGLContext.scenegraph.text.fontstyle3d.FontStyle' )
|
|
79
|
+
Node( 'Gear', 'OpenGLContext.scenegraph.gear.Gear' )
|
|
80
|
+
Node( 'Group', 'OpenGLContext.scenegraph.group.Group' )
|
|
81
|
+
Node( 'ImageTexture', 'OpenGLContext.scenegraph.imagetexture.ImageTexture' )
|
|
82
|
+
Node( 'IndexedFaceSet', 'OpenGLContext.scenegraph.indexedfaceset.IndexedFaceSet' )
|
|
83
|
+
Node( 'IndexedLineSet', 'OpenGLContext.scenegraph.indexedlineset.IndexedLineSet' )
|
|
84
|
+
Node( 'Inline', 'OpenGLContext.scenegraph.inline.Inline' )
|
|
85
|
+
Node( 'LOD', 'OpenGLContext.scenegraph.lod.LOD' )
|
|
86
|
+
Node( 'Material', 'OpenGLContext.scenegraph.material.Material' )
|
|
87
|
+
Node( 'MouseOver', 'OpenGLContext.scenegraph.mouseover.MouseOver' )
|
|
88
|
+
Node( 'MovieTexture', 'vrml.vrml97.basenodes.MovieTexture' )
|
|
89
|
+
Node( 'NavigationInfo', 'vrml.vrml97.basenodes.NavigationInfo' )
|
|
90
|
+
Node( 'Normal', 'vrml.vrml97.basenodes.Normal' )
|
|
91
|
+
Node( 'NormalInterpolator', 'vrml.vrml97.basenodes.NormalInterpolator' )
|
|
92
|
+
Node( 'OrientationInterpolator', 'OpenGLContext.scenegraph.interpolators.OrientationInterpolator' )
|
|
93
|
+
Node( 'PixelTexture', 'OpenGLContext.scenegraph.imagetexture.PixelTexture' )
|
|
94
|
+
Node( 'PlaneSensor', 'vrml.vrml97.basenodes.PlaneSensor' )
|
|
95
|
+
Node( 'PointLight', 'OpenGLContext.scenegraph.light.PointLight' )
|
|
96
|
+
Node( 'ParticleEmitter', 'OpenGLContext.scenegraph.particles.ParticleEmitter' )
|
|
97
|
+
Node( 'PointSet', 'OpenGLContext.scenegraph.pointset.PointSet' )
|
|
98
|
+
Node( 'PositionInterpolator', 'OpenGLContext.scenegraph.interpolators.PositionInterpolator' )
|
|
99
|
+
Node( 'ProximitySensor', 'vrml.vrml97.basenodes.ProximitySensor' )
|
|
100
|
+
Node( 'ScalarInterpolator', 'OpenGLContext.scenegraph.interpolators.ScalarInterpolator' )
|
|
101
|
+
Node( 'Shape', 'OpenGLContext.scenegraph.shape.Shape' )
|
|
102
|
+
Node( 'Sound', 'OpenGLContext.scenegraph.audio.Sound' )
|
|
103
|
+
Node( 'Sphere', 'OpenGLContext.scenegraph.quadrics.Sphere' )
|
|
104
|
+
Node( 'SphereSensor', 'vrml.vrml97.basenodes.SphereSensor' )
|
|
105
|
+
Node( 'SpotLight', 'OpenGLContext.scenegraph.light.SpotLight' )
|
|
106
|
+
Node( 'Switch', 'OpenGLContext.scenegraph.switch.Switch' )
|
|
107
|
+
Node( 'Teapot', 'OpenGLContext.scenegraph.teapot.Teapot' )
|
|
108
|
+
Node( 'Text', 'OpenGLContext.scenegraph.text.text.Text' )
|
|
109
|
+
Node( 'TextureCoordinate', 'vrml.vrml97.basenodes.TextureCoordinate' )
|
|
110
|
+
Node( 'TextureTransform', 'OpenGLContext.scenegraph.texturetransform.TextureTransform' )
|
|
111
|
+
Node( 'TimeSensor', 'OpenGLContext.scenegraph.timesensor.TimeSensor' )
|
|
112
|
+
Node( 'TouchSensor', 'vrml.vrml97.basenodes.TouchSensor' )
|
|
113
|
+
Node( 'Transform', 'OpenGLContext.scenegraph.transform.Transform' )
|
|
114
|
+
Node( 'Viewpoint', 'OpenGLContext.scenegraph.viewpoint.Viewpoint' )
|
|
115
|
+
Node( 'VisibilitySensor', 'vrml.vrml97.basenodes.VisibilitySensor' )
|
|
116
|
+
Node( 'WorldInfo', 'vrml.vrml97.basenodes.WorldInfo' )
|
|
117
|
+
Node( 'sceneGraph', 'OpenGLContext.scenegraph.scenegraph.SceneGraph' )
|
|
118
|
+
Node( 'IndexedPolygons', 'OpenGLContext.scenegraph.indexedpolygons.IndexedPolygons' )
|
|
119
|
+
Node( 'FontStyle3D', 'OpenGLContext.scenegraph.text.fontstyle3d.FontStyle3D' )
|
|
120
|
+
Node( 'SimpleBackground', 'OpenGLContext.scenegraph.simplebackground.SimpleBackground' )
|
|
121
|
+
Node( 'CubeBackground', 'OpenGLContext.scenegraph.cubebackground.CubeBackground' )
|
|
122
|
+
Node( 'SphereBackground', 'OpenGLContext.scenegraph.spherebackground.SphereBackground' )
|
|
123
|
+
Node( 'MMImageTexture', 'OpenGLContext.scenegraph.imagetexture.MMImageTexture' )
|
|
124
|
+
Node( 'Contour2D', 'OpenGLContext.scenegraph.nurbs.Contour2D' )
|
|
125
|
+
Node( 'NurbsCurve', 'OpenGLContext.scenegraph.nurbs.NurbsCurve' )
|
|
126
|
+
Node( 'NurbsCurve2D', 'OpenGLContext.scenegraph.nurbs.NurbsCurve2D' )
|
|
127
|
+
Node( 'NurbsDomainDistanceSample', 'OpenGLContext.scenegraph.nurbs.NurbsDomainDistanceSample' )
|
|
128
|
+
Node( 'NurbsSurface', 'OpenGLContext.scenegraph.nurbs.NurbsSurface' )
|
|
129
|
+
Node( 'NurbsToleranceSample', 'OpenGLContext.scenegraph.nurbs.NurbsToleranceSample' )
|
|
130
|
+
Node( 'Polyline2D', 'OpenGLContext.scenegraph.nurbs.Polyline2D' )
|
|
131
|
+
Node( 'TrimmedSurface', 'OpenGLContext.scenegraph.nurbs.TrimmedSurface' )
|
|
132
|
+
|
|
133
|
+
for suffix in ('1f','2f','3f','4f','m2','m3','m4','m2x3','m3x2','m2x4','m4x2','m3x4','m4x3'):
|
|
134
|
+
Node( 'FloatUniform'+suffix,'OpenGLContext.scenegraph.shaders.FloatUniform'+suffix )
|
|
135
|
+
for suffix in ('1i','2i','3i','4i'):
|
|
136
|
+
Node( 'IntUniform'+suffix,'OpenGLContext.scenegraph.shaders.IntUniform'+suffix )
|
|
137
|
+
Node( 'TextureUniform','OpenGLContext.scenegraph.shaders.TextureUniform' )
|
|
138
|
+
Node( 'TextureBufferUniform','OpenGLContext.scenegraph.shaders.TextureBufferUniform' )
|
|
139
|
+
Node( 'GLSLShader','OpenGLContext.scenegraph.shaders.GLSLShader' )
|
|
140
|
+
Node( 'GLSLObject','OpenGLContext.scenegraph.shaders.GLSLObject' )
|
|
141
|
+
Node( 'GLSLImport','OpenGLContext.scenegraph.shaders.GLSLImport' )
|
|
142
|
+
|
|
143
|
+
Node( 'ShaderAttribute','OpenGLContext.scenegraph.shaders.ShaderAttribute' )
|
|
144
|
+
Node( 'ShaderBuffer','OpenGLContext.scenegraph.shaders.ShaderBuffer' )
|
|
145
|
+
Node( 'ShaderIndexBuffer','OpenGLContext.scenegraph.shaders.ShaderIndexBuffer' )
|
|
146
|
+
Node( 'ShaderSlice','OpenGLContext.scenegraph.shaders.ShaderSlice' )
|
|
147
|
+
Node( 'ShaderGeometry','OpenGLContext.scenegraph.shaders.ShaderGeometry' )
|
|
148
|
+
|
|
149
|
+
Node( 'Shader','OpenGLContext.scenegraph.shaders.Shader' )
|
|
150
|
+
Node( 'ROUTE','vrml.route.ROUTE' )
|
|
151
|
+
Node( 'IS','vrml.route.IS' )
|
OpenGLContext/arrays.py
ADDED
OpenGLContext/atlas.py
ADDED
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
"""Texture atlas implementation"""
|
|
2
|
+
import math, weakref, logging
|
|
3
|
+
from OpenGL.GL import *
|
|
4
|
+
from OpenGLContext.arrays import zeros, array, dot, ArrayType
|
|
5
|
+
from OpenGLContext import texture
|
|
6
|
+
from vrml.vrml97 import transformmatrix
|
|
7
|
+
|
|
8
|
+
log = logging.getLogger( __name__ )
|
|
9
|
+
|
|
10
|
+
class _Strip( object ):
|
|
11
|
+
"""Strip within the atlas which takes particular set of images"""
|
|
12
|
+
def __init__( self, atlas, height, yoffset ):
|
|
13
|
+
"""Sets up the strip to receive images"""
|
|
14
|
+
self.atlas = atlas
|
|
15
|
+
self.height = height
|
|
16
|
+
self.width = 0
|
|
17
|
+
self.yoffset = yoffset
|
|
18
|
+
self.maps = []
|
|
19
|
+
def start_coord( self, x ):
|
|
20
|
+
"""Do we have an empty space sufficient to fit image of width x?
|
|
21
|
+
|
|
22
|
+
return starting coordinate or -1 if not enough space...
|
|
23
|
+
"""
|
|
24
|
+
last = 0
|
|
25
|
+
for map in self.maps:
|
|
26
|
+
referenced = map()
|
|
27
|
+
if referenced is not None:
|
|
28
|
+
if referenced.offset[0]-last >= x:
|
|
29
|
+
return last
|
|
30
|
+
else:
|
|
31
|
+
last = referenced.offset[0]+referenced.size[0]
|
|
32
|
+
if self.atlas.max_size-last >= x:
|
|
33
|
+
return last
|
|
34
|
+
return -1
|
|
35
|
+
def add( self, image, start=None ):
|
|
36
|
+
"""Add the given PIL image to our atlas' image"""
|
|
37
|
+
x,y = image.size
|
|
38
|
+
if start is None:
|
|
39
|
+
start = self.start_coord( x )
|
|
40
|
+
offset = (start,self.yoffset)
|
|
41
|
+
map = Map( self.atlas, offset, (x,y), image )
|
|
42
|
+
self.maps.append( weakref.ref( map, self._remover( offset )) )
|
|
43
|
+
self.atlas.need_updates.append( weakref.ref(map) )
|
|
44
|
+
return map
|
|
45
|
+
def _remover( self, offset ):
|
|
46
|
+
def remover( *args ):
|
|
47
|
+
self.onRemove( )
|
|
48
|
+
return remover
|
|
49
|
+
def onRemove( self, *args, **named ):
|
|
50
|
+
"""Remove map by offset (normally a weakref-release callback)"""
|
|
51
|
+
update = False
|
|
52
|
+
for mapRef in self.maps:
|
|
53
|
+
referenced = mapRef()
|
|
54
|
+
if referenced is None:
|
|
55
|
+
try:
|
|
56
|
+
self.maps.remove( mapRef )
|
|
57
|
+
except ValueError as err:
|
|
58
|
+
pass
|
|
59
|
+
update = True
|
|
60
|
+
|
|
61
|
+
class AtlasError( Exception ):
|
|
62
|
+
"""Raised when we can't/shouldn't append to this atlas"""
|
|
63
|
+
|
|
64
|
+
class Atlas( object ):
|
|
65
|
+
"""Collection of textures packed into a single texture
|
|
66
|
+
|
|
67
|
+
Texture atlases allow the rendering engine to reduce the
|
|
68
|
+
number of state-changes which occur during the rendering
|
|
69
|
+
process. They pack a large number of small textures into
|
|
70
|
+
a single large texture, producing offset/scale matrices to
|
|
71
|
+
use for modifying texture coordinates to map from the
|
|
72
|
+
original to the packed coordinates.
|
|
73
|
+
"""
|
|
74
|
+
_local = None
|
|
75
|
+
_size = None
|
|
76
|
+
def __init__( self, components=4, dataType='B', max_size=4096 ):
|
|
77
|
+
self.components = components
|
|
78
|
+
self.dataType = dataType
|
|
79
|
+
self.strips = []
|
|
80
|
+
self.max_size = max_size
|
|
81
|
+
self.need_updates = []
|
|
82
|
+
self.texture = None
|
|
83
|
+
log.info(
|
|
84
|
+
'Allocating a %s-component texture atlas of size %sx%s',
|
|
85
|
+
components,
|
|
86
|
+
max_size,max_size,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
def add( self, image ):
|
|
90
|
+
"""Insert a PIL image of values as a sub-texture
|
|
91
|
+
|
|
92
|
+
Has to find a place within the atlas to insert the
|
|
93
|
+
sub-texture and then return the offset/scale factors...
|
|
94
|
+
"""
|
|
95
|
+
max_x = max_y = self.max_size
|
|
96
|
+
x,y = image.size
|
|
97
|
+
strip,start = self.choose_strip( max_x, max_y, x, y )
|
|
98
|
+
return strip.add( image, start=start )
|
|
99
|
+
def choose_strip( self, max_x,max_y, x,y ):
|
|
100
|
+
"""Find the strip to which we should be added"""
|
|
101
|
+
candidates = [
|
|
102
|
+
s
|
|
103
|
+
for s in self.strips
|
|
104
|
+
if (
|
|
105
|
+
s.height >= y
|
|
106
|
+
)
|
|
107
|
+
]
|
|
108
|
+
for strip in candidates:
|
|
109
|
+
if strip.height == y:
|
|
110
|
+
start = strip.start_coord( x )
|
|
111
|
+
if start > -1:
|
|
112
|
+
return strip, start
|
|
113
|
+
for strip in candidates:
|
|
114
|
+
strip_mag = math.floor(math.log( strip.height, 2 ))
|
|
115
|
+
img_mag = math.floor(math.log( y, 2 ))
|
|
116
|
+
if strip_mag == img_mag:
|
|
117
|
+
start = strip.start_coord( x )
|
|
118
|
+
if start > -1:
|
|
119
|
+
return strip, start
|
|
120
|
+
if self.strips:
|
|
121
|
+
last = self.strips[-1]
|
|
122
|
+
current_height = last.yoffset + last.height
|
|
123
|
+
else:
|
|
124
|
+
current_height = 0
|
|
125
|
+
if current_height + y > max_y:
|
|
126
|
+
raise AtlasError( """Insufficient space to store in this atlas""" )
|
|
127
|
+
strip = _Strip( self, height=y, yoffset= current_height )
|
|
128
|
+
self.strips.append( strip )
|
|
129
|
+
start = strip.start_coord( x )
|
|
130
|
+
return strip, start
|
|
131
|
+
|
|
132
|
+
def size( self ):
|
|
133
|
+
if self._size is None:
|
|
134
|
+
x = y = self.max_size
|
|
135
|
+
self._size = (x,y,self.components)
|
|
136
|
+
return self._size
|
|
137
|
+
|
|
138
|
+
def render( self ):
|
|
139
|
+
"""Render this texture to the context"""
|
|
140
|
+
if self.texture is None:
|
|
141
|
+
format = [0, GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA ][self.components]
|
|
142
|
+
self.texture = texture.Texture(format=format)
|
|
143
|
+
x,y,d = self.size()
|
|
144
|
+
self.texture.store(
|
|
145
|
+
d,
|
|
146
|
+
format,
|
|
147
|
+
x,y,
|
|
148
|
+
None
|
|
149
|
+
)
|
|
150
|
+
self.texture()
|
|
151
|
+
needs = self.need_updates[:]
|
|
152
|
+
del self.need_updates[:len(needs)]
|
|
153
|
+
for need in needs:
|
|
154
|
+
need = need()
|
|
155
|
+
if need is not None:
|
|
156
|
+
need.update( self.texture )
|
|
157
|
+
return self.texture
|
|
158
|
+
def cached( self, mode ):
|
|
159
|
+
"""Get cached version of this texture
|
|
160
|
+
|
|
161
|
+
Note: currently we do *not* properly use mode-level caching
|
|
162
|
+
for the texture object
|
|
163
|
+
"""
|
|
164
|
+
return self.render()
|
|
165
|
+
def debugImageTexture( self, mode ):
|
|
166
|
+
"""Create a debugging image texture for this texture atlas
|
|
167
|
+
"""
|
|
168
|
+
from OpenGLContext.scenegraph.imagetexture import ImageTexture,Image
|
|
169
|
+
from OpenGLContext.texture import NumpyAdapter
|
|
170
|
+
from vrml import protofunctions
|
|
171
|
+
format = NumpyAdapter.shapeToMode( self.components )
|
|
172
|
+
instance = ImageTexture(
|
|
173
|
+
image = Image.new(format, (1,1), '#ffff00'),
|
|
174
|
+
)
|
|
175
|
+
holder = mode.cache.holder(instance, self.texture)
|
|
176
|
+
return instance
|
|
177
|
+
|
|
178
|
+
class Map( object ):
|
|
179
|
+
"""Object representing a sub-texture within a texture atlas
|
|
180
|
+
|
|
181
|
+
A Map object is a dependent version of an OpenGLContext.texture.Texture
|
|
182
|
+
object, i.e. it tries to offer the same API, but with support for
|
|
183
|
+
Atlas-based maps instead of stand-alone ones.
|
|
184
|
+
"""
|
|
185
|
+
_matrix = None
|
|
186
|
+
_coords = None
|
|
187
|
+
_uploaded = False
|
|
188
|
+
def __init__( self, atlas, offset, size, image ):
|
|
189
|
+
self.atlas = atlas
|
|
190
|
+
self.offset = offset
|
|
191
|
+
self.size = size
|
|
192
|
+
self.image = image
|
|
193
|
+
self.components = self.atlas.components
|
|
194
|
+
def matrix( self ):
|
|
195
|
+
"""Calculate a 4x4 transform matrix for texcoords
|
|
196
|
+
|
|
197
|
+
To manipulate texture coordinates with this matrix
|
|
198
|
+
they need to be in homogenous coordinates, i.e. a
|
|
199
|
+
"regular" 2d coordinate of (x,y) becomes (x,y,0.0,1.0)
|
|
200
|
+
so that it can pick up the translations.
|
|
201
|
+
|
|
202
|
+
dot( coord, matrix ) produces the transformed
|
|
203
|
+
coordinate for processing.
|
|
204
|
+
|
|
205
|
+
returns 4x4 translation matrix
|
|
206
|
+
"""
|
|
207
|
+
if self._matrix is None:
|
|
208
|
+
# translate by self.offset/atlas.size
|
|
209
|
+
# scale by self.size/atlas.size
|
|
210
|
+
tx,ty,d = self.atlas.size()
|
|
211
|
+
tx,ty = float(tx),float(ty)
|
|
212
|
+
x,y = self.offset
|
|
213
|
+
sx,sy = self.size
|
|
214
|
+
self._matrix = transformmatrix.transformMatrix (
|
|
215
|
+
translation = (x/tx,y/ty,0),
|
|
216
|
+
scale = (sx/tx,sy/ty,1),
|
|
217
|
+
)
|
|
218
|
+
return self._matrix
|
|
219
|
+
def coords( self ):
|
|
220
|
+
"""Return our bottom-left and top-right coordinate pairs"""
|
|
221
|
+
if self._coords is None:
|
|
222
|
+
tx,ty,d = self.atlas.size()
|
|
223
|
+
tx,ty = float(tx),float(ty)
|
|
224
|
+
x,y = self.offset
|
|
225
|
+
sx,sy = self.size
|
|
226
|
+
self._coords = array( ((x/tx,y/ty),((x+sx)/tx,(y+sy)/ty)), 'f')
|
|
227
|
+
return self._coords
|
|
228
|
+
|
|
229
|
+
def replace( self, image ):
|
|
230
|
+
"""Replace our current image with given (PIL) image"""
|
|
231
|
+
self._uploaded = False
|
|
232
|
+
self.image = image
|
|
233
|
+
self.atlas.need_updates.append( weakref.ref(self) )
|
|
234
|
+
def update( self, texture ):
|
|
235
|
+
"""Update texture with (new) data in self.image
|
|
236
|
+
|
|
237
|
+
This just calls texture.update with our metadata
|
|
238
|
+
in order to do the actual copy of the data-pointer.
|
|
239
|
+
"""
|
|
240
|
+
texture.update(
|
|
241
|
+
self.offset, self.size,
|
|
242
|
+
texture.pilAsString( self.image),
|
|
243
|
+
)
|
|
244
|
+
self._uploaded = True
|
|
245
|
+
@property
|
|
246
|
+
def texture( self ):
|
|
247
|
+
"""Retrieve our texture"""
|
|
248
|
+
return self.atlas.cached( None )
|
|
249
|
+
def __call__( self ):
|
|
250
|
+
"""Enable/call our texture"""
|
|
251
|
+
self.atlas.render()
|
|
252
|
+
# should also load our texture-transform matrix.
|
|
253
|
+
glMatrixMode( GL_TEXTURE )
|
|
254
|
+
glLoadMatrixd( self.matrix() )
|
|
255
|
+
glMatrixMode( GL_MODELVIEW )
|
|
256
|
+
|
|
257
|
+
class AtlasManager( object ):
|
|
258
|
+
"""Collection of atlases within the renderer"""
|
|
259
|
+
def __init__( self, max_size=4096, max_child_size=128 ):
|
|
260
|
+
self.components = {}
|
|
261
|
+
self.max_size = max_size
|
|
262
|
+
self.max_child_size = max_child_size
|
|
263
|
+
FORMAT_MAPPING = {
|
|
264
|
+
'L':(1,GL_LUMINANCE),
|
|
265
|
+
'LA':(2,GL_LUMINANCE_ALPHA),
|
|
266
|
+
'RGB':(3,GL_RGB),
|
|
267
|
+
'RGBA':(4,GL_RGBA),
|
|
268
|
+
}
|
|
269
|
+
def formatToComponents( self, format ):
|
|
270
|
+
"""Convert PIL format to component count"""
|
|
271
|
+
return self.FORMAT_MAPPING[ format ][0]
|
|
272
|
+
def add( self, image ):
|
|
273
|
+
"""Add the given image to the texture atlas"""
|
|
274
|
+
if isinstance( image, ArrayType ):
|
|
275
|
+
image = texture.NumpyAdapter( image )
|
|
276
|
+
x,y = image.size
|
|
277
|
+
if x > self.max_child_size:
|
|
278
|
+
raise AtlasError( """X size (%s) > %s"""%( x,self.max_child_size ) )
|
|
279
|
+
if y > self.max_child_size:
|
|
280
|
+
raise AtlasError( """Y size (%s) > %s"""%( y,self.max_child_size ) )
|
|
281
|
+
d = self.formatToComponents( image.mode )
|
|
282
|
+
atlases = self.components.setdefault( d, [])
|
|
283
|
+
for atlas in atlases:
|
|
284
|
+
try:
|
|
285
|
+
return atlas.add( image )
|
|
286
|
+
except AtlasError as err:
|
|
287
|
+
pass
|
|
288
|
+
atlas = Atlas( d, max_size=self.max_size or self.calculate_max_size() )
|
|
289
|
+
atlases.append( atlas )
|
|
290
|
+
return atlas.add( image )
|
|
291
|
+
_MAX_MAX_SIZE = 4096
|
|
292
|
+
def calculate_max_size( self ):
|
|
293
|
+
"""Calculate the maximum size of a texture
|
|
294
|
+
|
|
295
|
+
Note that this might, for instance, assume a
|
|
296
|
+
single-component texture or some similarly inappropriate
|
|
297
|
+
value...
|
|
298
|
+
"""
|
|
299
|
+
self.max_size = min( (glGetIntegerv(GL_MAX_TEXTURE_SIZE), self._MAX_MAX_SIZE) )
|
|
300
|
+
return self.max_size
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Giving an OpenGLContext context an ear.
|
|
2
|
+
|
|
3
|
+
The sound itself is :mod:`omi_audio`: the ``KHR_audio_emitter`` data model,
|
|
4
|
+
every gain curve, the clip cache, the numpy mixer, the device seam and the
|
|
5
|
+
engine that ties them together. None of that knows what a scenegraph is, and
|
|
6
|
+
none of it belongs here.
|
|
7
|
+
|
|
8
|
+
What is here is the two seams between that engine and a context:
|
|
9
|
+
|
|
10
|
+
========================= ====================================================
|
|
11
|
+
:mod:`~.scene` One engine per context, opened on the first frame
|
|
12
|
+
that has something audible in it, and driven once a
|
|
13
|
+
frame from the camera and the render pass's
|
|
14
|
+
``Auditory`` node paths.
|
|
15
|
+
:mod:`~.settings` :class:`~.settings.AudioSettings`, the player's own
|
|
16
|
+
switch, volume and voice budget, declared as a node
|
|
17
|
+
on the :class:`~OpenGLContext.contextdefinition.ContextDefinition`
|
|
18
|
+
so it validates, serialises and generates its own
|
|
19
|
+
settings page like every other field group.
|
|
20
|
+
========================= ====================================================
|
|
21
|
+
|
|
22
|
+
The nodes that put a sound *in* a scene are
|
|
23
|
+
:mod:`OpenGLContext.scenegraph.audio` -- ``AudioEmitter``, ``AudioSource`` and
|
|
24
|
+
VRML97's ``Sound`` -- and the glTF loader reads ``KHR_audio_emitter`` blocks
|
|
25
|
+
into them through :mod:`OpenGLContext.loaders.gltf.scene`.
|
|
26
|
+
|
|
27
|
+
Sound is **optional and never fatal**. ``miniaudio`` may be absent and a device
|
|
28
|
+
may fail to open; both end in one warning and a silent run, so a machine with no
|
|
29
|
+
sound card is simply a machine with no sound.
|
|
30
|
+
|
|
31
|
+
See ``docs/audio.html`` for the data-flow diagrams and a worked example.
|
|
32
|
+
"""
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"""Giving a context an ear, and driving the scene's sounds once a frame.
|
|
2
|
+
|
|
3
|
+
This is the whole of the seam between the render loop and :mod:`omi_audio`. The
|
|
4
|
+
render pass already collects every :class:`~vrml.vrml97.nodetypes.Auditory` node
|
|
5
|
+
path and already knows where the camera is; :func:`update` turns those two facts
|
|
6
|
+
into sound.
|
|
7
|
+
|
|
8
|
+
**Silence costs nothing.** A context gets no engine, and therefore opens no
|
|
9
|
+
device and starts no audio thread, until a frame is drawn with something audible
|
|
10
|
+
in it. A scene with no sounds -- which is most test scenes and every existing
|
|
11
|
+
OpenGLContext demo -- is untouched by any of this.
|
|
12
|
+
|
|
13
|
+
The engine hangs off the context rather than being a global, because two windows
|
|
14
|
+
are two listeners, and it is held weakly so closing a window does not leak a
|
|
15
|
+
device.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import logging
|
|
21
|
+
import time
|
|
22
|
+
import weakref
|
|
23
|
+
from typing import Any, Dict, Optional, Sequence
|
|
24
|
+
|
|
25
|
+
from omi_audio.device import open_device
|
|
26
|
+
from omi_audio.engine import AudioEngine
|
|
27
|
+
|
|
28
|
+
from OpenGLContext.audio.settings import settings_for
|
|
29
|
+
from OpenGLContext.scenegraph.audio import stop_scene_audio, update_scene_audio
|
|
30
|
+
|
|
31
|
+
log = logging.getLogger(__name__)
|
|
32
|
+
|
|
33
|
+
#: Engines by context. Weak, so a closed window's device goes with it; keyed by
|
|
34
|
+
#: the context itself rather than stored on it so a context class needs to know
|
|
35
|
+
#: nothing about audio to have some.
|
|
36
|
+
_engines: "weakref.WeakKeyDictionary[Any, AudioEngine]" = weakref.WeakKeyDictionary()
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def existing_engine(context: Any) -> Optional[AudioEngine]:
|
|
40
|
+
"""The engine ``context`` already has, or None. Never makes one."""
|
|
41
|
+
return _engines.get(context)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def enabled(context: Any) -> bool:
|
|
45
|
+
"""Whether this context's settings allow sound at all."""
|
|
46
|
+
return bool(settings_for(context).enabled)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def engine_for(context: Any) -> Optional[AudioEngine]:
|
|
50
|
+
"""The engine for ``context``, opened on first ask.
|
|
51
|
+
|
|
52
|
+
Returns None where the context's definition has audio switched off, which is
|
|
53
|
+
the one case a caller has to handle -- and handling it is doing nothing.
|
|
54
|
+
"""
|
|
55
|
+
if not enabled(context):
|
|
56
|
+
return None
|
|
57
|
+
engine = _engines.get(context)
|
|
58
|
+
if engine is None:
|
|
59
|
+
settings = settings_for(context)
|
|
60
|
+
engine = AudioEngine(device=open_device(), voices=int(settings.voices))
|
|
61
|
+
engine.volume = settings.volume
|
|
62
|
+
_engines[context] = engine
|
|
63
|
+
return engine
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def close(context: Any) -> None:
|
|
67
|
+
"""Release ``context``'s engine and its device. Safe if it had none."""
|
|
68
|
+
engine = _engines.pop(context, None)
|
|
69
|
+
if engine is not None:
|
|
70
|
+
engine.close()
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def update(context: Any, paths: Sequence[Any], now: Optional[float] = None) -> int:
|
|
74
|
+
"""Keep ``context``'s sounds in step with its camera, for one frame.
|
|
75
|
+
|
|
76
|
+
``paths`` are the render pass's collected ``Auditory`` node paths. An empty
|
|
77
|
+
sequence returns immediately **without opening a device**, which is what
|
|
78
|
+
makes sound free for a scene that has none.
|
|
79
|
+
|
|
80
|
+
``now`` is absolute seconds, because VRML97's ``startTime`` and ``stopTime``
|
|
81
|
+
are absolute; it is taken from the wall clock when not given.
|
|
82
|
+
|
|
83
|
+
Returns how many nodes were driven, for a debug overlay.
|
|
84
|
+
"""
|
|
85
|
+
if not paths or not enabled(context):
|
|
86
|
+
return 0
|
|
87
|
+
engine = engine_for(context)
|
|
88
|
+
if engine is None:
|
|
89
|
+
return 0
|
|
90
|
+
# The *player's* volume, read every frame: the settings screen writes the
|
|
91
|
+
# field, and a volume slider that only takes effect on the next launch is a
|
|
92
|
+
# volume slider nobody uses. The application's own `master_gain` is left
|
|
93
|
+
# alone -- writing over it here would make an application's mix level last
|
|
94
|
+
# exactly one frame.
|
|
95
|
+
engine.volume = settings_for(context).volume
|
|
96
|
+
platform = _view_platform(context)
|
|
97
|
+
if platform is not None:
|
|
98
|
+
engine.listen(platform)
|
|
99
|
+
return update_scene_audio(engine, paths,
|
|
100
|
+
time.time() if now is None else now)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def stop(context: Any, paths: Sequence[Any]) -> None:
|
|
104
|
+
"""Silence every sound in a scene that is going away."""
|
|
105
|
+
stop_scene_audio(paths)
|
|
106
|
+
engine = _engines.get(context)
|
|
107
|
+
if engine is not None:
|
|
108
|
+
engine.stop_all()
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _view_platform(context: Any) -> Any:
|
|
112
|
+
"""The context's camera, however it exposes one."""
|
|
113
|
+
getter = getattr(context, 'getViewPlatform', None)
|
|
114
|
+
if getter is not None:
|
|
115
|
+
return getter()
|
|
116
|
+
return getattr(context, 'platform', None)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def describe(context: Any) -> Dict[str, Any]:
|
|
120
|
+
"""What this context's audio is doing, for a debug overlay."""
|
|
121
|
+
engine = _engines.get(context)
|
|
122
|
+
if engine is None:
|
|
123
|
+
return {'audio': 'off' if not enabled(context) else 'idle'}
|
|
124
|
+
return {
|
|
125
|
+
'audio': 'silent' if engine.silent else '%d Hz' % (engine.sample_rate,),
|
|
126
|
+
'voices': engine.active_voices,
|
|
127
|
+
'volume': round(engine.volume, 2),
|
|
128
|
+
'mix': round(engine.master_gain, 2),
|
|
129
|
+
'muffle': round(engine.muffle, 2),
|
|
130
|
+
}
|