• Intro
  • Transform Provider

Transform provider

By: SKY ENGINE AI
scroll down ↓to find out moretransform-provider_1_resourcesTutorial

TransformProvider

In this section you will get to know how to use TransformProvider.

Agenda:

  • What is TransformProvider?
  • Types of TransformProviders
  • TransformProvider basic usage
  • TransformProvider in scene generation pipeline

What is TransformProvider?

TransformProvider is a class that supply transformation to a SceneNode for every frame in a specific required
manner.
Thanks to TransformProvider you don't have to pass different transformation for each frame and render them
separately - instead, you can pass TransformProvider to a LocusDefinition and have transformation updated based on
the passed provider.

Types of TransformProviders

In SkyRenderer, we distinguish several types of TransformProviders:

  • AlembicTransformProvider - provides transformations from animation written in the alembic file,
  • BallTransformProvider - generates transformations in the ball volume,
  • CameraEulerRotationProvider - generates camera rotations with given yaw-pitch-roll ranges,
  • CircleTransformProvider - generates transformation on the circle circumference,
  • DiscTransformProvider - generates transformations on the disc,
  • SimpleTransformProvider - generates transformations in passed ranges,
  • SphereTransformProvider - generates transformations on the sphere surface,
  • TransformPathProvider - generates transformations on the custom path,
  • TransformMultiProvider - joins multiple transform providers.

Each TransformProvider supply specific behaviour of the node's transformation, e.g. SphereTransformProvider will
generate new random positions on the sphere in each frame.

Scene setup

Let's use custom scene composer to set up the scene.

    from skyrenderer.cases.utils import TransformProviderSceneComposer
    scene_composer = TransformProviderSceneComposer()
    scene_composer.setup_scene(render_width=1400, render_height=900)
2025-02-05 12:17:52,001 | skyrenderer.scene.renderer_context |  INFO: Root paths:
- root path: /dli/skyenvironment/skyrenderer/skyrenderer
- assets path: /dli/mount/assets
- config path: /dli/skyenvironment/skyrenderer/skyrenderer/config
- gpu sources path: /dli/skyenvironment/skyrenderer/skyrenderer/optix_sources/sources
- cache path: /dli/mount/cache
- ptx cache path: compiled_ptx/ptx
- ocio path: ocio_configs/aces_1.2/config.ocio

TransformProvider basic usage

To supply SceneNode with custom TransformProvider, we will add example SimpleTransformProvider as the input to
LocusDefinition.
SimpleTransformProvider allows to configure transformations along specific axes, or planes, or space bounding
boxes, depending on how much arguments are passed into provider. This time, we want to populate object along only
one axis, thus we will pass only translation_range_x parameter.
To see it working, we will render few example renders. Observe how shaderball changes its position according to
the transformation randomization rules specified as TransformProvider.
In the last render we will increase the number of instances to see different values of parameter supplied to every
instance of the object.

    from skyrenderer.basic_types.provider.transform_providers.simple_transform_provider import SimpleTransformProvider
    transform_provider = SimpleTransformProvider(scene_composer.renderer_context, translation_range_x=(-3, 3))
    scene_composer.renderer_context.layout().get_node("shaderball_GEO").modify_locus_definition(
        transform_provider=transform_provider
    )
    for i in range(5):
        scene_composer.visualize(scene_composer.get_render(i))
    scene_composer.renderer_context.layout().get_node("shaderball_GEO").n_instances = 10
    scene_composer.visualize()
transform-provider_1_resourcesTutorial
transform-provider_2_resourcesTutorial
transform-provider_3_resourcesTutorial
transform-provider_4_resourcesTutorial
transform-provider_5_resourcesTutorial
transform-provider_6_resourcesTutorial
2025-02-05 12:17:52,441 | skyrenderer.utils.time_measurement |  INFO: Setup time: 395 ms

2025-02-05 12:17:55,205 | skyrenderer.utils.time_measurement |  INFO: Context update time: 2.76 seconds

2025-02-05 12:17:58,546 | skyrenderer.utils.time_measurement |  INFO: Key points calculation time: 0 ms

