[Code] realign UVs, or: convert projective to affine

[Code] realign UVs, or: convert projective to affine

Postby Aerilius » Thu May 24, 2012 12:44 am

When we want to work with textured organic meshes (like me in my current project), we want that the texture flows continuously over the surface. However it can happen that they become misaligned by editing etc.

I wrote this method and surprisingly figured out that the resulting mesh not only has an affine distortion but is still always continuous/seamless – even if it resulted from a projective distortion. That's something I've wanted for long for cases that don't work for projected textures.

Of course the conversion is not lossless, the more subdivided the mesh is, the less noticeable is the difference.
Code: Select all
def realign_uvs(entities=Sketchup.active_model.selection.to_a)
  model = Sketchup.active_model
   if Sketchup.version.to_i >= 7
      model.start_operation("Repair misaligned UV coordinates", true)
      model.start_operation("Repair misaligned UV coordinates")
  @tw = Sketchup.create_texture_writer
  side = true # frontside
  hash = {} # vertex => [uvs]
  faces = entities.find_all{|e| e.is_a?(Sketchup::Face) && (mat = (side)? e.material : e.back_material) && mat.materialType>0}
  # 1) Let's collect all uvs at each vertex
    uv_helper = f.get_UVHelper(true, true, @tw)
      p = v.position
      uv = (side)? uv_helper.get_front_UVQ(p) : uv_helper.get_back_UVQ(p)
      uv.x /= uv.z; uv.y /= uv.z; uv.z = 1
      hash[v] = [] if !hash[v]
      hash[v] << uv
  # 2) Find the uv with the least aberration. Alternative: Calculate the average of the uvs at a vertex.
  hash.each{|v, array|
    #average_uv = array.inject(Geom::Point3d.new([0,0,0])){|sum, uv| sum+uv.to_a}.to_a.collect{|c| c/array.length.to_f}
    #hash[v] = average_uv
    best_uv = array.min{|uv_a,uv_b|
      dist_a = array.inject(0){|dist, uv| d = uv_a.distance(uv); [d,dist].min} # sum of distances from uv_a
      dist_b = array.inject(0){|dist, uv| d = uv_b.distance(uv); [d,dist].min} # sum of distances from uv_b
      dist_b <=> dist_a}
    hash[v] = best_uv
  # 3) Apply the uvs for each face
    pt_array = []
    vs = f.vertices[0..3]
      pt_array << v.position
      pt_array << hash[v]
    f.position_material(((side)? f.material : f.back_material), pt_array, side)
Last edited by Aerilius on Sat Dec 22, 2012 11:36 pm, edited 1 time in total.

PluginStore Author
PluginStore Author

Re: [Code] realign UVs, or: convert projective to affine

Postby thomthom » Thu May 24, 2012 8:47 am

Looks very interesting. Though, could you explain "projective to affine" in this context? I'd like to understand this.
Thomas Thomassen — SketchUp Monkey & Coding addict
List of my plugins and link to the CookieWare fund
User avatar
PluginStore Author
PluginStore Author

Re: [Code] realign UVs, or: convert projective to affine

Postby Aerilius » Thu May 24, 2012 9:48 am

Projective: like projected textures (all four texture pins modified) (this it what the TextureWriter makes unique when exporting)
Affine: skewed or scaled or stretched like a parallelogram, preserves parallel lines and equispaced points along lines.
(I find this document very helpful http://www.cs.cmu.edu/~ph/texfund/texfund.pdf p.13)

PluginStore Author
PluginStore Author

SketchUcation One-Liner Adverts

by Ad Machine » 5 minutes ago

Ad Machine 


Return to Developers' Forum

Who is online

Users browsing this forum: No registered users and 14 guests