Merging 2 CFrame orientations, with the 3 axis's being from either of the two

Basically what im trying to do is make the red part have the same orientation as the purple part but only for the Y axis. the red part should keep their X and Z orientation axis, but have it face the same direction as the purple part on the Y axis. the golden part is the expected result.

image

How can i generate a new CFrame (without creating a new part) that is the same as the golden part given only both the red and purple part’s CFrame? any help is appreciated.

local PurplePart = --define
local RedPart = --define

RedPart.CFrame = CFrame.new(RedPart.Position) * CFrame.Angles(math.rad(RedPart.Orientation.X), math.rad(PurplePart.Orientation.Y), math.rad(RedPart.Orientation.Z))
1 Like

what if im only given the CFrames and not the parts? (meaning i can’t use the Orientation property)

how would i change the CFrames to get their Orientation values?

I would use this CFrame rotation between two vectors function from this tutorial. Don’t focus too much on the quaternions you can still the CFrame.fromAxisAngle which tbh is more understandable though quaternions are cooler.

Edit: @20amir02 here is the newer code that should work if you use this method to align one axis to another, the issue with the previous is that this rotation is relative to world space and so the rotation must happen before the red part CFrame. CFrame order of operation stuff. The + position is there in order to maintain the parts current position, and the .CFrame - .CFrame.Position is to add the previous parts rotation into account.

local PurplePart = workspace.Part2--define
local RedPart = script.Parent--define

local function getRotationBetween(u, v, axis)
	local dot, uxv = u:Dot(v), u:Cross(v)
	if (dot < -0.99999) then return CFrame.fromAxisAngle(axis, math.pi) end
	return CFrame.new(0, 0, 0, uxv.x, uxv.y, uxv.z, 1 + dot)
end
local addRotation = getRotationBetween(RedPart.CFrame.UpVector, PurplePart.CFrame.UpVector,Vector3.new(0,1,0))
RedPart.CFrame = addRotation*(RedPart.CFrame-RedPart.CFrame.Position)+RedPart.CFrame.Position
Old not working code
local PurplePart = --define
local RedPart = --define

local function getRotationBetween(u, v, axis)
    local dot, uxv = u:Dot(v), u:Cross(v)
    if (dot < -0.99999) then return CFrame.fromAxisAngle(axis, math.pi) end
    return CFrame.new(0, 0, 0, uxv.x, uxv.y, uxv.z, 1 + dot)
end

RedPart.CFrame *= getRotationBetween(RedPart.UpVector, PurplePart.UpVector,Vector3.new(0,1,0))

This should apply an additional rotation to the red part which should align the red parts up vector with the purple parts UpVector.

The UpVector should represent the y axis of the part as expected.

The third parameter which is (0,1,0) is arbitrary meaning it can be anything.

Case 2, from the tutorial

If the u and v are complete opposites i.e. u == -v, then we choose an arbitrary axis and rotate by 180 degrees.

@XdJackyboiiXd21 solution could work if you were to use:

local x,y,z = CFrame:ToOrientation() 

however I talked about the gotcha scenario here.

The devhub BasePart | Roblox Creator Documentation

This differs from proper Euler angles, and is instead Tait–Bryan angles which describe yaw, pitch and roll.

Yeah weird things will happen if you mix the two from experience.

1 Like

i can’t seem to get your solution to work. im not really that experienced in these advanced stuff :grimacing:

though ive been at it with jacky’s solution with ToOrientation(), using CFrame.Angles() and CFrame.fromOrientation() both doesn’t give me the expected results.

I ran this code:

local d = math.deg
local part1 = workspace.Part1 --Red Part
local part2 = workspace.Part2 --Purple Part

local x1,y1,z1 = part1.CFrame:ToOrientation()
local x2,y2,z2 = part2.CFrame:ToOrientation()

part1.CFrame = CFrame.new(part2.Position) * CFrame.fromOrientation(d(x1),d(y2),d(z1))

though it seems to be correct, the red parts X orientation is slightly different!
image

image

and the difference is much more noticable in other cases.

CFrame from Orientation and all of the constructors use radians and not degrees.

1 Like

i’ve had many little things betray me in debug, but i never thought math.deg would do me like that :joy:

i’ve been doing this all morning

it works now, thank you for your help!