Rotating Texture/Material of a Face

I am now fairly familiar with using the position_material method to position a material on a face.

The basic example is here in the Ruby API: Class: Sketchup::Face — SketchUp Ruby API Documentation

So far I’ve only needed to translate in the X or Z direction (or both) however now I am thinking about trying to rotate the texture image some arbitrary angle. Has anyone ever tried that before or know how to use this method to do that? or possibly a different method? At this point I’m not sure it is even possible with the API but I thought I might ask.

You can always get the image_rep of the texture and manipulate the data.
Then set it back to the face’s material.

I’d think the web would have some code already posted for rotating image pixel data.

… then again the pixel data UV coordinates could have a rotational transformation applied and then the coordinates truncated. (There might be some blurring.)

You’d need to use the 3D Geom::Transformation as the Transformation2d has it’s origin at the top left and Y coordinates going downward.

Some years ago I wrote a toolset that lets you manipulate textures in several ways.
It’s available at the SketchUcation PluginStore - TIG-TextureTools
See how it can rotate a texture to any desired angle…
You can borrow its methods as you see fit…

2 Likes

I might take a look at that code then and see if I can even understand what you are doing.

Did you figure it out? It’s all about the relationship between the world coordinates and the UV coordinates you pass it.

1 Like

So far I haven’t come up with a simple solution, other than to simply create the body at a different orientation first then rotate it into place.

One thing that might help is to study the Position Texture tool - observe how the texture pins are placed on the surface of the face.

position_material


model = Sketchup.active_model
model.active_entities.clear!

texture_path = Sketchup.find_support_file('/Materials/Brick, Cladding and Siding/Brick Colored Blue.skm')
material = model.materials.load(texture_path)

points = [ # World space coordinates
  Geom::Point3d.new(  0,   0, 0),
  Geom::Point3d.new(1.m,   0, 0),
  Geom::Point3d.new(1.m, 1.m, 0),
  Geom::Point3d.new(  0, 1.m, 0),
]
face = model.active_entities.add_face(points)
face.reverse! unless face.normal.samedirection?(Z_AXIS)
# Position texture to fit face:
uvs = [ # UV coordinates
  Geom::Point3d.new(0, 0),
  Geom::Point3d.new(1, 0),
  Geom::Point3d.new(1, 1),
  Geom::Point3d.new(0, 1),
]

mapping = [
  points[0], uvs[0],
  points[1], uvs[1],
  points[2], uvs[2],
  points[3], uvs[3],
]
# This could also be done via .zip - but the above illustrates clearer the order
# of the data.
# points.zip(uvs).flatten
face.position_material(material, mapping, true)

image


# Position tile across the face 2 times horizontally and 4 times vertically:
uvs = [ # UV coordinates
  Geom::Point3d.new(0, 0),
  Geom::Point3d.new(2, 0),
  Geom::Point3d.new(2, 4),
  Geom::Point3d.new(0, 4),
]
mapping = points.zip(uvs).flatten
face.position_material(material, mapping, true)

2022-08-23_12h34_20



# Position tile across the face 2 times horizontally and 4 times vertically.
# and rotate by 45 degrees:
uvs = [ # UV coordinates
  Geom::Point3d.new(0, 0),
  Geom::Point3d.new(2, 0),
  Geom::Point3d.new(2, 4),
  Geom::Point3d.new(0, 4),
]

# Instead of pinning the UVs to the vertices of the face, we pin them to points
# on the plane of the face. Similar to what the Position Texture tool does:
rotation_origin = Geom::Point3d.new(0, 0)
tr = Geom::Transformation.rotation(rotation_origin, face.normal, 45.degrees)
face_points = points.map { |uv| uv.transform(tr) }

mapping = face_points.zip(uvs).flatten
face.position_material(material, mapping, true)

image


In the above illustration the red square are the points on the face of the plane, they are rotated 45 degrees of the original vertices. Because the UV values remain the same you get the desired rotation. (Did that make sense?)

2 Likes