IntersectAsync-Based Part Bevel Plugin

Plugin:
https://create.roblox.com/store/asset/77892245690267/CSG-Part-Bevel

Code (Lite Version):
BevelConversionLite.lua (8.6 KB)

(To install the code file, move it into the local plugins folder. Top studio bar, Plugins > Plugins Folder, then re-open studio. Select parts or models and click the Bevel Selected Parts button)

Hello.
I have created a plugin for a very straightforward part bevel converter. I created this to replicate the bevels of pre-2013, while adding support for more primitives such as wedges and cylinders. I mostly use this because it’s extremely satisfying to use, though it would probably be more useful to others.

Method

Blocks: Creates 6 parts for intersecting, using orientated bounding boxes to calculate their dimensions, and then reducing the size of a specific axis.

Wedges: Similar to blocks, but with a bounding box calculation for the slope. I aimed to not alter the size of the resulting part, so the top and bottom edges of the slope aren’t bevelled.
Cylinders: Intersects against another cylinder of reduced length with squashed spheres unioned to each end.


Performance

(Please refer to future posts for updated information)

Strengths:
(Mostly about blocks and wedges. Comparisons are to a NegateOperation method I used which only worked on blocks. Only from what I’ve tested)

  • Requires far fewer operation parts.
  • Greatly reduces the number of triangles of the final IntersectOperation object (for blocks, NegateOperation method averaged 92-96 triangles, compared to this new method which averaged 44-48 triangles (unpredictable error cases exceeding this can occur).
  • Correctly displays surface normals via SmoothingAngle (most of the time).

Weaknesses:

  • The current cylinder method is very inefficient. SmoothingAngle isn’t set here to prevent ugly surface artifacts. Cone primitives (:folded_hands:) would be a definite solution, but alas. Also, the simplicity of the method results in small differences in bevel appearance across cylinder sizes.
  • There is a 1-3% case of unwanted surface artifacts. What’s more confusing is that it is incredibly random.
  • Converting high-part-count selections can take time. The Classic Happy Home model, containing 565 parts, took ~57 seconds.
  • Despite supporting undo, it is best utilised where you can quickly turn the union back into its original part shape.

Potential Updates
  • Support for stud/inlet surfaces by using texture normal maps, etc, once they’re released.
  • Cylinder bevels to use cones if they are ever added or meshparts once they are compatible with CSG. Consequently, include a toggle for alternative methods.
  • A bevel size slider. The default scale is based on the R6 torso mesh.
  • Implement a dummy/overlay part type for blocks with functionality, such as SpawnLocations and Seats.

That’s all. Uhh, here’s a crab?

9 Likes

Could you show me some before and after, as im curious.

Can you publish it as a roblox plugin and then put the creator store link here

1 Like

(This is the old method. Uses 20 NegateOperation parts):

This new method isn’t perfect. The error cases occur very randomly and frankly don’t make much sense. The plus is that sometimes they don’t occur at all.


(Error cases)

I just realised you probably meant this kind of comparison:

5 Likes

It’s now a published plugin. See top post.

2 Likes

1.02 Update:

  • Rewrote the part type check due to some basic parts in specific forms not being detected.
  • Rewrote the selection loop to fix slowdown when converting Model class selections.
  • I discovered (a bug) that union/smoothing quality deteriorates even with a relatively short distance from the world origin. Expect improvements on smaller parts now.

1.03 Update:

  • Added a simple warning-style gui to show conversion progress.
  • Can now handle CylinderMesh and any DataModelMesh with non-default offset and scale.
  • Implemented a cache system, where bevelled geometry is reused for parts of identical size. This improves conversion speeds greatly; selections with fewer unique parts will be much faster.

1.04 Update:

  • Upgraded the gui for creating bevels from length input. The box will appear after activating the toolbar button and making selections.
    image

The default 0.09192375 size rather neatly converts into length 0.065.

I had to update the cylinder math to prevent half size lengths intersecting away their final size. Even though half size lengths on wedges break this rule, I may leave them as is.

  • Now supports/re-parents JointInstances, WeldConstraints, Constraints, NoCollisionConstraints and ObjectValues.
  • Switched to IntersectAsync via GeometryService for even more stability. This has improved the way materials and decals are displayed.
3 Likes