SketchUp Receive: Huge performance improvements with just two lines of code!

TLDR; I can reduce a large receive operation from hours to seconds by simply modifying a couple lines in: “./speckle-connector/src/speckle_objects/geometry/mesh.rb”

replace:

entities.add_faces_from_mesh(native_mesh, smooth_flags, material, material)
added_faces = entities.grep(Sketchup::Face).last(native_mesh.polygons.length)

with:

mesh_group = entities.add_group
mesh_group.entities.fill_from_mesh(native_mesh, true, smooth_flags, material, material)
added_faces = mesh_group.entities.grep(Sketchup::Face)

The reason this helps:

  1. speckle should always be putting new meshes in separate groups because otherwise it’s going to be killing itself trying to merge/combine faces with faces added in previous steps.
  2. using “fill_from_mesh” is far more performant than “add_faces_from_mesh”.

There is a little more cleanup needed for production:

  1. Now that we group geometry, we should probably apply layers and attributes to the group and not the faces.
  2. Another benefit of using groups is we can do the CleanUp right after creating the entities. I recommend adding in erase_lonely_edges after merge_coplanar_faces.
  3. While we’re taking about how meshes are converted, I disagree with the smoothing flags setting; we should default to “HIDE_BASED_ON_INDEX” (1) in almost all conditions. AUTO_SOFTEN would be a rare exception.

Let me know if or where I can help with this. I can provide my modified scripts if needed.
You can get my mesh script here: mesh.rb

3 Likes

Hey @miketalbott ,

Welcome to the community! Feel free to Introduce yourself :person_gesturing_ok: to the community if you want to! :grinning:

I loved the title of this thread! @oguzhankoral will take a look at this. If they come with the benefits you mentioned, they can definitely be merged.

2 Likes

Hi Bilal,

It’s long overdue for me to get involved. I’ve been a speckle fan/user for over two years.

I’m an architect turned software developer turned computational designer and 10 years ago I was building ruby scripts for SketchUp fulltime. I’m a little rusty now but really wanted the SketchUp connector to be more usable for the scale and complexity of projects that I work on.

For my tests, I’ve been using the following model that is a parametric model from grasshopper, not too complex but enough to freeze up the SketchUp connector:
Utah Housing Facade Model

I just re-ran the receive with the current unmodified connector and got:

==== Converting to Native executed in 4250.207 sec ====

(1 hour and 10 minutes)

and on my modified branch:

==== Converting to Native executed in 36.163 sec ====

(that’s a 117x improvement!)

and if I turn off merge coplanar faces:

==== Converting to Native executed in 11.778 sec ====

And I think it will be even better on big Revit files.

I provided the link to the “mesh.rb” in the first post. but here’s the cleanup script with erase lonely edges added in:
clean_up.rb

And you need to remove the cleanup from receive_objects.rb:
receive_objects.rb

There is still room for improvement. The one case where you wouldn’t want every mesh in a group is for objects made up of sub-meshes that have different materials on different faces. I don’t know enough about the speckle object model but maybe we can detect and handle that condition. Also, it would be nice to add in auto-smoothing based on angle between faces. And finally, the “fill_from_mesh” has a “weld_vertices” option that I don’t understand yet.

Hope this is all helpful.

5 Likes

Hey @miketalbott,

Thanks for your input, the results are quite promising! :rocket:

Putting every generated mesh into its group eliminates geometrical checks for the application to find face-edge-planarity relationships, and bypass an exponential check when we keep adding more meshes to the document. This is a wise move in some cases because it might have massive performance improvement as you pointed out.

On the other hand, since every mesh lies in its group, it will become a bit cumbersome to modify objects if we want to. AFAIK -smoothing the faces will become unlikely since the edges are in different scopes (groups). These edges don’t have any relationship (because bypassed) even if they overlap with neighbor’s face edge.

But in some cases, users might not be interested at all in modifying faces or smoothing their edges. What I would suggest here is to have them both with another option.

We also have a ticket to partly replace the usage of meshes in SketchUp connector with Face and Polygon conversions on receive to have more native conversions instead of using meshes heavily to create Sketchup::Face objects.

More input is welcome, and this topic is worth discussing :raised_hands:

Hi @oguzhankoral,

Definitely worth the discussion.

