private void MainCameraChanged(object sender, CameraChangedRoutedEventArgs cameraChangedRoutedEventArgs) { // If line with text and text plane are not visible than we can exit this method if (TextPlaneVisual3D.Material != null) { // Else we need to convert the 3D start and end positions into 2D screen position Point screenPosition1 = MainCamera.Point3DTo2D(DistanceLineVisual3D.StartPosition); Point screenPosition2 = MainCamera.Point3DTo2D(DistanceLineVisual3D.EndPosition); // Now we check if the start position has moved to the right of the end position // This means that because of rotated camera, we are not watching the text from behind - it appears flipped if (screenPosition1.X > screenPosition2.X) { if (!_isTextPlaneNormalFlipped) { // To flip the rendered text texture, we just flip the normal of the plane TextPlaneVisual3D.Normal = -1 * TextPlaneVisual3D.Normal; _isTextPlaneNormalFlipped = true; } } else if (_isTextPlaneNormalFlipped) { // Uh, the normal was previously flipped - we need to flip it again to make it as original value TextPlaneVisual3D.Normal = -1 * TextPlaneVisual3D.Normal; _isTextPlaneNormalFlipped = false; } } UpdateDisplayedDistanceMeasurement(); }
private void CameraOnCameraChanged(object sender, CameraChangedRoutedEventArgs e) { UpdateCanvasSize(); // When camera is changed, we need to update the 2D positions that are get from 3D points UpdateScreenPositions(); }
protected void OnCameraChanged(CameraChangedRoutedEventArgs e) { if (CameraChanged != null) { CameraChanged(this, e); } }
private void OnMainCameraChanged(object sender, CameraChangedRoutedEventArgs e) { if (_transparencySorter != null) { if (_stopwatch == null) { _stopwatch = new Stopwatch(); } _stopwatch.Restart(); _transparencySorter.Sort(TransparencySorter.SortingModeTypes.ByCameraDistance); _stopwatch.Stop(); _totalSortTime += _stopwatch.Elapsed.TotalMilliseconds; } if (_isSyncingCamera) { return; } OnCameraChanged(e); }
private void Camera1OnCameraChanged(object sender, CameraChangedRoutedEventArgs cameraChangedRoutedEventArgs) { // On each change of camera we will update the orientation of billboard objects. // When using PlaneVisual3D, TextBlockVisual3D or TextVisual3D we can simply call the AlignWithCamera method. // If we did some changes to the Camera1 in the code, // it is recommended to call Refresh before calling AlignWithCamera method: // Camera1.Refresh(); AlignBillboards(); }
private void OnCameraChanged(object sender, CameraChangedRoutedEventArgs e) { var testScene = sender as TestScene; var changedCamera = testScene.MainCamera; for (var i = 0; i < _testScenes.Length; i++) { if (_testScenes[i] == testScene) { continue; } _testScenes[i].SyncCamera(changedCamera); } }
private void Camera2_OnCameraChanged(object sender, CameraChangedRoutedEventArgs e) { if (!this.IsLoaded || _isInternalCameraChange) { return; } //Synchronize Camera1 and Camera2 _isInternalCameraChange = true; Camera1.Heading = Camera2.Heading; Camera1.Attitude = Camera2.Attitude; Camera1.Distance = Camera2.Distance; _isInternalCameraChange = false; }
private void Camera2_OnCameraChanged(object sender, CameraChangedRoutedEventArgs e) { if (_isInternalChange) // Prevent infinite call or Camera1 / 2 change handlers { return; } _isInternalChange = true; Camera1.BeginInit(); Camera1.Heading = Camera2.Heading; Camera1.Attitude = Camera2.Attitude; Camera1.Distance = Camera2.Distance; Camera1.Offset = Camera2.Offset; Camera1.EndInit(); _isInternalChange = false; }
private void Camera1OnCameraChanged(object o, CameraChangedRoutedEventArgs cameraChangedRoutedEventArgs) { // To check if we need to flip TextDirection, // we first calculate the 3D vector that points into the direction from which the text is correctly seen. // This can be get with calculating cross product from TextDirection and UpDirection - getting perpendicular vector to those two vectors. Vector3D textFaceVector = Vector3D.CrossProduct(CenteredTextVisual2.TextDirection, CenteredTextVisual2.UpDirection); // Now calculate dot product from textFaceVector and camera's LookDirection // If the result is negative, then those two vectors are facing in opposite direction. // This is a desired result - text is facing towards camera and camera towards text. // But if the result is positive, then text is seen correctly from the other side. // In this case we flip the TextDirection by multiplying it with -1. // In our case this flips between initial (1, 0, 0) and (-1, 0, 0) vectors. if (Vector3D.DotProduct(textFaceVector, Camera1.LookDirection) > 0) { CenteredTextVisual2.TextDirection = CenteredTextVisual2.TextDirection * (-1); } }
private void CustomCamera_OnCameraChanged(object sender, CameraChangedRoutedEventArgs e) { double newCameraDistance = _customCamera.Distance; double distanceChangeFactor = newCameraDistance / _previousCameraDistance; _previousCameraDistance = newCameraDistance; // When custom camera (controller by user) is changed, we also change other cameras // But do not change distance (because this is different based on the size of the sphere) foreach (var targetPositionCamera in RootGrid.Children.OfType <TargetPositionCamera>()) { if (ReferenceEquals(_customCamera, targetPositionCamera)) { continue; } targetPositionCamera.Heading = _customCamera.Heading; targetPositionCamera.Attitude = _customCamera.Attitude; targetPositionCamera.Distance *= distanceChangeFactor; } }
private void WpfCamera_OnCameraChanged(object sender, CameraChangedRoutedEventArgs e) { CopyWpfCamera(); }
private void CameraOnCameraChanged(object sender, CameraChangedRoutedEventArgs cameraChangedRoutedEventArgs) { UpdateAxis(recreateEverything: false); }
private void Camera1OnCameraChanged(object sender, CameraChangedRoutedEventArgs cameraChangedRoutedEventArgs) { if (!(AlignWithCameraCheckBox.IsChecked ?? false)) { return; } // On each change of camera we will update the orientation of billboard objects. // When using PlaneVisual3D, TextBlockVisual3D or TextVisual3D we can simply call the AlignWithCamera method. // If we did some changes to the Camera1 in the code, // it is recommended to call Refresh before calling AlignWithCamera method: // Camera1.Refresh(); bool fixYAxis = FixYAxisCheckBox.IsChecked ?? false; PlaneVisual1.AlignWithCamera(Camera1); TextBlockVisual3D1.AlignWithCamera(Camera1); if (fixYAxis) { // To show a billboard with fixed Y axis, we first call AlignWithCamera and then set the UpDirection back to Y axis. PlaneVisual1.HeightDirection = Ab3d.Common.Constants.UpVector; // = new Vector3D(0, 1, 0); TextBlockVisual3D1.UpDirection = Ab3d.Common.Constants.UpVector; } if (FixScreenSizeCheckBox.IsChecked ?? false) { // When FixScreenSizeCheckBox is checked, we update the size of the billboards in 3D works // so that they are rendered to the same size on the screen. // // This is done with the GetWorldSize method that calculates a size in 3D world coordinates from a size provided in 2D screen coordinates. // You can also use CameraUtils.GetOrthographicWorldSize and CameraUtils.GetPerspectiveWorldSize methods to get the same results but with more low level parameters. // // It is also possible to get the opposite value - size on screen - with the following methods: // Camera1.GetScreenSize(Size worldSize, Point3D targetPosition3D) // CameraUtils.GetPerspectiveScreenSize(Size worldSize, double lookDirectionDistance, double fieldOfView, Size viewport3DSize) // CameraUtils.GetOrthographicScreenSize(Size worldSize, double cameraWidth, Size viewport3DSize) // Set the size so that it will be shown in 200 x 40 box on the screen. Size worldSize = Camera1.GetWorldSize(new Size(200, 40), TextBlockVisual3D1.Position); // With TextBlockVisual3D we can use multiple methods to adjust the size of the text: // 1) Change FontSize property - this is the most performance expensive method because this will require to update the text (and render the bitmap if it is used to show the content of TextBlockVisual3D - for example when in DXEngine). // 2) Change Size property - this is better but would require to update the plane's MeshGeometry3D. This creates a lot of objects on each camera change and require frequent garbage collections. // TextBlockVisual3D1.Size = worldSize; // 3) Scale the TextBlockVisual3D1 to the required size. This is by far the fastest and most efficient method because only the transformation is changed: var scaleTransform3D = TextBlockVisual3D1.Transform as ScaleTransform3D; if (scaleTransform3D == null) { scaleTransform3D = new ScaleTransform3D(); // To prevent scaling the position (multiplying it with the scale factor), we need to set the center of scale scaleTransform3D.CenterX = TextBlockVisual3D1.Position.X; scaleTransform3D.CenterY = TextBlockVisual3D1.Position.Y; scaleTransform3D.CenterZ = TextBlockVisual3D1.Position.Z; TextBlockVisual3D1.Transform = scaleTransform3D; } // Calculate required scale to get the size of the TextBlockVisual3D to the required worldSize double scaleFactor = worldSize.Width / TextBlockVisual3D1.Size.Width; scaleTransform3D.ScaleX = scaleFactor; scaleTransform3D.ScaleY = scaleFactor; scaleTransform3D.ScaleZ = scaleFactor; // Do the same for PlaneVisual3D worldSize = Camera1.GetWorldSize(new Size(200, 40), PlaneVisual1.CenterPosition); // The easiest way to update the size of a PlaneVisual3D is to change its Size. // But because this creates a new MeshGeometry3D, this can produce a lot of garbage because this is called on each frame (on each camera change). // Therefore it is better to use ScaleTransform3D to update the size. //PlaneVisual1.Size = worldSize; scaleTransform3D = PlaneVisual1.Transform as ScaleTransform3D; if (scaleTransform3D == null) { scaleTransform3D = new ScaleTransform3D(); // To prevent scaling the position (multiplying it with the scale factor), we need to set the center of scale scaleTransform3D.CenterX = PlaneVisual1.CenterPosition.X; scaleTransform3D.CenterY = PlaneVisual1.CenterPosition.Y; scaleTransform3D.CenterZ = PlaneVisual1.CenterPosition.Z; PlaneVisual1.Transform = scaleTransform3D; } scaleFactor = worldSize.Width / PlaneVisual1.Size.Width; scaleTransform3D.ScaleX = scaleFactor; scaleTransform3D.ScaleY = scaleFactor; scaleTransform3D.ScaleZ = scaleFactor; } else { // When FixScreenSizeCheckBox is unchecked, reset the size back to initial size TextBlockVisual3D1.Transform = null; PlaneVisual1.Transform = null; // The following code is used if we do not use ScaleTransform3D but instead change the Size //if (TextBlockVisual3D1.Size.Width != 80) // TextBlockVisual3D1.Size = new Size(80, 20); //if (PlaneVisual1.Size.Width != 80) // PlaneVisual1.Size = new Size(80, 20); } // Update all tree objects foreach (var treePlaneVisual in TreesPlaceholerVisual3D.Children.OfType <PlaneVisual3D>()) { treePlaneVisual.AlignWithCamera(Camera1); if (fixYAxis) { treePlaneVisual.HeightDirection = Ab3d.Common.Constants.UpVector; } } // After objects were rotated, we can reorder them so that those farther away from the camera are rendered first. // This way the objects will be correctly visible through transparent objects. _transparencySorter.Sort(TransparencySorter.SortingModeTypes.ByCameraDistance); UpdateOverlayCanvasElements(); }