Skip to content

Environment ​

SUMMARY

The Environment holds everything a scene can contain: the models, the material and background pools, the lights, and the camera. You fill it with add(), the randomizer decides what each scene does contain, and the generator renders it.

Import ​

python
from telekinesis.illusion import config
from telekinesis.illusion.core.environment import Environment

Constructor ​

python
environment = Environment()                 # or Environment(asset_dir="path/to/assets")
ParameterTypeDefaultDescription
asset_dirstr | Path | NoneNoneBase directory for relative asset paths, such as surface-imperfection maps. None resolves it with resolve_asset_dir() (see Asset directory). Nothing is registered from it automatically.

Constructing an environment resets the process-wide Blender scene, so keep one environment per process. It starts empty: no camera, no lights, no models.

Register Everything with add() ​

Every kind of resource is described by a config from telekinesis.illusion.config and registered the same way:

python
from telekinesis.illusion.utils.assets import resolve_asset_dir

assets = resolve_asset_dir()

environment.add(config.CameraConfig(image_width=640, image_height=480))
environment.add(config.LightConfig("key", "AREA", location=(0.0, 0.0, 1.2), properties={"power": 80.0, "size": 0.4}))
environment.add(config.ModelConfig.from_path(assets / "models/mechanical_parts/gearwheel_1.glb", model_name="gear", category_id=1))
environment.add(config.MaterialConfig.discover(assets / "materials"))   # a list: every material set, grouped by folder
environment.add(config.BackgroundConfig.discover(assets / "hdris"))     # a list: every .hdr/.exr, grouped by folder

add() accepts a single config or any iterable of them, and returns the normalized config (or a list of them). What happens on registration depends on the type:

ConfigOn add()
CameraConfigCreates the camera. Exactly one is allowed; a second raises ValueError.
LightConfigCreates the light immediately. Get it back with get_light(name).
ModelConfigRegisters the model and its annotation category. The mesh is imported later, when the generator prepares the instance pools.
MaterialConfigAdds the material set to the pool. Textures load only when a MaterialRandomizer first picks it.
BackgroundConfigAdds the HDRI to the pool. It is activated only when a BackgroundRandomizer picks it.

Add a camera

There is no default camera. get_camera(), and therefore rendering, raises RuntimeError until a CameraConfig has been added. CameraConfig() with no arguments gives a 720 × 720 camera.

Models ​

python
gear = config.ModelConfig.from_path(
    assets / "models/mechanical_parts/gearwheel_1.glb",
    model_name="gear",           # name used by randomizers; defaults to the file stem
    category_name="gear",        # COCO category; defaults to model_name
    category_id=1,               # defaults to the next free ID
    groups="parts",              # optional selection groups
)
FieldDefaultDescription
model_pathrequired.glb, .gltf, .fbx, .stl, .usd/.usda/.usdc, .obj, .ply or .dae.
model_namefile stemUnique name. Randomizers refer to the model by it.
category_namemodel_nameCOCO category. "distractor" renders the model but leaves it unannotated.
category_idnext free IDCOCO category ID, >= 0. Reusing a category_name reuses its ID.
active_in_simulationFalseWhether physics moves the model. Containers stay False.
collision_shape"CONVEX_HULL"BOX, SPHERE, CAPSULE, CYLINDER, CONE, CONVEX_HULL, MESH or COMPOUND. Use MESH for containers so parts can fall inside.
scale1.0Uniform scale or (x, y, z), all > 0.
preprocess_modelTrueClean up the imported mesh.
shading"FLAT"FLAT, SMOOTH or AUTO_SMOOTH.
material_preprocessing"replace"replace the imported materials or preserve them.
uv_mapping"smart"smart, cube, cylinder or sphere. Use cube for models without UVs that should take texture-based materials.
groups()Selection groups, e.g. "parts" or ["part", "metal_parts"]. A MaterialRandomizer can target models by group.

ModelConfig(...) takes the same fields directly; from_path() just fills in the name from the file.

Materials and backgrounds: discovery and groups ​

discover(root) walks a folder and returns one config per asset it finds. Each asset's groups are its parent folders, relative to root, including every ancestor:

text
assets/hdris/
├── indoor/
│   ├── industrial/boiler_room_1k.exr   → groups ("indoor", "indoor/industrial")
│   └── studio/...                       → groups ("indoor", "indoor/studio")
└── outdoor/day/...                      → groups ("outdoor", "outdoor/day")

