Search code examples
three.jssketchup

SketchUp entities mirrored with "flip along (axis)" not reflected in transform matrix


Question updates at the bottom....

I'm writing a custom SketchUp export plugin in Ruby. I then recreate the geometry in Three.js using the exported data.

I'm having troubles with some component/group transformations, and tracked it down to mirroring, or geometry that has "flip along" applied for some axis. Simply put, the flip along is not respected. I can not find any SU Ruby method to find out whether any given entity has this flip along applied.

I can get a transformation matrix, and convert it (see this question of mine how), however it does not work for these flipped objects. Here's an example result; the rest of the model is fine, but the boat is obviously created using flipped boat halves, and in this picture they appear all over the place:

messy boat

How can I properly take these flipped geometries into account? Do they have some kind of separate matrix, or entity flag in SU Ruby?

Note 1) I have observed similar buggy behaviour in the built-in SketchUp Collada exporter (when loading them with Three.js ColladaLoader).

Note 2) Although I believe this to be a SketchUp Ruby API issue, I tagged this with Three.js just in case there is something obvious I'm missing in regards to mirroring and Matrixes..

Note 3) If the geometries are flipped / mirrored using the scale tool instead of flip along tool (effectively the same result), they work correctly.

UPDATE:

Still struggling to apply this information, but getting closer based on this information: http://sketchucation.com/forums/viewtopic.php?f=6&t=3083

UPDATE #2:

Thanks to Thomthom, I was able to detect and apply correct flipping for objects that are not rotated. For a plain unrotated/unscaled/unflipped component the matrix is:

 1.0, 0.0, 0.0
 0.0, 1.0, 0.0
 0.0, 0.0, 1.0

For a flipped (mirrored) component the matrix can be:

-1.0, 0.0, 0.0
 0.0, 1.0, 0.0
 0.0, 0.0, 1.0

So I can detect that flip easily and all is fine.

But if I arbitrarily rotate the same component (unflipped) an a couple of axes, the matrix looks like this:

 -0.33, -0.58,  0,74
  0.87, -0.50,  0,00
  0.37,  0.64,  0,67

This works correctly in my exporter/importer, I can reapply this matrix on Three.js side.

But when that already rotated component is also mirrored, the matrix looks like this:

  0.33,  0.58, -0.74
  0.87, -0.50,  0.00
  0.37,  0.64,  0.67

I can't get this matrix work correctly in Three.js, and the component is never mirrored, resulting in the behaviour that can be seen in the picture.

So, I'm not sure what to do. I was able to get correct results by detecting the simpler case (only flipped, not rotated or scaled), then setting for example object.scale.x = object.scale.x * -1; in Three.js for such components. But no solution for items that are both flipped and otherwise rotated or scaled :(


Solution

  • Use my Transformation Inspector to visualize the SketchUp matrix in a 4x4 grid: http://extensions.sketchup.com/en/content/transformation-inspector

    Using that I can tell which matrix entry changed as I flipped along any axis: * **Flip along X:** Index #1 * **Flip along Y:** Index #5 * **Flip along Z:** Index #10

    Martin Rinehart has written a breakdown of the transformation in SketchUp: http://www.martinrinehart.com/models/tutorial/tutorial_t.html


    Find flipped axis with orientation:

    module TransformationHelper
    
      def flipped_x?
        dot_x, dot_y, dot_z = axes_dot_products()
        dot_x < 0 && flipped?(dot_x, dot_y, dot_z)
      end
    
      def flipped_y?
        dot_x, dot_y, dot_z = axes_dot_products()
        dot_y < 0 && flipped?(dot_x, dot_y, dot_z)
      end
    
      def flipped_z?
        dot_x, dot_y, dot_z = axes_dot_products()
        dot_z < 0 && flipped?(dot_x, dot_y, dot_z)
      end
    
      private
    
      def axes_dot_products
        [
          xaxis.dot(X_AXIS),
          yaxis.dot(Y_AXIS),
          zaxis.dot(Z_AXIS)
        ]
      end
    
      def flipped?(dot_x, dot_y, dot_z)
        dot_x * dot_y * dot_z < 0
      end
    
    end
    
    
    module Example
    
      def self.inspect_flipped
        tr = Sketchup.active_model.selection[0].transformation
        tr.extend(TransformationHelper)
    
        puts "X Flipped: #{tr.flipped_x?.inspect}"
        puts "Y Flipped: #{tr.flipped_y?.inspect}"
        puts "Z Flipped: #{tr.flipped_z?.inspect}"
      end
    
    end