/// <summary> /// The sort children. /// </summary> private void SortChildren() { var vp = Visual3DHelper.GetViewport3D(this); if (vp == null) { return; } var cam = vp.Camera as ProjectionCamera; if (cam == null) { return; } var cameraPos = cam.Position; var transform = new MatrixTransform3D(Visual3DHelper.GetTransform(this)); IList <Visual3D> transparentChildren = new List <Visual3D>(); IList <Visual3D> opaqueChildren = new List <Visual3D>(); if (this.CheckForOpaqueVisuals) { foreach (var child in this.Children) { if (this.IsVisualTransparent(child)) { transparentChildren.Add(child); } else { opaqueChildren.Add(child); } } } else { transparentChildren = this.Children; } // sort the children by distance from camera (note that OrderBy is a stable sort algorithm) var sortedTransparentChildren = transparentChildren.OrderBy(item => - this.GetCameraDistance(item, cameraPos, transform)).ToList(); this.Children.Clear(); // add the opaque children foreach (var c in opaqueChildren) { this.Children.Add(c); } // add the sorted transparent children foreach (var c in sortedTransparentChildren) { this.Children.Add(c); } }
/// <summary> /// Updates the clipping object. /// </summary> private void UpdateClipping() { var vp = Visual3DHelper.GetViewport3D(this); if (vp == null) { return; } this.Clipping = new CohenSutherlandClipping(10, vp.ActualWidth - 20, 10, vp.ActualHeight - 20); }
/// <summary> /// Invoked when an unhandled <see cref="E:System.Windows.Input.Mouse.MouseDown" /> attached event reaches an element in its route that is derived from this class. Implement this method to add class handling for this event. /// </summary> /// <param name="e">The <see cref="T:System.Windows.Input.MouseButtonEventArgs" /> that contains the event data. This event data reports details about the mouse button that was pressed and the handled state.</param> protected override void OnMouseDown(MouseButtonEventArgs e) { base.OnMouseDown(e); this.ParentViewport = Visual3DHelper.GetViewport3D(this); this.Camera = this.ParentViewport.Camera as ProjectionCamera; var projectionCamera = this.Camera; if (projectionCamera != null) { this.HitPlaneNormal = projectionCamera.LookDirection; } this.CaptureMouse(); }
/// <summary> /// The sort children. /// </summary> private void SortChildren() { var vp = Visual3DHelper.GetViewport3D(this); if (vp == null) { return; } var cam = vp.Camera as ProjectionCamera; if (cam == null) { return; } var cameraPos = cam.Position; var transform = new MatrixTransform3D(Visual3DHelper.GetTransform(this)); IList <Visual3D> transparentChildren = new List <Visual3D>(); IList <Visual3D> opaqueChildren = new List <Visual3D>(); if (this.CheckForOpaqueVisuals) { foreach (var child in this.Children) { if (this.IsVisualTransparent(child)) { transparentChildren.Add(child); } else { opaqueChildren.Add(child); } } } else { transparentChildren = this.Children; } // sort the children by distance from camera (note that OrderBy is a stable sort algorithm) var sortedTransparentChildren = transparentChildren.OrderBy(item => - this.GetCameraDistance(item, cameraPos, transform)).ToList(); // Now that opaqueChildren and sortedTransparentChildren describe our desired ordering, we need sort the current children in the new order. // To optimize the efficiency of this procedure we want to change the children list as little as possible. // Unfortunatally the Visual3DCollection does not have a swap method and we always need to remove an item before we can add it again as // temporary duplicates result in exceptions in the visual tree. // Due to this set of considerations we use selection sort to sort the current Children. (if we could swap without removal, cycle sort might be a small improvement) for (int desiredIndex = 0; desiredIndex < opaqueChildren.Count; desiredIndex++) { Visual3D currentChild = opaqueChildren[desiredIndex]; int currentIndex = Children.IndexOf(currentChild); //Insert in the proper spot if not contained: if (currentIndex == -1) { Children.Insert(desiredIndex, currentChild); continue; } //Do nothing if it is in the correct spot; //The order of the opaque children does not matter as long as they are before the transparent children: if (currentIndex < opaqueChildren.Count) { continue; } //remove from old spot and insert to the new correct spot: Children.RemoveAt(currentIndex); Children.Insert(desiredIndex, currentChild); } for (int desiredIndex = opaqueChildren.Count; desiredIndex < opaqueChildren.Count + sortedTransparentChildren.Count; desiredIndex++) { Visual3D currentChild = sortedTransparentChildren[desiredIndex - opaqueChildren.Count]; int currentIndex = Children.IndexOf(currentChild); //Insert in the proper spot if not contained: if (currentIndex == -1) { Children.Insert(desiredIndex, currentChild); continue; } //Do nothing if it is in the correct spot: if (currentIndex == desiredIndex) { continue; } //remove from old spot and insert to the new correct spot: Children.RemoveAt(currentIndex); Children.Insert(desiredIndex, currentChild); } }