Trying to understand Object Space

Hi,

at the moment I am trying to understand the concept of Object Space in CFrame and trying to see what Part.CFrame:ToObjectSpace(cf) does. I know that this should return part’s CFrame relative to cf. I think It’s as if you are using cf as an origin instead of the world origin.

I have this code:

local originPart = Instance.new("Part", game.Workspace)
originPart.Anchored = true
originPart.CanCollide = false
originPart.BrickColor = BrickColor.Random()
originPart.CFrame = CFrame.new(0,0,0)
originPart.Name = "originPart"

local newPart = Instance.new("Part", game.Workspace)
newPart.Anchored = true
newPart.CanCollide = false
newPart.BrickColor = BrickColor.Random()
newPart.CFrame = CFrame.new(0,0,4)
newPart.Name = "newPart"

local resultPart = Instance.new("Part", game.Workspace)
resultPart.Anchored = true
resultPart.CanCollide = false
resultPart.BrickColor = BrickColor.Random()
resultPart.CFrame = newPart.CFrame:ToObjectSpace(originPart.CFrame)-- The resultPart's cframe is the cframe of newPart Relative to originPart
resultPart.Name = "resultPart"

I have 3 parts where one is being used as the “origin” (originPart), one is being used as a random part (newPart) and the last one to show the relative cframe between the other two.

Before executing my code, I was expecting the resultPart to have the same position as newPart.
This is the result:

The resultPart seems to have moved to the opposite direction, in front of the originPart. Can someone explain why?

This might be wrong but does this happen because it takes the originPart’s lookvector which is 0,0,-1 opposite of the backvector which is 0,0,1?

Please correct me If I have said something incorrrect.

EDIT:
Hmm, I think I get it now. When I try to translate 0,0,4 relative to the originPart, I am attempting to put it 4 studs in front which in world position happens to be 0,0,-4.

I believe you mixed up the CFrames, it should be:

resultPart.CFrame = originPart.CFrame:ToObjectSpace(newPart.CFrame)

And this will get you the desired result. Currently, it’s reversed because order matters.

It does yield the result I initially expected however are you sure it is the order it has to be?
On the wiki it says this:
image

So if I am trying to get newPart’s Cframe relative to originPart, isn’t the order correct?

I think that ToWorldSpace is what you’re looking to use. Right now the result is (0,0,-4) because that’s the point relative to newPart.CFrame in object space, but what your expecting is that its the point that’s in world space relative to newPart.CFrame. originPart.CFrame is being transformed into object space, but that point in worldspace isn’t the same in object space.

resultPart.CFrame = newPart.CFrame:ToWorldSpace(originPart.CFrame)

I believe it’s an error with the dev forum wiki, I never used the football article to learn.

In this other CFrame article with the door, the door is calculated relative to the hinge, the hinge is the one rotating and the door goes to the “right” of the hinge.

local door = game.Workspace.Door
local hinge = game.Workspace.Hinge
 
local offset = hinge.CFrame:inverse() * door.CFrame; -- offset before rotation
game:GetService("RunService").Heartbeat:connect(function(dt)
	hinge.CFrame = hinge.CFrame * CFrame.Angles(0, math.rad(1)*dt*60, 0) -- rotate the hinge
	door.CFrame = hinge.CFrame * offset -- apply offset to rotated hinge
end)

Where:

local offset = hinge.CFrame:inverse() * door.CFrame
--Is equal to
local offset = hinge.CFrame:ToObjectSpace(door.CFrame)
local offsetDoorRelativeToHinge= hinge.CFrame:ToObjectSpace(door.CFrame)

and

	door.CFrame = hinge.CFrame * offset -- apply offset to rotated hinge
--is equal to
	door.CFrame = hinge.CFrame:ToWorldSpace(offset) -- apply offset to rotated hinge

Therefore my understanding is that the door CFrame is calculated relative to the hinge CFrame.

1 Like

:ToWorldSpace is basically multiplying CFrames together relative to World origin.

I am trying to understand what :ToObjectSpace() does.

Hmm, you might be right as I’ve seen it being worded like you’re saying on another forum thread. I will try to understand what you’ve posted. Thank you :slight_smile:

Sorry, but to be extra clear :ToWorldSpace is not always relative to world origin. It’s relative to the CFrame of CFrame:ToWorldSpace(cf). This is also how Attachments WorldCFrame is calculated via the formula:

attachmentWorldCFrame = part1.CFrame * attachment.CFrame --how attachment.WorldCFrame is calculated
--samething as
attachmentWorldCFrame = part1.CFrame:ToWorldSpace(attachment.CFrame) --how attachment.WorldCFrame is calculated

And as we know attachments are relative to the parented part which is named part1 in this example and thats how they “Stick” onto the part.

Brain is pretty fried rn, tbh.

1 Like

Hmm I see. Trust me my brain is fried as well right now especially with the wiki saying one thing and you saying another haha. I am going to play around the rotating door thing and I will give you the solution if I manage to understand. Thanks for the help :smiley:

1 Like

I have just confirmed with an experienced friend of mine and he says you’re right. So my initial expectation of the result was technically the result I should have gotten? As in, to get newPart’s CFrame relative to originPart’s CFrame (originPartCFrame:ToObjectSpace(newPart.CFrame)) would have yielded my initial expectation: