在类V3d_View的成员函数SetWindow中,共有两个函数原型:
1) Standard_EXPORT
void SetWindow(const Handle(Aspect_Window)& aWindow,const Aspect_RenderingContext
aContext,const Aspect_GraphicCallbackProc& aDisplayCB,const Standard_Address aClientData) ;
2) Standard_EXPORT
void SetWindow(const Handle(Aspect_Window)& IdWin) ;
对于第一个函数,各参数的含义如下:
// 引自opencascade 文档
Activates the view in the specified Window
If <acontext> is not NULL the graphic context is used
to draw something in this view.
Otherwise an internal graphic context is created.
If <adisplaycb> is not NULL then a user display CB is
call at the end of the OCC graphic traversal and just
before the swap of buffers. The <aclientdata> is pass
to this call back.
//! Warning! raises MultiplyDefined from Standard
if the view is already activated in a window.
Warning: The view is centered and resized to preserve
the height/width ratio of the window.
参数3 aDisplayCB 为一个函数指针,其函数声明为:
typedef int (* Aspect_GraphicCallbackProc )(Aspect_Drawable , void *, Aspect_GraphicCallbackStruct *)
若该回调函数指针部位null,则当在opengl的绘制过程结束前(swap buffer之前,绘制主场景之后)将会调用该函数。
参数4 aClientData 为void*,通常传入绘制窗口的指针(如CWnd*);
该回调函数的作用类似于top layer,但要灵活的多,我们可以再这里面使用opengl的所有函数。
在绘制过程中,各部分绘制的顺序如下:
// under layer
call_togl_redraw_layer2d (aview, anunderlayer);
// main scene
call_func_redraw_all_structs_proc (aview->WsId);
// top layer
call_togl_redraw_layer2d (aview, anoverlayer);
// call back func
call_subr_displayCB(aview,OCC_REDRAW_BITMAP);
在call_subr_displayCB中若SetWindow中的回调函数不为空,则执行该函数。
扩展:
上面的回调函数在场景全部绘制完成后,可以在最上层绘制其他的图元,如:
{
glDisable(GL_LIGHTING);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
glShadeModel(GL_SMOOTH);
glOrtho( left, right, bottom, top, 1.0, -1.0);
glPushAttrib (
GL_LIGHTING_BIT | GL_LINE_BIT | GL_POLYGON_BIT |
GL_DEPTH_BUFFER_BIT | GL_CURRENT_BIT|GL_COLOR_BUFFER_BIT);
glDisable (GL_DEPTH_TEST);
glBegin(GL_QUADS);
{
glColor4f(1.0, 1.0, 1.0, 1.0);
glVertex3d( 0.0, 0.0, 1.0);
glVertex3d( 10, 0.0, 1.0);
glColor4f(1.0, 1.0, 1.0, 1.0);
glVertex3d( 10, 10, 1.0);
glVertex3d( 0.0,10, 1.0);
}
glEnd();
glColor4f(1.0,0.0,0.0,1.0);
char* str = "123456";
int len = (int)strlen(str);
glRasterPos2f(10,10);
for( int i = 0; i < len ; i++ )
{
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12,str[i]);
}
glPopAttrib ();
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glFlush();
}
可以实现混合等特效。
我们同样可以加入一个同样的回调函数来实现under layer的功能,为此,为V3d_View重载函数SetWindow();函数声明为:
Standard_EXPORT void SetWindow(const Handle(Aspect_Window)& aWindow,const Aspect_RenderingContext
aContext,const Aspect_GraphicCallbackProc& aDisplayCB, const Aspect_GraphicCallbackProc&
aDisplayCB2, const Standard_Address aClientData) ;
参数4 aDisplayCB2为新加入的回调函数,其调用的位置为绘制过程刚开始的时候,为将他放在了under layer之后。
修改动的部分为:
1) V3d_View.hxx line 273
加入函数声明如上。
2) V3d_View.cxx line 254
添加函数定义, 注意函数体的区别。
3) Visual3d_View.hxx/cxx
重载函数SetWindow(),与V3d_View类似,V3d_View实际上调用Visual3d_View的SetWindow函数。
V3d_View的两个构造函数中MyCView.GContext = 0;后面添加
MyCView.GDisplayCB = 0;
初始化第二个回调函数为空。
4) InterfaceGraphic_Visual3d.hxx
修改CALL_DEF_VIEW的定义,添加成员:
Aspect_GraphicCallbackProc GDisplayCB2;
5) OpenGl_tgl_subrvis.h/c
添加函数 extern int call_subr_displayCB2(CALL_DEF_VIEW* /*aview*/, int /*reason*/ );的声明和定义。
6) OpenGl_togl_begin_immediat_mode.c line 256 func:call_togl_clear_immediat_mode
OpenGl_togl_print.c line 112 func:call_togl_print
OpenGl_togl_redraw.c
line 94 func:call_togl_redraw
line 271 func:call_togl_redraw_area
修改的内容相同,改变原来的绘制顺序为:
call_func_redraw_all_structs_begin (aview->WsId);
if (anunderlayer->ptrLayer)
call_togl_redraw_layer2d (aview, anunderlayer);
#ifdef RIC120302
call_subr_displayCB2(aview,OCC_REDRAW_WINDOWAREA);
#endif
call_func_redraw_all_structs_proc (aview->WsId);
#ifdef RIC120302
call_subr_displayCB(aview,OCC_REDRAW_WINDOWAREA);
#endif
if (anoverlayer->ptrLayer)
call_togl_redraw_layer2d (aview, anoverlayer);
call_func_redraw_all_structs_end (aview->WsId, 0);
call_togl_redraw_immediat_mode (aview);
我将回调函数的位置放在了top,under layer的中间,主要使用回调函数。
我们可以利用第二个回调函数来绘制渐变背景,从而避免opencascade绘制layer时存在的bug。
参考:http://www.opencascade.org/org/forum/thread_11428/