sketchucation logo sketchucation
    • Login
    ℹ️ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info

    Transformations

    Scheduled Pinned Locked Moved Developers' Forum
    29 Posts 6 Posters 1.5k Views 6 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Z Offline
      zitoun
      last edited by

      OK, I surrender, I chose Cleverbeans method in the end, which revealed to be quite fine to do:
      I re-initialized my plane transformation, then I scale it with a factor of 1/2 several time, until I had the right size (1/32 in the end). I then chose a reference rotation to position the plane as I wanted to in the first place. I then have an "initialTransformation" that I will have to apply each time BEFORE the other regular transformation.

      So for each frame I'll have
      e.transform!( e.transformation.inverse ) e.transform!( initialTransformation ) e.transform!( transformationAtSuchFrame ) #with transformationAtSuchFrame combining a rotation and a translation

      Now I am not depending anymore of a random initial state.
      Of course I will rather combine all the intermediate matrices and then apply once the resulting transformation, it should be quicker.

      EDIT: I may have a quicker solution, that I still have to validate: Geom::Transformation.origin method gives the translation to put the object at the origin (and then be able to perform a simple rotation).
      I might use this rather than combine several 4x4 matrix, it has to be a lot quicker !

      The light at the end of the tunnel is a train.

      1 Reply Last reply Reply Quote 0
      • thomthomT Offline
        thomthom
        last edited by

        @zitoun said:

        e.transform!( e.transformation.inverse )
        e.transform!( initialTransformation )

        This seems like it can be reduced to
        e.transformation = initialTransformation

        and that could possibly be reduced to:

        e.transformation = initialTransformation * transformationAtSuchFrame

        Thomas Thomassen — SketchUp Monkey & Coding addict
        List of my plugins and link to the CookieWare fund

        1 Reply Last reply Reply Quote 0
        • Z Offline
          zitoun
          last edited by

          @thomthom said:

          This seems like it can be reduced to
          e.transformation = initialTransformation
          and that could possibly be reduced to:
          e.transformation = initialTransformation * transformationAtSuchFrame

          Really?
          I thought I had tested this solution and my results were not conclusive.
          But maybe I was too tired: I'm gonna try again !

          The light at the end of the tunnel is a train.

          1 Reply Last reply Reply Quote 0
          • thomthomT Offline
            thomthom
            last edited by

            If you always calculate from one fixed state then there is no need to undo the current transformation, you just set a new transformation overriding the old one.

            Thomas Thomassen — SketchUp Monkey & Coding addict
            List of my plugins and link to the CookieWare fund

            1 Reply Last reply Reply Quote 0
            • Z Offline
              zitoun
              last edited by

              @thomthom said:

              If you always calculate from one fixed state then there is no need to undo the current transformation, you just set a new transformation overriding the old one.

              Yes indeed, but for some reason I thought that the method entity.transformation= was working differently (but I may have been really tired at the time I tested it).
              It completely make sense that it works the way you describe it.

              The light at the end of the tunnel is a train.

              1 Reply Last reply Reply Quote 0
              • Z Offline
                zitoun
                last edited by

                Ahem.

                Just remember:

                @object.transform! @object.transformation.inverse
                @object.transform! @transformationAt[toPage]
                
                @object.transform! @transformationAt[toPage] * @object.transformation.inverse
                

                Note the order of the transformations... I had forgotten this well known pb !

                The light at the end of the tunnel is a train.

                1 Reply Last reply Reply Quote 0
                • thomthomT Offline
                  thomthom
                  last edited by

                  @zitoun said:

                  @object.transform! @object.transformation.inverse

                  This just resets the transformation - same as @object.transformation = Geom::Transformation.new

                  @zitoun said:

                  @object.transform! @transformationAt[toPage] * @object.transformation.inverse

                  Isn't this just the same as: @object.transformation = @transformationAt[toPage] ?

                  Thomas Thomassen — SketchUp Monkey & Coding addict
                  List of my plugins and link to the CookieWare fund

                  1 Reply Last reply Reply Quote 0
                  • AdamBA Offline
                    AdamB
                    last edited by

                    @thomthom said:

                    If you always calculate from one fixed state then there is no need to undo the current transformation, you just set a new transformation overriding the old one.

                    And you will end up with many problems if you build your code around inverting the CTM and multiplying by a new transform.

                    So if you're rotating an object, a low quality approach is to repeatedly apply a (say) 5 degree rotation rather than as Thomthom suggest, calculate the rotation at a time T and then calc what rotation you need.

                    The problem is that floating point does have finite precision, so if you repeatedly perform incremental transform as it seems you're doing, you'll end up with a non-orthonormal matrix. (Thats a bad thing).

                    Developer of LightUp Click for website

                    1 Reply Last reply Reply Quote 0
                    • Z Offline
                      zitoun
                      last edited by

                      @thomthom said:

                      @zitoun said:

                      @object.transform! @object.transformation.inverse

                      This just resets the transformation - same as @object.transformation = Geom::Transformation.new

                      @zitoun said:

                      @object.transform! @transformationAt[toPage] * @object.transformation.inverse

                      Isn't this just the same as: @object.transformation = @transformationAt[toPage] ?

                      Yes, the inverse is not useful in my case.
                      I use @object.transformation= @transformationAt[toPage], as you suggest, and it works (well I still have some awkward pbs but I expect to solve them soon).

                      The code was just for my tests, I wanted to underline here that if you wish to do

                      entity.transform! entity.transformation.inverse
                      entity.transform! transfA
                      entity.transform! transfB
                      

                      you could as well do

                      entity.transform! transfB * transfA * entity.transformation.inverse
                      

                      or even better, as you say Thomthom

                      entity.transformation = transf[b]B[/b] * transf[b]A[/b]
                      

                      The light at the end of the tunnel is a train.

                      1 Reply Last reply Reply Quote 0
                      • Z Offline
                        zitoun
                        last edited by

                        @adamb said:

                        And you will end up with many problems if you build your code around inverting the CTM and multiplying by a new transform.

                        Not really: it's more like reseting the transformation and set the one you like. No inverse is needed, and this solution is actually the only solution I can see so far.

                        But you're right, ignoring each object's current orientation is a real problem.

                        The light at the end of the tunnel is a train.

                        1 Reply Last reply Reply Quote 0
                        • thomthomT Offline
                          thomthom
                          last edited by

                          @zitoun said:

                          But you're right, ignoring each object's current orientation is a real problem.

                          But you know that from the previous transformation.

                          Thomas Thomassen — SketchUp Monkey & Coding addict
                          List of my plugins and link to the CookieWare fund

                          1 Reply Last reply Reply Quote 0
                          • Z Offline
                            zitoun
                            last edited by

                            Another thing: angle_between only gives absolute angles.
                            If you need oriented angles, you might need something like

                            def angBtw(v1, v2)
                            	u1 = v1.normalize
                            	u2 = v2.normalize
                            	a = u1.angle_between u2
                            	if ( u1.cross u2 ).dot( Z_AXIS ) > 0
                            		return a
                            	else
                            		return -a
                            	end
                            end
                            

                            Note 1: normalization is used only because there seems to be some trouble with angle_between for small values...
                            Note 2: I took Z_AXIS as my scene reference vector for now, but the good way to do would be to take the up vector of your object.

                            The light at the end of the tunnel is a train.

                            1 Reply Last reply Reply Quote 0
                            • C Offline
                              Cleverbeans
                              last edited by

                              @zitoun said:

                              I have no clue what these are yet, but I guess I somehow can retrieve my rotation matrix from such component...

                              Note that a transformation has the .to_a method as well which gives you exactly the information you're looking for. The array it returns is 16 floats for the four by four matrix which defines the transformation from the components defining coordinate system to the current coordinate system. Since you mentioned quaternions I'll assume you're familiar with with the essentials of matrices and linear transformations. First, we can interpret the scaling and rotation of a component as the action of a matrix on the basis vectors of the component definition. Say for example you define your component relative to the standard basis of x=[1,0,0], y=[0,1,0], z=[0,0,1]. Rather than keeping these vectors separately, you can just encode them as the 3x3 identity matrix, and then define all the entities in the component relative to this matrix. From here, any sort of rotation/scaling can be interpreted as a change of basis. The trouble of course is that any linear transformation preserves the zero vector, so you can't model a translation in this way. This means to fully describe the relative coordinates you require a an equation of the form Ax + b where A is an invertible 3x3 change of basis matrix and b is the translation vector with x being the "defining" vector of some entity internal to the component.

                              This is where the clever bit comes in. You can model an affine transformation of the form Ax + b as a single matrix transformation by embedding it into a space with one higher dimension. This is why the transformation.to_a method returns a 16 entry array, it's a 4x4 matrix with the first four entries being the first column, the second four entries being the second column and so on. It's easy enough to extract the original 3x3 matrix and the translation vector as well, the "upper-left" 3x3 block matrix is exactly the change of basis matrix A, and the final column vector is of the form [b, 1] where b is the translation vector. From here extracting the rotation matrix is a simple matter of matrix algebra since any change of basis matrix A can be decomposed as A = QS where Q is a rotation matrix and S is a diagonal matrix representing the scaling of each axis.

                              It's worth getting to know the 4x4 representation if you haven't before since it's also the way the OpenGL standard models the objects. The ability to model vector addition as matrix multiplication is only one of the reason they do it, the other being that when you're rendering perspective views rather than simply orthographic views the value of the bottom right entry plays an important role in correcting the scale of the transformation after applying the perspective matrix.

                              1 Reply Last reply Reply Quote 0
                              • 1
                              • 2
                              • 2 / 2
                              • First post
                                Last post
                              Buy SketchPlus
                              Buy SUbD
                              Buy WrapR
                              Buy eBook
                              Buy Modelur
                              Buy Vertex Tools
                              Buy SketchCuisine
                              Buy FormFonts

                              Advertisement