Weird Orientation Behavior when Constructing CFrame from Vectors

Hey, I’m currently working on using AlignOrientation and ground normal to align a controllable office chair assembely to the ground below it. I’ve got it all working, except for the fact that I want to make it so the chair can spin freely on the Y-Axis, and because AlignOrientation lacks a MaxTorque vector3 value, I’m trying to do the code myself.

What I’m doing at the moment is compiling a new Orientation CFrame that is inputted by deriving it from the lookvector of the actual chair (this determines the orientation on Y axis) and the upvector of the ground normal (determining X and Z).

Using a Debug Libary, I can see that the actual Vectors (right,up, and look) are pointing perfectly as they should.

But whenever I actually enable the constraint into which I am feeding these vectors via CFrame.fromMatrix, the chair glitches out and just messes up entirely.
image

If it helps, in a scenario where the two vectors should in theory be identical, the orientations are:
0, -109, 0 — constraint
90, 70, 0 – actual

I feel like something is being rotated relative to something else incorrectly, but I’m entirely lost as to what it actually is, I would greatly appreciate any help!

1 Like

Maybe not the only problem, but the third vector you pass to fromMatrix should be -LookVector

local CalculatedFrame = CFrame.fromMatrix(MovePart.Position, ComputedRightVector, ComputedUpVector, -LookVector)
AlignOrientation.CFrame = CalculatedFrame

Like so? Doesn’t seem to have changed anything.

If it’s any help, when the AlignConstraint is outputting orientation of (0,0,0) the actual rotation (90,-118,-118), when these should be matching up.

That’s what I meant, yes. I can’t tell much else that’s wrong from the code, but if you share a minimal model with a reproduction I could help further

Here’s the model of the chair
Chair.rbxm (222.1 KB)

and here’s the code I’ve got running inside a RenderStepped loop (this is the Gizmo thing)

local AlignOrientation: AlignOrientation = ChairModel:WaitForChild("Mass"):FindFirstChild("AlignOrientation")    
local result = workspace:Raycast(MovePart.Position, Vector3.new(0,-10,0), Params)
    if result then
        -- local lookAt = result.Position + result.Normal
        --     -- //testing
        
        
        -- local Thing = CFrame.lookAt(result.Position, lookAt) 
        -- AlignOrientation.CFrame = CFrame.fromMatrix ()

        local UpVector = result.Normal
        local LookVector = MovePart.CFrame.LookVector
        Gizmo.PushProperty("Color3", Color3.new(0.933333, 0.184313, 1))
        Gizmo.Arrow:Draw(MovePart.Position, MovePart.Position + LookVector, 0.05, 0.1, 9)

        -- Sourcing: https://devforum.roblox.com/t/setting-cframe-upvector/258721/2
        local ComputedRightVector = (LookVector:Cross(UpVector)).Unit 
        Gizmo.PushProperty("Color3", Color3.new(1, 0.184313, 0.184313))
        Gizmo.Arrow:Draw(MovePart.Position, MovePart.Position + ComputedRightVector, 0.05, 0.1, 9)

        local ComputedUpVector = (ComputedRightVector:Cross(LookVector)).Unit
        Gizmo.PushProperty("Color3", Color3.new(0.184313, 1, 0.184313))
        Gizmo.Arrow:Draw(MovePart.Position, MovePart.Position + ComputedUpVector, 0.05, 0.1, 9)

        -- local CalculatedFrame = CFrame.fromMatrix(MovePart.Position, ComputedRightVector, ComputedUpVector, LookVector)
        local CalculatedFrame = CFrame.fromMatrix(MovePart.Position, ComputedRightVector, ComputedUpVector, -LookVector)
        AlignOrientation.CFrame = CalculatedFrame
    end

I think it’s freaking out because the AlignOrientation changes the LookVector that you use on the next frame to recompute the AlignOrientation?

Try enabling PrimaryAxisOnly on the AlignOrientation, so it lets the chair freely spin elsewise. You can probably simplify your CFrame computation a bit also since you no longer care about the look vector, but it should work as is too.

1 Like

Enabling primary axis only locks the chair on that Y axis, wdym by simplifying the CFrame math?

I may have misunderstood what you were trying to do.

I thought you wanted to align the Y axis of the chair with the raycast result Normal, while allowing the chair to spin freely on the Y axis.

Is that not the case?

That is correct yes, I mean that enabling PrimaryAxisOnly locks rotation on the Y axis and leaves the other 2 axis unlocked.

		local look = MovePart.CFrame.LookVector
		local normal = result.Normal
		
		local proj_look_onto_normal = look:Dot(normal) * normal
		local proj_look_onto_ground_plane = look - proj_look_onto_normal
		Gizmo.PushProperty("Color3", Color3.new(0.796078, 0.627451, 1))
		Gizmo.Arrow:Draw(MovePart.Position, MovePart.Position + look, 0.05, 0.1, 9)
		
		local computed_right = proj_look_onto_ground_plane.Unit:Cross(normal)
		Gizmo.PushProperty("Color3", Color3.new(1, 0.184313, 0.184313))
		Gizmo.Arrow:Draw(MovePart.Position, MovePart.Position + computed_right, 0.05, 0.1, 9)
		
		-- the 'computed up vector' is the normal
		Gizmo.PushProperty("Color3", Color3.new(0.184313, 1, 0.184313))
		Gizmo.Arrow:Draw(MovePart.Position, MovePart.Position + normal, 0.05, 0.1, 9)
		
		-- use the computed vectors
		-- rotate to match primary axis upward
		local CalculatedFrame = CFrame.fromMatrix(MovePart.Position, computed_right, normal, -(proj_look_onto_ground_plane.Unit)) * CFrame.Angles(0, 0, math.pi/2)
		AlignOrientation.CFrame = CalculatedFrame

I’ve adjusted the way we calculate the look vector, we’re not interested in the chair’s look vector but rather its projection onto the normal plane. Excuse my coding style if its a bit different :innocent:

I’ve also moved the attachment from the ‘Core’ to the ‘Mass’ (the Core was upside down) and made sure the attachment was at identity orientation.

Then I set the ‘primary axis only’ on the align orientation to ‘enabled’ and rotated the attachment so that it’s primary (X) axis is upward, and we account for this as well by adding a rotation to the final CalculatedCFrame.

This is the result, baseplate green indicates when the alignorientation was enabled:

Project File:
chairyaxis.rbxl (290.9 KB)

1 Like

Thank you so much, will try this out in a bit and see if it works correctly.

Took a bit of tweaking as I needed to make it work with the rest of my code but that works perfectly, thank you so much. I’m terrible at CFrames so you’ve saved me hours of work lol.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.