How do I align models with rotated parts? (Model placement system)

So, its pretty straight forward. I am trying to make a classic styled building system, but there seems to be a problem with placing models on tilted parts.

Basically, I am trying to get the model to snap on to parts and surfaces perfectly via CFrame and surfaces (normal). But I cannot for the life of me get this model to line up correctly with tilted surfaces.

image

Iv’e tried using CFrame:ToEulerAnglesYXZ() and CFrame:ToEulerAnglesXYZ(), but none of them seems to work.

Some help would be greatly appreciated!

local function MovePreviewModel(MouseTarget, MouseHit)
	if MouseTarget then
		if PreviewModel.Parent ~= PlayerCamera then
			PreviewModel.Parent = PlayerCamera
		end
		
		local PrimaryPart = PreviewModel.PrimaryPart
		
		local Params = RaycastParams.new()
		Params.FilterType = Enum.RaycastFilterType.Blacklist
		Params.FilterDescendantsInstances = {unpack(GetPlayerCharacters()), PreviewModel}
		
		local UnitRay = workspace.CurrentCamera:ScreenPointToRay(Mouse.X, Mouse.Y, 1)
		local BuildRay = workspace:Raycast(UnitRay.Origin, UnitRay.Direction * 1000, Params)
		if BuildRay then
			local HitPart = BuildRay.Instance
			if HitPart then
				local HitCFrame = CFrame.new(BuildRay.Position, BuildRay.Position + BuildRay.Normal)
				PreviewModel:SetPrimaryPartCFrame(HitCFrame * CFrame.Angles(math.rad(-90), 0, 0) * CFrame.new(0, PreviewModel.PrimaryPart.Size.Y/2, 0))
			end
		end
	end
end
3 Likes

i think its like vector to object space or smth then multipying the grey parts rotation matrix to the green thingies rotation matrix

1 Like

I’m no pro at building systems, so don’t count on my word. But have you tried getting the rotation of the targeted object? And then applying the rotation to the object you want to be rotated?

1 Like

As mentioned before, I tried that.

But the results seemed to just make the model rotate in completely wrong directions.

local HitCFrame = CFrame.new(BuildRay.Position, BuildRay.Position + BuildRay.Normal)

Yeah the main problem here is that when you made a new cframe here it got rid of the orientation of the vector normal to the surface. Yes, it does make a cframe that points away from the part normal, but that’s only half the battle.

CFrame:ToAxisAngle( )

Alright I think this function might help? This basically returns the vector which the axis the object is rotating at and how much it got rotated. You might have to finagle with the frame value of the object to make it work appropriately.

Report to me if you have questions I personally never touched this function.

2 Likes

you can also align vectors by spherical interpolation with quaternion number system

I tried using this in multiple cases, but this function doesn’t appear to even affect the model

local HitPartRotation = HitPart.CFrame:ToAxisAngle()
				local HitCFrame = CFrame.new(BuildRay.Position, BuildRay.Position + BuildRay.Normal)
				PreviewModel:SetPrimaryPartCFrame(HitCFrame * CFrame.Angles(HitPartRotation.X, HitPartRotation.Y, HitPartRotation.Z) * CFrame.Angles(math.rad(-90), 0, 0)  * CFrame.new(0, PreviewModel.PrimaryPart.Size.Y/2, 0))

Ok to clarify, the first argument doesn’t return a vector of rotation, it’s a vector that is the line of rotation. For example a vector of 0,1,0 means it’s a vector that rotates on the y axis. The thing about any rotation of a 3D object is that it can be defined as a rotation at a certain axis. The first vector is that axis.

You can’t treat the first returning value of :ToAxisAngles() like the orientation vector.

1 Like

But it does.

No you are right, it is a vector, but you are misinterpretating what the vector is meant to be. The first returning value is the axis of rotation, not a vector that you’d see in the orientation property of a vector.

1 Like

Well how do I use the returned value in my case?