Rao
Rao

Reputation: 2962

Snapping an object to another object vertex in Maya over Python Script

I want to snap / align an object A to vertex of object B. I have tried using below script but its not snapping exactly to the vertex but snapping with an offset. Can any one suggest me a solution. Here are the snapshots.

import maya.cmds as cmds

vertices = [];
srcObj = "pCone1";

def snapToVertex(vertex,object):

    cmds.select(vertex);
    x,y,z = cmds.pointPosition();
    cmds.select(object);
    cmds.duplicate();
    cmds.move(x,y,z);

def processTask():

    cmds.select( cmds.polyListComponentConversion( tv=True ) );        
    vertices = cmds.ls(sl = True);

    print vertices;
    for vrtx in vertices:
        snapToVertex(vrtx,srcObj);

processTask();

Snapped with my above Script, Which didn't snap exactly to vertex.

enter image description here

But it should be snapped exactly to the Vervex's as below image.

enter image description here

Upvotes: 3

Views: 5043

Answers (2)

Andy Jazz
Andy Jazz

Reputation: 58063

It's better not to use Reset Transformations command for your Cone from Modify main menu, 'cause pivot point goes back to its initial place. The analog for useful Freeze Transformations command in Python is cmds.makeIdentity(). Even if you've moved you pivot point by 1 unit (for example) along +Y axis, do not forget to subtract that 1 from variable y cause Maya somehow remembers pivot's position. Offset of the Cone's pivot point (for snapping pivot to a vertex) depends on the Cone's size itself. By default it's 1.

Add this snippet to your code to move the duplicates in World Space:

# cmds.makeIdentity( 'pCone1', apply=True )

pivSnap = 1  
cmds.xform( 'pCone1', piv=[ 0, pivSnap, 0 ] )
cmds.move( x, y-pivSnap, z, a=True, ws=True, wd=True )

enter image description here

You can test this code (here I moved pivot up by 0.5):

import maya.cmds as cmds

cmds.polyCube( sx=1, sy=15, sz=1, w=1, h=15, d=1 )
cmds.polyCone( r=.5, h=1, sx=10 )
cmds.move( 10, x=True )
pivSnap = .5
cmds.xform( 'pCone1', piv=[ 0, pivSnap, 0 ] )
cmds.rotate( 0, 0, '45deg' )
cmds.select( 'pCube1.e[33]','pCube1.e[37]','pCube1.e[41]','pCube1.e[45]','pCube1.e[49]','pCube1.e[53]','pCube1.e[57]','pCube1.e[61]' )
vertices = []
srcObj = "pCone1"

def snapToVertex( vertex, object ):

    cmds.select( vertex )
    x,y,z = cmds.pointPosition()
    print( x,y,z )

    cmds.select( object )
    cmds.manipMoveContext( m=2 )
    cmds.delete( 'pCube1', ch=True )
    cmds.duplicate()    
    cmds.move( x, y-pivSnap, z, a=True, ws=True, wd=True )

def processTask():

    cmds.select( cmds.polyListComponentConversion( tv=True ) )      
    vertices = cmds.ls( sl=True )
    print( vertices )

    for vrtx in vertices:
        snapToVertex( vrtx, srcObj )

processTask()

enter image description here

Upvotes: 3

silent_sight
silent_sight

Reputation: 502

you could greatly simplify your code and only use a few commands

import maya.cmds as mc

verts = mc.ls(os=True)
src = 'pCone1'
base_name = 'fancy_cone'

for i, vert in enumerate(verts):
    dup = mc.duplicate(src, n='%s_%s' %(base_name, i))[0]
    mc.xform(dup, ws=True, t=mc.xform(vert, q=True, ws=True, t=True))

keep in mind a few caveats:

1) this is assuming that the pivot of your source cone is at the tip with the tip at the origin... so it requires setting up that source cone the way you want it as if the origin point is a vertex you will be snapping it to. This would also be beneficial if the object you're 'pinning' to is rotated (no need to do any kind of vector math to determine the positional offset that way)
2) to use the orderedSelection (os) flag in the ls command, you need to be sure track selection order is turned on in your maya preferences under the selection sub section - this way you can select the verts you want in the order you want them to be created (top-down, bottum-up, whatever) instead of the vert index order

This should also be significantly faster - by tracking any created objects, you don't actually need to select anything and can manipulate the objects directly. I also put it all into one loop without any function calls which would be faster (although, you probably won't notice it unless you're making a LOOOOOOT of these).

Depending on your needs though, you may actually want to utilize a snapping function multiple places; However, I would suggest keeping the duplication out of it in case there are situations you want to snap without duplicating.

Something like this (subject to same caveats as above):

import maya.cmds as mc

def snapToVertex(vertex, object):
    pos = mc.xform(vertex, q=True, ws=True, t=True)
    mc.xform(object, ws=True, t=pos)  # combine to single line if prefered

def processTask():
    verts = mc.ls(os=True)
    src = 'pCone1'
    base_name = 'fancy_cone'

    for i, vert in enumerate(verts):
        dup = mc.duplicate(src, n='%s_%s' %(base_name, i))[0]
        snapToVertex(vert, dup)

processTask()

Upvotes: 1

Related Questions