Everything is much easier.
For MFnMesh
, a function is available to return the name to a string representation: fullPathName
Returns the full path of the attached object, from the root of the DAG on down.
Inherited from: MFnDagNode
https://help.autodesk.com/view/MAYAUL/2022/ENU/?guid=Maya_SDK_py_ref_class_open_maya_1_1_m_fn_dag_node_html
To assign a material to an object, you do not need to first select that object.
You will need to specify the name of the mesh, or the names of the specific polygons to which you want to assign the desired material.
import maya.api.OpenMaya as om
import maya.cmds as cmds
# For example, let's create a new mesh consisting of two triangular polygons
# (adding polygons in turn):
vertArray = om.MPointArray()
vert_point = [(0,0,0,1),(1,0,0,1),(1,0,1,1),(0,0,1,1)]
mesh_DG_name = om.MFnMesh()
# Create the first polygon for points: 0, 3, and 2.
# (with merge Vertices and merge Tolerance = 0.0 )
mesh_DG_name.addPolygon( vertArray.copy( map(vert_point.__getitem__, [0,3,2]) ), 1, 0.0 )
# Create a second polygon for points: 2, 1, and 0
mesh_DG_name.addPolygon( vertArray.copy( map(vert_point.__getitem__, [2,1,0]) ), 1, 0.0 )
# Obviously, we are building all polygons counter-clockwise,
# this determines the direction of the normal for the polygon.
# If we tried to build the second polygon in a clockwise direction,
# it would mean generating a little bit of geometry.
# Since we specified the merge for vertices with the same coordinates in the construction options,
# the polygons must have a common edge, but the normals must look in different directions.
# Maya does not allow you to create nonmanifold geometry.
# Therefore, the creation of the second polygon would be ignored.
# Next, get the name of the created mesh
mesh_fullPathName = mesh_DG_name.fullPathName()
# shape_name = mesh_DG_name.absoluteName()
# transform_name = mesh_DG_name.fullPathName().split('|')[1]
# Turn ON the display of materials and textures:
for item in ['modelPanel1', 'modelPanel2', 'modelPanel3', 'modelPanel4']:
cmds.modelEditor(item, edit = True,
dtx = 1, # display textures
cme = 1, # colormanagement
ocl = 0, # display oclusion culling
shadows = 0, # display shadows
swf = 1, # smoth wireframe
tx = 1, # display textures objects
udm = 0, # use default material
wos = 1, # wireframe on shaded
xr = 0) # XRay on/off
# Let's get closer:
cmds.viewFit( mesh_fullPathName, animate = True, allObjects = True )
# 1. Assign the default Lambert shader for the entire mesh ( initialShadingGroup ):
cmds.sets( mesh_fullPathName, edit = True, forceElement = 'initialShadingGroup' )
# Or just for some polygons:
cmds.sets(mesh_fullPathName + '.f[1]', e = 1, forceElement = 'initialShadingGroup')
# 2. Let's create a new Lambert material (or any other Shader):
# Create the Lambert material:
MY_LAMBERT_SHADER = cmds.shadingNode( 'lambert', asShader = True, name = 'MY_LAMBERT_MATERIAL' )
#Creating a SHADING ENGINE:
MY_SHADING_ENGINE = cmds.sets( renderable = True, noSurfaceShader = True, empty = 1, name = ( MY_LAMBERT_SHADER + '_SG' ) )
# We connect the resulting Lambert material with the input slot for the surface material:
cmds.connectAttr( MY_LAMBERT_SHADER + '.outColor', MY_SHADING_ENGINE + '.surfaceShader' )
# Set purple colot from attribute "color" for Lambert material:
cmds.setAttr(MY_LAMBERT_SHADER + '.color', 1.0, 0.0, 1.0, type = 'double3')
# Let's assign this new material:
cmds.sets( mesh_fullPathName, edit = True, forceElement = MY_SHADER_SG )
# Let's create and assign a chesker to the color chanel:
# create chesker:
MY_CHECKER = cmds.shadingNode('checker', asTexture = 1, name = 'MY_ERROR_CHECKER')
cmds.setAttr(MY_CHECKER + '.color1', 0.0, 0.0, 0.0, type = 'double3')
cmds.setAttr(MY_CHECKER + '.color2', 1.0, 0.0, 1.0, type = 'double3')
# create tex2dPlacement for chesker:
MY_CHECKER_tex2dPlacement = cmds.shadingNode("place2dTexture", asUtility = True, name = 'place2dTex__for_' + MY_CHECKER)
cmds.setAttr(MY_CHECKER_tex2dPlacement + '.ihi', 0)
cmds.setAttr(MY_CHECKER_tex2dPlacement + '.repeatU', 4)
cmds.setAttr(MY_CHECKER_tex2dPlacement + '.repeatV', 4)
# we conect tex2dPlacement with chesker:
cmds.connectAttr(MY_CHECKER_tex2dPlacement + '.outUV', MY_CHECKER + '.uvCoord')
cmds.connectAttr(MY_CHECKER_tex2dPlacement + '.outUvFilterSize', MY_CHECKER + '.uvFilterSize')
# we conect chesker with shader color chanel:
cmds.connectAttr(MY_CHECKER + '.outColor', MY_LAMBERT_SHADER + '.color')
# Whoops... we don't see a checker on polygons.
# That's because polygons don't have UV coordinates!
# Let's fix:
# Requesting the name of the current UV set:
curent_UVset_name = mesh_DG_name.getUVSetNames()[-1]
# set UVs:
mesh_DG_name.setUVs( (0.0, 1.0, 1.0, 0.0), (0.0, 0.0, 1.0, 1.0), curent_UVset_name )
# assign UVs:
mesh_DG_name.assignUVs((3,3),(0,3,2,2,1,0),curent_UVset_name)
# Voila!
# Let's try to connect the texture file instead of the checker:
# We will use a texture file from standard Maya.
# Get Maya installation path:
import os
maya_pth = sl_g_maya_dir = str(os.environ['MAYA_LOCATION'])
img_pth = maya_pth + '/brushImages/hotelFacade.jpg'
# Let's create a function to create a file node along with a place2dTexture node
# from the specified path
def createFileTexture(filename, nodename, colorManagement = True):
file_nodename = 'file__' + nodename
tex2d_nodename = 'place2dTex__' + nodename
# Create file node:
texFile = cmds.shadingNode('file', name = file_nodename , asTexture = True, isColorManaged = colorManagement)
cmds.setAttr(texFile + '.uvTilingMode', 0)
# from the specified path
cmds.setAttr(texFile + '.fileTextureName', filename, type = 'string')
# Create a place2dTexture node and connect it to the file node
tex2dPlacement = cmds.shadingNode('place2dTexture', name = tex2d_nodename, asUtility = True)
cmds.connectAttr(tex2dPlacement + '.outUV', texFile + '.uvCoord')
cmds.connectAttr(tex2dPlacement + '.outUvFilterSize', texFile + '.uvFilterSize')
cmds.connectAttr(tex2dPlacement + '.vertexCameraOne', texFile + '.vertexCameraOne')
cmds.connectAttr(tex2dPlacement + '.vertexUvThree', texFile + '.vertexUvThree')
cmds.connectAttr(tex2dPlacement + '.vertexUvTwo', texFile + '.vertexUvTwo')
cmds.connectAttr(tex2dPlacement + '.vertexUvOne', texFile + '.vertexUvOne')
cmds.connectAttr(tex2dPlacement + '.repeatV', texFile + '.repeatV')
cmds.connectAttr(tex2dPlacement + '.repeatU', texFile + '.repeatU')
cmds.connectAttr(tex2dPlacement + '.rotateFrame', texFile + '.rotateFrame')
cmds.connectAttr(tex2dPlacement + '.offsetV', texFile + '.offsetV')
cmds.connectAttr(tex2dPlacement + '.offsetU', texFile + '.offsetU')
cmds.setAttr(tex2dPlacement + '.ihi', 0)
return texFile, tex2dPlacement
# Run the function:
create_texture = createFileTexture(img_pth, 'albedo', colorManagement = True)
# Disconnect the checker node from the color channel:
cmds.disconnectAttr(MY_CHECKER + '.outColor', MY_LAMBERT_SHADER + '.color')
# We connect the node file with the color channel:
cmds.connectAttr(create_texture[0] + '.outColor', MY_LAMBERT_SHADER + '.color')