Transform Path Provider Introduction
In this case you will get familiar with a TransformPathProvider.
Agenda:
- Transform Path Provider introduction
- Initialize a Transform Path provider with a Transform List
- Initialize a Transform Path provider with a Cumulative Transform List
- Create custom Transform Path
Scene setup
Let's use custom scene composer to set up the scene.
Scene consists of:
- shaderballs - locations will be steered by TransformPathProvider
- plane - location: (0, 0, 0)
- camera - location: (7, 7, 7)
from skyrenderer.cases.utils import TransformPathProviderSceneComposer
scene_composer = TransformPathProviderSceneComposer()
scene_composer.setup_scene()
2025-02-05 12:01:46,233 | 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
Transform Path Provider introduction
Transform Path Provider allows objects allocation on a given curve or line, or a custom list of positions.
Simple Transform Provider draws random values within ranges and if we want to achieve a smooth movement effect
we should use Transform Path Provider.
In order to create a Transform Path Provider we will need an implementation of TransformPath class. We can use
predefined classes like TransformList or CumulativeTransformList, or create our own implementation.
Initialize a Transform Path provider with a Transform List
TransformList is a predefined TransformPath that takes a list of transforms as in input.
We can initialize TransformList in 3 ways: providing full transformation matrices, separate
translation/rotation/scale lists or just values describing one of the dimensions.
Provide full transformations
We will create a list of transformation matrices and pass it to constructor.
from skyrenderer.basic_types.transform_path.transform_list import TransformList
from skyrenderer.utils.common import get_transformation_matrix
translations_list = [(0, 0, 2), (0, 0, 1), (0, 0, 0), (0, 0, -1), (0, 0, -2)]
transformation_matrices = [get_transformation_matrix(translation=translation) for translation in translations_list]
transform_list = TransformList(transformation_matrices)
Provide x, y, z translations
transform_list = TransformList.from_translation_rotation_scale(translations_list)
Provide z translations
z_list = [2, 1, 0, -1, -2]
transform_list = TransformList.from_translation_rotation_scale_per_axis(translation_z_list=z_list)
Each of the examples above will have the same effect.
Let's visualize frames 0, 1 and 3 which correspond to the locations defined above.
from skyrenderer.basic_types.provider.transform_providers.transform_path_provider import TransformPathProvider
transform_path_provider = TransformPathProvider(scene_composer.renderer_context, transform_list)
scene_composer.renderer_context.layout().get_node("shaderball_GEO").modify_locus_definition(
transform_provider=transform_path_provider
)
render_dict = {
"Frame 0": scene_composer.get_render(0),
"Frame 1": scene_composer.get_render(1),
"Frame 3": scene_composer.get_render(3),
}
scene_composer.visualize_grid_desc(render_dict, (500, 1500), 3)
2025-02-05 12:01:46,733 | skyrenderer.utils.time_measurement | INFO: Setup time: 435 ms 2025-02-05 12:01:49,448 | skyrenderer.utils.time_measurement | INFO: Context update time: 2.71 seconds 2025-02-05 12:01:51,191 | skyrenderer.utils.time_measurement | INFO: Key points calculation time: 0 ms 2025-02-05 12:01:51,191 | skyrenderer.utils.time_measurement | INFO: Render time: 1.74 seconds 2025-02-05 12:01:51,249 | skyrenderer.utils.time_measurement | INFO: Setup time: 50 ms 2025-02-05 12:01:54,109 | skyrenderer.utils.time_measurement | INFO: Context update time: 2.86 seconds 2025-02-05 12:01:56,364 | skyrenderer.utils.time_measurement | INFO: Key points calculation time: 0 ms 2025-02-05 12:01:56,365 | skyrenderer.utils.time_measurement | INFO: Render time: 2.26 seconds 2025-02-05 12:01:56,416 | skyrenderer.utils.time_measurement | INFO: Setup time: 47 ms 2025-02-05 12:01:59,283 | skyrenderer.utils.time_measurement | INFO: Context update time: 2.87 seconds 2025-02-05 12:02:01,343 | skyrenderer.utils.time_measurement | INFO: Key points calculation time: 0 ms 2025-02-05 12:02:01,344 | skyrenderer.utils.time_measurement | INFO: Render time: 2.06 seconds
Initialize a Transform Path provider with a Cumulative Transform List
We initialized TransformList using a defined locations, in case of CumulativeTransformList we will provide
the changes in transformations that will be accumulated in the next frames.
We will use a list of transformation matrices, but it is also possible to use translation list or a list of
one-dimensional values, like in a previous example.
from skyrenderer.basic_types.transform_path.cumulative_transform_list import CumulativeTransformList
changes_in_translations = [get_transformation_matrix(translation=[0, 0, -1]) for _ in range(5)]
transform_path = CumulativeTransformList(changes_in_translations)
transform_path_provider = TransformPathProvider(scene_composer.renderer_context, transform_path)
scene_composer.renderer_context.layout().get_node("shaderball_GEO").modify_locus_definition(
transform_provider=transform_path_provider
)
render_dict = {
"Cumul: Frame 0": scene_composer.get_render(0),
"Cumul: Frame 1": scene_composer.get_render(1),
"Cumul: Frame 2": scene_composer.get_render(2),
}
scene_composer.visualize_grid_desc(render_dict, (500, 1500), 3)
2025-02-05 12:02:01,766 | skyrenderer.utils.time_measurement | INFO: Setup time: 48 ms 2025-02-05 12:02:04,626 | skyrenderer.utils.time_measurement | INFO: Context update time: 2.86 seconds 2025-02-05 12:02:06,010 | skyrenderer.utils.time_measurement | INFO: Key points calculation time: 0 ms 2025-02-05 12:02:06,011 | skyrenderer.utils.time_measurement | INFO: Render time: 1.38 seconds 2025-02-05 12:02:06,061 | skyrenderer.utils.time_measurement | INFO: Setup time: 46 ms 2025-02-05 12:02:08,922 | skyrenderer.utils.time_measurement | INFO: Context update time: 2.86 seconds 2025-02-05 12:02:11,081 | skyrenderer.utils.time_measurement | INFO: Key points calculation time: 0 ms 2025-02-05 12:02:11,081 | skyrenderer.utils.time_measurement | INFO: Render time: 2.16 seconds 2025-02-05 12:02:11,131 | skyrenderer.utils.time_measurement | INFO: Setup time: 46 ms 2025-02-05 12:02:13,859 | skyrenderer.utils.time_measurement | INFO: Context update time: 2.73 seconds 2025-02-05 12:02:15,957 | skyrenderer.utils.time_measurement | INFO: Key points calculation time: 0 ms 2025-02-05 12:02:15,958 | skyrenderer.utils.time_measurement | INFO: Render time: 2.10 seconds
Create custom Transform Path
We need to create a class that inherits TransformPath and implements 2 methods: __len__(self)
and_get_transform(self, index)
. Index parameter will be limited by the path length. _get_transform
will return
z-axis position equal to the negative index value.
from skyrenderer.basic_types.transform_path.transform_path import TransformPath
class CustomSimpleTransformPath(TransformPath):
def __len__(self):
return 3
def _get_transform(self, index):
return get_transformation_matrix(translation=[0, 0, -index])
custom_path_provider = TransformPathProvider(scene_composer.renderer_context, CustomSimpleTransformPath())
scene_composer.renderer_context.layout().get_node("shaderball_GEO").modify_locus_definition(
transform_provider=custom_path_provider
)
render_dict = {
"Custom - Frame 0": scene_composer.get_render(0),
"Custom - Frame 1": scene_composer.get_render(1),
"Custom - Frame 2": scene_composer.get_render(2),
}
scene_composer.visualize_grid_desc(render_dict, (500, 1500), 3)
2025-02-05 12:02:16,376 | skyrenderer.utils.time_measurement | INFO: Setup time: 47 ms 2025-02-05 12:02:19,302 | skyrenderer.utils.time_measurement | INFO: Context update time: 2.93 seconds 2025-02-05 12:02:20,777 | skyrenderer.utils.time_measurement | INFO: Key points calculation time: 0 ms 2025-02-05 12:02:20,778 | skyrenderer.utils.time_measurement | INFO: Render time: 1.47 seconds 2025-02-05 12:02:20,828 | skyrenderer.utils.time_measurement | INFO: Setup time: 47 ms 2025-02-05 12:02:23,582 | skyrenderer.utils.time_measurement | INFO: Context update time: 2.75 seconds 2025-02-05 12:02:25,690 | skyrenderer.utils.time_measurement | INFO: Key points calculation time: 0 ms 2025-02-05 12:02:25,691 | skyrenderer.utils.time_measurement | INFO: Render time: 2.11 seconds 2025-02-05 12:02:25,742 | skyrenderer.utils.time_measurement | INFO: Setup time: 47 ms 2025-02-05 12:02:28,547 | skyrenderer.utils.time_measurement | INFO: Context update time: 2.80 seconds 2025-02-05 12:02:29,904 | skyrenderer.utils.time_measurement | INFO: Key points calculation time: 0 ms 2025-02-05 12:02:29,906 | skyrenderer.utils.time_measurement | INFO: Render time: 1.36 seconds
If the frame number exceeds 3 (length of the transform_list) we simply loop back to the first transformation
render_dict = {
"Custom - Frame 1": scene_composer.get_render(1),
"Custom - Frame 2": scene_composer.get_render(2),
"Custom - Frame 3": scene_composer.get_render(3),
}
scene_composer.visualize_grid_desc(render_dict, (500, 1500), 3)
2025-02-05 12:02:30,310 | skyrenderer.utils.time_measurement | INFO: Setup time: 48 ms 2025-02-05 12:02:33,196 | skyrenderer.utils.time_measurement | INFO: Context update time: 2.88 seconds 2025-02-05 12:02:34,771 | skyrenderer.utils.time_measurement | INFO: Key points calculation time: 0 ms 2025-02-05 12:02:34,772 | skyrenderer.utils.time_measurement | INFO: Render time: 1.58 seconds 2025-02-05 12:02:34,823 | skyrenderer.utils.time_measurement | INFO: Setup time: 47 ms 2025-02-05 12:02:37,640 | skyrenderer.utils.time_measurement | INFO: Context update time: 2.82 seconds 2025-02-05 12:02:39,682 | skyrenderer.utils.time_measurement | INFO: Key points calculation time: 0 ms 2025-02-05 12:02:39,684 | skyrenderer.utils.time_measurement | INFO: Render time: 2.04 seconds 2025-02-05 12:02:39,735 | skyrenderer.utils.time_measurement | INFO: Setup time: 47 ms 2025-02-05 12:02:42,692 | skyrenderer.utils.time_measurement | INFO: Context update time: 2.96 seconds 2025-02-05 12:02:44,922 | skyrenderer.utils.time_measurement | INFO: Key points calculation time: 0 ms 2025-02-05 12:02:44,922 | skyrenderer.utils.time_measurement | INFO: Render time: 2.23 seconds
Summary
In this section you have learnt:
- We can move objects on a curve or line using Transform Path Provider.
- We can use two predefined transform paths - Transform List or Cumulative Transform List.
- If the predefined classes are not enough, we can create a custom implementation of Transform Path.