Applying material to individual faces is very slow

I’m creating a simple solid shape, a cylinder with flattened hemispherical ends so it looks like a capsule. dummy|690x466

I created a simple material to apply to it (just color and alpha), but I’m finding it extremely slow to apply the material if I do something like:

  @shapes["tank"].entities.grep(Sketchup::Face).each{ |face|
    face.material = @materialToSet
    face.back_material = @materialToSet
  }

Runtime for material application alone is about 20 seconds and I wouldn’t consider the geometry overly complex, the cylindrical section has 72 sides. Is there something I can do to speed this up? In the UI one click selects the entire cylindrical surface and manual material application is a fraction of a second.

Alternatively I could apply the material to the entire group, but that’s generally frowned upon, even if it is exceptionally fast.

Two ideas:

If you enclose the code in an operation with the disable_ui flag set true, that may let it run much faster. Updating the view after each face is colored will greatly slow things down. Don’t forget to commit the operation at the end.

The grep method automatically takes a block argument. You don’t need .each. I don’t know that this will speed up the code much though.

4 Likes

You are correct, removing the .each didn’t do much. BUT, enclosing it in an operation with the UI disabled brought it down to 0.2 seconds, thank you so much!

1 Like

I forgot to mention that wrapping in an operation also puts a single item onto the undo stack instead of flooding it with one per face. That will not only make the code a bit faster, it will make it possible to change your mind without undoing hundreds of actions (and maybe exhausting the undo stack!).

3 Likes

That’s good to know, thanks again.

Why is applying to the overall group frowned upon?
It is convenient when you want the same alpha on both sides of the faces.

1 Like

Actually, it depends on what you are trying to do. There are cases in which painting the outside of a group is fine. Especially if the group represents something that is homogeneous in reality. Why paint all the faces red one by one if that’s what the whole group is anyway?

But there are also situations where it doesn’t work well. Obviously, you can’t represent an object with different materials on its faces if you paint the container. An example is a wooden board, in which the face, edge, and end grain needs to differ if you are after realism. You also can’t fiddle with the alignment of the material’s texture, you have to live with however SketchUp mapped it on all the faces. That can look odd where it wraps around corners. Finally, I think there are some renderers that won’t work right if you paint the group not the faces?

2 Likes

One interesting thing, that I hadn’t realized before trying just now, applying a transparent material to one side of a face does also apply it to the other side. Unless the other side already has a material applied.

1 Like

Are you sure about that? If I start with no materials applied and I apply the transparent material to one side and do a section cut, the interior still has the default material.

The homogenous painting is a good point. In terms of being frowned upon, I’m just recalling the ‘10 Things I Hate About Your Sketchup Model’ from Basecamp and painting the entire group was one of those.

See this screen recording.

I can only duplicate that functionality when using the UI, the API seems to require explicit front and back face material application.

Ha! I should look more carefully at which forum page I’m on.

That is not what I’m seeing from the Ruby console. Given a grouped entity (a solid cube with no nested groups or components):

group.material= "Material1"

I gave that material a brown color with an alpha of 0.25, andl I’m seeing right through it, indicating both sides have been applied. I think I remember that if faces already have a material, they do not receive the material for the overall group or component. (Another reason to frown upon group level material if the plugin needs control of all face materials.)

Sketchup::Group has no back_material method, so presumably when the renderer works its way up the model tree looking for materials applied to the containers, if it finds a group.material, then that gets rendered on all surfaces (front or reverse) that don’t have their own explicit material assigned.

1 Like

I’ll state it more explicitly. If I start with no materials applied to any face and I apply the transparent material to the front face using the API and do a section cut, the back face still has the default material. I’m talking faces, not the group material.

You are correct about the group material application not pushing down on the faces, that was the takeaway from the ‘10 Things I Hate About Your Sketchup Model’ that I came back to elaborate on. It’s especially troublesome if there are nested groups with materials applied on the groups because you get behavior you wouldn’t expect, like the lower group materials having visibility precedence over the outer most group. It can get pretty messy if one isn’t careful.