| 780 | bool read_universaltransform_file(const std::string& rootDir) const; |
| 781 | |
| 782 | bool Move(vtkPoints* pts, double time) const override |
| 783 | { |
| 784 | if (this->transforms.empty()) |
| 785 | { |
| 786 | // at least one entry is required |
| 787 | return false; |
| 788 | } |
| 789 | |
| 790 | // let's clamp to time range in the universal transform file |
| 791 | time = std::min(this->transforms.rbegin()->first, time); |
| 792 | time = std::max(this->transforms.begin()->first, time); |
| 793 | |
| 794 | auto next = this->transforms.lower_bound(time); |
| 795 | auto prev = next; |
| 796 | |
| 797 | vtkNew<vtkTransform> transform; |
| 798 | transform->PostMultiply(); |
| 799 | |
| 800 | double t; |
| 801 | if (next->first > time) |
| 802 | { |
| 803 | prev = std::prev(next); |
| 804 | const double interval = (next->first - prev->first); |
| 805 | const double dt = std::min(time - prev->first, interval); |
| 806 | t = dt / interval; // normalized dt |
| 807 | } |
| 808 | else // this also handles single entry files |
| 809 | { |
| 810 | t = 0.0; |
| 811 | } |
| 812 | |
| 813 | const vtkVector3d rotation_center = |
| 814 | prev->second.rotation_center * (1.0 - t) + next->second.rotation_center * t; |
| 815 | transform->Translate((rotation_center * -1.0).GetData()); |
| 816 | |
| 817 | const vtkVector3d linear_scale = |
| 818 | prev->second.linear_scale * (1.0 - t) + next->second.linear_scale * t; |
| 819 | transform->Scale(linear_scale.GetData()); |
| 820 | |
| 821 | double quatdotprod = prev->second.quaternion.Dot(next->second.quaternion); |
| 822 | |
| 823 | if (quatdotprod < 0.0) |
| 824 | { |
| 825 | next->second.quaternion = -next->second.quaternion; |
| 826 | quatdotprod = -quatdotprod; |
| 827 | } |
| 828 | |
| 829 | vtkVector4d quatnow; |
| 830 | if (quatdotprod > 0.9995) // linear interpolation (LERP) |
| 831 | { |
| 832 | quatnow = prev->second.quaternion * (1.0 - t) + next->second.quaternion * t; |
| 833 | } |
| 834 | else // spherical linear interpolation (SLERP) |
| 835 | { |
| 836 | const double thdiff = std::acos(quatdotprod); |
| 837 | const double sndiff = std::sin(thdiff); |
| 838 | const double cfi = sin((1.0 - t) * thdiff) / sndiff; |
| 839 | const double cfn = sin(t * thdiff) / sndiff; |
nothing calls this directly
no test coverage detected