using System; using System.Collections.Generic; using System.Linq; using Autodesk.Revit.DB; using Autodesk.Revit.DB.DirectContext3D; using Autodesk.Revit.DB.ExternalService; namespace RevitJigSample.ExternalGraphics { public class DrawingServer : IDirectContext3DServer { private readonly Guid guid; private RenderingPassBufferStorage edgeBufferStorage; public DrawingServer(Document doc) { this.guid = Guid.NewGuid(); this.Document = doc; } public Document Document { get; set; } public Guid GetServerId() { return this.guid; } public string GetVendorId() { return "STSO"; } public ExternalServiceId GetServiceId() { return ExternalServices.BuiltInExternalServices.DirectContext3DService; } public virtual string GetName() { return ""; } public virtual string GetDescription() { return ""; } public string GetApplicationId() { return ""; } public string GetSourceId() { return ""; } public bool UsesHandles() { return false; } public virtual bool CanExecute(View view) { Document doc = view.Document; return doc.Equals(this.Document); } public virtual Outline GetBoundingBox(View view) { return null; } public bool UseInTransparentPass(View view) { return true; } // Submits the geometry for rendering. public virtual void RenderScene(View view, DisplayStyle displayStyle) { try { // Populate geometry buffers if they are not initialized or need updating. this.CreateBufferStorageForElement(displayStyle, view); // Conditionally submit line segment primitives. if ( displayStyle != DisplayStyle.Shading && this.edgeBufferStorage.PrimitiveCount > 0 ) { DrawContext.FlushBuffer( this.edgeBufferStorage.VertexBuffer, this.edgeBufferStorage.VertexBufferCount, this.edgeBufferStorage.IndexBuffer, this.edgeBufferStorage.IndexBufferCount, this.edgeBufferStorage.VertexFormat, this.edgeBufferStorage.EffectInstance, PrimitiveType.LineList, 0, this.edgeBufferStorage.PrimitiveCount ); } } catch (Exception e) { // } } public virtual List PrepareProfile() { return new List(); } public virtual void CreateBufferStorageForElement(DisplayStyle displayStyle, View view) { this.edgeBufferStorage = new RenderingPassBufferStorage(displayStyle); List lines = this.PrepareProfile(); foreach (Line edge in lines) { IList xyzs = edge.Tessellate(); this.edgeBufferStorage.VertexBufferCount += xyzs.Count; this.edgeBufferStorage.PrimitiveCount += xyzs.Count - 1; this.edgeBufferStorage.EdgeXYZs.Add(xyzs); } this.ProcessEdges(this.edgeBufferStorage); } private void ProcessEdges(RenderingPassBufferStorage bufferStorage) { List> edges = bufferStorage.EdgeXYZs; if (edges.Count == 0) { return; } // Edges are encoded as line segment primitives whose vertices contain only position information. bufferStorage.FormatBits = VertexFormatBits.Position; int edgeVertexBufferSizeInFloats = VertexPosition.GetSizeInFloats() * bufferStorage.VertexBufferCount; List numVerticesInEdgesBefore = new List { 0 }; bufferStorage.VertexBuffer = new VertexBuffer(edgeVertexBufferSizeInFloats); bufferStorage.VertexBuffer.Map(edgeVertexBufferSizeInFloats); { VertexStreamPosition vertexStream = bufferStorage.VertexBuffer.GetVertexStreamPosition(); foreach (IList xyzs in edges) { foreach (XYZ vertex in xyzs) { vertexStream.AddVertex(new VertexPosition(vertex)); } numVerticesInEdgesBefore.Add(numVerticesInEdgesBefore.Last() + xyzs.Count); } } bufferStorage.VertexBuffer.Unmap(); int edgeNumber = 0; bufferStorage.IndexBufferCount = bufferStorage.PrimitiveCount * IndexLine.GetSizeInShortInts(); int indexBufferSizeInShortInts = 1 * bufferStorage.IndexBufferCount; bufferStorage.IndexBuffer = new IndexBuffer(indexBufferSizeInShortInts); bufferStorage.IndexBuffer.Map(indexBufferSizeInShortInts); { IndexStreamLine indexStream = bufferStorage.IndexBuffer.GetIndexStreamLine(); foreach (IList xyzs in edges) { int startIndex = numVerticesInEdgesBefore[edgeNumber]; for (int i = 1; i < xyzs.Count; i++) { // Add two indices that define a line segment. indexStream.AddLine(new IndexLine(startIndex + i - 1, startIndex + i)); } edgeNumber++; } } bufferStorage.IndexBuffer.Unmap(); bufferStorage.VertexFormat = new VertexFormat(bufferStorage.FormatBits); bufferStorage.EffectInstance = new EffectInstance(bufferStorage.FormatBits); } } }