private void EnsureLeftControllerVisual3D() { if (_leftControllerVisual3D != null) { return; } EnsureLeftControllerMesh(); var controllerModel3D = new GeometryModel3D(_leftControllerMesh, _controllerMaterial); controllerModel3D.BackMaterial = _controllerMaterial; // Add transformations _leftControllerQuaternionRotation3D = new QuaternionRotation3D(); _leftControllerBodyRotateTransform3D = new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 1, 0), 0)); // rotate around y (up) axis _leftControllerTranslateTransform3D = new TranslateTransform3D(); var transform3DGroup = new Transform3DGroup(); transform3DGroup.Children.Add(new RotateTransform3D(_leftControllerQuaternionRotation3D)); transform3DGroup.Children.Add(_leftControllerBodyRotateTransform3D); transform3DGroup.Children.Add(_leftControllerTranslateTransform3D); controllerModel3D.Transform = transform3DGroup; // Finally create ModelVisualD that can be added to Viewport3D's Children _leftControllerVisual3D = controllerModel3D.CreateModelVisual3D(); }
void ShowAll() { SetGrid(100, 100, xMin, xMax, yMin, yMax); SetValues(); FindAllMinMax(); DrawAllValuesOnLabels(); NormailzeValues(); CreateMeshGeometry(); Transform3DGroup group = modelGeometry.Transform as Transform3DGroup; QuaternionRotation3D r = new QuaternionRotation3D( new Quaternion(new Vector3D(1, 0, 0), -200 / Math.PI)); group.Children.Add(new RotateTransform3D(r)); CreateAxes(); group = xAxis.Transform as Transform3DGroup; group.Children.Add(new RotateTransform3D(r)); group = yAxis.Transform as Transform3DGroup; group.Children.Add(new RotateTransform3D(r)); group = zAxis.Transform as Transform3DGroup; group.Children.Add(new RotateTransform3D(r)); InitAnimation(); }
private void Rotate() { double theta = yaw / 3; double phi = pitch / 3; // Clamp phi (pitch) between -90 and 90 to avoid 'going upside down' // Just remove this if you want to make loopings :) if (phi < -90) { phi = -90; } if (phi > 90) { phi = 90; } // Here the rotation magic happens. Ask jemidiah for details, I've no clue :P Vector3D thetaAxis = new Vector3D(0, 1, 0); Vector3D phiAxis = new Vector3D(-1, 0, 0); Transform3DGroup transformGroup = camera.Transform as Transform3DGroup; transformGroup.Children.Clear(); QuaternionRotation3D r = new QuaternionRotation3D(new Quaternion(-phiAxis, phi)); transformGroup.Children.Add(new RotateTransform3D(r)); r = new QuaternionRotation3D(new Quaternion(-thetaAxis, theta)); transformGroup.Children.Add(new RotateTransform3D(r)); }
private void RenderPart() { ModelVisual3D visual = new ModelVisual3D(); visual.Content = this.Part.Model; _rotateTransform = new QuaternionRotation3D(Math3D.GetRandomRotation()); visual.Transform = new RotateTransform3D(_rotateTransform); // Pull the camera back far enough to see the part double?maxDist = UtilityWPF.GetPointsFromMesh(this.Part.Model). Select(o => o.ToVector().LengthSquared). OrderByDescending(o => o). FirstOrDefault(); double cameraDist = 2.1; if (maxDist != null) { maxDist = Math.Sqrt(maxDist.Value); cameraDist = maxDist.Value * 3; } _viewport.Children.Add(visual); _camera.Position = (_camera.Position.ToVector().ToUnit() * cameraDist).ToPoint(); }
public AnyQuatWorker(QuaternionRotation3D transform, double angleDelta, int numFullRotations, double?maxTransitionAngle = null) { _transform = transform; _angleDelta = angleDelta; _numFullRotations = numFullRotations; _maxTransitionAngle = maxTransitionAngle; }
/// <summary> /// This limits destination orientation axiis to a cone /// </summary> public static AnimateRotation Create_LimitedOrientation(QuaternionRotation3D transform, Vector3D centerAxis, double maxConeAngle, double angleDelta, int numFullRotations = 0) { return(new AnimateRotation() { _worker = new ConeQuatWorker(transform, centerAxis, maxConeAngle, angleDelta, numFullRotations) }); }
public FixedWorker(QuaternionRotation3D transform, double delta) { _isQuat = true; _transformQuat = transform; _transformAxis = null; _delta = delta; }
public FixedWorker(AxisAngleRotation3D transform, double delta) { _isQuat = false; _transformAxis = transform; _transformQuat = null; _delta = delta; }
/// <summary> /// This will go from any angle to any angle, but at the time of choosing a new destination, it won't /// exceed a cone defined by maxTransitionAngle /// </summary> /// <remarks> /// Without this constraint, the changes in direction are pretty jarring. This is an attempt to smooth that out /// </remarks> public static AnimateRotation Create_AnyOrientation_LimitChange(QuaternionRotation3D transform, double maxTransitionConeAngle, double anglePerSecond, double angleBetweenTransitions) { return(new AnimateRotation() { _worker = new AnyQuatConeWorker(transform, maxTransitionConeAngle, anglePerSecond, angleBetweenTransitions) }); }
private void Drag(Tuple <Point, Point3D> startTuple, Point position) { var transform3DGroup = (Transform3DGroup)_groupModel.Transform; var hits = GetHits(_ => HitTestFilterBehavior.Continue, position); var meshHits = hits.Cast <RayMeshGeometry3DHitTestResult>().Where(h => h.MeshHit == _dragObject); var dragObjectHit = meshHits.OrderBy(h => (h.PointHit - startTuple.Item2).LengthSquared).FirstOrDefault(); if (dragObjectHit == null) { return; } Point3D start = startTuple.Item2; Point3D end = transform3DGroup.Transform(dragObjectHit.PointHit); Point3D origin = Center; // new Point3D(); Vector3D startVector = start - origin; Vector3D endVector = end - origin; var axis = Vector3D.CrossProduct(startVector, endVector); var cosAngle = Vector3D.DotProduct(startVector, endVector) / (startVector.Length * endVector.Length); var angleRads = Math.Acos(cosAngle); axis.Normalize(); var r = new QuaternionRotation3D(new Quaternion(axis, RadianToDegree(angleRads))); transform3DGroup.Children.RemoveAt(transform3DGroup.Children.Count - 1); transform3DGroup.Children.Add(new RotateTransform3D(r, origin)); }
void putar3d() { double yaw = Math.Ceiling(mySensorLog.Yaw); double pitch = Math.Ceiling(mySensorLog.Pitch); double roll = Math.Ceiling(mySensorLog.Roll); Vector3D axisYaw = new Vector3D(0, 0, -1); Vector3D axisPitch = new Vector3D(1, 0, 0); Vector3D axisRoll = new Vector3D(0, 1, 0); Transform3DGroup group = new Transform3DGroup(); QuaternionRotation3D r; try { r = new QuaternionRotation3D(new Quaternion(axisYaw, pitch)); //(new Vector3D(0, 1, 0), yaw)); group.Children.Add(new RotateTransform3D(r)); r = new QuaternionRotation3D(new Quaternion(axisPitch, -yaw)); //(new Vector3D(1, 0, 0), pitch)); group.Children.Add(new RotateTransform3D(r)); r = new QuaternionRotation3D(new Quaternion(axisRoll, roll)); //(new Vector3D(0, 0, 1), roll)); group.Children.Add(new RotateTransform3D(r)); rocket3D.Transform = group; } catch (Exception ex) { MessageBox.Show(ex.Message.ToString()); } }
/// <summary> /// This will rotate to a random rotation. Once at that destination, choose a new random rotation to /// go to, and rotate to that. Always at a constant speed /// </summary> /// <remarks> /// There are no limits on what axis can be used. The rotation will always be at the fixed speed /// </remarks> /// <param name="angleDelta">degrees per elapsed</param> /// <param name="numFullRotations"> /// If 0, this will rotate directly to destination, then choose a new destination. /// If 1, this will rotate to the destination, then a full 360, then choose another destination, 2 does 2 rotations, etc /// </param> public static AnimateRotation Create_AnyOrientation(QuaternionRotation3D transform, double angleDelta, int numFullRotations = 0) { return(new AnimateRotation() { _worker = new AnyQuatWorker(transform, angleDelta, numFullRotations) }); }
private void Filter_FilterUpdate(object sender, EventArgs e) { Application.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() => { Pitch = filter.Pitch; Roll = filter.Roll; if (EnableYaw) { Yaw = filter.Yaw; } else { Yaw = 0; } var pitchRotation = new Quaternion(new Vector3D(1, 0, 0), -Pitch); var rollRotation = new Quaternion(new Vector3D(0, 0, 1), Roll); var yawRotation = new Quaternion(new Vector3D(0, 1, 0), -Yaw); var quat = Quaternion.Multiply(Quaternion.Multiply(pitchRotation, rollRotation), yawRotation); var transform = new QuaternionRotation3D(quat); var rot = new RotateTransform3D(transform); Transform = new MatrixTransform3D(rot.Value); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Pitch")); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Roll")); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Yaw")); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Transform")); })); }
private void UpdateRotation() { Quaternion rotation = this.ModelAttitude * gesture.Rotation; QuaternionRotation3D quaternionRotation = new QuaternionRotation3D(rotation); RotateTransform3D myRotateTransform = new RotateTransform3D(quaternionRotation); model.Transform = myRotateTransform; xAxis.Transform = myRotateTransform; yAxis.Transform = myRotateTransform; PerspectiveCamera camera = (PerspectiveCamera)MainViewPort.Camera; Vector3D position = (Vector3D)camera.Position; Vector3D lookDirection = this.lookAt - camera.Position; double length = lookDirection.Length; length += (gesture.Zoom * this.modelRadius / 10); // 10 clicks to travel size of model if (length <= 0.1) { length = 0.1; } lookDirection.Normalize(); lookDirection *= length; gesture.Zoom = 0; camera.Position = this.lookAt - lookDirection; }
public Pose3DView() { this.InitializeComponent(); this.camera = new PerspectiveCamera(new Point3D(0, 0.75, -4), new Vector3D(0, 0, 1), new Vector3D(0, 1, 0), 45); this.Viewport.Camera = this.camera; this.cameraRotaion = new RotateTransform3D(); QuaternionRotation3D camRot = new QuaternionRotation3D(); camRot.Quaternion = CameraService.Instance.Camera?.Rotation3d ?? Quaternion.Identity; this.cameraRotaion.Rotation = camRot; this.cameraPosition = new TranslateTransform3D(); Transform3DGroup transformGroup = new Transform3DGroup(); transformGroup.Children.Add(this.cameraRotaion); transformGroup.Children.Add(this.cameraPosition); this.camera.Transform = transformGroup; this.ContentArea.DataContext = this; if (CameraService.Instance.Camera != null) { CameraService.Instance.Camera.PropertyChanged += this.OnCameraChanged; } }
void InitAnimation() { dt = new DispatcherTimer(); dt.Interval = TimeSpan.FromMilliseconds(10); double rotation = 0.01; Vector3D axis = new Vector3D(0.05, 0.9, 0); dt.Tick += (s, e) => { Transform3DGroup group = modelGeometry.Transform as Transform3DGroup; QuaternionRotation3D r = new QuaternionRotation3D( new Quaternion(axis, rotation * 180 / Math.PI)); group.Children.Add(new RotateTransform3D(r)); group = xAxis.Transform as Transform3DGroup; group.Children.Add(new RotateTransform3D(r)); group = yAxis.Transform as Transform3DGroup; group.Children.Add(new RotateTransform3D(r)); group = zAxis.Transform as Transform3DGroup; group.Children.Add(new RotateTransform3D(r)); }; dt.Start(); }
private void Grid_MouseMove(object sender, MouseEventArgs e) { Console.WriteLine("CALL"); if (!mDown) { return; } Point pos = Mouse.GetPosition(details_viewport); Point actualPos = new Point( pos.X - details_viewport.ActualWidth / 2, details_viewport.ActualHeight / 2 - pos.Y); double dx = actualPos.X - mLastPos.X; double dy = actualPos.Y - mLastPos.Y; double mouseAngle = 0; if (dx != 0 && dy != 0) { mouseAngle = Math.Asin(Math.Abs(dy) / Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2))); if (dx < 0 && dy > 0) { mouseAngle += Math.PI / 2; } else if (dx < 0 && dy < 0) { mouseAngle += Math.PI; } else if (dx > 0 && dy < 0) { mouseAngle += Math.PI * 1.5; } } else if (dx == 0 && dy != 0) { mouseAngle = Math.Sign(dy) > 0 ? Math.PI / 2 : Math.PI * 1.5; } else if (dx != 0 && dy == 0) { mouseAngle = Math.Sign(dx) > 0 ? 0 : Math.PI; } double axisAngle = mouseAngle + Math.PI / 2; Vector3D axis = new Vector3D( Math.Cos(axisAngle) * 4, Math.Sin(axisAngle) * 4, 0); double rotation = 0.02 * Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2)); Transform3DGroup group = (this.DataContext as MainWindowViewModel).activeGeometry.Transform as Transform3DGroup; QuaternionRotation3D r = new QuaternionRotation3D( new Quaternion(axis, rotation * 180 / Math.PI)); group.Children.Add(new RotateTransform3D(r)); Console.WriteLine("CHANGE", actualPos); mLastPos = actualPos; }
public ConeQuatWorker(QuaternionRotation3D transform, Vector3D centerAxis, double maxConeAngle, double angleDelta, int numFullRotations) { _transform = transform; _centerAxis = centerAxis; _maxConeAngle = maxConeAngle; _angleDelta = angleDelta; _numFullRotations = numFullRotations; }
private void SetAtHome() { var r = new QuaternionRotation3D(new Quaternion(new Vector3D(0, 0, 1), 0)); _pCamera.Transform = new RotateTransform3D(r); _dZ = 10; _pCamera.Position = new Point3D(0, 0, _dZ); }
public Planerator() { Class6.yDnXvgqzyB5jw(); this._quaternionRotation = new QuaternionRotation3D(); this._rotationTransform = new RotateTransform3D(); this._scaleTransform = new ScaleTransform3D(); base(); }
public AnyQuatConeWorker(QuaternionRotation3D transform, double maxTransitionConeAngle, double anglePerSecond, double angleBetweenTransitions) { _transform = transform; _maxTransitionConeAngle = maxTransitionConeAngle; _angleBetweenTransitionsAdjusted = anglePerSecond / NEWANGLE; _destinationPercent = angleBetweenTransitions / NEWANGLE; _currentPercent = _destinationPercent + 1; // set it greater so the first time tick is called, a new destination will be chosen }
private void MainGrid_MouseMove(object sender, MouseEventArgs e) { if (!mDown) { return; } Point pos = Mouse.GetPosition(ViewPort); Point actualPos = new Point( pos.X - ViewPort.ActualWidth / 2, ViewPort.ActualHeight / 2 - pos.Y); double dx = actualPos.X - mLastPos.X; double dy = actualPos.Y - mLastPos.Y; double mouseAngle = 0; if (dx != 0 && dy != 0) { mouseAngle = Math.Asin(Math.Abs(dy) / Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2))); if (dx < 0 && dy > 0) { mouseAngle += Math.PI / 2; } else if (dx < 0 && dy < 0) { mouseAngle += Math.PI; } else if (dx > 0 && dy < 0) { mouseAngle += Math.PI * 1.5; } } else if (dx == 0 && dy != 0) { mouseAngle = Math.Sign(dy) > 0 ? Math.PI / 2 : Math.PI * 1.5; } else if (dx != 0 && dy == 0) { mouseAngle = Math.Sign(dx) > 0 ? 0 : Math.PI; } double axisAngle = mouseAngle + Math.PI / 2; Vector3D axis = new Vector3D( Math.Cos(axisAngle) * 4, Math.Sin(axisAngle) * 4, 0); double rotation = 0.02 * Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2)); Transform3DGroup group = MGeometry.Transform as Transform3DGroup; QuaternionRotation3D r = new QuaternionRotation3D( new Quaternion(axis, rotation * 180 / Math.PI)); group.Children.Add(new RotateTransform3D(r)); mLastPos = actualPos; }
private void RemoveVisual() { if (_visual != null) { _viewport.Children.Remove(_visual); } _visual = null; _rotateTransform = null; }
public WpfScene(TextureProvider<BitmapSource> textureProvider, MeshViewSettingsViewModel settingsViewModel) { _viewPort = new Viewport3D(); _rendererCamera = new WpfRendererCamera(_viewPort, Vector3.Zero); _textureProvider = textureProvider; var lightGroup = new Model3DGroup(); var light = new PointLight(Colors.Cornsilk, _rendererCamera.Position.AsPoint3D()); CameraLight = new WpfLight(light); lightGroup.Children.Add(light); _viewPort.Children.Add(new ModelVisual3D {Content = lightGroup}); _meshModelGroup = new Model3DGroup(); _wireFrameModelGroup = new Model3DGroup(); _allModelGroup = new Model3DGroup(); _allModelGroup.Children.Add(_meshModelGroup); _allModelGroup.Children.Add(_wireFrameModelGroup); var rotation = new RotateTransform3D(); _quaternionRotation = new QuaternionRotation3D(); rotation.Rotation = _quaternionRotation; _allModelGroup.Transform = rotation; var visual = new ModelVisual3D {Content = _allModelGroup}; _viewPort.Children.Add(visual); var border = new Border{Background = Brushes.Black}; border.Child = _viewPort; Visual = border; MouseInput = new WpfMouseInput(border); settingsViewModel.WhenAnyValue(s => s.MeshEnabled, s => s.WireFrameEnabled).Subscribe(_ => { ToggleMesh(settingsViewModel.MeshEnabled); ToggleWireFrame(settingsViewModel.WireFrameEnabled); }); settingsViewModel.WhenAnyValue( s => s.YRotation, s => s.XRotation, s => s.ZRotation).Subscribe(_ => { SetRootRotation( new Quaternion(new Vector3D(1, 0, 0), settingsViewModel.XRotation) * new Quaternion(new Vector3D(0, 1, 0), settingsViewModel.YRotation) * new Quaternion(new Vector3D(0, 0, 1), settingsViewModel.ZRotation)); }); }
private void viewport3D1_MouseMove(object sender, MouseEventArgs e) { if (!_isMouseDown || _geometries.Count != 1) // for single ball { return; } // Calculate the change in position from the last mouse move Point pos = GetMousePositionRelativeToCenterOfViewPort(); double dx = pos.X - _lastPos.X; double dy = pos.Y - _lastPos.Y; double mouseAngle = 0d; if (dx != 0d && dy != 0d) { mouseAngle = Math.Asin(Math.Abs(dy) / Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2))); if (dx < 0 && dy > 0) { mouseAngle += Math.PI / 2; } else if (dx < 0 && dy < 0) { mouseAngle += Math.PI; } else if (dx > 0 && dy < 0) { mouseAngle += Math.PI * 1.5; } } else if (dx == 0 && dy != 0) { mouseAngle = Math.Sign(dy) > 0 ? Math.PI / 2 : Math.PI * 1.5; } else if (dx != 0 && dy == 0) { mouseAngle = Math.Sign(dx) > 0 ? 0 : Math.PI; } double axisAngle = mouseAngle + Math.PI / 2; Vector3D axis = new Vector3D(Math.Cos(axisAngle) * 4, Math.Sin(axisAngle) * 4, 0); double rotation = 0.01 * Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2)); Transform3DGroup group = _geometries[0].Transform as Transform3DGroup; QuaternionRotation3D r = new QuaternionRotation3D(new Quaternion(axis, rotation * 180 / Math.PI)); //TODO: Create a combined rotation, instead of continually adding new partial ones group.Children.Add(new RotateTransform3D(r)); _lastPos = pos; }
public void InitializeViewer() { /////////////////////////////////////////// // Camera Initialize /////////////////////////////////////////// PerspectiveCamera PanoramaCamera = new PerspectiveCamera(); PanoramaCamera.Position = new Point3D(0, -0.0, 0); PanoramaCamera.UpDirection = new Vector3D(0, 1, 0); PanoramaCamera.LookDirection = new Vector3D(0, 0, 1); PanoramaCamera.FieldOfView = 80; this.Camera = PanoramaCamera; FieldOfView = 80; /////////////////////////////////////////// // Light Initialize /////////////////////////////////////////// ModelVisual3D LightModel = new ModelVisual3D(); LightModel.Content = new DirectionalLight(Colors.White, new Vector3D(0, 0, 1)); this.Children.Add(LightModel); /////////////////////////////////////////// // Panorama Object Initialize /////////////////////////////////////////// PanoramaObject = new ModelVisual3D(); PanoramaGeometry = new GeometryModel3D(); PanoramaGeometry.Geometry = CreateGeometry(); PanoramaObject.Content = PanoramaGeometry; RotateTransform3D RotateTransform = new RotateTransform3D(); double x = 1.0; ScaleTransform3D ScaleTransform = new ScaleTransform3D() { ScaleX = x * 1, ScaleY = x * 1.65, ScaleZ = x * 1 }; Transform3DGroup Group = new Transform3DGroup(); PanoramaRotation = new QuaternionRotation3D(); Group.Children.Add(ScaleTransform); Group.Children.Add(RotateTransform); RotateTransform.Rotation = PanoramaRotation; PanoramaObject.Transform = Group; this.Children.Add(PanoramaObject); }
private void RenderMineral() { ModelVisual3D visual = new ModelVisual3D(); visual.Content = Mineral.GetNewVisual(this.MineralType); _rotateTransform = new QuaternionRotation3D(Math3D.GetRandomRotation()); visual.Transform = new RotateTransform3D(_rotateTransform); _viewport.Children.Add(visual); _camera.Position = (_camera.Position.ToVector().ToUnit() * 2.5d).ToPoint(); }
/// <summary> /// This simply rotates the same direction and same speed forever /// </summary> public static AnimateRotation Create_Constant(QuaternionRotation3D transform, double angleDelta) { if (transform.Quaternion.IsIdentity) { throw new ArgumentException("The transform passed in is an identity quaternion, so the axis is unpredictable"); } return(new AnimateRotation() { _worker = new FixedWorker(transform, angleDelta) }); }
/// <summary> /// Rotate the rectangle by a quaternion /// </summary> /// <param name="rot">The quaternion to rotate by</param> /// <returns>The current rectangle instance</returns> public Rectangle3D Rotate(Quaternion rot) { foreach (var k in new List <string>(Corners.Keys)) { var q = new QuaternionRotation3D(new System.Windows.Media.Media3D.Quaternion(rot.X, rot.Y, rot.Z, rot.W)); var r = new RotateTransform3D(q, ToPoint3D(Center)); Corners[k] = ToVector3(r.Transform(ToPoint3D(Corners[k]))); } Position = Corners["000"]; GenerateEdges(); GenerateFaces(); return(this); }
//自定义方法,三维对象跟随鼠标旋转 public Point MouseFollow(Viewport3D vp3d, Point mLPosition, ModelVisual3D m3D) { //获取鼠标窗口坐标 Point Mpos = Mouse.GetPosition(vp3d); //鼠标相对于三维对象中心的坐标 Point mouseRelativePosition = new Point(Mpos.X - vp3d.ActualWidth / 2, vp3d.ActualHeight / 2 - Mpos.Y); //计算本次鼠标坐标与上次鼠标坐标的差 double shiftX = mouseRelativePosition.X - mLPosition.X, shiftY = mouseRelativePosition.Y - mLPosition.Y; double mouseRotationAngle = 0; if (shiftX != 0 && shiftY != 0) { //计算鼠标转动的角度(三维空间近似计算) mouseRotationAngle = Math.Asin(Math.Abs(shiftY) / Math.Sqrt(Math.Pow(shiftX, 2) + Math.Pow(shiftY, 2))); //mouseRotationAngle = 0.2; //如果位于第2象限 if (shiftX < 0 && shiftY > 0) { mouseRotationAngle += Math.PI / 2; } //如果位于第3象限 if (shiftX < 0 && shiftY < 0) { mouseRotationAngle += Math.PI; } //如果位于第4象限 if (shiftX > 0 && shiftY < 0) { mouseRotationAngle += Math.PI * 1.5; } } if (shiftX == 0 && shiftY != 0) { mouseRotationAngle = Math.Sign(shiftY) > 0 ? Math.PI / 2 : Math.PI * 1.5; } if (shiftX != 0 && shiftY == 0) { mouseRotationAngle = Math.Sign(shiftX) > 0 ? 0 : Math.PI; } //旋转轴和旋转面垂直,使用右手法则 double axisRotationAngle = mouseRotationAngle + Math.PI / 2; Vector3D RotationAxis = new Vector3D(Math.Cos(axisRotationAngle) * 10, Math.Sin(axisRotationAngle) * 10, 0); double RotationAngle = 0.01 * Math.Sqrt(Math.Pow(shiftX, 2) + Math.Pow(shiftY, 2)); Transform3DGroup TF3DGroup = m3D.Transform as Transform3DGroup; //声明四元旋转对象,实现3D旋转,旋转中心是三维对象的中心点 Quaternion quaternion = new Quaternion(RotationAxis, RotationAngle * 180 / Math.PI); QuaternionRotation3D Qr3D = new QuaternionRotation3D(quaternion); TF3DGroup.Children.Add(new RotateTransform3D(Qr3D)); return(mouseRelativePosition); }