# AB4D Forum

Full Version: Get Rotation Values of Childgeometry
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hello,

Assuming I have 4 ModelVisual3D objects. And those objects are children of each other.
E.g. A is the root object, B is the children of A, C is the children of B and D is the children of C.
Now I rotate A around the X-Axis, B around the Y-Axis and C around the z-Axis.

Is there a AB4D Function or Method I can use which tells me how D is rotated? I need the values to rotate D back in its standard orientation, as if it was not a children of any of the parent objects.

Best Regards,
Nick
You can get the combined transformation of the final ModelVisual3D with using Ab3d.Utilities.TransformationsHelper.GetVisual3DTotalTransform and pass A and D objects to the method - this will get you one Transform3DGroup with all transformations from A to D.

If you know that you will only get RotateTransform3D objects in the Transform3DGroup, you can read the rotations from them.

But to use any transformation, you can read the Value property of the returned Transform3D - this will give you the total transformation Matrix3D.

To get the transformation that will cancel the parent transformations, you need to inverse this matrix.
You can do this by saving the Matrix3D to local matrix variable and then calling Inverse method on the matrix.

For the inverse matrix, you can create a new Matrix3DTransform and use the new matrix for it.

I had a look into the online "Ab3d.PowerToys reference help" for the TransformationHelper, but I can only find a Method "GetModelTotalTransform(...)" which would use Model3Ds.
I know that every ModelVisual3D have a Model3D as Content. But I have alle transformation applied to the ModelVisual3D.
When I tried to use the "GetModelTotalTransform(...)" Method with the Contents of the ModelVisual3Ds I didn't got a useful output. Maybe it is because we apply all transformation to the ModelVisual3D, so the "GetModelTotalTransform(...)" Method only adds all Transformations of the Model3Ds.

A "GetVisual3DTotalTransform(...)" Method sounds promising, is this maybe in a new version of the Ab3D framework available and I have an old version?

Best regards,
Nick
Uh, yes the GetVisual3DTotalTransform method is only part of the latest development version - it will be available with the next version.

Here is its source code:

