This plugin can solve CSG failures by aligning CFrames

Some people “brute force” CSG’s when they fail by randomly rotating parts. My solution is to perfectly align them by fixing up their CFrame matrices. I fill this plugin with random geometry tools I use and I added a “CFrame Repair” tool today:

Here’s what it does:

It displays the part’s exact CFrame and Size on the right. The fraction part is in octal because decimal doesn’t display binary numbers well; All you need to know is that ‘0x777777’ roughly means ‘0.999999’.

It displays which components can be repaired and why:

  • Red means the fraction is nearly 0. If you have something against negative 0’s, it gets rid of those too :stuck_out_tongue:
  • Purple means it’s nearly 1.
  • Green means it’s nearly equal to a common value like sin(45 degrees) or cos(30 degrees)
  • Blue means it’s nearly equal to a previous component in the same cframe…
  • Yellow means it’s nearly equal to a component from the part you last clicked on.

CFrames far from the origin can get pretty messed up


The properties pane might say that an object’s size is (0.5, 1, 0.5) when in reality its size is (0.499999, 1.000001, 0.4999989). It’s rotation might say it’s 180 degrees, when a vector in the cframe’s rotation matrix is actually (0.9999999, -0.000001, 0.000001) instead of (1, 0, 0), making it 179.9999999 degrees. If you start building off of a part with this problem, the problem spreads.

A lot of problems happen when you try to rotate a part by (even by 90 degrees). CFrame.Angles uses sine and cosine to create a 3x3 cframe rotation matrix. Because pi is irrational, and floating point precision is limited, sin(pi) will give you 0.0000000000000001 instead of just 0. If you set a parts rotation to 90 degrees through the properties pane, it actually gets set to something like 89.999999 degrees because of the radian conversion. Dragging parts over other parts also results in problems.
Here’s some simple code that will generate a clean, axis-aligned cframe:

local function RightAngles(rx, ry, rz)
	local xx, yx, zx, xy, yy, zy, xz, yz, zz =  1, 0, 0, 0, 1, 0, 0, 0, 1
	for i = 1, rx%4 do
		yx, yy, yz, zx, zy, zz = zx, zy, zz, -yx, -yy, -yz
	end
	for i = 1, ry%4 do
		zx, zy, zz, xx, xy, xz = xx, xy, xz, -zx, -zy, -zz
	end
	for i = 1, rz%4 do
		xx, xy, xz, yx, yy, yz = yx, yy, yz, -xx, -xy, -xz
	end
	return CFrame.new(0, 0, 0, xx, yx, zx, xy, yy, zy, xz, yz, zz)
end
print(CFrame.Angles(math.rad(180), math.rad(90), 0))
print(RightAngles(2, 1, 0))

This bow handle used to give me trouble

Problem solved! :joy:

7 Likes

For clarification, can I select multiple parts and then click a button to automatically fix them, or do I need to manually inspect each face/part and repair them individually?

So just update your plugin if you already have it?

Why does it only select one face rather than just the whole part?

Right each part needs to be clicked individually. It doesn’t matter what face is selected, it just reuses the “Face” input method that the other tools use; Depending on the selected face it used to simplify each of the 3 vectors individually (on my first iteration), but that was way too tedious. The tool takes context from the last part you clicked on so they can align. I could add a function to _G while the tool is selected that disregards that and tries to fix all selected parts.

Yep