A question about SUMaterialPositionInput

I get the correct SUMaterialPositionInput, but the model is wrong.
I copy faces from src.skp to dest.skp.
image
image

src.skp (1.2 MB)
dest.skp (1.8 MB)

Critical code of c++


#define SU(api_function_call) {\
  SUResult su_api_result = api_function_call;\
  assert(SU_ERROR_NONE == su_api_result);\
}\

SUResult AddFaceMaterial(SUFaceRef face,bool front,SUMaterialRef material_front_set,
 SUGeometryInputRef geom_input, size_t added_face_index, SUPoint3D pt) {
     
    SUMaterialPositionInput mat_pos_input_front;
    mat_pos_input_front.num_uv_coords = 4;
    mat_pos_input_front.material = material_front_set;

    // get points of mat_pos_input_front and uv_coords of mat_pos_input_front
    res = SUFaceGetUVTileAt(face, &pt, true, &(mat_pos_input_front.points[0]), &(mat_pos_input_front.uv_coords[0]));

    if (res == SU_ERROR_NONE) {
        // debug output
        printf("SUMaterialPositionInput Front %d\n", added_face_index);
        for (int i = 0; i < mat_pos_input_front.num_uv_coords; i++) {
            printf("World: Point3d(%lf, %lf, %lf)", mat_pos_input_front.points[i].x, mat_pos_input_front.points[i].y, mat_pos_input_front.points[i].z);
            printf(" - UV: Point3d(%lf, %lf, 0)\n", mat_pos_input_front.uv_coords[i].x, mat_pos_input_front.uv_coords[i].y);
        }
        // set material
        SU(SUGeometryInputFaceSetFrontMaterialByPosition(geom_input, added_face_index, &mat_pos_input_front));
    }
}

Critical code of ruby

Sketchup.active_model.selection.grep(Sketchup::Face).each do |face|
  puts "SUMaterialPositionInput Front"
  reference = face.vertices.first.position
  mapping = face.uv_tile_at(reference, true)
  mapping.each_slice(2) { |position, uv|
    puts "World: #{position.inspect} - UV: #{uv.inspect}"
  }
end

get info from src.skp by ruby

SUMaterialPositionInput Front
World: Point3d(3.72908, 393.77, 0) - UV: Point3d(-8, 0, 0)
World: Point3d(2.22821, 344.581, 0) - UV: Point3d(-7, 0, 0)
World: Point3d(2.22821, 344.581, 0) - UV: Point3d(-7, 0, 0)
World: Point3d(3.72908, 393.77, 0) - UV: Point3d(-8, 0, 0)

debug output by c

SUMaterialPositionInput Front 0
World: Point3d(3.729075, 393.770225, 0.000000) - UV: Point3d(-8.000000, 0.000000, 0)
World: Point3d(2.228215, 344.580518, 0.000000) - UV: Point3d(-7.000000, 0.000000, 0)
World: Point3d(2.228215, 344.580518, 0.000000) - UV: Point3d(-7.000000, 0.000000, 0)
World: Point3d(3.729075, 393.770225, 0.000000) - UV: Point3d(-8.000000, 0.000000, 0)

get info from dest.skp by ruby

SUMaterialPositionInput Front
World: Point3d(2.5793, 356.087, 0) - UV: Point3d(-356, 0, 0)
World: Point3d(2.5488, 355.087, 0) - UV: Point3d(-355, 0, 0)
World: Point3d(2.5488, 355.087, 0) - UV: Point3d(-355, 0, 0)
World: Point3d(2.5793, 356.087, 0) - UV: Point3d(-356, 0, 0)

hm… that’s strange. Notice that the World points and UV points returned only have two unique values, instead of four.

That tile isn’t a valid set of mapping points.

My own test:

model = Sketchup.active_model
face = model.selection.first

uv_mapping = face.uv_tile_at(face.vertices.first.position, true)
uv_mapping.each_slice(2) { |pair| p pair }
p face.get_texture_projection(true)
p face.position_material(face.material, uv_mapping, true, face.get_texture_projection(true))
nil
=> [Point3d(3.72908, 393.77, 0), Point3d(-8, 0, 0)]
[Point3d(2.22821, 344.581, 0), Point3d(-7, 0, 0)]
[Point3d(2.22821, 344.581, 0), Point3d(-7, 0, 0)]
[Point3d(3.72908, 393.77, 0), Point3d(-8, 0, 0)]
nil
Error: #<ArgumentError: Could not compute valid matrix from points>
<main>:6:in `position_material'
<main>:6:in `<main>'
SketchUp:in `eval'
nil

Can you log this as a bug please? Issues · SketchUp/api-issue-tracker · GitHub

ok.
The face is one of the curved surfaces.
Is there any way to deal with this problem temporarily?
[SUMaterialInput] (SketchUp C API: SUMaterialInput Struct Reference) is ok ?

error.skp (1.5 MB)

image

I try fix it, when I don’t think about projection.

face = Sketchup.active_model.selection[0]
uv_mapping = face.uv_tile_at(face.vertices.first.position, true)
puts "before fix"
puts uv_mapping
if (uv_mapping[1] - uv_mapping[7]).length == 0 && (uv_mapping[3] - uv_mapping[5]).length == 0
  uv_mapping[3] = uv_mapping[1].offset(X_AXIS, 1)
  uv_mapping[5] = uv_mapping[3].offset(Y_AXIS, 1)
  uv_mapping[7] = uv_mapping[7].offset(X_AXIS, -1)

  vec1 = uv_mapping[2] - uv_mapping[0]
  vec2 = vec1 * face.normal
  uv_mapping[4] = uv_mapping[2].offset(vec2, face.material.texture.height)
  uv_mapping[6] = uv_mapping[4].offset(vec1, -face.material.texture.width)
end

When material in the group, I also find a question.
I can not get the UV mapping of the front face.

test_src.skp (1.9 MB)
test_dest.skp (7.2 MB)

output.txt|Debug Output (11.9 KB)

The front face

The back face


When the material is inherited from a parent group/component then SUFaceGetUVTileAt won’t work. SUFaceGetUVTileAt only works when the face itself has a material applied.

When a face inherit a parent material it’s receiving automatic UVs. In that case you’d need SUUVHelperRef (SketchUp C API: SUUVHelperRef Struct Reference)
But, if you are trying to duplicate geometry, then all you’d need to be doing is to apply the parent material to the copied parent.

Ok,I will check my code.

How should use the SUUVHelperRef, when the material in the group?

I only find SUDrawingElementSetMaterial.

You must typecast the SUGroupRef to a SUDrawingElementRef using SUGroupToDrawingElement, then set the material.

Yes, I know. But I can not understand this.

I already set the material on the group but didn’t get the effect I wanted.

Can you elaborate on this? What did you expect and what do you observe happening?

I find the bug.
Because when I copy the material, the map size is wrong.
But I didn’t find a function to set the size of the material on C API.
I can only use the method (SUMaterialWriteToFile and SUModelLoadMaterial).

I logged this as an issue in the issue tracker: C API missing ability to set the material size · Issue #783 · SketchUp/api-issue-tracker · GitHub

1 Like