Mesh generation / importer examples?

This is something I posted at CGTalk [MAYA] , but no replies:

I am trying to make a mesh importer for a modding community in my spare time. Never really done this before.

The mesh format is something like this:

joints, parenting
every vertex - position, normal, vertex color, UV coords, joint influences, joint weights
triangulation data in three vert lines

Is there a good way to build a mesh from a list of verts and metadata or do you do it vert by vert setting these as you go? Or do I need to make the mesh then iterate through the indices setting these?

Hello Chris,

Maybe you can play with the maya python API for this task?
I have done it once to extract data from a polygonal mesh and include it in a locator openGL draw call:

I found later it was more interesting to create an input mesh connection in the locator node.
In the compute method i use maya MFnMesh class to extract and layout all the point data, edge connection etc and store it in this node internal attribute.

In the draw method the data were ready at hand.

The MFnMesh class has a create method that can be use to create your mesh
once you have collected your vertices position, vertex faceID, and UV

As a personal preference I create an empty group and capture its dagPath to pass it as the parent owner.

MFnMesh::create ( int numVertices,
int numPolygons,
const MFloatPointArray & vertexArray,
const MIntArray & polygonCounts,
const MIntArray & polygonConnects,
const MFloatArray & uArray,
const MFloatArray & vArray,
MObject parentOrOwner = MObject::kNullObj)

For the normals I will then use MFnMesh.setNormals() method

Hope it helps
Cedric

I saw your post at CG Talk. It looked lonely, as it does here. The lack of relevant code examples is probably due to the lack of utility to game developers of importing game data… they already have the original source material, so only exporters are of much use.

MEL will be nearly useless for your task overall, although embedding some MEL will help (such as using MEL to create a default skinCluster). Either python or C++ are needed to access the OpenMaya API.

I prefer C++, but I have a long history with the C language, so my opinion and methods are probably not unbiased. I think either will suffice, and most game meshes are not large enough for anyone to argue that speed is an issue.

As for the overall process, in Maya you will need to create a mesh object, add vertices to it, add polygons, add normals and UVs in a series of steps that essentially require you to build one or more data arrays and pass them as parameters to a function call. Adding joints and skinning are additional steps on top of this.

It does not hurt to have all of your data organized like you are talking about, but you will not be able (in most cases) to pass that directly to the Maya API functions. However, if you start with a set of data where you have members such as vertexCount, vertices[], faceCount, faces[], normalCount, … populated with data from whatever ‘reader’ process you have written, you will simplify the task of converting your game data to a Maya mesh.

As for specifics, you probably want to make a ‘translator’ plug-in for ease of educating your users, because that will allow you to integrate it as a Maya open or import function. There is a useful example of a translator plug-in in the API examples in the Maya documentation, it is really just a few dozen lines beyond your app-specific code.

And almost all of the code outside of joints and skinning will be done with methods from the MFnMesh() API function. You should start by looking at that in the technical documentation.

<* Wes *>

Can you convert it to something Maya can read (fbx, obj, etc) and then use a supported import function?

Nah, that’s why I picked it, it’s a challenge… Someone made a blender importer. I am almost done, will post it soon. Just terrible at openMaya API

Here I am just trying to make a single triangle… the lack of documentation and examples online for the openMaya python API makes things a bit daunting…

It just seems to say ‘failure’, which is not too useful:

Error: (kFailure): Unexpected Internal Failure


import maya.OpenMaya as om

vertexArray = om.MFloatPointArray()
uArray = om.MFloatArray()
vArray = om.MFloatArray()
        
numVertices = 1
numPolygons = 3
vertices = [(0,0,0), (0,0,1.01), (0,1.12,1)]
uvs = [(0,0), (0,1), (1,1)]
conns = [1,2,3]

pCounts = om.MIntArray()
for i in vertices: pCounts.append(3)
pConnects = om.MIntArray()
for c in conns: pConnects.append(c)

for i in range(0, len(vertices)):
    #Store the points
    pt = om.MFloatPoint(vertices[i][0],vertices[i][1], vertices[i][2])
    vertexArray.append(pt)
    uArray.append(uvs[i][0])
    vArray.append(uvs[i][1])
    
