CGTalk > Software > Autodesk Maya > Maya Programming
Login register
Thread Closed share thread « Previous Thread | Next Thread »  
 
Thread Tools Search this Thread Display Modes
Old 11-08-2013, 03:44 PM   #1
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,637
Send a message via ICQ to denisT
stript performance (Maya vs Max)

i'm moving some of my tools from max to maya and i already met some problems...
here is a test scene and object (poly cube with ~25K verts)
Code:
cmds.file(f=1,new=1) cmds.polyCube(n='pCube1',w=1,h=1,d=1,sx=64,sy=64,s z=64)


this is python API version to get all vert positions:
Code:
def getMeshPoints(meshFn): meshFnPoints = OpenMaya.MPointArray() meshFn.getPoints(meshFnPoints, OpenMaya.MSpace.kWorld) points = [] for i in xrange(meshFnPoints.length()): points.append([meshFnPoints[i][0], meshFnPoints[i][1], meshFnPoints[i][2]]) return points list = OpenMaya.MSelectionList() list.add('pCube1Shape') meshPath = OpenMaya.MDagPath() list.getDagPath(0,meshPath) meshFn = OpenMaya.MFnMesh(meshPath) t1 = cmds.timerX() pp = getPoints(meshPath) print cmds.timerX(startTime = t1) # 0.24


it takes 0.24 sec to collect all points. i'm not sure that i can do it faster with a script.
it's not technically very bad, but the same test with using only pure maxscript does do it for ~0.02 sec.
Code:
( n = box widthsegs:64 lengthsegs:64 heightsegs:64 m = snapshotasmesh n t1 = timestamp() for v=1 to m.numverts collect (getvert m v) print ((timestamp()-t1)*.001) ) -- 0.02


this is a 10 times difference. is it an expected performance? does it mean that i have to go with maya c++ API?
 
Old 11-08-2013, 03:48 PM   #2
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,637
Send a message via ICQ to denisT
10 time is the dramatic difference for me. it means that my tool looses real-time performance. and the tool makes no sense after that. am i really wasting my time with python or python API...
or there are some tricks to speed it up which i don't know about?

Last edited by denisT : 11-08-2013 at 03:52 PM.
 
Old 11-08-2013, 04:20 PM   #3
Keilun
Expert
Keilun
Canada
 
Join Date: Aug 2005
Posts: 738
Why are you converting this to a Python list? Is there a particular reason to not use the native MPointArray that's returned?

If you comment out that portion of your script, it runs very quickly. All of your time is spent extracting the 3 floats from each point and copying them into a Python list. If you were to do the same thing in MaxScript I'd imagine it'd slow down too.

Code:
import time import maya.OpenMaya as OpenMaya def getMeshPoints(path): meshFn = OpenMaya.MFnMesh(path) meshFnPoints = OpenMaya.MPointArray() meshFn.getPoints(meshFnPoints, OpenMaya.MSpace.kWorld) return meshFnPoints #points = [] #for i in xrange(meshFnPoints.length()): points.append([meshFnPoints[i][0], meshFnPoints[i][1], meshFnPoints[i][2]]) #return points list = OpenMaya.MSelectionList() list.add('pCube1Shape') meshPath = OpenMaya.MDagPath() list.getDagPath(0,meshPath) start = time.clock() pp = getMeshPoints(meshPath) end = time.clock() print end-start # 0.00456523622086

Last edited by Keilun : 11-08-2013 at 04:26 PM.
 
Old 11-08-2013, 05:16 PM   #4
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,637
Send a message via ICQ to denisT
Quote:
Originally Posted by Keilun
Why are you converting this to a Python list? Is there a particular reason to not use the native MPointArray that's returned?

i knew it and did it in purpose.
Quote:
If you comment out that portion of your script, it runs very quickly. All of your time is spent extracting the 3 floats from each point and copying them into a Python list. If you were to do the same thing in MaxScript I'd imagine it'd slow down too.

