[Closed] Calculate mouse direction
I’m creating a scripted manipulator with a circle gizmo that will rotate another box gizmo around a specific axis when the user clicks on it and moves the mouse. I’ve used the light roll angle manipulator example to get it up and running and it works fine up to a certain point, with the main problem being that the gizmo rotates in the opposite direction as the mouse depending on where you first click on the circle. So what I need is a general way to tell if the mouse is moving clockwise or counterclockwise in screen space around the center of the circle gizmo as the user is dragging the cursor around.
I’m going to continue working on what will probably be a really convoluted way of figuring this out, since I’m not much of a math guy. But I thought I’d check here to see if someone knows of a simple, elegant way of getting it.
Hi James,
here is a function to calculate rotation direction, relative to a point, in screenspace. It gets two subsequent mouse positions and calculates the cross product relative to the reference point in screen. Current version uses the center of viewport as reference. Then it tests result vector angle with a vector perpendicular to screen and sort the rotation direction. I hope this helps.
(
local p2PosScreenPrev = [0,0]
local p2PosScreenCurr = [0,0]
function clockWork msg ir obj faceNum shift ctrl alt =
(
local nStep = #continue
case msg of
(
#freeMove:
(
local p2ReferencePointScreen = getViewSize() / 2.0
local p3ViewDir = (inverse(getViewTM())).row3
p2PosScreenPrev = p2PosScreenCurr
p2PosScreenCurr = mouse.pos
local p2Vec_1 = p2PosScreenPrev - p2ReferencePointScreen
local p2Vec_2 = p2PosScreenCurr - p2ReferencePointScreen
local p3Cross = cross [p2Vec_1.x, p2Vec_1.y, 0] [p2Vec_2.x, p2Vec_2.y, 0]
if ((dot p3Cross [0,0,1]) >= 0) then
format "Rotating Clockwise
"
else
format "Rotating Counterclockwise
"
nStep = #continue
)
#mouseAbort:
(
nStep = #stop
)
)
return nStep
)
mouseTrack trackCallback:clockWork
)
- Enrico
Yeah, that did the trick. Here’s a quick example of how I’m using it (sort of, I’m not actually creating and deleting boxes).
plugin simpleManipulator rotationTest
name:"Rotation Test"
invisible:true
(
local unSelClr = colorMan.getColor #manipulatorsActive
local selClr = colorMan.getColor #manipulatorsSelected
local curRot
local lastM = [0,0]
local objP =[0,0]
local tempObj
fn mapWorldToScreen pos =
(
width=gw.getWinSizeX()
height=gw.getWinSizeY()
thePos = pos * viewport.getTM()
screenOrigin = mapScreenToView [0,0] (thePos.z) [width,height]
worldSize = screenOrigin*2
xAspect = width/(abs worldSize.x)
yAspect = height/(abs worldSize.y)
screenPos=point2 (xAspect *(thePos.x-screenOrigin.x)) (-(yAspect*(thePos.y-screenOrigin.y)))
if (screenPos.x) < 0 then (screenPos.x=0)
if (screenPos.y) < 0 then (screenPos.y=0)
screenPos.x = screenPos.x as integer
screenPos.y = screenPos.y as integer
screenPos
)
fn normalizeAngle a =
(
mod a 360
)
on canManipulateNode target do
(
(superClassOf target == helper)
)
on updateGizmos do
(
local giz
this.clearGizmos()
-- gizmo circle
giz = manip.makeCircle [0,0,0] 10 28
giz.transform (matrix3 [0,0,1] [0,1,0] [1,0,0] [0,0,0])
this.addGizmoShape giz 16 unSelClr selClr
if isValidNode tempObj then
(
tempObj.name + " [X Rotation: " + (tempObj.rotation.controller[1].value as string) + "]"
)
else
(
""
)
)
on mouseDown m which do
(
if not isValidNode tempOb then
(
tempObj = box name:"tempRotationObject" pos:node.pos wirecolor:red
)
lastM = m
objP = mapWorldToScreen node.pos
if keyboard.shiftPressed then
(
curRot = 0
)
else
(
curRot = normalizeAngle tempObj.rotation.controller[1].value
)
tempObj.rotation.controller[1].value = curRot
)
on mouseMove m which do
(
m = m
p2Vec_1 = lastM - objP
p2Vec_2 = m - objP
p3Vec_1 = [p2Vec_1.x, p2Vec_1.y, 0]
p3Vec_2 = [p2Vec_2.x, p2Vec_2.y, 0]
p3Cross = cross p3Vec_1 p3Vec_2
rotVal = distance p3Vec_1 p3Vec_2
if ((dot p3Cross [0,0,1]) >= 0) then
(
curRot += rotVal
)
else
(
curRot -= rotVal
)
tempObj.rotation.controller[1].value = curRot
lastM = m
)
on mouseUp m which do
(
if isValidNode tempObj then
(
delete tempObj
)
)
)
select (point())
manipulateMode = true