/// <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}); }
/// <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; }
/// <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> /// <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 RebuildGeometry() { Point3DCollection points = new Point3DCollection(4); foreach (Point3D p3d in _Points) { Vector3D dir = (p3d - _CenterPoint) * _visualToScreen; dir.Z = 0; dir.Normalize(); Vector delta = new Vector(-dir.Y, dir.X); Point4D pIn4 = (Point4D)(new Point3D(p3d.X - _CenterPoint.X, p3d.Y - _CenterPoint.Y, p3d.Z - _CenterPoint.Z)); Point4D pOut4 = pIn4 * _visualToScreen; pOut4.X += delta.X * pOut4.W; pOut4.Y += delta.Y * pOut4.W; pOut4 *= _screenToVisual; Point3D pOut = new Point3D( pOut4.X / pOut4.W * (_TextWidth / (2d * WidthSizeFactor)) + _CenterPoint.X, pOut4.Y / pOut4.W * (_TextHeight / (2d * HeightSizeFactor)) + _CenterPoint.Y, pOut4.Z / pOut4.W + _CenterPoint.Z); points.Add(pOut); } points.Freeze(); _mesh.Positions = points; }
/// <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; }
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; }
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; }
/// <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; }
/// <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; }
/// <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; }
private void SetPoints() { if (!this.ShowLinesVisual3D) { this.LinePoints.Clear(); } if (!this.ShowPointsVisual3D) { this.Points.Clear(); } 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; } } }
/// <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) { try { //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(); Debug.WriteLine(string.Format("{0} ellapsed for updating background preview.", sw.Elapsed)); } catch (InvalidOperationException exp) { Debug.WriteLine("WARNING: Exception occured in rendering " + exp.ToString()); } }