[返回博客](/cn/blog) # 在单独线程中渲染图纸

Evgeniy Tikhonov 四月 15, 2021 [\#rfa](/cn/blog/tag/rfa) [\#rvt](/cn/blog/tag/rvt) [\#rendering](/cn/blog/tag/rendering)

<a class="a2a_button_facebook"></a><a class="a2a_button_twitter"></a><a class="a2a_button_linkedin"></a>

#### 简介

本主题介绍如何在单独的线程中渲染图纸以提高性能。

ODA BimRv SDK 提供了一个简单的 API，用于为 OdBmMTDrawContext、OdBmMTDraw 和 OdBmMTDrawingMgr 类调用多线程功能。

OdBmMTDraw 类通过指定的上下文为单个 OdBmDBDrawing 元素提供线程安全的渲染功能。

OdBmMTDrawingMgr 类通过指定的上下文为 OdBmDBDrawing 元素数组提供线程安全的渲染功能。它只是启动多个 OdBmMTDraw 实例，以在单独的并发线程中渲染绘图数组。

您还需要 OdBmMTDrawContext 或其派生类的一个实例。请参阅下面的类型定义和构造函数：

```

typedef std::function<OdGsDevicePtr(const OdBmMTDrawContext*)> OdBmCreateGsDeviceFuncType;
typedef std::function<void(OdBmObjectId, OdGsDevice*, const OdBmMTDrawContext*)> OdBmPostProcessFuncType;

OdBmMTDrawContext(
    OdMutex* pDbAccessMutex,
    long picWidth,
    long picHeight,
    bool bZoomToExtents,
    const OdBmCreateGsDeviceFuncType& deviceCreator,
    const OdBmPostProcessFuncType& postProcessor)
```

最后两个参数是对需要实现的函数的引用。

第一个函数应满足 OdBmCreateGsDeviceFuncType 原型，创建适当的 GS 设备，并返回指向它的指针。

第二个函数应满足 OdBmPostProcessFuncType 原型，并执行渲染结果的后处理。

#### 示例

以下示例通过 GLES2 设备渲染 DBDrawings 并将结果存储在位图数组中。您可以在 BmMTDrawingMgrEx 示例中找到以下代码。

首先，创建 OdBmMTDrawContext 类的派生类。

```
struct OdBmGLES2MTDrawContext : public OdBmMTDrawContext {
  OdBmGLES2MTDrawContext(
    OdMutex* dbAccessMutex,
    long picWidth,
    long picHeight,
    bool bZoomToExtents,
    const OdBmCreateGsDeviceFuncType& createGsDeviceFunc,
    const OdBmPostProcessFuncType& postProcessFunc,
    // discard back faces wile rendering
    bool bDiscardBackFaces,
    // use plot generation
    bool bPlotGeneration,
    // background color of result images
    ODCOLORREF bgColor = ODRGB(255, 255, 255)):
  OdBmMTDrawContext(
    dbAccessMutex, picWidth, 
    picHeight, bZoomToExtents,
    createGsDeviceFunc, postProcessFunc),
    discardBackFaces(bDiscardBackFaces),
    plotGeneration(bPlotGeneration),
    bgColor(bgColor) {
  }

  bool discardBackFaces;
  ODCOLORREF bgColor;
  bool plotGeneration;
};
```

接下来，定义一个覆盖类，例如：

```
class OdBmMTRenderer {
public:
  // type defenition for rendering results
  typedef std::map Renditions; 
  /* execution params
    param drawings - an array of drawings to be rendered.
    param picWidth - width of result bitmaps in pixels.
    param picHeight - height of result bitmaps in pixels.
    param bZoomToExtents - use zoom to extents.
    param bDiscardBackFaces - discard back faces while rendering.
    param bgColor - result bitmaps background color.
  */
  Renditions run(OdBmDBDrawingPtrArray& drawings,
    long picWidth, long picHeight, bool bZoomToExtents = false,
    bool bDiscardBackFaces = false, ODCOLORREF bgColor = ODRGB(255, 255, 255));
};
```

现在，实现它。首先，获取所有必需的包含文件：

```
#include "BmMTRenderer.h"

#include "DynamicLinker.h"
#include "RxVariantValue.h"
#include "Gi/GiRasterWrappers.h"
#include "Database/MTDrawingMgr/BmMTDrawingMgr.h"

#include "MTDrawingMgr/BmMTDraw.h"
#include "BmGLES2MTDrawContext.h"
```

接下来，实现 run() 函数。这是一个专门的过程，因此第一步是创建 OdBmCreateGsDeviceFuncType 类型的函数。

```
/******************************************************************/
/* GS device creation function                                    */
/******************************************************************/

OdMutex m_createDevice;
auto createDevice = [&m_createDevice](const OdBmMTDrawContext* pContext) {
    TD_AUTOLOCK(m_createDevice);
    const OdBmGLES2MTDrawContext* pToImgContext =
      static_cast(pContext);

    OdGsModulePtr pGsModule = ::odrxDynamicLinker()->loadModule(OdWinGLES2ModuleName);
    OdGsDevicePtr pGsDevice = pGsModule->createBitmapDevice();

    // Enable HLR for Bitmap and WinGDI vectorizers
    OdRxDictionaryPtr pProps = pGsDevice->properties();
    if (pProps->has(OD_T("EnableSoftwareHLR"))) // Check if property is supported
      pProps->putAt(OD_T("EnableSoftwareHLR"), OdRxVariantValue(true));
    if (pProps->has(OD_T("DiscardBackFaces"))) // Check if property is supported
      pProps->putAt(OD_T("DiscardBackFaces"), OdRxVariantValue(pToImgContext->discardBackFaces()));

    OdRxThreadPoolServicePtr pThreadPool = ::odrxDynamicLinker()->loadApp(OdThreadPoolModuleName);
    if (pThreadPool.isNull())
      throw(L"ThreadPool.tx not found.\n");

    OdUInt16 nCPUs = pThreadPool->numCPUs();
    if (pGsDevice->properties()->has(OD_T("MaxRegenThreads")))
      pGsDevice->properties()->putAt(OD_T("MaxRegenThreads"), OdRxVariantValue(nCPUs));

    if (pGsDevice->properties()->has(OD_T("EnableMultithread")))
      pGsDevice->properties()->putAt(OD_T("EnableMultithread"), OdRxVariantValue(true));

    pGsDevice->setLogicalPalette(
      (ODGETRED(pToImgContext->bgColor()) < 140) && (ODGETGREEN(pToImgContext->bgColor()) < 140) && (ODGETBLUE(pToImgContext->bgColor()) < 140) ?
      (::odcmAcadDarkPalette()) : (::odcmAcadLightPalette()), 256);
    pGsDevice->setBackgroundColor(pToImgContext->bgColor());

    return pGsDevice;
};
```

接下来，创建 OdBmPostProcessFuncType 类型的函数。

```
/******************************************************************/
/* Rendering results processing function                          */
/******************************************************************/

OdMutex m_mutex;
Renditions renditions;
auto postPrecess = [&m_mutex, &renditions](OdBmObjectId id, OdGsDevice* pDevice, const OdBmMTDrawContext* pContext) {
    TD_AUTOLOCK(m_mutex);
    // Create clone of rendered raster image to correctly release all vectorizer resources in current thread
    OdGiRasterImagePtr pRaster = OdGiRasterImageHolder::createObject(
      OdGiRasterImagePtr(pDevice->properties().get()->getAt(OD_T("RasterImage"))));
    renditions[id] = pRaster;
};
```

最后，创建 OdBmMTDrawContext 的实例：

```
/******************************************************************/
/* Instantiate the context and start MT rendering                 */
/******************************************************************/

OdBmGLES2MTDrawContext m_ctx(&m_mutex, picWidth, picHeight, bZoomToExtents,
    (OdBmMTDrawContext::OdBmCreateGsDeviceFuncType)createDevice, 
    (OdBmMTDrawContext::OdBmPostProcessFuncType)postPrecess,
    bDiscardBackFaces, bgColor);
 
OdBmMTDrawingMgr().draw(drawings, &m_ctx);

return renditions;
```

您可以在 BimRv/Examples/BmMTDrawingMgrEx/BmMTDrawingMgrEx.cpp 文件中找到 run() 方法的实现。

## 今天就开始行动

**免费试用 ODA 软件 60 天。  
无风险，无需信用卡。**

[免费试用](https://www.opendesign.com/cn/free-trial)
