Translating, Rotating, and Scaling Objects
An IDLgrModel object is a container for any visualization objects that are to be rotated, translated, or scaled. Each IDLgrModel object has a transformation property (set via the TRANSFORM keyword to the IDLgrModel::Init or SetProperty method), which is a 4 x 4 floating-point matrix. For a general discussion of transformation matrices and three-dimensional graphics, see Coordinates of 3-D Graphics.
Note: A model object's transformation matrix is akin to the transformation matrix used by IDL Direct Graphics and stored in the !P.T system variable field. Transformation matrices associated with a model object do not use the value of !P.T, however, and are not affected by the T3D procedure used in Direct Graphics.
By default, a model object's transformation matrix is set equal to a 4-by-4 identity matrix:
[[1.0, 0.0, 0.0, 0.0],
[ 0.0, 1.0, 0.0, 0.0],
[ 0.0, 0.0, 1.0, 0.0],
[ 0.0, 0.0, 0.0, 1.0]]
You can change the transformation matrix of a model object directly, using the TRANSFORM keyword to the IDLgrModel::Init or SetProperty method:
myModel = OBJ_NEW('IDLgrModel', TRANSFORM = tmatrix)
where tmatrix
is a 4-by-4 transformation matrix.
Alternatively, you can use the Translate, Rotate, and Scale methods to the IDLgrModel object to alter the model's transformation matrix.
Translation
The IDLgrModel::Translate method takes three arguments specifying the amount to translate the model object and its contents in the X, Y, and Z directions. For example, to translate a model and its contents by 1 unit in the X-direction, you could use the following statements:
dx = 1 & dy = 0 & dz = 0
myModel->Translate, dx, dy, dz
How does this affect the transformation matrix? Notice that we could change the transformation matrix in an identical way using the following statements:
; Define translation values:
dx = 1 & dy = 0 & dz = 0
; Get existing transformation matrix:
myModel->GetProperty, TRANSFORM = oldT
; Provide a transformation matrix that performs the translation:
transT = [[1.0, 0.0, 0.0, dx], $
[0.0, 1.0, 0.0, dy], $
[0.0, 0.0, 1.0, dz], $
[0.0, 0.0, 0.0, 1.0]]
; Multiply the existing transformation matrix by
; the matrix that performs the translation:
newT = oldT # transT
; Apply the new transformation matrix to the model object:
myModel->SetProperty, TRANSFORM = newT
Rotation
The IDLgrModel::Rotate method takes two arguments specifying the axis about which to rotate and the number of degrees to rotate the model object and its contents. For example, to rotate a model and its contents by 90 degrees around the y-axis, you could use the following statements:
axis = [0,1,0] & angle = 90
myModel->Rotate, axis, angle
How does this affect the transformation matrix? Notice that we could change the transformation matrix in an identical way using the following statements:
; Define rotation values:
axis = [0,1,0] & angle = 90
; Get existing transformation matrix:
myModel->GetProperty, TRANSFORM = oldT
; Define sine and cosine of angle:
cosa = COS(!DTOR*angle)
sina = SIN(!DTOR*angle)
; Provide a transformation matrix that performs the rotation:
rotT = [[cosa, 0.0, sina, 0.0], $
[0.0, 1.0, 0.0, 0.0], $
[-sina, 0.0, cosa, 0.0], $
[0.0, 0.0, 0.0, 1.0]]
; Multiply the existing transformation matrix
; by the matrix that performs the rotation.
newT = oldT # rotT
; Apply the new transformation matrix to the model object:
myModel->SetProperty, TRANSFORM = newT
Scaling
The IDLgrModel::Scale method takes three arguments specifying the amount to scale the model object and its contents in the x, y, and z directions. For example, to scale a model and its contents by 2 units in the y direction, you could use the following statements:
sx = 1 & sy = 2 & sz = 1
myModel->Scale, sx, sy, sz
How does this affect the transformation matrix? Notice that we could change the transformation matrix in an identical way using the following statements:
; Define scaling values:
sx = 1 & sy = 2 & sz = 1
; Get existing transformation matrix:
myModel->GetProperty, TRANSFORM = oldT
; Provide a transformation matrix that performs the scaling:
scaleT = [[sx, 0.0, 0.0, 0.0], $
[0.0, sy, 0.0, 0.0], $
[0.0, 0.0, sz, 0.0], $
[0.0, 0.0, 0.0, 1.0]]
; Multiply the existing transformation matrix
; by the matrix that performs the scaling.
newT = oldT # scaleT
; Apply the new transformation matrix to the model object:
myModel->SetProperty, TRANSFORM = newT
Combining Transformations
Note that model transformations are cumulative. That is, a model object contained in another model is subject to both its own transformation and to that of its container. All transformation matrices that apply to a given model object are multiplied together when the object is rendered. For example, consider a model that contains another model:
model1 = OBJ_NEW('IDLgrModel', TRANSFORM = trans1)
model2 = OBJ_NEW('IDLgrModel', TRANSFORM = trans2)
model2->Add, model1
The model1
object is now subject to both its own transformation matrix (trans1
) and to that of its container (trans2
). The result is that when model1
is rendered, it will be rendered with a transformation matrix = trans1 # trans2
.