If there are valid scenarios for a “sticky” import, then I’d say an option would be a good way to go. I might suggest you default to grouped because it’s faster and less destructive. ie a user can easily explode a group if needed but you can’t unexplode it.

Your sphere test case is interesting to me because I’m not aware of the scenario where we would be sending a sphere with each quad separated into its own mesh. I see it two ways: 1. Either the sphere represents not well formed data, and it should have been joined/combined by the user or the speckle send. Or 2. It is intensional and the user wants separate quads and we should return those separate as intended.

Either way, we shouldn’t be modifying the data as it was sent, if it’s separate keep it separate. If it’s smoothed and combined keep it that way. When you do the “sticky” import you are modifying the data.

Regarding the face, edge, polygon approach. Seems like a good idea when the data would support it. Mesh still might be the best choice in some scenarios. Just remember to use the SketchUp EntityBuilder class to construct the geometry as using the .add_ methods will be super slow.

2 Likes

Hey @miketalbott,

I just wanted to update you that we are still reviewing the implications of your proposal. We haven’t forgotten about you. After conducting some benchmarking, we identified a bottleneck in our current implementation related to multi-meshes (which your model is full of, see image for an example). When comparing the two methods with single mesh objects, they perform very similarly.

At the moment, we are investigating how your proposal would impact object tracking and updating behavior. We will either accept it as is or explore alternative solutions to address the multi-mesh issue.

Here’s a comparison of current implementation and your proposal. As you can see, they perform very similar when it comes to models from Revit, Tekla, Archicad etc.

1 Like

Hi Bilal,

Sorry I didn’t have notifications on, so I didn’t see the update. All good news, and thanks for looking into it.

You are correct that the model provided is a bunch of combined/joined meshes. This was done on the grasshopper side to improved performance in Rhino. That said, I believe (Maybe it was in an older speckle version) I was experiencing the same issue with over-merging elements even when objects were singular and separate in Rhino. And I remember having the same issue with Revit.

You all know best how to proceed so I trust you’ll figure it out. That said, I’ll just share as a developer, designer, and longtime user if SketchUp, it is never right to add geometry from separate speckle objects into the same entities collection. SketchUp is designed as a deeply nested hierarchy of groups and components that define singularity. If it’s an object in speckle, it should be a group or component in SketchUp. The alternate of over-merging not only is the cause of the huge performance issues, but also modifies the geometry and damages the structure of the data.

Thanks again, for looking into this. Let me know if there is anything I can do to help.

ps. Separate from the over-merge issue, is the cleanup step. If you haven’t already, take a look at the modification of the smoothing flag and the addition of erase lonely edges.

1 Like

Hi @miketalbott,

I am so glad for your investigation on this topic. We also consider the usability of the model when it is received especially from Revit. For example, adjacency on the faces in the same component is important when we receive walls, windows, etc. for the sake of editability of faces via push-pull and other tools without having another nesting.

We will probably consider your suggestion at some point for some workflows.

Feel free to feed us if you have more findings! :slight_smile:

Best

Hi @oguzhankoral,

Thanks for the quick reply. I understand and support the desire for usability, but I think I just come to the opposite conclusion of what is more usable.

For example, if I import a door family from Revit that is composed of a frame and a door panel element. In Sketchup I find it much more “usable” if they a divided into separate objects. that way if I need to edit the door to be open, I don’t have to worry about it being merged with the frame. Same goes with walls. After importing walls from Revit, I still want to be able to select and isolate wall elements individually, apply new tags(layers), or possibly further groupings similar walls. Alternatively, in a merged model, if walls go from floor to floor the walls from other levels would be glued together and that would stop my ability to select and move the faces on one floor without effecting faces on another floor. I think the reason I’m so adamant about this is that if I need the usability that you describe, I can just explode the objects that I’m interested in editing, but if they are already merged, I can’t go back to individual objects.

In short, I can see why you might consider a merged model more editable because of tools like push-pull, however I argue that its actually less editable because you are giving up the ability to isolate and manage objects individually.

Thanks again for your consideration.

Revit elements are already created with components individually and their hosted elements like windows and doors are also components in related host. So walls and floors don’t glue together. They glue enough with their context. You can still change tags and edit them in their context without messing up other walls, floors, or whatever Revit element you received.

SketchUp_zoR8D2yupA-ezgif.com-resize

In a short story, this is a product decision we made for usability.

Best