sketchucation logo sketchucation
    • Login
    πŸ€‘ SketchPlus 1.3 | 44 Tools for $15 until June 20th Buy Now

    The Transformation Matrix

    Scheduled Pinned Locked Moved Developers' Forum
    13 Posts 7 Posters 3.4k Views 7 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.
    • J Offline
      Jim
      last edited by

      This is something I've always wanted to learn about, but have never found the time. Now I am collaborating with someone who would like a dialog to manipulate Group and Component Transformations. One thing that was requested is setting/getting the scale and rotation of a Group.

      The API provides methods to get the position via the Transformation.origin method. But there is no complement for getting the scale or rotation.

      It appears the scale and rotation values will need to be calculated from the values returned in the Array from Transformation.to_a. I figured a little trig and I'd be all set, but it's slightly more complicated.

      Can anyone help explain the transformation matrix, and how to extract the scale and rotation from it?

      Maybe we can develop some methods, such as:

      
      tr = my_group.transformation
      xs = tr.xscale
      ys = tr.yscale
      zs = tr.zscale
      xr = tr.xrotation
      ...
      
      

      I think the first thing I will do is write a method to pretty-print the array as a 4x4 matrix...

      And second, identify the elements of the array returned by Transformation.to_a.

      Hi

      1 Reply Last reply Reply Quote 0
      • W Offline
        Whaat
        last edited by

        Hi Jim,

        I wrote this snippet of code a long time ago for SkIndigo. It should help you a bit. I remember that extracting these values from the transformation array was pretty confusing.

        trans=trans.to_a
        
        scalex=Math.sqrt(trans[0]**2+trans[1]**2+trans[2]**2)
        scaley=Math.sqrt(trans[4]**2+trans[5]**2+trans[6]**2)
        scalez=Math.sqrt(trans[8]**2+trans[9]**2+trans[10]**2)
        			
        scale=scalex
        scale=scaley if scaley>scale
        scale=scalez if scalez>scale
        
        out.print "			<pos>#{trans[12]} #{trans[13]} #{trans[14]}</pos>\n"
        out.print "			<scale>#{scale}</scale>\n"	
        out.print "			<rotation>\n"
        out.print "				<matrix>\n"
        out.print "					#{trans[0]/scalex} #{trans[4]/scaley} #{trans[8]/scalez} #{trans[1]/scalex} #{trans[5]/scaley} #{trans[9]/scalez} #{trans[2]/scalex} #{trans[6]/scaley} #{trans[10]/scalez}\n"
        out.print "				</matrix>\n"
        out.print "			</rotation>\n"
        

        Since Indigo only supports uniform scaling, I decided to find the maximum scale of the object in the X,Y, or Z direction and then use that exported scale value.

        SketchUp Plugins for Professionals

        1 Reply Last reply Reply Quote 0
        • PixeroP Offline
          Pixero
          last edited by

          I'm certainly no expert but I wrote a MentalRay shader for Maya once that uses the transformation Matrix to position scale and rotate a texture. If you really want to learn it there is an exellent book called Complete Maya Programming volume 2 that explains in detail every thing about matrices and more. Not just for Maya.

          I'll try to make a very short explanation if I can remember it right.

          1 0 0
          0 1 0
          0 0 1
          

          The 1's is the x, y, z scale.

          
          1 0 0
          0 cos(rx) sin(rx)
          0 -sin(rx cos(rx)
          
          

          X axis rotation.

          
          cos(ry) 0 -sin(ry)
          0 1 0
          sin(ry) 0 cos(ry)
          
          

          Y axis rotation.

          
          cos(rz sin(rz) 0
          -sin(rz) cos(rz) 0
          0 0 1
          

          Z axis rotation.

          Feel free to have a look at the source code for my JS_Place3dTexture shader at my site: http://www.pixero.com.
          Mental Ray section.

          1 Reply Last reply Reply Quote 0
          • R Offline
            remus
            last edited by

            I know a bit about matrices and transformation matrices.

            Have you read the wiki article jim? Thatll be a good place to start to get the general idea about how matrices behave.

            I'll do a quick word document with an explanation of them, give us 30 mins or so.

            EDIT: just reread your post and im not sure how well any of the stuff i know will transfer over to ruby stuff, ill do it anyway πŸ˜„

            EDIT 2: i just realised what a large topic matrices are, and how long it would take to do a proper explanation. If you dont mind i wont do the word doc. Im happy to answer any queries you have about transformation matrices and matrices in general, though.

            http://remusrendering.wordpress.com/

            1 Reply Last reply Reply Quote 0
            • R Offline
              remus
              last edited by

              I dont think its possible to extract both the scale and rotation in matrix form, as each operation is defined by a separate matrix. These 2 matrices are then multiplied to give you the final transformation.

              To use a simple analogy, imagine we can define the final transformation as the number 12, trying to extract the scale and rotation is like saying "which numbers multiply to give us 12?" obviously theres a few different answers, so we cant say definitively.

              If you could find one though, say the scale of the enlargement, you could then find the rotation with a bit of matrix based jiggery pokery.

              http://remusrendering.wordpress.com/

              1 Reply Last reply Reply Quote 0
              • J Offline
                Jim
                last edited by

                So here's a bit of code to format the transformation array as a matrix. First, I should ask if I've got the matrix correct, or transposed?

                
                class Geom;;Transformation
                  def to_matrix
                    a = self.to_a
                    f = "%8.3f"
                    l = [f, f, f, f].join("  ") + "\n"
                    str =  sprintf l,  a[0], a[1], a[2], a[3]
                    str += sprintf l,  a[4], a[5], a[6], a[7]
                    str += sprintf l,  a[8], a[9], a[10], a[11]
                    str += sprintf l,  a[12], a[13], a[14], a[15]
                    str 
                  end
                end
                
                
                
                Geom;;Transformation.new.to_matrix
                   1.000     0.000     0.000     0.000
                   0.000     1.000     0.000     0.000
                   1.000     0.000     1.000     0.000
                   0.000     0.000     0.000     1.000
                
                
                

                A bit easier on the eyes. So what you see is the transformation matrix for a Group that is at the Origin, has no scaling, and no rotation.

                Now, let's move the Group to position (3, 4, 5):

                
                   1.000     0.000     0.000     0.000
                   0.000     1.000     0.000     0.000
                   0.000     0.000     1.000     0.000
                   3.000     4.000     5.000     1.000
                
                

                That's easy enough. Now move the Group back to the model Origin, and rotate it 45 deg around Z:

                
                   0.707    -0.707     0.000     0.000
                   0.707     0.707     0.000     0.000
                   0.000     0.000     1.000     0.000
                   0.000     0.000     0.000     1.000
                
                

                Now, I need a minute to make sense of that... although I recognize the relationship of 45 and 0.707... O.K. below is the same matrix with 4 sets labeled; p, v1, v2, and v3.

                
                   v1[0.707    -0.707     0.000]   0.000
                   v2[0.707     0.707     0.000]   0.000
                   v3[0.000     0.000     1.000]   0.000
                    p[0.000     0.000     0.000]   1.000
                
                

                The set labeled p is the Group's position in the model. The sets labeled v1, v2, and v3 represent the x, y, and z vectors for the Group. The following image [image 1] shows the physical representation of vectors v1, v2, and v3:

                Image 1

                And if this is correct, we should be able to simply take the length of the vectors v1, v2, and v3 to get the x, y, and z axis scale. Let's test... O.K. that seems logical and appears to give the correct results.

                So, for the getting the scale along each of the Group's axes, I get:

                
                class Geom;;Transformation
                  def xscale; Geom;;Vector3d.new(self.to_a[0, 3]).length; end
                  def yscale; Geom;;Vector3d.new(self.to_a[4, 3]).length; end
                  def zscale; Geom;;Vector3d.new(self.to_a[8, 3]).length; end
                end
                
                

                Which is in agreement with Whaat's solution also (although he used the length of vector formula.)

                Note: this is a work in progress...

                Hi

                1 Reply Last reply Reply Quote 0
                • tbdT Offline
                  tbd
                  last edited by

                  it still has bugs, but I am too sleepy now. maybe someone can see the problem with fresh eyes πŸ˜‰

                  
                  module Geom
                    class Transformation
                      def scale_x;self.to_a[0..2].x;end
                      def scale_y;self.to_a[4..6].y;end
                      def scale_z;self.to_a[8..10].z;end
                      
                      def rot_x;180-Math.acos((xaxis*X_AXIS).y).radians;end
                      def rot_y;Math.acos((yaxis*Y_AXIS).x).radians;end    
                      def rot_z;180-Math.acos((zaxis*Z_AXIS).y).radians;end    
                    end
                  end
                  
                  t =  Sketchup.active_model.selection[0].transformation
                  p "%s %s %s" % [t.rot_x, t.rot_y, t.rot_z]
                  
                  

                  SketchUp Ruby Consultant | Podium 1.x developer
                  http://plugins.ro

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

                    Could it also detect "flipped" transforms? When you do "flip along..." it does something to the transform. I never have been able to wrap my brain around it but AdamB wrote a explanation in this thread.

                    301 Moved Permanently

                    favicon

                    (www.sketchucation.com)

                    1 Reply Last reply Reply Quote 0
                    • R Offline
                      remus
                      last edited by

                      In a standard matrix transformation any matrix which flips an object has a negative determinant, good bit about how to find the determinant of a matrix here.

                      http://remusrendering.wordpress.com/

                      1 Reply Last reply Reply Quote 0
                      • Didier BurD Offline
                        Didier Bur
                        last edited by

                        Hi Jim,

                        Here's what I found:

                        module Math
                          def Math;;arcsin(x) 
                            x = x % 1
                            atan2(x,sqrt(1.0-x*x))
                          end
                        end
                        
                        class Geom;;Transformation
                          def identity
                            Geom;;Transformation.new([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1])
                          end
                        
                          def xscale
                            ((Geom;;Vector3d.new 1,0,0).transform! self).length
                          end
                        
                          def yscale
                            ((Geom;;Vector3d.new 0,1,0).transform! self).length
                          end
                        
                          def zscale
                            ((Geom;;Vector3d.new 0,0,1).transform! self).length
                          end
                        
                          def xrot
                            Sketchup.format_angle(Math.atan2(self.to_a[9],self.to_a[10]))
                          end
                        
                          def yrot
                            Sketchup.format_angle(-Math.arcsin(self.to_a[8]))
                          end
                        
                          def zrot
                            Sketchup.format_angle(Math.atan2(self.to_a[4],self.to_a[0]))
                          end
                        end
                        

                        Hope this helps,

                        DB

                        1 Reply Last reply Reply Quote 0
                        • J Offline
                          Jim
                          last edited by

                          Didier, is your arcsin the same as Math::asin?

                          Hi

                          1 Reply Last reply Reply Quote 0
                          • Didier BurD Offline
                            Didier Bur
                            last edited by

                            Yes β˜€

                            DB

                            1 Reply Last reply Reply Quote 0
                            • J Offline
                              Jim
                              last edited by

                              Ok, good. I wasn't sure if asin was simply overlooked, or if you needed something different.

                              Hi

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

                              Advertisement