Jump to content
  • Advertisement
Sign in to follow this  
V3rt3x

Computing normals for weighted vertices (vertex skinning)

This topic is 4867 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
Advertisement
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 :-)

http://www.doom3world.org/phpbb2/viewtopic.php?p=100174#100020

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 GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!