应用程序:DuplicateGraphics
Revit平台:所有版本
Revit版本:2018.0
首次发布:2018.0
编程语言:C#
技能级别:高级
类别:基础知识,几何学
类型:ExternalCommand 和 ExternalApplication
主题:使用DirectContext3D显示图形
摘要:该示例展示了使用DirectContext3D的基本用法。外部程序创建DirectContext3D服务器,从所选的Revit元素中提取几何信息,将其编码为顶点和索引缓冲区的一对,并使用DirectContext3D提交它以进行渲染。通过使用一个ExternalCommand触发这个过程的效果是,在一个偏移位置上显示所选Revit元素的几何内容,以便图形看起来被复制。
相关类:
Autodesk.Revit.DB.ExternalService.IExternalApplication
Autodesk.Revit.UI.IExternalCommand
Autodesk.Revit.DB.DirectContext3D.IDirectContext3DServer
Autodesk.Revit.DB.DirectContext3D.DrawContext
项目文件:
Application.cs
Application类是从IExternalApplication派生出来的,它创建并注册DirectContext3D服务器,向Revit提供外部几何元素。
Command.cs
两个派生自IExternalCommand的命令类提供了与应用程序的接口。命令类CommandDuplicateGraphics指示应用程序提示用户选择要处理的Revit元素。命令类CommandClearExternalGraphics指示应用程序删除已创建的DirectContext3D图形。
RevitElementDrawServer.cs
该文件包含了类RevitElementDrawServer,实现了IDirectContext3DServer接口。服务器类从Revit元素中提取几何信息,使用DirectContext3D.DrawContext提交渲染。
描述:
该示例展示了如何使用DirectContext3D来绘制几何图形,这些图形是从现有的Revit元素中获取的。几何图形被编码为一对顶点缓冲区和索引缓冲区。为了使所选的Revit元素在相同的显示样式下显示为其余Revit视图的图形内容的重复,不同类型的几何图形被准备用于不同的显示样式。
操作步骤:
打开Revit应用程序并执行“使用DirectContext3D显示图形”的命令。
1.选择需要使用DirectContext3D重新绘制图形的元素。
2.完成选择。
预期结果:所选图形将呈现为具有偏移量的重复形式。
3.更改视图的显示样式。
预期结果:DirectContext3D图形会改变以匹配显示样式。
完整的源代码请加入QQ群649037449,在群文件中下载RevitSDK.exe,解压后在文件夹中搜索本文中应用程序名称即可获得完整源码
Application.cs
//
// (C) Copyright 2003-2019 by Autodesk, Inc. All rights reserved.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM 'AS IS' AND WITH ALL ITS FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
/*
* This sample demonstrates how to use DirectContext3D to draw graphics. The graphics primitives that
* are needed for DirectContext3D are taken from the contents of existing Revit elements. The result of
* the macro is to duplicate the graphics of existing Revit elements by using DirectContext3D. No new
* elements are created to contain the graphics produced with DirectContext3D.
*
* The following are the main steps for using DirectContext3D:
* 1) create a DirectContext3D server (derived from Autodesk.Revit.DB.DirectContext3D.IDirectContext3DServer)
* a. register the server with the DirectContext3D service
* 2) use the server to submit geometry for drawing
* a. represent geometry primitives using pairs of vertex and index buffers
* b. determine when to submit opaque/transparent geometry
* c. flush the buffers
* d. update the buffers when necessary
*/
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.ExternalService;
using Autodesk.Revit.DB.Events;
using Autodesk.Revit.UI.Selection;
using System;
using System.Collections.Generic;
namespace Revit.SDK.Samples.DuplicateGraphics.CS
{
/// <summary>
/// Implements the Revit add-in interface IExternalApplication
/// </summary>
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
[Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
public class Application : IExternalApplication
{
#region IExternalApplication Members
/// <summary>
/// Implements the OnStartup event
/// </summary>
/// <param name="application"></param>
/// <returns>Result that indicates whether the external application has completed its work successfully.</returns>
public Result OnStartup(UIControlledApplication application)
{
try
{
// Register events.
application.ControlledApplication.DocumentClosing += new EventHandler
<Autodesk.Revit.DB.Events.DocumentClosingEventArgs>(OnDocumentClosing);
m_servers = new List<RevitElementDrawingServer>();
m_documents = new HashSet<Document>();
s_applicationInstance = this;
}
catch (Exception)
{
return Result.Failed;
}
return Result.Succeeded;
}
/// <summary>
/// Implements the OnShutdown event
/// </summary>
/// <param name="application"></param>
/// <returns>Result that indicates whether the external application has completed its work successfully.</returns>
public Result OnShutdown(UIControlledApplication application)
{
// remove the event.
application.ControlledApplication.DocumentClosing -= OnDocumentClosing;
return Result.Succeeded;
}
/// <summary>
/// Implements the OnDocumentClosing event
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
/// <returns></returns>
public void OnDocumentClosing(object sender, DocumentClosingEventArgs args)
{
unregisterServers(args.Document, false);
}
#endregion
/// <summary>
/// Responds to the external command CommandDuplicateGraphics.
/// </summary>
/// <param name="document"></param>
public static void ProcessCommandDuplicateGraphics(Document document)
{
if (s_applicationInstance != null)
{
s_applicationInstance.AddMultipleRevitElementServers(new UIDocument(document));
}
}
/// <summary>
/// Responds to the external command CommandClearExternalGraphics.
/// </summary>
/// <param name="document"></param>
public static void ProcessCommandClearExternalGraphics(Document document)
{
if (s_applicationInstance != null)
{
s_applicationInstance.unregisterServers(null, true);
}
}
/// <summary>
/// Picks a Revit element and creates a corresponding DirectContext3D server that will draw the element's graphics at a fixed offset from the original location.
/// </summary>
/// <param name="uidoc"></param>
public void AddRevitElementServer(UIDocument uidoc)
{
Reference reference = uidoc.Selection.PickObject(ObjectType.Element, "Select an element to duplicate with DirectContext3D");
Element elem = uidoc.Document.GetElement(reference);
// Create the server and register it with the DirectContext3D service.
ExternalService directContext3DService = ExternalServiceRegistry.GetService(ExternalServices.BuiltInExternalServices.DirectContext3DService);
RevitElementDrawingServer revitServer = new RevitElementDrawingServer(uidoc, elem, m_offset);
directContext3DService.AddServer(revitServer);
m_servers.Add(revitServer);
MultiServerService msDirectContext3DService = directContext3DService as MultiServerService;
IList<Guid> serverIds = msDirectContext3DService.GetActiveServerIds();
serverIds.Add(revitServer.GetServerId());
// Add the new server to the list of active servers.
msDirectContext3DService.SetActiveServers(serverIds);
m_documents.Add(uidoc.Document);
uidoc.UpdateAllOpenViews();
}
/// <summary>
/// Same as AddRevitElementServer(), but for multiple elements.
/// </summary>
/// <param name="uidoc"></param>
public void AddMultipleRevitElementServers(UIDocument uidoc)
{
IList<Reference> references = uidoc.Selection.PickObjects(ObjectType.Element, "Select elements to duplicate with DirectContext3D");
ExternalService directContext3DService = ExternalServiceRegistry.GetService(ExternalServices.BuiltInExternalServices.DirectContext3DService);
MultiServerService msDirectContext3DService = directContext3DService as MultiServerService;
IList<Guid> serverIds = msDirectContext3DService.GetActiveServerIds();
// Create one server per element.
foreach (Reference reference in references)
{
Element elem = uidoc.Document.GetElement(reference);
RevitElementDrawingServer revitServer = new RevitElementDrawingServer(uidoc, elem, m_offset);
directContext3DService.AddServer(revitServer);
m_servers.Add(revitServer);
serverIds.Add(revitServer.GetServerId());
}
msDirectContext3DService.SetActiveServers(serverIds);
m_documents.Add(uidoc.Document);
uidoc.UpdateAllOpenViews();
}
/// <summary>
/// Cleans up by unregistering the servers corresponding to the specified document, or all servers if the document is not provided.
/// </summary>
/// <param name="document">The document whose servers should be removed, or null.</param>
/// <param name="updateViews">Update views of the affected document(s).</param>
public void unregisterServers(Document document, bool updateViews)
{
ExternalServiceId externalDrawerServiceId = ExternalServices.BuiltInExternalServices.DirectContext3DService;
var externalDrawerService = ExternalServiceRegistry.GetService(externalDrawerServiceId) as MultiServerService;
if (externalDrawerService == null)
return;
foreach (var registeredServerId in externalDrawerService.GetRegisteredServerIds())
{
var externalDrawServer = externalDrawerService.GetServer(registeredServerId) as RevitElementDrawingServer;
if (externalDrawServer == null)
continue;
if (document != null && !document.Equals(externalDrawServer.Document))
continue;
externalDrawerService.RemoveServer(registeredServerId);
}
if (document != null)
{
m_servers.RemoveAll(server => document.Equals(server.Document));
if (updateViews)
{
UIDocument uidoc = new UIDocument(document);
uidoc.UpdateAllOpenViews();
}
m_documents.Remove(document);
}
else
{
m_servers.Clear();
if (updateViews)
foreach (var doc in m_documents)
{
UIDocument uidoc = new UIDocument(doc);
uidoc.UpdateAllOpenViews();
}
m_documents.Clear();
}
}
List<RevitElementDrawingServer> m_servers;
XYZ m_offset = new XYZ(0, 0, 45);
HashSet<Document> m_documents;
static Application s_applicationInstance;
}
}
RevitElementDrawServer.cs
//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
/*
* This sample demonstrates how to use DirectContext3D to draw graphics.
* This file defines a DirectContext3D server.
*/
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.ExternalService;
using Autodesk.Revit.DB.DirectContext3D;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace Revit.SDK.Samples.DuplicateGraphics.CS
{
class RevitElementDrawingServer : IDirectContext3DServer
{
public RevitElementDrawingServer(UIDocument uiDoc, Element elem, XYZ offset)
{
m_guid = Guid.NewGuid();
m_uiDocument = uiDoc;
m_element = elem;
m_offset = offset;
}
public System.Guid GetServerId() { return m_guid; }
public System.String GetVendorId() { return "ADSK"; }
public ExternalServiceId GetServiceId() { return ExternalServices.BuiltInExternalServices.DirectContext3DService; }
public System.String GetName() { return "Revit Element Drawing Server"; }
public System.String GetDescription() { return "Duplicates graphics from a Revit element."; }
// Corresponds to functionality that is not used in this sample.
public System.String GetApplicationId() { return ""; }
// Corresponds to functionality that is not used in this sample.
public System.String GetSourceId() { return ""; }
// Corresponds to functionality that is not used in this sample.
public bool UsesHandles() { return false; }
// Tests whether this server should be invoked for the given view.
// The server only wants to be invoked for 3D views that are part of the document that contains the element in m_element.
public bool CanExecute(Autodesk.Revit.DB.View view)
{
if (!m_element.IsValidObject)
return false;
if (view.ViewType != ViewType.ThreeD)
return false;
Document doc = view.Document;
Document otherDoc = m_element.Document;
return doc.Equals(otherDoc);
}
// Reports a bounding box of the geometry that this server submits for drawing.
public Outline GetBoundingBox(Autodesk.Revit.DB.View view)
{
try
{
BoundingBoxXYZ boundingBox = m_element.get_BoundingBox(null);
Outline outline = new Outline(boundingBox.Min + m_offset, boundingBox.Max + m_offset);
return outline;
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
throw;
}
}
// Indicates that this server will submit geometry during the rendering pass for transparent geometry.
public bool UseInTransparentPass(Autodesk.Revit.DB.View view) { return true; }
// Submits the geometry for rendering.
public void RenderScene(Autodesk.Revit.DB.View view, DisplayStyle displayStyle)
{
try
{
// Populate geometry buffers if they are not initialized or need updating.
if (m_nonTransparentFaceBufferStorage == null || m_nonTransparentFaceBufferStorage.needsUpdate(displayStyle) ||
m_transparentFaceBufferStorage == null || m_transparentFaceBufferStorage.needsUpdate(displayStyle) ||
m_edgeBufferStorage == null || m_edgeBufferStorage.needsUpdate(displayStyle))
{
Options options = new Options();
GeometryElement geomElem = m_element.get_Geometry(options);
CreateBufferStorageForElement(geomElem, displayStyle);
}
// 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 faceBufferStorage = DrawContext.IsTransparentPass() ? m_transparentFaceBufferStorage : m_nonTransparentFaceBufferStorage;
// Conditionally submit triangle primitives (for non-wireframe views).
if (displayStyle != DisplayStyle.Wireframe &&
faceBufferStorage.PrimitiveCount > 0)
DrawContext.FlushBuffer(faceBufferStorage.VertexBuffer,
faceBufferStorage.VertexBufferCount,
faceBufferStorage.IndexBuffer,
faceBufferStorage.IndexBufferCount,
faceBufferStorage.VertexFormat,
faceBufferStorage.EffectInstance, PrimitiveType.TriangleList, 0,
faceBufferStorage.PrimitiveCount);
// Conditionally submit line segment primitives.
if (displayStyle != DisplayStyle.Shading &&
m_edgeBufferStorage.PrimitiveCount > 0)
DrawContext.FlushBuffer(m_edgeBufferStorage.VertexBuffer,
m_edgeBufferStorage.VertexBufferCount,
m_edgeBufferStorage.IndexBuffer,
m_edgeBufferStorage.IndexBufferCount,
m_edgeBufferStorage.VertexFormat,
m_edgeBufferStorage.EffectInstance, PrimitiveType.LineList, 0,
m_edgeBufferStorage.PrimitiveCount);
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}
// Initialize and populate buffers that hold graphics primitives, set up related parameters that are needed for drawing.
private void CreateBufferStorageForElement(GeometryElement geomElem, DisplayStyle displayStyle)
{
List<Solid> allSolids = new List<Solid>();
foreach (GeometryObject geomObj in geomElem)
{
if (geomObj is Solid)
{
Solid solid = (Solid)geomObj;
if (solid.Volume > 1e-06)
allSolids.Add(solid);
}
}
m_nonTransparentFaceBufferStorage = new RenderingPassBufferStorage(displayStyle);
m_transparentFaceBufferStorage = new RenderingPassBufferStorage(displayStyle);
m_edgeBufferStorage = new RenderingPassBufferStorage(displayStyle);
// Collect primitives (and associated rendering parameters, such as colors) from faces and edges.
foreach (Solid solid in allSolids)
{
foreach (Face face in solid.Faces)
{
if (face.Area > 1e-06)
{
Mesh mesh = face.Triangulate();
ElementId materialId = face.MaterialElementId;
bool isTransparent = false;
ColorWithTransparency cwt = new ColorWithTransparency(127, 127, 127, 0);
if (materialId != ElementId.InvalidElementId)
{
Material material = m_element.Document.GetElement(materialId) as Material;
Color color = material.Color;
int transparency0To100 = material.Transparency;
uint transparency0To255 = (uint)((float)transparency0To100 / 100f * 255f);
cwt = new ColorWithTransparency(color.Red, color.Green, color.Blue, transparency0To255);
if (transparency0To255 > 0)
{
isTransparent = true;
}
}
BoundingBoxUV env = face.GetBoundingBox();
UV center = 0.5 * (env.Min + env.Max);
XYZ normal = face.ComputeNormal(center);
MeshInfo meshInfo = new MeshInfo(mesh, normal, cwt);
if (isTransparent)
{
m_transparentFaceBufferStorage.Meshes.Add(meshInfo);
m_transparentFaceBufferStorage.VertexBufferCount += mesh.Vertices.Count;
m_transparentFaceBufferStorage.PrimitiveCount += mesh.NumTriangles;
}
else
{
m_nonTransparentFaceBufferStorage.Meshes.Add(meshInfo);
m_nonTransparentFaceBufferStorage.VertexBufferCount += mesh.Vertices.Count;
m_nonTransparentFaceBufferStorage.PrimitiveCount += mesh.NumTriangles;
}
}
}
foreach (Edge edge in solid.Edges)
{
// if (edge.Length > 1e-06)
{
IList<XYZ> xyzs = edge.Tessellate();
m_edgeBufferStorage.VertexBufferCount += xyzs.Count;
m_edgeBufferStorage.PrimitiveCount += xyzs.Count - 1;
m_edgeBufferStorage.EdgeXYZs.Add(xyzs);
}
}
}
// Fill out buffers with primitives based on the intermediate information about faces and edges.
ProcessFaces(m_nonTransparentFaceBufferStorage);
ProcessFaces(m_transparentFaceBufferStorage);
ProcessEdges(m_edgeBufferStorage);
}
// 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;
List<int> numVerticesInMeshesBefore = new List<int>();
if (meshes.Count == 0) return;
bool useNormals = bufferStorage.DisplayStyle == DisplayStyle.Shading ||
bufferStorage.DisplayStyle == DisplayStyle.ShadingWithEdges;
// 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);
if (useNormals)
{
// A VertexStream is used to write data into a VertexBuffer.
VertexStreamPositionNormalColored vertexStream = bufferStorage.VertexBuffer.GetVertexStreamPositionNormalColored();
foreach (MeshInfo meshInfo in meshes)
{
Mesh mesh = meshInfo.Mesh;
foreach (XYZ vertex in mesh.Vertices)
{
vertexStream.AddVertex(new VertexPositionNormalColored(vertex + m_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();
foreach (MeshInfo meshInfo in meshes)
{
Mesh mesh = meshInfo.Mesh;
// make the color of all faces white in HLR
ColorWithTransparency color = (bufferStorage.DisplayStyle == DisplayStyle.HLR) ?
new ColorWithTransparency(255, 255, 255, meshInfo.ColorWithTransparency.GetTransparency()) :
meshInfo.ColorWithTransparency;
foreach (XYZ vertex in mesh.Vertices)
{
vertexStream.AddVertex(new VertexPositionColored(vertex + m_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);
}
// A helper function, analogous to ProcessFaces.
private void ProcessEdges(RenderingPassBufferStorage bufferStorage)
{
List<IList<XYZ>> 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<int> numVerticesInEdgesBefore = new List<int>();
numVerticesInEdgesBefore.Add(0);
bufferStorage.VertexBuffer = new VertexBuffer(edgeVertexBufferSizeInFloats);
bufferStorage.VertexBuffer.Map(edgeVertexBufferSizeInFloats);
{
VertexStreamPosition vertexStream = bufferStorage.VertexBuffer.GetVertexStreamPosition();
foreach (IList<XYZ> xyzs in edges)
{
foreach (XYZ vertex in xyzs)
{
vertexStream.AddVertex(new VertexPosition(vertex + m_offset));
}
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<XYZ> 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((int)(startIndex + i - 1),
(int)(startIndex + i)));
}
edgeNumber++;
}
}
bufferStorage.IndexBuffer.Unmap();
bufferStorage.VertexFormat = new VertexFormat(bufferStorage.FormatBits);
bufferStorage.EffectInstance = new EffectInstance(bufferStorage.FormatBits);
}
public Document Document
{
get { return (m_uiDocument != null) ? m_uiDocument.Document : null; }
}
private Guid m_guid;
private Element m_element;
private XYZ m_offset;
private UIDocument m_uiDocument;
private RenderingPassBufferStorage m_nonTransparentFaceBufferStorage;
private RenderingPassBufferStorage m_transparentFaceBufferStorage;
private RenderingPassBufferStorage m_edgeBufferStorage;
#region Helper classes
// A container to hold information associated with a triangulated face.
class MeshInfo
{
public MeshInfo(Mesh mesh, XYZ normal, ColorWithTransparency color)
{
Mesh = mesh;
Normal = normal;
ColorWithTransparency = color;
}
public Mesh Mesh;
public XYZ Normal;
public ColorWithTransparency ColorWithTransparency;
}
// A class that brings together all the data and rendering parameters that are needed to draw one sequence of primitives (e.g., triangles)
// with the same format and appearance.
class RenderingPassBufferStorage
{
public RenderingPassBufferStorage(DisplayStyle displayStyle)
{
DisplayStyle = displayStyle;
Meshes = new List<MeshInfo>();
EdgeXYZs = new List<IList<XYZ>>();
}
public bool needsUpdate(DisplayStyle newDisplayStyle)
{
if (newDisplayStyle != DisplayStyle)
return true;
if (PrimitiveCount > 0)
if (VertexBuffer == null || !VertexBuffer.IsValid() ||
IndexBuffer == null || !IndexBuffer.IsValid() ||
VertexFormat == null || !VertexFormat.IsValid() ||
EffectInstance == null || !EffectInstance.IsValid())
return true;
return false;
}
public DisplayStyle DisplayStyle { get; set; }
public VertexFormatBits FormatBits { get; set; }
public List<MeshInfo> Meshes { get; set; }
public List<IList<XYZ>> EdgeXYZs { get; set; }
public int PrimitiveCount { get; set; }
public int VertexBufferCount { get; set; }
public int IndexBufferCount { get; set; }
public VertexBuffer VertexBuffer { get; set; }
public IndexBuffer IndexBuffer { get; set; }
public VertexFormat VertexFormat { get; set; }
public EffectInstance EffectInstance { get; set; }
}
#endregion
}
}
版权所有 :无锡模信建筑科技有限公司 苏ICP备2021028830号-1 BIM建模|BIM技术应用|BIM软件开发
联系地址:江苏省无锡市新吴区龙山路4号B座705 手机:18761516598