Feedback

What's your question?

By: Asked

How do I use the paint attribute tool to paint values into objects located at mesh vertices

I have laid out the info here on my blog:

a href=http://www.hodge.net.au/sam/blog/?p=176

Basically I would like to be able to paint the scale offset of a bunch of geometry hugging to a surface

As scales or feathers.

Ideally I would like to be able to paint 9 grey scale maps tx,ty,tz,rx,ry,rz,sx,sy,sz

I am wanting to do this as a vertex map, looking up the vert for each scale.

But trying to get at a component via an expression or connected attribute seems tougher than it should be.

Is there some mapping that I am not observing.

I guess polyBlindData and a bunch of plugin code would work, but I cant see why what I am doing isnt working

I have done this kind of stuff in XSI before and it wasnt this hard, there was an extra layer ie mesh vert ID != cluster component ID, but the mapping was well documented and accesible.

Where is the mapping between control points array position and vertex position?

Add comment viewed 875 times Latest activity 7 months ago

or Cancel

2 answers

  • 3

julian [ Admin ]

Here's some MEL which should be enough to test the attribute-paint vertex indices. It doesn't paint offsets, just direct values to scale and rotate. I tested it on very messy mesh, with a lot of booleans and deleted components, and it seems to hold ok. If you get it working with python, feel free to post it here as another answer ;) Meanwhile I'll add a MEL tag.

To use it, select a mesh and type paintedLocators(); Then use Modify->Paint Attributes Tool

// a proc to place a locator at every vertex
global proc string[] makeLocatorsAtVertices(string $shape) {
    string $locators[]; 
    string $vts[] = `ls -flatten  ($shape+".vtx[*]")`;
    for ($v in $vts) {
        float $p[] = `pointPosition -w $v`;
        string $locs[] = `spaceLocator`;
        setAttr  ($locs[0] + ".t") $p[0] $p[1] $p[2];
        $locators[`size $locators`] = $locs[0] ;
    }
    return $locators;
}


global proc paintedLocators() {

    string $sel[] = `ls -sl -dag -leaf -type "mesh"`;
    string $shape = $sel[0];

    string $locs[] = makeLocatorsAtVertices($shape);
    int $n = size($locs);

    // Make paintable scale and rotate attributes - data type will be multi-float
    // Connect paintable attribute elements to the locator at the matching array position.
    // Set scale default value to 1
    for ($att in {"rx","ry","rz","sx","sy","sz"}) {
        int $isScaleAtt = (substring($a,1,1) == "s");
        addAttr -ln ("feather_"+$att) -im 1 -m -at "float" $shape; 
        makePaintable  -at "multiFloat" "mesh" ("feather_"+$att) ;
        for ($i=0;$i<$n;$i++){
            connectAttr -f ($shape + ".feather_"+$att+"["+$i+"]")   ($locs[$i] + "."+$att) ;
            if ($isScaleAtt) setAttr ($shape + ".feather_"+$att+"["+$i+"]") 1.0;
        }
    }
    select $shape; 
}

One more thing I got some errors at first. There were some lines in an installed maya script that were failing. If you get "procedure not found" errors when you try to select the attribute in the paint attributes tool, comment out the lines in artAttrCreateMenuItems.mel as follows:

change Line 190: to:

} else if ( $paintableNodeType == "mesh") {

and comment out lines 200 - 205

// if ( $currTool != "artClothPaint" ) 
// {
//  artClothPaintToolScript( 4 );
// } else {
//  clothPaintToolOn();
// }

and re source it

NN comments
sam hodge
-

This code seems to do what I need. I will have a look into making it in Python as soon as I get a chance.

or Cancel
  • 1

sam hodge

I have ported Julian's Answer to Python but I am getting an error:

// Error: Cannot find procedure "isValidAttrName". //

Any ideas?



"""
import maya, os, sys

cmds = maya.cmds

#Save file here as "vfxOverflow.py"

devPath = "/home/samh/"


print sys.path
if devPath not in sys.path:
    #sys.path = list(sys.path.replace(devPath + ":","")
    sys.path.insert(0,devPath)

import vfxOverflow
reload(vfxOverflow)

#maya.cmds.delete("locator*")

maya.cmds.file(new=True,force=True)

newGrid = maya.cmds.polyPlane(ch=False,o=True,width=25,height=25,cuv=2,sw=10,sh=10)[0]

newGridShape = maya.cmds.listRelatives(shapes=True)[0]

maya.cmds.select(newGridShape)

vfxOverflow.paintedLocators()

"""

import maya

def makeLocatorsAtVertices( shapeNode,template=True):
    polyE = maya.cmds.polyEvaluate()
    count = polyE["vertex"]
    positions = [maya.cmds.getAttr("%s.vt[%d]" % (shapeNode,i) )[0] for i in range(count)]
    locators = ["%s" % maya.cmds.spaceLocator(position=(0,0,0))[0] for i in range(count)]
    [maya.cmds.setAttr("%s.translateX" % locators[i],positions[i][0]) for i in range(count)]
    [maya.cmds.setAttr("%s.translateY" % locators[i],positions[i][1]) for i in range(count)]
    [maya.cmds.setAttr("%s.translateZ" % locators[i],positions[i][2]) for i in range(count)]
    [maya.cmds.setAttr("%s.template"%i,template) for i in locators]
    return locators


def paintedLocators(attrs = ["tx","ty","tz","rx","ry","rz","sx","sy","sz"], attributePrefix = "feather",scaleMax=5.0,transMax=5.0):
    shape = maya.cmds.ls(selection=True,dag=True,type="mesh")[0]
    locs = makeLocatorsAtVertices(shape)
    count = len(locs)
    isFirst = 1
    counter = 0
    print attrs
    for i in attrs:
        print i
        isScale = ("s"==i[0])
        isRotation = ("r"==i[0])
        isTranslation = ("t"==i[0])
        print maya.cmds.addAttr(shape,longName="%s_%s" % (attributePrefix,i),defaultValue=0.5,indexMatters=True,multi=True,attributeType="float")
        print maya.cmds.makePaintable( "mesh", "%s_%s" %  (attributePrefix,i),attrType = "multiFloat")
        for j in range(count):
            attributeData = "%s.%s_%s[%d]" % (shape,attributePrefix,i,j)
            print maya.cmds.getAttr(attributeData)
            locatorData = "%s.%s" % (locs[j],i)
            if isScale:
                maya.cmds.expression(string="%s=1 + (%s - 0.5)*%s" % (locatorData,attributeData,2*scaleMax))
            if isRotation:
                maya.cmds.expression(string="%s=(%s - 0.5)*%s" % (locatorData,attributeData,2*180))     
            if isTranslation:
                initialLocation = maya.cmds.getAttr("%s.%s" % (locs[j],i))
                maya.cmds.expression(string="%s=%s + (%s - 0.5)*%s" % (locatorData,initialLocation,attributeData,2*transMax))

NN comments
sam hodge
-

actually this working pretty well in maya 2008 but not in 2010, I will see how it goes in older versions, I think it is because cloth support has been removed and that is where some of the paintable attributes stuff is coming from

julian
-

I had that error too “isValidAttrName” when I was first testing, and I mentioned it in the post here, but then deleted that bit because I thought it was something to do with an error with my maya install. Anyway, I just undeleted it – so it is in the answer above now.

or Cancel