Hi guys,
I'm implementing a viewer for skinned character animation. Each frame of animation requires thousands of (4x4 matrix * vector) and (float * 4x4 matrix) calculations.
This is the section that is repeated thousands of times:
// For each vertex influenced by bone
for (int j=0; j<(int)Character::bones[i].get_vertices().size(); j++)
{
static vector<float> matrix(16, 0.0f);
index = Character::bones[i].get_vertices()[j];
// Matrix is multiplication of final_matrix and weight
multiply_matrices(Character::bones[i].get_weights()[j], final_matrix, matrix);
// Transform pose vertex by matrix
multiply_matrix_vertex(matrix, Character::mesh.get_vertices()[index].get_coord(), vers[index]);
}
index is a static int that is assigned an index value used to retrieve a vertex from a vector of vertices 'vers'.
.get_weights() returns a vector of floats by reference
final_matrix and t_matrix are static vector<float> that have a size of 16.
.get_coord() returns a pointer to an array of 3 floats, which are the xyz coordinates of the vertex.
'matrix' and 'vers[index]' are changed by the functions they are called with (hence no return values).
vers[index] is a Ver2, where Ver2 is:
class Ver2 {
public:
// ATTRIBUTES
float v_coord[3];
// ACCESSORS
float* get_coord();
// MANIPULATORS
void add(float&, float&, float&);
...
};
Now for the matrix functions. I should note that I represent a matrix by a vector<float> with size 16. Where matrix[0]...matrix[3] is the first row, matrix[4]...matrix[7] is the second etc.:
Multiplying each element in the matrix by a float
void multiply_matrices(float& weight, vector<float>& matrix, vector<float>& ret)
{
for (int i=0; i<(int)matrix.size(); i++)
{
ret[i] = matrix[i] * weight;
}
}
This multiplies a matrix by an array of floats (coordinates), and then adds the results to the current coordinates in 'v'.
void multiply_matrix_vertex(vector<float>& matrix, float* pose_v, Ver2& v)
{
static float x;
static float y;
static float z;
x = ( (matrix[0] * pose_v[0]) +
(matrix[1] * pose_v[1]) +
(matrix[2] * pose_v[2]) +
(matrix[3]) );
y = ( (matrix[4] * pose_v[0]) +
(matrix[5] * pose_v[1]) +
(matrix[6] * pose_v[2]) +
(matrix[7]) );
z = ( (matrix[8] * pose_v[0]) +
(matrix[9] * pose_v[1]) +
(matrix[10] * pose_v[2]) +
(matrix[11]) );
v.add(x, y, z);
}
Now the issue I have is that these functions cause a massive fps hit. Without the multiply_matrices/multiply_matrix_vertex calls, I run at 110fps. With them, i'm on 14fps.
The model only has about 2000 polygons, and I'm running on a very good computer, so no 'get a better pc', or 'use simpler model' responses please =)
What can I do to increase the efficiency of these functions?