View Full Version : Get mesh data?
AtrusDni 12-04-2008, 09:26 PM Hello everyone, im looking for a way to get the mesh data:
vertex positions
normals
uvs
face conencts
etc
from a mesh in a relatively easy fashion. Preferably I would like to use Python API to query the values and format the data and write it out to disk. I have been to Rob The Blokes website, but all that stuff is written for Maya API, not Python API, so the syntax is different. Any help would be much appreciated. Thanks!
|
|
python imports the maya API-- you should be able to read and translate it for your uses. Unfortunately I do not know python well but I have written an ASE exporter completely in MEL if you would like to take a look at that.
AtrusDni
12-05-2008, 09:37 PM
Sure, any information would be appreciated. Thanks!
ok, I attached a copy of my exporter. I know I commented a lot of stuff but it is still a work in progress and is not finalized by any means. It is a stable build though. I would consider it in beta phase as of now.
let me know if you have any questions on the methods or procedures.
AtrusDni
12-05-2008, 10:43 PM
Thanks Eric, i'll take a look. One of the reasons I wanted to use the python API is the speed. I was working on a 3DXML import script in maya, and it worked, but it was REALLY REALLY slow. Using the API it was a LOT faster, but im still learning it and am not familiar with it very well. How does your script preform speed-wise? Just curious. Thanks again and I will check it out.
AtrusDni
12-05-2008, 11:23 PM
Hey Eric, I took a look at your script. Its pretty straightforward and should do the trick. It looks like how I would manage it, and I guess speed is pretty fast because its writing to (in my case a text file) which is fast enough. I know there is a huge slow down when creating the meshes, but using mel to extract that data shouldnt be too bad. Thanks for the help!
Yes, the only reason I did not use the maya API with this exporter was because I am not familiar with the API at all or Python. I feel it would be a good script for me to learn python by converting all the code. It will definitly be faster with the API and another added bonus is that you can use python as a "script plugin" (non compiled).
I spent at least 2 or 3 days at work optomizing the speed of the code. I learned it is much faster to create an array of data and loop through the strings and write them as a procedure at the end rather than write the lines on-the-fly. I have yet to find a faster method for doing the mesh smooth groups.
the script gets slower when you start turning on some of the other features. the most intensive one is the mesh smooth groups because maya does not work with these natively (like 3DS Max does) and the only methods to get the edge smooth data are not pretty at all (very redunant and slow). I do not know what file format you intend to work with but if you do not need smooth groups the MEL will be pretty fast still.
oh keep in mind that as noted at the top of my script I did NOT test the face/vrtx normal procedure-- I know it will get the data but I was not sure if my calculations for converting it to the Z-Up axis were correct-- I did not have an engine to test this on nor another ASE exporter to compare. Also, some of the other procedures are setup to automatically convert to a Z-Up axis.
[EDIT] -- for some reason I never got email notifications with your replies :curious:
AtrusDni
12-08-2008, 02:59 PM
Hey Eric, so i modified the code and ended up just querying the face normals directly and using those values, and it worked! Eh, for the most part. Im exporting to dxmesh, which most people have not heard of, but its for a program called DXStudio. Anyways, thanks for your help. Curiously though, I could be just crazy, but I am compaing the speed of MEL (no mesh smoothing info) to Chad Vernon's cvXporter, (which is python based using the API) it almost seems faster. I would have to do more tests to be sure.
that is interesting. I would be glad to hear the results of your tests. Like I said previously I spent a good amount of time optimizing the codes speed. The way I setup my scripts I was able to isolate specific procedures and compare their speeds using an online stopwatch (fairly accurate but not as good as the real thing due to user error). For some reason I cant imagine the API being slower but perhaps that cvXporter is using outdated code or something.
NaughtyNathan
12-08-2008, 03:33 PM
Hey Eric, don't you use the MEL command timerX for timing stuff in Maya/MEL..?
Also, you're doing so much stuff with string arrays in these procs that if you did re-write it in python it'd probably be about 10 times quicker, and that's even without touching the API at all...! :D
:nathaN
nope I have never used timerX for anything but it looks like it could be a good help, thanks!
and yeah, with multi-dimensional or nested arrays (whatever you prefer to call em) managing the data would be much faster. I think I may pickup a command reference for python and start looking at converting this script. (although we dont use ASE files at work anymore and Epic has phased them out as well... not sure how much longer they will be around.)
oh do either of you use vertex color data? I have never used this nor does our engine at work support it (I think..) so I have been unable to gather and test any of this data.
AtrusDni
12-08-2008, 05:45 PM
About vertex color data - Nope. Never used it, I would just rather make a lightmap (more detail). :)
I would recommend learning Python. I know it fairly well, but its the API stuff that confuses me, mainly because theres not a lot of documentation on it when using it through the Python wrapper. I know how to create a mesh ok with it using existing data, but I cannot figure out the syntax on how to read the data from an existing mesh. :(
I've been to Rob the Bloke's website, but again, the syntax is different in python, so I understand the process, but I dont know exactly how to type it.
I rewrote a shatter script I made in mel to python, and a 3dxml file reader from mel to python to help me get the basics. To be honest, I hated python and thought it was pointless to have, especially since maya already has mel. But after using it the power of it is definitely noticeable. Plus any python package you find can be used in maya. I got PIL (python imaging library) working with Maya so now I can easily write out image files by specifying the rgb values per pixel, (which is hard to do without diving into the API).
its kind of funny because my first maya script I started in python because the syntax was more familiar to me than MEL. after I learned the MEL syntax it just kinda clicked how much faster I could script with it rather than python.
I got PIL (python imaging library) working with Maya so now I can easily write out image files by specifying the rgb values per pixel, (which is hard to do without diving into the API).
wish I had that PIL thing back at the begining fo the year, I was writing a script to automate thumbnail preview images for assets to be organzied on a central database. 3DS Max can do this natively with MaxScript (which I find more powerful than MEL in many areas and interfaces are soooo much easier)
A nice advantage to Python is that I can still use all the normal MEL commands that I am familiar with-- one thing that MEL does do better than python is handling vectors-- cant remember the reason why but python seems to have issues with vectors.
RyanT
12-08-2008, 07:27 PM
You guys might be interested in my site. I have been blogging code snippets of python and why I like using it over MEL. I have some examples of how python works differently with the API than say C++. For example since python does not have pointers you have to use the MScriptUtil class to create a fake pointer to pass to classes that pass by reference. My hope is to slowly build up some examples to demystify it somewhat. I am come at it from the angle that many are not using python at all so I have several examples for people that are new to python as well.
I also give an example of how to use MMatrix and MVector so that you will have ways to work with both even though python has no built in classes for those.
www.rtrowbridge.com/blog (http://www.rtrowbridge.com/blog)
AtrusDni
12-08-2008, 07:37 PM
Very nice site Ryan. Maybe you could help me out then on the original question. Do you know how to query mesh data (triangle count, face connects) with the API through python? at least the proper syntax?
RyanT
12-08-2008, 09:34 PM
I have no way to test this right now, I can try to get you something more solid later tonight. First if you dont know there is a document in the maya docs that shows all the API classes. You need to find this. There is a link to it from the main maya help documents near the bottom in the API section. This code example is very simplistic but shows how you would basicly use the classes and which classes you should be using. Each class has many functions. If a function says "No Script Support" it will not work with python. Ill say it again this is not tested so it might have syntax errors.
# Get the selection and create a selection list of all the nodes meshes
selection = OpenMaya.MSelectionList()
OpenMaya.MGlobal.getActiveSelectionList( selection );
# Create an itorator to iterate over the selection
# Use the MFn class to as a filter to filter node types
iter = OpenMaya.MItSelectionList ( selection, OpenMaya.MFn.kGeometric );
# Iterate through selection
while not iter.isDone():
# Get the selection as an MObject
mObj = OpenMaya.MObject()
iter.getDependNode( mObj )
iterMeshData = OpenMaya.MItMeshPolygon( mObj )
# Get connected faces
indexConFaces = OpenMaya.MIntArray()
iterMeshData.getConnectedFaces( indexConFaces )
# Iterate through connected faces
for i in range( iterMeshData.length ):
print iterMeshData[ i ]
# Get triangles
pntAry = OpenMaya.MPointArray()
intAry = OpenMaya.MIntArray()
space = OpenMaya.MSpace.kWorld
# Get the vertices and vertex positions of all the triangles in the current face's triangulation.
iterMeshData.getTriangles(pntAry, intAry, space)
# Get the number of triangles
intptr = OpenMaya.MScriptUtil().asIntPtr()
numTris = iterMeshData.numTriangles( intptr )
getNumTris = OpenMaya.MScriptUtil.getInt( intptr )
print getNumTris
# Go on to the next selected node
iter.next()
RyanT
12-09-2008, 12:38 AM
Sorry, as I suspected the above code had some issues. First I did not show how to import the API modules and I had some errors in the code. Check this out:
import maya.OpenMaya as OpenMaya
import maya.OpenMayaMPx as OpenMayaMPx
# Get the selection and create a selection list of all the nodes meshes
selection = OpenMaya.MSelectionList()
OpenMaya.MGlobal.getActiveSelectionList( selection );
# Create an itorator to iterate over the selection
# Use the MFn class to as a filter to filter node types
iter = OpenMaya.MItSelectionList ( selection, OpenMaya.MFn.kGeometric );
# Iterate through selection
while not iter.isDone():
# Get the selection as an MObject
mObj = OpenMaya.MObject()
iter.getDependNode( mObj )
iterMeshData = OpenMaya.MItMeshPolygon( mObj )
# Get connected faces
indexConFaces = OpenMaya.MIntArray()
iterMeshData.getConnectedFaces( indexConFaces )
# Iterate through connected faces
for i in range( indexConFaces.length() ):
print indexConFaces[ i ]
# Get triangles
pntAry = OpenMaya.MPointArray()
intAry = OpenMaya.MIntArray()
space = OpenMaya.MSpace.kObject
# Get the vertices and vertex positions of all the triangles in the current face's triangulation.
iterMeshData.getTriangles(pntAry, intAry, space)
# Get the number of triangles
intptr = OpenMaya.MScriptUtil().asIntPtr()
numTris = iterMeshData.numTriangles( intptr )
getNumTris = OpenMaya.MScriptUtil.getInt( intptr )
print getNumTris
# Go on to the next selected node
iter.next()
AtrusDni
12-09-2008, 12:55 AM
Ryan, I think you just became my new best friend! YAY! Lol. Thanks a lot for the example. Very informative. I'm going to dissect it and try to learn as much as I can from it. I'm sure I will have some questions for you, if you dont mind?
RyanT
12-09-2008, 01:03 AM
Sure I will try to help as best as I can. I will probably post a more expanded version of that script on my site later.
RyanT
12-09-2008, 04:23 PM
I worked on it a bit more and put something together that iterates through each polygon on the mesh and gets the vertices for that polygon, the edges, the connected polygons, and the vertices for the triangles. I have some extra help on my site as well. Check it out:
# the OpenMaya module has many of the general Maya classes
# note that some Maya classes require extra modules to use which is noted in the API docs
import maya.OpenMaya as OpenMaya
# This shows how to use the MSelectionList and MGlobal class
# Get the selection and create a selection list of all the nodes meshes
selection = OpenMaya.MSelectionList()
OpenMaya.MGlobal.getActiveSelectionList( selection );
# Create an MItSelectionList class to iterate over the selection
# Use the MFn class to as a filter to filter node types
iter = OpenMaya.MItSelectionList ( selection, OpenMaya.MFn.kGeometric );
# This uses build in functions of the MItSelectionList class to loop through the list of objects
# Note this is not a basic array you must use its built in functions iterate on its objects
# Iterate through selection
while not iter.isDone():
vertexList = []
edgeList = []
polytriVertsList = []
polyList = []
conpolyList = []
# Get MDagPath from current iterated node
dagPath = OpenMaya.MDagPath()
iter.getDagPath( dagPath )
# Get the selection as an MObject
mObj = OpenMaya.MObject()
iter.getDependNode( mObj )
# This shows how to use the MItMeshPolygon class to work with meshes
# Create an iterator for the polygons of the mesh
iterPolys = OpenMaya.MItMeshPolygon( mObj )
# Iterate through polys on current mesh
while not iterPolys.isDone():
# Get current polygons index
polyList.append (iterPolys.index())
# Get current polygons vertices
verts = OpenMaya.MIntArray()
iterMeshData.getVertices( verts )
# Append the current polygons vertex indices
for i in range( verts.length() ):
vertexList.append (verts[i])
# Get current polygons edges
edges = OpenMaya.MIntArray()
iterMeshData.getEdges( edges )
# Append the current polygons edge indices
for i in range( edges.length() ):
edgeList.append (edges[i])
# Get current polygons connected faces
indexConFaces = OpenMaya.MIntArray()
iterMeshData.getConnectedFaces( indexConFaces )
# Append the connected polygons indices
for i in range( indexConFaces.length() ):
conpolyList.append (indexConFaces[i])
# Get current polygons triangles
pntAry = OpenMaya.MPointArray()
intAry = OpenMaya.MIntArray()
space = OpenMaya.MSpace.kObject
# Get the vertices and vertex positions of all the triangles in the current face's triangulation.
iterMeshData.getTriangles(pntAry, intAry, space)
# Append vertices that are part of the triangles
for i in range( intAry.length() ):
polytriVertsList.append (intAry[i])
# Move to next polygon in the mesh list
iterPolys.next()
# print data for current node being iterated on
print (dagPath.fullPathName()), '//////////////////////////////////'
print 'Vertex list: ', vertexList
print 'Edge list: ', edgeList
print 'Poly Triangle Vertices: ', polytriVertsList
print 'Polygon index list: ', polyList
print 'Connected Polygons list: ', conpolyList
# Move to the next selected node in the list
iter.next()
AtrusDni
12-09-2008, 04:51 PM
Hey Ryan, you rock! I tried the latest and greatest version, but I get this error:
# Error: MFnMesh_getVertices() takes exactly 3 arguments (2 given)
# Traceback (most recent call last):
# File "<maya console>", line 45, in
# File "C:\engserv\rbuild\194\build\wrk\optim\runTime\Python\Lib\site-packages\maya\OpenMaya.py", line 4351, in getVertices
# TypeError: MFnMesh_getVertices() takes exactly 3 arguments (2 given) #
And I have a question about it, I have seen similar errors while trying to use the API. It says 2 arguments were given, but its referring to this line:
iterMeshData.getVertices( verts )
I dont understand how its 2 arguments when all that was passed was the intArray "verts" unless there were only 2 items in the list?
RyanT
12-09-2008, 05:54 PM
Sorry I made a mistake I renamed a variable last night then forgot to update the name in the rest of the code. The error says:
# Error: name 'iterMeshData' is not defined
# Traceback (most recent call last):
# File "<maya console>", line 45, in <module>
# NameError: name 'iterMeshData' is not defined #
Which is correct iterMeshData is not defined. If you look at line 45. iterMeshData should be iterPolys. Here is the correct version.
# the OpenMaya module has many of the general Maya classes
# note that some Maya classes require extra modules to use which is noted in the API docs
import maya.OpenMaya as OpenMaya
# This shows how to use the MSelectionList and MGlobal class
# Get the selection and create a selection list of all the nodes meshes
selection = OpenMaya.MSelectionList()
OpenMaya.MGlobal.getActiveSelectionList( selection );
# Create an MItSelectionList class to iterate over the selection
# Use the MFn class to as a filter to filter node types
iter = OpenMaya.MItSelectionList ( selection, OpenMaya.MFn.kGeometric );
# This uses build in functions of the MItSelectionList class to loop through the list of objects
# Note this is not a basic array you must use its built in functions iterate on its objects
# Iterate through selection
while not iter.isDone():
vertexList = []
edgeList = []
polytriVertsList = []
polyList = []
conpolyList = []
# Get MDagPath from current iterated node
dagPath = OpenMaya.MDagPath()
iter.getDagPath( dagPath )
# Get the selection as an MObject
mObj = OpenMaya.MObject()
iter.getDependNode( mObj )
# This shows how to use the MItMeshPolygon class to work with meshes
# Create an iterator for the polygons of the mesh
iterPolys = OpenMaya.MItMeshPolygon( mObj )
# Iterate through polys on current mesh
while not iterPolys.isDone():
# Get current polygons index
polyList.append (iterPolys.index())
# Get current polygons vertices
verts = OpenMaya.MIntArray()
iterPolys.getVertices( verts )
# Append the current polygons vertex indices
for i in range( verts.length() ):
vertexList.append (verts[i])
# Get current polygons edges
edges = OpenMaya.MIntArray()
iterPolys.getEdges( edges )
# Append the current polygons edge indices
for i in range( edges.length() ):
edgeList.append (edges[i])
# Get current polygons connected faces
indexConFaces = OpenMaya.MIntArray()
iterPolys.getConnectedFaces( indexConFaces )
# Append the connected polygons indices
for i in range( indexConFaces.length() ):
conpolyList.append (indexConFaces[i])
# Get current polygons triangles
pntAry = OpenMaya.MPointArray()
intAry = OpenMaya.MIntArray()
space = OpenMaya.MSpace.kObject
# Get the vertices and vertex positions of all the triangles in the current face's triangulation.
iterPolys.getTriangles(pntAry, intAry, space)
# Append vertices that are part of the triangles
for i in range( intAry.length() ):
polytriVertsList.append (intAry[i])
# Move to next polygon in the mesh list
iterPolys.next()
# print data for current node being iterated on
print (dagPath.fullPathName()), '//////////////////////////////////'
print 'Vertex list: ', vertexList
print 'Edge list: ', edgeList
print 'Poly Triangle Vertices: ', polytriVertsList
print 'Polygon index list: ', polyList
print 'Connected Polygons list: ', conpolyList
# Move to the next selected node in the list
iter.next()
AtrusDni
12-09-2008, 06:48 PM
:D Awesome man. By the way, where did you learn the python API stuff? Just from examples that ship with maya, or is there some online resource about it? I cannot find much information about it. Your example works great by the way.
RyanT
12-09-2008, 07:00 PM
I've learned to write C++ plugins using David Goulds book and I just learned through trial and error how to write Python API plugins. Most of my information has just been browsing the Autodesk docs and looking at what other scripters have done. The devkit folder in Maya has a batch of Python scripts as well to also give you some ideas. Because of this I am trying to put together resources on my site. So check back later and I will have more on how to create commands and nodes.
GennadiyKorol
12-09-2008, 08:41 PM
Been forced to quickly pick up python and have a note:
for i in range( verts.length() ):
vertexList.append (verts[i])
From what I have learned this is an unefficient version of a for loop in Python since range does create a temporary list having all elements from 0 to verts.length() - 1. This is wasting memory (and time allocating/deallocating it) since all you basically need is a counter, one number.
This is solved by using xrange() object. It implements the "stream" interface, having first last and next() functions, but it does not store all stream in memory. So this version should be much more efficient for big lists.
Thought I'd post it. I wouldn't be surprised versions of Python interpreters optimize this for you (?) though.
RyanT
12-09-2008, 09:29 PM
Thanks for the post, yeah there are several Python tricks to making more memory friendly code. I will take a look at xrange().
GennadiyKorol
12-13-2008, 06:50 PM
Looks like in python 3.0 there is no longer such thing as xrange. Instead range does the same thing, it is no longer returning a list but an object representing the sequence.
Backwards compatibility anyone? :D
RyanT
12-13-2008, 07:05 PM
Maya 2009 does not use Python 3.0 though. Hopefully Python 3.0 keeps the xrange() function around for backwards compatability and just makes range() call xrange().
-RyanT
GennadiyKorol
12-13-2008, 09:12 PM
Optimism rocks...
"for i in xrange(90 + 1):
NameError: name 'xrange' is not defined"
Actually I've heard that Python developers do not respect backwards compatibility. They are known for releasing 0.2 versions that totally break existing code.
On one hand this forces developers to invest time in porting their python code to the newer version, but on the other it allows for a much more rapid development of the language itself, without the stagnation of old not successful features.
RyanT
12-13-2008, 10:52 PM
Thankfully the Python in Maya can be partially controlled by Autodesk. So if they decided to switch to 3.0 in the next version they could add that feature themselves. Who knows, 3.0 could be revised to 3.2 with xrange() added back in.
CGTalk Moderation
12-13-2008, 10:52 PM
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.
vBulletin v3.0.5, Copyright ©2000-2012, Jelsoft Enterprises Ltd.