in max i put all points in mxs array to make the test fair.

the thing that have to avoid is probably do any API to native python type conversion if it's possible. but anyway as i said i'm enjoying the script+API very much.
 
Old 11-08-2013, 05:21 PM   #5
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,637
Send a message via ICQ to denisT
let's remove the appending to the list, but keep taking a data... for ... let me say... export, or get an average, or calculate a bounding box (i'm sure there are API methods for it, but it's a sample)
Code:
def getPoints(meshPath): meshFnPoints = OpenMaya.MPointArray() meshFn = OpenMaya.MFnMesh(meshPath) meshFn.getPoints(meshFnPoints, OpenMaya.MSpace.kWorld) for i in xrange(meshFnPoints.length()): meshFnPoints[i][0] meshFnPoints[i][1] meshFnPoints[i][2] return points list = OpenMaya.MSelectionList() list.add('pCube1Shape') meshPath = OpenMaya.MDagPath() list.getDagPath(0,meshPath) meshFn = OpenMaya.MFnMesh(meshPath) t1 = cmds.timerX() pp = getPoints(meshPath) print cmds.timerX(startTime = t1) # 0.22

Last edited by denisT : 11-08-2013 at 05:24 PM.
 
Old 11-08-2013, 05:52 PM   #6
Keilun
Expert
Keilun
Canada
 
Join Date: Aug 2005
Posts: 738
So one of the issues with the Python API 1.0 implementation is its basis on Swig which although automatic doesn't always make the most efficient conversion.

You can instead explore the Python API 2.0 if you're looking for something more performance critical. There are cases (this one included) where performance is up to 10x as fast as Python API 1.0.

The only caveat here is that since everything for Python API 2.0 was handcoded, not all C++ API classes have Python API 2.0 representations and you cannot interchange the two APIs. They cannot interpret each others objects. You can run them side by side however as long as they aren't trying to read objects from the other API.

For this case however, MFnMesh is supported as are the classes involved in this sample. You can read more about support here:

http://docs.autodesk.com/MAYAUL/201...-api/index.html

Here's the example converted to Python API 2.0:

Code:
import time import maya.api.OpenMaya as OpenMaya def getMeshPoints(path): meshFn = OpenMaya.MFnMesh(path) meshFnPoints = meshFn.getPoints(OpenMaya.MSpace.kWorld) points = [] for i in xrange(len(meshFnPoints)): points.append([meshFnPoints[i][0], meshFnPoints[i][1], meshFnPoints[i][2]]) return points list = OpenMaya.MSelectionList() list.add('pCube1Shape') meshPath = list.getDagPath(0) start = time.clock() pp = getMeshPoints(meshPath) end = time.clock() print end-start # 0.0197645971875
 
Old 11-08-2013, 05:57 PM   #7
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,637
Send a message via ICQ to denisT
thanks a lot Keilun for you guiding. python API 2.0 is the thing what i'm exploring now.
 
Old 11-08-2013, 07:41 PM   #8
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,637
Send a message via ICQ to denisT
Code:
cmds.polyCube(n='pCube1',w=1,h=1,d=1,sx=64,sy=64,s z=64) import maya.api.OpenMaya as api def getMeshPoints(mesh, space = api.MSpace.kWorld): meshFn = api.MFnMesh(mesh) points = meshFn.getPoints(space) for i in xrange(len(points)): points[i][0] points[i][1] points[i][2] return points import maya.OpenMaya as OpenMaya def getPoints( mesh, space = OpenMaya.MSpace.kWorld): points = OpenMaya.MPointArray() meshFn = OpenMaya.MFnMesh(mesh) meshFn.getPoints(points,space) for i in xrange(points.length()): points[i][0] points[i][1] points[i][2] return points list = api.MSelectionList() list.add('pCube1Shape') mesh = list.getDagPath(0) t1 = cmds.timerX() pp = getMeshPoints(mesh) print cmds.timerX(startTime = t1) # 0.01 list = OpenMaya.MSelectionList() list.add('pCube1Shape') meshPath = OpenMaya.MDagPath() list.getDagPath(0,meshPath) t1 = cmds.timerX() pp = getPoints(meshPath) print cmds.timerX(startTime = t1) # 0.18


