#include #include subface::~subface() noexcept { if (!data_center) return; data_center->transform_blocks.release(*model_matrices); } internal::transform_block &subface::raw_local_to_world() const { return model_matrices->local_to_world; } internal::transform_block &subface::raw_world_to_local() const { return model_matrices->world_to_local; } Eigen::Vector3d subface::local_to_world_scale() const { return model_matrices->local_to_world.linear().colwise().norm(); } Eigen::Matrix3d subface::trans_world_to_local_linear() const { return model_matrices->world_to_local.linear().transpose(); } std::pair subface::apply_transform(internal::transform_type type, Eigen::Vector4d param) { auto temp = *model_matrices; switch (type) { case internal::transform_type::scale: { temp.local_to_world.linear() = param.head<3>().asDiagonal() * temp.local_to_world.linear(); temp.world_to_local.linear() = temp.world_to_local.linear() * param.head<3>().cwiseInverse().asDiagonal(); } break; case internal::transform_type::rotation: { auto rotation_matrix = Eigen::Quaterniond(param).toRotationMatrix(); temp.local_to_world.linear() = rotation_matrix * temp.local_to_world.linear(); temp.world_to_local.linear() = temp.world_to_local.linear() * rotation_matrix.transpose(); } break; case internal::transform_type::translation: { Eigen::Translation3d translation(param.head<3>()); temp.local_to_world = translation * temp.local_to_world; temp.world_to_local = temp.world_to_local * translation.inverse(); } break; default: throw std::invalid_argument("Invalid transform type"); } bool reversed{}; if (temp.world_to_local.data()[0] < 0) { temp.local_to_world.matrix() *= -1; temp.world_to_local.matrix() *= -1; reversed = true; } auto [iter, _] = data_center->transform_blocks.acquire(temp); return {iter.operator->(), reversed}; }