A randomizer can then select by group (groups=["indoor"] picks from every indoor HDRI) or by exact name. A material set is a folder containing a <folder name>_Color.png/.jpg texture, plus any other PBR maps in the ambientCG naming scheme.

To register a single asset, or assets that sit directly in the root folder, give the groups yourself:

python
environment.add(config.MaterialConfig.from_path(assets / "materials/metal/Metal019_1K-PNG", groups="metal"))
environment.add(config.BackgroundConfig.discover("my_hdris", group_prefix="factory"))

Names must be unique per type

Two materials, or two backgrounds, with the same name raise ValueError, even when they live in different folders. Pass name= to from_path() to rename one.

Lights ​

python
environment.add(config.LightConfig("key", "AREA", properties={"power": 80.0, "size": 0.4, "shape": "DISK"}))
environment.add(config.LightConfig("sun", "SUN", rotation=(0.6, 0.0, 0.8), properties={"power": 2.0, "angle": 0.05}))

light_type is POINT, SUN, SPOT or AREA. location is in meters and rotation in radians (lights emit along their local −Z). Which properties are valid depends on the type:

PropertyLight typesMeaning
powerallWatts (W/m² for SUN)
colorallLinear RGB, each in [0, 1]
radiusPOINT, SPOTEmitter radius in meters
size, size_yAREAEmitter size in meters (size_y for RECTANGLE/ELLIPSE)
shapeAREASQUARE, RECTANGLE, DISK or ELLIPSE
angleSUNAngular diameter in radians, [0, π]
spot_size, spot_blendSPOTCone angle in radians, and edge softness in [0, 1]

Fixed values here are the starting point; a LightRandomizer and LightPoseRandomizer vary them per scene.

Camera ​

python
environment.add(config.CameraConfig(image_width=820, image_height=640, field_of_view=0.69))
FieldDefaultDescription
image_width, image_height720Output resolution in pixels
focal_lengthNoneLens in mm. Mutually exclusive with field_of_view
field_of_viewNoneHorizontal field of view in radians
clip_start, clip_end0.1, 1000.0Clipping distances in meters
pixel_aspect_x, pixel_aspect_y, shift_x, shift_y1.0, 1.0, 0.0, 0.0Sensor geometry
location, rotationNoneInitial pose, meters and degrees. Usually left to a CameraPoseRandomizer

Asset Directory ​

python
from telekinesis.illusion.utils.assets import resolve_asset_dir

assets = resolve_asset_dir()          # or resolve_asset_dir("path/to/my_assets")

resolve_asset_dir() returns the first of:

  1. the path you pass;
  2. ./assets in the current working directory;
  3. assets/ of a telekinesis-illusion source checkout;
  4. the public example assets, downloaded once (about 180 MB) to ~/.cache/telekinesis/telekinesis-illusion/ and reused afterwards.

The example assets are organized as models/, materials/, hdris/ and surface_imperfections/. Organize your own assets the same way and the snippets on these pages work unchanged.

Read the Environment ​

MethodReturns
get_camera()The Camera. Raises RuntimeError before a camera is added
get_light(name) / get_lights()One Light, or all of them by name
get_categories()The registered annotation categories
get_assets()The registered ModelConfigs by model name
get_models()Every prepared model instance, keyed <model_name>_INSTANCE_<n>
get_model_group(model_name)All instances of one model
get_models_by_name(name)Instances whose name contains name: one Model, or a list
get_visible_model_names()Instance names visible in the current scene
get_background()The live world background
get_asset_dir()The resolved asset directory

The instance accessors return results only after the generator has prepared the environment. Instance pools are sized from the randomizer's maximum counts.

The resource managers are available as environment.model_manager, material_manager, background_manager, light_manager and camera_manager. For example, environment.material_manager.get_names(groups=["metal"]) lists the metal material sets that a randomizer could pick.

Lifecycle ​

You rarely call these directly; SyntheticDataGenerator does:

  • prepare(required_instances) imports the model meshes into fixed-size instance pools. Adding a model after this raises RuntimeError.
  • begin_sample() deactivates every visible instance before the next scene is randomized. Poses and materials are not reset; the randomizer nodes set them again.
  • clean_up() releases the Blender resources. It is safe to call more than once, but the environment cannot be prepared again afterwards.
Configs
Every setting in Illusion is a validated, immutable config. See how they work.
Open configs →