• 10
• 13
• 19
• 27
• 9

Maya, Per-vertex Normals and Tangent Space

This topic is 4334 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Heya! I'm writing an exporter for Maya, and I'm trying to wrap my head around the way it generates normals. As far as I can tell, the Maya API's MFnMesh class outputs per-polygon per-vertex normals. This wording is somewhat strange to me... is it per-vertex, or per-polygon? If we take the documentation literally, each triangle - for the sake of simplicity - will have three vertex normals. All points on a triangle will always lie on the same plane, so won't their normals all be the same anyway? Per-vertex normals (averaged of all adjacent faces) do the equivalent of GL_NORMALIZE for smoother lighting. Is there any way to get these normals from Maya, preferably indexed? Another, somewhat related question: For a specific shader I'm going to write, I will require that per-pixel calculations be done in tangent-space. Do the normals I use in these calculations need to be perpendicular to the face of the polygon? Or can tangent-space somehow be calculated for the averaged per-vertex normals instead of the per-face normals? P.S. I can understand if my post is confusing. Please let me know if I need to be clearer!

Share on other sites
About the second question I don't know: I would like to implement bump mapping and I'm looking for tangent space infos myself ;-)

For the first: you are lucky: 3ds doesn't even save normals in the 3ds file :-( In order to have smooth normals (i.e. for gouraud shading) you have to average the normals of the triangles: that is you loop throught your vertices, sum the normals of the triangles sharing them, and the divide each computed normal by 3:
I use the following function (you will need to adpt it for your needs):
bool Loader3DS::SmoothNormals(unsigned int nfaces, unsigned short int *faces, float *vertices, float* normals){    if(!faces || ! vertices || ! normals) return false;    //First calculate the faces normals    float* temp = new float[nfaces*3];    if(!temp) return false;    FlatNormals(nfaces, faces, vertices, temp);     //Now calculate the smoothed normals    float n[3];    int c = 0;    float len = 0.0;    for(int i = 0; i &lt; nfaces * 3; i++)    {        c = 0;        n[0] = n[1] = n[2] = 0.0;        for(int j = 0; j &lt; nfaces; j++)        {            if(faces[j*3] == i || faces[j*3+1] == i || faces[j*3+2] == i)            {                n[0] += temp[j*3];                n[1] += temp[j*3+1];                n[2] += temp[j*3+2];                ++c;            }        }        if(c != 0) //Take the average of the normals        {            n[0] /= c;            n[1] /= c;            n[2] /= c;            len = sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);            normals[i*3] = n[0] / len;            normals[i*3+1] = n[1] / len;            normals[i*3+2] = n[2] / len;        }    }    delete temp;    return true;}

Note that since when I call this function I don't have per face normals, I need to calculate them. Your code will be much easier than this, I suppose, but perhaps you can get something working from this.

Share on other sites
@cignox:

@OP:
Quote:
 All points on a triangle will always lie on the same plane, so won't their normals all be the same anyway?

i think maya needs that to be able to adjust the normal smoothness. In maya you can adjust the normal softness from 0 -180. I think with 1 normal per vertex you cannot get that.

Quote:
 Is there any way to get these normals from Maya, preferably indexed?

in my exporter i was too lazy to export notmals...i calculate them at loadtime in my engine.(because it was a pain to export uvs so i didn't want to have the same chaos again with normals) But have you tried rob-the-blokes homepage? he has some really nice tutorials on how to write a maya exporter...

regards,
m4gnus

Share on other sites
Quote:
 Original post by m4gnus@cignox:he's talking about maya..not 3dsMax.

Yep, I know that. I just wanted to point out that he was lucky to have the normals in the file, while with other formats these have to be computed.
Anyway, the code I posted should work with some changes: in the code I compute the normals, while the op already has them.

Share on other sites
ooops ok understand what you meant

Share on other sites
In 3dsmax, a every triangle can have 3 seperate normals. To export these correctly, you have to duplicate some coordinates just like with UV's.
Here's a link that works for exporting UV's, but you can easily alter it to work for normals:
http://www.mindcontrol.org/~hplus/graphics/vertex-arrays.html

Calculating the normals at runtime isn't always a viable solution. In a modelling package, the normals can be flipped for some objects etc... So only exporting them will produce correct results.
If I remember right, the IGame exporter library for 3dsmax contains a function to generate a flat vertex array for the normals of any pologonal model.
Mind that if you want ultra-accurate results, you should export the normals using the code above in conjunction with reconstructing the normals through smooth-group traversion.

Share on other sites
Thanks for the replies all

Looks like I'm going to have to calculate them myself. Not a problem, really, but it'll most likely be an indexing nightmare to re-index normals, binormals and tangents...

...apparently not! As I wrote this I finally found the MFnMesh::getVertexNormal function, which apparently "calculated by Maya upon request as the average of all the per-polygon normals for the polygons adjacent to the vertex." Sweet, saves me a lot of work :)

@Cignox1

Check out this website. It's got some good info on tangent/binormal generation.

Share on other sites
Quote:
 Original post by skyfire360...@Cignox1Check out this website. It's got some good info on tangent/binormal generation.

Thank you, I already got it: in fact, I was just going to read it ;-)