2025-02-05 12:17:58,547 | skyrenderer.utils.time_measurement |  INFO: Render time: 3.34 seconds

2025-02-05 12:17:59,049 | skyrenderer.utils.time_measurement |  INFO: Setup time: 65 ms

2025-02-05 12:18:01,917 | skyrenderer.utils.time_measurement |  INFO: Context update time: 2.87 seconds

2025-02-05 12:18:05,224 | skyrenderer.utils.time_measurement |  INFO: Key points calculation time: 0 ms

2025-02-05 12:18:05,225 | skyrenderer.utils.time_measurement |  INFO: Render time: 3.31 seconds

2025-02-05 12:18:05,706 | skyrenderer.utils.time_measurement |  INFO: Setup time: 59 ms

2025-02-05 12:18:08,563 | skyrenderer.utils.time_measurement |  INFO: Context update time: 2.86 seconds

2025-02-05 12:18:11,480 | skyrenderer.utils.time_measurement |  INFO: Key points calculation time: 0 ms

2025-02-05 12:18:11,481 | skyrenderer.utils.time_measurement |  INFO: Render time: 2.92 seconds

2025-02-05 12:18:11,954 | skyrenderer.utils.time_measurement |  INFO: Setup time: 59 ms

2025-02-05 12:18:14,706 | skyrenderer.utils.time_measurement |  INFO: Context update time: 2.75 seconds

2025-02-05 12:18:18,767 | skyrenderer.utils.time_measurement |  INFO: Key points calculation time: 0 ms

2025-02-05 12:18:18,768 | skyrenderer.utils.time_measurement |  INFO: Render time: 4.06 seconds

2025-02-05 12:18:19,252 | skyrenderer.utils.time_measurement |  INFO: Setup time: 59 ms

2025-02-05 12:18:22,196 | skyrenderer.utils.time_measurement |  INFO: Context update time: 2.94 seconds

2025-02-05 12:18:25,854 | skyrenderer.utils.time_measurement |  INFO: Key points calculation time: 0 ms

2025-02-05 12:18:25,855 | skyrenderer.utils.time_measurement |  INFO: Render time: 3.66 seconds

2025-02-05 12:18:26,335 | skyrenderer.utils.time_measurement |  INFO: Setup time: 71 ms

2025-02-05 12:18:29,286 | skyrenderer.utils.time_measurement |  INFO: Context update time: 2.95 seconds

2025-02-05 12:18:33,492 | skyrenderer.utils.time_measurement |  INFO: Key points calculation time: 0 ms

2025-02-05 12:18:33,492 | skyrenderer.utils.time_measurement |  INFO: Render time: 4.21 seconds

TransformProvider in scene generation pipeline

One question that may arise is how the TransformProvider is working with actual transformation of the nodes in the
scene, especially due to the fact that every node has its own transformation.

When we pass TransformProvider to the LocusDefinition from the SceneLayoutNode, on setup it will be passed to
Locus that is stored in SceneNode. On update (that is, before the first render and between every two frames),
SceneNode will be updated. SceneNode will call TransformProvider to receive new transformation, and it will append
provider's transformation to its own.

To check this, we will move shaderball node by 1 unit in the -Z direction. Shaderball instances will be populated
along the X axis on z=-1.

    scene_composer.renderer_context.layout().get_node("shaderball_GEO").translation = [0, 0, -1]
    scene_composer.visualize()
transform-provider_7_resourcesTutorial
2025-02-05 12:18:34,008 | skyrenderer.utils.time_measurement |  INFO: Setup time: 72 ms

2025-02-05 12:18:36,782 | skyrenderer.utils.time_measurement |  INFO: Context update time: 2.77 seconds

2025-02-05 12:18:40,798 | skyrenderer.utils.time_measurement |  INFO: Key points calculation time: 0 ms

2025-02-05 12:18:40,799 | skyrenderer.utils.time_measurement |  INFO: Render time: 4.02 seconds

Summary

In this section you have learnt:

  • TransformProvider is a class that supply transformation to a SceneNode for every frame.
  • There are several types of TransformProviders.
  • TransformProvider is passed to LocusDefinition in SceneLayoutNode.
  • TransformProvider will be applied upon existing transformation of the node.