How can I apply vector rotations around the three axis and how can I extract them later on.

Looking at the API and the matrix structure I feel hopeless - one wants a vector and degree (SUTransformationRotation) and the other a 3x3 matrix.

How can I apply vector rotations around the three axis and how can I extract them later on.

Looking at the API and the matrix structure I feel hopeless - one wants a vector and degree (SUTransformationRotation) and the other a 3x3 matrix.

Do you have a desktop edition? If not install 2017 Make and get ThomThomâ€™s transformation inspector tool from the Extension Warehouse. This will enable you to inspect your C API generated modelâ€™s within SketchUp. (Just backsave them as 2017 version.)

And if youâ€™ll be using attribute dictionaries, Iâ€™d also recommend Aeriliusâ€™ Attribute Inspector extension.

Confused. Iâ€™m asking how to apply axis based rotations to an instance.

In the free web-based version that your profile indicates you are using?

You do realize this is the SDK section right?

It doesnâ€™t matter what version of sketchup I have.

Yes I do realize this is the SDK section.

Ok ignore everything else currently it is important extracting the rotation as floating point values per axis programmatically.

I think Iâ€™ve got the exportion part.

Donâ€™t be. I am basically giving you advice on how to inspect the models you create with the C API.

The desktop editions can have extensions. The extension I told you about, will allow you to inspect the transformation matrices of the instances that you transform. Ie, itâ€™s a self help avenue.

Firstly, again I remind you that SketchUpâ€™s modeling axes are different from game engines.

Z is up, X is to the right (points toward east,) Y runs away from the viewer (and is north 0 degrees.)

A simple single rotation would be done by creating a rotational transform.

`SUTransformationRotation`

- The
argument places the rotational axis`point`

somewhere in 3D space.`vector`

This does not have to be (but can be) within or even near the instance itself. - The
argument is the axis of rotation.`vector`

- The
argument will be the angle to rotate about the axis defined by the`angle`

argument.`vector`

- You can use the
`SUDegreesToRadians()`

function to specify values in degrees.

- You can use the

If you wish a compound rotation, then youâ€™ll need to create 2 rotational transforms, and multiply them together, using the `SUTransformationMultiply()`

function, and then apply the resultant transform to the instance.

You can also â€śmix inâ€ť translational and scaling transforms by multiplying them also.

But they are traditionally applied in a particular order. Translational first. Rotational second in (X, Y then Z order.) Then Scaling (X, Y then Z order.) Decomposing a transformation matrix must be done in reverse order. (*See Aeriliusâ€™ code â€¦ link posted below*.)

You could try this â€¦

- You get the transform of the instance.
- from this you get the transformâ€™s 3 axial vectors (X, Y and Z.)
`SUTransformationGetXAxis`

,*etc.* - You get the modelâ€™s global Axes object â€¦
`SUModelGetAxes`

- from this you get the modelâ€™s 3 axial vectors (X, Y and Z.)
`SUAxesGetXAxis`

,*etc.* - You compare each of the 3 corresponding instance transformation axis with the modelâ€™s corresponding axis.

â€¦ ie X for X, Y for Y,*etc.*using`SUVector3DAngleBetween`

- You can use the
`SURadiansToDegrees()`

function to convert the values to degrees.

- You can use the

Note that the both (Ruby and C) APIâ€™s may have a limitation with the angle between method/function. I think it works using dot product for vectors which always returns a value between 0 and 180. (May not be a problem if the return value is signed.)

There are some ways to use trigonometry on the matrix values to get the axial rotations.

Aerilius posted code in Ruby here â€¦

3 Likes

I still donâ€™t understand where the 3x3 rotation matrix is located inside the transformation matrix - can you specify which indices define it.

Is it 0 - 2, 4 - 6, 8 - 10

If you (again) install a desktop SketchUp and install ThomThomâ€™s Transfromation Inspector (also requires his TT_Lib2 library,) â€¦ youâ€™ll be able to visualize transformations, and play around with editing them parametrically.

https://extensions.sketchup.com/en/content/tt_libÂ˛

https://extensions.sketchup.com/en/content/transformation-inspector

In the image below, the 3x3 matrix has a green background.

Well the Ruby API returns a nested array where each row is a subarray.

So it would be `ary[0][0..2]`

, `ary[1][0..2]`

and `ary[2][0..2]`

But I think the C API just returns a flattened 16-element array (the equivalent of the Ruby APIâ€™s `transformation.to_a`

method.)

So **yes** youâ€™d use: `ary[0..2]`

, `ary[4..6]`

and `ary[8..10]`

Iâ€™ve made a Ruby library that can help extracting Euler angles. Maybe it can be helpful for implementing something similar using the C API.

I donâ€™t know how experienced you are with transformation matrices but the angles arenâ€™t directly written anywhere in there. Instead you can think of the matrix as the 3 axis vectors for a local coordinate system, as well as a translation (to get really technical the translation mathematically equals to a shearing in a 4th dimension). To extract angles you have to do some trigonometry.

1 Like

OK I used the formula from the wiki page to set translations but now objects are doubled in a weird way:

The above is supposed to be a single door. Here is my code:

