AI generated subdivison plugin
-
In the past view weeks, I worked with ai to make a subdivision and mesh reduction plugin. I started off with this old plugin (https://github.com/NB70/sketchup-loop-subdivision), and got the ai to improve it, and then I got it to make a dynamic subdivision plugin, and a mesh reduction plugin. I don't really know ruby coding, so I can't say it will work, but it works for me. I will attach it here, hopefully someone finds it useful. I also am attaching a manual, generated by ai (obviously) from the code.
mesh tool manual.pdf
Mesh Tools.rbz -
Impressive result.
Tons of Ruby Console errors
#<TypeError: reference to deleted Face> C:/Users/rclub/AppData/Roaming/SketchUp/SketchUp 2026/SketchUp/Plugins/mesh_tools/Dynamic_Subdivide.rb:190:in `edges' C:/Users/rclub/AppData/Roaming/SketchUp/SketchUp 2026/SketchUp/Plugins/mesh_tools/Dynamic_Subdivide.rb:190:in `block in dyn_loop_getvertices' C:/Users/rclub/AppData/Roaming/SketchUp/SketchUp 2026/SketchUp/Plugins/mesh_tools/Dynamic_Subdivide.rb:188:in `each' C:/Users/rclub/AppData/Roaming/SketchUp/SketchUp 2026/SketchUp/Plugins/mesh_tools/Dynamic_Subdivide.rb:188:in `dyn_loop_getvertices' C:/Users/rclub/AppData/Roaming/SketchUp/SketchUp 2026/SketchUp/Plugins/mesh_tools/Dynamic_Subdivide.rb:345:in `block in dyn_loop_subdivide' C:/Users/rclub/AppData/Roaming/SketchUp/SketchUp 2026/SketchUp/Plugins/mesh_tools/Dynamic_Subdivide.rb:343:in `times' C:/Users/rclub/AppData/Roaming/SketchUp/SketchUp 2026/SketchUp/Plugins/mesh_tools/Dynamic_Subdivide.rb:343:in `dyn_loop_subdivide' C:/Users/rclub/AppData/Roaming/SketchUp/SketchUp 2026/SketchUp/Plugins/mesh_tools/Dynamic_Subdivide.rb:555:in `loop_dynamic_build_result' C:/Users/rclub/AppData/Roaming/SketchUp/SketchUp 2026/SketchUp/Plugins/mesh_tools/Dynamic_Subdivide.rb:581:in `block in loop_dynamic_schedule_rebuild' -
Works well.
But I have a few observations from a non-AI view-point...
The Dynamic_Subdivide.rb file uses several
$xxx...global variables - these are frowned upon because they can pollute all other Ruby files [and are not acceptable in extensions submitted for review in the EWH].
It's a simple fix - replace them all with@xxx...variables that then work across methods in the same modules, but not 'globally' in unconnected scripts.That Dynamic_Subdivide.rb file also has potential trip-hazards as Rich pointed out -
e.g. in line#190 it's possible for it to reference an edge of a face that is no longer valid, as specified in an earlier line, so it falls over.
This not valid issue occurs when your operation does something to geometry that affects a previously made collection of things -
e.g. adding a new face [or edge] overwrites an existing face [or edge] so a reference to it is no longer valid.
Again it's a simple fix - add a 'skip' trap near the start of the block -
e.g. like this
faces.each do |face| next unless face.valid? ... end
which skips any invalid faces and so the errors are sidestepped.
You can do a 'find' in the code to add in similar traps like this for any non-valid face, edge, vertex etc.
Also note that the various blocks have an inconsistent format, swapping between
xxx.each { |e| ...xxx... }
to
xxx.each do |e| ...xxx... end
But editing either of them is possible with a little care.
Both forms are acceptable, but choosing to use just one for consistency is recommended... -
@TIG thank you very much for your tips, I will hopefully fix them soon.
-
here is the new version, hopefully it is fixed (I gave the feedback to ai, and asked it to fix it
.
mesh_tools_1.0.1.rbz -
I think you've trapped almost everything.
However in the self.loop_dynamic_purge_ghost_material method you look at ent and then manipulate its material if it's a face or a group or a component-instance.
But if those are no longer valid for some reason [I do suspect that could be an incredibly rare chance?] then it could throw an error and fall over.
A simple check at the start of the method's do-block that is searching through the model.entities e.g.
next unless ent.valid?
skips any invalid entIncidentally, without analyzing the whole code-set, firstly why not use model.active_entities which potentially reduces the list length, and secondly what about any faces within nested groups etc not inspected by this method that might still have that material ?
-
One further issue you should address before publishing this more widely - e.g. getting it 'signed' and in the EWH.
Its file naming does not follow the proper conventions.
An RBZ must contain just one .RB file that registers the extension and a folder of the exact same name.
Also the convention is to prepend the users 'name' at the start and even a sub-level if the modules do this.
So in your case there should be MendelAI_mesh_tools subfolder and a .RB file named MendelAI_mesh_tools.rb
You then edit the RB to load MendelAI_mesh_tools/loaderBecause previous users might also now have the older badly named file/folder installer and loading you need to do some tidying up.
Add some code to the start of the RB to check for the existence of mesh_tools_loader.rb and mesh_tools subfolder in the Plugins folder -
use File.exist?(str) or better still similar methods in the fileutilities [which you need to 'require'] which will make deleting the subfolder and its contents much easier. So if these files exist you should also add a UI.message_box() to ask the user to restart to sync everything - next time the rogue file/folder won't be found and the code is redundant, but is still needed in any future updates in case a user has skipped this change in 1.0.2... A manual restart is preferable to a forced quit etc as the user might not have saved some work before updating etc.
Advertisement