Rotation

There are various types of rotational displacement, i.e., about the X axis, about the Y axis, about the Z axis, and so on; these types are expressible by the following transformation matrices.

        Rotation about the X axis
        fig140.gif
        Rotation about the Y axis
        fig141.gif
        Rotation about the Z axis
        fig142.gif

As an example, take a three-dimensional "N" shape, matching the farthest point on its bottom left edge with the coordinate system's point of origin and defining the nearest point on the upper right edge as point P. The coordinates of P, i.e. (1.0, 2.0, 2.0) will represent the size of the character "N". The X, Y, and Z axes will be shown in the respective colors of red, green, and blue.

fig080.gif
        | characterN pointP xyzAxes compoundObject |
        characterN := JunOpenGL3dObject characterN.
        characterN paint: ColorValue magenta.
        characterN := characterN translatedBy: characterN boundingBox corner.
        pointP := JunOpenGL3dObject cube.
        pointP := pointP scaledBy: 0.1.
        pointP := pointP translatedBy: characterN boundingBox corner.
        xyzAxes := JunOpenGL3dObject axes.
        xyzAxes := xyzAxes scaledBy: 3.5.
        compoundObject := JunOpenGL3dCompoundObject new.
        compoundObject add: characterN.
        compoundObject add: xyzAxes.
        compoundObject add: pointP.
        compoundObject show.
        Transcript cr; show: pointP boundingBox center printString

Let us rotate the "N" 30 degrees about the X axis. The coordinates of P will become (1.0, 0.732, 2.732). Using the message rotateX:, an instance of Jun3dTransformation is created and the "N" is operated upon. Namely, the message transform: is sent to the "N". P is also moved accordingly.

fig150.gif
        | characterN pointP aTransformation xyzAxes compoundObject |
        characterN := JunOpenGL3dObject characterN.
        characterN paint: ColorValue magenta.
        characterN := characterN translatedBy: characterN boundingBox corner.
        pointP := JunOpenGL3dObject cube.
        pointP := pointP scaledBy: 0.1.
        pointP := pointP translatedBy: characterN boundingBox corner.
        aTransformation := Jun3dTransformation rotateX: (JunAngle fromDeg: 30).
        characterN := characterN transform: aTransformation.
        pointP := pointP transform: aTransformation.
        xyzAxes := JunOpenGL3dObject axes.
        xyzAxes := xyzAxes scaledBy: 3.5.
        compoundObject := JunOpenGL3dCompoundObject new.
        compoundObject add: characterN.
        compoundObject add: xyzAxes.
        compoundObject add: pointP.
        compoundObject show.
        Transcript cr; show: pointP boundingBox center printString

Now let us return to the original state of "N" and rotate it 30 degrees about the Y axis using the rotateY: message. The coordinates of P will become (1.866, 2.0, 1.232).

fig160.gif
        | characterN pointP aTransformation xyzAxes compoundObject |
        characterN := JunOpenGL3dObject characterN.
        characterN paint: ColorValue magenta.
        characterN := characterN translatedBy: characterN boundingBox corner.
        pointP := JunOpenGL3dObject cube.
        pointP := pointP scaledBy: 0.1.
        pointP := pointP translatedBy: characterN boundingBox corner.
        aTransformation := Jun3dTransformation rotateY: (JunAngle fromDeg: 30).
        characterN := characterN transform: aTransformation.
        pointP := pointP transform: aTransformation.
        xyzAxes := JunOpenGL3dObject axes.
        xyzAxes := xyzAxes scaledBy: 3.5.
        compoundObject := JunOpenGL3dCompoundObject new.
        compoundObject add: characterN.
        compoundObject add: xyzAxes.
        compoundObject add: pointP.
        compoundObject show.
        Transcript cr; show: pointP boundingBox center printString

Next return to the original state of "N" and rotate it 30 degrees about the Z axis using the rotateZ: message. This results in the coordinates (-0.134, 2.232, 2.0) for P.

fig170.gif
        | characterN pointP aTransformation xyzAxes compoundObject |
        characterN := JunOpenGL3dObject characterN.
        characterN paint: ColorValue magenta.
        characterN := characterN translatedBy: characterN boundingBox corner.
        pointP := JunOpenGL3dObject cube.
        pointP := pointP scaledBy: 0.1.
        pointP := pointP translatedBy: characterN boundingBox corner.
        aTransformation := Jun3dTransformation rotateZ: (JunAngle fromDeg: 30).
        characterN := characterN transform: aTransformation.
        pointP := pointP transform: aTransformation.
        xyzAxes := JunOpenGL3dObject axes.
        xyzAxes := xyzAxes scaledBy: 3.5.
        compoundObject := JunOpenGL3dCompoundObject new.
        compoundObject add: characterN.
        compoundObject add: xyzAxes.
        compoundObject add: pointP.
        compoundObject show.
        Transcript cr; show: pointP boundingBox center printString

