private bool _isDisposed = false; // To detect redundant calls protected virtual void Dispose(bool disposing) { if (!_isDisposed) { if (disposing) { _altaxoDrawingGeometry?.Dispose(); _altaxoDrawingGeometry = null; _altaxoMarkerGeometry?.Dispose(); _altaxoMarkerGeometry = null; _altaxoOverlayGeometry?.Dispose(); _altaxoOverlayGeometry = null; _altaxoCamera = null; _altaxoLightSettings = null; } if (null != _cachedDevice) { Detach(); } _isDisposed = true; } }
private void BringDrawingIntoBuffers(D3D10GraphicsContext altaxoDrawingGeometry) { Device device = _cachedDevice; if (device == null || device.IsDisposed) { return; } var altaxoBuffersOfType = new IEnumerable <KeyValuePair <MaterialKey, IndexedTriangleBuffer> >[] { altaxoDrawingGeometry.PositionIndexedTriangleBuffersAsIndexedTriangleBuffers, altaxoDrawingGeometry.PositionColorIndexedTriangleBuffersAsIndexedTriangleBuffers, altaxoDrawingGeometry.PositionUVIndexedTriangleBuffersAsIndexedTriangleBuffers, altaxoDrawingGeometry.PositionNormalIndexedTriangleBuffersAsIndexedTriangleBuffers, altaxoDrawingGeometry.PositionNormalColorIndexedTriangleBuffersAsIndexedTriangleBuffers, altaxoDrawingGeometry.PositionNormalUVIndexedTriangleBuffersAsIndexedTriangleBuffers, altaxoDrawingGeometry.PositionNormalUIndexedTriangleBuffersAsIndexedTriangleBuffers }; for (int i = 0; i < altaxoBuffersOfType.Length; ++i) { var newDeviceBuffers = new List <VertexAndIndexDeviceBuffer>(); foreach (var altaxoBuffer in altaxoBuffersOfType[i]) { var altaxoTriangleBuffer = altaxoBuffer.Value; if (altaxoTriangleBuffer.TriangleCount == 0) { continue; } var vertexBuffer = Buffer.Create <float>(device, altaxoTriangleBuffer.VertexStream, new BufferDescription() { BindFlags = BindFlags.VertexBuffer, CpuAccessFlags = CpuAccessFlags.None, OptionFlags = ResourceOptionFlags.None, SizeInBytes = altaxoTriangleBuffer.VertexStreamLength, Usage = ResourceUsage.Default }); var indexBuffer = Buffer.Create <int>(device, altaxoTriangleBuffer.IndexStream, new BufferDescription() { BindFlags = BindFlags.IndexBuffer, CpuAccessFlags = CpuAccessFlags.None, OptionFlags = ResourceOptionFlags.None, SizeInBytes = altaxoTriangleBuffer.IndexStreamLength, Usage = ResourceUsage.Default }); var indexCount = altaxoTriangleBuffer.TriangleCount * 3; Plane[] clipPlanes = null; if (altaxoBuffer.Key is MaterialPlusClippingKey) { var axoClipPlanes = ((MaterialPlusClippingKey)altaxoBuffer.Key).ClipPlanes; if (null != axoClipPlanes) { clipPlanes = axoClipPlanes.Select(axoPlane => new Plane((float)axoPlane.X, (float)axoPlane.Y, (float)axoPlane.Z, (float)-axoPlane.W)).ToArray(); } } byte[] uColors = null; var material = altaxoBuffer.Key.Material; if (altaxoTriangleBuffer is PositionNormalUIndexedTriangleBuffer && altaxoBuffer.Key is MaterialPlusClippingPlusColorProviderKey) { var bufs = (PositionNormalUIndexedTriangleBuffer)altaxoTriangleBuffer; var colorProvider = ((MaterialPlusClippingPlusColorProviderKey)(altaxoBuffer.Key)).ColorProvider; var fColors = bufs.GetColorArrayForColorProvider(colorProvider); uColors = new byte[fColors.Length * 4]; System.Buffer.BlockCopy(fColors, 0, uColors, 0, uColors.Length); material = material.WithColor(new NamedColor(colorProvider.GetAxoColor(double.NaN))); // Material needs to have InvalidColor, because this can not be represented in the Texture1D } newDeviceBuffers.Add(new VertexAndIndexDeviceBuffer(material: altaxoBuffer.Key.Material, vertexBuffer: vertexBuffer, vertexCount: altaxoTriangleBuffer.VertexCount, indexBuffer: indexBuffer, indexCount: indexCount, clipPlanes: clipPlanes, uColors: uColors)); } System.Threading.Interlocked.Exchange(ref _nextTriangleDeviceBuffers[i], newDeviceBuffers); } }
public void SetDrawing(D3D10GraphicsContext drawing) { _altaxoDrawingGeometry = drawing; BringDrawingIntoBuffers(drawing); }
/// <summary> /// Saves the project item as image to the provided stream. /// </summary> /// <param name="item">The item to export, for instance an item of type <see cref="Altaxo.Graph.Gdi.GraphDocument"/> or <see cref="Altaxo.Graph.Graph3D.GraphDocument"/>.</param> /// <param name="options">The export options.</param> /// <param name="toStream">The stream to save the image to.</param> public (int PixelsX, int PixelsY) ExportAsImageToStream(Altaxo.Main.IProjectItem item, Altaxo.Graph.Gdi.GraphExportOptions options, System.IO.Stream toStream) { // SharpDX.Configuration.EnableObjectTracking = true; // var listOfActiveObjects = SharpDX.Diagnostics.ObjectTracker.FindActiveObjects(); if (item == null) { throw new ArgumentNullException(nameof(item)); } if (!(item is Altaxo.Graph.Graph3D.GraphDocument)) { throw new ArgumentException(string.Format("Expected item of type {0}, but it is of type {1}", typeof(Altaxo.Graph.Graph3D.GraphDocument), item.GetType())); } var doc = (Altaxo.Graph.Graph3D.GraphDocument)item; double sourceDpi = options.SourceDpiResolution; Viewing.D3D10Scene scene = null; D3D10GraphicsContext g = null; try { scene = new Viewing.D3D10Scene(); g = new D3D10GraphicsContext(); doc.Paint(g); var matrix = doc.Camera.LookAtRHMatrix; var rect = new RectangleD3D(PointD3D.Empty, doc.RootLayer.Size); var bounds = RectangleD3D.NewRectangleIncludingAllPoints(rect.Vertices.Select(x => matrix.Transform(x))); int pixelsX = (int)Math.Ceiling(sourceDpi * bounds.SizeX / 72.0); pixelsX = (int)(4 * Math.Ceiling((pixelsX + 3) / 4.0)); int pixelsY = (int)(sourceDpi * bounds.SizeY / 72.0); double aspectRatio = pixelsY / (double)pixelsX; var sceneCamera = doc.Camera; if (sceneCamera is OrthographicCamera) { var orthoCamera = (OrthographicCamera)sceneCamera; orthoCamera = (OrthographicCamera)orthoCamera.WithWidthAtZNear(bounds.SizeX); double offsX = -(1 + 2 * bounds.X / bounds.SizeX); double offsY = -(1 + 2 * bounds.Y / bounds.SizeY); sceneCamera = orthoCamera.WithScreenOffset(new PointD2D(offsX, offsY)); } else if (sceneCamera is PerspectiveCamera) { var viewProj = sceneCamera.GetViewProjectionMatrix(1); // here we transform the points with AspectRatio=1, in order to get the AspectRatio of the ScreenBounds var screenBounds = RectangleD3D.NewRectangleIncludingAllPoints(rect.Vertices.Select(x => viewProj.Transform(x))); aspectRatio = screenBounds.SizeY / screenBounds.SizeX; // this is the aspectRatio of our image viewProj = sceneCamera.GetViewProjectionMatrix(aspectRatio); // now we get the transform with our aspectRatio determined above screenBounds = RectangleD3D.NewRectangleIncludingAllPoints(rect.Vertices.Select(x => viewProj.Transform(x))); // this are our actual screenBounds, of course in relative screen coordinates, thus the ratio of sizeX and sizeY should now be 1 double scaleFactor = 2 / screenBounds.SizeX; // since SizeX and SizeY should now be the same, we could have used SizeY alternatively double offsX = -(1 + scaleFactor * screenBounds.X); double offsY = -(1 + scaleFactor * screenBounds.Y); pixelsY = (int)(4 * Math.Ceiling((aspectRatio * pixelsX + 3) / 4.0)); // now calculate the size of the image in y direction from the aspectRatio var perspCamera = (PerspectiveCamera)sceneCamera; sceneCamera = perspCamera.WithWidthAtZNear(perspCamera.WidthAtZNear / scaleFactor); sceneCamera = sceneCamera.WithScreenOffset(new PointD2D(offsX, offsY)); } else { throw new NotImplementedException(); } scene.SetCamera(sceneCamera); scene.SetLighting(doc.Lighting); scene.SetDrawing(g); Export(pixelsX, pixelsY, scene, options, toStream); return(pixelsX, pixelsY); } finally { Disposer.RemoveAndDispose(ref g); Disposer.RemoveAndDispose(ref scene); } }