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
- 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!