How to get the angles of a surface?

Rather than trying to convert this up vector into an angle which is also complicated it’s better to leave it I would rather use @EgoMoose advanced CFrame technique to leave it in terms of vectors.

We can obtain a CFrame rotation to align the current persons “UpVector” to the new surface upvector. Here is an example script and video.

The advantage of this method is that it will allow you to rotate along the new upVector without having to specify a right vector as a CFrame.fromMatrix solution.

Even unity games use this method, They have the built in method Quaternion.FromToRotation which is @EgoMoose advanced CFrame trick


Also notice the similarities with my code piece:

local rotateToFloorCFrame = getRotationBetween(wedge.CFrame.UpVector,rayResult.Normal,randomAxis)
local goalCF = rotateToFloorCFrame*wedge.CFrame

--TL;DR 
local fromToQuaternion = getRotationBetween(wedge.CFrame.UpVector,rayResult.Normal,randomAxis)
wedge.CFrame = fromToQuaternion * wedge.CFrame

Edit: Yeah this is the correct and smoother version

local wedge = script.Parent

local randomAxis = Vector3.new(1,0,0) -- Read this in the EgoMoose article

local DOWN = -Vector3.new(0,500,0)

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


while true do
	local dt = wait()

	local rayResult = workspace:Raycast(wedge.Position,-1000*wedge.CFrame.UpVector)
	if rayResult then
		local rotateToFloorCFrame = getRotationBetween(wedge.CFrame.UpVector,rayResult.Normal,randomAxis)
		local goalCF = rotateToFloorCFrame*wedge.CFrame
		wedge.CFrame = wedge.CFrame:Lerp(goalCF,5*dt).Rotation +wedge.CFrame.Position
	end
end
27 Likes