bool Model::parseBones(FS::IFile& file) { int bone_count; file.read(&bone_count, sizeof(bone_count)); if (bone_count < 0) { return false; } m_bones.reserve(bone_count); for (int i = 0; i < bone_count; ++i) { Model::Bone& b = m_bones.emplace(m_allocator); int len; file.read(&len, sizeof(len)); char tmp[MAX_PATH_LENGTH]; if (len >= MAX_PATH_LENGTH) { return false; } file.read(tmp, len + 1); tmp[len] = 0; b.name = tmp; m_bone_map.insert(crc32(b.name.c_str()), m_bones.size() - 1); file.read(&len, sizeof(len)); if (len >= MAX_PATH_LENGTH) { return false; } if(len > 0) { file.read(tmp, len); tmp[len] = 0; b.parent = tmp; } else { b.parent = ""; } file.read(&b.position.x, sizeof(float) * 3); file.read(&b.rotation.x, sizeof(float) * 4); } m_first_nonroot_bone_index = -1; for (int i = 0; i < bone_count; ++i) { Model::Bone& b = m_bones[i]; if (b.parent.length() == 0) { b.parent_idx = -1; } else { b.parent_idx = getBoneIdx(b.parent.c_str()); if (b.parent_idx > i || b.parent_idx < 0) { g_log_error.log("renderer") << "Invalid skeleton in " << getPath().c_str(); return false; } if (m_first_nonroot_bone_index == -1) { m_first_nonroot_bone_index = i; } } } for (int i = 0; i < m_bones.size(); ++i) { m_bones[i].rotation.toMatrix(m_bones[i].inv_bind_matrix); m_bones[i].inv_bind_matrix.translate(m_bones[i].position); } for (int i = 0; i < m_bones.size(); ++i) { m_bones[i].inv_bind_matrix.fastInverse(); } return true; }
bool Model::parseBones(FS::IFile& file) { int bone_count; file.read(&bone_count, sizeof(bone_count)); if (bone_count < 0) return false; if (bone_count > Bone::MAX_COUNT) { g_log_warning.log("Renderer") << "Model " << getPath().c_str() << " has too many bones."; return false; } m_bones.reserve(bone_count); for (int i = 0; i < bone_count; ++i) { Model::Bone& b = m_bones.emplace(m_allocator); int len; file.read(&len, sizeof(len)); char tmp[MAX_PATH_LENGTH]; if (len >= MAX_PATH_LENGTH) { return false; } file.read(tmp, len); tmp[len] = 0; b.name = tmp; m_bone_map.insert(crc32(b.name.c_str()), m_bones.size() - 1); file.read(&len, sizeof(len)); if (len >= MAX_PATH_LENGTH) { return false; } if(len > 0) { file.read(tmp, len); tmp[len] = 0; b.parent = tmp; } else { b.parent = ""; } file.read(&b.transform.pos.x, sizeof(float) * 3); file.read(&b.transform.rot.x, sizeof(float) * 4); } m_first_nonroot_bone_index = -1; for (int i = 0; i < bone_count; ++i) { Model::Bone& b = m_bones[i]; if (b.parent.length() == 0) { if (m_first_nonroot_bone_index != -1) { g_log_error.log("Renderer") << "Invalid skeleton in " << getPath().c_str(); return false; } b.parent_idx = -1; } else { b.parent_idx = getBoneIdx(b.parent.c_str()); if (b.parent_idx > i || b.parent_idx < 0) { g_log_error.log("Renderer") << "Invalid skeleton in " << getPath().c_str(); return false; } if (m_first_nonroot_bone_index == -1) { m_first_nonroot_bone_index = i; } } } for (int i = 0; i < m_bones.size(); ++i) { m_bones[i].inv_bind_transform = m_bones[i].transform.inverted(); } for (int i = 0; i < m_bones.size(); ++i) { int p = m_bones[i].parent_idx; if (p >= 0) { m_bones[i].relative_transform = m_bones[p].inv_bind_transform * m_bones[i].transform; } else { m_bones[i].relative_transform = m_bones[i].transform; } } return true; }