Problem: I want to have the camera revolve around an origin given two points, a starting and ending point. Currently, I have code that should achieve this, but it fails to do this properly. It seems to not start at the start/finish properly.

Extra Info: I insert the start/end position manually. The script below is a local script.

Hypothesizing Equations: The equations below may be false, as I found them primarily online.

Theta of axis = arccos (vectorAxis / length)

t = a value between 0 and 1 based off of time

projectedTheta = offsetTheta * t + originTheta. This would give how far in-between the two positions theta should be based off of time

Mathmatical equations for q1, q2, and the equations for the finalX, finalY, and finalZ positions can be found here

Code: The below is my current code for this project.

wait(5)
local player = game.Players.LocalPlayer
local character = player.Character
local camera = game.Workspace.LocalCamera

local startCFrame = character.HumanoidRootPart.CFrame * CFrame.new(0,2,5)
local endCFrame = character.HumanoidRootPart.CFrame * CFrame.new(0,2,-5)
local origin = character.HumanoidRootPart.CFrame * CFrame.new(0,2,0)
local startVector = startCFrame.Position
local endVector = endCFrame.Position
	
local startUnit = startVector.Unit--startVector
local endUnit = endVector.Unit
	
local startXTheta = math.acos(startVector.X / (startVector.Magnitude))-- Theta = arccos(z/r)
local startYTheta = math.acos(startVector.Y / (startVector.Magnitude))
local startZTheta = math.acos(startVector.Z / (startVector.Magnitude))
local startTheta = Vector3.new(startXTheta, startYTheta, startZTheta)
	
local endXTheta = math.acos(endVector.X / (endVector.Magnitude))
local endYTheta = math.acos(endVector.Y / (endVector.Magnitude))
local endZTheta = math.acos(endVector.Z / (endVector.Magnitude))
local endTheta = Vector3.new(endXTheta, endYTheta, endZTheta)
	
local offsetTheta = endTheta - startTheta 
	
local n = (startVector - origin) * (endVector - origin)
local n0 = n.Unit
	
local q1 = startVector 
local q2 = origin + n0 * (q1 - origin)
local renderStepped;

renderStepped = runService.RenderStepped:Connect(function(deltaTime)
	timePassed += deltaTime
	--A value of time between 0 and 1 representing start/end
	local t = timePassed / pan.time  
	if t < 1 then
		local tOffsetOfTheta = offsetTheta * t
		print(tOffsetOfTheta)

		local projectedTheta = startTheta + tOffsetOfTheta
			 
		local finalX = origin.X + (math.cos(projectedTheta.X) * (q1.X - origin.X)) + (math.sin(projectedTheta.X) * (q2.X - origin.X)); 
		local finalY = origin.Y + (math.cos(projectedTheta.Y) * (q1.Y - origin.Y)) + (math.sin(projectedTheta.Y) * (q2.Y - origin.Y));
		local finalZ = origin.Z + (math.cos(projectedTheta.Z) * (q1.Z - origin.Z)) + (math.sin(projectedTheta.Z) * (q2.Z - origin.Z));
		local projectedPosition = Vector3.new(finalX, finalY, finalZ)
		--Creates a new CFrame set at Position, looking at the head.
		local cameraCFrame = CFrame.lookAt(projectedPosition, origin) 
		--Sets the cameraCFrame
					
		camera.CFrame = cameraCFrame 

	else
			
		renderStepped:Disconnect()

	end
end)