diff Framework/Scene2D/Internals/OpenGLInfoPanelRenderer.cpp @ 1325:be17fed8c7c5 broker

Added flag in InfoPanelSceneLayer to apply the scene rotation to the displayed image.
author Benjamin Golinvaux <bgo@osimis.io>
date Tue, 24 Mar 2020 20:34:28 +0100
parents 2d8ab34c8c91
children
line wrap: on
line diff
--- a/Framework/Scene2D/Internals/OpenGLInfoPanelRenderer.cpp	Tue Mar 24 16:24:26 2020 +0100
+++ b/Framework/Scene2D/Internals/OpenGLInfoPanelRenderer.cpp	Tue Mar 24 20:34:28 2020 +0100
@@ -32,6 +32,7 @@
         context_.MakeCurrent();
         texture_.reset(new OpenGL::OpenGLTexture(context_));
         texture_->Load(layer.GetTexture(), layer.IsLinearInterpolation());
+        applySceneRotation_ = layer.ShouldApplySceneRotation();
         anchor_ = layer.GetAnchor();
       }
     }
@@ -41,11 +42,11 @@
                                                      const InfoPanelSceneLayer& layer) :
       context_(context),
       program_(program),
-      anchor_(BitmapAnchor_TopLeft)
+      anchor_(BitmapAnchor_TopLeft),
+      applySceneRotation_(false)
     {
       LoadTexture(layer);
     }
-
     
     void OpenGLInfoPanelRenderer::Render(const AffineTransform2D& transform,
                                          unsigned int canvasWidth,
@@ -60,7 +61,56 @@
 
         // The position of this type of layer is layer: Ignore the
         // "transform" coming from the scene
-        program_.Apply(*texture_, AffineTransform2D::CreateOffset(dx, dy), true);
+        AffineTransform2D actualTransform = 
+          AffineTransform2D::CreateOffset(dx, dy);
+
+        if (applySceneRotation_)
+        {
+          // the transformation is as follows:
+          // - originally, the image is aligned so that its top left corner
+          // is at 0,0
+          // - first, we translate the image by -w/2,-h/2 
+          // - then we rotate it, so that the next rotation will make the  
+          //   image rotate around its center.
+          // - then, we translate the image by +w/2,+h/2 to put it
+          //   back in place
+          // - the fourth and last transform is the one that brings the 
+          //   image to its desired anchored location.
+
+          int32_t halfWidth = 
+            static_cast<int32_t>(0.5 * texture_->GetWidth());
+
+          int32_t halfHeight=
+            static_cast<int32_t>(0.5 * texture_->GetHeight());
+
+          AffineTransform2D translation1 =
+            AffineTransform2D::CreateOffset(-halfWidth, -halfHeight);
+
+          const Matrix& sceneTransformM = transform.GetHomogeneousMatrix();
+          Matrix r;
+          Matrix q;
+          LinearAlgebra::RQDecomposition3x3(r, q, sceneTransformM);
+
+          // counterintuitively, q is the rotation and r is the upper
+          // triangular
+          AffineTransform2D rotation(q);
+
+          AffineTransform2D translation2 =
+            AffineTransform2D::CreateOffset(halfWidth, halfHeight);
+
+          // please note that the last argument is the 1st applied 
+          // transformation (rationale: if arguments are a, b and c, then
+          // the resulting matrix is a*b*c:
+          // x2 = (a*b*c)*x1 = (a*(b*(c*x1))) (you can see that the result
+          // of c*x1 is transformed by b, and the result of b*c*x1 is trans-
+          // formed by a)
+          actualTransform = AffineTransform2D::Combine(actualTransform,
+                                                       translation2,
+                                                       rotation,
+                                                       translation1);
+        }
+
+        program_.Apply(*texture_, actualTransform, true);
       }
     }
   }