the big difference 0.01 vs 0.18... i can work with it now... unfortunately there is a blocker. it seems like there is no OpenMayaAnim in 2.0 :(
 
Old 11-09-2013, 01:56 AM   #9
zaskar
Expert
portfolio
franky****inFourFingaz
-
Dresden, Germany
 
Join Date: Dec 2010
Posts: 321
Dont know if it helps you with your python approach but if using the API i recognised that the MFnMesh.getPoints() method is damn slow compared with multiplying the raw points with the transforms world matrix. Here an example, maybe you can translate it efficiently into python:
Code:
MDagPath dagPath = MDagPath::getAPathTo( mesh ); // mesh: the MObject MFnMesh meshFn(dagPath); const unsigned int numVertices = meshFn.numVertices(); MMatrix matrix = dagPath.exclusiveMatrix(); double mtx[16]; for(unsigned int m=0; m<=3; m++){ double* ptr = matrix[m]; for(unsigned int n=0; n<=3; n++){ mtx[m * 4 + n] = ptr[n]; }; }; const float* rawPts = meshFn.getRawPoints(&stat); float x, y, z; MFloatPointArray fPts(numVertices); for(unsigned int k=0; k<numVertices; ++k) { x = *rawPts; ++rawPts; y = *rawPts; ++rawPts; z = *rawPts; ++rawPts; fPts[k].x = float(x * mtx[0] + y * mtx[4] + z * mtx[8] + mtx[12]); fPts[k].y = float(x * mtx[1] + y * mtx[5] + z * mtx[9] + mtx[13]); fPts[k].z = float(x * mtx[2] + y * mtx[6] + z * mtx[10] + mtx[14]); };
 
Old 11-09-2013, 02:31 AM   #10
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,637
Send a message via ICQ to denisT
thank you so much. i will dig into it for sure. i'm absolutelly sure that this maya community knows a lot of tricks which can make an impossible to be possible. if you would need any help with MAX you will be welcome on the MAX branch on this forum. most of my 6K whists were made there
 
Old 11-09-2013, 03:31 AM   #11
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,637
Send a message via ICQ to denisT
Quote:
Originally Posted by zaskar
Dont know if it helps you with your python approach but if using the API i recognised that the MFnMesh.getPoints() method is damn slow compared with multiplying the raw points with the transforms world matrix.

i have no idea what the raw points is yet. but i will.
interesting... according to the documentation
Code:
MStatus getPoints (MFloatPointArray &vertexArray, MSpace::Space space=MSpace::kObject) const

they make this array on the fly... but what can be easier than just multiply a point and a matrix?
 
Old 11-09-2013, 12:13 PM   #12
sirpalee
death from above
 
sirpalee's Avatar
portfolio
Pal Mezei
Software Engineer
Luma Pictures
Melbourne, Australia
 
Join Date: Feb 2004
Posts: 88
Python is not exactly designed (especially the pythonic api) to work with this kind of / amount of data. You really should look into the C++ api.
 
Old 11-09-2013, 12:13 PM   #13
CGTalk Moderation
Expert
CGTalk Forum Leader
 
Join Date: Sep 2003
Posts: 1,066,478
Thread automatically closed

This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.
__________________
CGTalk Policy/Legalities
Note that as CGTalk Members, you agree to the terms and conditions of using this website.
 
Thread Closed share thread


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
CGSociety
Society of Digital Artists
www.cgsociety.org

Powered by vBulletin
Copyright 2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump
Miscellaneous

All times are GMT. The time now is 04:49 PM.


Powered by vBulletin
Copyright ©2000 - 2016, Jelsoft Enterprises Ltd.