Code:
```       /// <summary>        /// GetVisual3DTotalTransform returns a Transform3D that contains all the transformations from the Viewport3D to the finalVisual3D.        /// If no transformation is found, then null is returned.        /// The isVisual3DConnected out parameter is set to false, when the Viewport3D is not reached from the finalVisual3D.        /// </summary>        /// <remarks>        /// <para>        /// <b>GetModelTotalTransform</b> returns a Transform3D that contains all the transformations from the Viewport3D to the finalVisual3D.        /// </para>        /// <para>        /// If no transformation is found, then null is returned.        /// </para>        /// <para>        /// The isVisual3DConnected out parameter is set to false, when the Viewport3D is not reached from the finalVisual3D.        /// </para>        /// <para>        /// GetVisual3DTotalTransform can be used when we want to get the transformation of a Visual3D that is inside a hierarchy of other Visual3D objects.        /// </para>        /// <para>        /// This method is the same as <see cref="GetVisual3DTotalTransform(Visual3D, Visual3D, bool, out bool)"/> is called with first parameter (rootVisual3D) set to null.        /// </para>        /// </remarks>        /// <param name="finalVisual3D">The Visual3D object for witch the Transform3D is created</param>        /// <param name="addFinalVisualTransformation">if true then the returned Transform3D also contains the transform of the finalVisual3D</param>        /// <param name="isVisual3DConnected">out Boolean parameter that is set to true, when finalVisual3D is connected to the rootVisual3D or Viewport3D; false when finalVisual3D is not reached from the finalVisual3D or Viewport3D.</param>        /// <returns>Transform3D or null if no transformation is found</returns>        public static Transform3D GetVisual3DTotalTransform(Visual3D finalVisual3D, bool addFinalVisualTransformation, out bool isVisual3DConnected)        {            return GetVisual3DTotalTransform(null, finalVisual3D, addFinalVisualTransformation, out isVisual3DConnected);        }        /// <summary>        /// GetVisual3DTotalTransform returns a Transform3D that contains all the transformations from the rootVisual3D to the finalVisual3D.        /// When rootVisual3D is null, then transformation from Viewport3D to the finalVisual3D is returned.        /// If no transformation is found, then null is returned.        /// The isVisual3DConnected out parameter is set to false, when the rootVisual3D or Viewport3D is not reached from the finalVisual3D.        /// </summary>        /// <remarks>        /// <para>        /// <b>GetModelTotalTransform</b> returns a Transform3D that contains all the transformations from the rootVisual3D to the finalVisual3D.        /// When rootVisual3D is null, then transformation from Viewport3D to the finalVisual3D is returned.        /// </para>        /// <para>        /// If no transformation is found, then null is returned.        /// </para>        /// <para>        /// The isVisual3DConnected out parameter is set to when finalVisual3D is connected to the rootVisual3D or Viewport3D; false when finalVisual3D is not reached from the finalVisual3D or Viewport3D.        /// </para>        /// <para>        /// GetVisual3DTotalTransform can be used when we want to get the transformation of a Visual3D that is inside a hierarchy of other Visual3D objects.        /// </para>        /// </remarks>        /// <param name="rootVisual3D">The Visual3D object that is the root of the hierarchy where the finalVisual3D is (if null then Viewport3D is considered the root object).</param>        /// <param name="finalVisual3D">The Visual3D object for witch the Transform3D is created</param>        /// <param name="addFinalVisualTransformation">if true then the returned Transform3D also contains the transform of the finalVisual3D</param>        /// <param name="isVisual3DConnected">out Boolean parameter that is set to true, when finalVisual3D is connected to the rootVisual3D or Viewport3D; false when finalVisual3D is not reached from the finalVisual3D or Viewport3D.</param>        /// <returns>Transform3D or null if no transformation is found</returns>        public static Transform3D GetVisual3DTotalTransform(Visual3D rootVisual3D, Visual3D finalVisual3D, bool addFinalVisualTransformation, out bool isVisual3DConnected)        {            if (finalVisual3D == null)                throw new ArgumentNullException("finalVisual3D", "finalVisual3D is null.");            if (ReferenceEquals(rootVisual3D, finalVisual3D))            {                isVisual3DConnected = true;                return null;            }            Visual3D oneVisual3D = finalVisual3D;            var transformGroup = new Transform3DGroup();            bool addNextTransformation = addFinalVisualTransformation; // We add the first transformation (finalVisual3D.Transform) only when addFinalModelTransformation is true            // First append all parent Visual3D transformations            while (oneVisual3D != null)            {                if (addNextTransformation)                {                    var oneTransform = oneVisual3D.Transform;                    if (oneTransform != null && !oneTransform.Value.IsIdentity)                    {                        if (transformGroup.Children.Count == 0)                            transformGroup.Children.Add(oneTransform);                        else                            transformGroup.Children.Insert(0, oneTransform);                    }                }                else                {                    addNextTransformation = true; // We skip first transformation when addFinalModelTransformation is false but add all following transformations.                }                if (rootVisual3D != null && ReferenceEquals(rootVisual3D, oneVisual3D)) // If rootVisual3D is not null, we stop when rootVisual3D is reached                    break;                var oneParent = VisualTreeHelper.GetParent(oneVisual3D);                // If rootVisual3D is null, we stop when we reach Viewport3D                // If rootVisual3D is not null, we will stop when finalVisual3D is reached - this is done after the transformations are applied                if (rootVisual3D == null && oneParent is Viewport3DVisual)                    break;                oneVisual3D = oneParent as Visual3D;            }            isVisual3DConnected = (oneVisual3D != null);            if (transformGroup.Children.Count == 0)                return null;            if (transformGroup.Children.Count == 1)                return transformGroup.Children;            return transformGroup;        }```
Thank you very much for the methods.
Unfortunately I haven't got it to work, with the functions. Maybe I missed something there.

But I found another possibility which has the same idea you have posted with the Matrix3D.Invert().

What I did is:

Code:
```GeneralTransform3D generalTransform = <ModelVisual3DObject>.TransformToAncestor(<RootModelVisual3D>);             if (generalTransform is MatrixTransform3D) {      _matrix3D = ((MatrixTransform3D)generalTransform ).Value;      _matrix3D.OffsetX = 0;      _matrix3D.OffsetY = 0;      _matrix3D.OffsetZ = 0;      _matrix3D.Invert(); } <ModelVisual3DObject>.Transform = new MatrixTransform3D(_matrix3D);```