找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 1203|回复: 1

[分享] 解决ARX自定义实体类viewportDraw显示问题

[复制链接]

已领礼包: 13个

财富等级: 恭喜发财

发表于 2016-9-27 23:35:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×

问题描述:

在自定义实体的viewportDraw里绘制与视图相关的显示,为什么运行3dorbit(三维动态观察)时不显示,退出3dorbit后显示又正常?

经反复测试,创建自定义实体后,只要调用了修改自定义实体属性的函数,相应的实体在运行3dorbit命令过程中就不会显示

  1. <b>Issue</b>

  2. Our custom entity does all its drawing in the ViewportDraw routine, but if you display one of our entities on a 'SHADEMODE' view (Hide/Flat/Gouraud etc.) then the entity does not appear. Changing back to 2D displays the entity properly.  Why doesn't our entity display properly in SHADEMODE?

  3. <b>Solution</b>

  4. There are several problems related to this issue which make this a difficult area to develop with.  These problems are present in AutoCAD 2000i, 2002, 2004, 2005, 2006 and 2007 but not in R2000.

  5. Here is a summary of them, and a brief description of each workaround, which is demonstrated below:

  6. 1) If graphics are created from within viewportDraw() (ie worldDraw() returns false), the kDrawableViewIndependentViewportDraw flag must be set within setAttributes() in order to see any custom entity graphics when in a SHADEMODE other than 2D Wireframe.  This applies not only for viewport-independent graphics, but also for viewport-dependent graphics.  This is related to Change Request 282888 and has been fixed for AutoCAD 2004 upwards.

  7. 2)  When in a SHADEMODE other than 2D wireframe, viewportDraw() will be called with the incorrect regenType() intermittently, so that when zooming or panning (among other operations), the graphics will appear to switch at random.  This is Change Request 168103.  A workaround to determine the regenType() manually can be implemented by simply trying to create an AcGsView with acgsGetGsView(), which will fail in 2D shademode, but succeed in any other mode.

  8. Note that acgsGetGsView() is part of the ObjectARX SDK (not ObjectDBX) and therefore care should be taken to get the module handle of acad.exe then get proc address - don't link your DBX to the ObjectARX SDK (See code below)

  9. 3)  When in a SHADEMODE other than 2D wireframe, AcGiViewportDraw::viewDir() will always return (0,0,1) when the regenType() is kAcGiRenderCommand (which again is intermittent).  The view direction must be calculated via AcGsView::position() and AcGsView::target().  See code workaround below. This is Change Request 136908.

  10. 4)  If while in SHADEMODE the graphics representation is changed (eg from 3d to 2d or vice versa), the 3D graphics queue must be flushed.  Even a Regen command will not always update these graphics, but AcGsView::invalidateCachedViewportGeometry() (or AcGsModel::invalidate()) does this properly.  This is not necessary when SHADEMODE is 2D wireframe.  This is by design, but is not well documented.
复制代码


Solution to Problem 1 (code)

  1. // Within the custom entity, add the kDrawableViewIndependentViewportDraw flag to
  2. // the base-class version of setAttributes()...
  3. Adesk::UInt32 Cline::setAttributes(AcGiDrawableTraits* pTraits)
  4. {
  5.     return AcDbEntity::setAttributes(pTraits) | kDrawableViewIndependentViewportDraw;
  6. }

Solution to Problem 2 (code)

  1. // tries to get the gsView from autocad. It's fine to do this in non AutoCAD
  2. // applications because if AutoCAD doesn't exist, we simply don't do anything
  3. AcGsView *GetGsView(AcGiViewportDraw *mode)
  4. {
  5.     // see if we are running inside of autocad
  6.     HMODULE hMod = ::GetModuleHandle(_T("acad.exe"));
  7.     // if we are
  8.     if(hMod)
  9.     {
  10.         // prepare a function pointer to get the AcGsView.
  11.         typedef AcGsView* (*exp_acgsGetGsView)(int, bool);
  12.         // try to get the function pointer to acgsGetGsView
  13.         exp_acgsGetGsView funcPtr = (exp_acgsGetGsView)::GetProcAddress(hMod, "?acgsGetGsView@@YAPAVAcGsView@@H_N@Z");
  14.         // If this was successful, we can assume that we can use it.
  15.         if(funcPtr)
  16.             // all ok, return the AcGsView
  17.             return funcPtr(mode->viewport().acadWindowId(), false);
  18.     }
  19.    
  20.     return NULL;
  21. }
  22. Solution to Problem 3 (code)
  23. // function to determine the view direction.
  24. AcGeVector3d GetViewDirection(AcGiViewportDraw *mode)
  25. {
  26.     // try and extract the acgsview
  27.     AcGsView *pView = GetGsView(mode);  
  28.     // if ok and in 3D view - we must calc our own view direction
  29.     if (pView)
  30.         // if 3D view, then we must calc our own...
  31.         return (pView->position()-pView->target()).normalize();
  32.     else
  33.         // otherwise, the viewdir must be ok
  34.         return mode->viewport().viewDir().normalize();
  35. }

  36. // Here is the overridden viewportDraw() which includes the remaining workarounds...
  37. void Cline::viewportDraw(AcGiViewportDraw* mode)
  38. {
  39.     // Try to obtain an AcGsView for the current viewport...this will fail if it is a 2D wireframe (normal) view or if not running in AutoCAD
  40.     // (will set pView to NULL.)
  41.     AcGsView *pView = GetGsView(mode); // This will solve problem 2
  42.     // You can detect if there is a conflict (ie the defect is present) like this:
  43.     if (pView && mode->regenType() == kAcGiStandardDisplay)
  44.         acutPrintf("Conflict in regen type ");
  45.    
  46.     // This is to workaround Change Request 136908...the viewDir is incorrect for regenType kRenderCommand...
  47.     // We can calculate the view direction ourselves for a 3D view.  .
  48.     AcGeVector3d vDir = GetViewDirection(mode); // This will solve problem 3
  49.    
  50.     // Draw your graphics here...perhaps they are drawn differently depending on 2D or 3D modes...
  51.    
  52.    
  53.     // You must invalidate the 3D graphics cache if your graphics change between 2D and 3D modes.  
  54.     // Perhaps this can be done within an Editor Reactor which detects when the SHADEMODE
  55.     // command ends, and place the call to invalidateCachedViewportGeometry() there, but of course
  56.     // that would require ObjectARX. Instead you can place the following code in the viewportDraw()
  57.     // function, note that it will cause the function to be called twice anytime an update is needed
  58.     // (This may be a small price to pay however).  
  59.    
  60.     if(pView)
  61.     {
  62.         pView->invalidateCachedViewportGeometry(); // This will solve problem 4
  63.         
  64.         // The following code also works for this purpose:
  65.         //AcGsModel *gsModel=acgsGetGsManager()->getDBModel();
  66.         //gsModel->invalidate(AcGsModel::kInvalidateViewportCache);
  67.     }
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

已领礼包: 112个

财富等级: 日进斗金

发表于 2016-10-1 09:14:57 | 显示全部楼层
谢谢楼主分享
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-5-26 13:48 , Processed in 0.329122 second(s), 30 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表