A few things are going on here.
First, it appears the MaxScript $.transform.scalepart
and $.transform.rotationpart
are bugged and don't support inverse scale. These are probably implemented similarly to the first answer on this post, which always gives positive scale coordinates, and wrong answers for negative scale matrices.
Second, when asking for $.scale.controller.value
and $.rotation.controller.value
the rotation part is also bugged and returns the same value as before mirroring, while the scale returns a mirrored value. If you think about how the (scale * rotation * position) matrix composition works, you can see that, for example, a mirror in X requires inverting the first component of scale but also reversing all rotations around the X axis.
Apparently (I'm speculating here) the mirror mode does two things when applied. (1) it activates special-case handling inside the PRS controller, such that, when composing the scale/rotation/transform subcontroller values into a matrix, it flips some coordinates without doing a true matrix composition. For example, a mirror in X inverts the first coordinate of the each of the first three rows of the transform matrix, but otherwise the PRS controller expects the pre-mirrored rotation value as input. (2) it flips components of scale subcontroller value. For example, a mirror in X inverts the first coordinate. But the rotation subcontroller in unaffected.
The result of all this is that you obtain an incorrect maxtrix composition when asking MaxScript for the transform parts. And you also get an incorrect composition when directly combining the position/rotation/scale subcontroller values.
What you need is to a better way to decompose the final (correct) transform in position/rotation/scale components. Here is a MaxScript based on the algorithm shown here. It returns an array with ScaleMatrix, RotationMatrix, PositionMatrix, so the original transform can be obtained again with (result[1] * result[2]) * result[3]
. Pass $.transform
as input.
fn matrixDecompose t =
(
trans = t.pos
trn = ( matrix3 [1,0,0] [0,1,0] [0,0,1] trans )
scaleX = length [ t[1][1], t[2][1], t[3][1] ]
scaleY = length [ t[1][2], t[2][2], t[3][2] ]
scalez = length [ t[1][3], t[2][3], t[3][3] ]
tempZ = cross t[1] t[2]
if( (dot tempZ t[3]) < 0 ) then
(
scaleX = -scaleX
t[1] = -t[1]
)
scl = ( matrix3 [scaleX,0,0] [0,scaleY,0] [0,0,scaleZ] [0,0,0] )
t[1] = normalize t[1]
t[2] = normalize t[2]
t[3] = normalize t[3]
rot = t.rotationPart as matrix3
#( scl, rot, trn )
)