Copy face UV position

Good morning,

Using get_UVHelper and get_front_UVQ, it is possible to copy UVs.

However, if these UVs have been pasted on a side with different normals, the UVs will be incorrect.

Here is sample code to copy the UVs:

  mod = Sketchup.active_model
  sel = mod.selection
  sel.grep(Sketchup::Face) do |f| 
    @mat = f.material
	next unless @mat or @mat.texture
    uv_helper = f.get_UVHelper(true)
    ps = f.vertices[0,4].map(&:position)
    uvs = ps.map do |p|
      uvq = uv_helper.get_front_UVQ(p)
      uvq.x /= uvq.z
      uvq.y /= uvq.z
      uvq.z = 1
      uvq
    end
	@uv_copy = ps.zip(uvs).flatten!
  end

Secondly, we can paste the UVs with this example:

  mod = Sketchup.active_model
  sel = mod.selection
  sel.grep(Sketchup::Face) do |f| 
    f.material = @mat
    f.position_material(f.material, @uv_copy, true)
  end  

SketchUp_V4W9VTVuY2

BOX.skp (36.5 KB)

How to recalculate the UVs according to the normals of the face which must receive the texture?

Another track:
Manually if I use the eyedropper in the materials window, it is possible to copy materials and UVs to apply them to any face even with different normals.

Is it possible and legal to see the ruby code of this SketchUp tool?

Or

Can I use the methods of this tool to copy the UVs without using the tools manually?

Thank you in advance for your help

Native tools are not coded in Ruby. They are coded in C++, and the code is not open source.

2 Likes

Yes. Apply for a relevant job at Trimble… :grinning:

1 Like

If I understand correctly, UVs are calculated with C++ methods when using Sketchup’s eyedropper tool?

Are we limited in the development of tools compared to Trimble?

:joy:

I don’t know as I’m not a UV & texture expert myself. But the subject of UVs has been discussed much in this category. I’d say do a search.

I’ve already done a search and no topic answers my question.
It seems to me that the access to the parmeters of the normals with the method get_front_UVQ is missing.

uvq = uv_helper.get_front_UVQ(vert.position, f.normal)

For cubes and normals I found the solution.

Copy the UVs of the selected face:

  mod = Sketchup.active_model
  sel = mod.selection
  sel.grep(Sketchup::Face) do |f| 
    @mat = f.material
	next unless @mat or @mat.texture
    uv_helper = f.get_UVHelper(true)
    ps = f.vertices[0,4].map(&:position)
    @uvs = ps.map do |p|
      uvq = uv_helper.get_front_UVQ(p)
      uvq.x /= uvq.z
      uvq.y /= uvq.z
      uvq.z = 1
      uvq
    end
  end

Paste the UVs on the selected face:

  mod = Sketchup.active_model
  sel = mod.selection
  sel.grep(Sketchup::Face) do |f|
    f.material = @mat  
    pts = f.vertices[0,4].map(&:position)
	uv_copy = pts.zip(@uvs).flatten!
    f.position_material(f.material, uv_copy, true)	
  end

However if the face of cube 2 is longer, the texture will be stretched.

When I think I have found a solution to a problem, there is always another one coming up. :thinking:

I managed to solve the problem by moving the 3D points according to the normals of the face where you have to paste the UVs.

This partially solves the problem but the code quickly becomes a gas plant.

UVs in SketchUp are very special and the API provides too few methods to manipulate them.

I’d recommend not sampling from the face vertices to copy the UVs. Because you might have faces with colinear edge or even triangles.

Instead, sample four point on the plane of the face, they don’t have to match any of the vertices. Then use that as a reference to apply the same mapping to another face. face.position_material accept 3D world coordinates and UVs that all related to the plane of the face.

1 Like