This line, despite all the math that goes into it, does nothing more than rotate the CFrame onto its back so that you get a CFrame that faces up relative to the original CanvasPart CFrame and move it up to the surface. EgoMoose does it in a more complex way, but it’s equivalent to this:
local cf = self.CanvasPart.CFrame * CFrame.Angles(math.rad(-90), math.rad(180), 0) * CFrame.new(0, 0, -canvasSize.Y/2)
The explanation
Let’s take a look at what EgoMoose is doing with his math to see how I arrived at my conclusion.
To start, remember what the different axes mean on a CFrame; the x-axis is the right axis, the y-axis is the up axis, and the z-axis is the back axis.
Notice that EgoMoose defines mathematical constants back
, top
, and right
to aid in his math. Do you notice something strange about them? He sets back
to the down direction, top
to the forward direction, and right
to the left direction. Imagine turning a cube on its back so that its backside points down and turning it so that all these other transformations apply. That’s basically what EgoMoose is doing. This is why I say he’s simply rotating the CFrame.
Now let’s look at how he does it using CFrame.fromMatrix()
. Let’s take a look at the CFrame he constructed using the fromMatrix()
constructor:
EgoMoose multiplies this CFrame by the original CFrame. Keep in mind that his goal is a CFrame facing directly upwards sitting on the surface of the CanvasPart. Also remember that multiplying two CFrames together positions a CFrame by another CFrame. The CFrame constructed here is created in to be in the original CFrame’s local space. It’s meant to be the offset from the original CFrame to the surface CFrame which is the goal. By multiplying by the original CFrame, you have the surface CFrame in global space.
The first argument is the position; that’s the easiest part. The CanvasPart’s CFrame is in the middle of the part, so to get it on the surface, you simply get the distance to the surface, which the height of the canvasPart divided by 2, since you’re bringing it up (in local space) to the surface. It looks unnecessarily complex because EgoMoose just took advantage of the mathematical constant he created, back
, to get the height:
local size = Vector3.new(x, y, z) -- Represents the size of the canvas part
(Vector3.new(0, 1, 0) * size)/2 == Vector3.new(0, y/2, 0) -- Just the offset of the distance required
-- Also remember negative of the back vector is Vector3.new(0, 1, 0)
In reality, -back*canvasSize/2
is just Vector3.new(0, canvasSize.Y/2, 0)
.
For the other three arguments, EgoMoose plugs in each of the three variables into their corresponding axes to create his rotated CFrame.
Then, multiplying by the original CFrame, cf
becomes the surface CFrame in global space, as was shown in the picture.