49582f9d |
1 | // Copyright (c) 2016-2019 OPEN CASCADE SAS |
2 | // |
3 | // This file is part of Open CASCADE Technology software library. |
4 | // |
5 | // This library is free software; you can redistribute it and/or modify it under |
6 | // the terms of the GNU Lesser General Public License version 2.1 as published |
7 | // by the Free Software Foundation, with special exception defined in the file |
8 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
9 | // distribution for complete text of the license and disclaimer of any warranty. |
10 | // |
11 | // Alternatively, this file may be used under the terms of Open CASCADE |
12 | // commercial license or contractual agreement. |
13 | |
14 | #include "AIS_ViewController.hxx" |
15 | |
2108d9a2 |
16 | #include <AIS_AnimationCamera.hxx> |
49582f9d |
17 | #include <AIS_InteractiveContext.hxx> |
18 | #include <AIS_Manipulator.hxx> |
19 | #include <AIS_Point.hxx> |
20 | #include <AIS_RubberBand.hxx> |
b40cdc2b |
21 | #include <AIS_XRTrackedDevice.hxx> |
22 | #include <Aspect_XRSession.hxx> |
49582f9d |
23 | #include <Aspect_Grid.hxx> |
24 | #include <Geom_CartesianPoint.hxx> |
b40cdc2b |
25 | #include <Graphic3d_ArrayOfSegments.hxx> |
26 | #include <Graphic3d_Texture2Dmanual.hxx> |
49582f9d |
27 | #include <Message.hxx> |
28 | #include <Message_Messenger.hxx> |
29 | #include <gp_Quaternion.hxx> |
30 | #include <V3d_View.hxx> |
d6fbb2ab |
31 | #include <WNT_HIDSpaceMouse.hxx> |
49582f9d |
32 | |
33 | // ======================================================================= |
34 | // function : AIS_ViewController |
35 | // purpose : |
36 | // ======================================================================= |
37 | AIS_ViewController::AIS_ViewController() |
38 | : myLastEventsTime (0.0), |
39 | myToAskNextFrame (false), |
40 | myMinCamDistance (1.0), |
41 | myRotationMode (AIS_RotationMode_BndBoxActive), |
42 | myNavigationMode (AIS_NavigationMode_Orbit), |
43 | myMouseAccel (1.0f), |
44 | myOrbitAccel (1.0f), |
45 | myToShowPanAnchorPoint (true), |
46 | myToShowRotateCenter (true), |
47 | myToLockOrbitZUp (false), |
48 | myToInvertPitch (false), |
49 | myToAllowTouchZRotation(false), |
50 | myToAllowRotation (true), |
51 | myToAllowPanning (true), |
52 | myToAllowZooming (true), |
53 | myToAllowZFocus (true), |
54 | myToAllowHighlight (true), |
55 | myToAllowDragging (true), |
9460f8c0 |
56 | myToStickToRayOnZoom (true), |
57 | myToStickToRayOnRotation (true), |
49582f9d |
58 | // |
59 | myWalkSpeedAbsolute (1.5f), |
60 | myWalkSpeedRelative (0.1f), |
61 | myThrustSpeed (0.0f), |
62 | myHasThrust (false), |
63 | // |
2108d9a2 |
64 | myViewAnimation (new AIS_AnimationCamera ("AIS_ViewController_ViewAnimation", Handle(V3d_View)())), |
49582f9d |
65 | myPrevMoveTo (-1, -1), |
66 | myHasHlrOnBeforeRotation (false), |
67 | // |
b40cdc2b |
68 | myXRPrsDevices (0, 0), |
69 | myXRLaserTeleColor (Quantity_NOC_GREEN), |
70 | myXRLaserPickColor (Quantity_NOC_BLUE), |
71 | myXRLastTeleportHand(Aspect_XRTrackedDeviceRole_Other), |
72 | myXRLastPickingHand (Aspect_XRTrackedDeviceRole_Other), |
73 | myXRLastPickDepthLeft (Precision::Infinite()), |
74 | myXRLastPickDepthRight(Precision::Infinite()), |
75 | myXRTurnAngle (M_PI_4), |
76 | myToDisplayXRAuxDevices (false), |
77 | myToDisplayXRHands (true), |
78 | // |
49582f9d |
79 | myMouseClickThreshold (3.0), |
80 | myMouseDoubleClickInt (0.4), |
81 | myScrollZoomRatio (15.0f), |
82 | myMouseActiveGesture (AIS_MouseGesture_NONE), |
83 | myMouseActiveIdleRotation (false), |
84 | myMouseClickCounter (0), |
85 | myMousePressed (Aspect_VKeyMouse_NONE), |
86 | myMouseModifiers (Aspect_VKeyFlags_NONE), |
87 | myMouseSingleButton (-1), |
215dd331 |
88 | myMouseStopDragOnUnclick (false), |
49582f9d |
89 | // |
90 | myTouchToleranceScale (1.0f), |
91 | myTouchRotationThresholdPx (6.0f), |
92 | myTouchZRotationThreshold (float(2.0 * M_PI / 180.0)), |
93 | myTouchPanThresholdPx (4.0f), |
94 | myTouchZoomThresholdPx (6.0f), |
95 | myTouchZoomRatio (0.13f), |
96 | // |
97 | myNbTouchesLast (0), |
98 | myUpdateStartPointPan (true), |
99 | myUpdateStartPointRot (true), |
100 | myUpdateStartPointZRot (true), |
101 | // |
d6fbb2ab |
102 | my3dMouseNoRotate (false, false, false), |
103 | my3dMouseToReverse (true, false, false), |
104 | my3dMouseAccelTrans (2.0f), |
105 | my3dMouseAccelRotate (4.0f), |
106 | my3dMouseIsQuadric (true), |
107 | // |
49582f9d |
108 | myPanPnt3d (Precision::Infinite(), 0.0, 0.0) |
109 | { |
d6fbb2ab |
110 | memset(my3dMouseButtonState, 0, sizeof(my3dMouseButtonState)); |
49582f9d |
111 | myEventTimer.Start(); |
d6fbb2ab |
112 | myViewAnimation->SetOwnDuration (0.5); |
49582f9d |
113 | |
114 | myAnchorPointPrs1 = new AIS_Point (new Geom_CartesianPoint (0.0, 0.0, 0.0)); |
115 | myAnchorPointPrs1->SetZLayer (Graphic3d_ZLayerId_Top); |
116 | myAnchorPointPrs1->SetMutable (true); |
117 | |
118 | myAnchorPointPrs2 = new AIS_Point (new Geom_CartesianPoint (0.0, 0.0, 0.0)); |
119 | myAnchorPointPrs2->SetZLayer (Graphic3d_ZLayerId_Topmost); |
120 | myAnchorPointPrs2->SetMutable (true); |
121 | |
122 | myRubberBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE, 0.4, 1.0); |
123 | myRubberBand->SetZLayer (Graphic3d_ZLayerId_TopOSD); |
124 | myRubberBand->SetTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_UPPER)); |
125 | myRubberBand->SetDisplayMode (0); |
126 | myRubberBand->SetMutable (true); |
127 | |
128 | myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton, AIS_MouseGesture_RotateOrbit); |
129 | myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_CTRL, AIS_MouseGesture_Zoom); |
130 | myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_SHIFT, AIS_MouseGesture_Pan); |
131 | myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton | Aspect_VKeyFlags_ALT, AIS_MouseGesture_SelectRectangle); |
132 | |
133 | myMouseGestureMap.Bind (Aspect_VKeyMouse_RightButton, AIS_MouseGesture_Zoom); |
134 | myMouseGestureMap.Bind (Aspect_VKeyMouse_RightButton | Aspect_VKeyFlags_CTRL, AIS_MouseGesture_RotateOrbit); |
135 | |
136 | myMouseGestureMap.Bind (Aspect_VKeyMouse_MiddleButton, AIS_MouseGesture_Pan); |
137 | myMouseGestureMap.Bind (Aspect_VKeyMouse_MiddleButton | Aspect_VKeyFlags_CTRL, AIS_MouseGesture_Pan); |
b40cdc2b |
138 | |
139 | myXRTeleportHaptic.Duration = 3600.0f; |
140 | myXRTeleportHaptic.Frequency = 0.1f; |
141 | myXRTeleportHaptic.Amplitude = 0.2f; |
142 | |
143 | myXRPickingHaptic.Duration = 0.1f; |
144 | myXRPickingHaptic.Frequency = 4.0f; |
145 | myXRPickingHaptic.Amplitude = 0.1f; |
146 | |
147 | myXRSelectHaptic.Duration = 0.2f; |
148 | myXRSelectHaptic.Frequency = 4.0f; |
149 | myXRSelectHaptic.Amplitude = 0.5f; |
49582f9d |
150 | } |
151 | |
00ea7f26 |
152 | // ======================================================================= |
153 | // function : ~AIS_ViewController |
154 | // purpose : |
155 | // ======================================================================= |
156 | AIS_ViewController::~AIS_ViewController() |
157 | { |
158 | // |
159 | } |
160 | |
49582f9d |
161 | // ======================================================================= |
162 | // function : ResetViewInput |
163 | // purpose : |
164 | // ======================================================================= |
165 | void AIS_ViewController::ResetViewInput() |
166 | { |
167 | myKeys.Reset(); |
168 | myMousePressed = Aspect_VKeyMouse_NONE; |
169 | myMouseModifiers = Aspect_VKeyFlags_NONE; |
170 | myMouseSingleButton = -1; |
171 | myUI.Dragging.ToAbort = true; |
172 | myMouseActiveGesture = AIS_MouseGesture_NONE; |
173 | myMouseClickTimer.Stop(); |
174 | myMouseClickCounter = 0; |
175 | } |
176 | |
177 | // ======================================================================= |
178 | // function : FlushViewEvents |
179 | // purpose : |
180 | // ======================================================================= |
181 | void AIS_ViewController::FlushViewEvents (const Handle(AIS_InteractiveContext)& theCtx, |
182 | const Handle(V3d_View)& theView, |
183 | Standard_Boolean theToHandle) |
184 | { |
185 | flushBuffers (theCtx, theView); |
186 | flushGestures(theCtx, theView); |
187 | if (theToHandle) |
188 | { |
189 | HandleViewEvents (theCtx, theView); |
190 | } |
191 | } |
192 | |
193 | // ======================================================================= |
194 | // function : flushBuffers |
195 | // purpose : |
196 | // ======================================================================= |
197 | void AIS_ViewController::flushBuffers (const Handle(AIS_InteractiveContext)& , |
198 | const Handle(V3d_View)& ) |
199 | { |
200 | myToAskNextFrame = false; |
201 | |
202 | myGL.IsNewGesture = myUI.IsNewGesture; |
203 | myUI.IsNewGesture = false; |
204 | |
205 | myGL.ZoomActions.Clear(); |
206 | myGL.ZoomActions.Append (myUI.ZoomActions); |
207 | myUI.ZoomActions.Clear(); |
208 | |
209 | myGL.Orientation.ToFitAll = myUI.Orientation.ToFitAll; |
210 | myUI.Orientation.ToFitAll = false; |
211 | if (myUI.Orientation.ToSetViewOrient) |
212 | { |
213 | myUI.Orientation.ToSetViewOrient = false; |
214 | myGL.Orientation.ToSetViewOrient = true; |
215 | myGL.Orientation.ViewOrient = myUI.Orientation.ViewOrient; |
216 | } |
217 | |
218 | if (myUI.MoveTo.ToHilight) |
219 | { |
220 | myUI.MoveTo.ToHilight = false; |
221 | myGL.MoveTo.ToHilight = true; |
222 | myGL.MoveTo.Point = myUI.MoveTo.Point; |
223 | } |
224 | |
225 | { |
226 | myGL.Selection.Tool = myUI.Selection.Tool; |
227 | myGL.Selection.IsXOR = myUI.Selection.IsXOR; |
228 | myGL.Selection.Points = myUI.Selection.Points; |
229 | myUI.Selection.IsXOR = false; |
230 | if (myUI.Selection.Tool == AIS_ViewSelectionTool_Picking) |
231 | { |
232 | myUI.Selection.Points.Clear(); |
233 | } |
234 | } |
235 | |
236 | if (myUI.Selection.ToApplyTool) |
237 | { |
238 | myGL.Selection.ToApplyTool = true; |
239 | myUI.Selection.ToApplyTool = false; |
240 | myUI.Selection.Points.Clear(); |
241 | } |
242 | |
243 | if (myUI.Panning.ToStart) |
244 | { |
245 | myUI.Panning.ToStart = false; |
246 | myGL.Panning.ToStart = true; |
247 | myGL.Panning.PointStart = myUI.Panning.PointStart; |
248 | } |
249 | |
250 | if (myUI.Panning.ToPan) |
251 | { |
252 | myUI.Panning.ToPan = false; |
253 | myGL.Panning.ToPan = true; |
254 | myGL.Panning.Delta = myUI.Panning.Delta; |
255 | } |
256 | |
257 | if (myUI.Dragging.ToAbort) |
258 | { |
259 | myUI.Dragging.ToAbort = false; |
260 | myGL.Dragging.ToAbort = true; |
261 | } |
262 | else if (myUI.Dragging.ToStop) |
263 | { |
264 | myUI.Dragging.ToStop = false; |
265 | myGL.Dragging.ToStop = true; |
266 | } |
267 | else if (myUI.Dragging.ToStart) |
268 | { |
269 | myUI.Dragging.ToStart = false; |
270 | myGL.Dragging.ToStart = true; |
271 | myGL.Dragging.PointStart = myUI.Dragging.PointStart; |
272 | } |
273 | myGL.Dragging.PointTo = myUI.Dragging.PointTo; |
274 | |
275 | if (myUI.OrbitRotation.ToStart) |
276 | { |
277 | myUI.OrbitRotation.ToStart = false; |
278 | myGL.OrbitRotation.ToStart = true; |
279 | myGL.OrbitRotation.PointStart = myUI.OrbitRotation.PointStart; |
280 | } |
281 | |
282 | if (myUI.OrbitRotation.ToRotate) |
283 | { |
284 | myUI.OrbitRotation.ToRotate = false; |
285 | myGL.OrbitRotation.ToRotate = true; |
286 | myGL.OrbitRotation.PointTo = myUI.OrbitRotation.PointTo; |
287 | } |
288 | |
289 | if (myUI.ViewRotation.ToStart) |
290 | { |
291 | myUI.ViewRotation.ToStart = false; |
292 | myGL.ViewRotation.ToStart = true; |
293 | myGL.ViewRotation.PointStart = myUI.ViewRotation.PointStart; |
294 | } |
295 | |
296 | if (myUI.ViewRotation.ToRotate) |
297 | { |
298 | myUI.ViewRotation.ToRotate = false; |
299 | myGL.ViewRotation.ToRotate = true; |
300 | myGL.ViewRotation.PointTo = myUI.ViewRotation.PointTo; |
301 | } |
302 | |
303 | if (myUI.ZRotate.ToRotate) |
304 | { |
305 | myGL.ZRotate = myUI.ZRotate; |
306 | myUI.ZRotate.ToRotate = false; |
307 | } |
308 | } |
309 | |
310 | // ======================================================================= |
311 | // function : flushGestures |
312 | // purpose : |
313 | // ======================================================================= |
314 | void AIS_ViewController::flushGestures (const Handle(AIS_InteractiveContext)& , |
315 | const Handle(V3d_View)& theView) |
316 | { |
317 | const Standard_Real aTolScale = myTouchToleranceScale; |
318 | const Standard_Integer aTouchNb = myTouchPoints.Extent(); |
319 | if (myNbTouchesLast != aTouchNb) |
320 | { |
321 | myNbTouchesLast = aTouchNb; |
322 | myGL.IsNewGesture = true; |
323 | } |
324 | if (aTouchNb == 1) // touch |
325 | { |
326 | Aspect_Touch& aTouch = myTouchPoints.ChangeFromIndex (1); |
327 | if (myUpdateStartPointRot) |
328 | { |
329 | // skip rotation if have active dragged object |
330 | if (myNavigationMode == AIS_NavigationMode_Orbit) |
331 | { |
332 | myGL.OrbitRotation.ToStart = true; |
333 | myGL.OrbitRotation.PointStart = myStartRotCoord; |
334 | } |
335 | else |
336 | { |
337 | myGL.ViewRotation.ToStart = true; |
338 | myGL.ViewRotation.PointStart = myStartRotCoord; |
339 | } |
340 | |
341 | myUpdateStartPointRot = false; |
342 | theView->Invalidate(); |
343 | } |
344 | |
345 | // rotation |
346 | const Standard_Real aRotTouchTol = !aTouch.IsPreciseDevice |
347 | ? aTolScale * myTouchRotationThresholdPx |
348 | : gp::Resolution(); |
349 | if (Abs (aTouch.Delta().x()) + Abs(aTouch.Delta().y()) > aRotTouchTol) |
350 | { |
351 | const Standard_Real aRotAccel = myNavigationMode == AIS_NavigationMode_FirstPersonWalk ? myMouseAccel : myOrbitAccel; |
352 | if (myNavigationMode == AIS_NavigationMode_Orbit) |
353 | { |
354 | const Graphic3d_Vec2d aRotDelta = aTouch.To - myGL.OrbitRotation.PointStart; |
355 | myGL.OrbitRotation.ToRotate = true; |
356 | myGL.OrbitRotation.PointTo = myGL.OrbitRotation.PointStart + aRotDelta * aRotAccel; |
357 | myGL.Dragging.PointTo.SetValues ((int )aTouch.To.x(), (int )aTouch.To.y()); |
358 | } |
359 | else |
360 | { |
361 | const Graphic3d_Vec2d aRotDelta = aTouch.To - myGL.ViewRotation.PointStart; |
362 | myGL.ViewRotation.ToRotate = true; |
363 | myGL.ViewRotation.PointTo = myGL.ViewRotation.PointStart + aRotDelta * aRotAccel; |
364 | myGL.Dragging.PointTo.SetValues ((int )aTouch.To.x(), (int )aTouch.To.y()); |
365 | } |
366 | |
367 | aTouch.From = aTouch.To; |
368 | } |
369 | } |
370 | else if (aTouchNb == 2) // pinch |
371 | { |
372 | Aspect_Touch& aFirstTouch = myTouchPoints.ChangeFromIndex (1); |
373 | Aspect_Touch& aLastTouch = myTouchPoints.ChangeFromIndex (2); |
374 | const Graphic3d_Vec2d aFrom[2] = { aFirstTouch.From, aLastTouch.From }; |
375 | const Graphic3d_Vec2d aTo[2] = { aFirstTouch.To, aLastTouch.To }; |
376 | |
377 | Graphic3d_Vec2d aPinchCenterStart ((aFrom[0].x() + aFrom[1].x()) / 2.0, |
378 | (aFrom[0].y() + aFrom[1].y()) / 2.0); |
379 | |
380 | Standard_Real aPinchCenterXEnd = (aTo[0].x() + aTo[1].x()) / 2.0; |
381 | Standard_Real aPinchCenterYEnd = (aTo[0].y() + aTo[1].y()) / 2.0; |
382 | |
383 | Standard_Real aPinchCenterXDev = aPinchCenterXEnd - aPinchCenterStart.x(); |
384 | Standard_Real aPinchCenterYDev = aPinchCenterYEnd - aPinchCenterStart.y(); |
385 | |
386 | Standard_Real aStartSize = (aFrom[0] - aFrom[1]).Modulus(); |
387 | Standard_Real anEndSize = ( aTo[0] - aTo[1]).Modulus(); |
388 | |
389 | Standard_Real aDeltaSize = anEndSize - aStartSize; |
390 | |
391 | bool anIsClearDev = false; |
392 | |
393 | if (myToAllowTouchZRotation) |
394 | { |
395 | Standard_Real A1 = aFrom[0].y() - aFrom[1].y(); |
396 | Standard_Real B1 = aFrom[1].x() - aFrom[0].x(); |
397 | |
398 | Standard_Real A2 = aTo[0].y() - aTo[1].y(); |
399 | Standard_Real B2 = aTo[1].x() - aTo[0].x(); |
400 | |
401 | Standard_Real aRotAngle = 0.0; |
402 | |
403 | Standard_Real aDenomenator = A1*A2 + B1*B2; |
404 | if (aDenomenator <= Precision::Confusion()) |
405 | { |
406 | aRotAngle = 0.0; |
407 | } |
408 | else |
409 | { |
410 | Standard_Real aNumerator = A1*B2 - A2*B1; |
411 | aRotAngle = ATan (aNumerator / aDenomenator); |
412 | } |
413 | |
414 | if (Abs(aRotAngle) > Standard_Real(myTouchZRotationThreshold)) |
415 | { |
416 | myGL.ZRotate.ToRotate = true; |
417 | myGL.ZRotate.Angle = aRotAngle; |
418 | anIsClearDev = true; |
419 | } |
420 | } |
421 | |
422 | if (Abs(aDeltaSize) > aTolScale * myTouchZoomThresholdPx) |
423 | { |
424 | // zoom |
425 | aDeltaSize *= Standard_Real(myTouchZoomRatio); |
426 | Aspect_ScrollDelta aParams (Graphic3d_Vec2i (aPinchCenterStart), aDeltaSize); |
427 | myGL.ZoomActions.Append (aParams); |
428 | anIsClearDev = true; |
429 | } |
430 | |
431 | const Standard_Real aPanTouchTol = !aFirstTouch.IsPreciseDevice |
432 | ? aTolScale * myTouchPanThresholdPx |
433 | : gp::Resolution(); |
434 | if (Abs(aPinchCenterXDev) + Abs(aPinchCenterYDev) > aPanTouchTol) |
435 | { |
436 | // pan |
437 | if (myUpdateStartPointPan) |
438 | { |
439 | myGL.Panning.ToStart = true; |
440 | myGL.Panning.PointStart = Graphic3d_Vec2i (myStartPanCoord); |
441 | myUpdateStartPointPan = false; |
442 | theView->Invalidate(); |
443 | } |
444 | |
445 | myGL.Panning.ToPan = true; |
446 | myGL.Panning.Delta.x() = int( aPinchCenterXDev); |
447 | myGL.Panning.Delta.y() = int(-aPinchCenterYDev); |
448 | anIsClearDev = true; |
449 | } |
450 | |
451 | if (anIsClearDev) |
452 | { |
453 | aFirstTouch.From = aFirstTouch.To; |
454 | aLastTouch .From = aLastTouch.To; |
455 | } |
456 | } |
457 | } |
458 | |
459 | // ======================================================================= |
460 | // function : UpdateViewOrientation |
461 | // purpose : |
462 | // ======================================================================= |
463 | void AIS_ViewController::UpdateViewOrientation (V3d_TypeOfOrientation theOrientation, |
464 | bool theToFitAll) |
465 | { |
466 | myUI.Orientation.ToFitAll = theToFitAll; |
467 | myUI.Orientation.ToSetViewOrient = true; |
468 | myUI.Orientation.ViewOrient = theOrientation; |
469 | } |
470 | |
471 | // ======================================================================= |
472 | // function : SelectInViewer |
473 | // purpose : |
474 | // ======================================================================= |
475 | void AIS_ViewController::SelectInViewer (const Graphic3d_Vec2i& thePnt, |
476 | const bool theIsXOR) |
477 | { |
478 | if (myUI.Selection.Tool != AIS_ViewSelectionTool_Picking) |
479 | { |
480 | myUI.Selection.Tool = AIS_ViewSelectionTool_Picking; |
481 | myUI.Selection.Points.Clear(); |
482 | } |
483 | |
484 | myUI.Selection.IsXOR = theIsXOR; |
485 | myUI.Selection.Points.Append (thePnt); |
486 | } |
487 | |
488 | // ======================================================================= |
489 | // function : SelectInViewer |
490 | // purpose : |
491 | // ======================================================================= |
492 | void AIS_ViewController::SelectInViewer (const NCollection_Sequence<Graphic3d_Vec2i>& thePnts, |
493 | const bool theIsXOR) |
494 | { |
495 | myUI.Selection.IsXOR = theIsXOR; |
496 | myUI.Selection.Points = thePnts; |
497 | myUI.Selection.ToApplyTool = true; |
498 | if (thePnts.Length() == 1) |
499 | { |
500 | myUI.Selection.Tool = AIS_ViewSelectionTool_Picking; |
501 | } |
502 | else if (thePnts.Length() == 2) |
503 | { |
504 | myUI.Selection.Tool = AIS_ViewSelectionTool_RubberBand; |
505 | } |
506 | else |
507 | { |
508 | myUI.Selection.Tool = AIS_ViewSelectionTool_Polygon; |
509 | } |
510 | } |
511 | |
512 | // ======================================================================= |
513 | // function : UpdateRubberBand |
514 | // purpose : |
515 | // ======================================================================= |
516 | void AIS_ViewController::UpdateRubberBand (const Graphic3d_Vec2i& thePntFrom, |
517 | const Graphic3d_Vec2i& thePntTo, |
518 | const bool theIsXOR) |
519 | { |
520 | myUI.Selection.Tool = AIS_ViewSelectionTool_RubberBand; |
521 | myUI.Selection.IsXOR = theIsXOR; |
522 | myUI.Selection.Points.Clear(); |
523 | myUI.Selection.Points.Append (thePntFrom); |
524 | myUI.Selection.Points.Append (thePntTo); |
525 | } |
526 | |
527 | // ======================================================================= |
528 | // function : UpdatePolySelection |
529 | // purpose : |
530 | // ======================================================================= |
531 | void AIS_ViewController::UpdatePolySelection (const Graphic3d_Vec2i& thePnt, |
532 | bool theToAppend) |
533 | { |
534 | if (myUI.Selection.Tool != AIS_ViewSelectionTool_Polygon) |
535 | { |
536 | myUI.Selection.Tool = AIS_ViewSelectionTool_Polygon; |
537 | myUI.Selection.Points.Clear(); |
538 | } |
539 | |
540 | if (myUI.Selection.Points.IsEmpty()) |
541 | { |
542 | myUI.Selection.Points.Append (thePnt); |
543 | } |
544 | else if (theToAppend |
545 | && myUI.Selection.Points.Last() != thePnt) |
546 | { |
547 | myUI.Selection.Points.Append (thePnt); |
548 | } |
549 | else |
550 | { |
551 | myUI.Selection.Points.ChangeLast() = thePnt; |
552 | } |
553 | } |
554 | |
555 | // ======================================================================= |
556 | // function : UpdateZoom |
557 | // purpose : |
558 | // ======================================================================= |
559 | bool AIS_ViewController::UpdateZoom (const Aspect_ScrollDelta& theDelta) |
560 | { |
561 | if (!myUI.ZoomActions.IsEmpty()) |
562 | { |
563 | if (myUI.ZoomActions.ChangeLast().Point == theDelta.Point) |
564 | { |
565 | myUI.ZoomActions.ChangeLast().Delta += theDelta.Delta; |
566 | return false; |
567 | } |
568 | } |
569 | |
570 | myUI.ZoomActions.Append (theDelta); |
571 | return true; |
572 | } |
573 | |
574 | // ======================================================================= |
575 | // function : UpdateZRotation |
576 | // purpose : |
577 | // ======================================================================= |
578 | bool AIS_ViewController::UpdateZRotation (double theAngle) |
579 | { |
580 | if (!ToAllowTouchZRotation()) |
581 | { |
582 | return false; |
583 | } |
584 | |
585 | myUI.ZRotate.Angle = myUI.ZRotate.ToRotate |
586 | ? myUI.ZRotate.Angle + theAngle |
587 | : theAngle; |
588 | if (myUI.ZRotate.ToRotate) |
589 | { |
590 | return false; |
591 | } |
592 | myUI.ZRotate.ToRotate = true; |
593 | return true; |
594 | } |
595 | |
596 | // ======================================================================= |
597 | // function : UpdateMouseScroll |
598 | // purpose : |
599 | // ======================================================================= |
600 | bool AIS_ViewController::UpdateMouseScroll (const Aspect_ScrollDelta& theDelta) |
601 | { |
602 | Aspect_ScrollDelta aDelta = theDelta; |
603 | aDelta.Delta *= myScrollZoomRatio; |
604 | return UpdateZoom (aDelta); |
605 | } |
606 | |
607 | // ======================================================================= |
608 | // function : UpdateMouseClick |
609 | // purpose : |
610 | // ======================================================================= |
611 | bool AIS_ViewController::UpdateMouseClick (const Graphic3d_Vec2i& thePoint, |
612 | Aspect_VKeyMouse theButton, |
613 | Aspect_VKeyFlags theModifiers, |
614 | bool theIsDoubleClick) |
615 | { |
616 | (void )theIsDoubleClick; |
617 | if (theButton == Aspect_VKeyMouse_LeftButton) |
618 | { |
619 | SelectInViewer (thePoint, (theModifiers & Aspect_VKeyFlags_SHIFT) != 0); |
620 | return true; |
621 | } |
622 | return false; |
623 | } |
624 | |
625 | // ======================================================================= |
626 | // function : UpdateMouseButtons |
627 | // purpose : |
628 | // ======================================================================= |
629 | bool AIS_ViewController::UpdateMouseButtons (const Graphic3d_Vec2i& thePoint, |
630 | Aspect_VKeyMouse theButtons, |
631 | Aspect_VKeyFlags theModifiers, |
632 | bool theIsEmulated) |
633 | { |
634 | bool toUpdateView = false; |
635 | const double aTolClick = (theIsEmulated ? myTouchToleranceScale : 1.0) * myMouseClickThreshold; |
636 | if (theButtons == Aspect_VKeyMouse_NONE |
637 | && myMouseSingleButton > 0) |
638 | { |
639 | const Graphic3d_Vec2i aDelta = thePoint - myMousePressPoint; |
640 | if (double(aDelta.cwiseAbs().maxComp()) < aTolClick) |
641 | { |
642 | ++myMouseClickCounter; |
643 | const bool isDoubleClick = myMouseClickCounter == 2 |
644 | && myMouseClickTimer.IsStarted() |
645 | && myMouseClickTimer.ElapsedTime() <= myMouseDoubleClickInt; |
646 | |
647 | myMouseClickTimer.Stop(); |
648 | myMouseClickTimer.Reset(); |
649 | myMouseClickTimer.Start(); |
650 | if (isDoubleClick) |
651 | { |
652 | myMouseClickCounter = 0; |
653 | } |
654 | toUpdateView = UpdateMouseClick (thePoint, (Aspect_VKeyMouse )myMouseSingleButton, theModifiers, isDoubleClick) || toUpdateView; |
655 | } |
656 | else |
657 | { |
658 | myMouseClickTimer.Stop(); |
659 | myMouseClickCounter = 0; |
215dd331 |
660 | myMouseStopDragOnUnclick = false; |
49582f9d |
661 | myUI.Dragging.ToStop = true; |
662 | toUpdateView = true; |
663 | } |
664 | myMouseSingleButton = -1; |
665 | } |
666 | else if (theButtons == Aspect_VKeyMouse_NONE) |
667 | { |
668 | myMouseSingleButton = -1; |
215dd331 |
669 | if (myMouseStopDragOnUnclick) |
670 | { |
671 | myMouseStopDragOnUnclick = false; |
672 | myUI.Dragging.ToStop = true; |
673 | toUpdateView = true; |
674 | } |
49582f9d |
675 | } |
676 | else if (myMouseSingleButton == -1) |
677 | { |
678 | if ((theButtons & Aspect_VKeyMouse_LeftButton) == Aspect_VKeyMouse_LeftButton) |
679 | { |
680 | myMouseSingleButton = Aspect_VKeyMouse_LeftButton; |
681 | } |
682 | else if ((theButtons & Aspect_VKeyMouse_RightButton) == Aspect_VKeyMouse_RightButton) |
683 | { |
684 | myMouseSingleButton = Aspect_VKeyMouse_RightButton; |
685 | } |
686 | else if ((theButtons & Aspect_VKeyMouse_MiddleButton) == Aspect_VKeyMouse_MiddleButton) |
687 | { |
688 | myMouseSingleButton = Aspect_VKeyMouse_MiddleButton; |
689 | } |
690 | else |
691 | { |
692 | myMouseSingleButton = 0; |
693 | } |
694 | if (myMouseSingleButton != 0) |
695 | { |
696 | if (myMouseClickCounter == 1) |
697 | { |
698 | const Graphic3d_Vec2i aDelta = thePoint - myMousePressPoint; |
699 | if (double(aDelta.cwiseAbs().maxComp()) >= aTolClick) |
700 | { |
701 | myMouseClickTimer.Stop(); |
702 | myMouseClickCounter = 0; |
703 | } |
704 | } |
705 | myMousePressPoint = thePoint; |
706 | } |
707 | } |
708 | else |
709 | { |
710 | myMouseSingleButton = 0; |
711 | |
712 | myUI.Dragging.ToAbort = true; |
713 | toUpdateView = true; |
714 | } |
715 | |
716 | const AIS_MouseGesture aPrevGesture = myMouseActiveGesture; |
717 | myMouseModifiers = theModifiers; |
718 | myMousePressed = theButtons; |
719 | if (theIsEmulated |
720 | || myNavigationMode != AIS_NavigationMode_FirstPersonWalk) |
721 | { |
722 | myMouseActiveIdleRotation = false; |
723 | myMouseActiveGesture = AIS_MouseGesture_NONE; |
724 | if (theButtons != 0) |
725 | { |
726 | myMousePressPoint = thePoint; |
727 | myMouseProgressPoint = myMousePressPoint; |
728 | } |
729 | |
730 | if (myMouseGestureMap.Find (theButtons | theModifiers, myMouseActiveGesture)) |
731 | { |
732 | switch (myMouseActiveGesture) |
733 | { |
734 | case AIS_MouseGesture_RotateView: |
735 | case AIS_MouseGesture_RotateOrbit: |
736 | { |
737 | if (myToAllowRotation) |
738 | { |
739 | myUpdateStartPointRot = true; |
740 | } |
741 | else |
742 | { |
743 | myMouseActiveGesture = AIS_MouseGesture_NONE; |
744 | } |
745 | break; |
746 | } |
747 | case AIS_MouseGesture_Pan: |
748 | { |
749 | if (myToAllowPanning) |
750 | { |
751 | myUpdateStartPointPan = true; |
752 | } |
753 | else |
754 | { |
755 | myMouseActiveGesture = AIS_MouseGesture_NONE; |
756 | } |
757 | break; |
758 | } |
759 | case AIS_MouseGesture_Zoom: |
e1c9a103 |
760 | case AIS_MouseGesture_ZoomWindow: |
49582f9d |
761 | { |
762 | if (!myToAllowZooming) |
763 | { |
764 | myMouseActiveGesture = AIS_MouseGesture_NONE; |
765 | } |
766 | break; |
767 | } |
768 | case AIS_MouseGesture_SelectRectangle: |
769 | { |
770 | break; |
771 | } |
772 | case AIS_MouseGesture_SelectLasso: |
773 | { |
774 | UpdatePolySelection (thePoint, true); |
775 | break; |
776 | } |
777 | case AIS_MouseGesture_NONE: |
778 | { |
779 | break; |
780 | } |
781 | } |
782 | } |
783 | |
784 | if (theButtons == Aspect_VKeyMouse_LeftButton |
785 | && theModifiers == Aspect_VKeyFlags_NONE |
786 | && myToAllowDragging) |
787 | { |
788 | myUI.Dragging.ToStart = true; |
789 | myUI.Dragging.PointStart = thePoint; |
790 | } |
791 | } |
792 | |
793 | if (aPrevGesture != myMouseActiveGesture) |
794 | { |
795 | if (aPrevGesture == AIS_MouseGesture_SelectRectangle |
e1c9a103 |
796 | || aPrevGesture == AIS_MouseGesture_SelectLasso |
797 | || aPrevGesture == AIS_MouseGesture_ZoomWindow) |
49582f9d |
798 | { |
799 | myUI.Selection.ToApplyTool = true; |
800 | } |
801 | |
802 | myUI.IsNewGesture = true; |
803 | toUpdateView = true; |
804 | } |
805 | return toUpdateView; |
806 | } |
807 | |
808 | // ======================================================================= |
809 | // function : UpdateMousePosition |
810 | // purpose : |
811 | // ======================================================================= |
812 | bool AIS_ViewController::UpdateMousePosition (const Graphic3d_Vec2i& thePoint, |
813 | Aspect_VKeyMouse theButtons, |
814 | Aspect_VKeyFlags theModifiers, |
815 | bool theIsEmulated) |
816 | { |
817 | myMousePositionLast = thePoint; |
818 | if (myMouseSingleButton > 0) |
819 | { |
820 | const double aTolClick = (theIsEmulated ? myTouchToleranceScale : 1.0) * myMouseClickThreshold; |
821 | const Graphic3d_Vec2i aPressDelta = thePoint - myMousePressPoint; |
822 | if (double(aPressDelta.cwiseAbs().maxComp()) >= aTolClick) |
823 | { |
824 | myMouseClickTimer.Stop(); |
825 | myMouseClickCounter = 0; |
826 | myMouseSingleButton = -1; |
215dd331 |
827 | myMouseStopDragOnUnclick = true; |
49582f9d |
828 | } |
829 | } |
830 | |
831 | bool toUpdateView = false; |
832 | Graphic3d_Vec2i aDelta = thePoint - myMouseProgressPoint; |
833 | if (!theIsEmulated |
834 | && myNavigationMode == AIS_NavigationMode_FirstPersonWalk) |
835 | { |
836 | if (!myMouseActiveIdleRotation |
837 | || myMouseActiveGesture != AIS_MouseGesture_RotateView) |
838 | { |
839 | myMouseActiveIdleRotation = true; |
840 | myMouseActiveGesture = AIS_MouseGesture_RotateView; |
841 | myMousePressPoint = thePoint; |
842 | myMouseProgressPoint = thePoint; |
843 | myUpdateStartPointRot = false; |
844 | myUI.ViewRotation.ToStart = true; |
845 | myUI.ViewRotation.PointStart.SetValues (thePoint.x(), thePoint.y()); |
846 | myUI.ViewRotation.ToRotate = false; |
847 | aDelta.SetValues (0, 0); |
848 | } |
849 | } |
850 | else |
851 | { |
852 | if (myMouseActiveIdleRotation |
853 | && myMouseActiveGesture == AIS_MouseGesture_RotateView) |
854 | { |
855 | myMouseActiveGesture = AIS_MouseGesture_NONE; |
856 | } |
857 | myMouseActiveIdleRotation = false; |
858 | } |
859 | |
860 | if (myMouseModifiers != theModifiers |
861 | && UpdateMouseButtons (thePoint, theButtons, theModifiers, theIsEmulated)) |
862 | { |
863 | toUpdateView = true; |
864 | } |
865 | |
866 | switch (myMouseActiveGesture) |
867 | { |
868 | case AIS_MouseGesture_SelectRectangle: |
e1c9a103 |
869 | case AIS_MouseGesture_ZoomWindow: |
49582f9d |
870 | { |
871 | UpdateRubberBand (myMousePressPoint, thePoint); |
e1c9a103 |
872 | if (myMouseActiveGesture == AIS_MouseGesture_ZoomWindow) |
873 | { |
874 | myUI.Selection.Tool = AIS_ViewSelectionTool_ZoomWindow; |
875 | } |
49582f9d |
876 | toUpdateView = true; |
877 | break; |
878 | } |
879 | case AIS_MouseGesture_SelectLasso: |
880 | { |
881 | UpdatePolySelection (thePoint, true); |
882 | toUpdateView = true; |
883 | break; |
884 | } |
885 | case AIS_MouseGesture_RotateOrbit: |
886 | case AIS_MouseGesture_RotateView: |
887 | { |
888 | if (!myToAllowRotation) |
889 | { |
890 | break; |
891 | } |
892 | if (myUpdateStartPointRot) |
893 | { |
894 | if (myMouseActiveGesture == AIS_MouseGesture_RotateOrbit) |
895 | { |
896 | myUI.OrbitRotation.ToStart = true; |
897 | myUI.OrbitRotation.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y()); |
898 | } |
899 | else |
900 | { |
901 | myUI.ViewRotation.ToStart = true; |
902 | myUI.ViewRotation.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y()); |
903 | } |
904 | myUpdateStartPointRot = false; |
905 | } |
906 | |
907 | const double aRotTol = theIsEmulated |
908 | ? double(myTouchToleranceScale) * myTouchRotationThresholdPx |
909 | : 0.0; |
910 | if (double (Abs (aDelta.x()) + Abs (aDelta.y())) > aRotTol) |
911 | { |
912 | const double aRotAccel = myNavigationMode == AIS_NavigationMode_FirstPersonWalk ? myMouseAccel : myOrbitAccel; |
913 | const Graphic3d_Vec2i aRotDelta = thePoint - myMousePressPoint; |
914 | if (myMouseActiveGesture == AIS_MouseGesture_RotateOrbit) |
915 | { |
916 | myUI.OrbitRotation.ToRotate = true; |
917 | myUI.OrbitRotation.PointTo = Graphic3d_Vec2d (myMousePressPoint.x(), myMousePressPoint.y()) |
918 | + Graphic3d_Vec2d (aRotDelta.x(), aRotDelta.y()) * aRotAccel; |
919 | } |
920 | else |
921 | { |
922 | myUI.ViewRotation.ToRotate = true; |
923 | myUI.ViewRotation.PointTo = Graphic3d_Vec2d (myMousePressPoint.x(), myMousePressPoint.y()) |
924 | + Graphic3d_Vec2d (aRotDelta.x(), aRotDelta.y()) * aRotAccel; |
925 | } |
926 | myUI.Dragging.PointTo = thePoint; |
927 | |
928 | myMouseProgressPoint = thePoint; |
929 | toUpdateView = true; |
930 | } |
931 | break; |
932 | } |
933 | case AIS_MouseGesture_Zoom: |
934 | { |
935 | if (!myToAllowZooming) |
936 | { |
937 | break; |
938 | } |
939 | const double aZoomTol = theIsEmulated |
940 | ? double(myTouchToleranceScale) * myTouchZoomThresholdPx |
941 | : 0.0; |
942 | if (double (Abs (aDelta.x())) > aZoomTol) |
943 | { |
944 | if (UpdateZoom (Aspect_ScrollDelta (aDelta.x()))) |
945 | { |
946 | toUpdateView = true; |
947 | } |
948 | myMouseProgressPoint = thePoint; |
949 | } |
950 | break; |
951 | } |
952 | case AIS_MouseGesture_Pan: |
953 | { |
954 | if (!myToAllowPanning) |
955 | { |
956 | break; |
957 | } |
958 | const double aPanTol = theIsEmulated |
959 | ? double(myTouchToleranceScale) * myTouchPanThresholdPx |
960 | : 0.0; |
961 | if (double (Abs (aDelta.x()) + Abs (aDelta.y())) > aPanTol) |
962 | { |
963 | if (myUpdateStartPointPan) |
964 | { |
965 | myUI.Panning.ToStart = true; |
966 | myUI.Panning.PointStart.SetValues (myMousePressPoint.x(), myMousePressPoint.y()); |
967 | myUpdateStartPointPan = false; |
968 | } |
969 | |
970 | aDelta.y() = -aDelta.y(); |
971 | myMouseProgressPoint = thePoint; |
972 | if (myUI.Panning.ToPan) |
973 | { |
974 | myUI.Panning.Delta += aDelta; |
975 | } |
976 | else |
977 | { |
978 | myUI.Panning.ToPan = true; |
979 | myUI.Panning.Delta = aDelta; |
980 | } |
981 | toUpdateView = true; |
982 | } |
983 | break; |
984 | } |
985 | default: |
986 | { |
987 | break; |
988 | } |
989 | } |
990 | |
991 | if (theButtons == Aspect_VKeyMouse_NONE |
992 | && myNavigationMode != AIS_NavigationMode_FirstPersonWalk |
993 | && !theIsEmulated |
994 | && !HasTouchPoints() |
995 | && myToAllowHighlight) |
996 | { |
997 | myUI.MoveTo.ToHilight = true; |
998 | myUI.MoveTo.Point = thePoint; |
999 | toUpdateView = true; |
1000 | } |
1001 | return toUpdateView; |
1002 | } |
1003 | |
1004 | // ======================================================================= |
1005 | // function : AddTouchPoint |
1006 | // purpose : |
1007 | // ======================================================================= |
1008 | void AIS_ViewController::AddTouchPoint (Standard_Size theId, |
1009 | const Graphic3d_Vec2d& thePnt, |
1010 | Standard_Boolean theClearBefore) |
1011 | { |
1012 | myUI.MoveTo.ToHilight = false; |
1013 | if (theClearBefore) |
1014 | { |
1015 | RemoveTouchPoint ((Standard_Size )-1); |
1016 | } |
1017 | |
1018 | myTouchPoints.Add (theId, Aspect_Touch (thePnt, false)); |
1019 | if (myTouchPoints.Extent() == 1) |
1020 | { |
1021 | myUpdateStartPointRot = true; |
1022 | myStartRotCoord = thePnt; |
1023 | if (myToAllowDragging) |
1024 | { |
1025 | myUI.Dragging.ToStart = true; |
1026 | myUI.Dragging.PointStart.SetValues ((int )thePnt.x(), (int )thePnt.y()); |
1027 | } |
1028 | } |
1029 | else if (myTouchPoints.Extent() == 2) |
1030 | { |
1031 | myUI.Dragging.ToAbort = true; |
1032 | |
1033 | myUpdateStartPointPan = true; |
1034 | myStartPanCoord = thePnt; |
1035 | } |
1036 | myUI.IsNewGesture = true; |
1037 | } |
1038 | |
1039 | // ======================================================================= |
1040 | // function : RemoveTouchPoint |
1041 | // purpose : |
1042 | // ======================================================================= |
1043 | bool AIS_ViewController::RemoveTouchPoint (Standard_Size theId, |
1044 | Standard_Boolean theClearSelectPnts) |
1045 | { |
1046 | if (theId == (Standard_Size )-1) |
1047 | { |
1048 | myTouchPoints.Clear (false); |
1049 | } |
1050 | else |
1051 | { |
1052 | const Standard_Integer anOldExtent = myTouchPoints.Extent(); |
1053 | myTouchPoints.RemoveKey (theId); |
1054 | if (myTouchPoints.Extent() == anOldExtent) |
1055 | { |
1056 | return false; |
1057 | } |
1058 | } |
1059 | |
1060 | if (myTouchPoints.Extent() == 1) |
1061 | { |
1062 | // avoid incorrect transition from pinch to one finger |
1063 | Aspect_Touch& aFirstTouch = myTouchPoints.ChangeFromIndex (1); |
1064 | aFirstTouch.To = aFirstTouch.From; |
1065 | |
1066 | myStartRotCoord = aFirstTouch.To; |
1067 | myUpdateStartPointRot = true; |
1068 | } |
1069 | else if (myTouchPoints.Extent() == 2) |
1070 | { |
1071 | myStartPanCoord = myTouchPoints.FindFromIndex (1).To; |
1072 | myUpdateStartPointPan = true; |
1073 | } |
1074 | else if (myTouchPoints.IsEmpty()) |
1075 | { |
1076 | if (theClearSelectPnts) |
1077 | { |
1078 | myUI.Selection.ToApplyTool = true; |
1079 | } |
1080 | |
1081 | myUI.Dragging.ToStop = true; |
1082 | } |
1083 | myUI.IsNewGesture = true; |
1084 | return true; |
1085 | } |
1086 | |
1087 | // ======================================================================= |
1088 | // function : UpdateTouchPoint |
1089 | // purpose : |
1090 | // ======================================================================= |
1091 | void AIS_ViewController::UpdateTouchPoint (Standard_Size theId, |
1092 | const Graphic3d_Vec2d& thePnt) |
1093 | { |
1094 | if (Aspect_Touch* aTouch = myTouchPoints.ChangeSeek (theId)) |
1095 | { |
1096 | aTouch->To = thePnt; |
1097 | } |
1098 | else |
1099 | { |
1100 | AddTouchPoint (theId, thePnt); |
1101 | } |
1102 | } |
1103 | |
d6fbb2ab |
1104 | // ======================================================================= |
1105 | // function : Update3dMouse |
1106 | // purpose : |
1107 | // ======================================================================= |
1108 | bool AIS_ViewController::Update3dMouse (const WNT_HIDSpaceMouse& theEvent) |
1109 | { |
1110 | bool toUpdate = false; |
1111 | toUpdate = update3dMouseTranslation (theEvent) || toUpdate; |
1112 | toUpdate = update3dMouseRotation (theEvent) || toUpdate; |
1113 | toUpdate = update3dMouseKeys (theEvent) || toUpdate; |
1114 | return toUpdate; |
1115 | } |
1116 | |
1117 | // ======================================================================= |
1118 | // function : update3dMouseTranslation |
1119 | // purpose : |
1120 | // ======================================================================= |
1121 | bool AIS_ViewController::update3dMouseTranslation (const WNT_HIDSpaceMouse& theEvent) |
1122 | { |
1123 | if (!theEvent.IsTranslation()) |
1124 | { |
1125 | return false; |
1126 | } |
1127 | |
1128 | bool isIdle = true; |
1129 | const double aTimeStamp = EventTime(); |
1130 | const Graphic3d_Vec3d aTrans = theEvent.Translation (isIdle, my3dMouseIsQuadric) * my3dMouseAccelTrans; |
1131 | myKeys.KeyFromAxis (Aspect_VKey_NavSlideLeft, Aspect_VKey_NavSlideRight, aTimeStamp, aTrans.x()); |
1132 | myKeys.KeyFromAxis (Aspect_VKey_NavForward, Aspect_VKey_NavBackward, aTimeStamp, aTrans.y()); |
1133 | myKeys.KeyFromAxis (Aspect_VKey_NavSlideUp, Aspect_VKey_NavSlideDown, aTimeStamp, aTrans.z()); |
1134 | return true; |
1135 | } |
1136 | |
1137 | // ======================================================================= |
1138 | // function : update3dMouseRotation |
1139 | // purpose : |
1140 | // ======================================================================= |
1141 | bool AIS_ViewController::update3dMouseRotation (const WNT_HIDSpaceMouse& theEvent) |
1142 | { |
1143 | if (!theEvent.IsRotation() |
1144 | || !myToAllowRotation) |
1145 | { |
1146 | return false; |
1147 | } |
1148 | |
1149 | bool isIdle = true, toUpdate = false; |
1150 | const double aTimeStamp = EventTime(); |
1151 | const Graphic3d_Vec3d aRot3 = theEvent.Rotation (isIdle, my3dMouseIsQuadric) * my3dMouseAccelRotate; |
1152 | if (!my3dMouseNoRotate.x()) |
1153 | { |
1154 | KeyFromAxis (Aspect_VKey_NavLookUp, Aspect_VKey_NavLookDown, aTimeStamp, !my3dMouseToReverse.x() ? aRot3.x() : -aRot3.x()); |
1155 | toUpdate = true; |
1156 | } |
1157 | if (!my3dMouseNoRotate.y()) |
1158 | { |
1159 | KeyFromAxis (Aspect_VKey_NavRollCW, Aspect_VKey_NavRollCCW, aTimeStamp, !my3dMouseToReverse.y() ? aRot3.y() : -aRot3.y()); |
1160 | toUpdate = true; |
1161 | } |
1162 | if (!my3dMouseNoRotate.z()) |
1163 | { |
1164 | KeyFromAxis (Aspect_VKey_NavLookLeft, Aspect_VKey_NavLookRight, aTimeStamp, !my3dMouseToReverse.z() ? aRot3.z() : -aRot3.z()); |
1165 | toUpdate = true; |
1166 | } |
1167 | return toUpdate; |
1168 | } |
1169 | |
1170 | // ======================================================================= |
1171 | // function : update3dMouseKeys |
1172 | // purpose : |
1173 | // ======================================================================= |
1174 | bool AIS_ViewController::update3dMouseKeys (const WNT_HIDSpaceMouse& theEvent) |
1175 | { |
1176 | bool toUpdate = false; |
1177 | const double aTimeStamp = EventTime(); |
1178 | if (theEvent.IsKeyState()) |
1179 | { |
1180 | const uint32_t aKeyState = theEvent.KeyState(); |
1181 | for (unsigned short aKeyBit = 0; aKeyBit < 32; ++aKeyBit) |
1182 | { |
1183 | const bool isPressed = (aKeyState & (1 << aKeyBit)) != 0; |
1184 | const bool isReleased = my3dMouseButtonState[aKeyBit] && !isPressed; |
1185 | //const bool isRepeated = my3dMouseButtonState[aKeyBit] && isPressed; |
1186 | my3dMouseButtonState[aKeyBit] = isPressed; |
1187 | if (!isReleased && !isPressed) |
1188 | { |
1189 | continue; |
1190 | } |
1191 | |
1192 | const Aspect_VKey aVKey = theEvent.HidToSpaceKey (aKeyBit); |
1193 | if (aVKey != Aspect_VKey_UNKNOWN) |
1194 | { |
1195 | toUpdate = true; |
1196 | if (isPressed) |
1197 | { |
1198 | KeyDown (aVKey, aTimeStamp); |
1199 | } |
1200 | else |
1201 | { |
1202 | KeyUp (aVKey, aTimeStamp); |
1203 | } |
1204 | } |
1205 | } |
1206 | } |
1207 | return toUpdate; |
1208 | } |
1209 | |
49582f9d |
1210 | // ======================================================================= |
1211 | // function : SetNavigationMode |
1212 | // purpose : |
1213 | // ======================================================================= |
1214 | void AIS_ViewController::SetNavigationMode (AIS_NavigationMode theMode) |
1215 | { |
1216 | myNavigationMode = theMode; |
1217 | |
1218 | // abort rotation |
1219 | myUI.OrbitRotation.ToStart = false; |
1220 | myUI.OrbitRotation.ToRotate = false; |
1221 | myUI.ViewRotation.ToStart = false; |
1222 | myUI.ViewRotation.ToRotate = false; |
1223 | } |
1224 | |
1225 | // ======================================================================= |
1226 | // function : KeyDown |
1227 | // purpose : |
1228 | // ======================================================================= |
1229 | void AIS_ViewController::KeyDown (Aspect_VKey theKey, |
1230 | double theTime, |
1231 | double thePressure) |
1232 | { |
1233 | myKeys.KeyDown (theKey, theTime, thePressure); |
1234 | } |
1235 | |
1236 | // ======================================================================= |
1237 | // function : KeyUp |
1238 | // purpose : |
1239 | // ======================================================================= |
1240 | void AIS_ViewController::KeyUp (Aspect_VKey theKey, |
1241 | double theTime) |
1242 | { |
1243 | myKeys.KeyUp (theKey, theTime); |
1244 | } |
1245 | |
1246 | // ======================================================================= |
1247 | // function : KeyFromAxis |
1248 | // purpose : |
1249 | // ======================================================================= |
1250 | void AIS_ViewController::KeyFromAxis (Aspect_VKey theNegative, |
1251 | Aspect_VKey thePositive, |
1252 | double theTime, |
1253 | double thePressure) |
1254 | { |
1255 | myKeys.KeyFromAxis (theNegative, thePositive, theTime, thePressure); |
1256 | } |
1257 | |
1258 | // ======================================================================= |
1259 | // function : FetchNavigationKeys |
1260 | // purpose : |
1261 | // ======================================================================= |
1262 | AIS_WalkDelta AIS_ViewController::FetchNavigationKeys (Standard_Real theCrouchRatio, |
1263 | Standard_Real theRunRatio) |
1264 | { |
1265 | AIS_WalkDelta aWalk; |
1266 | |
1267 | // navigation keys |
1268 | double aPrevEventTime = 0.0, aNewEventTime = 0.0; |
1269 | updateEventsTime (aPrevEventTime, aNewEventTime); |
1270 | |
1271 | double aDuration = 0.0, aPressure = 1.0; |
1272 | if (Abs (myThrustSpeed) > gp::Resolution()) |
1273 | { |
1274 | if (myHasThrust) |
1275 | { |
1276 | aWalk[AIS_WalkTranslation_Forward].Value = myThrustSpeed * (aNewEventTime - aPrevEventTime); |
1277 | } |
1278 | myHasThrust = true; |
1279 | myToAskNextFrame = true; |
1280 | } |
1281 | else |
1282 | { |
1283 | myHasThrust = false; |
1284 | } |
1285 | |
1286 | aWalk.SetRunning (theRunRatio > 1.0 |
1287 | && myKeys.IsKeyDown (Aspect_VKey_Shift)); |
1288 | if (myKeys.HoldDuration (Aspect_VKey_NavJump, aNewEventTime, aDuration)) |
1289 | { |
1290 | myKeys.KeyUp (Aspect_VKey_NavJump, aNewEventTime); |
1291 | aWalk.SetJumping (true); |
1292 | } |
1293 | if (!aWalk.IsJumping() |
1294 | && theCrouchRatio < 1.0 |
1295 | && myKeys.HoldDuration (Aspect_VKey_NavCrouch, aNewEventTime, aDuration)) |
1296 | { |
1297 | aWalk.SetRunning (false); |
1298 | aWalk.SetCrouching (true); |
1299 | } |
1300 | |
1301 | const double aMaxDuration = aNewEventTime - aPrevEventTime; |
1302 | const double aRunRatio = aWalk.IsRunning() |
1303 | ? theRunRatio |
1304 | : aWalk.IsCrouching() |
1305 | ? theCrouchRatio |
1306 | : 1.0; |
1307 | if (myKeys.HoldDuration (Aspect_VKey_NavForward, aNewEventTime, aDuration, aPressure)) |
1308 | { |
1309 | double aProgress = Abs (Min (aMaxDuration, aDuration)); |
1310 | aProgress *= aRunRatio; |
1311 | aWalk[AIS_WalkTranslation_Forward].Value += aProgress; |
1312 | aWalk[AIS_WalkTranslation_Forward].Pressure = aPressure; |
1313 | aWalk[AIS_WalkTranslation_Forward].Duration = aDuration; |
1314 | } |
1315 | if (myKeys.HoldDuration (Aspect_VKey_NavBackward, aNewEventTime, aDuration, aPressure)) |
1316 | { |
1317 | double aProgress = Abs (Min (aMaxDuration, aDuration)); |
1318 | aProgress *= aRunRatio; |
1319 | aWalk[AIS_WalkTranslation_Forward].Value += -aProgress; |
1320 | aWalk[AIS_WalkTranslation_Forward].Pressure = aPressure; |
1321 | aWalk[AIS_WalkTranslation_Forward].Duration = aDuration; |
1322 | } |
1323 | if (myKeys.HoldDuration (Aspect_VKey_NavSlideLeft, aNewEventTime, aDuration, aPressure)) |
1324 | { |
1325 | double aProgress = Abs (Min (aMaxDuration, aDuration)); |
1326 | aProgress *= aRunRatio; |
1327 | aWalk[AIS_WalkTranslation_Side].Value = -aProgress; |
1328 | aWalk[AIS_WalkTranslation_Side].Pressure = aPressure; |
1329 | aWalk[AIS_WalkTranslation_Side].Duration = aDuration; |
1330 | } |
1331 | if (myKeys.HoldDuration (Aspect_VKey_NavSlideRight, aNewEventTime, aDuration, aPressure)) |
1332 | { |
1333 | double aProgress = Abs (Min (aMaxDuration, aDuration)); |
1334 | aProgress *= aRunRatio; |
1335 | aWalk[AIS_WalkTranslation_Side].Value = aProgress; |
1336 | aWalk[AIS_WalkTranslation_Side].Pressure = aPressure; |
1337 | aWalk[AIS_WalkTranslation_Side].Duration = aDuration; |
1338 | } |
1339 | if (myKeys.HoldDuration (Aspect_VKey_NavLookLeft, aNewEventTime, aDuration, aPressure)) |
1340 | { |
1341 | double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure; |
1342 | aWalk[AIS_WalkRotation_Yaw].Value = aProgress; |
1343 | aWalk[AIS_WalkRotation_Yaw].Pressure = aPressure; |
1344 | aWalk[AIS_WalkRotation_Yaw].Duration = aDuration; |
1345 | } |
1346 | if (myKeys.HoldDuration (Aspect_VKey_NavLookRight, aNewEventTime, aDuration, aPressure)) |
1347 | { |
1348 | double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure; |
1349 | aWalk[AIS_WalkRotation_Yaw].Value = -aProgress; |
1350 | aWalk[AIS_WalkRotation_Yaw].Pressure = aPressure; |
1351 | aWalk[AIS_WalkRotation_Yaw].Duration = aDuration; |
1352 | } |
1353 | if (myKeys.HoldDuration (Aspect_VKey_NavLookUp, aNewEventTime, aDuration, aPressure)) |
1354 | { |
1355 | double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure; |
1356 | aWalk[AIS_WalkRotation_Pitch].Value = !myToInvertPitch ? -aProgress : aProgress; |
1357 | aWalk[AIS_WalkRotation_Pitch].Pressure = aPressure; |
1358 | aWalk[AIS_WalkRotation_Pitch].Duration = aDuration; |
1359 | } |
1360 | if (myKeys.HoldDuration (Aspect_VKey_NavLookDown, aNewEventTime, aDuration, aPressure)) |
1361 | { |
1362 | double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure; |
1363 | aWalk[AIS_WalkRotation_Pitch].Value = !myToInvertPitch ? aProgress : -aProgress; |
1364 | aWalk[AIS_WalkRotation_Pitch].Pressure = aPressure; |
1365 | aWalk[AIS_WalkRotation_Pitch].Duration = aDuration; |
1366 | } |
1367 | if (myKeys.HoldDuration (Aspect_VKey_NavRollCCW, aNewEventTime, aDuration, aPressure)) |
1368 | { |
1369 | double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure; |
1370 | aWalk[AIS_WalkRotation_Roll].Value = -aProgress; |
1371 | aWalk[AIS_WalkRotation_Roll].Pressure = aPressure; |
1372 | aWalk[AIS_WalkRotation_Roll].Duration = aDuration; |
1373 | } |
1374 | if (myKeys.HoldDuration (Aspect_VKey_NavRollCW, aNewEventTime, aDuration, aPressure)) |
1375 | { |
1376 | double aProgress = Abs (Min (aMaxDuration, aDuration)) * aPressure; |
1377 | aWalk[AIS_WalkRotation_Roll].Value = aProgress; |
1378 | aWalk[AIS_WalkRotation_Roll].Pressure = aPressure; |
1379 | aWalk[AIS_WalkRotation_Roll].Duration = aDuration; |
1380 | } |
1381 | if (myKeys.HoldDuration (Aspect_VKey_NavSlideUp, aNewEventTime, aDuration, aPressure)) |
1382 | { |
1383 | double aProgress = Abs (Min (aMaxDuration, aDuration)); |
1384 | aWalk[AIS_WalkTranslation_Up].Value = aProgress; |
1385 | aWalk[AIS_WalkTranslation_Up].Pressure = aPressure; |
1386 | aWalk[AIS_WalkTranslation_Up].Duration = aDuration; |
1387 | } |
1388 | if (myKeys.HoldDuration (Aspect_VKey_NavSlideDown, aNewEventTime, aDuration, aPressure)) |
1389 | { |
1390 | double aProgress = Abs (Min (aMaxDuration, aDuration)); |
1391 | aWalk[AIS_WalkTranslation_Up].Value = -aProgress; |
1392 | aWalk[AIS_WalkTranslation_Up].Pressure = aPressure; |
1393 | aWalk[AIS_WalkTranslation_Up].Duration = aDuration; |
1394 | } |
1395 | return aWalk; |
1396 | } |
1397 | |
2108d9a2 |
1398 | // ======================================================================= |
1399 | // function : AbortViewAnimation |
1400 | // purpose : |
1401 | // ======================================================================= |
1402 | void AIS_ViewController::AbortViewAnimation() |
1403 | { |
1404 | if (!myViewAnimation.IsNull() |
1405 | && !myViewAnimation->IsStopped()) |
1406 | { |
1407 | myViewAnimation->Stop(); |
1408 | myViewAnimation->SetView (Handle(V3d_View)()); |
1409 | } |
1410 | } |
1411 | |
49582f9d |
1412 | // ======================================================================= |
1413 | // function : handlePanning |
1414 | // purpose : |
1415 | // ======================================================================= |
1416 | void AIS_ViewController::handlePanning (const Handle(V3d_View)& theView) |
1417 | { |
1418 | if (!myGL.Panning.ToPan |
1419 | || !myToAllowPanning) |
1420 | { |
1421 | return; |
1422 | } |
1423 | |
2108d9a2 |
1424 | AbortViewAnimation(); |
1425 | |
49582f9d |
1426 | const Handle(Graphic3d_Camera)& aCam = theView->Camera(); |
1427 | if (aCam->IsOrthographic() |
1428 | || !hasPanningAnchorPoint()) |
1429 | { |
1430 | theView->Pan (myGL.Panning.Delta.x(), myGL.Panning.Delta.y()); |
1431 | theView->Invalidate(); |
b40cdc2b |
1432 | theView->View()->SynchronizeXRPosedToBaseCamera(); |
49582f9d |
1433 | return; |
1434 | } |
1435 | |
1436 | Graphic3d_Vec2i aWinSize; |
1437 | theView->Window()->Size (aWinSize.x(), aWinSize.y()); |
1438 | |
1439 | const gp_Dir& aDir = aCam->Direction(); |
1440 | const gp_Ax3 aCameraCS (aCam->Center(), aDir.Reversed(), aDir ^ aCam->Up()); |
1441 | const gp_XYZ anEyeToPnt = myPanPnt3d.XYZ() - aCam->Eye().XYZ(); |
1442 | const gp_Pnt aViewDims = aCam->ViewDimensions (anEyeToPnt.Dot (aCam->Direction().XYZ())); // view dimensions at 3D point |
1443 | const Graphic3d_Vec2d aDxy (-aViewDims.X() * myGL.Panning.Delta.x() / double(aWinSize.x()), |
1444 | -aViewDims.X() * myGL.Panning.Delta.y() / double(aWinSize.x())); |
1445 | |
1446 | //theView->Translate (aCam, aDxy.x(), aDxy.y()); |
1447 | gp_Trsf aPanTrsf; |
1448 | const gp_Vec aCameraPan = gp_Vec (aCameraCS.XDirection()) * aDxy.x() |
1449 | + gp_Vec (aCameraCS.YDirection()) * aDxy.y(); |
1450 | aPanTrsf.SetTranslation (aCameraPan); |
1451 | aCam->Transform (aPanTrsf); |
1452 | theView->Invalidate(); |
b40cdc2b |
1453 | theView->View()->SynchronizeXRPosedToBaseCamera(); |
49582f9d |
1454 | } |
1455 | |
1456 | // ======================================================================= |
1457 | // function : handleZRotate |
1458 | // purpose : |
1459 | // ======================================================================= |
1460 | void AIS_ViewController::handleZRotate (const Handle(V3d_View)& theView) |
1461 | { |
1462 | if (!myGL.ZRotate.ToRotate |
1463 | || !myToAllowRotation) |
1464 | { |
1465 | return; |
1466 | } |
1467 | |
2108d9a2 |
1468 | AbortViewAnimation(); |
1469 | |
49582f9d |
1470 | Graphic3d_Vec2i aViewPort; |
1471 | theView->Window()->Size (aViewPort.x(), aViewPort.y()); |
1472 | Graphic3d_Vec2d aRotPnt (0.99 * aViewPort.x(), |
1473 | 0.5 * aViewPort.y()); |
1474 | theView->StartRotation (int(aRotPnt.x()), int(aRotPnt.y()), 0.4); |
1475 | aRotPnt.y() += myGL.ZRotate.Angle * aViewPort.y(); |
1476 | theView->Rotation (int(aRotPnt.x()), int(aRotPnt.y())); |
1477 | theView->Invalidate(); |
b40cdc2b |
1478 | theView->View()->SynchronizeXRPosedToBaseCamera(); |
49582f9d |
1479 | } |
1480 | |
1481 | // ======================================================================= |
1482 | // function : handleZoom |
1483 | // purpose : |
1484 | // ======================================================================= |
1485 | void AIS_ViewController::handleZoom (const Handle(V3d_View)& theView, |
1486 | const Aspect_ScrollDelta& theParams, |
1487 | const gp_Pnt* thePnt) |
1488 | { |
1489 | if (!myToAllowZooming) |
1490 | { |
1491 | return; |
1492 | } |
1493 | |
2108d9a2 |
1494 | AbortViewAnimation(); |
1495 | |
49582f9d |
1496 | const Handle(Graphic3d_Camera)& aCam = theView->Camera(); |
1497 | if (thePnt != NULL) |
1498 | { |
1499 | const double aViewDist = Max (myMinCamDistance, (thePnt->XYZ() - aCam->Eye().XYZ()).Modulus()); |
1500 | aCam->SetCenter (aCam->Eye().XYZ() + aCam->Direction().XYZ() * aViewDist); |
1501 | } |
1502 | |
1503 | if (!theParams.HasPoint()) |
1504 | { |
1505 | Standard_Real aCoeff = Abs(theParams.Delta) / 100.0 + 1.0; |
1506 | aCoeff = theParams.Delta > 0.0 ? aCoeff : 1.0 / aCoeff; |
1507 | theView->SetZoom (aCoeff, true); |
1508 | theView->Invalidate(); |
b40cdc2b |
1509 | theView->View()->SynchronizeXRPosedToBaseCamera(); |
49582f9d |
1510 | return; |
1511 | } |
1512 | |
1513 | // integer delta is too rough for small smooth increments |
1514 | //theView->StartZoomAtPoint (theParams.Point.x(), theParams.Point.y()); |
1515 | //theView->ZoomAtPoint (0, 0, (int )theParams.Delta, (int )theParams.Delta); |
1516 | |
1517 | double aDZoom = Abs (theParams.Delta) / 100.0 + 1.0; |
1518 | aDZoom = (theParams.Delta > 0.0) ? aDZoom : 1.0 / aDZoom; |
1519 | if (aDZoom <= 0.0) |
1520 | { |
1521 | return; |
1522 | } |
1523 | |
1524 | const Graphic3d_Vec2d aViewDims (aCam->ViewDimensions().X(), aCam->ViewDimensions().Y()); |
1525 | |
1526 | // ensure that zoom will not be too small or too big |
1527 | double aCoef = aDZoom; |
1528 | if (aViewDims.x() < aCoef * Precision::Confusion()) |
1529 | { |
1530 | aCoef = aViewDims.x() / Precision::Confusion(); |
1531 | } |
1532 | else if (aViewDims.x() > aCoef * 1e12) |
1533 | { |
1534 | aCoef = aViewDims.x() / 1e12; |
1535 | } |
1536 | if (aViewDims.y() < aCoef * Precision::Confusion()) |
1537 | { |
1538 | aCoef = aViewDims.y() / Precision::Confusion(); |
1539 | } |
1540 | else if (aViewDims.y() > aCoef * 1e12) |
1541 | { |
1542 | aCoef = aViewDims.y() / 1e12; |
1543 | } |
1544 | |
1545 | Graphic3d_Vec2d aZoomAtPointXYv (0.0, 0.0); |
1546 | theView->Convert (theParams.Point.x(), theParams.Point.y(), |
1547 | aZoomAtPointXYv.x(), aZoomAtPointXYv.y()); |
1548 | Graphic3d_Vec2d aDxy = aZoomAtPointXYv / aCoef; |
1549 | aCam->SetScale (aCam->Scale() / aCoef); |
1550 | |
1551 | const gp_Dir& aDir = aCam->Direction(); |
1552 | const gp_Ax3 aCameraCS (aCam->Center(), aDir.Reversed(), aDir ^ aCam->Up()); |
1553 | |
1554 | // pan back to the point |
1555 | aDxy = aZoomAtPointXYv - aDxy; |
1556 | if (thePnt != NULL) |
1557 | { |
1558 | // zoom at 3D point with perspective projection |
1559 | const gp_XYZ anEyeToPnt = thePnt->XYZ() - aCam->Eye().XYZ(); |
1560 | aDxy.SetValues (anEyeToPnt.Dot (aCameraCS.XDirection().XYZ()), |
1561 | anEyeToPnt.Dot (aCameraCS.YDirection().XYZ())); |
1562 | |
1563 | // view dimensions at 3D point |
1564 | const gp_Pnt aViewDims1 = aCam->ViewDimensions (anEyeToPnt.Dot (aCam->Direction().XYZ())); |
1565 | |
1566 | Graphic3d_Vec2i aWinSize; |
1567 | theView->Window()->Size (aWinSize.x(), aWinSize.y()); |
1568 | const Graphic3d_Vec2d aPanFromCenterPx (double(theParams.Point.x()) - 0.5 * double(aWinSize.x()), |
9460f8c0 |
1569 | double(aWinSize.y() - theParams.Point.y() - 1) - 0.5 * double(aWinSize.y())); |
49582f9d |
1570 | aDxy.x() += -aViewDims1.X() * aPanFromCenterPx.x() / double(aWinSize.x()); |
9460f8c0 |
1571 | aDxy.y() += -aViewDims1.Y() * aPanFromCenterPx.y() / double(aWinSize.y()); |
49582f9d |
1572 | } |
1573 | |
1574 | //theView->Translate (aCam, aDxy.x(), aDxy.y()); |
1575 | gp_Trsf aPanTrsf; |
1576 | const gp_Vec aCameraPan = gp_Vec (aCameraCS.XDirection()) * aDxy.x() |
1577 | + gp_Vec (aCameraCS.YDirection()) * aDxy.y(); |
1578 | aPanTrsf.SetTranslation (aCameraPan); |
1579 | aCam->Transform (aPanTrsf); |
1580 | theView->Invalidate(); |
b40cdc2b |
1581 | theView->View()->SynchronizeXRPosedToBaseCamera(); |
49582f9d |
1582 | } |
1583 | |
1584 | // ======================================================================= |
1585 | // function : handleZFocusScroll |
1586 | // purpose : |
1587 | // ======================================================================= |
1588 | void AIS_ViewController::handleZFocusScroll (const Handle(V3d_View)& theView, |
1589 | const Aspect_ScrollDelta& theParams) |
1590 | { |
1591 | if (!myToAllowZFocus |
1592 | || !theView->Camera()->IsStereo()) |
1593 | { |
1594 | return; |
1595 | } |
1596 | |
1597 | Standard_Real aFocus = theView->Camera()->ZFocus() + (theParams.Delta > 0.0 ? 0.05 : -0.05); |
1598 | if (aFocus > 0.2 |
1599 | && aFocus < 2.0) |
1600 | { |
1601 | theView->Camera()->SetZFocus (theView->Camera()->ZFocusType(), aFocus); |
b40cdc2b |
1602 | theView->Invalidate(); |
49582f9d |
1603 | } |
1604 | } |
1605 | |
1606 | // ======================================================================= |
1607 | // function : handleOrbitRotation |
1608 | // purpose : |
1609 | // ======================================================================= |
1610 | void AIS_ViewController::handleOrbitRotation (const Handle(V3d_View)& theView, |
1611 | const gp_Pnt& thePnt, |
1612 | bool theToLockZUp) |
1613 | { |
1614 | if (!myToAllowRotation) |
1615 | { |
1616 | return; |
1617 | } |
1618 | |
b40cdc2b |
1619 | const Handle(Graphic3d_Camera)& aCam = theView->View()->IsActiveXR() |
1620 | ? theView->View()->BaseXRCamera() |
1621 | : theView->Camera(); |
49582f9d |
1622 | if (myGL.OrbitRotation.ToStart) |
1623 | { |
1624 | // default alternatives |
1625 | //if (myRotationMode == AIS_RotationMode_BndBoxActive) theView->StartRotation (myGL.RotateAtPoint.x(), myGL.RotateAtPoint.y()); |
1626 | //theView->Rotate (0.0, 0.0, 0.0, thePnt.X(), thePnt.Y(), thePnt.Z(), true); |
1627 | |
1628 | myRotatePnt3d = thePnt; |
1629 | myCamStartOpUp = aCam->Up(); |
607e5e62 |
1630 | myCamStartOpDir = aCam->Direction(); |
49582f9d |
1631 | myCamStartOpEye = aCam->Eye(); |
1632 | myCamStartOpCenter = aCam->Center(); |
1633 | |
1634 | gp_Trsf aTrsf; |
1635 | aTrsf.SetTransformation (gp_Ax3 (myRotatePnt3d, aCam->OrthogonalizedUp(), aCam->Direction()), |
1636 | gp_Ax3 (myRotatePnt3d, gp::DZ(), gp::DX())); |
1637 | const gp_Quaternion aRot = aTrsf.GetRotation(); |
1638 | aRot.GetEulerAngles (gp_YawPitchRoll, myRotateStartYawPitchRoll[0], myRotateStartYawPitchRoll[1], myRotateStartYawPitchRoll[2]); |
1639 | |
1640 | aTrsf.Invert(); |
1641 | myCamStartOpToEye = gp_Vec (myRotatePnt3d, aCam->Eye()).Transformed (aTrsf); |
1642 | myCamStartOpToCenter = gp_Vec (myRotatePnt3d, aCam->Center()).Transformed (aTrsf); |
1643 | |
1644 | theView->Invalidate(); |
1645 | } |
1646 | |
1647 | if (!myGL.OrbitRotation.ToRotate) |
1648 | { |
1649 | return; |
1650 | } |
1651 | |
2108d9a2 |
1652 | AbortViewAnimation(); |
49582f9d |
1653 | if (theToLockZUp) |
1654 | { |
1655 | // amend camera to exclude roll angle (put camera Up vector to plane containing global Z and view direction) |
1656 | Graphic3d_Vec2i aWinXY; |
1657 | theView->Window()->Size (aWinXY.x(), aWinXY.y()); |
1658 | double aYawAngleDelta = ((myGL.OrbitRotation.PointStart.x() - myGL.OrbitRotation.PointTo.x()) / double (aWinXY.x())) * (M_PI * 0.5); |
1659 | double aPitchAngleDelta = -((myGL.OrbitRotation.PointStart.y() - myGL.OrbitRotation.PointTo.y()) / double (aWinXY.y())) * (M_PI * 0.5); |
b40cdc2b |
1660 | double aPitchAngleNew = 0.0, aRoll = 0.0; |
1661 | const double aYawAngleNew = myRotateStartYawPitchRoll[0] + aYawAngleDelta; |
1662 | if (!theView->View()->IsActiveXR()) |
1663 | { |
1664 | aPitchAngleNew = Max (Min (myRotateStartYawPitchRoll[1] + aPitchAngleDelta, M_PI * 0.5 - M_PI / 180.0), -M_PI * 0.5 + M_PI / 180.0); |
1665 | aRoll = 0.0; |
1666 | } |
49582f9d |
1667 | |
1668 | gp_Quaternion aRot; |
1669 | aRot.SetEulerAngles (gp_YawPitchRoll, aYawAngleNew, aPitchAngleNew, aRoll); |
1670 | gp_Trsf aTrsfRot; |
1671 | aTrsfRot.SetRotation (aRot); |
1672 | |
1673 | const gp_Dir aNewUp = gp::DZ().Transformed (aTrsfRot); |
1674 | aCam->SetUp (aNewUp); |
607e5e62 |
1675 | aCam->SetEyeAndCenter (myRotatePnt3d.XYZ() + myCamStartOpToEye .Transformed (aTrsfRot).XYZ(), |
1676 | myRotatePnt3d.XYZ() + myCamStartOpToCenter.Transformed (aTrsfRot).XYZ()); |
1677 | |
49582f9d |
1678 | aCam->OrthogonalizeUp(); |
1679 | } |
1680 | else |
1681 | { |
1682 | // default alternatives |
1683 | //if (myRotationMode == AIS_RotationMode_BndBoxActive) theView->Rotation (myGL.RotateToPoint.x(), myGL.RotateToPoint.y()); |
1684 | //theView->Rotate (aDX, aDY, aDZ, myRotatePnt3d.X(), myRotatePnt3d.Y(), myRotatePnt3d.Z(), false); |
1685 | |
1686 | // restore previous camera state |
607e5e62 |
1687 | aCam->SetEyeAndCenter (myCamStartOpEye, myCamStartOpCenter); |
1688 | aCam->SetUp (myCamStartOpUp); |
1689 | aCam->SetDirectionFromEye (myCamStartOpDir); |
49582f9d |
1690 | |
1691 | Graphic3d_Vec2d aWinXY; |
1692 | theView->Size (aWinXY.x(), aWinXY.y()); |
1693 | const Standard_Real rx = (Standard_Real )theView->Convert (aWinXY.x()); |
1694 | const Standard_Real ry = (Standard_Real )theView->Convert (aWinXY.y()); |
1695 | |
1696 | const double THE_2PI = M_PI * 2.0; |
1697 | double aDX = (myGL.OrbitRotation.PointTo.x() - myGL.OrbitRotation.PointStart.x()) * M_PI / rx; |
1698 | double aDY = (myGL.OrbitRotation.PointStart.y() - myGL.OrbitRotation.PointTo.y()) * M_PI / ry; |
1699 | |
1700 | if (aDX > 0.0) { while (aDX > THE_2PI) { aDX -= THE_2PI; } } |
1701 | else if(aDX < 0.0) { while (aDX < -THE_2PI) { aDX += THE_2PI; } } |
1702 | if (aDY > 0.0) { while (aDY > THE_2PI) { aDY -= THE_2PI; } } |
1703 | else if(aDY < 0.0) { while (aDY < -THE_2PI) { aDY += THE_2PI; } } |
1704 | |
1705 | // rotate camera around 3 initial axes |
1706 | gp_Dir aCamDir (aCam->Direction().Reversed()); |
1707 | gp_Dir aCamUp (aCam->Up()); |
1708 | gp_Dir aCamSide(aCamUp.Crossed (aCamDir)); |
1709 | |
1710 | gp_Trsf aRot[2], aTrsf; |
1711 | aRot[0].SetRotation (gp_Ax1 (myRotatePnt3d, aCamUp), -aDX); |
1712 | aRot[1].SetRotation (gp_Ax1 (myRotatePnt3d, aCamSide), aDY); |
1713 | aTrsf.Multiply (aRot[0]); |
1714 | aTrsf.Multiply (aRot[1]); |
1715 | |
1716 | aCam->Transform (aTrsf); |
1717 | } |
1718 | |
1719 | theView->Invalidate(); |
b40cdc2b |
1720 | theView->View()->SynchronizeXRBaseToPosedCamera(); |
49582f9d |
1721 | } |
1722 | |
1723 | // ======================================================================= |
1724 | // function : handleViewRotation |
1725 | // purpose : |
1726 | // ======================================================================= |
1727 | void AIS_ViewController::handleViewRotation (const Handle(V3d_View)& theView, |
1728 | double theYawExtra, |
1729 | double thePitchExtra, |
1730 | double theRoll, |
1731 | bool theToRestartOnIncrement) |
1732 | { |
1733 | if (!myToAllowRotation) |
1734 | { |
1735 | return; |
1736 | } |
1737 | |
1738 | const Handle(Graphic3d_Camera)& aCam = theView->Camera(); |
1739 | const bool toRotateAnyway = Abs (theYawExtra) > gp::Resolution() |
1740 | || Abs (thePitchExtra) > gp::Resolution() |
1741 | || Abs (theRoll - myRotateStartYawPitchRoll[2]) > gp::Resolution(); |
1742 | if (toRotateAnyway |
1743 | && theToRestartOnIncrement) |
1744 | { |
1745 | myGL.ViewRotation.ToStart = true; |
1746 | myGL.ViewRotation.PointTo = myGL.ViewRotation.PointStart; |
1747 | } |
1748 | if (myGL.ViewRotation.ToStart) |
1749 | { |
1750 | gp_Trsf aTrsf; |
1751 | aTrsf.SetTransformation (gp_Ax3 (gp::Origin(), aCam->OrthogonalizedUp(), aCam->Direction()), |
1752 | gp_Ax3 (gp::Origin(), gp::DZ(), gp::DX())); |
1753 | const gp_Quaternion aRot = aTrsf.GetRotation(); |
1754 | double aRollDummy = 0.0; |
1755 | aRot.GetEulerAngles (gp_YawPitchRoll, myRotateStartYawPitchRoll[0], myRotateStartYawPitchRoll[1], aRollDummy); |
1756 | } |
1757 | if (toRotateAnyway) |
1758 | { |
1759 | myRotateStartYawPitchRoll[0] += theYawExtra; |
1760 | myRotateStartYawPitchRoll[1] += thePitchExtra; |
1761 | myRotateStartYawPitchRoll[2] = theRoll; |
1762 | myGL.ViewRotation.ToRotate = true; |
1763 | } |
1764 | |
1765 | if (!myGL.ViewRotation.ToRotate) |
1766 | { |
1767 | return; |
1768 | } |
1769 | |
2108d9a2 |
1770 | AbortViewAnimation(); |
1771 | |
49582f9d |
1772 | Graphic3d_Vec2i aWinXY; |
1773 | theView->Window()->Size (aWinXY.x(), aWinXY.y()); |
1774 | double aYawAngleDelta = ((myGL.ViewRotation.PointStart.x() - myGL.ViewRotation.PointTo.x()) / double (aWinXY.x())) * (M_PI * 0.5); |
1775 | double aPitchAngleDelta = -((myGL.ViewRotation.PointStart.y() - myGL.ViewRotation.PointTo.y()) / double (aWinXY.y())) * (M_PI * 0.5); |
1776 | const double aPitchAngleNew = Max (Min (myRotateStartYawPitchRoll[1] + aPitchAngleDelta, M_PI * 0.5 - M_PI / 180.0), -M_PI * 0.5 + M_PI / 180.0); |
1777 | const double aYawAngleNew = myRotateStartYawPitchRoll[0] + aYawAngleDelta; |
1778 | gp_Quaternion aRot; |
1779 | aRot.SetEulerAngles (gp_YawPitchRoll, aYawAngleNew, aPitchAngleNew, theRoll); |
1780 | gp_Trsf aTrsfRot; |
1781 | aTrsfRot.SetRotation (aRot); |
1782 | |
49582f9d |
1783 | const gp_Dir aNewUp = gp::DZ().Transformed (aTrsfRot); |
1784 | const gp_Dir aNewDir = gp::DX().Transformed (aTrsfRot); |
607e5e62 |
1785 | aCam->SetUp (aNewUp); |
1786 | aCam->SetDirectionFromEye (aNewDir); |
49582f9d |
1787 | aCam->OrthogonalizeUp(); |
1788 | theView->Invalidate(); |
1789 | } |
1790 | |
1791 | // ======================================================================= |
1792 | // function : PickPoint |
1793 | // purpose : |
1794 | // ======================================================================= |
1795 | bool AIS_ViewController::PickPoint (gp_Pnt& thePnt, |
1796 | const Handle(AIS_InteractiveContext)& theCtx, |
1797 | const Handle(V3d_View)& theView, |
1798 | const Graphic3d_Vec2i& theCursor, |
1799 | bool theToStickToPickRay) |
1800 | { |
1801 | ResetPreviousMoveTo(); |
1802 | |
1803 | const Handle(StdSelect_ViewerSelector3d)& aSelector = theCtx->MainSelector(); |
1804 | aSelector->Pick (theCursor.x(), theCursor.y(), theView); |
1805 | if (aSelector->NbPicked() < 1) |
1806 | { |
1807 | return false; |
1808 | } |
1809 | |
1810 | const SelectMgr_SortCriterion& aPicked = aSelector->PickedData (1); |
1811 | if (theToStickToPickRay |
1812 | && !Precision::IsInfinite (aPicked.Depth)) |
1813 | { |
1814 | thePnt = aSelector->GetManager().DetectedPoint (aPicked.Depth); |
1815 | } |
1816 | else |
1817 | { |
1818 | thePnt = aSelector->PickedPoint (1); |
1819 | } |
1820 | return !Precision::IsInfinite (thePnt.X()) |
1821 | && !Precision::IsInfinite (thePnt.Y()) |
1822 | && !Precision::IsInfinite (thePnt.Z()); |
1823 | } |
1824 | |
1825 | // ======================================================================= |
1826 | // function : GravityPoint |
1827 | // purpose : |
1828 | // ======================================================================= |
1829 | gp_Pnt AIS_ViewController::GravityPoint (const Handle(AIS_InteractiveContext)& theCtx, |
1830 | const Handle(V3d_View)& theView) |
1831 | { |
1832 | switch (myRotationMode) |
1833 | { |
1834 | case AIS_RotationMode_PickLast: |
1835 | case AIS_RotationMode_PickCenter: |
1836 | { |
1837 | Graphic3d_Vec2i aCursor ((int )myGL.OrbitRotation.PointStart.x(), (int )myGL.OrbitRotation.PointStart.y()); |
1838 | if (myRotationMode == AIS_RotationMode_PickCenter) |
1839 | { |
1840 | Graphic3d_Vec2i aViewPort; |
1841 | theView->Window()->Size (aViewPort.x(), aViewPort.y()); |
1842 | aCursor = aViewPort / 2; |
1843 | } |
1844 | |
1845 | gp_Pnt aPnt; |
9460f8c0 |
1846 | if (PickPoint (aPnt, theCtx, theView, aCursor, myToStickToRayOnRotation)) |
49582f9d |
1847 | { |
1848 | return aPnt; |
1849 | } |
1850 | break; |
1851 | } |
1852 | case AIS_RotationMode_CameraAt: |
1853 | { |
1854 | const Handle(Graphic3d_Camera)& aCam = theView->Camera(); |
1855 | return aCam->Center(); |
1856 | } |
1857 | case AIS_RotationMode_BndBoxScene: |
1858 | { |
1859 | Bnd_Box aBndBox = theView->View()->MinMaxValues (false); |
1860 | if (!aBndBox.IsVoid()) |
1861 | { |
1862 | return (aBndBox.CornerMin().XYZ() + aBndBox.CornerMax().XYZ()) * 0.5; |
1863 | } |
1864 | break; |
1865 | } |
1866 | case AIS_RotationMode_BndBoxActive: |
1867 | break; |
1868 | } |
1869 | |
1870 | return theCtx ->GravityPoint (theView); |
1871 | } |
1872 | |
d6fbb2ab |
1873 | // ======================================================================= |
1874 | // function : FitAllAuto |
1875 | // purpose : |
1876 | // ======================================================================= |
1877 | void AIS_ViewController::FitAllAuto (const Handle(AIS_InteractiveContext)& theCtx, |
1878 | const Handle(V3d_View)& theView) |
1879 | { |
1880 | const Bnd_Box aBoxSel = theCtx->BoundingBoxOfSelection(); |
1881 | const double aFitMargin = 0.01; |
1882 | if (aBoxSel.IsVoid()) |
1883 | { |
1884 | theView->FitAll (aFitMargin, false); |
1885 | return; |
1886 | } |
1887 | |
1888 | // fit all algorithm is not 100% stable - so compute some precision to compare equal camera values |
1889 | const double aFitTol = (aBoxSel.CornerMax().XYZ() - aBoxSel.CornerMin().XYZ()).Modulus() * 0.000001; |
1890 | const Bnd_Box aBoxAll = theView->View()->MinMaxValues(); |
1891 | |
1892 | const Handle(Graphic3d_Camera)& aCam = theView->Camera(); |
1893 | Handle(Graphic3d_Camera) aCameraSel = new Graphic3d_Camera (aCam); |
1894 | Handle(Graphic3d_Camera) aCameraAll = new Graphic3d_Camera (aCam); |
1895 | theView->FitMinMax (aCameraSel, aBoxSel, aFitMargin); |
1896 | theView->FitMinMax (aCameraAll, aBoxAll, aFitMargin); |
1897 | if (aCameraSel->Center().IsEqual (aCam->Center(), aFitTol) |
1898 | && Abs (aCameraSel->Scale() - aCam->Scale()) < aFitTol |
1899 | && Abs (aCameraSel->Distance() - aCam->Distance()) < aFitTol) |
1900 | { |
1901 | // fit all entire view on second FitALL request |
1902 | aCam->Copy (aCameraAll); |
1903 | } |
1904 | else |
1905 | { |
1906 | aCam->Copy (aCameraSel); |
1907 | } |
1908 | } |
1909 | |
1910 | // ======================================================================= |
1911 | // function : handleViewOrientationKeys |
1912 | // purpose : |
1913 | // ======================================================================= |
1914 | void AIS_ViewController::handleViewOrientationKeys (const Handle(AIS_InteractiveContext)& theCtx, |
1915 | const Handle(V3d_View)& theView) |
1916 | { |
1917 | if (myNavigationMode == AIS_NavigationMode_FirstPersonWalk) |
1918 | { |
1919 | return; |
1920 | } |
1921 | |
1922 | Handle(Graphic3d_Camera) aCameraBack; |
1923 | struct ViewKeyAction |
1924 | { |
1925 | Aspect_VKey Key; |
1926 | V3d_TypeOfOrientation Orientation; |
1927 | }; |
1928 | static const ViewKeyAction THE_VIEW_KEYS[] = |
1929 | { |
1930 | { Aspect_VKey_ViewTop, V3d_TypeOfOrientation_Zup_Top }, |
1931 | { Aspect_VKey_ViewBottom, V3d_TypeOfOrientation_Zup_Bottom }, |
1932 | { Aspect_VKey_ViewLeft, V3d_TypeOfOrientation_Zup_Left }, |
1933 | { Aspect_VKey_ViewRight, V3d_TypeOfOrientation_Zup_Right }, |
1934 | { Aspect_VKey_ViewFront, V3d_TypeOfOrientation_Zup_Front }, |
1935 | { Aspect_VKey_ViewBack, V3d_TypeOfOrientation_Zup_Back }, |
1936 | { Aspect_VKey_ViewAxoLeftProj, V3d_TypeOfOrientation_Zup_AxoLeft }, |
1937 | { Aspect_VKey_ViewAxoRightProj, V3d_TypeOfOrientation_Zup_AxoRight }, |
1938 | { Aspect_VKey_ViewRoll90CW, (V3d_TypeOfOrientation )-1}, |
1939 | { Aspect_VKey_ViewRoll90CCW, (V3d_TypeOfOrientation )-1}, |
1940 | { Aspect_VKey_ViewFitAll, (V3d_TypeOfOrientation )-1} |
1941 | }; |
1942 | { |
1943 | Standard_Mutex::Sentry aLock (myKeys.Mutex()); |
1944 | const size_t aNbKeys = sizeof(THE_VIEW_KEYS) / sizeof(*THE_VIEW_KEYS); |
1945 | const double anEventTime = EventTime(); |
1946 | for (size_t aKeyIter = 0; aKeyIter < aNbKeys; ++aKeyIter) |
1947 | { |
1948 | const ViewKeyAction& aKeyAction = THE_VIEW_KEYS[aKeyIter]; |
1949 | if (!myKeys.IsKeyDown (aKeyAction.Key)) |
1950 | { |
1951 | continue; |
1952 | } |
1953 | |
1954 | myKeys.KeyUp (aKeyAction.Key, anEventTime); |
1955 | if (aCameraBack.IsNull()) |
1956 | { |
1957 | aCameraBack = theView->Camera(); |
1958 | theView->SetCamera (new Graphic3d_Camera (aCameraBack)); |
1959 | } |
1960 | if (aKeyAction.Orientation != (V3d_TypeOfOrientation )-1) |
1961 | { |
1962 | theView->SetProj (aKeyAction.Orientation); |
1963 | FitAllAuto (theCtx, theView); |
1964 | } |
1965 | else if (aKeyAction.Key == Aspect_VKey_ViewRoll90CW) |
1966 | { |
1967 | const double aTwist = theView->Twist() + M_PI / 2.0; |
1968 | theView->SetTwist (aTwist); |
1969 | } |
1970 | else if (aKeyAction.Key == Aspect_VKey_ViewRoll90CCW) |
1971 | { |
1972 | const double aTwist = theView->Twist() - M_PI / 2.0; |
1973 | theView->SetTwist (aTwist); |
1974 | } |
1975 | else if (aKeyAction.Key == Aspect_VKey_ViewFitAll) |
1976 | { |
1977 | FitAllAuto (theCtx, theView); |
1978 | } |
1979 | } |
1980 | } |
1981 | |
1982 | if (aCameraBack.IsNull()) |
1983 | { |
1984 | return; |
1985 | } |
1986 | |
1987 | Handle(Graphic3d_Camera) aCameraNew = theView->Camera(); |
1988 | theView->SetCamera (aCameraBack); |
1989 | const Graphic3d_Mat4d anOrientMat1 = aCameraBack->OrientationMatrix(); |
1990 | const Graphic3d_Mat4d anOrientMat2 = aCameraNew ->OrientationMatrix(); |
1991 | if (anOrientMat1 != anOrientMat2) |
1992 | { |
1993 | const Handle(AIS_AnimationCamera)& aCamAnim = myViewAnimation; |
1994 | aCamAnim->SetView (theView); |
1995 | aCamAnim->SetStartPts (0.0); |
1996 | aCamAnim->SetCameraStart (new Graphic3d_Camera (aCameraBack)); |
1997 | aCamAnim->SetCameraEnd (new Graphic3d_Camera (aCameraNew)); |
1998 | aCamAnim->StartTimer (0.0, 1.0, true, false); |
1999 | } |
2000 | } |
2001 | |
d22962e4 |
2002 | // ======================================================================= |
2003 | // function : handleNavigationKeys |
2004 | // purpose : |
2005 | // ======================================================================= |
2006 | AIS_WalkDelta AIS_ViewController::handleNavigationKeys (const Handle(AIS_InteractiveContext)& , |
2007 | const Handle(V3d_View)& theView) |
2008 | { |
2009 | // navigation keys |
2010 | double aCrouchRatio = 1.0, aRunRatio = 1.0; |
2011 | if (myNavigationMode == AIS_NavigationMode_FirstPersonFlight) |
2012 | { |
2013 | aRunRatio = 3.0; |
2014 | } |
2015 | |
2016 | const double aRotSpeed = 0.5; |
2017 | const double aWalkSpeedCoef = WalkSpeedRelative(); |
2018 | AIS_WalkDelta aWalk = FetchNavigationKeys (aCrouchRatio, aRunRatio); |
2019 | if (aWalk.IsJumping()) |
2020 | { |
2021 | // ask more frames |
2022 | setAskNextFrame(); |
2023 | theView->Invalidate(); |
2024 | } |
2025 | if (aWalk.IsEmpty()) |
2026 | { |
2027 | return aWalk; |
2028 | } |
2029 | else if (myGL.OrbitRotation.ToRotate |
2030 | || myGL.OrbitRotation.ToStart) |
2031 | { |
2032 | return aWalk; |
2033 | } |
2034 | |
2035 | gp_XYZ aMin, aMax; |
2036 | const Bnd_Box aBndBox = theView->View()->MinMaxValues(); |
2037 | if (!aBndBox.IsVoid()) |
2038 | { |
2039 | aMin = aBndBox.CornerMin().XYZ(); |
2040 | aMax = aBndBox.CornerMax().XYZ(); |
2041 | } |
2042 | double aBndDiam = Max (Max (aMax.X() - aMin.X(), aMax.Y() - aMin.Y()), aMax.Z() - aMin.Z()); |
2043 | if (aBndDiam <= gp::Resolution()) |
2044 | { |
2045 | aBndDiam = 0.001; |
2046 | } |
2047 | |
2048 | const double aWalkSpeed = myNavigationMode != AIS_NavigationMode_Orbit |
2049 | && myNavigationMode != AIS_NavigationMode_FirstPersonFlight |
2050 | ? theView->View()->UnitFactor() * WalkSpeedAbsolute() |
2051 | : aWalkSpeedCoef * aBndDiam; |
2052 | const Handle(Graphic3d_Camera)& aCam = theView->View()->IsActiveXR() |
2053 | ? theView->View()->BaseXRCamera() |
2054 | : theView->Camera(); |
2055 | |
2056 | // move forward in plane XY and up along Z |
2057 | const gp_Dir anUp = ToLockOrbitZUp() ? gp::DZ() : aCam->OrthogonalizedUp(); |
2058 | if (aWalk.ToMove() |
2059 | && myToAllowPanning) |
2060 | { |
2061 | const gp_Vec aSide = -aCam->SideRight(); |
2062 | gp_XYZ aFwd = aCam->Direction().XYZ(); |
2063 | aFwd -= anUp.XYZ() * (anUp.XYZ() * aFwd); |
2064 | |
2065 | gp_XYZ aMoveVec; |
2066 | if (!aWalk[AIS_WalkTranslation_Forward].IsEmpty()) |
2067 | { |
2068 | if (!aCam->IsOrthographic()) |
2069 | { |
2070 | aMoveVec += aFwd * aWalk[AIS_WalkTranslation_Forward].Value * aWalk[AIS_WalkTranslation_Forward].Pressure * aWalkSpeed; |
2071 | } |
2072 | } |
2073 | if (!aWalk[AIS_WalkTranslation_Side].IsEmpty()) |
2074 | { |
2075 | aMoveVec += aSide.XYZ() * aWalk[AIS_WalkTranslation_Side].Value * aWalk[AIS_WalkTranslation_Side].Pressure * aWalkSpeed; |
2076 | } |
2077 | if (!aWalk[AIS_WalkTranslation_Up].IsEmpty()) |
2078 | { |
2079 | aMoveVec += anUp.XYZ() * aWalk[AIS_WalkTranslation_Up].Value * aWalk[AIS_WalkTranslation_Up].Pressure * aWalkSpeed; |
2080 | } |
2081 | { |
2082 | if (aCam->IsOrthographic()) |
2083 | { |
2084 | if (!aWalk[AIS_WalkTranslation_Forward].IsEmpty()) |
2085 | { |
2086 | const double aZoomDelta = aWalk[AIS_WalkTranslation_Forward].Value * aWalk[AIS_WalkTranslation_Forward].Pressure * aWalkSpeedCoef; |
2087 | handleZoom (theView, Aspect_ScrollDelta (aZoomDelta * 100.0), NULL); |
2088 | } |
2089 | } |
2090 | |
2091 | gp_Trsf aTrsfTranslate; |
2092 | aTrsfTranslate.SetTranslation (aMoveVec); |
2093 | aCam->Transform (aTrsfTranslate); |
2094 | } |
2095 | } |
2096 | |
2097 | if (myNavigationMode == AIS_NavigationMode_Orbit |
2098 | && myToAllowRotation) |
2099 | { |
2100 | if (!aWalk[AIS_WalkRotation_Yaw].IsEmpty()) |
2101 | { |
2102 | gp_Trsf aTrsfRot; |
2103 | aTrsfRot.SetRotation (gp_Ax1 (aCam->Eye(), anUp), aWalk[AIS_WalkRotation_Yaw].Value * aRotSpeed); |
2104 | aCam->Transform (aTrsfRot); |
2105 | } |
2106 | if (!aWalk[AIS_WalkRotation_Pitch].IsEmpty()) |
2107 | { |
2108 | const gp_Vec aSide = -aCam->SideRight(); |
2109 | gp_Trsf aTrsfRot; |
2110 | aTrsfRot.SetRotation (gp_Ax1 (aCam->Eye(), aSide), -aWalk[AIS_WalkRotation_Pitch].Value * aRotSpeed); |
2111 | aCam->Transform (aTrsfRot); |
2112 | } |
2113 | if (!aWalk[AIS_WalkRotation_Roll].IsEmpty() |
2114 | && !ToLockOrbitZUp()) |
2115 | { |
2116 | gp_Trsf aTrsfRot; |
2117 | aTrsfRot.SetRotation (gp_Ax1 (aCam->Center(), aCam->Direction()), aWalk[AIS_WalkRotation_Roll].Value * aRotSpeed); |
2118 | aCam->Transform (aTrsfRot); |
2119 | } |
2120 | } |
2121 | |
2122 | // ask more frames |
2123 | setAskNextFrame(); |
2124 | theView->Invalidate(); |
2125 | theView->View()->SynchronizeXRBaseToPosedCamera(); |
2126 | return aWalk; |
2127 | } |
2128 | |
49582f9d |
2129 | // ======================================================================= |
2130 | // function : handleCameraActions |
2131 | // purpose : |
2132 | // ======================================================================= |
2133 | void AIS_ViewController::handleCameraActions (const Handle(AIS_InteractiveContext)& theCtx, |
2134 | const Handle(V3d_View)& theView, |
2135 | const AIS_WalkDelta& theWalk) |
2136 | { |
2137 | // apply view actions |
2138 | if (myGL.Orientation.ToSetViewOrient) |
2139 | { |
2140 | theView->SetProj (myGL.Orientation.ViewOrient); |
2141 | myGL.Orientation.ToFitAll = true; |
2142 | } |
2143 | |
2144 | // apply fit all |
2145 | if (myGL.Orientation.ToFitAll) |
2146 | { |
2147 | const double aFitMargin = 0.01; |
2148 | theView->FitAll (aFitMargin, false); |
2149 | theView->Invalidate(); |
2150 | myGL.Orientation.ToFitAll = false; |
2151 | } |
2152 | |
2153 | if (myGL.IsNewGesture) |
2154 | { |
2155 | if (myAnchorPointPrs1->HasInteractiveContext()) |
2156 | { |
2157 | theCtx->Remove (myAnchorPointPrs1, false); |
2158 | if (!theView->Viewer()->ZLayerSettings (myAnchorPointPrs1->ZLayer()).IsImmediate()) |
2159 | { |
2160 | theView->Invalidate(); |
2161 | } |
2162 | else |
2163 | { |
2164 | theView->InvalidateImmediate(); |
2165 | } |
2166 | } |
2167 | if (myAnchorPointPrs2->HasInteractiveContext()) |
2168 | { |
2169 | theCtx->Remove (myAnchorPointPrs2, false); |
2170 | if (!theView->Viewer()->ZLayerSettings (myAnchorPointPrs2->ZLayer()).IsImmediate()) |
2171 | { |
2172 | theView->Invalidate(); |
2173 | } |
2174 | else |
2175 | { |
2176 | theView->InvalidateImmediate(); |
2177 | } |
2178 | } |
2179 | |
2180 | if (myHasHlrOnBeforeRotation) |
2181 | { |
2182 | myHasHlrOnBeforeRotation = false; |
2183 | theView->SetComputedMode (true); |
2184 | theView->Invalidate(); |
2185 | } |
2186 | } |
2187 | |
2188 | if (myNavigationMode != AIS_NavigationMode_FirstPersonWalk) |
2189 | { |
2190 | if (myGL.Panning.ToStart |
2191 | && myToAllowPanning) |
2192 | { |
2193 | gp_Pnt aPanPnt (Precision::Infinite(), 0.0, 0.0); |
2194 | if (!theView->Camera()->IsOrthographic()) |
2195 | { |
2196 | bool toStickToRay = false; |
2197 | if (myGL.Panning.PointStart.x() >= 0 |
2198 | && myGL.Panning.PointStart.y() >= 0) |
2199 | { |
2200 | PickPoint (aPanPnt, theCtx, theView, myGL.Panning.PointStart, toStickToRay); |
2201 | } |
2202 | if (Precision::IsInfinite (aPanPnt.X())) |
2203 | { |
2204 | Graphic3d_Vec2i aWinSize; |
2205 | theView->Window()->Size (aWinSize.x(), aWinSize.y()); |
2206 | PickPoint (aPanPnt, theCtx, theView, aWinSize / 2, toStickToRay); |
2207 | } |
2208 | if (!Precision::IsInfinite (aPanPnt.X()) |
2209 | && myToShowPanAnchorPoint) |
2210 | { |
2211 | gp_Trsf aPntTrsf; |
2212 | aPntTrsf.SetTranslation (gp_Vec (aPanPnt.XYZ())); |
2213 | theCtx->SetLocation (myAnchorPointPrs2, aPntTrsf); |
2214 | } |
2215 | } |
2216 | setPanningAnchorPoint (aPanPnt); |
2217 | } |
2218 | |
2219 | if (myToShowPanAnchorPoint |
2220 | && hasPanningAnchorPoint() |
2221 | && myGL.Panning.ToPan |
2222 | && !myGL.IsNewGesture |
2223 | && !myAnchorPointPrs2->HasInteractiveContext()) |
2224 | { |
2225 | theCtx->Display (myAnchorPointPrs2, 0, -1, false, AIS_DS_Displayed); |
2226 | } |
2227 | |
2228 | handlePanning (theView); |
2229 | handleZRotate (theView); |
2230 | } |
2231 | |
2232 | if ((myNavigationMode == AIS_NavigationMode_Orbit |
2233 | || myGL.OrbitRotation.ToStart |
2234 | || myGL.OrbitRotation.ToRotate) |
2235 | && myToAllowRotation) |
2236 | { |
2237 | if (myGL.OrbitRotation.ToStart |
2238 | && !myHasHlrOnBeforeRotation) |
2239 | { |
2240 | myHasHlrOnBeforeRotation = theView->ComputedMode(); |
2241 | if (myHasHlrOnBeforeRotation) |
2242 | { |
2243 | theView->SetComputedMode (false); |
2244 | } |
2245 | } |
2246 | |
2247 | gp_Pnt aGravPnt; |
2248 | if (myGL.OrbitRotation.ToStart) |
2249 | { |
2250 | aGravPnt = GravityPoint (theCtx, theView); |
2251 | if (myToShowRotateCenter) |
2252 | { |
2253 | gp_Trsf aPntTrsf; |
2254 | aPntTrsf.SetTranslation (gp_Vec (aGravPnt.XYZ())); |
2255 | theCtx->SetLocation (myAnchorPointPrs1, aPntTrsf); |
2256 | theCtx->SetLocation (myAnchorPointPrs2, aPntTrsf); |
2257 | } |
2258 | } |
2259 | |
2260 | if (myToShowRotateCenter |
2261 | && myGL.OrbitRotation.ToRotate |
2262 | && !myGL.IsNewGesture |
2263 | && !myAnchorPointPrs1->HasInteractiveContext()) |
2264 | { |
2265 | theCtx->Display (myAnchorPointPrs1, 0, -1, false, AIS_DS_Displayed); |
2266 | theCtx->Display (myAnchorPointPrs2, 0, -1, false, AIS_DS_Displayed); |
2267 | } |
2268 | handleOrbitRotation (theView, aGravPnt, |
2269 | myToLockOrbitZUp || myNavigationMode != AIS_NavigationMode_Orbit); |
2270 | } |
2271 | |
2272 | if ((myNavigationMode != AIS_NavigationMode_Orbit |
2273 | || myGL.ViewRotation.ToStart |
2274 | || myGL.ViewRotation.ToRotate) |
2275 | && myToAllowRotation) |
2276 | { |
2277 | if (myGL.ViewRotation.ToStart |
2278 | && !myHasHlrOnBeforeRotation) |
2279 | { |
2280 | myHasHlrOnBeforeRotation = theView->ComputedMode(); |
2281 | if (myHasHlrOnBeforeRotation) |
2282 | { |
2283 | theView->SetComputedMode (false); |
2284 | } |
2285 | } |
2286 | |
2287 | double aRoll = 0.0; |
2288 | if (!theWalk[AIS_WalkRotation_Roll].IsEmpty() |
2289 | && !myToLockOrbitZUp) |
2290 | { |
2291 | aRoll = (M_PI / 12.0) * theWalk[AIS_WalkRotation_Roll].Pressure; |
2292 | aRoll *= Min (1000.0 * theWalk[AIS_WalkRotation_Roll].Duration, 100.0) / 100.0; |
2293 | if (theWalk[AIS_WalkRotation_Roll].Value < 0.0) |
2294 | { |
2295 | aRoll = -aRoll; |
2296 | } |
2297 | } |
2298 | |
2299 | handleViewRotation (theView, theWalk[AIS_WalkRotation_Yaw].Value, theWalk[AIS_WalkRotation_Pitch].Value, aRoll, |
2300 | myNavigationMode == AIS_NavigationMode_FirstPersonFlight); |
2301 | } |
2302 | |
2303 | if (!myGL.ZoomActions.IsEmpty()) |
2304 | { |
2305 | for (NCollection_Sequence<Aspect_ScrollDelta>::Iterator aZoomIter (myGL.ZoomActions); aZoomIter.More(); aZoomIter.Next()) |
2306 | { |
2307 | Aspect_ScrollDelta aZoomParams = aZoomIter.Value(); |
2308 | if (myToAllowZFocus |
2309 | && (aZoomParams.Flags & Aspect_VKeyFlags_CTRL) != 0 |
2310 | && theView->Camera()->IsStereo()) |
2311 | { |
2312 | handleZFocusScroll (theView, aZoomParams); |
2313 | continue; |
2314 | } |
2315 | |
2316 | if (!myToAllowZooming) |
2317 | { |
2318 | continue; |
2319 | } |
2320 | |
2321 | if (!theView->Camera()->IsOrthographic()) |
2322 | { |
49582f9d |
2323 | gp_Pnt aPnt; |
2324 | if (aZoomParams.HasPoint() |
9460f8c0 |
2325 | && PickPoint (aPnt, theCtx, theView, aZoomParams.Point, myToStickToRayOnZoom)) |
49582f9d |
2326 | { |
2327 | handleZoom (theView, aZoomParams, &aPnt); |
2328 | continue; |
2329 | } |
2330 | |
2331 | Graphic3d_Vec2i aWinSize; |
2332 | theView->Window()->Size (aWinSize.x(), aWinSize.y()); |
9460f8c0 |
2333 | if (PickPoint (aPnt, theCtx, theView, aWinSize / 2, myToStickToRayOnZoom)) |
49582f9d |
2334 | { |
2335 | aZoomParams.ResetPoint(); // do not pretend to zoom at 'nothing' |
2336 | handleZoom (theView, aZoomParams, &aPnt); |
2337 | continue; |
2338 | } |
2339 | } |
2340 | handleZoom (theView, aZoomParams, NULL); |
2341 | } |
2342 | myGL.ZoomActions.Clear(); |
2343 | } |
2344 | } |
2345 | |
b40cdc2b |
2346 | // ======================================================================= |
2347 | // function : handleXRInput |
2348 | // purpose : |
2349 | // ======================================================================= |
2350 | void AIS_ViewController::handleXRInput (const Handle(AIS_InteractiveContext)& theCtx, |
2351 | const Handle(V3d_View)& theView, |
2352 | const AIS_WalkDelta& ) |
2353 | { |
2354 | theView->View()->ProcessXRInput(); |
2355 | if (!theView->View()->IsActiveXR()) |
2356 | { |
2357 | return; |
2358 | } |
2359 | if (myXRCameraTmp.IsNull()) |
2360 | { |
2361 | myXRCameraTmp = new Graphic3d_Camera(); |
2362 | } |
2363 | handleXRTurnPad (theCtx, theView); |
2364 | handleXRTeleport(theCtx, theView); |
2365 | handleXRPicking (theCtx, theView); |
2366 | } |
2367 | |
2368 | // ======================================================================= |
2369 | // function : handleXRTurnPad |
2370 | // purpose : |
2371 | // ======================================================================= |
2372 | void AIS_ViewController::handleXRTurnPad (const Handle(AIS_InteractiveContext)& , |
2373 | const Handle(V3d_View)& theView) |
2374 | { |
2375 | if (myXRTurnAngle <= 0.0 |
2376 | || !theView->View()->IsActiveXR()) |
2377 | { |
2378 | return; |
2379 | } |
2380 | |
2381 | // turn left/right at 45 degrees on left/right trackpad clicks |
2382 | for (int aHand = 0; aHand < 2; ++aHand) |
2383 | { |
2384 | const Aspect_XRTrackedDeviceRole aRole = aHand == 0 ? Aspect_XRTrackedDeviceRole_RightHand : Aspect_XRTrackedDeviceRole_LeftHand; |
2385 | const Handle(Aspect_XRAction)& aPadClickAct = theView->View()->XRSession()->GenericAction (aRole, Aspect_XRGenericAction_InputTrackPadClick); |
2386 | const Handle(Aspect_XRAction)& aPadPosAct = theView->View()->XRSession()->GenericAction (aRole, Aspect_XRGenericAction_InputTrackPadPosition); |
2387 | if (aPadClickAct.IsNull() |
2388 | || aPadPosAct.IsNull()) |
2389 | { |
2390 | continue; |
2391 | } |
2392 | |
2393 | const Aspect_XRDigitalActionData aPadClick = theView->View()->XRSession()->GetDigitalActionData (aPadClickAct); |
2394 | const Aspect_XRAnalogActionData aPadPos = theView->View()->XRSession()->GetAnalogActionData (aPadPosAct); |
2395 | if (aPadClick.IsActive |
2396 | && aPadClick.IsPressed |
2397 | && aPadClick.IsChanged |
2398 | && aPadPos.IsActive |
2399 | && Abs (aPadPos.VecXYZ.y()) < 0.5f |
2400 | && Abs (aPadPos.VecXYZ.x()) > 0.7f) |
2401 | { |
2402 | gp_Trsf aTrsfTurn; |
2403 | aTrsfTurn.SetRotation (gp_Ax1 (gp::Origin(), theView->View()->BaseXRCamera()->Up()), aPadPos.VecXYZ.x() < 0.0f ? myXRTurnAngle : -myXRTurnAngle); |
2404 | theView->View()->TurnViewXRCamera (aTrsfTurn); |
2405 | break; |
2406 | } |
2407 | } |
2408 | } |
2409 | |
2410 | // ======================================================================= |
2411 | // function : handleXRTeleport |
2412 | // purpose : |
2413 | // ======================================================================= |
2414 | void AIS_ViewController::handleXRTeleport (const Handle(AIS_InteractiveContext)& theCtx, |
2415 | const Handle(V3d_View)& theView) |
2416 | { |
2417 | if (!theView->View()->IsActiveXR()) |
2418 | { |
2419 | return; |
2420 | } |
2421 | |
2422 | // teleport on forward trackpad unclicks |
2423 | const Aspect_XRTrackedDeviceRole aTeleOld = myXRLastTeleportHand; |
2424 | myXRLastTeleportHand = Aspect_XRTrackedDeviceRole_Other; |
2425 | for (int aHand = 0; aHand < 2; ++aHand) |
2426 | { |
2427 | const Aspect_XRTrackedDeviceRole aRole = aHand == 0 ? Aspect_XRTrackedDeviceRole_RightHand : Aspect_XRTrackedDeviceRole_LeftHand; |
2428 | const Standard_Integer aDeviceId = theView->View()->XRSession()->NamedTrackedDevice (aRole); |
2429 | if (aDeviceId == -1) |
2430 | { |
2431 | continue; |
2432 | } |
2433 | |
2434 | const Handle(Aspect_XRAction)& aPadClickAct = theView->View()->XRSession()->GenericAction (aRole, Aspect_XRGenericAction_InputTrackPadClick); |
2435 | const Handle(Aspect_XRAction)& aPadPosAct = theView->View()->XRSession()->GenericAction (aRole, Aspect_XRGenericAction_InputTrackPadPosition); |
2436 | if (aPadClickAct.IsNull() |
2437 | || aPadPosAct.IsNull()) |
2438 | { |
2439 | continue; |
2440 | } |
2441 | |
2442 | const Aspect_XRDigitalActionData aPadClick = theView->View()->XRSession()->GetDigitalActionData (aPadClickAct); |
2443 | const Aspect_XRAnalogActionData aPadPos = theView->View()->XRSession()->GetAnalogActionData (aPadPosAct); |
2444 | const bool isPressed = aPadClick.IsPressed; |
2445 | const bool isClicked = !aPadClick.IsPressed |
2446 | && aPadClick.IsChanged; |
2447 | if (aPadClick.IsActive |
2448 | && (isPressed || isClicked) |
2449 | && aPadPos.IsActive |
2450 | && aPadPos.VecXYZ.y() > 0.6f |
2451 | && Abs (aPadPos.VecXYZ.x()) < 0.5f) |
2452 | { |
2453 | const Aspect_TrackedDevicePose& aPose = theView->View()->XRSession()->TrackedPoses()[aDeviceId]; |
2454 | if (!aPose.IsValidPose) |
2455 | { |
2456 | continue; |
2457 | } |
2458 | |
2459 | myXRLastTeleportHand = aRole; |
2460 | Standard_Real& aPickDepth = aRole == Aspect_XRTrackedDeviceRole_LeftHand ? myXRLastPickDepthLeft : myXRLastPickDepthRight; |
2461 | aPickDepth = Precision::Infinite(); |
2462 | Graphic3d_Vec3 aPickNorm; |
2463 | const gp_Trsf aHandBase = theView->View()->PoseXRToWorld (aPose.Orientation); |
2464 | const Standard_Real aHeadHeight = theView->View()->XRSession()->HeadPose().TranslationPart().Y(); |
2465 | { |
2466 | const Standard_Integer aPickedId = handleXRMoveTo (theCtx, theView, aPose.Orientation, false); |
2467 | if (aPickedId >= 1) |
2468 | { |
2469 | const SelectMgr_SortCriterion& aPickedData = theCtx->MainSelector()->PickedData (aPickedId); |
2470 | aPickNorm = aPickedData.Normal; |
2471 | if (aPickNorm.SquareModulus() > ShortRealEpsilon()) |
2472 | { |
2473 | aPickDepth = aPickedData.Point.Distance (aHandBase.TranslationPart()); |
2474 | } |
2475 | } |
2476 | } |
2477 | if (isClicked) |
2478 | { |
2479 | myXRLastTeleportHand = Aspect_XRTrackedDeviceRole_Other; |
2480 | if (!Precision::IsInfinite (aPickDepth)) |
2481 | { |
2482 | const gp_Dir aTeleDir = -gp::DZ().Transformed (aHandBase); |
2483 | const gp_Dir anUpDir = theView->View()->BaseXRCamera()->Up(); |
2484 | |
2485 | bool isHorizontal = false; |
2486 | gp_Dir aPickNormDir (aPickNorm.x(), aPickNorm.y(), aPickNorm.z()); |
2487 | if (anUpDir.IsEqual ( aPickNormDir, M_PI_4) |
2488 | || anUpDir.IsEqual (-aPickNormDir, M_PI_4)) |
2489 | { |
2490 | isHorizontal = true; |
2491 | } |
2492 | |
2493 | gp_Pnt aNewEye = aHandBase.TranslationPart(); |
2494 | if (isHorizontal) |
2495 | { |
2496 | aNewEye = aHandBase.TranslationPart() |
2497 | + aTeleDir.XYZ() * aPickDepth |
2498 | + anUpDir.XYZ() * aHeadHeight; |
2499 | } |
2500 | else |
2501 | { |
2502 | if (aPickNormDir.Dot (aTeleDir) < 0.0) |
2503 | { |
2504 | aPickNormDir.Reverse(); |
2505 | } |
2506 | aNewEye = aHandBase.TranslationPart() |
2507 | + aTeleDir.XYZ() * aPickDepth |
2508 | - aPickNormDir.XYZ() * aHeadHeight / 4; |
2509 | } |
2510 | |
2511 | theView->View()->PosedXRCamera()->MoveEyeTo (aNewEye); |
2512 | theView->View()->ComputeXRBaseCameraFromPosed (theView->View()->PosedXRCamera(), theView->View()->XRSession()->HeadPose()); |
2513 | } |
2514 | } |
2515 | break; |
2516 | } |
2517 | } |
2518 | |
2519 | if (myXRLastTeleportHand != aTeleOld) |
2520 | { |
2521 | if (aTeleOld != Aspect_XRTrackedDeviceRole_Other) |
2522 | { |
2523 | if (const Handle(Aspect_XRAction)& aHaptic = theView->View()->XRSession()->GenericAction (aTeleOld, Aspect_XRGenericAction_OutputHaptic)) |
2524 | { |
2525 | theView->View()->XRSession()->AbortHapticVibrationAction (aHaptic); |
2526 | } |
2527 | } |
2528 | if (myXRLastTeleportHand != Aspect_XRTrackedDeviceRole_Other) |
2529 | { |
2530 | if (const Handle(Aspect_XRAction)& aHaptic = theView->View()->XRSession()->GenericAction (myXRLastTeleportHand, Aspect_XRGenericAction_OutputHaptic)) |
2531 | { |
2532 | theView->View()->XRSession()->TriggerHapticVibrationAction (aHaptic, myXRTeleportHaptic); |
2533 | } |
2534 | } |
2535 | } |
2536 | } |
2537 | |
2538 | // ======================================================================= |
2539 | // function : handleXRPicking |
2540 | // purpose : |
2541 | // ======================================================================= |
2542 | void AIS_ViewController::handleXRPicking (const Handle(AIS_InteractiveContext)& theCtx, |
2543 | const Handle(V3d_View)& theView) |
2544 | { |
2545 | if (!theView->View()->IsActiveXR()) |
2546 | { |
2547 | return; |
2548 | } |
2549 | |
2550 | // handle selection on trigger clicks |
2551 | Aspect_XRTrackedDeviceRole aPickDevOld = myXRLastPickingHand; |
2552 | myXRLastPickingHand = Aspect_XRTrackedDeviceRole_Other; |
2553 | for (int aHand = 0; aHand < 2; ++aHand) |
2554 | { |
2555 | const Aspect_XRTrackedDeviceRole aRole = aHand == 0 ? Aspect_XRTrackedDeviceRole_RightHand : Aspect_XRTrackedDeviceRole_LeftHand; |
2556 | const Handle(Aspect_XRAction)& aTrigClickAct = theView->View()->XRSession()->GenericAction (aRole, Aspect_XRGenericAction_InputTriggerClick); |
2557 | const Handle(Aspect_XRAction)& aTrigPullAct = theView->View()->XRSession()->GenericAction (aRole, Aspect_XRGenericAction_InputTriggerPull); |
2558 | if (aTrigClickAct.IsNull() |
2559 | || aTrigPullAct.IsNull()) |
2560 | { |
2561 | continue; |
2562 | } |
2563 | |
2564 | const Aspect_XRDigitalActionData aTrigClick = theView->View()->XRSession()->GetDigitalActionData (aTrigClickAct); |
2565 | const Aspect_XRAnalogActionData aTrigPos = theView->View()->XRSession()->GetAnalogActionData (aTrigPullAct); |
2566 | if (aTrigPos.IsActive |
2567 | && Abs (aTrigPos.VecXYZ.x()) > 0.1f) |
2568 | { |
2569 | myXRLastPickingHand = aRole; |
2570 | handleXRHighlight (theCtx, theView); |
2571 | if (aTrigClick.IsActive |
2572 | && aTrigClick.IsPressed |
2573 | && aTrigClick.IsChanged) |
2574 | { |
2575 | theCtx->Select (false); |
2576 | OnSelectionChanged (theCtx, theView); |
2577 | if (const Handle(Aspect_XRAction)& aHaptic = theView->View()->XRSession()->GenericAction (myXRLastPickingHand, Aspect_XRGenericAction_OutputHaptic)) |
2578 | { |
2579 | theView->View()->XRSession()->TriggerHapticVibrationAction (aHaptic, myXRSelectHaptic); |
2580 | } |
2581 | } |
2582 | break; |
2583 | } |
2584 | } |
2585 | if (myXRLastPickingHand != aPickDevOld) |
2586 | { |
2587 | theCtx->ClearDetected(); |
2588 | } |
2589 | } |
2590 | |
49582f9d |
2591 | // ======================================================================= |
2592 | // function : OnSelectionChanged |
2593 | // purpose : |
2594 | // ======================================================================= |
2595 | void AIS_ViewController::OnSelectionChanged (const Handle(AIS_InteractiveContext)& , |
2596 | const Handle(V3d_View)& ) |
2597 | { |
2598 | // |
2599 | } |
2600 | |
2601 | // ======================================================================= |
2602 | // function : OnObjectDragged |
2603 | // purpose : |
2604 | // ======================================================================= |
2605 | void AIS_ViewController::OnObjectDragged (const Handle(AIS_InteractiveContext)& theCtx, |
2606 | const Handle(V3d_View)& theView, |
2607 | AIS_DragAction theAction) |
2608 | { |
2609 | switch (theAction) |
2610 | { |
2611 | case AIS_DragAction_Start: |
2612 | { |
2613 | myDragObject.Nullify(); |
2614 | if (!theCtx->HasDetected()) |
2615 | { |
2616 | return; |
2617 | } |
2618 | |
2619 | Handle(AIS_InteractiveObject) aPrs = theCtx->DetectedInteractive(); |
2620 | if (Handle(AIS_Manipulator) aManip = Handle(AIS_Manipulator)::DownCast (aPrs)) |
2621 | { |
2622 | if (aManip->HasActiveMode()) |
2623 | { |
2624 | myDragObject = aManip; |
2625 | aManip->StartTransform (myGL.Dragging.PointStart.x(), myGL.Dragging.PointStart.y(), theView); |
2626 | } |
2627 | } |
2628 | return; |
2629 | } |
2630 | case AIS_DragAction_Update: |
2631 | { |
2632 | if (myDragObject.IsNull()) |
2633 | { |
2634 | return; |
2635 | } |
2636 | |
2637 | if (Handle(SelectMgr_EntityOwner) aGlobOwner = myDragObject->GlobalSelOwner()) |
2638 | { |
2639 | theCtx->SetSelectedState (aGlobOwner, true); |
2640 | } |
2641 | if (Handle(AIS_Manipulator) aManip = Handle(AIS_Manipulator)::DownCast (myDragObject)) |
2642 | { |
2643 | aManip->Transform (myGL.Dragging.PointTo.x(), myGL.Dragging.PointTo.y(), theView); |
2644 | } |
2645 | theView->Invalidate(); |
2646 | return; |
2647 | } |
2648 | case AIS_DragAction_Abort: |
2649 | { |
2650 | if (myDragObject.IsNull()) |
2651 | { |
2652 | return; |
2653 | } |
2654 | |
2655 | myGL.Dragging.PointTo = myGL.Dragging.PointStart; |
2656 | OnObjectDragged (theCtx, theView, AIS_DragAction_Update); |
2657 | |
2658 | if (Handle(AIS_Manipulator) aManip = Handle(AIS_Manipulator)::DownCast (myDragObject)) |
2659 | { |
2660 | aManip->StopTransform (false); |
2661 | } |
2662 | Standard_FALLTHROUGH |
2663 | } |
2664 | case AIS_DragAction_Stop: |
2665 | { |
2666 | if (myDragObject.IsNull()) |
2667 | { |
2668 | return; |
2669 | } |
2670 | |
2671 | if (Handle(SelectMgr_EntityOwner) aGlobOwner = myDragObject->GlobalSelOwner()) |
2672 | { |
2673 | theCtx->SetSelectedState (aGlobOwner, false); |
2674 | } |
2675 | |
2676 | theView->Invalidate(); |
2677 | myDragObject.Nullify(); |
2678 | return; |
2679 | } |
2680 | } |
2681 | } |
2682 | |
2683 | // ======================================================================= |
2684 | // function : contextLazyMoveTo |
2685 | // purpose : |
2686 | // ======================================================================= |
2687 | void AIS_ViewController::contextLazyMoveTo (const Handle(AIS_InteractiveContext)& theCtx, |
2688 | const Handle(V3d_View)& theView, |
2689 | const Graphic3d_Vec2i& thePnt) |
2690 | { |
2691 | if (myPrevMoveTo == thePnt) |
2692 | { |
2693 | return; |
2694 | } |
2695 | |
2696 | myPrevMoveTo = thePnt; |
2697 | |
2698 | Handle(SelectMgr_EntityOwner) aLastPicked = theCtx->DetectedOwner(); |
b40cdc2b |
2699 | theView->AutoZFit(); |
49582f9d |
2700 | theCtx->MoveTo (thePnt.x(), thePnt.y(), theView, false); |
2701 | Handle(SelectMgr_EntityOwner) aNewPicked = theCtx->DetectedOwner(); |
2702 | |
2703 | if (theView->Viewer()->Grid()->IsActive() |
2704 | && theView->Viewer()->GridEcho()) |
2705 | { |
2706 | if (aNewPicked.IsNull()) |
2707 | { |
2708 | Graphic3d_Vec3d aPnt3d; |
2709 | theView->ConvertToGrid (thePnt.x(), thePnt.y(), aPnt3d[0], aPnt3d[1], aPnt3d[2]); |
2710 | theView->Viewer()->ShowGridEcho (theView, Graphic3d_Vertex (aPnt3d[0], aPnt3d[1], aPnt3d[2])); |
2711 | theView->InvalidateImmediate(); |
2712 | } |
2713 | else |
2714 | { |
2715 | theView->Viewer()->HideGridEcho (theView); |
2716 | theView->InvalidateImmediate(); |
2717 | } |
2718 | } |
2719 | |
2720 | if (aLastPicked != aNewPicked |
2721 | || (!aNewPicked.IsNull() && aNewPicked->IsForcedHilight())) |
2722 | { |
2723 | // dynamic highlight affects all Views |
2724 | for (V3d_ListOfViewIterator aViewIter (theView->Viewer()->ActiveViewIterator()); aViewIter.More(); aViewIter.Next()) |
2725 | { |
2726 | const Handle(V3d_View)& aView = aViewIter.Value(); |
2727 | aView->InvalidateImmediate(); |
2728 | } |
2729 | } |
2730 | } |
2731 | |
2732 | // ======================================================================= |
2733 | // function : handleSelectionPick |
2734 | // purpose : |
2735 | // ======================================================================= |
2736 | void AIS_ViewController::handleSelectionPick (const Handle(AIS_InteractiveContext)& theCtx, |
2737 | const Handle(V3d_View)& theView) |
2738 | { |
2739 | if (myGL.Selection.Tool == AIS_ViewSelectionTool_Picking |
2740 | && !myGL.Selection.Points.IsEmpty()) |
2741 | { |
2742 | for (NCollection_Sequence<Graphic3d_Vec2i>::Iterator aPntIter (myGL.Selection.Points); aPntIter.More(); aPntIter.Next()) |
2743 | { |
49582f9d |
2744 | const bool hadPrevMoveTo = HasPreviousMoveTo(); |
2745 | contextLazyMoveTo (theCtx, theView, aPntIter.Value()); |
2746 | if (!hadPrevMoveTo) |
2747 | { |
2748 | ResetPreviousMoveTo(); |
2749 | } |
2750 | |
2751 | if (myGL.Selection.IsXOR) |
2752 | { |
2753 | theCtx->ShiftSelect (false); |
2754 | } |
2755 | else |
2756 | { |
2757 | theCtx->Select (false); |
2758 | } |
2759 | |
2760 | // selection affects all Views |
2761 | theView->Viewer()->Invalidate(); |
2762 | |
2763 | OnSelectionChanged (theCtx, theView); |
2764 | } |
2765 | |
2766 | myGL.Selection.Points.Clear(); |
2767 | } |
2768 | } |
2769 | |
2770 | // ======================================================================= |
2771 | // function : handleSelectionPoly |
2772 | // purpose : |
2773 | // ======================================================================= |
2774 | void AIS_ViewController::handleSelectionPoly (const Handle(AIS_InteractiveContext)& theCtx, |
2775 | const Handle(V3d_View)& theView) |
2776 | { |
2777 | // rubber-band & window polygon selection |
2778 | if (myGL.Selection.Tool == AIS_ViewSelectionTool_RubberBand |
e1c9a103 |
2779 | || myGL.Selection.Tool == AIS_ViewSelectionTool_Polygon |
2780 | || myGL.Selection.Tool == AIS_ViewSelectionTool_ZoomWindow) |
49582f9d |
2781 | { |
2782 | if (!myGL.Selection.Points.IsEmpty()) |
2783 | { |
2784 | myRubberBand->ClearPoints(); |
2785 | myRubberBand->SetToUpdate(); |
2786 | |
e1c9a103 |
2787 | const bool anIsRubber = myGL.Selection.Tool == AIS_ViewSelectionTool_RubberBand |
2788 | || myGL.Selection.Tool == AIS_ViewSelectionTool_ZoomWindow; |
49582f9d |
2789 | if (anIsRubber) |
2790 | { |
2791 | myRubberBand->SetRectangle (myGL.Selection.Points.First().x(), -myGL.Selection.Points.First().y(), |
2792 | myGL.Selection.Points.Last().x(), -myGL.Selection.Points.Last().y()); |
2793 | } |
2794 | else |
2795 | { |
2796 | Graphic3d_Vec2i aPrev (IntegerLast(), IntegerLast()); |
2797 | for (NCollection_Sequence<Graphic3d_Vec2i>::Iterator aSelIter (myGL.Selection.Points); aSelIter.More(); aSelIter.Next()) |
2798 | { |
2799 | Graphic3d_Vec2i aPntNew = Graphic3d_Vec2i (aSelIter.Value().x(), -aSelIter.Value().y()); |
2800 | if (aPntNew != aPrev) |
2801 | { |
2802 | aPrev = aPntNew; |
2803 | myRubberBand->AddPoint (Graphic3d_Vec2i (aSelIter.Value().x(), -aSelIter.Value().y())); |
2804 | } |
2805 | } |
2806 | } |
2807 | |
2808 | myRubberBand->SetPolygonClosed (anIsRubber); |
2809 | try |
2810 | { |
2811 | theCtx->Display (myRubberBand, 0, -1, false, AIS_DS_Displayed); |
2812 | } |
2813 | catch (const Standard_Failure& theEx) |
2814 | { |
a87b1b37 |
2815 | Message::SendWarning (TCollection_AsciiString ("Internal error while displaying rubber-band: ") |
2816 | + theEx.DynamicType()->Name() + ", " + theEx.GetMessageString()); |
49582f9d |
2817 | myRubberBand->ClearPoints(); |
2818 | } |
2819 | if (!theView->Viewer()->ZLayerSettings (myRubberBand->ZLayer()).IsImmediate()) |
2820 | { |
2821 | theView->Invalidate(); |
2822 | } |
2823 | else |
2824 | { |
2825 | theView->InvalidateImmediate(); |
2826 | } |
2827 | } |
2828 | else if (!myRubberBand.IsNull() |
2829 | && myRubberBand->HasInteractiveContext()) |
2830 | { |
2831 | theCtx->Remove (myRubberBand, false); |
2832 | myRubberBand->ClearPoints(); |
2833 | } |
2834 | } |
2835 | |
2836 | if (myGL.Selection.ToApplyTool) |
2837 | { |
2838 | myGL.Selection.ToApplyTool = false; |
2839 | if (theCtx->IsDisplayed (myRubberBand)) |
2840 | { |
2841 | theCtx->Remove (myRubberBand, false); |
2842 | { |
2843 | const NCollection_Sequence<Graphic3d_Vec2i>& aPoints = myRubberBand->Points(); |
2844 | if (aPoints.Size() == 4 |
2845 | && aPoints.Value (1).x() == aPoints.Value (2).x() |
2846 | && aPoints.Value (3).x() == aPoints.Value (4).x() |
2847 | && aPoints.Value (1).y() == aPoints.Value (4).y() |
2848 | && aPoints.Value (2).y() == aPoints.Value (3).y()) |
2849 | { |
2850 | const Graphic3d_Vec2i aPnt1 (aPoints.Value (1).x(), -aPoints.Value (1).y()); |
2851 | const Graphic3d_Vec2i aPnt2 (aPoints.Value (3).x(), -aPoints.Value (3).y()); |
e1c9a103 |
2852 | if (myGL.Selection.Tool == AIS_ViewSelectionTool_ZoomWindow) |
49582f9d |
2853 | { |
e1c9a103 |
2854 | theView->WindowFitAll (aPnt1.x(), aPnt1.y(), aPnt2.x(), aPnt2.y()); |
2855 | theView->Invalidate(); |
49582f9d |
2856 | } |
2857 | else |
2858 | { |
e1c9a103 |
2859 | theCtx->MainSelector()->AllowOverlapDetection (aPnt1.y() != Min (aPnt1.y(), aPnt2.y())); |
2860 | if (myGL.Selection.IsXOR) |
2861 | { |
2862 | theCtx->ShiftSelect (Min (aPnt1.x(), aPnt2.x()), Min (aPnt1.y(), aPnt2.y()), |
2863 | Max (aPnt1.x(), aPnt2.x()), Max (aPnt1.y(), aPnt2.y()), |
2864 | theView, false); |
2865 | } |
2866 | else |
2867 | { |
2868 | theCtx->Select (Min (aPnt1.x(), aPnt2.x()), Min (aPnt1.y(), aPnt2.y()), |
2869 | Max (aPnt1.x(), aPnt2.x()), Max (aPnt1.y(), aPnt2.y()), |
2870 | theView, false); |
2871 | } |
2872 | theCtx->MainSelector()->AllowOverlapDetection (false); |
49582f9d |
2873 | } |
49582f9d |
2874 | } |
2875 | else if (aPoints.Length() >= 3) |
2876 | { |
2877 | TColgp_Array1OfPnt2d aPolyline (1, aPoints.Length()); |
2878 | TColgp_Array1OfPnt2d::Iterator aPolyIter (aPolyline); |
2879 | for (NCollection_Sequence<Graphic3d_Vec2i>::Iterator aSelIter (aPoints); |
2880 | aSelIter.More(); aSelIter.Next(), aPolyIter.Next()) |
2881 | { |
2882 | const Graphic3d_Vec2i& aNewPnt = aSelIter.Value(); |
2883 | aPolyIter.ChangeValue() = gp_Pnt2d (aNewPnt.x(), -aNewPnt.y()); |
2884 | } |
2885 | |
49582f9d |
2886 | if (myGL.Selection.IsXOR) |
2887 | { |
2888 | theCtx->ShiftSelect (aPolyline, theView, false); |
2889 | } |
2890 | else |
2891 | { |
2892 | theCtx->Select (aPolyline, theView, false); |
2893 | } |
a24a7821 |
2894 | theCtx->MainSelector()->AllowOverlapDetection (false); |
49582f9d |
2895 | } |
2896 | } |
2897 | |
49582f9d |
2898 | myRubberBand->ClearPoints(); |
e1c9a103 |
2899 | if (myGL.Selection.Tool != AIS_ViewSelectionTool_ZoomWindow) |
2900 | { |
2901 | // selection affects all Views |
2902 | theView->Viewer()->Invalidate(); |
2903 | OnSelectionChanged (theCtx, theView); |
2904 | } |
49582f9d |
2905 | } |
2906 | } |
2907 | } |
2908 | |
2909 | // ======================================================================= |
2910 | // function : handleDynamicHighlight |
2911 | // purpose : |
2912 | // ======================================================================= |
2913 | void AIS_ViewController::handleDynamicHighlight (const Handle(AIS_InteractiveContext)& theCtx, |
2914 | const Handle(V3d_View)& theView) |
2915 | { |
2916 | if ((myGL.MoveTo.ToHilight || myGL.Dragging.ToStart) |
2917 | && myNavigationMode != AIS_NavigationMode_FirstPersonWalk) |
2918 | { |
2919 | const Graphic3d_Vec2i& aMoveToPnt = myGL.MoveTo.ToHilight ? myGL.MoveTo.Point : myGL.Dragging.PointStart; |
2920 | if (myGL.Dragging.ToStart && (!myGL.MoveTo.ToHilight || !myToAllowHighlight) |
2921 | && !HasPreviousMoveTo()) |
2922 | { |
2923 | contextLazyMoveTo (theCtx, theView, aMoveToPnt); |
2924 | ResetPreviousMoveTo(); |
2925 | OnObjectDragged (theCtx, theView, AIS_DragAction_Start); |
2926 | theCtx->ClearDetected(); |
2927 | } |
2928 | else if (myToAllowHighlight) |
2929 | { |
2930 | if (myPrevMoveTo != aMoveToPnt |
b40cdc2b |
2931 | || (!theView->View()->IsActiveXR() |
2932 | && (myGL.OrbitRotation.ToRotate |
2933 | || myGL.ViewRotation.ToRotate |
2934 | || theView->IsInvalidated()))) |
49582f9d |
2935 | { |
2936 | ResetPreviousMoveTo(); |
2937 | contextLazyMoveTo (theCtx, theView, aMoveToPnt); |
2938 | } |
2939 | if (myGL.Dragging.ToStart) |
2940 | { |
2941 | OnObjectDragged (theCtx, theView, AIS_DragAction_Start); |
2942 | } |
2943 | } |
2944 | |
2945 | myGL.MoveTo.ToHilight = false; |
2946 | } |
2947 | |
2948 | if (!myDragObject.IsNull()) |
2949 | { |
2950 | if (myGL.Dragging.ToAbort) |
2951 | { |
2952 | OnObjectDragged (theCtx, theView, AIS_DragAction_Abort); |
2953 | myGL.OrbitRotation.ToRotate = false; |
2954 | myGL.ViewRotation .ToRotate = false; |
2955 | } |
2956 | else if (myGL.Dragging.ToStop) |
2957 | { |
2958 | OnObjectDragged (theCtx, theView, AIS_DragAction_Stop); |
2959 | myGL.OrbitRotation.ToRotate = false; |
2960 | myGL.ViewRotation .ToRotate = false; |
2961 | } |
2962 | else if (myGL.OrbitRotation.ToRotate |
2963 | || myGL.ViewRotation.ToRotate) |
2964 | { |
2965 | OnObjectDragged (theCtx, theView, AIS_DragAction_Update); |
2966 | myGL.OrbitRotation.ToRotate = false; |
2967 | myGL.ViewRotation .ToRotate = false; |
2968 | } |
2969 | } |
2970 | } |
2971 | |
2972 | // ======================================================================= |
2973 | // function : handleMoveTo |
2974 | // purpose : |
2975 | // ======================================================================= |
2976 | void AIS_ViewController::handleMoveTo (const Handle(AIS_InteractiveContext)& theCtx, |
2977 | const Handle(V3d_View)& theView) |
2978 | { |
2979 | handleSelectionPick (theCtx, theView); |
2980 | handleDynamicHighlight(theCtx, theView); |
2981 | handleSelectionPoly (theCtx, theView); |
2982 | } |
2983 | |
2984 | // ======================================================================= |
2985 | // function : handleViewRedraw |
2986 | // purpose : |
2987 | // ======================================================================= |
2988 | void AIS_ViewController::handleViewRedraw (const Handle(AIS_InteractiveContext)& , |
2989 | const Handle(V3d_View)& theView) |
2990 | { |
2108d9a2 |
2991 | // manage animation state |
2992 | if (!myViewAnimation.IsNull() |
2993 | && !myViewAnimation->IsStopped()) |
2994 | { |
2995 | myViewAnimation->UpdateTimer(); |
2996 | ResetPreviousMoveTo(); |
2997 | setAskNextFrame(); |
2998 | } |
2999 | |
b40cdc2b |
3000 | if (theView->View()->IsActiveXR()) |
3001 | { |
3002 | // VR requires continuous rendering |
3003 | myToAskNextFrame = true; |
3004 | } |
3005 | |
49582f9d |
3006 | for (V3d_ListOfViewIterator aViewIter (theView->Viewer()->ActiveViewIterator()); aViewIter.More(); aViewIter.Next()) |
3007 | { |
3008 | const Handle(V3d_View)& aView = aViewIter.Value(); |
3009 | if (aView->IsInvalidated() |
d6fbb2ab |
3010 | || (myToAskNextFrame && aView == theView)) |
49582f9d |
3011 | { |
3012 | if (aView->ComputedMode()) |
3013 | { |
3014 | aView->Update(); |
3015 | } |
3016 | else |
3017 | { |
3018 | aView->Redraw(); |
3019 | } |
3020 | } |
3021 | else if (aView->IsInvalidatedImmediate()) |
3022 | { |
3023 | aView->RedrawImmediate(); |
3024 | } |
3025 | } |
3026 | |
3027 | if (myToAskNextFrame) |
3028 | { |
3029 | // ask more frames |
3030 | theView->Window()->InvalidateContent (Handle(Aspect_DisplayConnection)()); |
3031 | } |
3032 | } |
3033 | |
b40cdc2b |
3034 | // ======================================================================= |
3035 | // function : handleXRMoveTo |
3036 | // purpose : |
3037 | // ======================================================================= |
3038 | Standard_Integer AIS_ViewController::handleXRMoveTo (const Handle(AIS_InteractiveContext)& theCtx, |
3039 | const Handle(V3d_View)& theView, |
3040 | const gp_Trsf& thePose, |
3041 | const Standard_Boolean theToHighlight) |
3042 | { |
3043 | //ResetPreviousMoveTo(); |
3044 | Standard_Integer aPickResult = 0; |
3045 | |
3046 | Handle(Graphic3d_Camera) aCamBack = theView->Camera(); |
3047 | myXRCameraTmp->Copy (aCamBack); |
3048 | theView->View()->ComputeXRPosedCameraFromBase (*myXRCameraTmp, thePose); |
3049 | theView->SetCamera (myXRCameraTmp); |
3050 | Graphic3d_Vec2i aPickPixel; |
3051 | theView->Window()->Size (aPickPixel.x(), aPickPixel.y()); |
3052 | aPickPixel /= 2; |
3053 | const Standard_Integer aSelTolerBack = theCtx->MainSelector()->CustomPixelTolerance(); |
3054 | theCtx->MainSelector()->SetPixelTolerance (1); |
3055 | theView->AutoZFit(); |
3056 | if (theToHighlight) |
3057 | { |
3058 | theCtx->MoveTo (aPickPixel.x(), aPickPixel.y(), theView, false); |
3059 | if (!theCtx->DetectedOwner().IsNull()) |
3060 | { |
3061 | // ignore 2D objects |
3062 | for (aPickResult = 1; !theCtx->DetectedOwner()->Selectable()->TransformPersistence().IsNull(); ++aPickResult) |
3063 | { |
3064 | if (theCtx->HilightNextDetected (theView, false) <= 1) |
3065 | { |
3066 | theCtx->ClearDetected(); |
3067 | aPickResult = 0; |
3068 | break; |
3069 | } |
3070 | } |
3071 | } |
3072 | } |
3073 | else |
3074 | { |
3075 | theCtx->MainSelector()->Pick (aPickPixel.x(), aPickPixel.y(), theView); |
3076 | for (Standard_Integer aPickIter = 1; aPickIter <= theCtx->MainSelector()->NbPicked(); ++aPickIter) |
3077 | { |
3078 | const SelectMgr_SortCriterion& aPickedData = theCtx->MainSelector()->PickedData (aPickIter); |
3079 | if (!aPickedData.Entity->OwnerId()->Selectable()->TransformPersistence().IsNull()) |
3080 | { |
3081 | // skip 2d objects |
3082 | continue; |
3083 | } |
3084 | |
3085 | aPickResult = aPickIter; |
3086 | break; |
3087 | } |
3088 | } |
3089 | theCtx->MainSelector()->SetPixelTolerance (aSelTolerBack); |
3090 | theView->SetCamera (aCamBack); |
3091 | return aPickResult; |
3092 | } |
3093 | |
3094 | // ======================================================================= |
3095 | // function : handleXRHighlight |
3096 | // purpose : |
3097 | // ======================================================================= |
3098 | void AIS_ViewController::handleXRHighlight (const Handle(AIS_InteractiveContext)& theCtx, |
3099 | const Handle(V3d_View)& theView) |
3100 | { |
3101 | if (myXRLastPickingHand != Aspect_XRTrackedDeviceRole_LeftHand |
3102 | && myXRLastPickingHand != Aspect_XRTrackedDeviceRole_RightHand) |
3103 | { |
3104 | return; |
3105 | } |
3106 | |
3107 | const Standard_Integer aDeviceId = theView->View()->XRSession()->NamedTrackedDevice (myXRLastPickingHand); |
3108 | if (aDeviceId == -1) |
3109 | { |
3110 | return; |
3111 | } |
3112 | |
3113 | const Aspect_TrackedDevicePose& aPose = theView->View()->XRSession()->TrackedPoses()[aDeviceId]; |
3114 | if (!aPose.IsValidPose) |
3115 | { |
3116 | return; |
3117 | } |
3118 | |
3119 | Handle(SelectMgr_EntityOwner) aDetOld = theCtx->DetectedOwner(); |
3120 | handleXRMoveTo (theCtx, theView, aPose.Orientation, true); |
3121 | if (!theCtx->DetectedOwner().IsNull() |
3122 | && theCtx->DetectedOwner() != aDetOld) |
3123 | { |
3124 | if (const Handle(Aspect_XRAction)& aHaptic = theView->View()->XRSession()->GenericAction (myXRLastPickingHand, Aspect_XRGenericAction_OutputHaptic)) |
3125 | { |
3126 | theView->View()->XRSession()->TriggerHapticVibrationAction (aHaptic, myXRPickingHaptic); |
3127 | } |
3128 | } |
3129 | |
3130 | Standard_Real& aPickDepth = myXRLastPickingHand == Aspect_XRTrackedDeviceRole_LeftHand ? myXRLastPickDepthLeft : myXRLastPickDepthRight; |
3131 | aPickDepth = Precision::Infinite(); |
3132 | if (theCtx->MainSelector()->NbPicked() > 0) |
3133 | { |
3134 | const gp_Trsf aHandBase = theView->View()->PoseXRToWorld (aPose.Orientation); |
3135 | const SelectMgr_SortCriterion& aPicked = theCtx->MainSelector()->PickedData (1); |
3136 | aPickDepth = aPicked.Point.Distance (aHandBase.TranslationPart()); |
3137 | } |
3138 | } |
3139 | |
3140 | // ======================================================================= |
3141 | // function : handleXRPresentations |
3142 | // purpose : |
3143 | // ======================================================================= |
3144 | void AIS_ViewController::handleXRPresentations (const Handle(AIS_InteractiveContext)& theCtx, |
3145 | const Handle(V3d_View)& theView) |
3146 | { |
3147 | if (!theView->View()->IsActiveXR() |
3148 | || (!myToDisplayXRAuxDevices |
3149 | && !myToDisplayXRHands)) |
3150 | { |
3151 | for (NCollection_Array1<Handle(AIS_XRTrackedDevice)>::Iterator aPrsIter (myXRPrsDevices); aPrsIter.More(); aPrsIter.Next()) |
3152 | { |
3153 | if (!aPrsIter.Value().IsNull() |
3154 | && aPrsIter.Value()->HasInteractiveContext()) |
3155 | { |
3156 | theCtx->Remove (aPrsIter.Value(), false); |
3157 | } |
3158 | aPrsIter.ChangeValue().Nullify(); |
3159 | } |
3160 | return; |
3161 | } |
3162 | |
3163 | if (myXRPrsDevices.Length() != theView->View()->XRSession()->TrackedPoses().Length()) |
3164 | { |
3165 | for (NCollection_Array1<Handle(AIS_XRTrackedDevice)>::Iterator aPrsIter (myXRPrsDevices); aPrsIter.More(); aPrsIter.Next()) |
3166 | { |
3167 | if (!aPrsIter.Value().IsNull()) |
3168 | { |
3169 | theCtx->Remove (aPrsIter.Value(), false); |
3170 | } |
3171 | } |
3172 | myXRPrsDevices.Resize (theView->View()->XRSession()->TrackedPoses().Lower(), theView->View()->XRSession()->TrackedPoses().Upper(), false); |
3173 | } |
3174 | |
3175 | const Standard_Integer aHeadDevice = theView->View()->XRSession()->NamedTrackedDevice (Aspect_XRTrackedDeviceRole_Head); |
3176 | const Standard_Integer aLeftDevice = theView->View()->XRSession()->NamedTrackedDevice (Aspect_XRTrackedDeviceRole_LeftHand); |
3177 | const Standard_Integer aRightDevice = theView->View()->XRSession()->NamedTrackedDevice (Aspect_XRTrackedDeviceRole_RightHand); |
3178 | for (Standard_Integer aDeviceIter = theView->View()->XRSession()->TrackedPoses().Lower(); aDeviceIter <= theView->View()->XRSession()->TrackedPoses().Upper(); ++aDeviceIter) |
3179 | { |
3180 | const Aspect_TrackedDevicePose& aPose = theView->View()->XRSession()->TrackedPoses()[aDeviceIter]; |
3181 | Handle(AIS_XRTrackedDevice)& aPosePrs = myXRPrsDevices[aDeviceIter]; |
3182 | if (!aPose.IsValidPose) |
3183 | { |
3184 | continue; |
3185 | } |
3186 | |
3187 | const bool isHand = aDeviceIter == aLeftDevice |
3188 | || aDeviceIter == aRightDevice; |
3189 | if ((!myToDisplayXRHands && isHand) |
3190 | || (!myToDisplayXRAuxDevices && !isHand)) |
3191 | { |
3192 | if (!aPosePrs.IsNull() |
3193 | && aPosePrs->HasInteractiveContext()) |
3194 | { |
3195 | theCtx->Remove (aPosePrs, false); |
3196 | } |
3197 | continue; |
3198 | } |
3199 | |
3200 | Aspect_XRTrackedDeviceRole aRole = Aspect_XRTrackedDeviceRole_Other; |
3201 | if (aDeviceIter == aLeftDevice) |
3202 | { |
3203 | aRole = Aspect_XRTrackedDeviceRole_LeftHand; |
3204 | } |
3205 | else if (aDeviceIter == aRightDevice) |
3206 | { |
3207 | aRole = Aspect_XRTrackedDeviceRole_RightHand; |
3208 | } |
3209 | |
3210 | if (!aPosePrs.IsNull() |
3211 | && aPosePrs->UnitFactor() != (float )theView->View()->UnitFactor()) |
3212 | { |
3213 | theCtx->Remove (aPosePrs, false); |
3214 | aPosePrs.Nullify(); |
3215 | } |
3216 | |
3217 | if (aPosePrs.IsNull()) |
3218 | { |
3219 | Handle(Image_Texture) aTexture; |
3220 | Handle(Graphic3d_ArrayOfTriangles) aTris; |
3221 | if (aDeviceIter != aHeadDevice) |
3222 | { |
3223 | aTris = theView->View()->XRSession()->LoadRenderModel (aDeviceIter, aTexture); |
3224 | } |
3225 | if (!aTris.IsNull()) |
3226 | { |
3227 | aPosePrs = new AIS_XRTrackedDevice (aTris, aTexture); |
3228 | } |
3229 | else |
3230 | { |
3231 | aPosePrs = new AIS_XRTrackedDevice(); |
3232 | } |
3233 | aPosePrs->SetUnitFactor ((float )theView->View()->UnitFactor()); |
3234 | aPosePrs->SetMutable (true); |
3235 | aPosePrs->SetInfiniteState (true); |
3236 | } |
3237 | aPosePrs->SetRole (aRole); |
3238 | |
3239 | if (!aPosePrs->HasInteractiveContext()) |
3240 | { |
3241 | theCtx->Display (aPosePrs, 0, -1, false); |
3242 | } |
3243 | |
3244 | gp_Trsf aPoseLocal = aPose.Orientation; |
3245 | if (aDeviceIter == aHeadDevice) |
3246 | { |
3247 | // show headset position on floor level |
3248 | aPoseLocal.SetTranslationPart (gp_Vec (aPoseLocal.TranslationPart().X(), 0.0, aPoseLocal.TranslationPart().Z())); |
3249 | } |
3250 | const gp_Trsf aPoseWorld = theView->View()->PoseXRToWorld (aPoseLocal); |
3251 | theCtx->SetLocation (aPosePrs, aPoseWorld); |
3252 | |
3253 | Standard_Real aLaserLen = 0.0; |
3254 | if (isHand |
3255 | && aPosePrs->Role() == myXRLastPickingHand) |
3256 | { |
3257 | aLaserLen = myXRLastPickingHand == Aspect_XRTrackedDeviceRole_LeftHand ? myXRLastPickDepthLeft : myXRLastPickDepthRight; |
3258 | if (Precision::IsInfinite (aLaserLen)) |
3259 | { |
3260 | const Bnd_Box aViewBox = theView->View()->MinMaxValues (true); |
3261 | if (!aViewBox.IsVoid()) |
3262 | { |
3263 | aLaserLen = Sqrt (aViewBox.SquareExtent()); |
3264 | } |
3265 | else |
3266 | { |
3267 | aLaserLen = 100.0; |
3268 | } |
3269 | } |
3270 | aPosePrs->SetLaserColor (myXRLaserPickColor); |
3271 | } |
3272 | else if (isHand |
3273 | && aPosePrs->Role() == myXRLastTeleportHand) |
3274 | { |
3275 | aLaserLen = myXRLastTeleportHand == Aspect_XRTrackedDeviceRole_LeftHand ? myXRLastPickDepthLeft : myXRLastPickDepthRight; |
3276 | if (Precision::IsInfinite (aLaserLen)) |
3277 | { |
3278 | const Bnd_Box aViewBox = theView->View()->MinMaxValues (true); |
3279 | if (!aViewBox.IsVoid()) |
3280 | { |
3281 | aLaserLen = Sqrt (aViewBox.SquareExtent()); |
3282 | } |
3283 | else |
3284 | { |
3285 | aLaserLen = 100.0; |
3286 | } |
3287 | } |
3288 | aPosePrs->SetLaserColor (myXRLaserTeleColor); |
3289 | } |
3290 | aPosePrs->SetLaserLength ((float )aLaserLen); |
3291 | } |
3292 | } |
3293 | |
49582f9d |
3294 | // ======================================================================= |
3295 | // function : HandleViewEvents |
3296 | // purpose : |
3297 | // ======================================================================= |
3298 | void AIS_ViewController::HandleViewEvents (const Handle(AIS_InteractiveContext)& theCtx, |
3299 | const Handle(V3d_View)& theView) |
3300 | { |
b40cdc2b |
3301 | const bool wasImmediateUpdate = theView->SetImmediateUpdate (false); |
49582f9d |
3302 | |
d6fbb2ab |
3303 | handleViewOrientationKeys (theCtx, theView); |
d22962e4 |
3304 | const AIS_WalkDelta aWalk = handleNavigationKeys (theCtx, theView); |
b40cdc2b |
3305 | handleXRInput (theCtx, theView, aWalk); |
3306 | if (theView->View()->IsActiveXR()) |
3307 | { |
3308 | theView->View()->SetupXRPosedCamera(); |
3309 | } |
a7400019 |
3310 | handleMoveTo (theCtx, theView); |
49582f9d |
3311 | handleCameraActions (theCtx, theView, aWalk); |
b40cdc2b |
3312 | theView->View()->SynchronizeXRPosedToBaseCamera(); // handleCameraActions() may modify posed camera position - copy this modifications also to the base camera |
3313 | handleXRPresentations (theCtx, theView); |
3314 | |
49582f9d |
3315 | handleViewRedraw (theCtx, theView); |
b40cdc2b |
3316 | theView->View()->UnsetXRPosedCamera(); |
3317 | |
3318 | theView->SetImmediateUpdate (wasImmediateUpdate); |
49582f9d |
3319 | |
3320 | // make sure to not process the same events twice |
3321 | myGL.Reset(); |
3322 | myToAskNextFrame = false; |
3323 | } |