#Now create the mesh
#build components
mesh = om.MFnMesh()
meshMObj = mesh.create(numVertices, numPolygons, vertexArray, pCounts, pConnects, uArray, vArray)

I am probably just passing something wrong, this implementation is very non-pythonic… reminds me of when MotionBuilder added ‘python support’ through boost.

I have track several error in your script:
excuse my weak coding style…

import maya.OpenMaya as om
import maya.cmds as cmds

def get_mobject(node):
selectionList = om.MSelectionList()
selectionList.add(node)
oNode = om.MObject()
selectionList.getDependNode(0, oNode)
return oNode

vertexArray = om.MFloatPointArray()
uArray = om.MFloatArray()
vArray = om.MFloatArray()

numVertices = 1 #<-- this error you want you have 3 vertice in your triangle
numPolygons = 3 #<-- this error just swap the value : 1 poly

numVertices = 3
numPolygons = 1

vertices = [(0,0,0), (0,0,1.01), (0,1.12,1)]
uvs = [(0,0), (0,1), (1,1)]
conns = [1,2,3] #<-- another error vertex indices start at 0 in maya…
conns = [0,1,2]
pConnects = om.MIntArray()
for c in conns: pConnects.append©

pCounts = om.MIntArray()
for i in vertices: pCounts.append(3) #<-- another error in each poly we specify how many vertices here 3 but it can be more
pCounts = om.MIntArray()

for o in range(numPolygons):
pCounts.append(3)# one triagle so add 3 vertices
uvCounts = om.MIntArray()
uvIds = om.MIntArray()

for i in range(0, len(vertices)):
#Store the points
pt = om.MFloatPoint(vertices[i][0],vertices[i][1], vertices[i][2])
vertexArray.append(pt)
uArray.append(uvs[i][0])
vArray.append(uvs[i][1])
uvIds.append(i)

normally to fill uVcounts with only 1 UV set , the faceVertId are the same as face vert connection array : here 3 vertices/UV

uvCounts = pCounts

#Now create the mesh
#build components
mesh = om.MFnMesh()

ShapeMesh = cmds.group(em=True) # <-- we create an empty group/ trnasform node that will receive the mesh node as a sibling
parentOwner = get_mobject( ShapeMesh )

meshMObj = mesh.create(numVertices, numPolygons, vertexArray, pCounts, pConnects, uArray, vArray ,parentOwner ) #<-- don’t forget to add a parent owner
cmds.sets( ‘null1’, e=True,forceElement=‘initialShadingGroup’) # <–assign the defaut lambert shader

defaultUVSetName = ‘’
defaultUVSetName = mesh.currentUVSetName(-1)
mesh.assignUVs( uvCounts,uvIds, defaultUVSetName) #< even if uv a created you must assign them

oups,
you can replace
cmds.sets( ‘null1’, e=True,forceElement=‘initialShadingGroup’) # <–assign the defaut lambert shader

by :
cmds.sets( ShapeMesh, e=True,forceElement=‘initialShadingGroup’) # <–assign the defaut lambert shader

As for the maya API not pythonic enough, you may be right, there is many bug,
the syntax are not enough explained ( in some case ) but as it is , everyone with a bit of effort can have some results

just see some of the development on cgtalk:

zoharl seems to have forgotten that in the devellopper reference --> Differences between the C++ Maya API and Maya Python API:
No MStatus class …

There was a Maya video podcast that worked with this, can’t seem to find it now i’m afraid.
but it was called something in the style of “Maya api for game development”.
They worked with Maya python API to create both an import and export tool of meshes.

[QUOTE=cedricB;12885]Differences between the C++ Maya API and Maya Python API:
No MStatus class …[/QUOTE]

Out of curiosity then, is there any way to determine if a call to the API succeeded (when using python)?

I am a big believer in checking your results after every function call (using whatever API).

<* Wes *>

I didn’t use it at all to be honest , I usually check my data before submitting it to an API call:

But It seems that the maya developer as choose to use error logging:

developer resources --> Using the Maya Python API --> Exceptions versus MStatus:

When there is some cryptic error logging I try to compare a valid data set created by maya to the faulty one.

I see. It uses try and except.

Thanks for the info. I am currently busy reading that section of teh docs now.

<* Wes *>