protected void CreatePositions(double thickness = 2.0, double depthOffset = 0.0) { double halfThickness = thickness * 0.5; int segmentCount = _linePoints.Count / 2; Point3DCollection positions = new Point3DCollection(segmentCount * 4); for (int i = 0; i < segmentCount; i++) { int startIndex = i * 2; Point3D startPoint = _linePoints[startIndex]; Point3D endPoint = _linePoints[startIndex + 1]; Point4D s0 = (Point4D)startPoint * _visualToScreen; Point4D s1 = (Point4D)endPoint * _visualToScreen; double lx = s1.X / s1.W - s0.X / s0.W; double ly = s1.Y / s1.W - s0.Y / s0.W; double j = halfThickness / Math.Sqrt(lx * lx + ly * ly); double dx = -ly * j; double dy = lx * j; Point4D p0 = s0; Point4D p1 = s0; Point4D p2 = s1; Point4D p3 = s1; p0.X += dx * p0.W; p0.Y += dy * p0.W; p1.X -= dx * p1.W; p1.Y -= dy * p1.W; p2.X += dx * p2.W; p2.Y += dy * p2.W; p3.X -= dx * p3.W; p3.Y -= dy * p3.W; if (depthOffset != 0.0) { p0.Z -= depthOffset; p1.Z -= depthOffset; p2.Z -= depthOffset; p3.Z -= depthOffset; p0 *= _screenToVisual; p1 *= _screenToVisual; p2 *= _screenToVisual; p3 *= _screenToVisual; positions.Add(new Point3D(p0.X / p0.W, p0.Y / p0.W, p0.Z / p0.W)); positions.Add(new Point3D(p1.X / p0.W, p1.Y / p1.W, p1.Z / p1.W)); positions.Add(new Point3D(p2.X / p0.W, p2.Y / p2.W, p2.Z / p2.W)); positions.Add(new Point3D(p3.X / p0.W, p3.Y / p3.W, p3.Z / p3.W)); } else { p0 *= _screenToVisual; p1 *= _screenToVisual; p2 *= _screenToVisual; p3 *= _screenToVisual; positions.Add(new Point3D(p0.X, p0.Y, p0.Z)); positions.Add(new Point3D(p1.X, p1.Y, p1.Z)); positions.Add(new Point3D(p3.X, p3.Y, p3.Z)); positions.Add(new Point3D(p2.X, p2.Y, p2.Z)); } } positions.Freeze(); _mesh.Positions = positions; }
private void SetPoints() { if (!this.ShowLinesVisual3D) { this.LinePoints = new Point3DCollection(); } if (!this.ShowPointsVisual3D) { this.Points = new Point3DCollection(); } if (this.ShowLinesVisual3D || this.ShowPointsVisual3D) { var newPoints = PointsAndLinesDemo.MainWindow.GeneratePoints(this.NumberOfPoints, this.watch.ElapsedMilliseconds * 0.001) .ToArray(); if (this.ShowPointsVisual3D) { var pc = new Point3DCollection(newPoints); pc.Freeze(); this.Points = pc; } if (this.ShowLinesVisual3D) { var pc = new Point3DCollection(newPoints); pc.Freeze(); this.LinePoints = pc; } } }
protected ModelVisual3D MakeVisualModel(LoadResult objmesh, ZipArchiveEntry texture) { var r = new ModelVisual3D(); r.Content = MakeModel(objmesh, texture); Points.Freeze(); // We won't change them anymore Normals.Freeze(); Indices.Freeze(); TexCoords.Freeze(); r.Transform = new Transform3DGroup(); Transform3DGroup transformGroup = r.Transform as Transform3DGroup; TranslateTransform3D translation = new TranslateTransform3D( -(r.Content.Bounds.X + r.Content.Bounds.SizeX / 2), -(r.Content.Bounds.Y + r.Content.Bounds.SizeY / 2), -(r.Content.Bounds.Z + r.Content.Bounds.SizeZ / 2) ); transformGroup.Children.Add(translation); double scale = Math.Abs(1 / (r.Content.Bounds.SizeX)); scale = Math.Min(scale, Math.Abs(1 / (r.Content.Bounds.SizeY))); scale = Math.Min(scale, Math.Abs(1 / (r.Content.Bounds.SizeZ))); ScaleTransform3D scaletr = new ScaleTransform3D(scale, scale, scale); transformGroup.Children.Add(scaletr); return(r); }
protected ModelVisual3D MakeVisualModel() { var r = new ModelVisual3D(); r.Content = MakeModel(); Points.Freeze(); // We won't change them anymore Indices.Freeze(); r.Transform = new Transform3DGroup(); Transform3DGroup transformGroup = r.Transform as Transform3DGroup; Transform3DGroup meshTransformGroup = _model.Transform as Transform3DGroup; transformGroup.Children.Add(meshTransformGroup.Children [0].Clone()); transformGroup.Children.Add(meshTransformGroup.Children [1].Clone()); return(r); }
/// <summary> /// Gets the billboard positions with the current screen transform. /// </summary> /// <param name="billboards">The billboards.</param> /// <param name="offset">The offset.</param> /// <param name="pinWidth">Width of the pins.</param> /// <returns>The mesh vertices.</returns> public Point3DCollection GetPinPositions(IList <Billboard> billboards, Vector offset, double pinWidth) { var pinStart = new Point(0, 0); var pinEnd = pinStart + (offset * (1 + (2 * pinWidth / offset.Length))); var pinNormal = new Vector(pinEnd.Y, -pinEnd.X); pinNormal.Normalize(); pinNormal *= pinWidth * 0.5; var pinPoints = new Point[4]; pinPoints[0] = new Point(0, 0) + (pinNormal * 0.5); pinPoints[1] = new Point(0, 0) - (pinNormal * 0.5); pinPoints[2] = pinEnd - pinNormal; pinPoints[3] = pinEnd + pinNormal; var positions = new Point3DCollection(billboards.Count * 4); foreach (var bb in billboards) { Point4D screenPoint; if (!bb.WorldDepthOffset.Equals(0)) { var viewPoint = (Point4D)bb.Position * this.visualToProjection; screenPoint = new Point4D(viewPoint.X, viewPoint.Y, viewPoint.Z + bb.WorldDepthOffset, viewPoint.W) * this.projectionToScreen; } else { screenPoint = (Point4D)bb.Position * this.visualToScreen; } double spw = screenPoint.W; double spx = screenPoint.X; double spy = screenPoint.Y; double spz = screenPoint.Z - ((bb.DepthOffset - 1e-5) * spw); foreach (var pinPoint in pinPoints) { var p = new Point4D(spx + (pinPoint.X * spw), spy + (pinPoint.Y * spw), spz, spw) * this.screenToVisual; double wi = 1 / p.W; positions.Add(new Point3D(p.X * wi, p.Y * wi, p.Z * wi)); } } positions.Freeze(); return(positions); }
/// <summary> /// Gets the billboard positions with the current screen transform. /// </summary> /// <param name="billboards">The billboards.</param> /// <param name="offset">The offset.</param> /// <returns>The positions.</returns> public Point3DCollection GetPositions(IList <Billboard> billboards, Vector offset) { var positions = new Point3DCollection(billboards.Count * 4); foreach (var bb in billboards) { Point4D screenPoint; if (!bb.WorldDepthOffset.Equals(0)) { var viewPoint = (Point4D)bb.Position * this.visualToProjection; screenPoint = new Point4D(viewPoint.X, viewPoint.Y, viewPoint.Z + bb.WorldDepthOffset, viewPoint.W) * this.projectionToScreen; } else { screenPoint = (Point4D)bb.Position * this.visualToScreen; } double spw = screenPoint.W; double spx = screenPoint.X; double spy = screenPoint.Y; double spz = screenPoint.Z - (bb.DepthOffset * spw); // Convert bottom-left corner to visual space var p = new Point4D(spx + ((bb.Left + offset.X) * spw), spy + ((bb.Bottom + offset.Y) * spw), spz, spw) * this.screenToVisual; double wi = 1 / p.W; positions.Add(new Point3D(p.X * wi, p.Y * wi, p.Z * wi)); // Convert bottom-right corner to visual space p = new Point4D(spx + ((bb.Right + offset.X) * spw), spy + ((bb.Bottom + offset.Y) * spw), spz, spw) * this.screenToVisual; wi = 1 / p.W; positions.Add(new Point3D(p.X * wi, p.Y * wi, p.Z * wi)); // Convert top-right corner to visual space p = new Point4D(spx + ((bb.Right + offset.X) * spw), spy + ((bb.Top + offset.Y) * spw), spz, spw) * this.screenToVisual; wi = 1 / p.W; positions.Add(new Point3D(p.X * wi, p.Y * wi, p.Z * wi)); // Convert top-left corner to visual space p = new Point4D(spx + ((bb.Left + offset.X) * spw), spy + ((bb.Top + offset.Y) * spw), spz, spw) * this.screenToVisual; wi = 1 / p.W; positions.Add(new Point3D(p.X * wi, p.Y * wi, p.Z * wi)); } positions.Freeze(); return(positions); }
private void AddWirefreamPoints(Point3D[,] pts) { Point3DCollection points = new Point3DCollection(pts.Length); int xLength = pts.GetLength(0); int yLength = pts.GetLength(1); for (int x = 0; x < xLength - 1; x++) { if (!double.IsNaN(pts[x, 0].Z)) { if (double.IsNaN(pts[x + 1, 0].Z)) { for (int y = 0; y < yLength - 1; y++) { points.Add(pts[x, y]); points.Add(pts[x, y + 1]); } } else { for (int y = 0; y < yLength - 1; y++) { points.Add(pts[x, y]); points.Add(pts[x, y + 1]); points.Add(pts[x, y]); points.Add(pts[x + 1, y]); } points.Add(pts[x, yLength - 1]); points.Add(pts[x + 1, yLength - 1]); } } } if (!double.IsNaN(pts[xLength - 1, 0].Z)) { for (int y = 0; y < yLength - 1; y++) { points.Add(pts[xLength - 1, y]); points.Add(pts[xLength - 1, y + 1]); } } points.Freeze(); base.Points = points; }
/// <summary> /// Creates the positions for the specified points. /// </summary> /// <param name="points"> /// The points. /// </param> /// <param name="size"> /// The size of the points. /// </param> /// <param name="depthOffset"> /// The depth offset. A positive number (e.g. 0.0001) moves the point towards the camera. /// </param> /// <returns> /// The positions collection. /// </returns> public Point3DCollection CreatePositions(IList <Point3D> points, double size = 1.0, double depthOffset = 0.0) { double halfSize = size / 2.0; int numPoints = points.Count; var outline = new[] { new Vector(-halfSize, halfSize), new Vector(-halfSize, -halfSize), new Vector(halfSize, halfSize), new Vector(halfSize, -halfSize) }; var positions = new Point3DCollection(numPoints * 4); for (int i = 0; i < numPoints; i++) { var screenPoint = (Point4D)points[i] * this.visualToScreen; double spx = screenPoint.X; double spy = screenPoint.Y; double spz = screenPoint.Z; double spw = screenPoint.W; if (!depthOffset.Equals(0)) { spz -= depthOffset * spw; } var p0 = new Point4D(spx, spy, spz, spw) * this.screenToVisual; double pwinverse = 1 / p0.W; foreach (var v in outline) { var p = new Point4D(spx + v.X * spw, spy + v.Y * spw, spz, spw) * this.screenToVisual; positions.Add(new Point3D(p.X * pwinverse, p.Y * pwinverse, p.Z * pwinverse)); } } positions.Freeze(); return(positions); }
protected void CreatePositions(double depthOffset = 0.0) { double halfSize = this.Size / 2.0; int numPoints = this.Points.Length; Vector[] outline = new Vector[] { new Vector(-halfSize, halfSize), new Vector(-halfSize, -halfSize), new Vector(halfSize, halfSize), new Vector(halfSize, -halfSize) }; Point3DCollection positions = new Point3DCollection(numPoints * 4); for (int x = 0; x < this.Points.GetLength(0); x++) { for (int y = 0; y < this.Points.GetLength(1); y++) { Point4D screenPoint = (Point4D)this.Points[x, y] * _visualToScreen; double spx = screenPoint.X; double spy = screenPoint.Y; double spz = screenPoint.Z; double spw = screenPoint.W; if (!depthOffset.Equals(0.0)) { spz -= depthOffset * spw; } double pwinverse = 1.0 / (new Point4D(spx, spy, spz, spw) * _screenToVisual).W; Vector[] array = outline; for (int i = 0; i < array.Length; i++) { Vector v = array[i]; Point4D p = new Point4D(spx + v.X * spw, spy + v.Y * spw, spz, spw) * _screenToVisual; positions.Add(new Point3D(p.X * pwinverse, p.Y * pwinverse, p.Z * pwinverse)); } } } positions.Freeze(); _mesh.Positions = positions; }
public Point3DCollection GetCenterOutLines(Rect3D rect) { Point3DCollection result = new Point3DCollection { new Point3D(rect.X + rect.SizeX, rect.Y + rect.SizeY / 2, rect.Z + rect.SizeZ / 2), new Point3D(rect.X + rect.SizeX + LineWith, rect.Y + rect.SizeY / 2, rect.Z + rect.SizeZ / 2), new Point3D(rect.X, rect.Y + rect.SizeY / 2, rect.Z + rect.SizeZ / 2), new Point3D(rect.X - LineWith, rect.Y + rect.SizeY / 2, rect.Z + rect.SizeZ / 2), new Point3D(rect.X + rect.SizeX / 2, rect.Y + rect.SizeY, rect.Z + rect.SizeZ / 2), new Point3D(rect.X + rect.SizeX / 2, rect.Y + rect.SizeY + LineWith, rect.Z + rect.SizeZ / 2), new Point3D(rect.X + rect.SizeX / 2, rect.Y, rect.Z + rect.SizeZ / 2), new Point3D(rect.X + rect.SizeX / 2, rect.Y - LineWith, rect.Z + rect.SizeZ / 2), new Point3D(rect.X + rect.SizeX / 2, rect.Y + rect.SizeY / 2, rect.Z + rect.SizeZ), new Point3D(rect.X + rect.SizeX / 2, rect.Y + rect.SizeY / 2, rect.Z + rect.SizeZ + LineWith), new Point3D(rect.X + rect.SizeX / 2, rect.Y + rect.SizeY / 2, rect.Z), new Point3D(rect.X + rect.SizeX / 2, rect.Y + rect.SizeY / 2, rect.Z - LineWith) }; result.Freeze(); return(result); }
/// <summary> /// Creates the positions for the specified points. /// </summary> /// <param name="points"> /// The points. /// </param> /// <param name="size"> /// The size of the points. /// </param> /// <param name="depthOffset"> /// The depth offset. A positive number (e.g. 0.0001) moves the point towards the camera. /// </param> /// <returns> /// The positions collection. /// </returns> public Point3DCollection CreatePositions(IList <Point3D> points, double size = 1.0, double depthOffset = 0.0) { double halfSize = size / 2.0; int numPoints = points.Count; var outline = new[] { new Vector(-halfSize, halfSize), new Vector(-halfSize, -halfSize), new Vector(halfSize, halfSize), new Vector(halfSize, -halfSize) }; var positions = new Point3DCollection(numPoints * 4); for (int i = 0; i < numPoints; i++) { var screenPoint = (Point4D)points[i] * this.visualToScreen; foreach (var v in outline) { var p = screenPoint; p.X += v.X * p.W; p.Y += v.Y * p.W; if (depthOffset != 0) { p.Z -= depthOffset * p.W; p *= this.screenToVisual; positions.Add(new Point3D(p.X / p.W, p.Y / p.W, p.Z / p.W)); } else { p *= this.screenToVisual; Debug.Assert(Math.Abs(p.W - 1) < 1e-6, "Something wrong with the homogeneous coordinates."); positions.Add(new Point3D(p.X, p.Y, p.Z)); } } } positions.Freeze(); return(positions); }
/// <summary> /// Gets the billboard positions with the current screen transform. /// </summary> /// <returns>The positions.</returns> public Point3DCollection GetPositions(IList <Billboard> billboards) { var positions = new Point3DCollection(billboards.Count * 4); foreach (var bb in billboards) { var screenPoint = (Point4D)bb.Position * this.visualToScreen; double spx = screenPoint.X; double spy = screenPoint.Y; double spz = screenPoint.Z; double spw = screenPoint.W; if (!bb.DepthOffset.Equals(0)) { spz -= bb.DepthOffset * spw; } var p0 = new Point4D(spx, spy, spz, spw) * this.screenToVisual; double pwinverse = 1 / p0.W; var p1 = new Point4D(spx + bb.Left * spw, spy + bb.Bottom * spw, spz, spw) * this.screenToVisual; positions.Add(new Point3D(p1.X * pwinverse, p1.Y * pwinverse, p1.Z * pwinverse)); var p2 = new Point4D(spx + bb.Right * spw, spy + bb.Bottom * spw, spz, spw) * this.screenToVisual; positions.Add(new Point3D(p2.X * pwinverse, p2.Y * pwinverse, p2.Z * pwinverse)); var p3 = new Point4D(spx + bb.Right * spw, spy + bb.Top * spw, spz, spw) * this.screenToVisual; positions.Add(new Point3D(p3.X * pwinverse, p3.Y * pwinverse, p3.Z * pwinverse)); var p4 = new Point4D(spx + bb.Left * spw, spy + bb.Top * spw, spz, spw) * this.screenToVisual; positions.Add(new Point3D(p4.X * pwinverse, p4.Y * pwinverse, p4.Z * pwinverse)); } positions.Freeze(); return(positions); }
private void SendGraphicsToView(Point3DCollection points, Point3DCollection pointsSelected, Point3DCollection lines, Point3DCollection linesSelected, Point3DCollection redLines, Point3DCollection greenLines, Point3DCollection blueLines, Point3DCollection verts, Vector3DCollection norms, Int32Collection tris, Point3DCollection vertsSel, Vector3DCollection normsSel, Int32Collection trisSel, MeshGeometry3D mesh, MeshGeometry3D meshSel, List <BillboardTextItem> text) { points.Freeze(); pointsSelected.Freeze(); lines.Freeze(); linesSelected.Freeze(); redLines.Freeze(); greenLines.Freeze(); blueLines.Freeze(); verts.Freeze(); norms.Freeze(); tris.Freeze(); vertsSel.Freeze(); normsSel.Freeze(); trisSel.Freeze(); Points = points; PointsSelected = pointsSelected; Lines = lines; LinesSelected = linesSelected; XAxes = redLines; YAxes = greenLines; ZAxes = blueLines; mesh.Positions = verts; mesh.Normals = norms; mesh.TriangleIndices = tris; meshSel.Positions = vertsSel; meshSel.Normals = normsSel; meshSel.TriangleIndices = trisSel; Mesh = mesh; MeshSelected = meshSel; Text = text; }
/// <summary> /// Creates a billboard. /// </summary> /// <param name="position">The position (centre).</param> /// <param name="width">The width of the billboard.</param> /// <param name="height">The height of the billboard.</param> /// <param name="depthOffset">The depth offset.</param> /// <returns>The points of the billboard.</returns> public Point3DCollection CreateBillboard(Point3D position, double width = 1.0, double height = 1.0, double depthOffset = 0.0) { double halfWidth = width / 2.0; double halfHeight = height / 2.0; var outline = new[] { new Vector(-halfWidth, halfHeight), new Vector(-halfWidth, -halfHeight), new Vector(halfWidth, halfHeight), new Vector(halfWidth, -halfHeight) }; var positions = new Point3DCollection(4); var screenPoint = (Point4D)position * this.visualToScreen; foreach (var v in outline) { var p = screenPoint; p.X += v.X * p.W; p.Y += v.Y * p.W; if (depthOffset != 0) { p.Z -= depthOffset * p.W; p *= this.screenToVisual; positions.Add(new Point3D(p.X / p.W, p.Y / p.W, p.Z / p.W)); } else { p *= this.screenToVisual; Debug.Assert(Math.Abs(p.W - 1) < 1e-6, "Something wrong with the homogeneous coordinates."); positions.Add(new Point3D(p.X, p.Y, p.Z)); } } positions.Freeze(); return(positions); }
private void RebuildGeometry() { double halfThickness = Thickness / 2.0; int numLines = Points.Count / 2; Point3DCollection positions = new Point3DCollection(numLines * 4); for (int i = 0; i < numLines; i++) { int startIndex = i * 2; Point3D startPoint = Points[startIndex]; Point3D endPoint = Points[startIndex + 1]; AddSegment(positions, startPoint, endPoint, halfThickness); } positions.Freeze(); _mesh.Positions = positions; Int32Collection indices = new Int32Collection(Points.Count * 3); for (int i = 0; i < Points.Count / 2; i++) { indices.Add(i * 4 + 2); indices.Add(i * 4 + 1); indices.Add(i * 4 + 0); indices.Add(i * 4 + 2); indices.Add(i * 4 + 3); indices.Add(i * 4 + 1); } indices.Freeze(); _mesh.TriangleIndices = indices; }
protected void CreateWirefreamPoints() { _linePoints = new Point3DCollection(this.Points.Length); int xLength = this.Points.GetLength(0); int yLength = this.Points.GetLength(1); for (int x = 0; x < xLength; x++) { for (int y = 0; y < yLength; y++) { if (y < yLength - 1) { _linePoints.Add(this.Points[x, y]); _linePoints.Add(this.Points[x, y + 1]); } if (x < xLength - 1) { _linePoints.Add(this.Points[x, y]); _linePoints.Add(this.Points[x + 1, y]); } } } _linePoints.Freeze(); }
/// <summary> /// Use the render packages returned from the visualization manager to update the visuals. /// The visualization event arguments will contain a set of render packages and an id representing /// the associated node. Visualizations for the background preview will return an empty id. /// </summary> /// <param name="e"></param> private void RenderDrawables(VisualizationEventArgs e) { //check the id, if the id is meant for another watch, //then ignore it if (e.Id != _id) { return; } var sw = new Stopwatch(); sw.Start(); Points = null; Lines = null; Mesh = null; XAxes = null; YAxes = null; ZAxes = null; PointsSelected = null; LinesSelected = null; MeshSelected = null; Text = null; MeshCount = 0; //separate the selected packages var packages = e.Packages.Where(x => x.Selected == false).ToArray(); var selPackages = e.Packages.Where(x => x.Selected).ToArray(); //pre-size the points collections var pointsCount = packages.Select(x => x.PointVertices.Count / 3).Sum(); var selPointsCount = selPackages.Select(x => x.PointVertices.Count / 3).Sum(); var points = new Point3DCollection(pointsCount); var pointsSelected = new Point3DCollection(selPointsCount); //pre-size the lines collections //these sizes are conservative as the axis lines will be //taken from the linestripvertex collections as well. var lineCount = packages.Select(x => x.LineStripVertices.Count / 3).Sum(); var lineSelCount = selPackages.Select(x => x.LineStripVertices.Count / 3).Sum(); var lines = new Point3DCollection(lineCount); var linesSelected = new Point3DCollection(lineSelCount); var redLines = new Point3DCollection(lineCount); var greenLines = new Point3DCollection(lineCount); var blueLines = new Point3DCollection(lineCount); //pre-size the text collection var textCount = e.Packages.Count(x => x.DisplayLabels); var text = new List <BillboardTextItem>(textCount); //http://blogs.msdn.com/b/timothyc/archive/2006/08/31/734308.aspx //presize the mesh collections var meshVertCount = packages.Select(x => x.TriangleVertices.Count / 3).Sum(); var meshVertSelCount = selPackages.Select(x => x.TriangleVertices.Count / 3).Sum(); var mesh = new MeshGeometry3D(); var meshSel = new MeshGeometry3D(); var verts = new Point3DCollection(meshVertCount); var vertsSel = new Point3DCollection(meshVertSelCount); var norms = new Vector3DCollection(meshVertCount); var normsSel = new Vector3DCollection(meshVertSelCount); var tris = new Int32Collection(meshVertCount); var trisSel = new Int32Collection(meshVertSelCount); foreach (var package in packages) { ConvertPoints(package, points, text); ConvertLines(package, lines, redLines, greenLines, blueLines, text); ConvertMeshes(package, verts, norms, tris); } foreach (var package in selPackages) { ConvertPoints(package, pointsSelected, text); ConvertLines(package, linesSelected, redLines, greenLines, blueLines, text); ConvertMeshes(package, vertsSel, normsSel, trisSel); } points.Freeze(); pointsSelected.Freeze(); Points = points; PointsSelected = pointsSelected; lines.Freeze(); linesSelected.Freeze(); redLines.Freeze(); greenLines.Freeze(); blueLines.Freeze(); Lines = lines; LinesSelected = linesSelected; XAxes = redLines; YAxes = greenLines; ZAxes = blueLines; verts.Freeze(); norms.Freeze(); tris.Freeze(); vertsSel.Freeze(); normsSel.Freeze(); trisSel.Freeze(); mesh.Positions = verts; mesh.Normals = norms; mesh.TriangleIndices = tris; meshSel.Positions = vertsSel; meshSel.Normals = normsSel; meshSel.TriangleIndices = trisSel; Mesh = mesh; MeshSelected = meshSel; Text = text; sw.Stop(); GC.Collect(); Debug.WriteLine(string.Format("{0} ellapsed for updating background preview.", sw.Elapsed)); }
public Transition3D() : base(new Viewport3D()) { // camera to ue WrappedElement.Camera = new PerspectiveCamera(); // the model visual 3D ModelVisual3D mv3D = new ModelVisual3D(); mv3D.Content = new PointLight(Colors.White, new Point3D(0, 0, 0)); WrappedElement.Children.Add(mv3D); MeshGeometry3D plane = new MeshGeometry3D(); Point3DCollection positions = new Point3DCollection(); positions.Add(new Point3D(-1, -1, 0)); positions.Add(new Point3D(-1, 1, 0)); positions.Add(new Point3D(1, 1, 0)); positions.Add(new Point3D(1, -1, 0)); positions.Freeze(); plane.Positions = positions; PointCollection textureCoords = new PointCollection(); textureCoords.Add(new Point(0, 1)); textureCoords.Add(new Point(0, 0)); textureCoords.Add(new Point(1, 0)); textureCoords.Add(new Point(1, 1)); textureCoords.Freeze(); plane.TextureCoordinates = textureCoords; Int32Collection indices = new Int32Collection(); indices.Add(0); indices.Add(3); indices.Add(1); indices.Add(1); indices.Add(3); indices.Add(2); indices.Freeze(); plane.TriangleIndices = indices; Material planeMaterial = new DiffuseMaterial(Brushes.Blue); planeMaterial.SetValue(Viewport2DVisual3D.IsVisualHostMaterialProperty, true); m_visual3D = new Viewport2DVisual3D(); m_visual3D.Geometry = plane; m_visual3D.Material = planeMaterial; Transform3DGroup transform = new Transform3DGroup(); m_rotation = new AxisAngleRotation3D(new Vector3D(0, 1, 0), 35); m_scale = new ScaleTransform3D(0, 0, 0); m_translation = new TranslateTransform3D(-2.5, 0, -10); transform.Children.Add(m_scale); transform.Children.Add(new RotateTransform3D(m_rotation)); transform.Children.Add(m_translation); m_visual3D.Transform = transform; WrappedElement.Children.Add(m_visual3D); }
/// <summary> /// Creates the positions for the specified line segments. /// </summary> /// <param name="points"> /// The points of the line segments. /// </param> /// <param name="thickness"> /// The thickness of the line. /// </param> /// <param name="depthOffset"> /// The depth offset. A positive number (e.g. 0.0001) moves the point towards the camera. /// </param> /// <param name="clipping"> /// The clipping. /// </param> /// <returns> /// The positions collection. /// </returns> public Point3DCollection CreatePositions( IList <Point3D> points, double thickness = 1.0, double depthOffset = 0.0, CohenSutherlandClipping clipping = null) { var halfThickness = thickness * 0.5; var segmentCount = points.Count / 2; var positions = new Point3DCollection(segmentCount * 4); for (int i = 0; i < segmentCount; i++) { int startIndex = i * 2; var startPoint = points[startIndex]; var endPoint = points[startIndex + 1]; // Transform the start and end points to screen space var s0 = (Point4D)startPoint * this.visualToScreen; var s1 = (Point4D)endPoint * this.visualToScreen; if (clipping != null) { // Apply a clipping rectangle var x0 = s0.X / s0.W; var y0 = s0.Y / s0.W; var x1 = s1.X / s1.W; var y1 = s1.Y / s1.W; if (!clipping.ClipLine(ref x0, ref y0, ref x1, ref y1)) { continue; } s0.X = x0 * s0.W; s0.Y = y0 * s0.W; s1.X = x1 * s1.W; s1.Y = y1 * s1.W; } var lx = (s1.X / s1.W) - (s0.X / s0.W); var ly = (s1.Y / s1.W) - (s0.Y / s0.W); var l2 = (lx * lx) + (ly * ly); var p00 = s0; var p01 = s0; var p10 = s1; var p11 = s1; if (l2.Equals(0)) { // coinciding points (in world space or screen space) var dz = halfThickness; // TODO: make a square with the thickness as side length p00.X -= dz * p00.W; p00.Y -= dz * p00.W; p01.X -= dz * p01.W; p01.Y += dz * p01.W; p10.X += dz * p10.W; p10.Y -= dz * p10.W; p11.X += dz * p11.W; p11.Y += dz * p11.W; } else { var m = halfThickness / Math.Sqrt(l2); // the normal (dx,dy) var dx = -ly * m; var dy = lx * m; // segment start points p00.X += dx * p00.W; p00.Y += dy * p00.W; p01.X -= dx * p01.W; p01.Y -= dy * p01.W; // segment end points p10.X += dx * p10.W; p10.Y += dy * p10.W; p11.X -= dx * p11.W; p11.Y -= dy * p11.W; } if (!depthOffset.Equals(0)) { // Adjust the z-coordinate by the depth offset p00.Z -= depthOffset; p01.Z -= depthOffset; p10.Z -= depthOffset; p11.Z -= depthOffset; // Transform from screen space to world space p00 *= this.screenToVisual; p01 *= this.screenToVisual; p10 *= this.screenToVisual; p11 *= this.screenToVisual; positions.Add(new Point3D(p00.X / p00.W, p00.Y / p00.W, p00.Z / p00.W)); positions.Add(new Point3D(p01.X / p00.W, p01.Y / p01.W, p01.Z / p01.W)); positions.Add(new Point3D(p10.X / p00.W, p10.Y / p10.W, p10.Z / p10.W)); positions.Add(new Point3D(p11.X / p00.W, p11.Y / p11.W, p11.Z / p11.W)); } else { // Transform from screen space to world space p00 *= this.screenToVisual; p01 *= this.screenToVisual; p10 *= this.screenToVisual; p11 *= this.screenToVisual; positions.Add(new Point3D(p00.X, p00.Y, p00.Z)); positions.Add(new Point3D(p01.X, p01.Y, p01.Z)); positions.Add(new Point3D(p10.X, p10.Y, p10.Z)); positions.Add(new Point3D(p11.X, p11.Y, p11.Z)); } } positions.Freeze(); return(positions); }
/// <summary> /// Creates the positions for the specified line segments. /// </summary> /// <param name="points"> /// The points of the line segments. /// </param> /// <param name="thickness"> /// The thickness of the line. /// </param> /// <param name="depthOffset"> /// The depth offset. A positive number (e.g. 0.0001) moves the point towards the camera. /// </param> /// <param name="clipping"> /// The clipping. /// </param> /// <returns> /// The positions collection. /// </returns> public Point3DCollection CreatePositions( IList <Point3D> points, double thickness = 1.0, double depthOffset = 0.0, CohenSutherlandClipping clipping = null) { double halfThickness = thickness * 0.5; int segmentCount = points.Count / 2; var positions = new Point3DCollection(segmentCount * 4); for (int i = 0; i < segmentCount; i++) { int startIndex = i * 2; Point3D startPoint = points[startIndex]; Point3D endPoint = points[startIndex + 1]; var s0 = (Point4D)startPoint * this.visualToScreen; var s1 = (Point4D)endPoint * this.visualToScreen; if (clipping != null) { double x0 = s0.X / s0.W; double y0 = s0.Y / s0.W; double x1 = s1.X / s1.W; double y1 = s1.Y / s1.W; if (!clipping.ClipLine(ref x0, ref y0, ref x1, ref y1)) { continue; } s0.X = x0 * s0.W; s0.Y = y0 * s0.W; s1.X = x1 * s1.W; s1.Y = y1 * s1.W; } double lx = s1.X / s1.W - s0.X / s0.W; double ly = s1.Y / s1.W - s0.Y / s0.W; double m = halfThickness / Math.Sqrt(lx * lx + ly * ly); double dx = -ly * m; double dy = lx * m; var p00 = s0; var p01 = s0; var p10 = s1; var p11 = s1; p00.X += dx * p00.W; p00.Y += dy * p00.W; p01.X -= dx * p01.W; p01.Y -= dy * p01.W; p10.X += dx * p10.W; p10.Y += dy * p10.W; p11.X -= dx * p11.W; p11.Y -= dy * p11.W; if (depthOffset != 0) { p00.Z -= depthOffset; p01.Z -= depthOffset; p10.Z -= depthOffset; p11.Z -= depthOffset; p00 *= this.screenToVisual; p01 *= this.screenToVisual; p10 *= this.screenToVisual; p11 *= this.screenToVisual; positions.Add(new Point3D(p00.X / p00.W, p00.Y / p00.W, p00.Z / p00.W)); positions.Add(new Point3D(p01.X / p00.W, p01.Y / p01.W, p01.Z / p01.W)); positions.Add(new Point3D(p10.X / p00.W, p10.Y / p10.W, p10.Z / p10.W)); positions.Add(new Point3D(p11.X / p00.W, p11.Y / p11.W, p11.Z / p11.W)); } else { p00 *= this.screenToVisual; p01 *= this.screenToVisual; p10 *= this.screenToVisual; p11 *= this.screenToVisual; positions.Add(new Point3D(p00.X, p00.Y, p00.Z)); positions.Add(new Point3D(p01.X, p01.Y, p01.Z)); positions.Add(new Point3D(p10.X, p10.Y, p10.Z)); positions.Add(new Point3D(p11.X, p11.Y, p11.Z)); } } positions.Freeze(); return(positions); }
/// <summary> /// Use the render packages returned from the visualization manager to update the visuals. /// The visualization event arguments will contain a set of render packages and an id representing /// the associated node. Visualizations for the background preview will return an empty id. /// </summary> /// <param name="e"></param> public void RenderDrawables(VisualizationEventArgs e) { //check the id, if the id is meant for another watch, //then ignore it if (e.Id != _id) { return; } Debug.WriteLine(string.Format("Rendering visuals for {0}", e.Id)); var sw = new Stopwatch(); sw.Start(); Points = null; Lines = null; Mesh = null; XAxes = null; YAxes = null; ZAxes = null; PointsSelected = null; LinesSelected = null; MeshSelected = null; Text = null; MeshCount = 0; //separate the selected packages var packages = e.Packages.Where(x => x.Selected == false) .Where(rp => rp.TriangleVertices.Count % 9 == 0) .ToArray(); var selPackages = e.Packages .Where(x => x.Selected) .Where(rp => rp.TriangleVertices.Count % 9 == 0) .ToArray(); //pre-size the points collections var pointsCount = packages.Select(x => x.PointVertices.Count / 3).Sum(); var selPointsCount = selPackages.Select(x => x.PointVertices.Count / 3).Sum(); var points = new Point3DCollection(pointsCount); var pointsSelected = new Point3DCollection(selPointsCount); //pre-size the lines collections //these sizes are conservative as the axis lines will be //taken from the linestripvertex collections as well. var lineCount = packages.Select(x => x.LineStripVertices.Count / 3).Sum(); var lineSelCount = selPackages.Select(x => x.LineStripVertices.Count / 3).Sum(); var lines = new Point3DCollection(lineCount); var linesSelected = new Point3DCollection(lineSelCount); var redLines = new Point3DCollection(lineCount); var greenLines = new Point3DCollection(lineCount); var blueLines = new Point3DCollection(lineCount); //pre-size the text collection var textCount = e.Packages.Count(x => x.DisplayLabels); var text = new List <BillboardTextItem>(textCount); //http://blogs.msdn.com/b/timothyc/archive/2006/08/31/734308.aspx //presize the mesh collections var meshVertCount = packages.Select(x => x.TriangleVertices.Count / 3).Sum(); var meshVertSelCount = selPackages.Select(x => x.TriangleVertices.Count / 3).Sum(); var mesh = new MeshGeometry3D(); var meshSel = new MeshGeometry3D(); var verts = new Point3DCollection(meshVertCount); var vertsSel = new Point3DCollection(meshVertSelCount); var norms = new Vector3DCollection(meshVertCount); var normsSel = new Vector3DCollection(meshVertSelCount); var tris = new Int32Collection(meshVertCount); var trisSel = new Int32Collection(meshVertSelCount); foreach (var package in packages) { ConvertPoints(package, points, text); ConvertLines(package, lines, redLines, greenLines, blueLines, text); ConvertMeshes(package, verts, norms, tris); } foreach (var package in selPackages) { ConvertPoints(package, pointsSelected, text); ConvertLines(package, linesSelected, redLines, greenLines, blueLines, text); ConvertMeshes(package, vertsSel, normsSel, trisSel); } sw.Stop(); Debug.WriteLine(string.Format("RENDER: {0} ellapsed for updating background preview.", sw.Elapsed)); var vm = (IWatchViewModel)DataContext; if (vm.CheckForLatestRenderCommand.CanExecute(e.TaskId)) { vm.CheckForLatestRenderCommand.Execute(e.TaskId); } points.Freeze(); pointsSelected.Freeze(); lines.Freeze(); linesSelected.Freeze(); redLines.Freeze(); greenLines.Freeze(); blueLines.Freeze(); verts.Freeze(); norms.Freeze(); tris.Freeze(); vertsSel.Freeze(); normsSel.Freeze(); trisSel.Freeze(); Dispatcher.Invoke(new Action <Point3DCollection, Point3DCollection, Point3DCollection, Point3DCollection, Point3DCollection, Point3DCollection, Point3DCollection, Point3DCollection, Vector3DCollection, Int32Collection, Point3DCollection, Vector3DCollection, Int32Collection, MeshGeometry3D, MeshGeometry3D, List <BillboardTextItem> >(SendGraphicsToView), DispatcherPriority.Render, new object[] { points, pointsSelected, lines, linesSelected, redLines, greenLines, blueLines, verts, norms, tris, vertsSel, normsSel, trisSel, mesh, meshSel, text }); }
private static Model3D GenerateTreeMap3DModel(int index, int count) { MeshGeometry3D meshGeometry3D = new MeshGeometry3D(); Point3DCollection positions = new Point3DCollection(); positions.Add(new Point3D(0, 0, 1)); positions.Add(new Point3D(0, 0, 0)); positions.Add(new Point3D(1, 0, 0)); positions.Add(new Point3D(1, 0, 1)); positions.Add(new Point3D(0, 1, 1)); positions.Add(new Point3D(0, 1, 0)); positions.Add(new Point3D(1, 1, 0)); positions.Add(new Point3D(1, 1, 1)); positions.Freeze(); Int32Collection triangleIndices = new Int32Collection(); triangleIndices.Add(0); triangleIndices.Add(1); triangleIndices.Add(2); triangleIndices.Add(2); triangleIndices.Add(3); triangleIndices.Add(0); triangleIndices.Add(4); triangleIndices.Add(7); triangleIndices.Add(6); triangleIndices.Add(6); triangleIndices.Add(5); triangleIndices.Add(4); triangleIndices.Add(0); triangleIndices.Add(3); triangleIndices.Add(7); triangleIndices.Add(7); triangleIndices.Add(4); triangleIndices.Add(0); triangleIndices.Add(1); triangleIndices.Add(5); triangleIndices.Add(6); triangleIndices.Add(6); triangleIndices.Add(2); triangleIndices.Add(1); triangleIndices.Add(3); triangleIndices.Add(2); triangleIndices.Add(6); triangleIndices.Add(6); triangleIndices.Add(7); triangleIndices.Add(3); triangleIndices.Add(0); triangleIndices.Add(4); triangleIndices.Add(5); triangleIndices.Add(5); triangleIndices.Add(7); triangleIndices.Add(0); triangleIndices.Freeze(); // finally set the data meshGeometry3D.TriangleIndices = triangleIndices; meshGeometry3D.Positions = positions; // create the geometry model GeometryModel3D geom3D = new GeometryModel3D(); geom3D.Geometry = meshGeometry3D; Color color = ColorHelper.HsbToRgb(index / (float)count, .9f, 1f); SolidColorBrush solidColorBrush = color.ToBrush(); solidColorBrush.Freeze(); geom3D.Material = new DiffuseMaterial(solidColorBrush); return(geom3D); }
/// <summary> /// Creates the positions for the specified line segments. /// </summary> /// <param name="points"> /// The points of the line segments. /// </param> /// <param name="thickness"> /// The thickness of the line. /// </param> /// <param name="depthOffset"> /// The depth offset. A positive number (e.g. 0.0001) moves the point towards the camera. /// </param> /// <param name="clipping"> /// The clipping. /// </param> /// <returns> /// The positions collection. /// </returns> public Point3DCollection CreatePositions( IList <Point3D> points, double thickness, double depthOffset, double fixedLength, CohenSutherlandClipping clipping) { double halfThickness = thickness * 0.5; int segmentCount = points.Count / 2; var positions = new Point3DCollection(segmentCount * 4); for (int i = 0; i < segmentCount; i++) { int startIndex = i * 2; Point3D startPoint = points[startIndex]; Point3D endPoint = points[startIndex + 1]; var screenStartPoint = (Point4D)startPoint * this.visualToScreen; var screenEndPoint = (Point4D)endPoint * this.visualToScreen; if (fixedLength > 0) { Point3D screenStartPoint3D = startPoint * this.visualToScreen; Point3D screenEndPoint3D = endPoint * this.visualToScreen; double deltaScreenPointX = screenEndPoint3D.X - screenStartPoint3D.X; double deltaScreenPointY = screenEndPoint3D.Y - screenStartPoint3D.Y; double magnitudeScreenPoint = Math.Sqrt(deltaScreenPointX * deltaScreenPointX + deltaScreenPointY * deltaScreenPointY); deltaScreenPointX *= fixedLength * screenEndPoint.W / magnitudeScreenPoint; deltaScreenPointY *= fixedLength * screenEndPoint.W / magnitudeScreenPoint; screenEndPoint = screenStartPoint; screenEndPoint.X += deltaScreenPointX; screenEndPoint.Y += deltaScreenPointY; } if (clipping != null) { double x0 = screenStartPoint.X / screenStartPoint.W; double y0 = screenStartPoint.Y / screenStartPoint.W; double x1 = screenEndPoint.X / screenEndPoint.W; double y1 = screenEndPoint.Y / screenEndPoint.W; if (!clipping.ClipLine(ref x0, ref y0, ref x1, ref y1)) { continue; } screenStartPoint.X = x0 * screenStartPoint.W; screenStartPoint.Y = y0 * screenStartPoint.W; screenEndPoint.X = x1 * screenEndPoint.W; screenEndPoint.Y = y1 * screenEndPoint.W; } double lx = screenEndPoint.X / screenEndPoint.W - screenStartPoint.X / screenStartPoint.W; double ly = screenEndPoint.Y / screenEndPoint.W - screenStartPoint.Y / screenStartPoint.W; double m = halfThickness / Math.Sqrt(lx * lx + ly * ly); double deltaX = -ly * m; double deltaY = lx * m; positions.Add(Widen(screenStartPoint, deltaX, deltaY, depthOffset)); positions.Add(Widen(screenStartPoint, -deltaX, -deltaY, depthOffset)); positions.Add(Widen(screenEndPoint, deltaX, deltaY, depthOffset)); positions.Add(Widen(screenEndPoint, -deltaX, -deltaY, depthOffset)); } positions.Freeze(); return(positions); }
private void CreateSurface() { if (this.Points != null && this.TextureBuilder != null) { Material texture = this.TextureBuilder.CreateTexture(); int xWidth = this.Points.GetLength(0); int yWidth = this.Points.GetLength(1); int capacity = (xWidth - 1) * (yWidth - 1); Point3DCollection positions = new Point3DCollection(capacity); Int32Collection indices = new Int32Collection(capacity); PointCollection texCoords = new PointCollection(capacity); Vector3DCollection normals = new Vector3DCollection(capacity); int indiceCount = 0; for (int ix = 0; ix < xWidth - 1; ix++) { if (!double.IsNaN(this.Points[ix, 0].Z)) { if (!double.IsNaN(this.Points[ix + 1, 0].Z)) { for (int iy = 0; iy < yWidth - 1; iy++) { // V0-----V3 // | | // | | // V1-----V2 //Add Triangle V0--V1--V2 positions.Add(this.Points[ix, iy]); positions.Add(this.Points[ix + 1, iy]); positions.Add(this.Points[ix + 1, iy + 1]); double middleZ = (this.Points[ix, iy].Z + this.Points[ix + 1, iy].Z + this.Points[ix + 1, iy + 1].Z + this.Points[ix, iy + 1].Z) / 4.0; Point texturePt = this.TextureBuilder.GetTextureMapping(middleZ); texCoords.Add(texturePt); texCoords.Add(texturePt); texCoords.Add(texturePt); indices.Add(indiceCount++); indices.Add(indiceCount++); indices.Add(indiceCount++); Vector3D normal = MathHelper.CalculateNormal(this.Points[ix + 1, iy + 1], this.Points[ix + 1, iy], this.Points[ix, iy]); normals.Add(normal); normals.Add(normal); normals.Add(normal); //Add Triangle V2--V3-V0 positions.Add(this.Points[ix + 1, iy + 1]); positions.Add(this.Points[ix, iy + 1]); positions.Add(this.Points[ix, iy]); texCoords.Add(texturePt); texCoords.Add(texturePt); texCoords.Add(texturePt); indices.Add(indiceCount++); indices.Add(indiceCount++); indices.Add(indiceCount++); Vector3D normal2 = MathHelper.CalculateNormal(this.Points[ix, iy], this.Points[ix, iy + 1], this.Points[ix + 1, iy + 1]); normals.Add(normal2); normals.Add(normal2); normals.Add(normal2); } } } } positions.Freeze(); _mesh.Positions = positions; indices.Freeze(); _mesh.TriangleIndices = indices; texCoords.Freeze(); _mesh.TextureCoordinates = texCoords; normals.Freeze(); _mesh.Normals = normals; _model3D.Material = texture; _model3D.BackMaterial = texture; } }