/// <summary> /// Handles hit testing on mouse down. /// </summary> /// <param name="pt">The hit point.</param> /// <param name="originalInputEventArgs"> /// The original input event (which mouse button pressed?) /// </param> private void MouseDownHitTest(Point pt, PointerRoutedEventArgs originalInputEventArgs = null) { if (!enableMouseButtonHitTest) { return; } if (this.FindHits(pt.ToVector2(), ref hits) && hits.Count > 0) { this.currentHit = hits.FirstOrDefault(x => x.IsValid); if (this.currentHit != null) { if (currentHit.ModelHit is Element3D ele) { ele.RaiseMouseDownEvent(this.currentHit, pt, this, originalInputEventArgs); } else if (currentHit.ModelHit is SceneNode node) { node.RaiseMouseDownEvent(this, pt.ToVector2(), currentHit, originalInputEventArgs); } } } else { currentHit = null; } this.OnMouse3DDown?.Invoke(this, new MouseDown3DEventArgs(currentHit, pt, this, originalInputEventArgs)); }
/// <summary> /// Rotate the camera around the specified point. /// </summary> /// <param name="p0"> /// The p 0. /// </param> /// <param name="p1"> /// The p 1. /// </param> /// <param name="rotateAround"> /// The rotate around. /// </param> public void Rotate(Point p0, Point p1, Point3D rotateAround) { if (!this.Viewport.IsRotationEnabled) { return; } switch (this.Viewport.CameraRotationMode) { case CameraRotationMode.Trackball: this.RotateTrackball(p0, p1, rotateAround); break; case CameraRotationMode.Turntable: this.RotateTurntable(p1.ToVector2() - p0.ToVector2(), rotateAround); break; case CameraRotationMode.Turnball: this.RotateTurnball(p0, p1, rotateAround); break; } if (Math.Abs(this.Camera.UpDirection.Length() - 1) > 1e-8) { this.Camera.UpDirection.Normalize(); } }
/// <summary> /// Rotate the camera around the specified point. /// </summary> /// <param name="p0"> /// The p 0. /// </param> /// <param name="p1"> /// The p 1. /// </param> /// <param name="rotateAround"> /// The rotate around. /// </param> /// <param name="stopOther">Stop other manipulation</param> public void Rotate(Point p0, Point p1, Point3D rotateAround, bool stopOther = true) { if (!this.Controller.IsRotationEnabled) { return; } if (stopOther) { Controller.StopZooming(); Controller.StopPanning(); } switch (this.Controller.CameraRotationMode) { case CameraRotationMode.Trackball: this.RotateTrackball(p0, p1, rotateAround); break; case CameraRotationMode.Turntable: this.RotateTurntable(p1.ToVector2() - p0.ToVector2(), rotateAround); break; case CameraRotationMode.Turnball: this.RotateTurnball(p0, p1, rotateAround); break; } if (Math.Abs(this.Camera.UpDirection.Length() - 1) > 1e-8) { this.Camera.UpDirection.Normalize(); } }
private bool ViewBoxHitTest(Point p) { if (!(Camera is ProjectionCamera camera)) { return(false); } var vp = p.ToVector2(); if (!this.UnProject(vp, out var ray)) { return(false); } var hits = new List <HitTestResult>(); if (viewCube.HitTest(new HitTestContext(RenderContext, ref ray, ref vp), ref hits)) { var normal = hits[0].NormalAtHit; if (Vector3.Cross(normal, ModelUpDirection).LengthSquared() < 1e-5) { var vecLeft = new Vector3(-normal.Y, -normal.Z, -normal.X); ViewCubeClicked(hits[0].NormalAtHit, vecLeft); } else { ViewCubeClicked(hits[0].NormalAtHit, ModelUpDirection); } return(true); } else { return(false); } }
public void Vector2FromPointTest() { var point = new Windows.Foundation.Point(23, 42); Vector2 result = point.ToVector2(); Assert.AreEqual(23.0f, result.X); Assert.AreEqual(42.0f, result.Y); }
/// <summary> /// Occurs when the manipulation is started. /// </summary> /// <param name="e">The <see cref="ManipulationEventArgs"/> instance containing the event data.</param> public override void Started(Point e) { base.Started(e); this.rotationPoint = new Vector2( this.Controller.Width / 2f, this.Controller.Height / 2f); this.rotationPoint3D = this.Camera.CameraInternal.Target; switch (this.CameraMode) { case CameraMode.WalkAround: this.rotationPoint = this.MouseDownPoint; this.rotationPoint3D = this.Camera.CameraInternal.Position; break; default: if (Controller.Viewport.FixedRotationPointEnabled) { this.rotationPoint3D = Controller.Viewport.FixedRotationPoint; } else if (this.changeLookAt && this.MouseDownNearestPoint3D != null) { this.LookAt(this.MouseDownNearestPoint3D.Value, 0); this.rotationPoint3D = this.Camera.CameraInternal.Target; } else if (this.Controller.RotateAroundMouseDownPoint && this.MouseDownNearestPoint3D != null) { this.rotationPoint = this.MouseDownPoint; this.rotationPoint3D = this.MouseDownNearestPoint3D.Value; } break; } if (this.CameraMode == CameraMode.Inspect) { //this.Viewport.ShowTargetAdorner(this.rotationPoint); } switch (this.CameraRotationMode) { case CameraRotationMode.Trackball: break; case CameraRotationMode.Turntable: break; case CameraRotationMode.Turnball: CameraMath.InitTurnballRotationAxes(e.ToVector2(), Controller.Width, Controller.Height, Camera, out rotationAxisX, out rotationAxisY); break; } this.Controller.StopSpin(); }
/// <summary> /// Rotate around three axes. /// </summary> /// <param name="p1"> /// The previous mouse position. /// </param> /// <param name="p2"> /// The current mouse position. /// </param> /// <param name="rotateAround"> /// The point to rotate around. /// </param> public void RotateTurnball(Point p1, Point p2, Point3D rotateAround) { this.InitTurnballRotationAxes(p1); Vector2 delta = p2.ToVector2() - p1.ToVector2(); var relativeTarget = rotateAround - this.Camera.Target; var relativePosition = rotateAround - this.Camera.Position; float d = -1f; if (this.CameraMode != CameraMode.Inspect) { d = 0.2f; } d *= (float)this.RotationSensitivity; var q1 = Quaternion.RotationAxis(this.rotationAxisX, (float)(d * delta.X / 180 * Math.PI)); var q2 = Quaternion.RotationAxis(this.rotationAxisY, (float)(d * delta.Y / 180 * Math.PI)); Quaternion q = q1 * q2; var m = Matrix.RotationQuaternion(q); var newLookDir = Vector3D.Transform(this.Camera.LookDirection, m).ToVector3(); var newUpDirection = Vector3D.Transform(this.Camera.UpDirection, m).ToVector3(); var newRelativeTarget = Vector3D.Transform(relativeTarget, m).ToVector3(); var newRelativePosition = Vector3D.Transform(relativePosition, m).ToVector3(); var newRightVector = Vector3D.Cross(newLookDir, newUpDirection); newRightVector.Normalize(); var modUpDir = Vector3D.Cross(newRightVector, newLookDir); modUpDir.Normalize(); if ((newUpDirection - modUpDir).Length() > 1e-8) { newUpDirection = modUpDir; } var newTarget = rotateAround - newRelativeTarget; var newPosition = rotateAround - newRelativePosition; var newLookDirection = newTarget - newPosition; this.Camera.LookDirection = newLookDirection; if (this.CameraMode == CameraMode.Inspect) { this.Camera.Position = newPosition; } this.Camera.UpDirection = newUpDirection; }
/// <summary> /// Handles hit testing on mouse move. /// </summary> /// <param name="pt">The hit point.</param> /// <param name="originalInputEventArgs"> /// The original input (which mouse button pressed?) /// </param> private void MouseMoveHitTest(Point pt, PointerRoutedEventArgs originalInputEventArgs = null) { if (!enableMouseButtonHitTest) { return; } if (this.currentHit != null) { if (currentHit.ModelHit is Element3D ele) { ele.RaiseMouseMoveEvent(this.currentHit, pt, this, originalInputEventArgs); } else if (currentHit.ModelHit is SceneNode node) { node.RaiseMouseMoveEvent(this, pt.ToVector2(), currentHit, originalInputEventArgs); } } this.OnMouse3DMove?.Invoke(this, new MouseMove3DEventArgs(currentHit, pt, this, originalInputEventArgs)); }
/// <summary> /// Finds the nearest point and its normal. /// </summary> /// <param name="viewport"> /// The viewport. /// </param> /// <param name="position"> /// The position. /// </param> /// <param name="point"> /// The point. /// </param> /// <param name="normal"> /// The normal. /// </param> /// <param name="model"> /// The model. /// </param> /// <param name="node"></param> /// <returns> /// The find nearest. /// </returns> public static bool FindNearest(this Viewport3DX viewport, Point position, out Vector3 point, out Vector3 normal, out Element3D model, out SceneNode node) { model = null; node = null; if (viewport.FindNearest(position.ToVector2(), out point, out normal, out var m)) { if (m is Element3D ele) { model = ele; node = ele.SceneNode; } else if (m is SceneNode nd) { node = nd; model = null; } return(true); } return(false); }
/// <summary> /// The on time step. /// </summary> /// <param name="ticks"> /// The time. /// </param> public void OnTimeStep(long ticks) { if (lastTick == 0) { lastTick = ticks; } var time = (float)(ticks - this.lastTick) / Stopwatch.Frequency; // should be independent of time var factor = Viewport.IsInertiaEnabled ? (float)Clamp(Math.Pow(Viewport.CameraInertiaFactor, time / 0.02f), 0.1f, 1) : 0; bool needUpdate = false; if (this.rotationSpeed.LengthSquared() > 0.1) { this.rotateHandler.Rotate( this.rotationPosition, (rotationPosition.ToVector2() + (rotationSpeed * time)).ToPoint(), this.rotationPoint3D); this.rotationSpeed *= factor; needUpdate = true; this.spinningSpeed = VectorZero; } else { this.rotationSpeed = VectorZero; if (this.isSpinning && this.spinningSpeed.LengthSquared() > 0.1) { this.rotateHandler.Rotate( this.spinningPosition, (spinningPosition.ToVector2() + (spinningSpeed * time)).ToPoint(), this.spinningPoint3D); if (!Viewport.InfiniteSpin) { this.spinningSpeed *= factor; } needUpdate = true; } else { this.spinningSpeed = VectorZero; } } if (this.panSpeed.LengthSquared() > 0.0001) { this.panHandler.Pan(this.panSpeed * time); this.panSpeed *= factor; needUpdate = true; } else { this.panSpeed = Vector3DZero; } if (this.moveSpeed.LengthSquared() > 0.0001) { this.zoomHandler.MoveCameraPosition(this.moveSpeed * time); this.moveSpeed *= factor; needUpdate = true; } else { this.moveSpeed = Vector3DZero; } if (Math.Abs(this.zoomSpeed) > 0.001) { this.zoomHandler.Zoom(this.zoomSpeed * time, this.zoomPoint3D); this.zoomSpeed *= factor; needUpdate = true; } else { zoomSpeed = 0; } if (ActualCamera != null && ActualCamera.OnTimeStep()) { needUpdate = true; } if (needUpdate) { lastTick = ticks; Viewport.InvalidateRender(); } else { lastTick = 0; } }
public static Vector3 ToVector3(this Point point) { return(new Vector3(point.ToVector2(), 0f)); }
public void Vector2FromPointTest() { var point = new Windows.Foundation.Point(23, 42); Vector2 result = point.ToVector2(); Assert.AreEqual(23.0f, result.X); Assert.AreEqual(42.0f, result.Y); }
/// <summary> /// Called when the <see cref="E:System.Windows.UIElement.ManipulationDelta"/> event occurs. /// </summary> /// <param name="e"> /// The data for the event. /// </param> public void OnManipulationDelta(ManipulationDeltaRoutedEventArgs e) { // number of manipulators (fingers) if (Viewport.PointerCaptures == null) { return; } int n = Viewport.PointerCaptures.Count(); var position = new Point(touchPreviousPoint.X + e.Cumulative.Translation.X, touchPreviousPoint.Y + e.Cumulative.Translation.Y); // http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationdelta.aspx //System.Diagnostics.Debug.WriteLine($"OnManipulationDelta: T={e.Cumulative.Translation}, S={e.Cumulative.Scale}, R={e.Cumulative.Rotation}, E={e.Cumulative.Expansion}"); //// System.Diagnostics.Debug.WriteLine(n + " Delta:" + e.DeltaManipulation.Translation + " Origin:" + e.ManipulationOrigin + " pos:" + position); if (this.manipulatorCount != n) { // the number of manipulators has changed switch (this.manipulatorCount) { case 1: this.rotateHandler.Completed(position); break; case 2: this.zoomHandler.Completed(e.Position); break; case 3: this.panHandler.Completed(position); break; } switch (n) { case 1: if (EnableTouchRotate) { this.rotateHandler.Started(position); e.Handled = true; } break; case 2: if (EnablePinchZoom) { this.zoomHandler.Started(e.Position); e.Handled = true; } break; case 3: if (EnableThreeFingerPan) { this.panHandler.Started(position); e.Handled = true; } break; } // skip this event, the origin may have changed this.manipulatorCount = n; return; } else { switch (n) { case 1: if (EnableTouchRotate) { this.rotateHandler.Delta(position.ToVector2()); e.Handled = true; } break; case 2: if (EnablePinchZoom) { if (prevScale == 1) { prevScale = e.Cumulative.Scale; } else { if (PinchZoomAtCenter) { float s = e.Cumulative.Scale; this.zoomHandler.Zoom((prevScale - s), CameraPosition + CameraLookDirection, true); prevScale = s; } else { var zoomAroundPoint = this.zoomHandler.UnProject( e.Position, this.zoomHandler.Origin, this.CameraLookDirection); if (zoomAroundPoint.HasValue) { float s = e.Cumulative.Scale; this.zoomHandler.Zoom((prevScale - s), zoomAroundPoint.Value, true); prevScale = s; } } } } e.Handled = true; break; case 3: if (EnableThreeFingerPan) { this.panHandler.Delta(position.ToVector2()); e.Handled = true; } break; } } }
/// <summary> /// Finds the hits for a given 2D viewport position. /// </summary> /// <param name="viewport"> /// The viewport. /// </param> /// <param name="position"> /// The position. /// </param> /// <returns> /// List of hits, sorted with the nearest hit first. /// </returns> public static IList <HitTestResult> FindHits(this Viewport3DX viewport, Point position) { return(viewport.FindHits(position.ToVector2())); }
/// <summary> /// Un-project a point from the screen (2D) to a point on plane (3D) /// </summary> /// <param name="viewport"> /// The viewport. /// </param> /// <param name="p"> /// The 2D point. /// </param> /// <param name="position"> /// plane position /// </param> /// <param name="normal"> /// plane normal /// </param> /// <returns> /// A 3D point. /// </returns> public static Vector3?UnProjectOnPlane(this Viewport3DX viewport, Point p, Vector3 position, Vector3 normal) { return(viewport.UnProjectOnPlane(p.ToVector2(), position, normal)); }
public static Ray UnProject(this Viewport3DX viewport, Point point2d) { return(UnProject(viewport, point2d.ToVector2())); }