/// <summary> /// Create input with empty geometry inputs. /// </summary> /// <param name="_outline">3D space for Revit to re-draw screen.</param> public GeometryDrawServerInputs(Outline _outline, bool _enableFaceNormal = false) { this.NonTransFaceBuffer = new RenderingPassBufferStorage(); this.TransFaceBuffer = new RenderingPassBufferStorage(); this.NonTransTriangleBuffer = new RenderingPassBufferStorage(); this.TransTriangleBuffer = new RenderingPassBufferStorage(); this.EdgeBuffer = new RenderingPassBufferStorage(); this.PointBuffer = new RenderingPassBufferStorage(); this.Outline = _outline; this.EnableFaceNormal = _enableFaceNormal; }
public RenderingPassBufferStorage Merge(RenderingPassBufferStorage _other) { var newBuffer = new RenderingPassBufferStorage(); newBuffer.Meshes = this.Meshes.Combine(_other.Meshes).ToList(); newBuffer.Edges = this.Edges.Combine(_other.Edges).ToList(); newBuffer.Points = this.Points.Combine(_other.Points).ToList(); newBuffer.Triangles = this.Triangles.Combine(_other.Triangles).ToList(); newBuffer.VertexBufferCount = this.VertexBufferCount + _other.VertexBufferCount; newBuffer.PrimitiveCount = this.PrimitiveCount + _other.PrimitiveCount; return(newBuffer); }
public static GeometryDrawServerInputs Merge(IEnumerable <GeometryDrawServerInputs> _inputs) { var outlines = _inputs.Select(x => x.Outline.ToBoundingBox()).GetBoundingBox().ToOutLine(); var input = new GeometryDrawServerInputs(outlines, _inputs.First().EnableFaceNormal); input.NonTransFaceBuffer = RenderingPassBufferStorage.Merge(_inputs.Select(x => x.NonTransFaceBuffer).ToList()); input.TransFaceBuffer = RenderingPassBufferStorage.Merge(_inputs.Select(x => x.TransFaceBuffer).ToList()); input.NonTransTriangleBuffer = RenderingPassBufferStorage.Merge(_inputs.Select(x => x.NonTransTriangleBuffer).ToList()); input.TransTriangleBuffer = RenderingPassBufferStorage.Merge(_inputs.Select(x => x.TransTriangleBuffer).ToList()); input.EdgeBuffer = RenderingPassBufferStorage.Merge(_inputs.Select(x => x.EdgeBuffer).ToList()); input.PointBuffer = RenderingPassBufferStorage.Merge(_inputs.Select(x => x.PointBuffer).ToList()); return(input); }
// A helper function, analogous to ProcessFaces. private void ProcessPoints(RenderingPassBufferStorage bufferStorage) { var points = bufferStorage.Points; if (points.Count == 0) { return; } // Edges are encoded as line segment primitives whose vertices contain only position information. bufferStorage.FormatBits = VertexFormatBits.PositionColored; //int edgeVertexBufferSizeInFloats = VertexPosition.GetSizeInFloats() * bufferStorage.VertexBufferCount; int vertexBufferSizeInFloats = VertexPositionColored.GetSizeInFloats() * bufferStorage.VertexBufferCount; int numPoints = points.Count; bufferStorage.VertexBuffer = new VertexBuffer(vertexBufferSizeInFloats); bufferStorage.VertexBuffer.Map(vertexBufferSizeInFloats); var vertexStream = bufferStorage.VertexBuffer.GetVertexStreamPositionColored(); for (int i = 0; i < numPoints; i++) { var pointInfo = points[i]; var vertex = pointInfo.Vertex; vertexStream.AddVertex(new VertexPositionColored(vertex + pointInfo.Offset, pointInfo.Color)); } bufferStorage.VertexBuffer.Unmap(); bufferStorage.IndexBufferCount = bufferStorage.PrimitiveCount * IndexPoint.GetSizeInShortInts(); int indexBufferSizeInShortInts = 1 * bufferStorage.IndexBufferCount; bufferStorage.IndexBuffer = new IndexBuffer(indexBufferSizeInShortInts); bufferStorage.IndexBuffer.Map(indexBufferSizeInShortInts); { IndexStreamPoint indexStream = bufferStorage.IndexBuffer.GetIndexStreamPoint(); for (int i = 0; i < numPoints; i++) { indexStream.AddPoint(new IndexPoint(i)); } } bufferStorage.IndexBuffer.Unmap(); bufferStorage.VertexFormat = new VertexFormat(bufferStorage.FormatBits); bufferStorage.EffectInstance = new EffectInstance(bufferStorage.FormatBits); }
// A helper function, analogous to ProcessFaces. private void ProcessEdges(RenderingPassBufferStorage bufferStorage) { var edges = bufferStorage.Edges; if (edges.Count == 0) { return; } // Edges are encoded as line segment primitives whose vertices contain only position information. bufferStorage.FormatBits = VertexFormatBits.PositionColored; //int edgeVertexBufferSizeInFloats = VertexPosition.GetSizeInFloats() * bufferStorage.VertexBufferCount; int edgeVertexBufferSizeInFloats = VertexPositionColored.GetSizeInFloats() * bufferStorage.VertexBufferCount; List <int> numVerticesInEdgesBefore = new List <int>(); numVerticesInEdgesBefore.Add(0); int numEdges = edges.Count; bufferStorage.VertexBuffer = new VertexBuffer(edgeVertexBufferSizeInFloats); bufferStorage.VertexBuffer.Map(edgeVertexBufferSizeInFloats); var vertexStream = bufferStorage.VertexBuffer.GetVertexStreamPositionColored(); for (int i = 0; i < numEdges; i++) { var edgeInfo = edges[i]; foreach (XYZ vertex in edgeInfo.Vertices) { vertexStream.AddVertex(new VertexPositionColored(vertex + edgeInfo.Offset, edgeInfo.Color)); } numVerticesInEdgesBefore.Add(numVerticesInEdgesBefore.Last() + edgeInfo.Vertices.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 (var edgeInfo in edges) { var xyzs = edgeInfo.Vertices; int startIndex = numVerticesInEdgesBefore[edgeNumber]; for (int i = 1; i < xyzs.Count; i++) { // Add two indices that define a line segment. indexStream.AddLine(new IndexLine((int)(startIndex + i - 1), (int)(startIndex + i))); } edgeNumber++; } } bufferStorage.IndexBuffer.Unmap(); bufferStorage.VertexFormat = new VertexFormat(bufferStorage.FormatBits); bufferStorage.EffectInstance = new EffectInstance(bufferStorage.FormatBits); }
// Create and populate a pair of vertex and index buffers. Also update parameters associated with the format of the vertices. private void ProcessTriangles(RenderingPassBufferStorage bufferStorage) { List <TriangleInfo> triangles = bufferStorage.Triangles; if (triangles.Count == 0) { return; } bool useNormals = this.Inputs.EnableFaceNormal; // Vertex attributes are stored sequentially in vertex buffers. The attributes can include position, normal vector, and color. // All vertices within a vertex buffer must have the same format. Possible formats are enumerated by VertexFormatBits. // Vertex format also determines the type of rendering effect that can be used with the vertex buffer. In this sample, // the color is always encoded in the vertex attributes. bufferStorage.FormatBits = useNormals ? VertexFormatBits.PositionNormalColored : VertexFormatBits.PositionColored; // The format of the vertices determines the size of the vertex buffer. int vertexBufferSizeInFloats = (useNormals ? VertexPositionNormalColored.GetSizeInFloats() : VertexPositionColored.GetSizeInFloats()) * bufferStorage.VertexBufferCount; bufferStorage.VertexBuffer = new VertexBuffer(vertexBufferSizeInFloats); bufferStorage.VertexBuffer.Map(vertexBufferSizeInFloats); int numTriangles = triangles.Count; if (useNormals) { // A VertexStream is used to write data into a VertexBuffer. VertexStreamPositionNormalColored vertexStream = bufferStorage.VertexBuffer.GetVertexStreamPositionNormalColored(); for (int i = 0; i < numTriangles; i++) { var triangleInfo = triangles[i]; g3.Triangle3d triangle = triangleInfo.Triangle; vertexStream.AddVertex(new VertexPositionNormalColored(triangle.V0.ToXYZ() + triangleInfo.Offset, triangleInfo.Normal, triangleInfo.ColorWithTransparency)); vertexStream.AddVertex(new VertexPositionNormalColored(triangle.V1.ToXYZ() + triangleInfo.Offset, triangleInfo.Normal, triangleInfo.ColorWithTransparency)); vertexStream.AddVertex(new VertexPositionNormalColored(triangle.V2.ToXYZ() + triangleInfo.Offset, triangleInfo.Normal, triangleInfo.ColorWithTransparency)); } } else { // A VertexStream is used to write data into a VertexBuffer. VertexStreamPositionColored vertexStream = bufferStorage.VertexBuffer.GetVertexStreamPositionColored(); for (int i = 0; i < numTriangles; i++) { var triangleInfo = triangles[i]; g3.Triangle3d triangle = triangleInfo.Triangle; // make the color of all faces white in HLR ColorWithTransparency color = triangleInfo.ColorWithTransparency; vertexStream.AddVertex(new VertexPositionColored(triangle.V0.ToXYZ() + triangleInfo.Offset, color)); vertexStream.AddVertex(new VertexPositionColored(triangle.V1.ToXYZ() + triangleInfo.Offset, color)); vertexStream.AddVertex(new VertexPositionColored(triangle.V2.ToXYZ() + triangleInfo.Offset, color)); } } bufferStorage.VertexBuffer.Unmap(); // Primitives are specified using a pair of vertex and index buffers. An index buffer contains a sequence of indices into // the associated vertex buffer, each index referencing a particular vertex. bufferStorage.IndexBufferCount = bufferStorage.PrimitiveCount * IndexTriangle.GetSizeInShortInts(); int indexBufferSizeInShortInts = 1 * bufferStorage.IndexBufferCount; bufferStorage.IndexBuffer = new IndexBuffer(indexBufferSizeInShortInts); bufferStorage.IndexBuffer.Map(indexBufferSizeInShortInts); // An IndexStream is used to write data into an IndexBuffer. IndexStreamTriangle indexStream = bufferStorage.IndexBuffer.GetIndexStreamTriangle(); int currIndex = 0; for (int i = 0; i < numTriangles; i++) { // Add three indices that define a triangle. indexStream.AddTriangle(new IndexTriangle(currIndex + 0, currIndex + 1, currIndex + 2)); currIndex += 3; } bufferStorage.IndexBuffer.Unmap(); // VertexFormat is a specification of the data that is associated with a vertex (e.g., position). bufferStorage.VertexFormat = new VertexFormat(bufferStorage.FormatBits); // Effect instance is a specification of the appearance of geometry. For example, it may be used to specify color, if there is no color information provided with the vertices. bufferStorage.EffectInstance = new EffectInstance(bufferStorage.FormatBits); }
// Create and populate a pair of vertex and index buffers. Also update parameters associated with the format of the vertices. private void ProcessFaces(RenderingPassBufferStorage bufferStorage) { List <MeshInfo> meshes = bufferStorage.Meshes; if (meshes.Count == 0) { return; } List <int> numVerticesInMeshesBefore = new List <int>(); bool useNormals = this.Inputs.EnableFaceNormal; // Vertex attributes are stored sequentially in vertex buffers. The attributes can include position, normal vector, and color. // All vertices within a vertex buffer must have the same format. Possible formats are enumerated by VertexFormatBits. // Vertex format also determines the type of rendering effect that can be used with the vertex buffer. In this sample, // the color is always encoded in the vertex attributes. bufferStorage.FormatBits = useNormals ? VertexFormatBits.PositionNormalColored : VertexFormatBits.PositionColored; // The format of the vertices determines the size of the vertex buffer. int vertexBufferSizeInFloats = (useNormals ? VertexPositionNormalColored.GetSizeInFloats() : VertexPositionColored.GetSizeInFloats()) * bufferStorage.VertexBufferCount; numVerticesInMeshesBefore.Add(0); bufferStorage.VertexBuffer = new VertexBuffer(vertexBufferSizeInFloats); bufferStorage.VertexBuffer.Map(vertexBufferSizeInFloats); int numMeshes = meshes.Count; if (useNormals) { // A VertexStream is used to write data into a VertexBuffer. VertexStreamPositionNormalColored vertexStream = bufferStorage.VertexBuffer.GetVertexStreamPositionNormalColored(); for (int i = 0; i < numMeshes; i++) { var meshInfo = meshes[i]; Mesh mesh = meshInfo.Mesh; foreach (XYZ vertex in mesh.Vertices) { vertexStream.AddVertex(new VertexPositionNormalColored(vertex + meshInfo.Offset, meshInfo.Normal, meshInfo.ColorWithTransparency)); } numVerticesInMeshesBefore.Add(numVerticesInMeshesBefore.Last() + mesh.Vertices.Count); } } else { // A VertexStream is used to write data into a VertexBuffer. VertexStreamPositionColored vertexStream = bufferStorage.VertexBuffer.GetVertexStreamPositionColored(); for (int i = 0; i < numMeshes; i++) { var meshInfo = meshes[i]; Mesh mesh = meshInfo.Mesh; // make the color of all faces white in HLR ColorWithTransparency color = meshInfo.ColorWithTransparency; foreach (XYZ vertex in mesh.Vertices) { vertexStream.AddVertex(new VertexPositionColored(vertex + meshInfo.Offset, color)); } numVerticesInMeshesBefore.Add(numVerticesInMeshesBefore.Last() + mesh.Vertices.Count); } } bufferStorage.VertexBuffer.Unmap(); // Primitives are specified using a pair of vertex and index buffers. An index buffer contains a sequence of indices into // the associated vertex buffer, each index referencing a particular vertex. int meshNumber = 0; bufferStorage.IndexBufferCount = bufferStorage.PrimitiveCount * IndexTriangle.GetSizeInShortInts(); int indexBufferSizeInShortInts = 1 * bufferStorage.IndexBufferCount; bufferStorage.IndexBuffer = new IndexBuffer(indexBufferSizeInShortInts); bufferStorage.IndexBuffer.Map(indexBufferSizeInShortInts); { // An IndexStream is used to write data into an IndexBuffer. IndexStreamTriangle indexStream = bufferStorage.IndexBuffer.GetIndexStreamTriangle(); foreach (MeshInfo meshInfo in meshes) { Mesh mesh = meshInfo.Mesh; int startIndex = numVerticesInMeshesBefore[meshNumber]; for (int i = 0; i < mesh.NumTriangles; i++) { MeshTriangle mt = mesh.get_Triangle(i); // Add three indices that define a triangle. indexStream.AddTriangle(new IndexTriangle((int)(startIndex + mt.get_Index(0)), (int)(startIndex + mt.get_Index(1)), (int)(startIndex + mt.get_Index(2)))); } meshNumber++; } } bufferStorage.IndexBuffer.Unmap(); // VertexFormat is a specification of the data that is associated with a vertex (e.g., position). bufferStorage.VertexFormat = new VertexFormat(bufferStorage.FormatBits); // Effect instance is a specification of the appearance of geometry. For example, it may be used to specify color, if there is no color information provided with the vertices. bufferStorage.EffectInstance = new EffectInstance(bufferStorage.FormatBits); }
// Submits the geometry for rendering. public void RenderScene(Autodesk.Revit.DB.View view, DisplayStyle displayStyle) { try { //on request, process pre-stored graphic data //to get ready for submission for drawing. if (InputChanged) { ProcessFaces(this.Inputs.NonTransFaceBuffer); ProcessFaces(this.Inputs.TransFaceBuffer); ProcessTriangles(this.Inputs.NonTransTriangleBuffer); ProcessTriangles(this.Inputs.TransTriangleBuffer); ProcessEdges(this.Inputs.EdgeBuffer); ProcessPoints(this.Inputs.PointBuffer); } DrawContext.SetWorldTransform(this.WorldTransform); // Submit a subset of the geometry for drawing. Determine what geometry should be submitted based on // the type of the rendering pass (opaque or transparent) and DisplayStyle (wireframe or shaded). // If the server is requested to submit transparent geometry, DrawContext().IsTransparentPass() // will indicate that the current rendering pass is for transparent objects. RenderingPassBufferStorage faceBuffer = DrawContext.IsTransparentPass() ? this.Inputs.TransFaceBuffer : this.Inputs.NonTransFaceBuffer; RenderingPassBufferStorage triangleBuffer = DrawContext.IsTransparentPass() ? this.Inputs.TransTriangleBuffer : this.Inputs.NonTransTriangleBuffer; var edgeBuffer = this.Inputs.EdgeBuffer; var pointBuffer = this.Inputs.PointBuffer; // Conditionally submit triangle primitives (for non-wireframe views). if (displayStyle != DisplayStyle.Wireframe && faceBuffer.PrimitiveCount > 0) { DrawContext.FlushBuffer(faceBuffer.VertexBuffer, faceBuffer.VertexBufferCount, faceBuffer.IndexBuffer, faceBuffer.IndexBufferCount, faceBuffer.VertexFormat, faceBuffer.EffectInstance, PrimitiveType.TriangleList, 0, faceBuffer.PrimitiveCount); } if (displayStyle != DisplayStyle.Wireframe && triangleBuffer.PrimitiveCount > 0) { DrawContext.FlushBuffer(triangleBuffer.VertexBuffer, triangleBuffer.VertexBufferCount, triangleBuffer.IndexBuffer, triangleBuffer.IndexBufferCount, triangleBuffer.VertexFormat, triangleBuffer.EffectInstance, PrimitiveType.TriangleList, 0, triangleBuffer.PrimitiveCount); } // Conditionally submit line segment primitives. if (displayStyle != DisplayStyle.Shading && edgeBuffer.PrimitiveCount > 0) { DrawContext.FlushBuffer(edgeBuffer.VertexBuffer, edgeBuffer.VertexBufferCount, edgeBuffer.IndexBuffer, edgeBuffer.IndexBufferCount, edgeBuffer.VertexFormat, edgeBuffer.EffectInstance, PrimitiveType.LineList, 0, edgeBuffer.PrimitiveCount); } if (pointBuffer.PrimitiveCount > 0) { DrawContext.FlushBuffer(pointBuffer.VertexBuffer, pointBuffer.VertexBufferCount, pointBuffer.IndexBuffer, pointBuffer.IndexBufferCount, pointBuffer.VertexFormat, pointBuffer.EffectInstance, PrimitiveType.PointList, 0, pointBuffer.PrimitiveCount); } } catch (Exception e) { MessageBox.Show(e.ToString()); } finally { InputChanged = false; } }