Mel: How to move one or more vertices to the same position as the 'leading' vertex?

This is really just an exercise to learn more Mel, more than anything else. I gave myself a simple task of taking a number of vertices and moving them all to the same position as the ‘leading’ vertex (the one selected first).

Here is what I have:

string $sel[]= `ls -flatten -orderedSelection`;        //get all the selected vertice into an array
$attr = `getAttr $sel[1]`;                             // query the position of the first selected vertex
print($sel);                                           // I get expected results (three vertices = three elements)
print($attr);                                           // position of the first vertex does get returned


// Here is where I am stuck; setting the postion of the vertices to the first one
//setAttr $sel[0].x 5;                                   // Error: Syntax error
//setAttr $sel[0] $attr ;                               // Error: No object matches name: 

//move $attr;                                            // more errors
//move  $sel[0] $sel[1] ;                                  // more errors
//matchTransform  $sel[0] $sel[1];                          // more errors

Where I am stuck on seems to be setting the vertex position. I searched around and the answers seem to be pointing to setAttr but I am not sure where I am going wrong.

I asked a similar question before, Simple command that will merge a vertex to the position of the ‘leading’/first vertex?, and the user bjelDark kindly gave me a solution. This here is my attempt to programme a solution in Mel.

forget using setAttr and getAttr for component data or positions, unfortunately they don’t work lke that, something to do with tweaks and history and all sorts of extremely complicated and confusing architecture.
Points (all components) are also not technically transforms, so most functions that are designed to operate on transforms probably won’t work on components either.

If you want to get the position of a point (vertex) the best solution is to use the pointPosition command, which can return the position in local or world space (check the MEL command docs for details).
If you want to move a point (vertex) then you can just use the move command directly, or the polyMoveVertex command.

I wouldn’t personally use the xform command for component manipulation, as it’s more designed for transforms, so while it does work (see comment above) I’m guessing it’s jumping through more hoops and is less efficient (I have no evidence or experience to back that up though, so…)

string $sel[]= `ls -flatten -orderedSelection`;
vector $firstPos = `pointPosition -world $sel[0]`;
move ($firstPos.x) ($firstPos.y) ($firstPos.z) -worldSpace $sel;

notes:

  • remember -orderedSelection only works if the correct selection pref is enabled in your prefs (see command docs for details),
  • use pointPosition to get the position of any point type object/component
  • pointPosition returns a list of floats, but as it’s 3 in this case, we can capture it as a vector
  • use move, with the vector components as the world position, and we may as well just move ALL $selection. (this is because working with arrays in MEL is a pain, so if you really wanted to only move the other verts, you’d probably just be better off removing the first item from the array).
2 Likes

Whenever you answer a thread of mine, I always learn a ton, this instance is no acception. As well as adressing the main task, you have answered a number of questions I was struglliing and a bunch that I undoubtedly would have come across.

Your points on performance is especially appreciated. Thank you.

1 Like