ADN Open CIS
Сообщество программистов Autodesk в СНГ

16/02/2016

Визуализация при помощи RenderToImage API

Как вы возможно уже знаете API графической системы было изменено в AutoCAD 2015, как описано в статье Изменения в графике в AutoCAD 2015. В AutoCAD 2016 рендер RapidRT заменил рендер MentalRay, который использовался в предыдущих версиях. В свете этого в ObjectARX 2016 появился новый класс AcDbRapidRTRenderSettings. Все эти изменения требуют изменений в вашем коде в случае, если вы использовали метод AcGsView::RenderToImage для генерации изображения модели AutoCAD.

Следующий код должен генерировать визуализацию изображения как в AutoCAD 2016, так и в предыдущих версиях. Чтобы учесть различные изменения графической системы и средства визуализации, приведенный ниже код широко использует возможности условной компиляции.

Чтобы попробовать это, откройте чертеж и задайте направление взгляда в AutoCAD, такой как вы хотите для того чтобы генерировать визуализированное изображение. Настройте параметры визуализации и выполните визуализацию в AutoCAD. После того как вас устроят результаты, сделать настройки визуализации текущими. Это должно сохранить предустановки визуализации в качестве активных. Приведенный ниже код, получает параметры на основе активной предустановки, и используют их для создания изображении.

