解决ARX自定义实体类viewportDraw显示问题 - 口吕品的专栏 - CSDNBl...

来源:百度文库 编辑:神马文学网 时间:2024/10/06 18:45:52

问题描述:

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

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

Issue

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?

Solution

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. 

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

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.

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.

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)

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.

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)

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

Solution to Problem 2 (code)

 

// tries to get the gsView from autocad. It's fine to do this in non AutoCAD
// applications because if AutoCAD doesn't exist, we simply don't do anything
AcGsView *GetGsView(AcGiViewportDraw *mode)
{
    // see if we are running inside of autocad
    HMODULE hMod = ::GetModuleHandle(_T("acad.exe"));
    // if we are
    if(hMod)
    {
        // prepare a function pointer to get the AcGsView.
        typedef AcGsView* (*exp_acgsGetGsView)(int, bool); 
        // try to get the function pointer to acgsGetGsView
        exp_acgsGetGsView funcPtr = (exp_acgsGetGsView)::GetProcAddress(hMod, "?acgsGetGsView@@YAPAVAcGsView@@H_N@Z");
        // If this was successful, we can assume that we can use it.
        if(funcPtr)
            // all ok, return the AcGsView
            return funcPtr(mode->viewport().acadWindowId(), false);
    }
    
    return NULL;
}

Solution to Problem 3 (code) 

// function to determine the view direction.
AcGeVector3d GetViewDirection(AcGiViewportDraw *mode)
{
    // try and extract the acgsview
    AcGsView *pView = GetGsView(mode);  
    // if ok and in 3D view - we must calc our own view direction 
    if (pView) 
        // if 3D view, then we must calc our own... 
        return (pView->position()-pView->target()).normalize(); 
    else 
        // otherwise, the viewdir must be ok
        return mode->viewport().viewDir().normalize();
}

 

// Here is the overridden viewportDraw() which includes the remaining workarounds...
void Cline::viewportDraw(AcGiViewportDraw* mode)

    // 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
    // (will set pView to NULL.)
    AcGsView *pView = GetGsView(mode); // This will solve problem 2
    // You can detect if there is a conflict (ie the defect is present) like this:
    if (pView && mode->regenType() == kAcGiStandardDisplay)
        acutPrintf("Conflict in regen type ");
    
    // This is to workaround Change Request 136908...the viewDir is incorrect for regenType kRenderCommand...
    // We can calculate the view direction ourselves for a 3D view.  .
    AcGeVector3d vDir = GetViewDirection(mode); // This will solve problem 3
    
    // Draw your graphics here...perhaps they are drawn differently depending on 2D or 3D modes...
    
    
    // You must invalidate the 3D graphics cache if your graphics change between 2D and 3D modes.  
    // Perhaps this can be done within an Editor Reactor which detects when the SHADEMODE
    // command ends, and place the call to invalidateCachedViewportGeometry() there, but of course
    // that would require ObjectARX. Instead you can place the following code in the viewportDraw()
    // function, note that it will cause the function to be called twice anytime an update is needed
    // (This may be a small price to pay however).  
    
    if(pView)
    {
        pView->invalidateCachedViewportGeometry(); // This will solve problem 4
        
        // The following code also works for this purpose:
        //AcGsModel *gsModel=acgsGetGsManager()->getDBModel();
        //gsModel->invalidate(AcGsModel::kInvalidateViewportCache);
    }
解决ARX自定义实体类viewportDraw显示问题 - 口吕品的专栏 - CSDNBl... arx删除实体 ARX面试 - gyssoft的专栏 - CSDNBlog symbian中文字符串显示问题的解决(转载) - bodybo的专栏 - CSDNBlo... 使用Rundll32.exe和Rundll.exe - rjren的专栏 - CSDNBl... 架构平台 - kevin的专栏&&Inter Kakas' NO.21 - CSDNBl... 使用Rundll32.exe和Rundll.exe - rjren的专栏 - CSDNBl... 解决 Java 应用程序的中文显示及中文输入问题 安装moodle,中文显示乱码问题的完美解决 清理任务栏自定义通知,解决宽带上网任务栏有两个网络连接图标的问题 关于自定义标记的问题 windows下进程间通信的手段有哪些? - tanliyoung的专栏 - CSDNBl... 一些网络协议的定义和内容(如Http等) - joephoenix的专栏 - CSDNBl... 一些网络协议的定义和内容(如Http等) - joephoenix的专栏 - CSDNBl... windows下进程间通信的手段有哪些? - tanliyoung的专栏 - CSDNBl... 编译chm格式PHP手册 - Haohappy的专栏--PHP5研究中心 - CSDNBl... 《Java与模式》学习笔记:设计模式——原则 - shanchao的专栏 - CSDNBl... WinCE BSP工程文件pbcxml分析 - ARM-WinCE的专栏 - CSDNBl... 编译chm格式PHP手册 - Haohappy的专栏--PHP5研究中心 - CSDNBl... WinCE BSP工程文件pbcxml分析 - ARM-WinCE的专栏 - CSDNBl... 谈谈职业规划——陈皓的采访 - 陈皓专栏 【空谷幽兰,心如皓月】 - CSDNBl... 怎样解决卖淫问题?李银河专栏 Keil C51汉字显示的bug问题 - willhu2008的专栏 - CSDN博客 如何解决chm格式文件无法显示问题