0

I'm currently trying to transform some object's pivot by some arbitrary matrix.

So far I've been able to do it for objects without any non-uniform scales applied, but it breaks when the target object has some non-uniform scales.

I have the impression that, for this to work, this would need to access the scalerotationpart of the objectOffset, which seems to be unavalaible in maxscript.

This would be doable using the C++ SDK as the objectOffset scale is expressed as a ScaleValue (which contains a scale vector and a quaternion, see SDK docs).

Am I missing something obvious ? or do I have to craft some maxscript plugin extension for this to work ?

Thanks,

My starting point was the following function :

fn AlignPivotTo Obj Trgt =
(
    -- http://forums.cgsociety.org/archive/index.php/t-636495.html
    --This fails miserably for any objects having a negative or non-uniform scale, but it seems to work well in any other case I have tested:

    -- Get matrix from object
    if classOf Trgt != matrix3 then Trgt = Trgt.transform

    -- Store child transforms
    local ChldTms = in coordSys Trgt ( for Chld in Obj.children collect Chld.transform )

    -- Current offset transform matrix
    local TmScale = scaleMatrix Obj.objectOffsetScale
    local TmRot = Obj.objectOffsetRot as matrix3
    local TmPos = transMatrix Obj.objectOffsetPos
    local TmOffset = TmScale * TmRot * TmPos

    -- New offset transform matrix
    local deltaTransform = obj.transform * inverse Trgt
    TmOffset *= deltaTransform

    -- Apply matrix
    Obj.transform = Trgt

    -- Restore offsets
    Obj.objectOffsetPos = TmOffset.translationPart * inverse TmOffset.scalerotationpart 
    Obj.objectOffsetRot = TmOffset.rotationPart * invers eTmOffset.scalerotationpart 
    Obj.objectOffsetScale = TmOffset.scalePart

    -- Restore child transforms
    for i = 1 to Obj.children.count do ( Obj.children[i].transform = ChldTms[i] * inverse Trgt * Obj.transform )
)
rotoglup
  • 5,223
  • 25
  • 37

1 Answers1

0

I'm not 100% sure I've got the gist of your question right, but the basic answer is 'yes', you need a more complex transform stack to achieve what you want than a simple PRS.

You want to apply a transform to the pivot point of an object while counter-transforming the actual object to keep it in the same world space. This is possible with simple PRS till you add non-uniform scale.

You need to remove the effect of the object rotation to get back to an orthogonal basis before you can apply the counter-scale. What you kinda want to do is origPRS * newPRS * Inv(newPRS) * offsetPRS. The Inverse decomposes to inv(S) * inv(R) * inv(P) (reverse order). After a bit of juggling your transform stack becomes PRS * P * R * Inv(R) * S * R. Which you can do with a scalevalue.

However, I strongly discourage you from doing this. It'll work once, but the moment your artists try rotating the pivot, you'll break everything again, and of course you couldn't apply any animation to the system.

Depending on what you want to do, the best way to approach this might be 'borrowing' the CAT hierarchy. You can create CAT controllers (Depending on your version of Max, and only through MaxScript) that automatically compensate for non-uniform scale to keep your entities in orthoganol space. Basically it boils down to 'what are you trying to achieve', but its probably easier to solve it in another way.

FrozenKiwi
  • 1,362
  • 13
  • 26
  • Also - don't forget that if you create a rotated scale in C++ for the obj-offset, it'll be impossible for an artist to remove it. – FrozenKiwi Nov 16 '13 at 16:47
  • Thanks for the insight, I came to this while trying to script some pivot alignment, which failed on objects with non-uniform scales. Basically I took the safe route and applied a ResetXForm on those. I'm just trying to check if maxscript is less expressive than C++ for manipulating obj-offset. – rotoglup Nov 20 '13 at 18:28