|
| 1 | +/* |
| 2 | + * Demonstrating coordinate frame transformations |
| 3 | + */ |
| 4 | +#include <iostream> |
| 5 | +#include <sm/vec> |
| 6 | +#include <sm/mat> |
| 7 | +#include <mplot/Visual.h> |
| 8 | +#include <mplot/CoordArrows.h> // This is the only VisualModel derived class not called SomethingVisual! |
| 9 | + |
| 10 | +int main() |
| 11 | +{ |
| 12 | + mplot::Visual v(1024, 768, "Slerping"); |
| 13 | + v.lightingEffects (true); |
| 14 | + |
| 15 | + // A is the end location coordinate arrows (darker) |
| 16 | + sm::vec<float> offset = {}; |
| 17 | + auto cavm = std::make_unique<mplot::CoordArrows<>> (offset); |
| 18 | + v.bindmodel (cavm); |
| 19 | + cavm->x_axis_col = mplot::colour::maroon; |
| 20 | + cavm->y_axis_col = mplot::colour::darkgreen; |
| 21 | + cavm->z_axis_col = mplot::colour::midnightblue; |
| 22 | + cavm->finalize(); |
| 23 | + auto cA = v.addVisualModel (cavm); |
| 24 | + |
| 25 | + // B is the starting location coordinate arrows (lighter) |
| 26 | + cavm = std::make_unique<mplot::CoordArrows<>> (offset); |
| 27 | + v.bindmodel (cavm); |
| 28 | + cavm->x_axis_col = mplot::colour::firebrick1; |
| 29 | + cavm->y_axis_col = mplot::colour::palegreen3; |
| 30 | + cavm->z_axis_col = mplot::colour::steelblue1; |
| 31 | + cavm->finalize(); |
| 32 | + auto cB = v.addVisualModel (cavm); |
| 33 | + |
| 34 | + cavm = std::make_unique<mplot::CoordArrows<>> (offset); |
| 35 | + v.bindmodel (cavm); |
| 36 | + cavm->finalize(); |
| 37 | + auto cC = v.addVisualModel (cavm); |
| 38 | + |
| 39 | + // Define A's location as a viewmatrix. Apply a rotation (first) then a translation |
| 40 | + sm::mat<float, 4> A; |
| 41 | + A.translate (sm::vec<float>{0.2,0.4,0}); |
| 42 | + A.rotate (sm::vec<float>::uy(), sm::mathconst<float>::pi_over_4); |
| 43 | + |
| 44 | + // The starting location. |
| 45 | + sm::mat<float, 4> B; |
| 46 | + B.translate (sm::vec<float>{1,1,1}); |
| 47 | + B.rotate (sm::vec<float>::uz(), sm::mathconst<float>::pi_over_2); |
| 48 | + |
| 49 | + // From A and B find the pure translation between the two |
| 50 | + sm::vec<float> delta_x = A.translation() - B.translation(); |
| 51 | + |
| 52 | + // Compute the pre-translation rotations |
| 53 | + sm::mat<float, 4> A0 = A; |
| 54 | + A0.translate (-A.translation()); |
| 55 | + sm::mat<float, 4> B0 = B; |
| 56 | + B0.translate (-B.translation()); |
| 57 | + sm::quaternion<float> rA = A0.rotation(); |
| 58 | + sm::quaternion<float> rB = B0.rotation(); |
| 59 | + |
| 60 | + // Set the viewmatrix for both A and B coordinate arrows (these will stay fixed) |
| 61 | + cA->setViewMatrix (A); |
| 62 | + cB->setViewMatrix (B); |
| 63 | + |
| 64 | + int count = 0; |
| 65 | + while (!v.readyToFinish()) { |
| 66 | + |
| 67 | + v.render(); |
| 68 | + v.wait (0.018); |
| 69 | + |
| 70 | + float prop = static_cast<float>(count++ % 100) / 100.0f; |
| 71 | + |
| 72 | + // Compute the intermediate translation and rotation, C and apply this to the cC coordinate arrows |
| 73 | + sm::mat<float, 4> C; |
| 74 | + // C is a rotation of the intermediate rotation between rA and rB, then a translation to B + |
| 75 | + // the intermediate delta_x: |
| 76 | + C.translate (B.translation() + prop * delta_x); |
| 77 | + C.rotate (rB.slerp (rA, prop)); |
| 78 | + |
| 79 | + cC->setViewMatrix (C); |
| 80 | + } |
| 81 | +} |
0 commit comments