I''m trying to implement skeletal animation, but it isn''t working like it should. Please help! Anyway the problem is that the vertices are all screwed up, and I don''t know quite what''s wrong. It is animating it''s just not drawing the vertices in the right places!
I''ve looked over the source 3 times already and can''t see that anything is wrong!
Here''s a screenshot of the model in my program:
here
And here''s a screesnhot of the real model:
here
And the source...
here''s my rendering code:
void CModel::Draw() { // Render the model
unsigned char IsTexEnabled = glIsEnabled(GL_TEXTURE_2D); // Get this so we don''t mess up the state after drawing the model
for (int i = 0; i < numMeshes; i++) { // Loop through all the meshes in the modelW
int materialIndex = mesh[i].MaterialIndex; // Fetch the material index
if (materialIndex >= 0) { // If there is a material index
glMaterialfv(GL_FRONT, GL_AMBIENT, materials[materialIndex].ambient); // Set the ambient material property
glMaterialfv(GL_FRONT, GL_DIFFUSE, materials[materialIndex].diffuse); // Set the diffuse material property
glMaterialfv(GL_FRONT, GL_SPECULAR, materials[materialIndex].specular); // Set the specular material property
glMaterialfv(GL_FRONT, GL_EMISSION, materials[materialIndex].emissive); // Set the emissive material property
glMaterialf(GL_FRONT, GL_SHININESS, materials[materialIndex].shininess); // And the shininess property
if (materials[materialIndex].texID > 0) { // If there is a texture for this material
glBindTexture(GL_TEXTURE_2D, materials[materialIndex].texID); // Bind the texture
glEnable(GL_TEXTURE_2D); // And enable texture mapping
} else glDisable(GL_TEXTURE_2D); // If there was no texture, we disable texturing
} else // If there were no materials
glDisable(GL_TEXTURE_2D); // Disable texturing
glBegin(GL_TRIANGLES); // Begin rendering this models triangles
for (int j = 0; j < mesh[i].numTriangles; j++) { // Loop through the triangles in the mesh
int triIndex = mesh[i].TriIndices[j]; // Fetch the triangle index
const Triangle* tempTri = &tri[triIndex]; // Fetch a temporary triangle
for (int k = 0; k < 3; k++) {
int index = tempTri->VertexIndex[k]; // Get the index to the vertex
if (vertex[index].boneID == -1) { // If it belongs to the root joint
glNormal3fv(tri[index].VertexNormals[k].v); // Set the normal for this vertex
glTexCoord2f(tri[index].s[k], tri[index].t[k]); // Set the texture coordinate for this vertex
glVertex3fv(vertex[index].position.v); // And pass the vertex to OpenGL
} else { // If it belongs to another joint
const Matrix& final = joints[vertex[index].boneID].final; // Get the final matrix
Vector3D newNormal(tempTri->VertexNormals[k]); // Need to get the normal
newNormal.transform3(final); // So it can get transformed
newNormal.normalize(); // Then normalize it
glNormal3fv(newNormal.v); // Set the normal
glTexCoord2f(tempTri->s[k], tempTri->t[k]); // Set the texture coordinate for this vertex
Vector3D newVertex(vertex[index].position);
newVertex.transform(final); // Transform the vertex
glVertex3fv(newVertex.v); // Pass it to OpenGL
}
}
}
glEnd(); // End the triangles
}
if (IsTexEnabled) // If it was enabled before we started rendering
glEnable(GL_TEXTURE_2D); // Restore the state
else glDisable(GL_TEXTURE_2D); // If it wasn''t we disable it again
}
and heres my animation code:
void CModel::Animate() { // Animate the model
float time = timer->GetTime(); // Get the current time
if (time > totalTime) { // If the entire animation has been played
restart(); // Reset the animation
time = 0;
// If not, play the last part of the animation
}
for (int i = 0; i < numJoints; i++) { // Loop through the joints
float trans[3]; // Translation vector
Matrix transform;
int frame; // The current frame
Joint *joint = &joints[i]; // Get the joint
if (joint->numRotationKeyframes == 0 && joint->numTranslationKeyframes == 0) { // If there are no keyframes
joint->final = joint->absolute; // The final matrix is equal to the absolute matrix
continue; // Go to next joint
}
frame = joint->CurrentTranslationKeyframe; // Get the current translation frame
// While this is not the last frame, and the time of the frame has not gone past the current time
while (frame < joint->numTranslationKeyframes && joint->TranslationKeyframes[frame].time < time) {
frame++; // Go to the next frame
}
joint->CurrentTranslationKeyframe = frame; // Set the current frame
if (frame == 0) // If it is the first frame
memcpy(trans, joint->TranslationKeyframes[0].parameter, sizeof (float) * 3);
else if (frame == joint->numTranslationKeyframes) // If it is the last frame
memcpy(trans, joint->TranslationKeyframes[frame - 1].parameter, sizeof(float) * 3);
else { // If it is one of the frames between
if (frame < 0) // Limit the frame to
frame = 0; // 0 - numTranslationKeyframes
if (frame > joint->numTranslationKeyframes)
frame = joint->numTranslationKeyframes;
const CModel::Keyframe& curFrame = joint->TranslationKeyframes[frame]; // Get the current
const CModel::Keyframe& prevFrame = joint->TranslationKeyframes[frame - 1]; // And previous frames
float timeDelta = curFrame.time - prevFrame.time; // And get the elapsed time
float interpolation = (float)((time - prevFrame.time) / timeDelta); // And get the percent of interpolation between the frames
trans[0] = prevFrame.parameter[0] + (curFrame.parameter[0] - prevFrame.parameter[0]) * interpolation;
trans[1] = prevFrame.parameter[1] + (curFrame.parameter[1] - prevFrame.parameter[1]) * interpolation;
trans[2] = prevFrame.parameter[2] + (curFrame.parameter[2] - prevFrame.parameter[2]) * interpolation;
}
frame = joint->CurrentRotationKeyframe; // Get the current rotation keyframe
// While this is not the last frame, and the time of the frame has not gone past the current time
while (frame < joint->numRotationKeyframes && joint->RotationKeyframes[frame].time < time) {
frame++; // Go to the next frame
}
joint->CurrentRotationKeyframe = frame; // Set the current frame
if (frame == 0) // If it is the first frame
transform.setRotationRadians(joint->RotationKeyframes[0].parameter);
else if (frame == joint->numRotationKeyframes) // If it is the last frame
transform.setRotationRadians(joint->RotationKeyframes[frame - 1].parameter);
else { // If it is one of the frames between
if (frame < 0) // Limit the frame to
frame = 0; // 0 - numRotationKeyframes
if (frame > joint->numRotationKeyframes)
frame = joint->numRotationKeyframes;
const CModel::Keyframe& curFrame = joint->RotationKeyframes[frame]; // Get the current
const CModel::Keyframe& prevFrame = joint->RotationKeyframes[frame - 1]; // And previous frames
float timeDelta = curFrame.time - prevFrame.time; // And get the elapsed time
float interpolation = (float)((time - prevFrame.time) / timeDelta); // And get the percent of interpolation between the frames
if (interpolation <= 0) // Limit the interpolation
interpolation = 0; // Between zero and one
if (interpolation >= 1)
interpolation = 1;
// Use quaternions for rotation
Quaternion qPrev(prevFrame.parameter); // Get quaternions from the
Quaternion qCur(curFrame.parameter); // Previous and current frame
Quaternion qFinal(qPrev, qCur, interpolation); // And calculate the final rotation
transform.setRotationQuaternion(qFinal); // Then apply the final rotation to the matrix
}
transform.setTranslation(trans); // Apply the translation to the matrix
Matrix relativeFinal(joint->relative); // And get the relative final matrix
relativeFinal.postMultiply(transform); // And post-multiply it by the transformation matrix
if (joint->parent == -1) // If there is no parent joint
joint->final = relativeFinal; // Then the final matrix of this joint is the relative final matrix
else { // If this is not the root
joint->final = joints[joint->parent].final; // Then the final matrix of this joint is the final matrix of the parent joint
joint->final.postMultiply(relativeFinal); // Multiplied by the relative final matrix
}
}
}
plz help!!