In the case of rotation about multiple axes, the order of the coordinate transformations, i.e., the associativity of the order of joining the transformation matrices, is of utmost importance. Rotating in the order of X axis, Y axis, Z axis leads to a completely different result from the order Z axis, Y axis, X axis.

fig180.gif
        | characterN pointP aTransformation xyzAxes compoundObject |
        characterN := JunOpenGL3dObject characterN.
        characterN paint: ColorValue magenta.
        characterN := characterN translatedBy: characterN boundingBox corner.
        pointP := JunOpenGL3dObject cube.
        pointP := pointP scaledBy: 0.1.
        pointP := pointP translatedBy: characterN boundingBox corner.
        aTransformation := ((Jun3dTransformation rotateX: (JunAngle fromDeg: 30))
                                product: (Jun3dTransformation rotateY: (JunAngle fromDeg: 30)))
                                product: (Jun3dTransformation rotateZ: (JunAngle fromDeg: 30)).
        characterN := characterN transform: aTransformation.
        pointP := pointP transform: aTransformation.
        xyzAxes := JunOpenGL3dObject axes.
        xyzAxes := xyzAxes scaledBy: 3.5.
        compoundObject := JunOpenGL3dCompoundObject new.
        compoundObject add: characterN.
        compoundObject add: xyzAxes.
        compoundObject add: pointP.
        compoundObject show.
        Transcript cr; show: pointP boundingBox center printString
fig190.gif
        | characterN pointP aTransformation xyzAxes compoundObject |
        characterN := JunOpenGL3dObject characterN.
        characterN paint: ColorValue magenta.
        characterN := characterN translatedBy: characterN boundingBox corner.
        pointP := JunOpenGL3dObject cube.
        pointP := pointP scaledBy: 0.1.
        pointP := pointP translatedBy: characterN boundingBox corner.
        aTransformation := ((Jun3dTransformation rotateZ: (JunAngle fromDeg: 30))
                                product: (Jun3dTransformation rotateY: (JunAngle fromDeg: 30)))
                                product: (Jun3dTransformation rotateX: (JunAngle fromDeg: 30)).
        characterN := characterN transform: aTransformation.
        pointP := pointP transform: aTransformation.
        xyzAxes := JunOpenGL3dObject axes.
        xyzAxes := xyzAxes scaledBy: 3.5.
        compoundObject := JunOpenGL3dCompoundObject new.
        compoundObject add: characterN.
        compoundObject add: xyzAxes.
        compoundObject add: pointP.
        compoundObject show.
        Transcript cr; show: pointP boundingBox center printString

To rotationally displace about an arbitrary line (arbitrary axis), the message rotate:around: should prove convenient. Let us rotate the "N" 30 degrees about an axis formed by the line ((0,0,0),(1,2,2)). As this is rotation about the diagonal line through "N", there will be no change in the coordinates (1.0, 2.0, 2.0) of P.

fig200.gif
        | characterN pointP aLine aTransformation xyzAxes aPolyline compoundObject |
        characterN := JunOpenGL3dObject characterN.
        characterN paint: ColorValue magenta.
        characterN := characterN translatedBy: characterN boundingBox corner.
        pointP := JunOpenGL3dObject cube.
        pointP := pointP scaledBy: 0.1.
        pointP := pointP translatedBy: characterN boundingBox corner.
        aLine := Jun3dLine from: 0 , 0 , 0 to: characterN boundingBox corner.
        aTransformation := Jun3dTransformation rotate: (JunAngle fromDeg: 30)
                                around: aLine.
        characterN := characterN transform: aTransformation.
        pointP := pointP transform: aTransformation.
        xyzAxes := JunOpenGL3dObject axes.
        xyzAxes := xyzAxes scaledBy: 3.5.
        aPolyline := JunOpenGL3dPolyline vertexes: (Array with: (aLine atT: -2)
                                        with: (aLine atT: 2)).
        aPolyline paint: ColorValue cyan.
        compoundObject := JunOpenGL3dCompoundObject new.
        compoundObject add: characterN.
        compoundObject add: xyzAxes.
        compoundObject add: pointP.
        compoundObject add: aPolyline.
        compoundObject show.
        Transcript cr; show: pointP boundingBox center printString

See also:


06 November 1997 / Author: AOKI Atsushi