Inaccurate Rotation with Custom ArcHandles

I have got a custom system made of several HandleAdornments which allows me to make my custom archandle look similar to Studio’s own orientator tool. However there is an issue with rotating the object based on the movement of the mouse whilst the handle is dragged.

Context

Here’s the main component of the draggable handle part below

local function LinkOrientHandle(handle: SphereHandleAdornment, dragMethod: (number)->(), axis: Enum.Axis)
	local pairedAxes =
		{
			Enum.Axis:FromValue((axis.Value + 1) % 3),
			Enum.Axis:FromValue((axis.Value - 1) % 3)
		}
	local axisFilter = (Vector3.FromAxis(pairedAxes[1]) + Vector3.FromAxis(pairedAxes[2]))
	
	handle.MouseButton1Down:Connect(function()
		local onMove : RBXScriptConnection
		local mouseOrigin = mouse.Origin
		
		
		local lastAngle = 0
		onMove = mouse.Move:Connect(function()
			local adornCF = handle.Adornee:GetPivot()
			local mousePlane : Vector3 = cfe.axisIntersect(adornCF:ToObjectSpace(mouse.Origin), axis)
			
			
			local currentAngle
			if pairedAxes[1].Value > pairedAxes[2].Value then
				currentAngle = math.atan2(mousePlane[pairedAxes[1].Name], mousePlane[pairedAxes[2].Name])
			else
				currentAngle = math.atan2(mousePlane[pairedAxes[2].Name], mousePlane[pairedAxes[1].Name])
			end
			
			local angularChange = (currentAngle - lastAngle + math.pi) % (2 * math.pi) - math.pi
			lastAngle += angularChange
			
			dragMethod(angularChange)
		end)
		mouse.Button1Up:Once(function()
			onMove:Disconnect()
		end)
	end)
end

For context, cfe reffers to a module script (CFrame Extentions), the method mentioned above .axisIntersect is of such:

cfExtentions.axisIntersect = function(line: CFrame, axis: Enum.Axis)
	local t = - line.Position[axis.Name] / line.LookVector[axis.Name]
	return line.Position + t * line.LookVector
end

For this context, it is used to figure out where the mouse would intersect with the plane perpendicular to the rotation axis, it is used to find the angle between the object and mouse.

The usage of the LinkOrientHandle() procedure is as such:

			LinkOrientHandle(uniqueHandle, function(change)
				local startPivot = uniqueHandle.Adornee:GetPivot()
				local orientalChange = {0, 0, 0}
				orientalChange[inx] = -change / math.pi
				uniqueHandle.Adornee:PivotTo(startPivot * CFrame.fromEulerAnglesXYZ(table.unpack(orientalChange)))
			end, axis)

inx: The index of the current axis (x axis: 1, y axis: 2, z axis: 3)
change: The change in radian angle in the last frame.
uniqueHandle.Adornee: The basepart or model that is being orientated.

Problem

There seem to be two major problems with this, which are the following:

Over-rotation

When the mouse moves, it seems that the change in angle on the plane is overstated, causing for the model to rotate far more than intended. This effect seems to act stronger with the distance between mouse-plane intersect and object center.

Rotation Opposition

One or Two of the Three axes (depending on sign multiplier) rotate opposite of their intended direction of rotation.

As a conclusion, it’s safe to assume that this problem is coming from the usage of arctan2, yet changes to the order don’t seem to fix things. If you need extra source code or context then do ask!

Hey there,

Regarding the issues you’re facing, I’d like to offer a few suggestions that might help:

Over-Rotation

The over-rotation you’re experiencing is likely due to how the angularChange is calculated and applied in relation to mouse movement. To address this, you might want to introduce a damping factor that can help normalize the rotation based on the distance between the mouse intersection and the object’s pivot. This could help stabilize the rotation speed relative to the distance, preventing the model from spinning out of control.

Rotation Opposition

For the rotation opposition issue, it sounds like it could be tied to how the atan2 function is being used. I recommend double-checking the order of the parameters you’re passing into atan2, ensuring that they reflect the intended axes correctly. It might also be beneficial to visualize the axes and the resulting angle changes to diagnose the directionality issues more effectively.

As you debug, consider logging the values of currentAngle, lastAngle, and angularChange to see how they change in real-time. This can provide invaluable insight into where things might be going awry.

If you need further assistance or additional code snippets to clarify any concepts ill be happy to help.

Testing out the z-axis rotation again, the results are of reasonable magnitude of rotation but in opposite direction. This is understandable since I’m actually changing it by -change / math.pi, the division of math.pi as just a constant to try and control the rotation a bit more, and -change since initually other axes were oppositely before the sign inversal.
image

Whilst z-axis spins not at perfect magnitude, probably due to the pi division, the y-axis spins in the write direction whilst being very sluggish.
image

And the x-axis acts similar to z-axis. The rotation is that the same magnitude with the both axes and they’re both in the opposite direction.

I’ll be looking into the atan2 usage as that is the most likely to be the source of the rotation direction problem, although the y-axis sluggish movement problem is unexpected.

EDIT:
By changing change usage from -change/math.pi to just change, it seems to now almost work on the x-axis atleast, but there is a weird snapping-like problem where at very small mouse movements, the rotated object behaviours “glitchly” like it’s constantly rotating between two points.
image
EDIT 2:
It’s also important to know that here’s the recorded movements with even the smallest of mouse movements. These may seem small until you consider that these are in radians, not degrees.
image

Just an update on this, I have resolved this issue.

The problem was that I was rotating it by the Angle Delta, but this Angle Delta is relative to the model. Once the model is rotated, this Angle Delta will be relative to the new angle and the old angle of the model, which is why it would alter back and forwards even with minimal mouse rotation.

The solution was simply to rotate it by the CurrentAngle and not Delta Angle.

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