Tracking 360deg rotation with a DragDetector

So, what I’m trying to do is create a dragdetector that can track the value of its rotation.

I’m a new scripter, started maybe like 2-3 weeks ago but I know a bit about math, so I did some research into this, and found (and learnt a bit about) quaternions, gimbal lock and euler rotations.
The orientation system works only in a 180deg region and I can’t really seem to find a way around this.

For reference, I’m trying to make a pepperoni grater, for which every X deg, a pepperoni is made, etc

So, I looked into some documentation about scriptable drag detectors to see if I could make a custom rotation axis one, which I could track angles with directly using quaternions potentially.
I couldn’t find much, but I found a good link for which I tried to understand but scripting is actually hard!!

Anyways, this is as close as I’ve gotten so far, kind of works but not really…

local dragDetector = script.Parent.DragDetector
local handle = script.Parent
local lastViewFrame = CFrame.new()

local function RequestNetworkOwnershipEvent(clickedPart)
	local requestNetworkOwnershipEvent = script.Parent:WaitForChild("RemoteEvent")
	requestNetworkOwnershipEvent:FireServer(clickedPart)
end

local function rotateHandle(cosAngle)
	
	--local coshalfAngle 
	--if cosAngle >= 0 then
	--	coshalfAngle = math.sqrt((cosAngle + 1)/2)
	--else
	--	coshalfAngle = -math.sqrt((cosAngle + 1)/2)
	--end
	
	--local tanAngle = math.tan(math.acos(cosAngle))

--- Some potential work maybe with cos2x identities?? ^^^
	
local angle = cosAngle
	angle *= 0.5
	
	print(cosAngle)
	
	local quaternion = CFrame.new(handle:GetPivot().Position.X, handle:GetPivot().Position.Y, handle:GetPivot().Position.Z,
		math.sin(angle), 0, 0, math.cos(angle)
		)
	--> Quaternion
	handle:PivotTo(quaternion)
	
end

dragDetector.DragStart:Connect(function(player, ray, viewFrame, hitFrame, clickedPart)
	RequestNetworkOwnershipEvent(clickedPart)	
end)

local HandleVector = handle:GetPivot().ZVector.Unit


local function getRotatedVector(cursorRay)
	local VectorToRay = cursorRay:ClosestPoint(handle:GetPivot().Position).Unit
	local VectorsDotProduct = HandleVector:Dot(VectorToRay) -- Magntinudes are 1 so this = cosAngle
	rotateHandle(VectorsDotProduct)
end


dragDetector.DragContinue:Connect(function(player, ray, viewFrame)
	getRotatedVector(ray)
	print("test")
end)

--dragDetector:SetDragStyleFunction(function(cursorRay) --
--	getRotatedVector(cursorRay)
--end)


I get that you could probably do this without local functions and all in 1 go but this was me trying to learn a bit more about how the parameter systems work in functions and such.

So, if anyone has any ideas of how rotations can be tracked in terms of 360deg, whether if it’s with the scriptable DragDetector, or even with the inbuilt RotationAxis one, that would be amazing.

Edit:

^^ This was my thought process behind it

If you are using a custom camera CFrame, it’d probably be best to just track the mouse position after they click. I made a little uncopylocked demo here: Pepperoni Sim(Dev Forum) - Roblox. Hope this helps!

1 Like

And sorry I didn’t explain much here, the code basically just keeps track of your target and the current angle of the handle. I figured you would have more control if it was your own system. If you see the print statements, they help keep track of rotations. You could modify the code to travel in the closest direction to the desired angle and stop the stacking of rotations if you want, I just don’t exactly know what your ideal system would be.

No, it works brilliantly, and you’ve pretty much got it spot on, on what I’m trying to achieve!!

I’m just trying to really spend some time to figure out why the maths works and why you did what you did

To make it more procedural, I changed the mouse.ViewSizeX and Y to using WorldToScreenPoint from the pivot, so it becomes more local, and can be used at any pivot point of the handle

After, I’ll probably integrate this with a click detector, or potentially bring it back into a dragdetector so it only happens while the handle is dragged

For something like this I would recommend avoiding a drag detector. You’ll spend more time trying to get it to work how you want than it would be to just code your own system. You don’t need to reinvent the wheel, but there are lots of ways you could keep your control over this strong without too much code. Feel free to keep replying here, or create a new post in the future(if 14 days of inactivity pass) in case you want a little more guidance on the specifics of the math. I can also explain portions of it if there’s something specific that stands out to you. Good luck!

1 Like

Only reason why I’m wanting to use the dragdetector is so I can utilise dragcontinue, but I get what you mean :slight_smile:


	--Detect when angle of pi turns into -pi
	if math.abs(targetTheta+math.pi*2 - lastTheta) < math.abs(targetTheta-lastTheta) then
		currentTheta -= math.pi*2
		targetRotations += 1
		print("Forward:", targetRotations)


		--Detect when angle of -pi turns into pi
	elseif math.abs(targetTheta-math.pi*2 - lastTheta) < math.abs(targetTheta-lastTheta) then
		currentTheta += math.pi*2

		targetRotations -= 1
		print("Backward:", targetRotations)
	end

I understand that the part of the rotation goes from 0 to -pi, and the other from 0 to pi, and that’s what allows it to differentiate between each targetRotation
I’ve kind of got an idea of what’s going on, but as it’s more of a how you came up with this

Like everything I write, trial and error. Luckily the calcTheta math worked first try since I didn’t have to do any manipulating to it. Once I could reliably print the current angle of the mouse, I started messing around with the CFrames so the handle would follow. Making the system to have a set speed the handle traveled at was pretty straightforward, aside from keeping track of rotations. The statements you quoted are mainly about distance. They see if the angle would be closer if we added or subtracted 2pi radians(one full loop) compared to our current distance. I then made the next part(which took the most time): how do I see when the handle itself crosses the -pi to pi barrier? Modulus(%) is the remainder operator. The goal is to just see what we are at ignoring full loops. When I do mod-change, I’m reversing the math I did a few steps before. I am just checking to see if we were originally past half a rotation and now we are less than half a rotation(and vice versa). Hope this helps.

1 Like

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