std::optional<math::Transform<>> Animation::bone_transform(const core::String& name, float time) const { auto channel = std::find_if(_channels.begin(), _channels.end(), [&](const auto& ch) { return ch.name() == name; }); if(channel == _channels.end()) { return std::optional<math::Transform<>>(); } return std::optional(channel->bone_transform(time)); }
void shadow_mapper_render_animated(animated_object* ao) { if (ao->skeleton->num_bones > MAX_BONES) { error("animated object skeleton has too many bones (over %i)", MAX_BONES); } matrix_4x4 r_world_matrix = m44_world( ao->position, ao->scale, ao->rotation ); m44_to_array(r_world_matrix, world_matrix); for(int i = 0; i < ao->skeleton->num_bones; i++) { matrix_4x4 base, ani; base = bone_transform(ao->skeleton->bones[i]); ani = bone_transform(ao->pose->bones[i]); bone_matrices[i] = m44_mul_m44(ani, m44_inverse(base)); m44_to_array(bone_matrices[i], bone_matrix_data + (i * 4 * 4)); } glUseProgram(*depth_shader_animated); GLint bone_world_matrices_u = glGetUniformLocation(*depth_shader_animated, "bone_world_matrices"); glUniformMatrix4fv(bone_world_matrices_u, ao->skeleton->num_bones, GL_FALSE, bone_matrix_data); GLint bone_count_u = glGetUniformLocation(*depth_shader_animated, "bone_count"); glUniform1i(bone_count_u, ao->skeleton->num_bones); GLint world_matrix_u = glGetUniformLocation(*depth_shader_animated, "world_matrix"); glUniformMatrix4fv(world_matrix_u, 1, 0, world_matrix); GLint proj_matrix_u = glGetUniformLocation(*depth_shader_animated, "proj_matrix"); glUniformMatrix4fv(proj_matrix_u, 1, 0, proj_matrix); GLint view_matrix_u = glGetUniformLocation(*depth_shader_animated, "view_matrix"); glUniformMatrix4fv(view_matrix_u, 1, 0, view_matrix); renderable* r = ao->renderable; for(int i = 0; i < r->num_surfaces; i++) { renderable_surface* s = r->surfaces[i]; if(s->is_rigged) { GLsizei stride = sizeof(float) * 24; glBindBuffer(GL_ARRAY_BUFFER, s->vertex_vbo); glVertexPointer(3, GL_FLOAT, stride, (void*)0); glEnableClientState(GL_VERTEX_ARRAY); glVertexAttribPointer(BONE_INDICIES, 3, GL_FLOAT, GL_FALSE, stride, (void*)(sizeof(float) * 18)); glEnableVertexAttribArray(BONE_INDICIES); glVertexAttribPointer(BONE_WEIGHTS, 3, GL_FLOAT, GL_FALSE, stride, (void*)(sizeof(float) * 21)); glEnableVertexAttribArray(BONE_WEIGHTS); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->triangle_vbo); glDrawElements(GL_TRIANGLES, s->num_triangles * 3, GL_UNSIGNED_INT, (void*)0); glDisableClientState(GL_VERTEX_ARRAY); glDisableVertexAttribArray(BONE_INDICIES); glDisableVertexAttribArray(BONE_WEIGHTS); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); } else { error("animated object is not rigged"); } } glUseProgram(0); }