Interpolating rotations (NOT ALIGN ORIENTATION)

I am making a tutorial on how to make faux gravity in roblox (think of like u can walk on sphere meshes) and everything is working great, the code works if i position my player it goes to the planet (non euler integration) however the vectors of the player are axis aligned. In a sense if I am under the planet it still applies forces as if I am on the top. My question here is how can I align the orientation so that its normal is the same as the sphere? I would cast a ray and align the normal difference however you can’t really do that on a planetary scale, can u? Or maybe i’m wrong I just don’t know what to do. ’

TL:DR

how to rotate object perpendicular to other object

I found a pretty cool trick you can use from this really great tutorial with some really nice functions.

Basically you can apply a CFrame rotation to the player from where it’s currently facing towards the normal vector of the surface and the up axis will align using the functions provided. Personally I really like the quaternion version as it accomplished the same task but in only 3 lines of code and seems mathematically sound as well :flushed:.

I believe this has to be done continuously while disabling certain parts of the humanoid code which makes it auto align to the baseplate surface (0,1,0).

1 Like

I already saw that and trying to do it while also constantly applying a force gave a weird glitch

I am looking for a more straight forward approach that just involves euler angles

1 Like

I think using vectors to describe orientation is already straight forward as is I mean one of your given inputs is the normal vector of the surface, you would have to convert this into an rotation matrix researching online.

As for your current implementation all I can do is guess the issue without being given the code. Assuming you implemented it correctly, are you sure the sphere normal makes sense? Are you using a meshpart with weird collision fidelity? Did you disable the humanoid forces? And yeah.

Edit: also this has been done before with EgoMooses very own wall stick controller and you can see how the rotations look like in the walls tick code. I believe he created his own custom physics based humanoid root part judging by the code on his GitHub.

local targetCF = self.Physics.Floor.CFrame * part.CFrame:ToObjectSpace(teleportCF or self.HRP.CFrame)
	local sphericalArc = getRotationBetween(targetCF.YVector, UNIT_Y, targetCF.XVector)

	physicsHRP.CFrame = (sphericalArc * (targetCF - targetCF.p)) + targetCF.p
	self._fallStart = self.Physics.HRP.Position.y
local function getMass(char)
	local mass = 0
	for _, v in pairs(char:GetDescendants()) do
		if v:IsA("BasePart") then
			mass += v:GetMass()
		end
	end
	return mass
end

local function getClosestFaux(char, fauxs)
	local closest = 0
	local faux = nil
	for i, v in pairs(fauxs:GetChildren()) do
		if v:IsA("BasePart") then
			local dif = (v.Position - char.HumanoidRootPart.Position).Magnitude
			if dif > closest then
				closest = dif
				faux = v
			end
		end
	end
	return closest, faux, faux:GetMass()
end

local function getScalar(char)
	local m1 = getMass(char)
	local difference, faux, m2 = getClosestFaux(char, workspace.Fauxs)
	return m1 * m2 / difference^2, faux, difference
end

local function getNormal(char, faux)
	return (faux.Position - char.HumanoidRootPart.Position).Unit
end

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


game.Players.PlayerAdded:Connect(function(plr)
	plr.CharacterAdded:Connect(function(char)
	local attractor = script.attractor:Clone()
	attractor.Parent = char.HumanoidRootPart
	game:GetService("RunService").Heartbeat:Connect(function()
		local scalar, faux, difference = getScalar(char)
		local normal = getNormal(char, faux)
		local force = scalar * normal
		attractor.Force = force
		local u = char.HumanoidRootPart.CFrame.UpVector
		local axis = u:Cross(normal)
			char.HumanoidRootPart.CFrame *= getRotationBetween(u, -normal, axis)
		end)
	end)
end)

this is my code so far. It seems like it rotates it a bit if i try and move it but it also seems like it keeps teleporting for some reason.

Your code seems ok assuming faux.Position is at the center of the sphere which it should be for a sphere base part. Looking at EgoMooses code for the wall stick controller he turns on humanoid platform stand to prevent the humanoid from interfering with the physics. If you searched online you will find that Humanoid physics are wack and will cause most of your problems like this ragdoll fling.

1 Like