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,156 @@
|
|
|
1
|
+
"""Interactions for navigating the context"""
|
|
2
|
+
from gettext import gettext as _
|
|
3
|
+
from OpenGLContext.move import movementmanager
|
|
4
|
+
import math
|
|
5
|
+
|
|
6
|
+
class Direct( movementmanager.MovementManager ):
|
|
7
|
+
"""OpenGLContext's original manipulation for the view platform"""
|
|
8
|
+
commands = movementmanager.MovementManager.commands + [
|
|
9
|
+
# User-name, key, function-name
|
|
10
|
+
(_('Forward'), 'forward','forward'),
|
|
11
|
+
(_('Back'), 'backward','backward' ),
|
|
12
|
+
(_('Up'), 'up','up' ),
|
|
13
|
+
(_('Down'), 'down', 'down' ),
|
|
14
|
+
(_('Left'), 'left', 'left' ),
|
|
15
|
+
(_('Right'), 'right', 'right' ),
|
|
16
|
+
|
|
17
|
+
(_('Turn Up'), 'turnup', 'turnup' ),
|
|
18
|
+
(_('Turn Down'), 'turndown', 'turndown' ),
|
|
19
|
+
(_('Turn Left'), 'turnleft', 'turnleft' ),
|
|
20
|
+
(_('Turn Right'), 'turnright', 'turnright' ),
|
|
21
|
+
|
|
22
|
+
(_('Straighten'), 'straighten','straighten'),
|
|
23
|
+
|
|
24
|
+
(_('Faster'), 'faster', 'faster' ),
|
|
25
|
+
(_('Slower'), 'slower','slower' ),
|
|
26
|
+
]
|
|
27
|
+
commandBindings = dict(
|
|
28
|
+
forward=dict( eventType='keyboard', name='<up>', state=1, modifiers=(0,0,0) ),
|
|
29
|
+
backward=dict( eventType='keyboard', name='<down>', state=1, modifiers=(0,0,0) ),
|
|
30
|
+
up=dict( eventType='keyboard', name='<up>', state=1, modifiers=(0,0,1)),
|
|
31
|
+
turnup=dict(eventType='keyboard', name='<up>', state=1, modifiers=(0,1,0)),
|
|
32
|
+
turndown=dict(eventType='keyboard', name='<down>', state=1, modifiers=(0,1,0)),
|
|
33
|
+
down=dict(eventType='keyboard', name='<down>', state=1, modifiers=(0,0,1),),
|
|
34
|
+
turnleft=dict(eventType='keyboard', name='<left>', state=1, modifiers=(0,0,0),),
|
|
35
|
+
left=dict(eventType='keyboard', name='<left>', state=1, modifiers=(0,0,1)),
|
|
36
|
+
turnright=dict(eventType='keyboard', name='<right>', state=1, modifiers=(0,0,0),),
|
|
37
|
+
right=dict(eventType='keyboard', name='<right>', state=1, modifiers=(0,0,1),),
|
|
38
|
+
straighten=dict(eventType='keypress', name='-', modifiers=(0,0,0),),
|
|
39
|
+
slower=dict(eventType='keypress', name='[', modifiers=(0,0,0),),
|
|
40
|
+
faster=dict(eventType='keypress', name=']', modifiers=(0,0,0),),
|
|
41
|
+
examine=dict(eventType='mousebutton', button=1, state = 1, modifiers=(0,0,0),),
|
|
42
|
+
)
|
|
43
|
+
STEPDISTANCE = 0.5 # 1/2 of a unit
|
|
44
|
+
TURNANGLE = math.pi/32
|
|
45
|
+
|
|
46
|
+
### LOGO-like commands...
|
|
47
|
+
def turn (self, deltaOrientation= (0,1,0,math.pi/4) ):
|
|
48
|
+
"""Apply rotation within the current orientation
|
|
49
|
+
|
|
50
|
+
In essence, this allows you to "turn your head"
|
|
51
|
+
which gives you the commonly useful ability to
|
|
52
|
+
function from your own frame of reference.
|
|
53
|
+
|
|
54
|
+
For example:
|
|
55
|
+
turn( 1,0,0,angle ) will rotate the camera up
|
|
56
|
+
from its current view orientation
|
|
57
|
+
turn( 0,1,0,angle ) will rotate the camera about
|
|
58
|
+
the current horizon
|
|
59
|
+
|
|
60
|
+
This method is implemented almost entirely within
|
|
61
|
+
the quaternion class. Quaternion's have considerable
|
|
62
|
+
advantages for this type of work, as they do not
|
|
63
|
+
become "warped" with successive rotations.
|
|
64
|
+
"""
|
|
65
|
+
self.platform.setOrientation( self.platform.relativeOrientation( deltaOrientation ) )
|
|
66
|
+
self.context.triggerRedraw(1)
|
|
67
|
+
|
|
68
|
+
def stepRelative( self, x=0,y=0,z=0 ):
|
|
69
|
+
"""Step this distance in relative (view) coordinates"""
|
|
70
|
+
self.platform.moveRelative( x=x,y=y,z=z )
|
|
71
|
+
self.context.triggerRedraw(1)
|
|
72
|
+
|
|
73
|
+
def forward( self, event ):
|
|
74
|
+
"""(callback) Move platform forward by STEPDISTANCE
|
|
75
|
+
|
|
76
|
+
triggers redraw after completion
|
|
77
|
+
"""
|
|
78
|
+
self.stepRelative( z = -self.STEPDISTANCE )
|
|
79
|
+
def backward( self, event ):
|
|
80
|
+
"""(callback) Move platform backward by STEPDISTANCE
|
|
81
|
+
|
|
82
|
+
triggers redraw after completion
|
|
83
|
+
"""
|
|
84
|
+
self.stepRelative( z = self.STEPDISTANCE )
|
|
85
|
+
def up( self, event ):
|
|
86
|
+
"""(callback) Move platform upward by STEPDISTANCE
|
|
87
|
+
|
|
88
|
+
triggers redraw after completion
|
|
89
|
+
"""
|
|
90
|
+
self.stepRelative( y = self.STEPDISTANCE )
|
|
91
|
+
def down( self, event ):
|
|
92
|
+
"""(callback) Move platform downward by STEPDISTANCE
|
|
93
|
+
|
|
94
|
+
triggers redraw after completion
|
|
95
|
+
"""
|
|
96
|
+
self.stepRelative( y = -self.STEPDISTANCE )
|
|
97
|
+
def left( self, event ):
|
|
98
|
+
"""(callback) Move platform left by STEPDISTANCE
|
|
99
|
+
|
|
100
|
+
triggers redraw after completion
|
|
101
|
+
"""
|
|
102
|
+
self.stepRelative( x = -self.STEPDISTANCE )
|
|
103
|
+
def right( self, event ):
|
|
104
|
+
"""(callback) Move platform right by STEPDISTANCE
|
|
105
|
+
|
|
106
|
+
triggers redraw after completion
|
|
107
|
+
"""
|
|
108
|
+
self.stepRelative( x = self.STEPDISTANCE )
|
|
109
|
+
def turnup( self, event ):
|
|
110
|
+
"""(callback) Rotates "head" backward (looks upward) by TURNANGLE
|
|
111
|
+
|
|
112
|
+
triggers redraw after completion
|
|
113
|
+
"""
|
|
114
|
+
self.turn( (1.0,0.0,0.0, self.TURNANGLE) )
|
|
115
|
+
def turndown( self, event ):
|
|
116
|
+
"""(callback) Rotates "head" forward (looks downward) by TURNANGLE
|
|
117
|
+
|
|
118
|
+
triggers redraw after completion
|
|
119
|
+
"""
|
|
120
|
+
self.turn( (1.0,0.0,0.0, -self.TURNANGLE) )
|
|
121
|
+
def turnleft( self, event ):
|
|
122
|
+
"""(callback) Rotates "head" to the left by TURNANGLE
|
|
123
|
+
|
|
124
|
+
triggers redraw after completion
|
|
125
|
+
"""
|
|
126
|
+
self.turn( (0.0,1.0,0.0, self.TURNANGLE) )
|
|
127
|
+
def turnright( self, event ):
|
|
128
|
+
"""(callback) Rotates "head" to the right by TURNANGLE
|
|
129
|
+
|
|
130
|
+
triggers redraw after completion
|
|
131
|
+
"""
|
|
132
|
+
self.turn( (0.0,1.0,0.0, -self.TURNANGLE) )
|
|
133
|
+
def straighten( self, event ):
|
|
134
|
+
"""(callback) Straightens the platform orientation
|
|
135
|
+
|
|
136
|
+
Attempts to make the orientation equal to the
|
|
137
|
+
y-axis orientation of the current orientation.
|
|
138
|
+
|
|
139
|
+
In other words, tries to make the camera's horizon
|
|
140
|
+
equal to the object-space horizon (the x,z plane)
|
|
141
|
+
without altering the y-axis orientation.
|
|
142
|
+
|
|
143
|
+
See:
|
|
144
|
+
OpenGLContext.viewplatform.ViewPlatform.straighten
|
|
145
|
+
|
|
146
|
+
triggers redraw after completion
|
|
147
|
+
"""
|
|
148
|
+
self.platform.straighten()
|
|
149
|
+
self.context.triggerRedraw(1)
|
|
150
|
+
|
|
151
|
+
def faster( self, event ):
|
|
152
|
+
"""Increase our walking speed"""
|
|
153
|
+
self.STEPDISTANCE *= 1.5
|
|
154
|
+
def slower( self, event ):
|
|
155
|
+
"""Decrease our walking speed"""
|
|
156
|
+
self.STEPDISTANCE /= 1.5
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Semantics for fractional and absolute dragging"""
|
|
2
|
+
|
|
3
|
+
class DragWatcher(object):
|
|
4
|
+
"""Class providing semantics for fractional and absolute dragging
|
|
5
|
+
|
|
6
|
+
With this class you can track the start position of a drag action
|
|
7
|
+
and query for both absolute distance dragged, and distance as a
|
|
8
|
+
fraction of the distance to the edges of the window.
|
|
9
|
+
"""
|
|
10
|
+
def __init__ (self, startX, startY, totalX, totalY ):
|
|
11
|
+
"""Initialise the DragWatcher
|
|
12
|
+
|
|
13
|
+
startX, startY -- initial coordinates for the drag
|
|
14
|
+
totalX, totalY -- overall dimensions of the context
|
|
15
|
+
"""
|
|
16
|
+
self.start = startX, startY
|
|
17
|
+
self.total = totalX, totalY
|
|
18
|
+
def fractions (self, newX, newY ):
|
|
19
|
+
"""Calculate fractional delta from the start point
|
|
20
|
+
|
|
21
|
+
newX, newY -- new selection point from which to calculate
|
|
22
|
+
"""
|
|
23
|
+
if (newX, newY) == self.start:
|
|
24
|
+
return 0.0,0.0
|
|
25
|
+
values = []
|
|
26
|
+
for index, item in ((0, newX), (1, newY)):
|
|
27
|
+
if item < self.start[index]:
|
|
28
|
+
value = float(item-self.start[index])/ self.start[index]
|
|
29
|
+
else:
|
|
30
|
+
value = float(item-self.start[index])/ (self.total[index]-self.start[index])
|
|
31
|
+
values.append (value)
|
|
32
|
+
return values
|
|
33
|
+
def distances (self, newX, newY ):
|
|
34
|
+
"""Calculate absolute distances from start point
|
|
35
|
+
|
|
36
|
+
newX, newY -- new selection point from which to calculate
|
|
37
|
+
"""
|
|
38
|
+
if (newX, newY) == self.start:
|
|
39
|
+
return 0,0
|
|
40
|
+
else:
|
|
41
|
+
return newX-self.start[0], newY-self.start[1]
|
|
42
|
+
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""Interaction mode for examining objects"""
|
|
2
|
+
import math
|
|
3
|
+
|
|
4
|
+
from OpenGLContext.events import eventmanager
|
|
5
|
+
|
|
6
|
+
#: How far a drag from where it started to the edge of the window turns the
|
|
7
|
+
#: view: **half a circle**. The trackball's own default is a full one, which
|
|
8
|
+
#: put the far side of the model half a window away and made a nudge a quarter
|
|
9
|
+
#: turn -- with nothing that could be called examining in between. Half a turn
|
|
10
|
+
#: to the edge is what a VRML browser has always done, and it means the whole
|
|
11
|
+
#: of an object is reachable in one drag while a small movement is a small look.
|
|
12
|
+
EXAMINE_DRAG_ANGLE = math.pi
|
|
13
|
+
|
|
14
|
+
class ExamineManager ( eventmanager.EventManager):
|
|
15
|
+
"""Interaction EventManager for "Examine" mode
|
|
16
|
+
|
|
17
|
+
This interaction manager implements an examine mode
|
|
18
|
+
similar to that found in VRML97 browsers. Pointing
|
|
19
|
+
to an object and dragging up/down left/right causes
|
|
20
|
+
the viewpoint to orbit around the object as if the
|
|
21
|
+
object were held in the hand and being rotated.
|
|
22
|
+
|
|
23
|
+
The manager uses the trackball thereby the dragwatcher
|
|
24
|
+
to provide screen-relative scaling of the input. In
|
|
25
|
+
other words, distances are measured as fractions of
|
|
26
|
+
the distance to the edge of the screen.
|
|
27
|
+
"""
|
|
28
|
+
type = "examine"
|
|
29
|
+
def __init__ (self, context, platform, center, event):
|
|
30
|
+
"""Initialise the ExamineManager
|
|
31
|
+
|
|
32
|
+
context -- Context instance
|
|
33
|
+
platform -- ViewPlatform instance
|
|
34
|
+
center -- object-space coordinates about which to revolve
|
|
35
|
+
event -- event which began the examine interaction.
|
|
36
|
+
"""
|
|
37
|
+
self.platform = platform
|
|
38
|
+
self.client = context
|
|
39
|
+
eventmanager.EventManager.__init__ (self)
|
|
40
|
+
width, height = self.client.getViewPort()
|
|
41
|
+
self.button = event.button
|
|
42
|
+
self.OnBuildTrackball( platform, center, event, width, height )
|
|
43
|
+
self.OnBind()
|
|
44
|
+
### client API
|
|
45
|
+
def update( self, event ):
|
|
46
|
+
'''Update the examine trackball with new mouse event
|
|
47
|
+
|
|
48
|
+
This updates the internal position, then triggers a
|
|
49
|
+
redraw of the context.
|
|
50
|
+
'''
|
|
51
|
+
position, orientation = self.trackball.update(* event.getPickPoint() )
|
|
52
|
+
self.platform.position = position
|
|
53
|
+
self.platform.quaternion = orientation
|
|
54
|
+
self.client.triggerRedraw(1)
|
|
55
|
+
def release( self, event ):
|
|
56
|
+
"""Trigger cleanup of the examine mode"""
|
|
57
|
+
self.OnUnBind()
|
|
58
|
+
def cancel(self, event):
|
|
59
|
+
"""Cancel the examine mode, return to original position and orientation"""
|
|
60
|
+
position, orientation = self.trackball.cancel ()
|
|
61
|
+
self.OnUnBind()
|
|
62
|
+
self.platform.position = position
|
|
63
|
+
self.platform.quaternion = orientation
|
|
64
|
+
self.client.triggerRedraw(1)
|
|
65
|
+
|
|
66
|
+
### Customisation points
|
|
67
|
+
def OnBuildTrackball( self, platform, center, event, width, height ):
|
|
68
|
+
"""Build the trackball object
|
|
69
|
+
Customisation point for those wanting to use a different
|
|
70
|
+
trackball implementation."""
|
|
71
|
+
from OpenGLContext.move import trackball
|
|
72
|
+
self.trackball = trackball.Trackball (
|
|
73
|
+
platform.position, platform.quaternion,
|
|
74
|
+
center,
|
|
75
|
+
event.getPickPoint()[0],event.getPickPoint()[1],
|
|
76
|
+
width, height,
|
|
77
|
+
dragAngle = EXAMINE_DRAG_ANGLE,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
def OnBind( self ):
|
|
81
|
+
"""Bind the events needing binding to run the examine mode
|
|
82
|
+
Customisation point for those needing custom controls"""
|
|
83
|
+
self.client.captureEvents("mousebutton", self)
|
|
84
|
+
self.client.captureEvents("mousemove", self)
|
|
85
|
+
def OnUnBind( self ):
|
|
86
|
+
"""UnBind the events for the examine mode
|
|
87
|
+
Customisation point for those needing custom controls"""
|
|
88
|
+
self.client.captureEvents("mousemove", None)
|
|
89
|
+
self.client.captureEvents("mousebutton", None)
|
|
90
|
+
def ProcessEvent (self, event):
|
|
91
|
+
"""Respond to events from the system
|
|
92
|
+
Customisation point for those needing custom controls"""
|
|
93
|
+
if event.type == "mousemove":
|
|
94
|
+
self.update (event)
|
|
95
|
+
elif event.type == "mousebutton":
|
|
96
|
+
if event.button == self.button and event.state == 0: # mouse released
|
|
97
|
+
self.release (event)
|
|
98
|
+
elif event.state == 0: # mouse released, not our button, cancel
|
|
99
|
+
self.cancel( event )
|
|
100
|
+
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"""A fixed-offset follow camera for third-person / overhead demos.
|
|
2
|
+
|
|
3
|
+
The camera sits at a constant offset from a target and looks at it — no user
|
|
4
|
+
control, no orbiting. Each frame the caller sets the target (usually a moving
|
|
5
|
+
object's position) and calls :meth:`apply`, which writes the position and
|
|
6
|
+
orientation onto a :class:`~OpenGLContext.move.viewplatform.ViewPlatform`.
|
|
7
|
+
|
|
8
|
+
It also supports **holding**: freeze on the current target and ignore new ones
|
|
9
|
+
until released. The marble demo uses this to keep the view locked on the square a
|
|
10
|
+
marble fell from while the respawn penalty elapses, instead of chasing the marble
|
|
11
|
+
into the void.
|
|
12
|
+
|
|
13
|
+
Orientation convention: this targets the **core-profile** view path, where
|
|
14
|
+
``ViewPlatform`` builds the modelview from ``modelMatrix`` /
|
|
15
|
+
``quaternion.matrix``. :func:`look_at_orientation` returns the VRML axis-angle
|
|
16
|
+
that (after ``setOrientation`` negates it, as it does for every VRML orientation)
|
|
17
|
+
places the target on the camera's view -Z axis — verified end-to-end against
|
|
18
|
+
``ViewPlatform.modelMatrix`` in ``tests/test_followcam.py``.
|
|
19
|
+
"""
|
|
20
|
+
from typing import Any, Optional, Tuple
|
|
21
|
+
|
|
22
|
+
import numpy as np
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _normalize(v: Any) -> np.ndarray:
|
|
26
|
+
v = np.asarray(v, dtype='d')
|
|
27
|
+
n = np.linalg.norm(v)
|
|
28
|
+
return v / n if n > 1e-12 else v
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def look_at_orientation(eye: Any, target: Any,
|
|
32
|
+
up: Any = (0.0, 1.0, 0.0)) -> Tuple[float, float, float, float]:
|
|
33
|
+
"""VRML axis-angle ``(x, y, z, radians)`` orienting a camera at ``eye`` to
|
|
34
|
+
look at ``target``.
|
|
35
|
+
|
|
36
|
+
Builds the camera basis (right, up, backward) in world space and converts the
|
|
37
|
+
resulting rotation matrix to an axis-angle. ``up`` is the desired world up;
|
|
38
|
+
pass a different up (e.g. ``(0,0,-1)``) when looking straight down, where the
|
|
39
|
+
default up is degenerate.
|
|
40
|
+
"""
|
|
41
|
+
eye = np.asarray(eye, dtype='d')
|
|
42
|
+
target = np.asarray(target, dtype='d')
|
|
43
|
+
|
|
44
|
+
backward = _normalize(eye - target) # camera local +Z
|
|
45
|
+
right = _normalize(np.cross(_normalize(up), backward)) # camera local +X
|
|
46
|
+
true_up = np.cross(backward, right) # camera local +Y
|
|
47
|
+
# Columns are where the camera's local x/y/z land in world space (the
|
|
48
|
+
# camera-local → world rotation). ViewPlatform.setOrientation negates the
|
|
49
|
+
# angle and the core modelMatrix consumes it so this basis becomes the view.
|
|
50
|
+
R = np.column_stack([right, true_up, backward])
|
|
51
|
+
return _matrix_to_axis_angle(R)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _matrix_to_axis_angle(R: np.ndarray) -> Tuple[float, float, float, float]:
|
|
55
|
+
"""Convert a 3×3 rotation matrix to VRML axis-angle ``(x, y, z, radians)``."""
|
|
56
|
+
trace = np.trace(R)
|
|
57
|
+
cos_angle = np.clip((trace - 1.0) / 2.0, -1.0, 1.0)
|
|
58
|
+
angle = np.arccos(cos_angle)
|
|
59
|
+
if angle < 1e-9:
|
|
60
|
+
return (0.0, 1.0, 0.0, 0.0)
|
|
61
|
+
if angle > np.pi - 1e-6:
|
|
62
|
+
# Near 180°: axis from the largest diagonal term, sign-recovered off-diagonal.
|
|
63
|
+
d = np.array([R[0, 0], R[1, 1], R[2, 2]])
|
|
64
|
+
k = int(np.argmax(d))
|
|
65
|
+
axis = np.zeros(3)
|
|
66
|
+
axis[k] = np.sqrt(max((R[k, k] + 1.0) / 2.0, 0.0))
|
|
67
|
+
other = [(k + 1) % 3, (k + 2) % 3]
|
|
68
|
+
for j in other:
|
|
69
|
+
axis[j] = R[k, j] / (2.0 * axis[k]) if axis[k] > 1e-9 else 0.0
|
|
70
|
+
axis = _normalize(axis)
|
|
71
|
+
return (float(axis[0]), float(axis[1]), float(axis[2]), float(angle))
|
|
72
|
+
axis = np.array([R[2, 1] - R[1, 2],
|
|
73
|
+
R[0, 2] - R[2, 0],
|
|
74
|
+
R[1, 0] - R[0, 1]])
|
|
75
|
+
axis = _normalize(axis)
|
|
76
|
+
return (float(axis[0]), float(axis[1]), float(axis[2]), float(angle))
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class FollowCamera:
|
|
80
|
+
"""Drive a ``ViewPlatform`` to a fixed offset from a target, looking at it."""
|
|
81
|
+
|
|
82
|
+
def __init__(self, platform: Any, offset: Any = (0.0, 14.0, 14.0),
|
|
83
|
+
up: Any = (0.0, 1.0, 0.0)) -> None:
|
|
84
|
+
self.platform = platform
|
|
85
|
+
self.offset = np.asarray(offset, dtype='d')
|
|
86
|
+
self.up = np.asarray(up, dtype='d')
|
|
87
|
+
self._target = np.zeros(3)
|
|
88
|
+
self._held_target: Optional[np.ndarray] = None
|
|
89
|
+
|
|
90
|
+
def target(self, position: Any) -> None:
|
|
91
|
+
"""Record the live point to follow.
|
|
92
|
+
|
|
93
|
+
Always updates the live target; while holding, :meth:`apply` simply
|
|
94
|
+
ignores it, so on :meth:`release` the camera snaps to the most recent
|
|
95
|
+
live target rather than a stale one.
|
|
96
|
+
"""
|
|
97
|
+
self._target = np.asarray(position, dtype='d')[:3]
|
|
98
|
+
|
|
99
|
+
def hold(self) -> None:
|
|
100
|
+
"""Freeze the camera on the current target until :meth:`release`."""
|
|
101
|
+
if self._held_target is None:
|
|
102
|
+
self._held_target = self._target.copy()
|
|
103
|
+
|
|
104
|
+
def release(self) -> None:
|
|
105
|
+
"""Resume following live targets."""
|
|
106
|
+
self._held_target = None
|
|
107
|
+
|
|
108
|
+
@property
|
|
109
|
+
def is_holding(self) -> bool:
|
|
110
|
+
return self._held_target is not None
|
|
111
|
+
|
|
112
|
+
@property
|
|
113
|
+
def active_target(self) -> np.ndarray:
|
|
114
|
+
return self._held_target if self._held_target is not None else self._target
|
|
115
|
+
|
|
116
|
+
def apply(self) -> None:
|
|
117
|
+
"""Write the camera pose onto the platform for this frame."""
|
|
118
|
+
target = self.active_target
|
|
119
|
+
eye = target + self.offset
|
|
120
|
+
self.platform.setPosition(tuple(eye))
|
|
121
|
+
self.platform.setOrientation(look_at_orientation(eye, target, self.up))
|