MFnMesh.setNormals not working

687 views
Skip to first unread message

Chadrik

unread,
Feb 12, 2009, 6:46:11 PM2/12/09
to python_inside_maya
i'm having another one of those api "what?!" moments. someone please
help me to understand what i'm doing wrong. i'm making a sphere and
trying to invert it's normals, but MFnMesh.setNormals seems to only
incrementally set the normals. each time i run it with the same set of
input normals and the normals get closer to the desired values without
ever actually getting set all the way.

import maya.cmds as cmds
import maya.mel as mel
import maya.OpenMaya as api

# make the sphere and get the MFn
mesh, h = cmds.polySphere( sa=10, sh=10 )
mel.eval( 'setPolygonDisplaySettings("vNormal")' )
mesh = cmds.listRelatives( mesh, s=1)[0]
sel = api.MSelectionList()
sel.add( mesh )
dag = api.MDagPath()
sel.getDagPath(0,dag)
meshFn = api.MFnMesh( dag )

# invert the vertex normals
normalArray = api.MFloatVectorArray()
newNormalArray = api.MFloatVectorArray()

meshFn.getNormals( normalArray, api.MSpace.kWorld )
for i in range( normalArray.length() ):
normal = normalArray[i]
newNormalArray.append( normal * -1 )

# set the new, inverted vertex normals
meshFn.setNormals( newNormalArray, api.MSpace.kWorld )

# new get the normals. they should be the same as what we just set,
right?
checkNormalArray = api.MFloatVectorArray()
meshFn.getNormals( checkNormalArray, api.MSpace.kWorld )

def angularDiff( arrayOne, arrayTwo ):
"add up the absolute angular difference between two vector arrays and
print it out"
sumAngles = 0.0
for i in range( arrayOne.length() ):
newNormal = arrayOne[i]
checkNormal = arrayTwo[i]
sumAngles += abs( newNormal.angle( checkNormal ) )
print sumAngles

angularDiff( newNormalArray, checkNormalArray)
# 227.588285092

meshFn.setNormals( newNormalArray, api.MSpace.kWorld )
meshFn.getNormals( checkNormalArray, api.MSpace.kWorld )
angularDiff( newNormalArray, checkNormalArray)
#11.7161702135

meshFn.setNormals( newNormalArray, api.MSpace.kWorld )
meshFn.getNormals( checkNormalArray, api.MSpace.kWorld )
angularDiff( newNormalArray, checkNormalArray)
#5.86650015175

meshFn.setNormals( newNormalArray, api.MSpace.kWorld )
meshFn.getNormals( checkNormalArray, api.MSpace.kWorld )
angularDiff( newNormalArray, checkNormalArray)
#2.94336352771

meshFn.setNormals( newNormalArray, api.MSpace.kWorld )
meshFn.getNormals( checkNormalArray, api.MSpace.kWorld )
angularDiff( newNormalArray, checkNormalArray)
#1.48185980244


i feel like i must be getting tripped up with c++ pointer methodology
in python somewhere but i can't see where. any help would be greatly
appreciated.

btw, this group is really growing into a great list. it's got a great
mixture of gurus and newbs all helping each other out in their various
areas of expertise. good stuff.

-chad

Matthew Chapman

unread,
Feb 12, 2009, 8:18:47 PM2/12/09
to python_in...@googlegroups.com
Man this is crazy bug! I tried it at first and it didn't work. Then I added the multiple calls as you did and it worked. I tried moving it around a bit and found that I could get it to work if  I add another  setNormal()  at the end. This is on a linux 64 bit maya 8.5 sp1. I might try setFaceVertexNormals if it will produce the results you are looking for. Ive also noticed in the past certain times working in the python maya api that if I did'nt wrap my code into a function or class the effect would not happen in maya until I manually "del()" the objects. I think a flaw in some of the swig maya api objects is they don't fully run until destruction. This did'nt work in this case but I have run into it a bit in the past.

Matt




import maya.cmds as cmds
import maya.mel as mel
import maya.OpenMaya as api

# make the sphere and get the MFn
mesh, h = cmds.polySphere( sa=10, sh=10 )
mel.eval( 'setPolygonDisplaySettings("vNormal")' )
mesh = cmds.listRelatives( mesh, s=1)[0]
sel = api.MSelectionList()
sel.add( mesh )
dag = api.MDagPath()
sel.getDagPath(0,dag)
meshFn = api.MFnMesh( dag )

# invert the vertex normals
normalArray = api.MFloatVectorArray()
newNormalArray = api.MFloatVectorArray()

meshFn.getNormals( normalArray, api.MSpace.kWorld )
for i in range( normalArray.length() ):
       normal = normalArray[i]
       newNormalArray.append( normal * -1 )

# set the new, inverted vertex normals
meshFn.setNormals( newNormalArray, api.MSpace.kWorld )

checkNormalArray = api.MFloatVectorArray()
meshFn.getNormals( checkNormalArray, api.MSpace.kWorld )
#Adding this here made it work with out multiple calls on my machine
#meshFn.setNormals( newNormalArray, api.MSpace.kWorld )


def angularDiff( arrayOne, arrayTwo ):
       sumAngles = 0.0
       for i in range( arrayOne.length() ):
               newNormal = arrayOne[i]
               checkNormal = arrayTwo[i]
               sumAngles += abs( newNormal.angle( checkNormal ) )
       print sumAngles

angularDiff( newNormalArray, checkNormalArray)
# 227.588285092

meshFn.setNormals( newNormalArray, api.MSpace.kWorld )
meshFn.getNormals( checkNormalArray, api.MSpace.kWorld )
angularDiff( newNormalArray, checkNormalArray)
#11.7161702135

meshFn.setNormals( newNormalArray, api.MSpace.kWorld )
meshFn.getNormals( checkNormalArray, api.MSpace.kWorld )
angularDiff( newNormalArray, checkNormalArray)
#5.86650015175

596.902620792
0.0
0.0



Reply all
Reply to author
Forward
0 new messages