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

    Matrix Multiplication in C[++]

    Scheduled Pinned Locked Moved Developers' Forum
    13 Posts 5 Posters 486 Views 5 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.
    • M Offline
      MartinRinehart
      last edited by

      To get every possible scale using Move!() I had to write my own matrix multiplier. It wasn't particularly hard, but if I've overlooked something it was particularly stupid.

      Is there any way to use the API to get at the matrix multiplication written in C (or C++)? Any way better than, for example, doing a transform!(), grabbing the matrix and then doing an undo?

      Author, Edges to Rubies - The Complete SketchUp Tutorial at http://www.MartinRinehart.com/models/tutorial.

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

        is there any reason (transformation * transformation) won't work? I guess I'm a bit confused in what exactly you want.

        1 Reply Last reply Reply Quote 0
        • M Offline
          MartinRinehart
          last edited by

          @cjthompson said:

          is there any reason (transformation * transformation) won't work?

          The doc says *() is Transformation * Point3d => Transformation. I'm in need of Transformation * Transformation => Transformation.

          My application is animation. I may be turning 180 degrees by, for example, turning 0.5 degrees over each of 360 frames. If you have xform, a "turn 0.5 degrees" transformation, and you call instance.transform!( xform ) the transform!() method multiplies the existing transformation by the new xform matrix.

          It also pushes undo info onto the undo stack, which you don't want. instance.move!( xform ) is supposed to be the same as instance.transform!() minus the undo stack. Unfortunately, it's buggy. It forgets to multiply, and just replaces the old transformation matrix with the new one (losing all existing scales, rotations and location). Bad bug.

          So I'm getting xform via API calls, then multiplying (in Ruby) the existing and new transformations and giving the result to move!(). It works, but using the matrix multiplication code that's there already would be a lot faster. (The matrix multiplication is so fundamental to 3d geometry that it may be hand-tooled assembler.)

          Author, Edges to Rubies - The Complete SketchUp Tutorial at http://www.MartinRinehart.com/models/tutorial.

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

            transformation * transformation works.

            The docs says

            @unknownuser said:

            point1
            A Point3d, Vector3d, or Transformation object.

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

            1 Reply Last reply Reply Quote 0
            • M Offline
              MartinRinehart
              last edited by

              @thomthom said:

              transformation * transformation works.

              The docs says

              @unknownuser said:

              point1
              A Point3d, Vector3d, or Transformation object.

              Blind me! Many thanks.

              Author, Edges to Rubies - The Complete SketchUp Tutorial at http://www.MartinRinehart.com/models/tutorial.

              1 Reply Last reply Reply Quote 0
              • M Offline
                MartinRinehart
                last edited by

                Blind me? Maybe it was, "Lucky me."

                Transformation * Transformation multiplies the 3x3 rotation/scale matrix. It does not handle location. My code multiplies the 4x4 matrices. Here are the results:

                09.jpg

                xform:
                1.0, 0.0, 0.0, 0.0 0.0, 1.0, 0.0, 0.0 0.0, 0.0, 1.0, 0.0 20.0, 0.0, 0.0, 1.0

                Asked for Transformation.rotation( [0,0,0], [0,1,0], 30 ). Got:

                0.866025403784439, 0.0, -0.5, 0.0 0.0, 1.0, 0.0, 0.0 0.5, 0.0, 0.866025403784439, 0.0 0.0, 0.0, 0.0, 1.0

                Used Transformation * Transformation, then move!().

                10.jpg

                xform:
                0.866025403784439, 0.0, -0.5, 0.0 0.0, 1.0, 0.0, 0.0 0.5, 0.0, 0.866025403784439, 0.0 20.0, 0.0, 0.0, 1.0

                Not my idea of rotating around the origin. So I tried again, using my own matrix multiplication:

                11.jpg

                xform:
                0.866025403784439, 0.0, -0.5, 0.0 0.0, 1.0, 0.0, 0.0 0.5, 0.0, 0.866025403784439, 0.0 17.3205080756888, 0.0, -10, 1.0

                My own version appears to rotate around the origin.

                Anybody wanting to fiddle with this, here's a little Matrix class. You create a Matrix with Matrix.new( nrows, ncols, [array of values] ). From a Transformation, that's Matrix.new( 4, 4, xform.to_a() ). Individual values may be retrieved by subscripting: m1[3,3] is the global scale factor, Wt. You multiply by multiplying: m1 * m2. ( instance_xform * new_xform. It's not commutative.)

                class Matrix
                =begin
                You can multiply one matrix by another with this class.
                
                In m1 * m2, the number of rows in m1 must equal the number of columns in m2. This code does absolutely no checking. Program must check sizes before calling this code! (Application herein; square matrices of equal size, where this is not an issue.) 
                =end
                    
                    attr_reader ;nrows, ;ncols, ;values
                    
                    def initialize( nrows, ncols, values )
                        @nrows = nrows
                        @ncols = ncols
                        @values = values
                    end # of initialize()
                    
                    def * ( m2 )
                        vals = []
                        for r in 0..(@nrows-1)
                            for c in 0..(m2.ncols-1)
                                vals.push( row_col(row( r ), m2.col( c )) )
                            end
                        end
                        return Matrix.new( @nrows, m2.ncols, vals )
                    end # of *()
                
                    def [] ( row, col )
                        return @values[ row * @ncols + col ]
                    end # of []()
                    
                    def col( c )
                        ret = []
                        for r in 0..(@nrows-1)
                            ret.push( @values[r*@ncols + c] )
                        end
                        return ret
                    end # of col()
                
                    def row( r )
                        start = r * @ncols
                        return @values[ start .. (start + @ncols - 1) ]
                    end # of row()
                    
                    def row_col( row, col )
                        ret = 0
                        for i in 0..(row.length()-1)
                            ret += row[ i ] * col[ i ]
                        end
                        return ret
                    end
                    
                    def inspect()
                        ret = ''
                        for r in 0..(@nrows-1)
                            for c in 0..(@ncols-1)
                                ret += self[r, c].to_s
                                ret += ', ' if c < (@ncols-1)
                            end
                            ret += "\n"
                        end
                        return ret
                    end # of inspect()
                    
                end # of class Matrix
                
                

                Anybody not believing what I say (that included me!) is invited to try for themselves.

                Author, Edges to Rubies - The Complete SketchUp Tutorial at http://www.MartinRinehart.com/models/tutorial.

                1 Reply Last reply Reply Quote 0
                • Chris FullmerC Offline
                  Chris Fullmer
                  last edited by

                  I have not read much of this thread yet, just enough to see that you can multiply a transformation by a point3d?????

                  That might be the missing link for moving an object to a specified point, retaining scale/rotation and not having to tweak the matrix manually. I'll investigate that, along with Martin's code later tonight if all goes well,

                  Chris - I'm excited about this development.

                  Lately you've been tan, suspicious for the winter.
                  All my Plugins I've written

                  1 Reply Last reply Reply Quote 0
                  • Chris FullmerC Offline
                    Chris Fullmer
                    last edited by

                    Nope, my mistake. Now that i've had a chance to look at it, and think it through, multiplying a transformation by a point 3d moves the transformation by the vector defined by the point at the component axis to the point specified.

                    I guess my prefered way to translate to a specific point is still done be finding the vector to that point from the given point and then .transform! to that point.

                    Chris

                    Now its time to read Martin's post thoroughly.

                    Lately you've been tan, suspicious for the winter.
                    All my Plugins I've written

                    1 Reply Last reply Reply Quote 0
                    • M Offline
                      MartinRinehart
                      last edited by

                      My third screenshot could have been clearer. This is an elaboration:

                      12.jpg

                      Author, Edges to Rubies - The Complete SketchUp Tutorial at http://www.MartinRinehart.com/models/tutorial.

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

                        This is what I learned when I wrote my MentalRay transformation matrix plugin.
                        Maybe this info can be of some help:

                        A transformation matrix is made of these components and multipled in the following order:

                        Scale pivot point: point around which scales are performed [Sp]

                        Scale: scaling about x, y, z axes [S]

                        Shear: shearing in xy, xz, yx [Sh]

                        Scale pivot translation: translation introduced to preserve existing scale transformations when moving pivot.
                        This is used to prevent the object from moving when the objects pivot point is not at the origin and a non-unit scale is applied to the object [St].

                        Rotate pivot: point point about which rotations are performed [Rp]

                        Rotation orientation: rotation to orient local rotation space [Ro]

                        Rotation: rotation [R]

                        Rotate pivot translation: translation introduced to preserve exisiting rotate transformations when moving pivot.
                        This is used to prevent the object from moving when the objects pivot point is not at the origin and the pivot is moved. [Rt]

                        Translate: translation in x, y, z axes [T]

                        The transformation matrix is then constructed as follows:

                        [Sp(Inverse)] x [S] x [Sh] x [Sp] x [St] x [Rp(Inverse)] x [Ro] x [R] x [Rp] x [Rt] x [T]

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

                          Can anyone explain why (transformation1 * transformation2) isn't the same as (transformation2 * transformation1)?

                          Anyways, it looks like if you use move!, you have two options, from a practical standpoint:
                          instance.move!(newTransformation*instance.transformation), which is essentially the same as (instance.transform!(newTransformation)) and
                          instance.move!(instance.transformation*newTransformation), which will apply the transformation according to the component's axes.

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

                            @cjthompson said:

                            Can anyone explain why (transformation1 * transformation2) isn't the same as (transformation2 * transformation1)?

                            +1

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

                            1 Reply Last reply Reply Quote 0
                            • Chris FullmerC Offline
                              Chris Fullmer
                              last edited by

                              I like those lines of code Chris, I want to test those later tonight.

                              Chris

                              Lately you've been tan, suspicious for the winter.
                              All my Plugins I've written

                              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