AB4D Forum

Full Version: Dynamically changing the CustomRenderableNode Model transformation
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Related to my question in https://forum.ab4d.com/showthread.php?tid=4169

How can I dynamically change the model transform for a CustomRenderableNode.  For example I have numerous point clouds displayed using CustomRenderableNode, each having an initial transform.

So far I have looked at the ShadedPointCloudSample, where a Transform3D is assigned to the SceneNodeVisual3D, e.g... in AddPointCloudNode()

Code:
var sceneNodeVisual3D = new SceneNodeVisual3D(customRenderableNode);
sceneNodeVisual3D.Transform = transform;

So for each point cloud, I assign the initial 'transform' and this works great.

But later when I want to change the Model transform, I have tried setting 'transform' to be a MatrixTransform3D and changing the Matrix property, and also reassigning the SceneNodVisual3D Transform.

These changes do not seem to propagate through to the RenderAction.

Could you please advise what is the most suitable procedure to control the Model transform used for rendering of the CustomRenderableNode?  Should I be doing this around the example code in RenderAction...

Code:
SharpDX.Matrix worldViewProjectionMatrix = renderingContext.UsedCamera.GetViewProjection();
if (customRenderableNode.Transform != null && !customRenderableNode.Transform.IsIdentity)
    worldViewProjectionMatrix = customRenderableNode.Transform.Value * worldViewProjectionMatrix;

I have had a play around trying to set the customRenderableNode.Transform but the display was completely mangled.  I didn't look into that too deeply in case I was completely going off track.

Also for my understanding, how is the SceneNodeVisual3D Transform applied, is this only used for an initialisation of another Transformation used by the Custom renderer?

Many thanks in advance.
You are right. After the CustomRenderableNode has been rendered, changing its (or parent's) transformation does not have any effect.

The reason for this is that the transformation matrix is written into a constant buffer (used by the shaders) in ApplyMaterial step that is called before RenderAction. The matrix value is read from the CustomRenderablePrimitive object that is created by the CustomRenderableNode and added to the RenderingQueue. The problem with the current version is that the matrix value is read from the transformation only at initialization time and is not updated after that (and the CustomRenderablePrimitive is stored in a private field so you cannot change it from outside).

I have updated the code in CustomRenderableNode so that it correctly updates the transformation value. This fix will be available with the next version (cannot say when it will be released). After this fix you will be able to change the transformation on the CustomRenderableNode or on the parent SceneNodeVisual3D (or any other parent).

Until this fix is available you can use the following workaround (sample code from the updated OptimizedPointCloud sample):
Code:
if (_sceneNodeVisual3D != null)
{
    MainViewport.Children.Remove(_sceneNodeVisual3D);
    _customRenderableNode.Dispose();
}

_counter++;

_customRenderableNode = new CustomRenderableNode(RenderAction, _optimizedPointMesh.Bounds, _optimizedPointMesh, _pixelMaterial);

//_customRenderableNode.Transform = new Ab3d.DirectX.Transformation(Matrix.Translation(0, _counter * 2, 0));
_customRenderableNode.Name = "CustomRenderableNode_" + _counter.ToString();

// Because the _customRenderableNode can be disposed before the whole view is unloaded,
// it should not be added to the _modelDisposables but need to be disposed separately.
//_modelDisposables.Add(_customRenderableNode);

_sceneNodeVisual3D = new SceneNodeVisual3D(_customRenderableNode);
_sceneNodeVisual3D.Transform = new TranslateTransform3D(0, _counter * 2, 0);

MainViewport.Children.Add(_sceneNodeVisual3D);

As you see, you need to create a new CustomRenderableNode and a new SceneNodeVisual3D and set transformation to SceneNodeVisual3D (or to CustomRenderableNode - commented in the sample above). There is no special cost with that solution (except creating 2 new objects on the heap and some fast DXEngine update code because of adding new objects to the scene; no DirectX resources are recreated).