```
static struct SUTransformation matrixtransform, matrixrotationX, matrixrotationY, matrixrotationZ;
SUTransformationTranslation(&matrixrotationX, (struct SUVector3D[]) { 0, 0, 0 });
SUTransformationTranslation(&matrixrotationY, (struct SUVector3D[]) { 0, 0, 0 });
SUTransformationTranslation(&matrixrotationZ, (struct SUVector3D[]) { 0, 0, 0 });
0[matrixrotationZ.values] = cos(rotation.z),
1[matrixrotationZ.values] = -sin(rotation.z),
2[matrixrotationZ.values] = 0,
4[matrixrotationZ.values] = sin(rotation.z),
5[matrixrotationZ.values] = cos(rotation.z),
6[matrixrotationZ.values] = 0,
8[matrixrotationZ.values] = 0,
9[matrixrotationZ.values] = 0,
10[matrixrotationZ.values] = 1,
0[matrixrotationY.values] = cos(rotation.y),
1[matrixrotationY.values] = 0,
2[matrixrotationY.values] = sin(rotation.y),
4[matrixrotationY.values] = 0,
5[matrixrotationY.values] = 1,
6[matrixrotationY.values] = 0,
8[matrixrotationY.values] = -sin(rotation.y),
9[matrixrotationY.values] = 0,
10[matrixrotationY.values] = cos(rotation.y),
0[matrixrotationX.values] = 1,
1[matrixrotationX.values] = 0,
2[matrixrotationX.values] = 0,
4[matrixrotationX.values] = 0,
5[matrixrotationX.values] = cos(rotation.x),
6[matrixrotationX.values] = -sin(rotation.x),
8[matrixrotationX.values] = 0,
9[matrixrotationX.values] = sin(rotation.x),
10[matrixrotationX.values] = cos(rotation.x);
SUTransformationTranslation(&matrixtransform, &translation);
SUTransformationMultiply(&matrixtransform, &matrixrotationX, &matrixtransform);
SUTransformationMultiply(&matrixtransform, &matrixrotationY, &matrixtransform);
SUTransformationMultiply(&matrixtransform, &matrixrotationZ, &matrixtransform);
SUComponentInstanceSetTransform(instance, &matrixtransform);
```

Is this **your** door component?

If not, take extra care with door and window components. Actually any â€śsnap_toâ€ť component. If they are snap_to components then they are drawn lying flat on the XY ground plane (which is the cutting plane if their â€ścuts_openingâ€ť flag is set,) facing up (the doorâ€™s outside faceâ€™s normal vector is perpendicular to the blue Z axis.)

In the GUI when the user is placing one of these type of components, the core automatically reorients the instance attached to the cursor when it nears a snapable face (which depends upon what the definitionâ€™s â€śsnap_toâ€ť/â€śglue toâ€ť setting is, ie, vertical, horizontal, sloped, or any.)

I havenâ€™t assigned any special properties to this specific component instance. In fact I draw everything equally dumb - by using 3d faces.

My original idea was doing something like:

```
SUTransformationRotation(&matrixrotationX, &translation, (struct SUVector3D[]) { 1, 0, 0 }, rotation.x * M_PI / 180.0),
SUTransformationRotation(&matrixrotationY, &translation, (struct SUVector3D[]) { 0, 1, 0 }, rotation.y * M_PI / 180.0),
SUTransformationRotation(&matrixrotationZ, &translation, (struct SUVector3D[]) { 0, 0, 1 }, rotation.z * M_PI / 180.0);
SUTransformationTranslation(&matrixtransform, &translation);
SUTransformationMultiply(&matrixtransform, &matrixrotationX, &matrixtransform);
SUTransformationMultiply(&matrixtransform, &matrixrotationY, &matrixtransform);
SUTransformationMultiply(&matrixtransform, &matrixrotationZ, &matrixtransform);
SUComponentInstanceSetTransform(instance, &matrixtransform);
```

But obviously this doesnâ€™t work since the resulting transformations are way off the original models in the game engine.

Never mind I got it to work - excluding duplicates that is and I havenâ€™t even started exportion yet.

Iâ€™m actually working on an update to better visualize the matrix. My current released version indicate row-major order. But SketchUp uses column-major order.

New version is currently looking like this:

Color coding for the rotation axes, along with their angles described in degrees.

Note that the translation values are now located to the right, not the bottom. Hovering over a matrix will display what index it relates to.

WIP is is the `dev/column-major`

branch:

3 Likes

FR: When hovering a field there could be a tooltip saying â€śX component of Y axisâ€ť and the like. I never really got transformation matrices until I noticed how the rows (or is it teh columns) of the 3x3 rotation matrix are the vectors of the axes.

1 Like

Wow. Never noticed this either, until now. Thanks.

1 Like

That was a key aha moment for me too, and Iâ€™ve gone to using this idea in my extensions when placing complicated groups such as angular dimensions, slope markers, etc. I draw the group at the origin in the model (which makes it easier to place all the parts) and then use unit vectors at the desired destination to create the Transformation from an Array without ever knowing or caring about the angles involved.

1 Like