We found that the Fix Model errors are a bug in the validation itself. The UV mapping matrix created by your example is valid in both cases. If Fix Model is run then it will reset the coordinates for that face.
I am able to reproduce the same issue in the Ruby API:
model = Sketchup.active_model
face = model.selection.first
p face.outer_loop.vertices.map(&:position)
uvs = [
Geom::Point3d.new(0.5, 0.0, 0),
Geom::Point3d.new(1.0, 0.0, 0),
Geom::Point3d.new(1.0, 1.0, 0),
Geom::Point3d.new(0.5, 0.5, 0),
]
points = [
Geom::Point3d.new( 57.5, 0.0, 0),
Geom::Point3d.new(115.0, 0.0, 0),
Geom::Point3d.new(115.0, 25.0, 0),
Geom::Point3d.new( 57.5, 25.0, 0),
]
mapping = [
points[0],
uvs[0],
points[1],
uvs[1],
points[2],
uvs[2],
points[3],
uvs[3],
]
face.position_material(face.material, mapping, true)
I also found that just a slight noise in the UV data would avoid the validation error:
model = Sketchup.active_model
face = model.selection.first
p face.outer_loop.vertices.map(&:position)
uvs = [
Geom::Point3d.new(0.5, 0.0, 0),
Geom::Point3d.new(1.0, 0.0, 0),
Geom::Point3d.new(1.0, 0.9999, 0),
Geom::Point3d.new(0.5, 0.5, 0),
]
points = [
Geom::Point3d.new( 57.5, 0.0, 0),
Geom::Point3d.new(115.0, 0.0, 0),
Geom::Point3d.new(115.0, 25.0, 0),
Geom::Point3d.new( 57.5, 25.0, 0),
]
mapping = [
points[0],
uvs[0],
points[1],
uvs[1],
points[2],
uvs[2],
points[3],
uvs[3],
]
face.position_material(face.material, mapping, true)
However, if you are looking to produce this:
Then you won’t be affected by the validation error as that only happen with perspective UV mapping and in very particular edge case like in the right face of this test model.
These UV coordinates will produce the result as the above screenshot shows, and will not trigger any validation errors:
SUPoint2D uv_coords[4] = { { 0, 0 }, { 0.5, 0 }, { 0.5, 1.0 }, { 0, 1 } };
// ...
SUPoint2D uv_coords1[4] = { { 0.5, 0 }, { 1, 0 }, { 1, 1 }, { 0.5, 1.0 } };