/// <summary> /// Finds the bounding box for the specified visual. /// </summary> /// <param name="visual"> /// The visual. /// </param> /// <param name="transform"> /// The transform of the visual. /// </param> /// <returns> /// A <see cref="Rect3D"/>. /// </returns> public static Rect3D FindBounds(this Visual3D visual, Transform3D transform) { var bounds = Rect3D.Empty; var childTransform = Transform3DHelper.CombineTransform(visual.Transform, transform); var model = GetModel(visual); if (model != null) { // apply transform var transformedBounds = childTransform.TransformBounds(model.Bounds); if (!double.IsNaN(transformedBounds.X)) { bounds.Union(transformedBounds); } } foreach (var child in GetChildren(visual)) { if (child is IBoundsIgnoredVisual3D) { continue; } var b = FindBounds(child, childTransform); bounds.Union(b); } return(bounds); }
/// <summary> /// The on mouse move. /// </summary> /// <param name="e"> /// The event arguments. /// </param> protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (this.IsMouseCaptured) { var hitPlaneOrigin = this.ToWorld(this.Position); var p = e.GetPosition(this.ParentViewport); var nearestPoint = this.GetNearestPoint(p, hitPlaneOrigin, this.HitPlaneNormal); if (nearestPoint == null) { return; } var delta = this.ToLocal(nearestPoint.Value) - this.lastPoint; this.Value += Vector3D.DotProduct(delta, this.Direction); if (this.TargetTransform != null) { var translateTransform = new TranslateTransform3D(delta); this.TargetTransform = Transform3DHelper.CombineTransform(translateTransform, this.TargetTransform); } else { this.Position += delta; } nearestPoint = this.GetNearestPoint(p, hitPlaneOrigin, this.HitPlaneNormal); if (nearestPoint != null) { this.lastPoint = this.ToLocal(nearestPoint.Value); } } }
/// <summary> /// Gets the transform. /// </summary> /// <param name="current"> /// The current. /// </param> /// <param name="model"> /// The model. /// </param> /// <param name="parentTransform"> /// The parent transform. /// </param> /// <returns> /// The transform. /// </returns> public static GeneralTransform3D GetTransform(this Model3D current, Model3D model, Transform3D parentTransform) { var currentTransform = Transform3DHelper.CombineTransform(current.Transform, parentTransform); if (ReferenceEquals(current, model)) { return(currentTransform); } var mg = current as Model3DGroup; if (mg != null) { foreach (var m in mg.Children) { var result = GetTransform(m, model, currentTransform); if (result != null) { return(result); } } } return(null); }
/// <summary> /// Updates the TargetTransform in addition to updating position. /// </summary> /// <param name="e"> /// The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data. /// </param> protected override void OnPositionChanged(DependencyPropertyChangedEventArgs e) { base.OnPositionChanged(e); if (this.TargetTransform != null) { var delta = (Point3D)e.NewValue - (Point3D)e.OldValue; var translateTransform = new TranslateTransform3D(delta); this.TargetTransform = Transform3DHelper.CombineTransform(translateTransform, this.TargetTransform); } }
/// <summary> /// The export scene node. /// </summary> /// <param name="gm"> /// The gm. /// </param> /// <param name="transform"> /// The transform. /// </param> private void ExportSceneNode(Model3D gm, Transform3D transform) { string nodeId = this.nodes[gm]; string instanceId = nodeId + "-instance"; this.writer.WriteStartElement("node"); this.writer.WriteAttributeString("id", instanceId); this.writer.WriteAttributeString("name", instanceId); var totalTransform = Transform3DHelper.CombineTransform(transform, gm.Transform); this.WriteMatrix("matrix", totalTransform.Value); this.writer.WriteStartElement("instance_node"); this.writer.WriteAttributeString("url", "#" + nodeId); this.writer.WriteEndElement(); // instance node this.writer.WriteEndElement(); // node }
/// <summary> /// Updates the target transform by the change in rotation value. /// </summary> /// <param name="e"> /// The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data. /// </param> protected override void ValueChanged(DependencyPropertyChangedEventArgs e) { var oldValue = (double)e.OldValue; var newValue = (double)e.NewValue; var theta = newValue - oldValue; var rotateTransform = new RotateTransform3D( new AxisAngleRotation3D(this.Axis, theta), this.InternalPivotPoint); this.Transform = Transform3DHelper.CombineTransform(rotateTransform, this.Transform); if (this.TargetTransform != null) { var targetRotateTransform = new RotateTransform3D(new AxisAngleRotation3D(this.Axis, theta), this.Pivot); this.TargetTransform = Transform3DHelper.CombineTransform(targetRotateTransform, this.TargetTransform); } }
/// <summary> /// Traverses the visual tree and invokes the specified action on each object of the specified type. /// </summary> /// <typeparam name="T"> /// The type filter. /// </typeparam> /// <param name="visual"> /// The visual. /// </param> /// <param name="transform"> /// The transform. /// </param> /// <param name="action"> /// The action. /// </param> private static void Traverse <T>(Visual3D visual, Transform3D transform, Action <T, Transform3D> action) where T : Model3D { var childTransform = Transform3DHelper.CombineTransform(visual.Transform, transform); var model = GetModel(visual); if (model != null) { model.Traverse(childTransform, action); } foreach (var child in GetChildren(visual)) { Traverse(child, childTransform, action); } }
/// <summary> /// Invoked when an unhandled <see cref="E:System.Windows.Input.Mouse.MouseMove" /> 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.MouseEventArgs" /> that contains the event data.</param> protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (this.IsMouseCaptured) { var hitPlaneOrigin = this.ToWorld(this.Position); var hitPlaneNormal = this.ToWorld(this.Axis); var position = e.GetPosition(this.ParentViewport); var hitPoint = this.GetHitPlanePoint(position, hitPlaneOrigin, hitPlaneNormal); if (hitPoint == null) { return; } var currentPoint = this.ToLocal(hitPoint.Value); var v = this.lastPoint - this.Position; var u = currentPoint - this.Position; v.Normalize(); u.Normalize(); var currentAxis = Vector3D.CrossProduct(u, v); double sign = -Vector3D.DotProduct(this.Axis, currentAxis); double theta = Math.Sign(sign) * Math.Asin(currentAxis.Length) / Math.PI * 180; this.Value += theta; if (this.TargetTransform != null) { var rotateTransform = new RotateTransform3D(new AxisAngleRotation3D(this.Axis, theta), this.Pivot); this.TargetTransform = Transform3DHelper.CombineTransform(rotateTransform, this.TargetTransform); } hitPoint = this.GetHitPlanePoint(position, hitPlaneOrigin, hitPlaneNormal); if (hitPoint != null) { this.lastPoint = this.ToLocal(hitPoint.Value); } } }
/// <summary> /// The export model. /// </summary> /// <param name="writer">The writer.</param> /// <param name="model">The model.</param> /// <param name="transform">The transform.</param> protected override void ExportModel(ObjWriters writer, GeometryModel3D model, Transform3D transform) { writer.ObjWriter.WriteLine("o object{0}", this.objectNo++); writer.ObjWriter.WriteLine("g group{0}", this.groupNo++); if (this.exportedMaterials.ContainsKey(model.Material)) { string matName = this.exportedMaterials[model.Material]; writer.ObjWriter.WriteLine("usemtl {0}", matName); } else { string matName = string.Format("mat{0}", this.matNo++); writer.ObjWriter.WriteLine("usemtl {0}", matName); this.ExportMaterial(writer.MaterialsWriter, matName, model.Material, model.BackMaterial); this.exportedMaterials.Add(model.Material, matName); } var mesh = model.Geometry as MeshGeometry3D; this.ExportMesh(writer.ObjWriter, mesh, Transform3DHelper.CombineTransform(transform, model.Transform)); }
/// <summary> /// The expand. /// </summary> /// <param name="model"> /// The model. /// </param> /// <param name="transformation"> /// The transformation. /// </param> private void Expand(GeometryModel3D model, Transform3D transformation) { Transform3D ot; if (this.originalTransforms.ContainsKey(model)) { ot = this.originalTransforms[model]; } else { ot = model.Transform; this.originalTransforms.Add(model, ot); } Transform3D totalTransform = Transform3DHelper.CombineTransform(transformation, ot); var mesh = model.Geometry as MeshGeometry3D; if (mesh == null) { return; } var bounds = new Rect3D(); foreach (int i in mesh.TriangleIndices) { bounds.Union(totalTransform.Transform(mesh.Positions[i])); } Point3D p = bounds.Location; Vector3D d = p - this.actualExpandOrigin; d *= this.Expansion; Point3D p2 = this.actualExpandOrigin + d; var t = new TranslateTransform3D(p2 - p); model.Transform = Transform3DHelper.CombineTransform(ot, t); }
/// <summary> /// Traverses the Model3D tree and invokes the specified action on each Model3D of the specified type. /// </summary> /// <typeparam name="T"> /// The type. /// </typeparam> /// <param name="model"> /// The model. /// </param> /// <param name="transform"> /// The transform. /// </param> /// <param name="action"> /// The action. /// </param> public static void Traverse <T>(this Model3D model, Transform3D transform, Action <T, Transform3D> action) where T : Model3D { var mg = model as Model3DGroup; if (mg != null) { var childTransform = Transform3DHelper.CombineTransform(model.Transform, transform); foreach (var m in mg.Children) { Traverse(m, childTransform, action); } } var gm = model as T; if (gm != null) { var childTransform = Transform3DHelper.CombineTransform(model.Transform, transform); action(gm, childTransform); } }