// Creates a ScreenSpaceLineNode with multiple positions and with different colors for positions. public static ScreenSpaceLineNode CreateColoredLineNode(Vector3[] positions, Color4[] lineColors, float lineThickness, DisposeList disposables, bool isPolyLine = true) // when false we create a multi-line line (each individual line is defined by 2 position) { var lineMaterial = new PositionColoredLineMaterial() { LineColor = Color4.White, // When PositionColors are used, then LineColor is used as a mask - each color is multiplied by LineColor - use White to preserve PositionColors LineThickness = lineThickness, PositionColors = lineColors, IsPolyLine = isPolyLine }; // NOTE: When rendering multi-lines we need to set isLineStrip to false var screenSpaceLineNode = new ScreenSpaceLineNode(positions, isLineClosed: false, isLineStrip: isPolyLine, lineMaterial: lineMaterial); if (disposables != null) { disposables.Add(screenSpaceLineNode); disposables.Add(lineMaterial); } return(screenSpaceLineNode); }
private void CreateTest3DObjects() { TestObjectsModelVisual3D.Children.Clear(); // Reset ReadZBuffer to its default value _dxLineMaterial.ReadZBuffer = true; var objectMaterial = new DiffuseMaterial(Brushes.Silver); // Uncomment the following line to test drawing hidden lines behind transparent objects: //objectMaterial = new DiffuseMaterial(new SolidColorBrush(Color.FromArgb(230, 100, 100, 100))); CreateCylinderWithCircles(new Point3D(0, 0, -5), 10, 30, objectMaterial); CreateBoxWithEdgeLines(new Point3D(0, 10, 40), new Size3D(20, 20, 20), objectMaterial); CreateTeapotWireframeModel(new Point3D(0, 10, -50), new Size3D(50, 50, 50), objectMaterial); // The following code shows how to create a DXEngine's ScreenSpaceLineNode directly (see DXEngineAdvanced/ScreenSpaceLineNodeSample for more info): var positions = new Vector3[2]; positions[0] = new Vector3(-70, -3, 60); positions[1] = new Vector3(70, -3, 60); _screenSpaceLineNode = new ScreenSpaceLineNode(positions, isLineStrip: false, isLineClosed: false, lineMaterial: _dxLineMaterial); // To add ScreenSpaceLineNode into WPF's objects hierarchy we use SceneNodeVisual3D var sceneNodeVisual3D = new SceneNodeVisual3D(_screenSpaceLineNode); TestObjectsModelVisual3D.Children.Add(sceneNodeVisual3D); }
private void ChangePositions(ScreenSpaceLineNode screenSpaceLineNode) { ChangePositions(screenSpaceLineNode.Positions); screenSpaceLineNode.UpdatePositions(); screenSpaceLineNode.UpdateBounds(); }
public ScreenSpaceLineNodeSample() { InitializeComponent(); _disposables = new DisposeList(); var linePositions = CreateLinePositions(xOffset: 0, zOffset: -50); _screenSpaceLineNode1 = CreateLinesWithPositions(linePositions, isLineStrip: false, isPolyLine: false, isLineClosed: false, lineColor: Colors.Blue, xOffset: -90); AddTextBlockVisual3D(xOffset: -90, isLineStrip: false, isPolyLine: false); _screenSpaceLineNode2 = CreateLinesWithPositions(linePositions, isLineStrip: true, isPolyLine: false, isLineClosed: false, lineColor: Colors.Green, xOffset: -30); AddTextBlockVisual3D(xOffset: -30, isLineStrip: true, isPolyLine: false); _screenSpaceLineNode3 = CreateLinesWithPositions(linePositions, isLineStrip: true, isPolyLine: true, isLineClosed: false, lineColor: Colors.Red, xOffset: 30); AddTextBlockVisual3D(xOffset: 30, isLineStrip: true, isPolyLine: true); _screenSpaceLineNode4 = CreateLinesWithLineMesh(linePositions, isLineStrip: false, isLineClosed: false, isPolyLine: false, lineColor: Colors.Orange, xOffset: 90, screenSpaceLineMesh: out _screenSpaceLineMesh); AddTextBlockVisual3D(xOffset: 90, "using\r\nScreenSpaceLineMesh"); Unloaded += delegate { Dispose(); }; }
public WLineRenderData(ScreenSpaceLineNode _node, LineSelectorData _selectData, PositionColoredLineMaterial mtl, List <SharpDX.Color4> _colors) { node = _node; selectData = _selectData; material = mtl; colors = _colors; }
void CreateColoredPolyLine(int count, int layer) { Vector3 preV = new Vector3(0, layer, 0); Color4 preC = Color4.White; var points = new List <Point3D>(); var vectors = new List <Vector3>(); var colors = new List <SharpDX.Color4>(); for (int i = 0; i < count; i++) { float max = 1f; Vector3 v = new Vector3(1, layer, 0); v.X += preV.X; //Console.WriteLine("{0} : {1} {2} {3}", i, v.X, v.Y, v.Z); colors.Add(preC); points.Add(new Point3D((double)v.X, (double)v.Y, (double)v.Z)); vectors.Add(v); preV = v; } DisposeList disposables = new DisposeList(); float lineThickness = 5; bool isPolyLine = false; var lineMaterial = new PositionColoredLineMaterial() { LineColor = Color4.White, // When PositionColors are used, then LineColor is used as a mask - each color is multiplied by LineColor - use White to preserve PositionColors LineThickness = lineThickness, PositionColors = colors.ToArray(), IsPolyLine = isPolyLine }; // NOTE: When rendering multi-lines we need to set isLineStrip to false var screenSpaceLineNode = new ScreenSpaceLineNode(vectors.ToArray(), isLineClosed: false, isLineStrip: true, lineMaterial: lineMaterial); if (disposables != null) { disposables.Add(screenSpaceLineNode); disposables.Add(lineMaterial); } var sceneNodeVisual = new SceneNodeVisual3D(screenSpaceLineNode); MainViewport.Children.Add(sceneNodeVisual); bool isVisualConnected; var lineSelectorData = new LineSelectorData(points, true); lineSelectorData.PositionsTransform3D = Ab3d.Utilities.TransformationsHelper.GetVisual3DTotalTransform(sceneNodeVisual, true, out isVisualConnected); _lineSelectorData.Add(lineSelectorData); var _data = new WLineRenderData(screenSpaceLineNode, lineSelectorData, lineMaterial, colors); lrData.Add(_data); }
private ScreenSpaceLineNode CreateLinesWithLineMesh(Vector3[] linePositions, bool isLineStrip, bool isLineClosed, Color lineColor, float xOffset, out ScreenSpaceLineMesh screenSpaceLineMesh) { if (linePositions == null || linePositions.Length < 2) { screenSpaceLineMesh = null; return(null); } // If line is closed but the first position is not the same as the last position, then add the first position as the last one if (isLineClosed && linePositions[0] != linePositions[linePositions.Length - 1]) { Array.Resize(ref linePositions, linePositions.Length + 1); linePositions[linePositions.Length - 1] = linePositions[0]; } // If we can easily calculate the bounding box from line positions // it is recommended to specify it in the ScreenSpaceLineMesh constructor. // If boundingBox is not specified, it will be calculated in the ScreenSpaceLineMesh constructor with checking all the positions. // // NOTE: If bounding box is not correct then camera's near and far planes can be invalid and this can cut some 3D objects at near or far plane (when DXScene.OptimizeNearAndFarCameraPlanes is true - by default) //var boundingBox = new BoundingBox(new Vector3(startX, 0, startZ), new Vector3(startX + linesCount * margin, 0, endZ)); // Create ScreenSpaceLineMesh - it is used to create DirectX vertex buffer from positions screenSpaceLineMesh = new ScreenSpaceLineMesh(linePositions, isLineStrip); // When the line positions are changed many times, it is recommended to set CreateDynamicVertexBuffer to true. screenSpaceLineMesh.CreateDynamicVertexBuffer = true; var lineMaterial = new LineMaterial() { LineColor = lineColor.ToColor4(), LineThickness = 2 }; var screenSpaceLineNode = new ScreenSpaceLineNode(screenSpaceLineMesh, lineMaterial); screenSpaceLineNode.Transform = new Transformation(SharpDX.Matrix.Translation(xOffset, 0, 0)); // To show ScreenSpaceLineNode in DXViewportView we need to put it inside a SceneNodeVisual3D var sceneNodeVisual3D = new SceneNodeVisual3D(screenSpaceLineNode); MainViewport.Children.Add(sceneNodeVisual3D); _disposables.Add(screenSpaceLineMesh); _disposables.Add(screenSpaceLineNode); _disposables.Add(lineMaterial); return(screenSpaceLineNode); }
private void ChangePositions(ScreenSpaceLineNode screenSpaceLineNode, ScreenSpaceLineMesh screenSpaceLineMesh) { ChangePositions(screenSpaceLineMesh.Positions); // Recreate vertex buffer that is defined with ScreenSpaceLineMesh screenSpaceLineMesh.RecreateMesh(); // Update bounds of the mesh and SceneNode. BoundingBox boundingBox; BoundingBox.FromPoints(screenSpaceLineMesh.Positions, out boundingBox); // We could set boundingBox manually, but for demonstration purpose we calculate it from the positions screenSpaceLineMesh.Bounds.SetBoundingBox(ref boundingBox); screenSpaceLineNode.UpdatePositions(); screenSpaceLineNode.UpdateBounds(); }
private ScreenSpaceLineNode CreateLinesWithPositions(Vector3[] linePositions, bool isLineStrip, bool isPolyLine, bool isLineClosed, Color lineColor, float xOffset) { var lineMaterial = CreateLineMaterial(isPolyLine, lineColor); var screenSpaceLineNode = new ScreenSpaceLineNode(linePositions, isLineStrip, isLineClosed, lineMaterial); screenSpaceLineNode.Transform = new Transformation(SharpDX.Matrix.Translation(xOffset, 0, 0)); // To show ScreenSpaceLineNode in DXViewportView we need to put it inside a SceneNodeVisual3D var sceneNodeVisual3D = new SceneNodeVisual3D(screenSpaceLineNode); MainViewport.Children.Add(sceneNodeVisual3D); _disposables.Add(screenSpaceLineNode); _disposables.Add(lineMaterial); return(screenSpaceLineNode); }
private void AddLines(Point3D startPosition, int positionsCount, Color lineColor, bool readZBuffer = true, bool writeZBuffer = true, RenderingQueue customRenderingQueue = null) { Vector3[] positions = new Vector3[positionsCount * 2]; Vector3 position = startPosition.ToVector3(); int index = 0; for (int i = 0; i < positionsCount; i++) { positions[index] = position; positions[index + 1] = position + new Vector3(40, 0, 0); index += 2; position += new Vector3(0, 0, 10); } // ThickLineEffect that renders the 3D lines can use the ReadZBuffer and WriteZBuffer values from LineMaterial. // // When ReadZBuffer is false (true by default), then line is rendered without checking the depth buffer - // so it is always rendered even it is is behind some other 3D object and should not be visible from the camera). // // When WriteZBuffer is false (true by default), then when rendering the 3D line, the depth of the line is not // written to the depth buffer. So No other object will be made hidden by the line even if that object is behind the line. var lineMaterial = new LineMaterial() { LineColor = lineColor.ToColor4(), LineThickness = 2, ReadZBuffer = readZBuffer, WriteZBuffer = writeZBuffer }; _disposables.Add(lineMaterial); var screenSpaceLineNode = new ScreenSpaceLineNode(positions, isLineStrip: false, isLineClosed: false, lineMaterial: lineMaterial); // It is also needed that the 3D line is put to the Background or Overlay rendering queue so that it is rendered before or after other 3D objects. screenSpaceLineNode.CustomRenderingQueue = customRenderingQueue; var sceneNodeVisual3D = new SceneNodeVisual3D(screenSpaceLineNode); MainViewport.Children.Add(sceneNodeVisual3D); }
public ScreenSpaceLineNodeSample() { InitializeComponent(); _disposables = new DisposeList(); var linePositions = CreateLinePositions(0, 0); _screenSpaceLineNode1 = CreateLinesWithPositions(linePositions, isLineStrip: false, isLineClosed: false, lineColor: Colors.Blue, xOffset: -100); // To create poly-lines we need to set isLineStrip to true _screenSpaceLineNode2 = CreateLinesWithPositions(linePositions, isLineStrip: true, isLineClosed: false, lineColor: Colors.Green, xOffset: 0); _screenSpaceLineNode3 = CreateLinesWithLineMesh(linePositions, isLineStrip: false, isLineClosed: false, lineColor: Colors.Red, xOffset: 100, screenSpaceLineMesh: out _screenSpaceLineMesh); Unloaded += delegate { Dispose(); }; }
public static SceneNode CreateLineSceneNodes(Point3D center, Size3D size, bool useSingleColor, int xCount, int yCount, int zCount, DisposeList disposables) { var rootSceneNode = new SceneNode(); float xStep = (float)(size.X / xCount); float yStep = (float)(size.Y / yCount); float zStep = (float)(size.Z / zCount); float xHalfLineSize = xStep * 0.3f; //float yHalfLineSize = xStep * 0.3f; float zHalfLineSize = xStep * 0.3f; var singleColorLineMaterial = new LineMaterial() { LineColor = Colors.Orange.ToColor4(), LineThickness = 2 }; if (disposables != null) { disposables.Add(singleColorLineMaterial); } for (int z = 0; z < zCount; z++) { float zPos = (float)(center.Z - (size.Z / 2.0) + (z * zStep)); float zPercent = (float)z / (float)zCount; for (int y = 0; y < yCount; y++) { float yPos = (float)(center.Y - (size.Y / 2.0) + (y * yStep)); float yPercent = (float)y / (float)yCount; for (int x = 0; x < xCount; x++) { float xPos = (float)(center.X - (size.X / 2.0) + (x * xStep)); var linePositions = new Vector3[] { new Vector3(xPos - xHalfLineSize, yPos, zPos - zHalfLineSize), new Vector3(xPos + xHalfLineSize, yPos, zPos + zHalfLineSize), new Vector3(xPos - xHalfLineSize, yPos, zPos + zHalfLineSize), new Vector3(xPos + xHalfLineSize, yPos, zPos - zHalfLineSize), }; LineMaterial usedLineMaterial; if (useSingleColor) { // Using single color improved performance by 30% because we do not need to update per-object constant buffer for each line. usedLineMaterial = singleColorLineMaterial; } else { usedLineMaterial = new LineMaterial() { LineColor = new Color4((float)x / (float)xCount, yPercent, zPercent, 1), LineThickness = 2 }; if (disposables != null) { disposables.Add(usedLineMaterial); } } // NOTE: // The sample can also show many instances of ScreenSpaceLineNode to simulate showing many different 3D lines. // It would be much better to use a single ScreenSpaceLineNode and set all line positions to that object. var screenSpaceLineNode = new ScreenSpaceLineNode(linePositions, isLineStrip: false, isLineClosed: false, lineMaterial: usedLineMaterial); rootSceneNode.AddChild(screenSpaceLineNode); } } } return(rootSceneNode); }
private void ShowVisibleAndHiddenLines() { // To show both visible and hidden lines we need to render each line twice: // once with standard settings to shew visible part of the one, // once with using HiddenLineMaterial to show the hidden part of the line. // Now we will clone the existing 3D lines var existingLineVisuals = TestObjectsModelVisual3D.Children.OfType <BaseLineVisual3D>().ToList(); var newLineVisuals = new List <BaseLineVisual3D>(); foreach (var lineVisual3D in existingLineVisuals) { var clonedLineVisual = CloneLineVisuals(lineVisual3D); // To correctly show hidden lines, then need to be rendered after the objects in front of the lines // (they are rendered only in case when there are already some objects in front of them - line's depth is bigger then current depth value). // In case you want to show the hidden lines behind semi-transparent objects, you need to make sure that // the lines are put into the OverlayRenderingQueue. // This is needed because TransparentRenderingQueue is defined after LineGeometryRenderingQueue // and therefore all transparent objects are rendered after all 3D lines (this is needed so the lines are visible through transparent objects). // This can be done with using the SetDXAttribute method and setting the CustomRenderingQueue value. // Note that this value need to be set before the line is initialized by the DXEngine - so before the MainDXViewportView.Update call a few lines below. // (in case of using ScreenSpaceLineNode, you can set its CustomRenderingQueue). //clonedLineVisual.SetDXAttribute(DXAttributeType.CustomRenderingQueue, MainDXViewportView.DXScene.OverlayRenderingQueue); TestObjectsModelVisual3D.Children.Add(clonedLineVisual); newLineVisuals.Add(clonedLineVisual); } // After adding new WPF objects to the scene, we need to manually call Update to create DXEngine's SceneNode objects that will be needed later MainDXViewportView.Update(); // We need to update the _sceneNodesDictionary because we have changed the scene CreateSceneNodesDictionary(); // Now change the materials of the clones lines to hiddenLineMaterial foreach (var newLineVisual3D in newLineVisuals) { // Now we can change the material to _hiddenLineMaterial. // // We also need to put the hidden line to the OverlayRenderingQueue. // This is needed because to correctly show hidden lines, they need to be rendered after the objects in front of the lines // (they are rendered only in case when there are already some objects in front of them - line's depth is bigger then current depth value). // In case you want to show the hidden lines behind semi-transparent objects, you need to make sure that // the lines are put into the OverlayRenderingQueue. // This is needed because TransparentRenderingQueue is defined after LineGeometryRenderingQueue // and therefore all transparent objects are rendered after all 3D lines (this is needed so the lines are visible through transparent objects). // // Here this is done with setting the CustomRenderingQueue on the ScreenSpaceLineNode (see ChangeLineMaterial method). ChangeLineMaterial(newLineVisual3D, _hiddenLineMaterial, MainDXViewportView.DXScene.OverlayRenderingQueue); // We could also call SetDXAttribute and set the CustomRenderingQueue to OverlayRenderingQueue. // This can be done with uncommenting the following line // (but this is less efficient than setting the CustomRenderingQueue on the ScreenSpaceLineNode as done in the ChangeLineMaterial): //newLineVisual3D.SetDXAttribute(DXAttributeType.CustomRenderingQueue, MainDXViewportView.DXScene.OverlayRenderingQueue); } if (_wireframeGeometryModel3D != null) { // Clone the GeometryModel3D that shows teapot wireframe and use hiddenLineMaterial to render it var newWpfWireframeMaterial = new DiffuseMaterial(Brushes.Red); newWpfWireframeMaterial.SetUsedDXMaterial(_hiddenLineMaterial); var geometryModel3D = new GeometryModel3D(_wireframeGeometryModel3D.Geometry, newWpfWireframeMaterial); geometryModel3D.Transform = _wireframeGeometryModel3D.Transform; var modelVisual3D = new ModelVisual3D() { Content = geometryModel3D }; TestObjectsModelVisual3D.Children.Add(modelVisual3D); } // Create a new ScreenSpaceLineNode from the data for _screenSpaceLineNode // Set its material to _hiddenLineMaterial and move it to the OverlayRenderingQueue: var hiddenScreenSpaceLineNode = new ScreenSpaceLineNode(_screenSpaceLineNode.Positions, _screenSpaceLineNode.IsLineStrip, _screenSpaceLineNode.IsLineClosed, _hiddenLineMaterial); hiddenScreenSpaceLineNode.CustomRenderingQueue = MainDXViewportView.DXScene.OverlayRenderingQueue; var sceneNodeVisual3D = new SceneNodeVisual3D(hiddenScreenSpaceLineNode); TestObjectsModelVisual3D.Children.Add(sceneNodeVisual3D); }