Rotate axis?

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 01/04/2011 at 10:12, xxxxxxxx wrote:

Hi,

I'm trying to convert my Coffee code that rotates the axis of an object to Python. But my Coffee example uses two functions called GetMulM() & GetMulP(). Which aren't in the Python SDK.

import c4d  
from c4d import gui  
  
def main() :  
newMatrix = c4d.Matrix(c4d.Vector(45), c4d.Vector(0), c4d.Vector(0), c4d.Vector(0))   
  
obj = doc.GetActiveObject()  
points = obj.GetAllPoints();  
count = obj.GetPointCount();  
mLocal = obj.GetMl() # the local matrix  
mGlobal = mLocal.GetMulM(newMatrix) # <------How to do this with python?  
obj.SetMl(mGlobal)   
    
invertedMatrix = newMatrix.GetClone()  
invertedMatrix.Invert()  
  
for i in range(len(points)) :  
   points[i] = invertedMatrix.GetMulP(points[i]) # <------How to do this with python?  
    
# Write the points back to the object.  
obj.SetPoints(points)   
obj.Message(MSG_UPDATE)  
c4d.EventAdd()  
  
if __name__=='__main__':  
  main()  

Does anyone know how to convert this to Python?

-ScottA

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 01/04/2011 at 18:24, xxxxxxxx wrote:

Hi Scott,

You can multiply a matrix using the '*' operator. You can invert a matrix using the '~' operator before the matrix.

The following pieces are what you're missing:

  
   #mGlobal = mLocal.GetMulM(newMatrix) # <------How to do this with python?   
   mGlobal = mLocal * newMatrix   
  
   invertedMatrix = copy.copy(newMatrix)   
   invertedMatrix = ~invertedMatrix #The '~' operator inverts a matrix   
  
     #points[i] = invertedMatrix.GetMulP(points[i]) # <------How to do this with python?   
     points[i] = invertedMatrix * points[i]   

Note: I'm not great with matrix math, so someone please correct me if I'm wrong here. My above answer was generated by poking around in the COFFEE & Python SDKs and online docs.
Cheers,

Donovan

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 02/04/2011 at 08:52, xxxxxxxx wrote:

Thanks Donovan,

That gets me a little bit closer. But using straight multiplication on the points crushes them all down to the same vector(0,0,0) position.
The two Coffee functions I used must  have something inside of them that does more than multiplication.

Here's my code:

import c4d  
from c4d import gui  
  
def main() :  
newMatrix = c4d.Matrix(c4d.Vector(45), c4d.Vector(0), c4d.Vector(0), c4d.Vector(0))   
  
obj = doc.GetActiveObject()  
points = obj.GetAllPoints();  
count = obj.GetPointCount();  
mLocal = obj.GetMl() # the local matrix  
mGlobal = mLocal * newMatrix  
obj.SetMl(mGlobal)     
  
invertedMatrix = ~newMatrix #The '~' operator inverts a matrix   
  
for i in range(len(points)) :  
   points[i] = invertedMatrix * points[i]  
    
# Write the points back to the object.  
obj.SetAllPoints(points)   
obj.Message(c4d.MSG_UPDATE)  
c4d.EventAdd()  
  
if __name__=='__main__':  
  main()  

-ScottA

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 02/04/2011 at 10:50, xxxxxxxx wrote:

Got it!
Since python does things a little differently. I dumped my Coffee code and started from scratch.

Thinking about how global point positions are calculated by multiplying their local positions by the object's matrix.
I finally came up with the code to rotate the axis, and then move the points back to their previous global positions.

import c4d  
from  c4d import *  
  
def main() :  
  RotAmount = c4d.Vector(0,.4,0)  
  op.SetRelRot(RotAmount)  
  matrix = op.GetMg()  
  inverted = ~matrix      
  points = op.GetAllPoints()           
       
  for i in range(len(points)) :      
    points[i] = points[i]* inverted            
      
  op.SetAllPoints(points)  
  op.Message(c4d.MSG_UPDATE)  
  c4d.EventAdd()      
  
if __name__=='__main__':  
  main()  

-ScottA

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 03/04/2011 at 14:07, xxxxxxxx wrote:

I asked the exact same questions (equivalent of GetMulP and Rotate axis) a few days ago.
For completeness here's the links to the posts:

https://plugincafe.maxon.net/topic/5610/5639_how-to-rotate-just-the-axis
https://plugincafe.maxon.net/topic/5618/5648_equivalent-of-getmulp-

But I think your solution is far better since you avoid MatrixToHPB(HPBToMatrix()) roundtrips. Gotta try this right away.

Also, over at CGTalk I have a post going in the script resources thread where I post all my Python Helper functions as I come across them.

It's a bit of the same spirit as the COFFEE bible just without nice wordings and context :)

I'll post it as gist, since it's better to read...
https://gist.github.com/888507

Disclaimer:
I'm just learning all of this myself, so my code may not be the most elegant or efficient solution yet :)

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 03/04/2011 at 20:01, xxxxxxxx wrote:

And I think now I know why my rotate axis solution isn't working as great as yours.... GetRelRot returns verbatim what the coordinate manager shows for rotation of an object, whereas MatrixToHPB returning Euler angles, often times has more than one "solution" that it can return, namely the angle as recorded in the coordinate manager or 360 degrees - the angle as recorded in the coordinate manager.

Now using GetRelRot, I should be able to get rid of the recursion in my function. It was always striking me as odd that I needed this.

Code smelled funny as they say.

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 03/04/2011 at 20:38, xxxxxxxx wrote:

Scott, can I add your function to my Helpers class?
With credits, of course.

Oh and btw, I would add a check at the beginning of the function if the current rotation is already the desired new axis rotation, because if you execute the function twice on an object with the same desired rotation, the second time the axis wont move but the points will.

def SetAxisRotation(op, rot, local=False) :   
    """   
    Set the rotation of the object axis (i.e. keeping points in place).   
       
    obj   object   
    rot   vector   
  
    Courtesy of Scott Ayers, source:   
    https://plugincafe.maxon.net/topic/5632/5663_rotate-axis&PID;=23480#23480   
    """   
    if op is None: return False   
    if not isinstance(rot, c4d.Vector) :   
        raise TypeError("expected c4d.Vector, got %s" % type(rot))   
    currot = op.GetRelRot()   
    if VectorEqual(currot, rot) : return   
    op.SetRelRot(rot)   
    if local is True:   
        mat = op.GetMl()   
    else:   
        mat = op.GetMg()   
    inv = ~mat   
    points = op.GetAllPoints()   
    for i in range(len(points)) :       
      points[i] = points[i] * inv   
    op.SetAllPoints(points)   
    op.Message(c4d.MSG_UPDATE)   
    c4d.EventAdd()   

VectorEqual needs

from c4d.utils import *

Andre

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 03/04/2011 at 21:02, xxxxxxxx wrote:

Sure Andre.
That's fine with me.

-ScottA

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 03/04/2011 at 21:34, xxxxxxxx wrote:

Does it work reliably for you if the object is already rotated?

My function will do it, but it needs like 10 recursions or more to get there... hm....

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 04/04/2011 at 08:09, xxxxxxxx wrote:

It works fine the first time for me.

But....
I just noticed that this is a one shot deal.
It works the first time. But if you try to run the script again with a different vector value. The points will also rotate with the matrix for some strange reason!?
It's as if the script skips over the whole get-move point routine for some reason.

I guess it still needs more work.

-ScottA