Advertisement Jump to content
Sign in to follow this  

Computing normals for weighted vertices (vertex skinning)

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, I'm wondering how to compute vertex normals when using vertex skinning? I would like to pre-compute normals from vertex weights in order to get final vertex normals like I get final vertices:
for( i = 0; i < _numVerts; ++i ) {
  Vector3f finalVertex = kZeroVectorf;
  Vector3f finalNormal = kZeroVectorf;

  // Calculate final vertex to draw with weights
  for( int j = 0; j < _verts->countWeight; ++j ) {
    const Weight_t *pWeight = _weights[ _verts->startWeight + j ];
    const Joint_t *pJoint = skel->getJoint( pWeight->joint );

    // Calculate transformed vertex for this weight
    Vector3f wv = pWeight->pos;
    pJoint->orient.rotate( wv );

    // The sum of all pWeight->bias should be 1.0
    finalVertex += (pJoint->pos + wv) * pWeight->bias;

    Vector3f wn = pWeight->norm;
    pJoint->orient.rotate( wn );

    finalNormal += wn * pWeight->bias;

  _vertexArray[0] = finalVertex._x;
  _vertexArray[1] = finalVertex._y;
  _vertexArray[2] = finalVertex._z;

  _normalArray[0] = finalNormal._x;
  _normalArray[1] = finalNormal._y;
  _normalArray[2] = finalNormal._z;
What I want is to compute pWeight->norm, which is the weighted normal associated to a weighted vertex, preferably at loading time. Perhaps I'm wrong and this is not a good idea... But then I would like to know how to compute these normals without having to rebuild all triangle normals at rendering time, then averaging them for vertices, etc.

Share this post

Link to post
Share on other sites
Hey V3rt3x,

I think you're going about it the wrong way. You only need to compute the normals for each vertex in its bind pose. When you multiple the normal by the bones final combined transformation it will transform the normal to the correct space.

So just use the models original normals with all the frames original transforms.

Share this post

Link to post
Share on other sites
The bind pose? is it that the bind pose?

I'm using the MD5 model format, but vertices have ”multiple positions” stored separately with the weight factor and joint index (in order to get access to quaternion orientation and joint's position).

struct Md5Vertex_t
float st[2]; // Texture coordinates

int startWeight; // Start index weights
int countWeight; // Number of weights

struct Md5Weight_t
int joint; // Joint index
float bias; // Weight factor
Vector3f pos;
Vector3f norm; // what I would like in my dreams (o_o)

So if I want to compute normals I need to use a Skeleton because a vertex weights give a position depending on their joint...

I'm completely lost with theses weight positions... In books I have the position is the same but there are multiple transformation matrices (one for each bone). Here we have multiple positions and multiple matrices :(

Share this post

Link to post
Share on other sites
I got the solution at doom3world :-)

Problem solved.

Share this post

Link to post
Share on other sites
Well, there are 2 good ways to do it.

You can apply the rotation of the different bones to the normal (not the translation!) and scale by the respective weights, BUT you're not going to have a unit-length normal after this step so you'll need to normalize.

Or, a lot of ps2 games do this:
Just transform the normal by the most heavily weighted bone. If there isn't scaling on the bone (which is true 99% of the time), you don't need to re-normalize the normal, so in many cases this is super cheap to do and there isn't significant visual difference. It's especially easy if you use the convention that the most heavily weighted bone is stored as the first weight/idx.

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using, you agree to our community Guidelines, Terms of Use, and Privacy Policy. is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!