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

    [Code] position of texture pins

    Scheduled Pinned Locked Moved Developers' Forum
    16 Posts 3 Posters 3.8k Views 3 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.
    • thomthomT Offline
      thomthom
      last edited by

      That's very interesting.

      btw...

      @aerilius said:

      Note: SketchUp dynamically places the texture pins where the user clicks, thus they can be translated about u/v +/-1

      From what I see, that is only true if the texture has not been positioned. If the use has positioned the texture, then the pins appear where they where last placed.

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

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

        Btw, where was that C code?

        Could be interesting to have that in a C Extension...

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

        1 Reply Last reply Reply Quote 0
        • A Offline
          Aerilius
          last edited by

          @unknownuser said:

          Btw, where was that C code?

          It's available as a pdf at the bottom of that page: http://www.cs.cmu.edu/~ph/

          @thomthom said:

          If the use has positioned the texture, then the pins appear where they where last placed.
          I tested it again. It's true, when the user has changed the pins from their default positioning, they stick fixed. But still the uvq sometimes don't match the pins (once I got [-1,0,1] for the red pin).

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

            You sure you don't need the fourth in order to get the skew and distortion?

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

            1 Reply Last reply Reply Quote 0
            • A Offline
              Aerilius
              last edited by

              I suddenly got a bit more understanding of what we actually do here... 💭

              So this whole code is actually much simpler. SketchUp gives us a Q coordinate (that we didn't use so far). In fact we don't need a 4×4 transformation matrix (rectangle ←→ quadrilateral), but a 3×3 matrix is enough. That means we can get rid of very expansive calculations and even use SketchUp's native Geom::Transformation (which is 3×3). All the details in the code below and in this thread:

              
              module AE;end # (replace this by your author/company namespace!)
              
              
              class AE;;UVHelper
              
              
              # This initializes our UVHelper. It calculates the transformation matrix between
              # model space (XYZ) and texture space (UVQ). We also create an instance of SketchUp;;UVHelper
              # for faster conversion from model to texture space (but it can't do the reverse).
              #
              # @param [Sketchup;;Face] face The face on which we want to convert coordinates.
              # @param [Sketchup;;Face] on_front True if you want the texture coordinates for the front face, false if not. Defaults to true.
              # @param [Sketchup;;Face] on_back True if you want the texture coordinates for the back face, false if not. Defaults to true.
              # @param [Sketchup;;TextureWriter] tw A TextureWriter object.
              #
              # @return [AE;;UVHelper]
              def initialize(face, on_front=true, on_back=true, tw=Sketchup.create_texture_writer)
                @face = face
                ### Get the native UVHelper for for conversion from XYZ to UVQ.
                @uvh = face.get_UVHelper(on_front, on_back)
                ### Get a transformation matrix for UVQ to XYZ.
                # Since every quadrilateral can be understood as a perspectivic projection of a 3d rectangle,
                # we do not need to find a transformation [square <-> quadrilateral] (4x4 matrix) but only an
                # affine transformation in 3d space (3x3 matrix, can use Geom;;Transformation!).
                #
                # Get 3 points of a square of size 1*1. It spans a local 2d space of the face's plane (XY).
                p0 = face.vertices[0].position
                p1 = face.vertices[1].position
                vec01 = p0.vector_to(p1).normalize
                p1 = p0 + vec01
                vec12 = (vec01 * face.normal)
                p2 = p1 + vec12
                # For one side of the face
                get_transformation = Proc.new{|side|
                  # Get their uvq
                  uvq = [p0,p1,p2].collect{|p|
                    get_UVQ(p, side)
                  }
                  # Get the transformation of the between model space (XYZ) and the face (XY).
                  txyz = Geom;;Transformation.axes(p0, vec01, vec12, face.normal) # * scaling(1)
                  # Get the transformation of the between the face (XY) and UVQ.
                  # Since we have input a square, it corresponds to a rectangle in UVQ space
                  # and we may use an axes transformation (that's why 3 points are enough).
                  vecuvq01 = uvq[0].vector_to(uvq[1])
                  vecuvq12 = uvq[1].vector_to(uvq[2])
                  vecuvqn = vecuvq01*vecuvq12
                  tuvq = Geom;;Transformation.axes(uvq[0], vecuvq01, vecuvq12, vecuvq01*vecuvq12) *
                         Geom;;Transformation.scaling(ORIGIN, vecuvq01.length, vecuvq12.length, 1)
                  # The combined transformation from texture space to model space.
                  t = txyz * tuvq.inverse
                  # The projection plane (necessary if confronted with UV and Q=1)
                  plane = [uvq[0], vecuvqn]
                  [t, plane]
                }
                @t_front_uvq2xyz = @t_back_uvq2xyz = Geom;;Transformation.new()
                @plane_front = @plane_back = [ORIGIN, Z_AXIS]
                @t_front_uvq2xyz, @plane_front = get_transformation.call(true) if on_front
                @t_back_uvq2xyz, @plane_back = get_transformation.call(false) if on_back
              end
              
              
              # Wrapper method for Sketchup;;UVHelper (more useful with front/back Boolean)
              #
              # @param [Geom;;Point3d, Array] xyz A point in model space.
              # @param [Boolean] on_front Whether you want the texture coordinates for the front face or the back face.
              #
              # @return [Geom;;Point3d] Point The corresponding point in texture space (UVQ).
              def get_UVQ(xyz, on_front=true)
                return (on_front)? @uvh.get_front_UVQ(xyz) ; @uvh.get_back_UVQ(xyz)
              end
              
              
              # Get the coordinates in model space from given coordinates in texture space.
              #
              # @param [Geom;;Point3d, Array] uvq A point in texture space (UV or UVQ).
              # @param [Boolean] on_front Whether you want the model coordinates for the front face or the back face.
              #
              # @return [Geom;;Point3d] Point The corresponding point in model space (XYZ).
              def get_XYZ(uvq, on_front=true)
                # If the input is a 2d texture coordinate (UV with Q==1) it may not lay on the 
                # projection plane and our transformation won't work with a 3x3 matrix. 
                # Thus find the correct Q value on the projection plane.
                vec_q = [uvq[0]*2, uvq[1]*2, (uvq[2]||1)*2]
                uvq = Geom.intersect_line_plane([uvq, vec_q], (on_front)? @plane_front ; @plane_back)
                return uvq.transform((on_front)? @t_front_uvq2xyz ; @t_back_uvq2xyz)
              end
              
              
              # Get the coordinates in model space from given coordinates in texture space.
              #
              # @param [Geom;;Point3d, Array] Point A point in texture space (UV or UVQ).
              # @param [Boolean] on_front Whether you want the texture pins for the front face or the back face.
              #
              # @return [Geom;;Point3d] Point The corresponding point in model space (XYZ).
              def get_texture_pins(on_front=true)
                pins = [ get_XYZ([0,0,1], on_front),
                         get_XYZ([1,0,1], on_front),
                         get_XYZ([1,1,1], on_front),
                         get_XYZ([0,1,1], on_front),
                       ]
                # example; show pins with construction points
                Sketchup.active_model.start_operation "get texture pins"
                pins.each{|p| Sketchup.active_model.entities.add_cpoint(p)}
                Sketchup.active_model.commit_operation
                return pins
              end #def get_texture_pins
              
              
              end
              
              
              1 Reply Last reply Reply Quote 0
              • thomthomT Offline
                thomthom
                last edited by

                SketchUp's Texture Pins

                get_texture_pins


                Sample Model

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

                1 Reply Last reply Reply Quote 0
                • A Offline
                  Aerilius
                  last edited by

                  Hmm, about skewing I'm not sure, but I see it works without. I think for 4 points there are 8 degrees of freedom (? 4*[U,V] if Q=1 is constant). With varying Q it works also with 3 points 3*[U,V,Q]=9 (?).

                  Edit: I haven't experienced before what your image/skp shows. One construction point is across the inversion horizont of the texture (where it grows after shrinking). I have to see what can be done...

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

                    When you position a texture SketchUp let you provide the following Point3d and UV pairs:

                    1x : Position
                    2x : Position and Scale Uniform
                    3x : Position and Skew
                    4x : Perspective Distortion

                    So for the reverse one does need all four points as well - without it you lose the data.

                    Many render engines struggle with SketchUp's distorted textures - mainly because they read the UV data from the vertices of the face. That fails when a triangle has a distorted texture applies. And it is why SU's UV mapping methods accepts 3D points that are on the plane of the face instead of using the vertices.

                    Several render engines works around it by triangulating the mesh and reading the texture for each triangle - it doesn't give correct UV map though - as they only read 3 point they only get a skewed map. For some geometry you hardly notice it, but other times it is very visible.

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

                    1 Reply Last reply Reply Quote 0
                    • A Offline
                      Aerilius
                      last edited by

                      But since a texture is 2d, it has 8 degrees of freedom on the plane. You need four points with 2d coordinates (UV) to sufficiently define texture position/skew/distortion. With 3d texture coordinates, we have already enough data in three 3d points (UVQ) (the third Q coordinate contains the missing info).

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

                        @aerilius said:

                        With 3d texture coordinates, we have already enough data in three 3d points (UVQ) (the third Q coordinate contains the missing info).

                        I never worked out how to use that value... I tried asking the SketchUppers - but there feedback hasn't really provided anything...

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

                        1 Reply Last reply Reply Quote 0
                        • renderizaR Offline
                          renderiza
                          last edited by

                          I am so frustrated that I don’t possess the knowledge yet to understand most of this discussion. Correct me if I am wrong but could this code make animating textures possible? If so I am very interested in trying to figure how I can do this myself.

                          [url=https://www.sketchupcode.com/:z3kqsidd]My Extensions ...[/url:z3kqsidd]

                          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