Wednesday, 23 August 2017

Tip #2: MDoubleArray Bug

I recently discovered that there is a bug with the Maya Python API when dealing with setting data in an MDoubleArray.

I was writing a few tools to deal with skinning information but found that my previously normalised values kept being adjusted to slightly below or slightly above 1. Visually this had little impact although seams on meshes had evidence of splitting under extreme deformation however I wanted precise results and so was confused with the values I was getting out of the tool.

When passing skinning information between different meshes on the same skeletal hierarchy it can be necessary to re-order the information to suit the influence order of one skin cluster to another. To deal with this part of the process one of my tools would read source skin data into an MDoubleArray then build a new MDoubleArray of the length of the number of influences on the target cluster. Part of this process involved passing weighting values per influence into a python variable to store them and then dropping that into the right location in the new MDoubleArray. I found that when passing the value back into the MDoubleArray was where it was altered. Python apparently does not have a type but its float types have double precision and at first I thought that this was to blame.

Try out the below in the script editor to see what I mean. I use Maya 2016 but I am under the impression that this happens in all versions of Maya.

import maya.OpenMaya as om
source = om.MDoubleArray()
source.setLength(1)
source.set(0.1234567890123, 0)
print source

When speaking with someone from Autodesk it turned out that the python wrapper for the API only passes data using the 'float' method of the MDoubleArray class and so the type conversion causes the error in value. This must affect hundreds of Maya Python scripts around the world so I am hoping this might get addressed in the future. In the meantime this is the way around the problem.

import maya.OpenMaya as om
source = om.MDoubleArray()
source.setLength(1)
source[0] = 0.1234567890123
print source

For some reason this way of setting the value gives a different, more accurate result. Make sure you have set the length of your MDoubleArray first or this will not work.

0 comments:

Post a Comment