Код - C++: [Выделить]
  1. static  void  AdskMyTestRTITest(void )
  2. {
  3.  
  4.   AcDbDatabase *pDb
  5.     = acdbHostApplicationServices()->workingDatabase();
  6.  
  7.   AcGsManager *gsManager = acgsGetGsManager();
  8.  
  9.   if  (!gsManager)
  10.     return ;
  11.  
  12. #ifdef  ACAD2016 // 2016 и новее используют RapidRT рендер
  13.  
  14.   AcGsManager2 *gsManager2
  15.  
  16.     = dynamic_cast <AcGsManager2 *>(gsManager);
  17.  
  18.   if  (! gsManager2)
  19.  
  20.     return ;
  21.  
  22.   AcGsKernelDescriptor descriptor;
  23.  
  24.   descriptor.addRequirement(AcGsKernelDescriptor::k3DRapidRTRendering);
  25.  
  26.   AcGsGraphicsKernel *pGraphicsKernel = AcGsManager::acquireGraphicsKernel(descriptor);
  27.  
  28.   AcGsDevice *offDevice = gsManager2->getOffScreenDevice(*pGraphicsKernel);
  29.  
  30.   if  (! offDevice)
  31.  
  32.     return ;
  33.  
  34. #elif  ACAD2015
  35.  
  36.   // 2015 использует Mental Ray рендер. Учитываем изменения в GS API
  37.  
  38.   AcGsKernelDescriptor descriptor;
  39.  
  40.   descriptor.addRequirement (AcGsKernelDescriptor::k3DDrawing);
  41.  
  42.   AcGsGraphicsKernel *pGraphicsKernel = AcGsManager::acquireGraphicsKernel(descriptor);
  43.  
  44.   AcGsDevice *offDevice  = pGraphicsKernel->createOffScreenDevice();
  45.  
  46.   if  (! offDevice)
  47.     return ;
  48.  
  49. #else  // 2014 и более ранние используют Mental ray рендер
  50.  
  51.   AcGsClassFactory *factory = gsManager->getGSClassFactory();
  52.  
  53.   if  (! factory)
  54.     return ;
  55.  
  56.   AcGsDevice *offDevice = factory->createOffScreenDevice();
  57.  
  58.   if  (! offDevice)
  59.     return ;
  60.  
  61. #endif
  62.  
  63.  
  64.  
  65.   AcDbObjectId curVportId = AcDbObjectId::kNull;
  66.  
  67.   int  width = 10, height = 10;
  68.  
  69.  
  70.  
  71.   Adesk::IntDbId viewportObjectId;
  72.  
  73.   LONG_PTR acadWindowId;
  74.  
  75.   LONG_PTR viewportId;
  76.  
  77.  
  78.  
  79.   if  (pDb->tilemode())
  80.  
  81.   { // Пространство модели
  82.  
  83.     curVportId = acedActiveViewportId();
  84.  
  85.     struct  resbuf rb;
  86.  
  87.     int  rt = acedGetVar(_T("CVPORT" ), &rb);
  88.  
  89.     if (rt != RTNORM)
  90.  
  91.       return ;
  92.  
  93.     int  vportNum = rb.resval.rint;
  94.  
  95.  
  96.     AcDbObjectPointer<AcDbViewportTableRecord> curVTR (curVportId,AcDb::kForRead);
  97.  
  98.     if (curVTR.openStatus() == Acad::eOk)
  99.     {
  100.       curVTR.close();
  101.     }
  102.  
  103.  
  104.     int  l,r,b,t;
  105.  
  106.     acgsGetViewportInfo(vportNum,l,b,r,t);
  107.  
  108.     height = t - b - 1;
  109.  
  110.     width = r - l - 1;
  111.  
  112.     viewportObjectId = curVportId.asOldId();
  113.  
  114.     acadWindowId = vportNum;
  115.  
  116.     viewportId = curVportId.asOldId();
  117.  
  118.   }
  119.  
  120.   else 
  121.  
  122.   { // Пространство Листа, но находимся внутри Пространства Модели
  123.  
  124.     // Активируем видовой экран
  125.  
  126.     curVportId = acedGetCurViewportObjectId();
  127.  
  128.     AcDbObjectPointer<AcDbViewport> curVport (curVportId,AcDb::kForRead);
  129.  
  130.     if (curVport->number() < 2)
  131.     {
  132.       AfxMessageBox(_T("Для работы рендера Пространство Модели должно быть активно в видовом экране."));
  133.         return ;
  134.     }
  135.  
  136.     int  l,r,b,t;
  137.  
  138.     acgsGetViewportInfo(curVport->number(),l,b,r,t);
  139.  
  140.     height = t - b - 1;
  141.  
  142.     width = r - l - 1;
  143.  
  144.     viewportObjectId = curVportId.asOldId();
  145.  
  146.     acadWindowId = curVport->number();
  147.  
  148.     viewportId = curVportId.asOldId();
  149.  
  150.   }
  151.  
  152.   offDevice->onSize(width, height);
  153.  
  154.  
  155. #ifdef  ACAD2016
  156.  
  157.   AcGsClientViewInfo info;
  158.  
  159.   info.viewportId = viewportId;
  160.  
  161.   info.acadWindowId = acadWindowId;
  162.  
  163.   info.viewportObjectId = viewportObjectId;
  164.  
  165.   AcGsView* pView = gsManager2->getOffScreenView(*pGraphicsKernel, info);
  166.  
  167. #elif  ACAD2015
  168.  
  169.   AcGsView *pView = pGraphicsKernel->createView();
  170.  
  171.   if  (! pView)
  172.     return ;
  173.  
  174. #else
  175.  
  176.   AcGsView *pView = factory->createView();
  177.  
  178.   if  (! pView)
  179.     return ;
  180.  
  181. #endif
  182.  
  183.  
  184.   acgsGetViewParameters(acadWindowId, pView);
  185.  
  186.   offDevice->setDeviceRenderer(AcGsDevice::kFullRender);
  187.  
  188.   offDevice->add(pView);
  189.  
  190.   offDevice->update();
  191.  
  192. #if  defined (ACAD2016) || defined (ACAD2015)
  193.  
  194.   AcGsModel *pModel = gsManager->createAutoCADModel(*pGraphicsKernel);
  195.  
  196. #else
  197.  
  198.   AcGsModel *pModel = gsManager->createAutoCADModel();
  199.  
  200. #endif
  201.  
  202.   if  (! pModel)
  203.     return ;
  204.  
  205.   // Пространство модели
  206.  
  207.   AcDbBlockTable *pBT = NULL;
  208.   AcDbBlockTableRecord *pBTR = NULL;
  209.   AcDbObjectId msId;
  210.   pDb->getBlockTable(pBT, AcDb::kForRead);
  211.   pBT->getAt(ACDB_MODEL_SPACE, msId);
  212.   pBT->close();
  213.  
  214.   AcDbBlockTableRecordPointer spaceRec(msId, AcDb::kForRead);
  215.   if  (spaceRec.openStatus() != Acad::eOk)
  216.     return ;
  217.  
  218.   pView->add(spaceRec, pModel);
  219.   spaceRec.close();
  220.  
  221.   if  (pView != NULL)
  222.   {
  223.     pView->invalidate();
  224.     pView->update();
  225.   }
  226.  
  227.   // Получаем имя файла для вывода
  228.   struct  resbuf *result = NULL;
  229.   int  status = acedGetFileNavDialog(
  230.     _T("Визуализированное изображение" ),
  231.     NULL,
  232.     _T("jpg;png;tif;bmp" ),
  233.     _T("RenderImageDialog" ), 1, &result); 
  234.  
  235.   if  (status == RTNORM)
  236.   {
  237.     ACHAR *pFileName = result->resval.rstring;
  238.     if  (! CreateAtilImage(pView, width, height, 32, 0, pFileName))
  239.       AfxMessageBox(_T("Ошибка при создании изображения..." ));
  240.   }
  241.  
  242.   // Очищаем графическую систему
  243.   pView->eraseAll();
  244.   offDevice->erase(pView);
  245.  
  246. #if  defined (ACAD2016)
  247.  
  248.   //pGraphicsKernel->deleteView(pView);
  249.   pGraphicsKernel->deleteModel(pModel);
  250.   //pGraphicsKernel->deleteDevice(offDevice);
  251.   AcGsManager::releaseGraphicsKernel(pGraphicsKernel);
  252.  
  253. #elif  ACAD2015
  254.  
  255.   pGraphicsKernel->deleteView(pView);
  256.   pGraphicsKernel->deleteModel(pModel);
  257.   pGraphicsKernel->deleteDevice(offDevice);
  258.   AcGsManager::releaseGraphicsKernel(pGraphicsKernel);
  259.  
  260. #else
  261.  
  262.   factory->deleteView(pView);
  263.   factory->deleteModel(pModel);
  264.   factory->deleteDevice(offDevice);
  265.  
  266. #endif
  267.  
  268. }
  269.  
  270.  
  271.  
  272. #ifdef  ACAD2016
  273.  
  274. static   Acad::ErrorStatus GetActiveRapidRTRenderSetting (AcDbRapidRTRenderSettings *&pRenderSetting)
  275. {
  276.  
  277.   AcApDocument *pActiveDoc = acDocManager->mdiActiveDocument();
  278.   AcDbDatabase *pDB = pActiveDoc->database();
  279.  
  280.   AcDbDictionary *pNODContainer = NULL;
  281.  
  282.   Acad::ErrorStatus es = pDB->getNamedObjectsDictionary
  283.     (pNODContainer, AcDb::OpenMode::kForRead);
  284.  
  285.   AcDbObject *pMyDictObject = NULL;
  286.   if (pNODContainer->has(
  287.     ACRX_T("ACAD_RENDER_ACTIVE_RAPIDRT_SETTINGS" )))
  288.   {
  289.  
  290.     es = pNODContainer->getAt(ACRX_T(
  291.       "ACAD_RENDER_ACTIVE_RAPIDRT_SETTINGS" ),
  292.       pMyDictObject, AcDb::OpenMode::kForRead);
  293.     AcDbObjectId myObjectId = AcDbObjectId::kNull;
  294.  
  295.     if (es == Acad::eOk)
  296.     {
  297.  
  298.       AcDbRapidRTRenderSettings *pRapidRTActiveSetting
  299.         = AcDbRapidRTRenderSettings::cast(pMyDictObject);
  300.  
  301.       if (pRapidRTActiveSetting != NULL)
  302.       {
  303.         pRenderSetting = new  AcDbRapidRTRenderSettings();
  304.         es = pRenderSetting->copyFrom(pRapidRTActiveSetting);
  305.       }
  306.  
  307.       es = pRapidRTActiveSetting->close();
  308.  
  309.     }
  310.   }
  311.  
  312.   else
  313.  
  314.   {
  315.  
  316.     acutPrintf(
  317.       ACRX_T("ACAD_RENDER_ACTIVE_RAPIDRT_SETTINGS не найдена !!" ));
  318.  
  319.   }
  320.  
  321.   pNODContainer->close();
  322.  
  323.   return  Acad::eOk;
  324.  
  325. }
  326.  
  327.  
  328.  
  329. #else
  330.  
  331.  
  332. static   Acad::ErrorStatus GetActiveRenderSetting (AcDbMentalRayRenderSettings *&pRenderSetting)
  333. {
  334.  
  335.   AcApDocument *pActiveDoc = acDocManager->mdiActiveDocument();
  336.   AcDbDatabase *pDB = pActiveDoc->database();
  337.  
  338.   AcDbDictionary *pNODContainer = NULL;
  339.  
  340.   Acad::ErrorStatus es = pDB->getNamedObjectsDictionary
  341.     (pNODContainer, AcDb::OpenMode::kForRead);
  342.  
  343.   AcDbObject *pMyDictObject = NULL;
  344.  
  345.   if (pNODContainer->has(ACRX_T("ACAD_RENDER_ACTIVE_SETTINGS" )))
  346.   {
  347.  
  348.     es = pNODContainer->getAt(
  349.       ACRX_T("ACAD_RENDER_ACTIVE_SETTINGS" ),
  350.       pMyDictObject, AcDb::OpenMode::kForRead);
  351.  
  352.     AcDbObjectId myObjectId = AcDbObjectId::kNull;
  353.  
  354.     if (es == Acad::eOk)
  355.     {
  356.       AcDbMentalRayRenderSettings *pMentalRayActiveSetting =
  357.         AcDbMentalRayRenderSettings::cast(pMyDictObject);
  358.  
  359.       if (pMentalRayActiveSetting != NULL)
  360.       {
  361.         pRenderSetting = new  AcDbMentalRayRenderSettings();
  362.         es = pRenderSetting->copyFrom(pMentalRayActiveSetting);
  363.  
  364.       }
  365.       es = pMentalRayActiveSetting->close();
  366.     }
  367.   }
  368.  
  369.   else
  370.  
  371.   {
  372.     acutPrintf(ACRX_T("ACAD_RENDER_ACTIVE_SETTINGS не найдена !!" ));
  373.   }
  374.  
  375.   pNODContainer->close();
  376.  
  377.   return  Acad::eOk;
  378.  
  379. }
  380.  
  381. #endif
  382.  
  383. static  bool  CreateAtilImage(AcGsView *pView,
  384.   int  width, int  height,
  385.   int  colorDepth, int  paletteSize,
  386.   ACHAR *pFileName)
  387.  
  388. {
  389.  
  390.   bool  done = false ;
  391.  
  392.   AcGsDCRect screenRect(0,width-1,0, height-1);
  393.  
  394.   // Мы хотели бы иметь глубину цвета 24 или 32 бита
  395.  
  396.   if  (colorDepth < 24)
  397.     colorDepth = 24;
  398.   if  (colorDepth > 24)
  399.     colorDepth = 32;
  400.  
  401.   // Создаём rbgmodel 32 битную полноцветную
  402.  
  403.   Atil::RgbModel rgbModel(colorDepth);
  404.  
  405.   Atil::ImagePixel initialColor(rgbModel.pixelType());
  406.  
  407.   // Создаём Atil изображение в стеке
  408.  
  409.   Atil::Image imgSource (Atil::Size(width, height)&rgbModel, initialColor);
  410.  
  411.   bool  ok = false ;
  412.  
  413. #ifdef  ACAD2016 // 2016 использует Rapid RT рендер
  414.  
  415.   AcDbRapidRTRenderSettings  *pCurrentSetting = NULL;
  416.  
  417.   Acad::ErrorStatus es = GetActiveRapidRTRenderSetting(pCurrentSetting);
  418.  
  419.   if (pCurrentSetting != NULL)
  420.   {
  421.  
  422.     ok = pView->renderToImage (&imgSource, pCurrentSetting, nullptr , screenRect);
  423.     delete  pCurrentSetting;
  424.   }
  425.  
  426. #else  // 2015 и более ранние используют Mental Ray рендер
  427.  
  428.   AcDbMentalRayRenderSettings *pCurrentSetting = NULL;
  429.  
  430.   Acad::ErrorStatus es = GetActiveRenderSetting(pCurrentSetting);
  431.  
  432.   if (pCurrentSetting != NULL)
  433.   {
  434.     ok = pView->RenderToImage (&imgSource, pCurrentSetting, nullptr , screenRect);
  435.     delete  pCurrentSetting;
  436.   }
  437.  
  438. #endif
  439.  
  440.   if  (!ok)
  441.   {
  442.  
  443.     AfxMessageBox(_T("Ошибка при рендере изображения" ));
  444.  
  445.     return  false ;
  446.  
  447.   }
  448.  
  449.   else
  450.  
  451.   {
  452.  
  453.     done = WriteImageToFile(&imgSource, pFileName);
  454.  
  455.   }
  456.  
  457.   return  done;
  458.  
  459. }

Проект этого примера и чертежа с настройками визуализации можно скачать здесь:

Загрузите RTI

Загрузите Тор_2016

А это скриншот визуализированного изображения, полученный в AutoCAD 2016 при помощи рендера RapidRT:

 

Источник: http://adndevblog.typepad.com/autocad/2015/09/rendering-using-rendertoimage-api-.html

Автор перевода: Александр Ривилис

Обсуждение: http://adn-cis.org/forum/index.php?topic=4265

Опубликовано 16.02.2016
Отредактировано 16.02.2016 в 02:50:53