Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
6

A short CFrame question. Can someone explain this? [closed]

Asked by
AZDev 590 Moderation Voter
8 years ago

Why is CFrame.new(1,1,1) * CFrame.new(2,2,2) equal to CFrame.new(3,3,3)?

0
It has to do with confusing matrix math mumbo jumbo Perci1 4988 — 8y
0
Just imagine * is a "plus". Netflixy 126 — 8y

Locked by AZDev, Link150, DepressionSensei, and shayner32

This question has been locked to preserve its current state and prevent spam and unwanted comments and answers.

Why was this question closed?

1 answer

Log in to vote
8
Answered by
BlueTaslem 18071 Moderation Voter Administrator Community Moderator Super Administrator
8 years ago
Edited by OldPalHappy 7 years ago

I'm going to back-up and first answer a related question:

Why is Vector3.new(1, 2, 3) + Vector3.new(4, 5, 6) equal to Vector3.new(5, 7, 9)?

What are vectors -- in general

Vector3s represent two kinds of values:

  1. positions in the world (called absolute coordinates)
  2. translations between points in the world -- the relationship between two points in space (how far, close, in what direction they are) (called relative coordinates)

In general, the .x and .y and .z of absolute coordinates don't really mean much. How "big" they are just means how far they are from (0, 0, 0) -- and you probably build your games not really caring where (0, 0, 0) is anyway. Their sign gives you an idea of which "direction" they are from the origin, but again, who cares about the origin?

The .x and .y and .z of relative coordinates means everything. "one stud below" is Vector3.new(0, -1, 0) -- you probably have relative coordinates like this all throughout your code.

What do you mean by 'relative coordinate'?

Adding to absolute

Let's say we want to spawn a light 10 studs above a player's head. What does the code for that look like?

local p = Instance.new("Part", workspace)
p.Position = head.Position + Vector3.new(0, 10, 0)
Instance.new("PointLight", p)

When we say "10 studs above", we are describing a position (p.Position) relative to another position (head.Position).

That relative Vector3 is Vector3.new(0, 10, 0).

If we do <absolute> + <relative>, we get another absolute vector.

Adding relative

If you have two relative positions, e.g., 10 steps forward Vector3.new(0, 0, -10) and 10 steps to the right Vector3.new(10, 0, 0), you could take that like this:

person.Position = foo
person.Position = person.Position + Vector3.new(0, 0, -10)
person.Position = person.Position + Vector3.new(10, 0, 0)

This is really just doing

person.Position = foo + Vector3.new(0, 0, -10) + Vector3.new(10, 0, 0)

You can combine the two relative vectors into a single relative vector instead:

motion = Vector3.new(0, 0, -10) + Vector3.new(10, 0, 0) -- equal to Vector3.new(10, 0, -10)
person.Position = foo + motion

Subtracting

Algebra tells us that if p = h + r, then we should be able to do p - h = r.

In fact, we can print

print(p.Position - head.Position) --> 0, 10, 0

In general, you can get the relative displacement between two absolute positions by subtracting them. This is useful for, e.g., getting the distance to a target:

local displacement = zombie.Position - victim.Position

if displacement.magnitude < 10 then
    -- the relative difference in position
    -- between `victim` and `zombie`
    -- is less than 10 in magnitude

    -- i.e., they're nearby
end

Vectors

Vectors are in general defined by the behavior of + and - to behave as they do here.

Actually, vectors are defined in terms of addition + and inverse -. When you write a - b, really what that means is a + -b. This is significant in the analogy CFrames.

CFrames

CFrames are similar, with a few wrinkles.

CFrames can be relative or absolute;

part.CFrame is an absolute CFrame; CFrame.new(0, 1, 0) is a relative CFrame describing "up" one stud.

You can "apply" a relative CFrame by using * instead of +:

part.CFrame = part.CFrame * CFrame.new(0, 1, 0)

Just like with Vector3s, you can "combine" two relative CFrames into another relative CFrame, by using *:

part.CFrame = part.CFrame * CFrame.new(10, 0, 0)
part.CFrame = part.CFrame * CFrame.new(0, 0, -10)

-- same thing as
local motion = CFrame.new(10, 0, 0) * CFrame.new(0, 0, -10)
part.CFrame = part.CFrame * motion

Minus CFrames

Because of how CFrames are constructed, CFrame.new(a, b, c) is the same thing as CFrame.new(Vector3.new(a, b, c)) -- we know how Vectors get combined (add the components), so the corresponding Vector3 + happens when you * the CFrames constructed in that way.

Note that CFrames are a bit different; with vectors, u + v is the same as v + u. That's not the case with CFrames; x * y is NOT1 the same as y * x (and that's why CFrames don't also use +).

However, there isn't a corresponding - for *. In mathematics, we write x^-1, but that's not an acceptable notation in code. CFrames have an :inverse() method which makes the relative CFrame that "undoes" a CFrame. Thus

part.CFrame * blah * blah:inverse()
-- same thing as
part.CFrame

  1. In general, they're different, but they can be the same. For CFrame.new(x, y, z)'s, they behave just like vectors -- a * b and b * a will be the same in that case. Try using CFrame.Angles as an example where they're different 

0
Whoa DepressionSensei 315 — 8y
1
But I just tried print(a * b) print(b * a), where a and b are both CFrames, and I got the same result each time. Perci1 4988 — 8y
2
@Perci1 in general it's not true, but for some CFrames (e.g., just translations) it is. Added footnote BlueTaslem 18071 — 8y
0
Much thanks. This was extremely helpful. I already knew everything you explained at the top. I've been told that part.CFrame * CFrame * CFrame:Inverse() is the same as part.CFrame but never understood why until now. Thank you very much. AZDev 590 — 8y
Ad