What it does
A CFrame value represents a coordinate system in 3D space, offset from the base coordinate system of the game world by some translation and rotation. The first 3 numbers are the position and the remaining 9 make up a rotation matrix. There’s 9 numbers for one rotation because the rotation is represented by 3 vectors, one for each axis of the coordinate system.
When you use the *
operator on a CFrame and a Vector3 then it implicitly calls the VectorToWorldSpace
method on the CFrame value with the Vector3 value as it’s argument. It’s named like that because it answers the question “Given this vector in this coordinate system, what is that vector in the base coordinate system of the world”.
For example: CF = CFrame.new(0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9); v = Vector3.new(1, 0, 0); CF * v -- (1, 4, 7)
. This asks “what happens if I go out 1 on the X axis of this coordinate system, 0 on the Y axis and 0 on the Z axis”, or rather “what does that look like from the perspective of the world space”, and the answer is (1, 4, 7)
. This tells us that the X axis of the CFrame is (1, 4, 7)
. This also tells us that the 4th, 7th and 10th argument to CFrame.new make up the X axis of the returned CFrame.
Here’s a code snippet that shows you where each number goes in general:
function vectorToWorldSpace(cf, v)
local cfX = cf.RightVector
local cfY = cf.UpVector
local cfZ = cf.LookVector
return return cf.p + v.X * cfX + v.Y * cfY + v.Z * cfZ
end
Or if you want to know what exact numbers go into what exact calculations:
function vectorToWorldSpace(cf, v)
local x, y, z, r00, r01, r02, r10, r11, r12, r20, r21, r22 = cf:components()
return Vector3.new(x, y, z)
+ v.X * Vector3.new(r00, r10, r20)
+ v.Y * Vector3.new(r01, r11, r21)
+ v.Z * Vector3.new(r02, r12, r22)
end
Weirdness
Both code snippets you posted have only 11 arguments, and the one where you transform by a vector uses a different vector from what you mentioned just before. On top of that, the CFrame you mention is a bit weird because it’s not one that a Part can ever have in Roblox. Specifically it’s rotation matrix doesn’t satisfy the two conditions for being orthonormal: having orthogonal (right-angle) basis vectors and unit-length basis vectors. The basis vectors define the axes of the coordinate system that any given CFrame represents, i.e. the X, Y and Z axes i.e. the RightVector, UpVector and -LookVector (notice the sign). The math for what happens when you transform a Vector3 by a CFrame is still the same if the CFrame is weird like this tho.
You can verify that no part can have that CFrame like this:
local CF = -- your weird CFrame
somePart.CFrame = CF
print(somePart.CFrame == CF) --prints false
This happens because Roblox automatically orthonormalizes (“fixes”) the CFrame value if you try to actually set a Part’s CFrame property to it.
You can verify they’re not orthogonal like so:
print(CF.UpVector:Dot(CF.RightVector)) -- ~ 10.5
print(CF.UpVector:Dot(CF.RightVector)) -- ~ 0.99
print(CF.LookVector:Dot(CF.RightVector)) -- ~1.12
All of those should print very close to 0, because the dot product of any two orthogonal vectors is 0. In reality they don’t print 0 (something like -5.960463766996327e-08, wayyyy closer than 0.99) probably due to floating point imprecision.
You can verify they’re not unit vectors like this:
print(CF.RightVector.Magnitude) -- ~1.5
... and so on
More reading
If you want a full introduction to how 3D transforms are handled in games, I highly recommend chapters 1 and 2 of Foundations of Game Engine Development Volume 1: Mathematics. They introduce vector math and linear algebra (matrix math) as well as their “combination”, transforms, from a coding perspective (with full examples in C++). It’s… not exactly fun reading though. It’s a literal math textbook.
If you prefer videos, Khan Academy has a course on linear algebra but nothing that applies directly to game dev (there are some quirks that are covered in Game Engine Development)
Honestly though, understanding the mathematics is not really that useful. If (like me) you only care about how it applies to game dev, just focus on building an intuition for what it means to perform the different operations that are available to you and how you can solve problems using them. You can literally just go through the wiki page on CFrame and see if you understand what everything does:
If you don’t understand something, play around with simple examples in Studio to build intuition or search/ask here on the forums about “how to use PointToWorldSpace” for exaple.