miniworld-maze 1.0.0__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.
Potentially problematic release.
This version of miniworld-maze might be problematic. Click here for more details.
- miniworld_maze/__init__.py +37 -0
- miniworld_maze/core/__init__.py +8 -0
- miniworld_maze/core/constants.py +130 -0
- miniworld_maze/core/miniworld_gymnasium/README.md +1 -0
- miniworld_maze/core/miniworld_gymnasium/__init__.py +4 -0
- miniworld_maze/core/miniworld_gymnasium/base_env.py +52 -0
- miniworld_maze/core/miniworld_gymnasium/entities/__init__.py +7 -0
- miniworld_maze/core/miniworld_gymnasium/entities/agent.py +117 -0
- miniworld_maze/core/miniworld_gymnasium/entities/base_entity.py +135 -0
- miniworld_maze/core/miniworld_gymnasium/entities/objects.py +116 -0
- miniworld_maze/core/miniworld_gymnasium/entity_manager.py +358 -0
- miniworld_maze/core/miniworld_gymnasium/envs/__init__.py +3 -0
- miniworld_maze/core/miniworld_gymnasium/math.py +83 -0
- miniworld_maze/core/miniworld_gymnasium/objmesh.py +294 -0
- miniworld_maze/core/miniworld_gymnasium/occlusion_queries.py +97 -0
- miniworld_maze/core/miniworld_gymnasium/opengl.py +21 -0
- miniworld_maze/core/miniworld_gymnasium/params.py +128 -0
- miniworld_maze/core/miniworld_gymnasium/random.py +105 -0
- miniworld_maze/core/miniworld_gymnasium/rendering/__init__.py +7 -0
- miniworld_maze/core/miniworld_gymnasium/rendering/drawing.py +77 -0
- miniworld_maze/core/miniworld_gymnasium/rendering/framebuffer.py +260 -0
- miniworld_maze/core/miniworld_gymnasium/rendering/texture.py +101 -0
- miniworld_maze/core/miniworld_gymnasium/rendering_engine.py +293 -0
- miniworld_maze/core/miniworld_gymnasium/room.py +330 -0
- miniworld_maze/core/miniworld_gymnasium/texture_utils.py +64 -0
- miniworld_maze/core/miniworld_gymnasium/textures/airduct_grate_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/asphalt_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/beanpaste_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/beige_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/black_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/blueberry_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/brick_wall_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/cardboard_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/cardboard_2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/cardboard_3.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/cardboard_4.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/ceiling_tile_noborder_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/ceiling_tiles_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/cinder_blocks_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/cobaltgreen_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/concrete_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/concrete_2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/concrete_3.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/concrete_4.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/concrete_tiles_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/copperred_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/crimson_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/door_doom_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/door_doom_2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/door_garage_red.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/door_garage_white.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/door_steel_brown.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/door_steel_grey.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/door_steel_red.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/drywall_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/floor_tiles_bw_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/floor_tiles_white.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/grass_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/grass_2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/lava_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/lava_2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/lemongrass_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/lightbeige_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/lightcobaltgreen_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/lightgray_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/lightnavyblue_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/lightskyblue_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/lime_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/logo_mila_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/magenta_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/marble_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/marble_2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/metal_grill_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/metal_grill_2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/morningglory_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/navyblue_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/oakbrown_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/orange_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/orchid_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/picket_fence_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/adelaide_hanscom1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/adelaide_hanscom1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/alessandro_allori1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/alessandro_allori1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/alessandro_allori2.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/alessandro_allori2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/alexandre_cabanel1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/alexandre_cabanel1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/alexei_harlamov1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/alexei_harlamov1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/alexey_petrovich_antropov1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/alexey_petrovich_antropov1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/alice_pike_barney1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/alice_pike_barney1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/aman_theodor1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/aman_theodor1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/antonello_messina1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/antonello_messina1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/antonio_herrera_toro1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/antonio_herrera_toro1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/benjamin-constant1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/benjamin-constant1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/benoist_marie-guillemine1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/benoist_marie-guillemine1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/bouguereau_william-adolphe1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/bouguereau_william-adolphe1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/byron1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/byron1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/carl_fredric_breda1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/carl_fredric_breda1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/carl_fredric_breda2.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/carl_fredric_breda2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/cramacj_lucas1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/cramacj_lucas1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/cranach_lucas2.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/cranach_lucas2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/cristobal_rojas1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/cristobal_rojas1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/delacroix_eugene_ferdinand_victor1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/delacroix_eugene_ferdinand_victor1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/domenikos_theotokopoulos1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/domenikos_theotokopoulos1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/edmund_blair_leighton1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/edmund_blair_leighton1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/edmund_blair_leighton2.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/edmund_blair_leighton2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/edwin_longsden_long1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/edwin_longsden_long1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/falero_luis_ricardo1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/falero_luis_ricardo1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/felix_bonfils1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/felix_bonfils1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/francesco_hayez1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/francesco_hayez1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/francisco_goya_lucientes1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/francisco_goya_lucientes1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/francisco_goya_lucientes2.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/francisco_goya_lucientes2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/francisco_zurbaran1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/francisco_zurbaran1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/franz_von_defregger1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/franz_von_defregger1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/franz_von_defregger2.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/franz_von_defregger2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/franz_von_defregger3.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/franz_von_defregger3.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/frederic_westin1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/frederic_westin1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/frederic_yates1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/frederic_yates1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/frederick_leighton1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/frederick_leighton1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/gaston_bussiere1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/gaston_bussiere1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/george_henry_hall1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/george_henry_hall1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/giovanni_battista_tiepolo1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/giovanni_battista_tiepolo1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/giovanni_bellini1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/giovanni_bellini1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/hans_holbein1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/hans_holbein1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/hayez_francesco1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/hayez_francesco1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/henryk_siemiradzki1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/henryk_siemiradzki1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/ilja_jefimowitsch_repin1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/ilja_jefimowitsch_repin1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/james_carrol_beckwith1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/james_carrol_beckwith1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/jean-baptiste-camille_corot1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/jean-baptiste-camille_corot1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/jean-baptiste-camille_corot2.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/jean-baptiste-camille_corot2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/jean-leon_gerome1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/jean-leon_gerome1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/jean-leon_gerome2.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/jean-leon_gerome2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/jean-leon_gerome3.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/jean-leon_gerome3.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/jean-leon_gerome4.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/jean-leon_gerome4.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/john_william_godward1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/john_william_godward1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/john_william_godward2.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/john_william_godward2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/john_william_godward3.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/john_william_godward3.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/julije_klovic1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/julije_klovic1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/juriaen_streek1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/juriaen_streek1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/kiprenskij_orest_adamovic1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/kiprenskij_orest_adamovic1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/konstantin_makovsky1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/konstantin_makovsky1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/lefebvre_jules_joseph1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/lefebvre_jules_joseph1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/leon-francois_comerre1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/leon-francois_comerre1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/leopold_loffler1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/leopold_loffler1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/lewis_john_frederick1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/lewis_john_frederick1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/madrazo_garreta_raimundo1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/madrazo_garreta_raimundo1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/marie_bashkirtseff1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/marie_bashkirtseff1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/moritz_kellerhoven1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/moritz_kellerhoven1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/nathaniel_jocelyn1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/nathaniel_jocelyn1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/nikolai_alexandrowitsch_jaroschenko1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/nikolai_alexandrowitsch_jaroschenko1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/nils_johan_olsson_blommer1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/nils_johan_olsson_blommer1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/paolo_veronese1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/paolo_veronese1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/parmigianino1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/parmigianino1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/paul_cesar_helleu1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/paul_cesar_helleu1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/regnault_henri1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/regnault_henri1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/richard_bergh1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/richard_bergh1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/richard_bergh2.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/richard_bergh2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/robert_dampier1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/robert_dampier1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/robert_lefevre1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/robert_lefevre1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/robert_leopold1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/robert_leopold1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/sichel_nathanael1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/sichel_nathanael1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/svetoslav_roerich1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/svetoslav_roerich1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/velazquez_diego1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/velazquez_diego1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/viktor_vasnetsov1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/viktor_vasnetsov1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/william-adolphe_bouguereau1.license +2 -0
- miniworld_maze/core/miniworld_gymnasium/textures/portraits/william-adolphe_bouguereau1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/realblueberry_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/redbean_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/rock_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/seablue_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/silver_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/skyblue_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/slime_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/stucco_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/sunnyyellow_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/turquoise_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/violet_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/water_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/water_2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/water_3.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/white_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/wood_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/wood_2.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/textures/wood_planks_1.png +0 -0
- miniworld_maze/core/miniworld_gymnasium/unified_env.py +1364 -0
- miniworld_maze/core/miniworld_gymnasium/utils.py +37 -0
- miniworld_maze/core/miniworld_gymnasium/wrappers.py +2 -0
- miniworld_maze/core/observation_types.py +32 -0
- miniworld_maze/environments/__init__.py +16 -0
- miniworld_maze/environments/base_grid_rooms.py +204 -0
- miniworld_maze/environments/factory.py +155 -0
- miniworld_maze/environments/nine_rooms.py +74 -0
- miniworld_maze/environments/spiral_nine_rooms.py +70 -0
- miniworld_maze/environments/twenty_five_rooms.py +122 -0
- miniworld_maze/tools/__init__.py +5 -0
- miniworld_maze/tools/generate_observations.py +199 -0
- miniworld_maze/wrappers/__init__.py +5 -0
- miniworld_maze/wrappers/image_transforms.py +40 -0
- miniworld_maze-1.0.0.dist-info/METADATA +108 -0
- miniworld_maze-1.0.0.dist-info/RECORD +280 -0
- miniworld_maze-1.0.0.dist-info/WHEEL +4 -0
- miniworld_maze-1.0.0.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Centralized rendering system for MiniWorld environments.
|
|
3
|
+
|
|
4
|
+
This module provides a comprehensive rendering architecture that separates
|
|
5
|
+
OpenGL state management from high-level rendering logic, providing better
|
|
6
|
+
maintainability and testability.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from typing import Any, Optional
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
from pyglet.gl import *
|
|
13
|
+
from pyglet.gl.glu import *
|
|
14
|
+
|
|
15
|
+
from ..observation_types import ObservationLevel
|
|
16
|
+
from .rendering.framebuffer import FrameBuffer
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class OpenGLContextManager:
|
|
20
|
+
"""Manage OpenGL state and context switching."""
|
|
21
|
+
|
|
22
|
+
def __init__(self):
|
|
23
|
+
"""Initialize OpenGL context manager."""
|
|
24
|
+
self._saved_state = {}
|
|
25
|
+
|
|
26
|
+
def save_state(self):
|
|
27
|
+
"""Save current OpenGL state."""
|
|
28
|
+
self._saved_state = {
|
|
29
|
+
"viewport": (GLint * 4)(),
|
|
30
|
+
"projection_matrix": (GLfloat * 16)(),
|
|
31
|
+
"modelview_matrix": (GLfloat * 16)(),
|
|
32
|
+
}
|
|
33
|
+
glGetIntegerv(GL_VIEWPORT, self._saved_state["viewport"])
|
|
34
|
+
glGetFloatv(GL_PROJECTION_MATRIX, self._saved_state["projection_matrix"])
|
|
35
|
+
glGetFloatv(GL_MODELVIEW_MATRIX, self._saved_state["modelview_matrix"])
|
|
36
|
+
|
|
37
|
+
def restore_state(self):
|
|
38
|
+
"""Restore previously saved OpenGL state."""
|
|
39
|
+
if self._saved_state:
|
|
40
|
+
glViewport(*self._saved_state["viewport"])
|
|
41
|
+
glMatrixMode(GL_PROJECTION)
|
|
42
|
+
glLoadMatrixf(self._saved_state["projection_matrix"])
|
|
43
|
+
glMatrixMode(GL_MODELVIEW)
|
|
44
|
+
glLoadMatrixf(self._saved_state["modelview_matrix"])
|
|
45
|
+
|
|
46
|
+
def rendering_context(self):
|
|
47
|
+
"""Context manager for safe rendering state management."""
|
|
48
|
+
return RenderingContext(self)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class RenderingContext:
|
|
52
|
+
"""Context manager for OpenGL rendering state."""
|
|
53
|
+
|
|
54
|
+
def __init__(self, context_manager: OpenGLContextManager):
|
|
55
|
+
"""Initialize rendering context with OpenGL context manager."""
|
|
56
|
+
self.context_manager = context_manager
|
|
57
|
+
|
|
58
|
+
def __enter__(self):
|
|
59
|
+
"""Enter rendering context and save OpenGL state."""
|
|
60
|
+
self.context_manager.save_state()
|
|
61
|
+
return self
|
|
62
|
+
|
|
63
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
64
|
+
"""Exit rendering context and restore OpenGL state."""
|
|
65
|
+
self.context_manager.restore_state()
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class FrameBufferManager:
|
|
69
|
+
"""Manage frame buffers and resolution handling."""
|
|
70
|
+
|
|
71
|
+
def __init__(self, obs_width: int, obs_height: int):
|
|
72
|
+
"""Initialize framebuffer manager with default observation dimensions."""
|
|
73
|
+
self.obs_width = obs_width
|
|
74
|
+
self.obs_height = obs_height
|
|
75
|
+
self.frame_buffers = {}
|
|
76
|
+
|
|
77
|
+
def get_or_create_framebuffer(
|
|
78
|
+
self, name: str, width: Optional[int] = None, height: Optional[int] = None
|
|
79
|
+
) -> FrameBuffer:
|
|
80
|
+
"""Get existing framebuffer or create new one."""
|
|
81
|
+
width = width or self.obs_width
|
|
82
|
+
height = height or self.obs_height
|
|
83
|
+
key = (name, width, height)
|
|
84
|
+
|
|
85
|
+
if key not in self.frame_buffers:
|
|
86
|
+
self.frame_buffers[key] = FrameBuffer(width, height)
|
|
87
|
+
|
|
88
|
+
return self.frame_buffers[key]
|
|
89
|
+
|
|
90
|
+
def cleanup(self):
|
|
91
|
+
"""Clean up all frame buffers."""
|
|
92
|
+
for fb in self.frame_buffers.values():
|
|
93
|
+
if hasattr(fb, "cleanup"):
|
|
94
|
+
fb.cleanup()
|
|
95
|
+
self.frame_buffers.clear()
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class CameraSystem:
|
|
99
|
+
"""Handle camera positioning and projection matrices."""
|
|
100
|
+
|
|
101
|
+
def __init__(self):
|
|
102
|
+
"""Initialize camera system with configuration cache."""
|
|
103
|
+
self.camera_configs = {}
|
|
104
|
+
|
|
105
|
+
def get_config(self, obs_level: ObservationLevel, agent: Any) -> dict:
|
|
106
|
+
"""Get camera configuration for observation level."""
|
|
107
|
+
if obs_level == ObservationLevel.FIRST_PERSON:
|
|
108
|
+
return {
|
|
109
|
+
"type": "perspective",
|
|
110
|
+
"position": agent.pos + np.array([0, agent.cam_height, 0]),
|
|
111
|
+
"direction": agent.dir_vec,
|
|
112
|
+
"up": np.array([0, 1, 0]),
|
|
113
|
+
"fov": agent.cam_fov_y,
|
|
114
|
+
}
|
|
115
|
+
elif obs_level in [
|
|
116
|
+
ObservationLevel.TOP_DOWN_PARTIAL,
|
|
117
|
+
ObservationLevel.TOP_DOWN_FULL,
|
|
118
|
+
]:
|
|
119
|
+
return {
|
|
120
|
+
"type": "orthographic",
|
|
121
|
+
"position": agent.pos + np.array([0, 10, 0]), # High above
|
|
122
|
+
"direction": np.array([0, -1, 0]), # Looking down
|
|
123
|
+
"up": np.array([0, 0, -1]), # Z-axis points up in top view
|
|
124
|
+
"bounds": self._calculate_view_bounds(obs_level, agent),
|
|
125
|
+
}
|
|
126
|
+
else:
|
|
127
|
+
raise ValueError(f"Unsupported observation level: {obs_level}")
|
|
128
|
+
|
|
129
|
+
def _calculate_view_bounds(self, obs_level: ObservationLevel, agent: Any) -> dict:
|
|
130
|
+
"""Calculate view bounds for top-down rendering."""
|
|
131
|
+
if obs_level == ObservationLevel.TOP_DOWN_PARTIAL:
|
|
132
|
+
# POMDP view - limited around agent
|
|
133
|
+
view_size = 8.0 # Configurable view size
|
|
134
|
+
return {
|
|
135
|
+
"left": agent.pos[0] - view_size,
|
|
136
|
+
"right": agent.pos[0] + view_size,
|
|
137
|
+
"bottom": agent.pos[2] - view_size,
|
|
138
|
+
"top": agent.pos[2] + view_size,
|
|
139
|
+
}
|
|
140
|
+
else:
|
|
141
|
+
# Full view - would need environment bounds
|
|
142
|
+
return {"left": -20, "right": 20, "bottom": -20, "top": 20}
|
|
143
|
+
|
|
144
|
+
def setup_camera(self, config: dict, frame_buffer: FrameBuffer):
|
|
145
|
+
"""Setup camera projection and view matrices."""
|
|
146
|
+
glMatrixMode(GL_PROJECTION)
|
|
147
|
+
glLoadIdentity()
|
|
148
|
+
|
|
149
|
+
if config["type"] == "perspective":
|
|
150
|
+
aspect_ratio = frame_buffer.width / frame_buffer.height
|
|
151
|
+
# Setup perspective projection
|
|
152
|
+
gluPerspective(config["fov"], aspect_ratio, 0.04, 100.0)
|
|
153
|
+
elif config["type"] == "orthographic":
|
|
154
|
+
bounds = config["bounds"]
|
|
155
|
+
glOrtho(
|
|
156
|
+
bounds["left"],
|
|
157
|
+
bounds["right"],
|
|
158
|
+
bounds["bottom"],
|
|
159
|
+
bounds["top"],
|
|
160
|
+
0.01,
|
|
161
|
+
100.0,
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
glMatrixMode(GL_MODELVIEW)
|
|
165
|
+
glLoadIdentity()
|
|
166
|
+
|
|
167
|
+
# Setup view matrix
|
|
168
|
+
pos = config["position"]
|
|
169
|
+
direction = config["direction"]
|
|
170
|
+
up = config["up"]
|
|
171
|
+
target = pos + direction
|
|
172
|
+
|
|
173
|
+
gluLookAt(
|
|
174
|
+
pos[0], pos[1], pos[2], target[0], target[1], target[2], up[0], up[1], up[2]
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
class RenderingEngine:
|
|
179
|
+
"""Centralized rendering system for MiniWorld environments."""
|
|
180
|
+
|
|
181
|
+
def __init__(self, obs_width: int, obs_height: int):
|
|
182
|
+
"""Initialize rendering engine with all subsystems."""
|
|
183
|
+
self.context_manager = OpenGLContextManager()
|
|
184
|
+
self.framebuffer_manager = FrameBufferManager(obs_width, obs_height)
|
|
185
|
+
self.camera_system = CameraSystem()
|
|
186
|
+
|
|
187
|
+
self.obs_width = obs_width
|
|
188
|
+
self.obs_height = obs_height
|
|
189
|
+
|
|
190
|
+
def render_observation(
|
|
191
|
+
self,
|
|
192
|
+
obs_level: ObservationLevel,
|
|
193
|
+
agent: Any,
|
|
194
|
+
entities: list,
|
|
195
|
+
rooms: list,
|
|
196
|
+
frame_buffer: Optional[FrameBuffer] = None,
|
|
197
|
+
) -> np.ndarray:
|
|
198
|
+
"""Unified observation rendering."""
|
|
199
|
+
if frame_buffer is None:
|
|
200
|
+
frame_buffer = self.framebuffer_manager.get_or_create_framebuffer("obs")
|
|
201
|
+
|
|
202
|
+
camera_config = self.camera_system.get_config(obs_level, agent)
|
|
203
|
+
|
|
204
|
+
with self.context_manager.rendering_context():
|
|
205
|
+
frame_buffer.bind()
|
|
206
|
+
self.camera_system.setup_camera(camera_config, frame_buffer)
|
|
207
|
+
self._setup_scene()
|
|
208
|
+
self._render_entities_and_rooms(
|
|
209
|
+
entities,
|
|
210
|
+
rooms,
|
|
211
|
+
agent,
|
|
212
|
+
render_agent=(obs_level != ObservationLevel.FIRST_PERSON),
|
|
213
|
+
)
|
|
214
|
+
img = frame_buffer.resolve()
|
|
215
|
+
|
|
216
|
+
return img
|
|
217
|
+
|
|
218
|
+
def render_top_view(
|
|
219
|
+
self,
|
|
220
|
+
agent: Any,
|
|
221
|
+
entities: list,
|
|
222
|
+
rooms: list,
|
|
223
|
+
POMDP: bool = False,
|
|
224
|
+
render_agent: bool = True,
|
|
225
|
+
frame_buffer: Optional[FrameBuffer] = None,
|
|
226
|
+
) -> np.ndarray:
|
|
227
|
+
"""Render top-down view of the environment."""
|
|
228
|
+
if frame_buffer is None:
|
|
229
|
+
frame_buffer = self.framebuffer_manager.get_or_create_framebuffer("topview")
|
|
230
|
+
|
|
231
|
+
obs_level = (
|
|
232
|
+
ObservationLevel.TOP_DOWN_PARTIAL
|
|
233
|
+
if POMDP
|
|
234
|
+
else ObservationLevel.TOP_DOWN_FULL
|
|
235
|
+
)
|
|
236
|
+
camera_config = self.camera_system.get_config(obs_level, agent)
|
|
237
|
+
|
|
238
|
+
with self.context_manager.rendering_context():
|
|
239
|
+
frame_buffer.bind()
|
|
240
|
+
self.camera_system.setup_camera(camera_config, frame_buffer)
|
|
241
|
+
self._setup_scene()
|
|
242
|
+
self._render_entities_and_rooms(entities, rooms, agent, render_agent)
|
|
243
|
+
img = frame_buffer.resolve()
|
|
244
|
+
|
|
245
|
+
return img
|
|
246
|
+
|
|
247
|
+
def _setup_scene(self):
|
|
248
|
+
"""Setup basic OpenGL scene state."""
|
|
249
|
+
# Clear buffers
|
|
250
|
+
glClearColor(0.8, 0.9, 1.0, 1.0) # Light blue background
|
|
251
|
+
glClearDepth(1.0)
|
|
252
|
+
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
|
|
253
|
+
|
|
254
|
+
# Enable depth testing
|
|
255
|
+
glEnable(GL_DEPTH_TEST)
|
|
256
|
+
glDepthFunc(GL_LESS)
|
|
257
|
+
|
|
258
|
+
# Enable face culling
|
|
259
|
+
glEnable(GL_CULL_FACE)
|
|
260
|
+
glCullFace(GL_BACK)
|
|
261
|
+
glFrontFace(GL_CCW)
|
|
262
|
+
|
|
263
|
+
# Setup lighting (basic ambient light)
|
|
264
|
+
glEnable(GL_LIGHTING)
|
|
265
|
+
glEnable(GL_LIGHT0)
|
|
266
|
+
|
|
267
|
+
light_pos = (GLfloat * 4)(10.0, 10.0, 10.0, 1.0)
|
|
268
|
+
light_ambient = (GLfloat * 4)(0.2, 0.2, 0.2, 1.0)
|
|
269
|
+
light_diffuse = (GLfloat * 4)(0.8, 0.8, 0.8, 1.0)
|
|
270
|
+
|
|
271
|
+
glLightfv(GL_LIGHT0, GL_POSITION, light_pos)
|
|
272
|
+
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient)
|
|
273
|
+
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse)
|
|
274
|
+
|
|
275
|
+
def _render_entities_and_rooms(
|
|
276
|
+
self, entities: list, rooms: list, agent: Any, render_agent: bool = True
|
|
277
|
+
):
|
|
278
|
+
"""Render all entities and rooms in the scene."""
|
|
279
|
+
# Render rooms first (floors, walls, ceilings)
|
|
280
|
+
for room in rooms:
|
|
281
|
+
if hasattr(room, "_render"):
|
|
282
|
+
room._render()
|
|
283
|
+
|
|
284
|
+
# Render entities
|
|
285
|
+
for entity in entities:
|
|
286
|
+
if entity is agent and not render_agent:
|
|
287
|
+
continue
|
|
288
|
+
if hasattr(entity, "render"):
|
|
289
|
+
entity.render()
|
|
290
|
+
|
|
291
|
+
def cleanup(self):
|
|
292
|
+
"""Clean up rendering resources."""
|
|
293
|
+
self.framebuffer_manager.cleanup()
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
"""Room class for MiniWorld environments."""
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
from pyglet.gl import *
|
|
5
|
+
|
|
6
|
+
from .math import Y_VEC
|
|
7
|
+
from .opengl import Texture
|
|
8
|
+
from .texture_utils import gen_texcs_floor, gen_texcs_wall
|
|
9
|
+
|
|
10
|
+
# Default wall height for room
|
|
11
|
+
DEFAULT_WALL_HEIGHT = 2.74
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Room:
|
|
15
|
+
"""Represent an individual room and its contents"""
|
|
16
|
+
|
|
17
|
+
def __init__(
|
|
18
|
+
self,
|
|
19
|
+
outline,
|
|
20
|
+
wall_height=DEFAULT_WALL_HEIGHT,
|
|
21
|
+
floor_tex="floor_tiles_bw",
|
|
22
|
+
wall_tex="concrete",
|
|
23
|
+
ceil_tex="concrete_tiles",
|
|
24
|
+
no_ceiling=False,
|
|
25
|
+
):
|
|
26
|
+
# The outlien should have shape Nx2
|
|
27
|
+
assert len(outline.shape) == 2
|
|
28
|
+
assert outline.shape[1] == 2
|
|
29
|
+
assert outline.shape[0] >= 3
|
|
30
|
+
|
|
31
|
+
# Add a Y coordinate to the outline points
|
|
32
|
+
outline = np.insert(outline, 1, 0, axis=1)
|
|
33
|
+
|
|
34
|
+
# Number of outline vertices / walls
|
|
35
|
+
self.num_walls = outline.shape[0]
|
|
36
|
+
|
|
37
|
+
# List of 2D points forming the outline of the room
|
|
38
|
+
# Shape is Nx3
|
|
39
|
+
self.outline = outline
|
|
40
|
+
|
|
41
|
+
# Compute the min and max x, z extents
|
|
42
|
+
self.min_x = self.outline[:, 0].min()
|
|
43
|
+
self.max_x = self.outline[:, 0].max()
|
|
44
|
+
self.min_z = self.outline[:, 2].min()
|
|
45
|
+
self.max_z = self.outline[:, 2].max()
|
|
46
|
+
|
|
47
|
+
# Compute midpoint coordinates
|
|
48
|
+
self.mid_x = (self.max_x + self.min_x) / 2
|
|
49
|
+
self.mid_z = (self.max_z + self.min_z) / 2
|
|
50
|
+
|
|
51
|
+
# Compute approximate surface area
|
|
52
|
+
self.area = (self.max_x - self.min_x) * (self.max_z - self.min_z)
|
|
53
|
+
|
|
54
|
+
# Compute room edge directions and normals
|
|
55
|
+
# Compute edge vectors (p1 - p0)
|
|
56
|
+
# For the first point, p0 is the last
|
|
57
|
+
# For the last point, p0 is p_n-1
|
|
58
|
+
next_pts = np.concatenate(
|
|
59
|
+
[self.outline[1:], np.expand_dims(self.outline[0], axis=0)], axis=0
|
|
60
|
+
)
|
|
61
|
+
self.edge_dirs = next_pts - self.outline
|
|
62
|
+
self.edge_dirs = (self.edge_dirs.T / np.linalg.norm(self.edge_dirs, axis=1)).T
|
|
63
|
+
self.edge_norms = -np.cross(self.edge_dirs, Y_VEC)
|
|
64
|
+
self.edge_norms = (
|
|
65
|
+
self.edge_norms.T / np.linalg.norm(self.edge_norms, axis=1)
|
|
66
|
+
).T
|
|
67
|
+
|
|
68
|
+
# Height of the room walls
|
|
69
|
+
self.wall_height = wall_height
|
|
70
|
+
|
|
71
|
+
# No ceiling flag
|
|
72
|
+
self.no_ceiling = no_ceiling
|
|
73
|
+
|
|
74
|
+
# Texture names
|
|
75
|
+
self.wall_tex_name = wall_tex
|
|
76
|
+
self.floor_tex_name = floor_tex
|
|
77
|
+
self.ceil_tex_name = ceil_tex
|
|
78
|
+
|
|
79
|
+
# Lists of portals, indexed by wall/edge index
|
|
80
|
+
self.portals = [[] for i in range(self.num_walls)]
|
|
81
|
+
|
|
82
|
+
# List of neighbor rooms
|
|
83
|
+
# Same length as list of portals
|
|
84
|
+
self.neighbors = []
|
|
85
|
+
|
|
86
|
+
def add_portal(
|
|
87
|
+
self,
|
|
88
|
+
edge,
|
|
89
|
+
start_pos=None,
|
|
90
|
+
end_pos=None,
|
|
91
|
+
min_x=None,
|
|
92
|
+
max_x=None,
|
|
93
|
+
min_z=None,
|
|
94
|
+
max_z=None,
|
|
95
|
+
min_y=0,
|
|
96
|
+
max_y=None,
|
|
97
|
+
):
|
|
98
|
+
"""Create a new portal/opening in a wall of this room"""
|
|
99
|
+
|
|
100
|
+
if max_y is None:
|
|
101
|
+
max_y = self.wall_height
|
|
102
|
+
|
|
103
|
+
assert edge <= self.num_walls
|
|
104
|
+
assert max_y > min_y
|
|
105
|
+
|
|
106
|
+
# Get the edge points, compute the direction vector
|
|
107
|
+
e_p0 = self.outline[edge]
|
|
108
|
+
e_p1 = self.outline[(edge + 1) % self.num_walls]
|
|
109
|
+
e_len = np.linalg.norm(e_p1 - e_p0)
|
|
110
|
+
e_dir = (e_p1 - e_p0) / e_len
|
|
111
|
+
x0, _, z0 = e_p0
|
|
112
|
+
x1, _, z1 = e_p1
|
|
113
|
+
dx, _, dz = e_dir
|
|
114
|
+
|
|
115
|
+
# If the portal extents are specified by x coordinates
|
|
116
|
+
if min_x is not None:
|
|
117
|
+
assert min_z is None and max_z is None
|
|
118
|
+
assert start_pos is None and end_pos is None
|
|
119
|
+
assert x0 != x1
|
|
120
|
+
|
|
121
|
+
m0 = (min_x - x0) / dx
|
|
122
|
+
m1 = (max_x - x0) / dx
|
|
123
|
+
|
|
124
|
+
if m1 < m0:
|
|
125
|
+
m0, m1 = m1, m0
|
|
126
|
+
|
|
127
|
+
start_pos, end_pos = m0, m1
|
|
128
|
+
|
|
129
|
+
# If the portal extents are specified by z coordinates
|
|
130
|
+
elif min_z is not None:
|
|
131
|
+
assert min_x is None and max_x is None
|
|
132
|
+
assert start_pos is None and end_pos is None
|
|
133
|
+
assert z0 != z1
|
|
134
|
+
|
|
135
|
+
m0 = (min_z - z0) / dz
|
|
136
|
+
m1 = (max_z - z0) / dz
|
|
137
|
+
|
|
138
|
+
if m1 < m0:
|
|
139
|
+
m0, m1 = m1, m0
|
|
140
|
+
|
|
141
|
+
start_pos, end_pos = m0, m1
|
|
142
|
+
|
|
143
|
+
else:
|
|
144
|
+
assert min_x is None and max_x is None
|
|
145
|
+
assert min_z is None and max_z is None
|
|
146
|
+
|
|
147
|
+
assert end_pos > start_pos
|
|
148
|
+
assert start_pos >= 0, "portal outside of wall extents"
|
|
149
|
+
assert end_pos <= e_len, "portal outside of wall extents"
|
|
150
|
+
|
|
151
|
+
self.portals[edge].append(
|
|
152
|
+
{"start_pos": start_pos, "end_pos": end_pos, "min_y": min_y, "max_y": max_y}
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# Sort the portals by start position
|
|
156
|
+
self.portals[edge].sort(key=lambda e: e["start_pos"])
|
|
157
|
+
|
|
158
|
+
return start_pos, end_pos
|
|
159
|
+
|
|
160
|
+
def point_inside(self, p):
|
|
161
|
+
"""Test if a point is inside the room"""
|
|
162
|
+
|
|
163
|
+
# Vector from edge start to test point
|
|
164
|
+
ap = p - self.outline
|
|
165
|
+
|
|
166
|
+
# Compute the dot products of normals to AP vectors
|
|
167
|
+
dotNAP = np.sum(self.edge_norms * ap, axis=1)
|
|
168
|
+
|
|
169
|
+
# The point is inside if all the dot products are greater than zero
|
|
170
|
+
return np.all(np.greater(dotNAP, 0))
|
|
171
|
+
|
|
172
|
+
def _gen_static_data(self, params, rng):
|
|
173
|
+
"""Generate polygons and static data for this room
|
|
174
|
+
|
|
175
|
+
Needed for rendering and collision detection
|
|
176
|
+
Note: the wall polygons are quads, but the floor and
|
|
177
|
+
ceiling can be arbitrary n-gons
|
|
178
|
+
"""
|
|
179
|
+
self._load_textures(rng)
|
|
180
|
+
self._generate_floor_geometry()
|
|
181
|
+
self._generate_ceiling_geometry()
|
|
182
|
+
self._generate_wall_geometry()
|
|
183
|
+
self._finalize_wall_geometry()
|
|
184
|
+
|
|
185
|
+
def _load_textures(self, rng):
|
|
186
|
+
"""Load and randomize room textures."""
|
|
187
|
+
self.wall_tex = Texture.get(self.wall_tex_name, rng)
|
|
188
|
+
self.floor_tex = Texture.get(self.floor_tex_name, rng)
|
|
189
|
+
self.ceil_tex = Texture.get(self.ceil_tex_name, rng)
|
|
190
|
+
|
|
191
|
+
def _generate_floor_geometry(self):
|
|
192
|
+
"""Generate floor vertices and texture coordinates."""
|
|
193
|
+
self.floor_verts = self.outline
|
|
194
|
+
self.floor_texcs = gen_texcs_floor(self.floor_tex, self.floor_verts)
|
|
195
|
+
|
|
196
|
+
def _generate_ceiling_geometry(self):
|
|
197
|
+
"""Generate ceiling vertices and texture coordinates."""
|
|
198
|
+
# Flip the ceiling vertex order because of backface culling
|
|
199
|
+
self.ceil_verts = np.flip(self.outline, axis=0) + self.wall_height * Y_VEC
|
|
200
|
+
self.ceil_texcs = gen_texcs_floor(self.ceil_tex, self.ceil_verts)
|
|
201
|
+
|
|
202
|
+
def _generate_wall_geometry(self):
|
|
203
|
+
"""Generate wall vertices, normals, texture coordinates, and collision segments."""
|
|
204
|
+
self.wall_verts = []
|
|
205
|
+
self.wall_norms = []
|
|
206
|
+
self.wall_texcs = []
|
|
207
|
+
self.wall_segs = []
|
|
208
|
+
|
|
209
|
+
def gen_seg_poly(edge_p0, side_vec, seg_start, seg_end, min_y, max_y):
|
|
210
|
+
if seg_end == seg_start:
|
|
211
|
+
return
|
|
212
|
+
|
|
213
|
+
if min_y == max_y:
|
|
214
|
+
return
|
|
215
|
+
|
|
216
|
+
s_p0 = edge_p0 + seg_start * side_vec
|
|
217
|
+
s_p1 = edge_p0 + seg_end * side_vec
|
|
218
|
+
|
|
219
|
+
# If this polygon starts at ground level, add a collidable segment
|
|
220
|
+
if min_y == 0:
|
|
221
|
+
self.wall_segs.append(np.array([s_p1, s_p0]))
|
|
222
|
+
|
|
223
|
+
# Generate the vertices
|
|
224
|
+
# Vertices are listed in counter-clockwise order
|
|
225
|
+
self.wall_verts.append(s_p0 + min_y * Y_VEC)
|
|
226
|
+
self.wall_verts.append(s_p0 + max_y * Y_VEC)
|
|
227
|
+
self.wall_verts.append(s_p1 + max_y * Y_VEC)
|
|
228
|
+
self.wall_verts.append(s_p1 + min_y * Y_VEC)
|
|
229
|
+
|
|
230
|
+
# Compute the normal for the polygon
|
|
231
|
+
normal = np.cross(s_p1 - s_p0, Y_VEC)
|
|
232
|
+
normal = -normal / np.linalg.norm(normal)
|
|
233
|
+
for i in range(4):
|
|
234
|
+
self.wall_norms.append(normal)
|
|
235
|
+
|
|
236
|
+
# Generate the texture coordinates
|
|
237
|
+
texcs = gen_texcs_wall(
|
|
238
|
+
self.wall_tex, seg_start, min_y, seg_end - seg_start, max_y - min_y
|
|
239
|
+
)
|
|
240
|
+
self.wall_texcs.append(texcs)
|
|
241
|
+
|
|
242
|
+
# For each wall
|
|
243
|
+
for wall_idx in range(self.num_walls):
|
|
244
|
+
edge_p0 = self.outline[wall_idx, :]
|
|
245
|
+
edge_p1 = self.outline[(wall_idx + 1) % self.num_walls, :]
|
|
246
|
+
wall_width = np.linalg.norm(edge_p1 - edge_p0)
|
|
247
|
+
side_vec = (edge_p1 - edge_p0) / wall_width
|
|
248
|
+
|
|
249
|
+
if len(self.portals[wall_idx]) > 0:
|
|
250
|
+
seg_end = self.portals[wall_idx][0]["start_pos"]
|
|
251
|
+
else:
|
|
252
|
+
seg_end = wall_width
|
|
253
|
+
|
|
254
|
+
# Generate the first polygon (going up to the first portal)
|
|
255
|
+
gen_seg_poly(edge_p0, side_vec, 0, seg_end, 0, self.wall_height)
|
|
256
|
+
|
|
257
|
+
# For each portal in this wall
|
|
258
|
+
for portal_idx, portal in enumerate(self.portals[wall_idx]):
|
|
259
|
+
portal = self.portals[wall_idx][portal_idx]
|
|
260
|
+
start_pos = portal["start_pos"]
|
|
261
|
+
end_pos = portal["end_pos"]
|
|
262
|
+
min_y = portal["min_y"]
|
|
263
|
+
max_y = portal["max_y"]
|
|
264
|
+
|
|
265
|
+
# Generate the bottom polygon
|
|
266
|
+
gen_seg_poly(edge_p0, side_vec, start_pos, end_pos, 0, min_y)
|
|
267
|
+
|
|
268
|
+
# Generate the top polygon
|
|
269
|
+
gen_seg_poly(
|
|
270
|
+
edge_p0, side_vec, start_pos, end_pos, max_y, self.wall_height
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
if portal_idx < len(self.portals[wall_idx]) - 1:
|
|
274
|
+
next_portal = self.portals[wall_idx][portal_idx + 1]
|
|
275
|
+
next_portal_start = next_portal["start_pos"]
|
|
276
|
+
else:
|
|
277
|
+
next_portal_start = wall_width
|
|
278
|
+
|
|
279
|
+
# Generate the polygon going up to the next portal
|
|
280
|
+
gen_seg_poly(
|
|
281
|
+
edge_p0, side_vec, end_pos, next_portal_start, 0, self.wall_height
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
def _finalize_wall_geometry(self):
|
|
285
|
+
"""Convert wall geometry lists to numpy arrays."""
|
|
286
|
+
self.wall_verts = np.array(self.wall_verts)
|
|
287
|
+
self.wall_norms = np.array(self.wall_norms)
|
|
288
|
+
|
|
289
|
+
if len(self.wall_segs) > 0:
|
|
290
|
+
self.wall_segs = np.array(self.wall_segs)
|
|
291
|
+
else:
|
|
292
|
+
self.wall_segs = np.array([]).reshape(0, 2, 3)
|
|
293
|
+
|
|
294
|
+
if len(self.wall_texcs) > 0:
|
|
295
|
+
self.wall_texcs = np.concatenate(self.wall_texcs)
|
|
296
|
+
else:
|
|
297
|
+
self.wall_texcs = np.array([]).reshape(0, 2)
|
|
298
|
+
|
|
299
|
+
def _render(self):
|
|
300
|
+
"""Render the static elements of the room"""
|
|
301
|
+
|
|
302
|
+
glColor3f(1, 1, 1)
|
|
303
|
+
|
|
304
|
+
# Draw the floor
|
|
305
|
+
self.floor_tex.bind()
|
|
306
|
+
glBegin(GL_POLYGON)
|
|
307
|
+
glNormal3f(0, 1, 0)
|
|
308
|
+
for i in range(self.floor_verts.shape[0]):
|
|
309
|
+
glTexCoord2f(*self.floor_texcs[i, :])
|
|
310
|
+
glVertex3f(*self.floor_verts[i, :])
|
|
311
|
+
glEnd()
|
|
312
|
+
|
|
313
|
+
# Draw the ceiling
|
|
314
|
+
if not self.no_ceiling:
|
|
315
|
+
self.ceil_tex.bind()
|
|
316
|
+
glBegin(GL_POLYGON)
|
|
317
|
+
glNormal3f(0, -1, 0)
|
|
318
|
+
for i in range(self.ceil_verts.shape[0]):
|
|
319
|
+
glTexCoord2f(*self.ceil_texcs[i, :])
|
|
320
|
+
glVertex3f(*self.ceil_verts[i, :])
|
|
321
|
+
glEnd()
|
|
322
|
+
|
|
323
|
+
# Draw the walls
|
|
324
|
+
self.wall_tex.bind()
|
|
325
|
+
glBegin(GL_QUADS)
|
|
326
|
+
for i in range(self.wall_verts.shape[0]):
|
|
327
|
+
glNormal3f(*self.wall_norms[i, :])
|
|
328
|
+
glTexCoord2f(*self.wall_texcs[i, :])
|
|
329
|
+
glVertex3f(*self.wall_verts[i, :])
|
|
330
|
+
glEnd()
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""Texture utility functions for MiniWorld environments."""
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
# Texture size/density in texels/meter
|
|
6
|
+
TEX_DENSITY = 512
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def gen_texcs_wall(tex, min_x, min_y, width, height):
|
|
10
|
+
"""
|
|
11
|
+
Generate texture coordinates for a wall quad.
|
|
12
|
+
|
|
13
|
+
Maps wall surface dimensions to texture coordinates based on texture density.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
tex: Texture object with width/height properties
|
|
17
|
+
min_x (float): Minimum x coordinate of wall surface
|
|
18
|
+
min_y (float): Minimum y coordinate of wall surface
|
|
19
|
+
width (float): Width of wall surface
|
|
20
|
+
height (float): Height of wall surface
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
np.ndarray: 4x2 array of texture coordinates for wall quad vertices
|
|
24
|
+
"""
|
|
25
|
+
xc = TEX_DENSITY / tex.width
|
|
26
|
+
yc = TEX_DENSITY / tex.height
|
|
27
|
+
|
|
28
|
+
min_u = (min_x) * xc
|
|
29
|
+
max_u = (min_x + width) * xc
|
|
30
|
+
min_v = (min_y) * yc
|
|
31
|
+
max_v = (min_y + height) * yc
|
|
32
|
+
|
|
33
|
+
return np.array(
|
|
34
|
+
[
|
|
35
|
+
[min_u, min_v],
|
|
36
|
+
[min_u, max_v],
|
|
37
|
+
[max_u, max_v],
|
|
38
|
+
[max_u, min_v],
|
|
39
|
+
],
|
|
40
|
+
dtype=np.float32,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def gen_texcs_floor(tex, poss):
|
|
45
|
+
"""
|
|
46
|
+
Generate texture coordinates for floor or ceiling surfaces.
|
|
47
|
+
|
|
48
|
+
Maps 3D world positions directly to 2D texture coordinates by projecting
|
|
49
|
+
x,z coordinates onto texture space using texture density scaling.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
tex: Texture object with width/height properties
|
|
53
|
+
poss (np.ndarray): Nx3 array of 3D world positions
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
np.ndarray: Nx2 array of texture coordinates
|
|
57
|
+
"""
|
|
58
|
+
texc_mul = np.array(
|
|
59
|
+
[TEX_DENSITY / tex.width, TEX_DENSITY / tex.height], dtype=float
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
coords = np.stack([poss[:, 0], poss[:, 2]], axis=1) * texc_mul
|
|
63
|
+
|
|
64
|
+
return coords
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|