I just started the api too earlier this week so I can’t help much without digging a ton too haha. I’m glad much more knowledgeable people than I am are answering here. I literally have to do a similar operation pretty soon in my script too.
-----------------------------------------------------------------------------
You could try this for a simple vector orientation match:
Lets say you want to transform locator Y axis to match normal,
LocYVector = om.MVector(0,1,0) # really Y axis
YourNormalVector = the normal you got from mfnmesh or MIter
om.MQuaternion(MVectorA, MVectorB): # when you pass in two vectors A B
returns your quaternion to transform A to B!
Basically 0,1,0 to the normal orientation basically to align vector A to B
rotateQuaternion = om.MQuaternion(LocYVector, YourNormalVector)
Btw there is this too:
Returns the vector that represents the rotation of this vector by the given quaternion.
MVector.rotateBy()
But in this case you dont want to rotate the vector you want to rotate the locator, assuming you select the locator
you can do
getActiveSelectionList() returns an om.SelectionList() object from your active selection
locatorSL = om.something globals.getActiveSelectionList() # pseudocode++
I cant remember the globals name just google it haha.
This only shows up in the python 2.0 api docs:
Selection lists have a getcomponent(index) method that returns tuple (dagpath, mobject) of the 0th item in the selection list
locdag, locMobj = locatorSL.getcomponent(0)
Getcomponent doesnt show up in the c++ docs I have but it shows up on Maya 2.0 Api I use it a lot:
getComponent(index) -> (MDagPath, MObject)
Returns the index'th item of the list as a component, represented by
a tuple containing an MDagPath and an MObject. If the item is just a
DAG path without a component then MObject.kNullObj will be returned
in the second element of the tuple. Raises TypeError if the item is
neither a DAG path nor a component. Raises IndexError if index is
out of range.
https://help.autodesk.com/view/MAYAUL/2020/ENU/?guid=__py_ref_class_open_maya_1_1_m_selection_list_html
the c++ docs tell me MFnTransform needs an mobject constructor:
Relatively change the rotation of this transformation using a quaternion.
om.MFnTransform(locMobj).rotateByQuaternion(rotateQuaternion)
Im kind of busy atm but Im going to try this soon too… hope it works…ha
ps there is also a setActiveSelectionList(pass in a selection list here)
that sets your viewport selection to a selection list when youre done with the api
Side Note
Speaking of normals, just fyi (in your case you prob don’t need a second vector, but if you want an ortho-normal basis chad vernon explains it nicely)
You can take the double cross product of two vertex normals to establish a basis assuming the vertex isnt on a totally flat surface: (in which case the vertex normals would all be the same right?) also this is assuming you havent manually edited the normals to misguide a calculation…
Note: You could use a tangent space normal too but you have ensure they haven’t been edited and are the same as vertex normal.
On a flat surface you could use normal and a connected edge ( you can get connected edges and then get their vertex 1 or 2, picking the one whose world position is not equal to the verrtex world positoin, that should always give you two distinct vectors to create an ortho-normal basis):
Look at the methods for mfnmesh and MIterMeshVertex.getConnectedEdges()
Those methods return the vertex ID for each vertex when you pass in 0 then pass in 1. The edge index’s 2 points, picking the one whose world position != your vertex.
Sorry its convoluted. You can do om.MItMeshVertex.getPoint(vertexID, worldspace) to get world positions to pick the right vertex to generate a distinct second vector.
Its a lot of bouncing back and forth between the iterator MIt and the Mfn function set, the more you can do in 1 iteration, getting the data you need, the faster things should go I think.
This is what Im using to understand the object model (the 2.0 api is a bit different but mostly similar regarding mobject pointers)
https://www.cgcircuit.com/tutorial/maya-python-api
The syntax for calling the mobject and getting your selection into a selection list is covered more in depth above. (like what bob was doing)
I think he explains it in applied-3d-math (its free)
An ortho-normal basis is basically a new local coordinate system where XYZ vectors all are 90 degres to one another. As in dotproduct(XY) | (YZ) | (ZX) == 0:
Chad explains it much nicer in maya here:
Say your locators were bolts, you could ensure the orientation of a bolt was in a predictable way (the way the two axis are pointing besides the one oriented to the normal) if you have a basis… without you just have one aligned vector / axis (hope that makes sense)