View Full Version : Maya API - Normals question, advice needed
08 August 2012, 06:25 PM
Hey everyone, so I have made the dive into API programming and I am working on my first plugin. I've hit a bit of a speed bump when it comes to polygon normals. Let me explain what the plugin does:
If you select a bunch of objects, it will create a new combined object from the selection. It then tracks the vertices of all the selected objects and updates the corresponding vertices of the combined mesh, all the while making geometry caches of each frame. So in the end, you have a single mesh that's geocached, lighter weight scene, faster render times and should be easily portable to other packages (like Max for doing FumeFX sims).
Everything is working ok (still need to set the uvs, shader assignments, etc) but it does create the geometry and caches it correctly. I am reading the data of each object and appending it to a master list and creating the mesh from that.
Problem is, I now want the normals to be the same on the final mesh as the selected objects. (right now the normals are all smooth).
How would you go about setting the normals for a new mesh like this? I've looked into getFaceVertexNormal, and getFaceVertexNormals. I'm not sure how to continue. I've read that a sphere with smoothing on will contain less normal information than a cube, since its normals can be shared, so how does this fit into a new mesh that could potentially have hard and soft normals?
One unsuccessful idea was to go through each face of each object and get the vertices that make up the face, then query the normal data for each face vertex, then apply that to the corresponding face of the final mesh as a secondary routine after the final mesh is created.
needless to say, I'm stumped at the moment. Any ideas? :banghead:
08 August 2012, 08:07 AM
I didn't fully understand the exact problem you are facing, but since you update the combined mesh vertices, you probably want to update the normal at each vertex as well. So I think that get/setNormalVertex() should do the job.
08 August 2012, 03:57 PM
Interesting, I'll take a look at those functions. Thanks Zoharl!
08 August 2012, 04:00 PM
Quick question, would you build the new mesh first, then query the normals on the selected objects and set them on the new mesh, or is there a way to set the normals while you are building the data for the new mesh?
08 August 2012, 04:07 PM
I can't see in the mfnmesh doc a constructor that accepts normals. You specify a normal per vertex, which can be specified to a single vertex anyway.
08 August 2012, 04:13 PM
I guess I am confused about the normals. I tried building a master normals list by querying each vertex normal. But the part that is confusing me is, if I have a cube with hard edges and a cube with soft edges, there will be 24 normal values for the cube with hard edges and only 8 for the cube with soft edges. Im not quite sure how to build a master list of normals per face vertex, which is what I think I need, because some normals can be shared.
08 August 2012, 05:43 PM
You'll need to decide which method you are going with. If you need normal per vertex poly, then you should work with this set of functions. Since it conforms with maya inner structure it's preferable to the easier set of functions (normal per vertex) which I suggested before. Please read the intro of the doc, and see it it clarifies which set to use when:
Normals Some of the Normals in Maya are now user-settable. If the vertex normals are not set or locked, they are computed by maya when the mesh changes. If set or locked, the normals remain frozen relative to the object, unless the user unlocks them. There are 3 types of normals for a mesh:
Per-vertex per-polygon Polygonal objects store a list of per-vertex per-polygon normals (similar to the vertex list) This list is what is returned by MFnMesh::getNormals (http://forums.cgsociety.org/) and MItMeshPolygon::getNormal(index, normal). As well, MItMeshPolygon::normalIndex( vertexIndex ) returns the index into the normal list for a particular vertex of the polygon.
For a cube, the list would contain 24 normals (4 vertices * 6 polygons) since the edges for a cube are hard and the per-vertex per-polygon normals cannot be shared. For a sphere or torus, which has smooth edges, the normals can be shared, and thus the normal list contains the same number of normals as vertices.
Per-polygon normals Polygonal objects store a normal for each polygon. These normals can be accessed via MItMeshPolygon::getNormal(normal) or MFnMesh::getPolygonNormal (http://forums.cgsociety.org/). So, a cube, which is comprised of 6 polygons would contain 6 such normals.
Per-vertex You can also access a normal for each vertex of the mesh, independent of any polygons. Such normals are not stored in the object, but instead are calculated by Maya upon request as the average of all the per-polygon normals for the polygons adjacent to the vertex. These normals are what is returned by MFnMesh::getVertexNormal (http://forums.cgsociety.org/) or MItMeshVertex::getNormal (http://forums.cgsociety.org/).
On second thought if it's just what you quoted, then I'll clarify: You have three set of functions to work with the normals. Each one is described in a bold paragraph in the doc. Choose one that suits you, and go with it.
At this point I'll need you to elaborate exactly on what you are missing, since these are the functions that set and get normals, and they should be enough for you app.
08 August 2012, 08:01 PM
I'm still struggling with this normals issue. So my plugin reads mesh data and does it's own "combine" method. Reason being is I need to track vertices from multiple meshes to the new mesh and the only way I can insure point order is if I create the mesh myself.
Anyways, for example, say you have a cube and a sphere. One has hard normals and the other has soft. How would you go about making a master list for a new mesh of the normals and apply them so some are hard and some are soft?
08 August 2012, 08:07 PM
Can you track the source of each vertex? Sure you do.
If you have the old vertex, can you track its neighborhood normals? Yes.
So you know for each new vertex its source vertex and the normal to put there.
What are you missing?
Who cares about hard or soft? You just set/combine the old normals whatever they are.
08 August 2012, 08:54 PM
I am no expert on the API, but after reading through your situation, I would query the Normals Per Vertex Per Face. this will work for both a smooth sphere and a hard cube.
08 August 2012, 12:55 AM
Ahhhh GOT IT WORKING! :buttrock:
I basically went through each face of each object, found the vertex indexes of each face and queried the normals and stored them in a master list, then went through every face of the new mesh, got the vertex of each face and applied the normals that way. Seems to have worked ok. Is this the method you guys would use?
08 August 2012, 05:18 AM
I don't really see many other ways. Maybe there can be a variation in case that a vertex tracks back to both meshes, and then you need some averaging or some interpolation scheme for the new normal.
08 August 2012, 05:49 PM
Normals are exposed in a rather odd way in the Maya API. There's the pre-computed normals that Maya automatically generates. Then there's "user normals" which is what you're setting when you invoke setVertexNormal/setFaceVertexNormal. The difference here is:
Pre-computed normals will auto update the normals as the user updates the mesh (eg. dragging a vertex around.)
User normals do not auto update. They are fixed normal specifications for that vertex.
Typically you want to interface with pre-computed normals, but if the user does not need to tweak the mesh, user normals might suffice. The only real interface to the precomputed normals is to interact with setEdgeSmoothing(). This is how I've done it for any node that generates mesh topology.
08 August 2012, 05:49 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.