Fct_Draw_Stencil

 

The array of functions pointed to by Fct_Draw_Stencil[]() are used to draw in the Stencil step of the drawing process.

 

You can add your own callback to the array (you need to get an index in the array with the "Get_Callback_ID()" function). 

 

Stencil are used to protect region of the screen when they are refreshed.  As an example, the watershed lines in mode "Morpho" are drawn in the stencil buffer.  This way, we only need to redraw the lines when the complete image is redrawn.

 

There are only 8 available positions in the stencil callback array. This is because the array index is also the bit that this stencil operation will use in the stencil buffer.  For example, if the function Get_Callback_ID assign you the ID "3", this mean that when your callback will be called, the drawing operation you make will use the 3rd bit in the stencil buffer to protect your drawing.

 

 

Syntax

 

int  (*Fct_Draw_Stencil[CALLBACK_NB_STENCIL])(

          SliceO_Class *pt,

          UInt64 flag,

          SliceO_Window *window

)

 

 

Parameters

 

pt

Pointer to the class calling the function.

 

flag

Value of the Redraw_Flag.

 

window

Pointer to the window where the class is drawn.

 

 

Return value

 

This function return "1" if successful.

 

 

Remarks

 

 

 

Requirements

 

Header:

          sliceO_include.hpp

 

Library:

          sliceO_Structures.lib

 

 

Example

 

Drawing the "Morpho" watershed lines in the stencil buffer.
 

// --- in morpho_var.cpp ---

extern          unsigned char          Morpho_Line_Mode ;

extern          unsigned int          Morpho_Line_Color ;

extern          unsigned short          Morpho_Merge_Cur ;

 

// --- Callback ID assign at startup with Get_Callback_ID() ---

static unsigned short          Local_Callback_ID ;

 

// --- Callback function ---

static int          Morpho_Draw_Line( SliceO_Window *window, SliceO_Frame *ima ) ;

 

// --- in morho_ctrl.cpp ---

extern "C" __declspec(dllexport) unsigned int          Ctrl_Query( void ) ;

 

// ----------------------------------------------------------------------------

//

//          Function:          Get_Callback_ID...

//

//          Parameters:          id (unsigned short)          // Array of callback IDs

//          Returns:          (unsigned short)          // bit mask of used IDs in the array

//

//          SliceOmatic will use this function at start-up to assign a unique

//          ID number to your DLL.

//

// ----------------------------------------------------------------------------

extern "C" __declspec(dllexport) unsigned short Get_Callback_ID( unsigned short *id )

{

          Local_Callback_ID = id[CALLBACK_DRAW_STENCIL] ;

          return( 1 << CALLBACK_DRAW_STENCIL ) ;

}

 

// ----------------------------------------------------------------------------

//

//          Function:          Morpho_Callback_Register

//

//          Parameters:          (void)

//          Returns:          (int)                    0 for errors

//

//          This function will assign the "Morpho_Line" fct to the Fct_Draw_Stencil

//          of each frames in the database.

//

// ----------------------------------------------------------------------------

int          Morpho_Callback_Register( void )

{

          Morpho_Callback_Reset() ;

 

          // --- for all frames ---

          if ( ! Iterator_Init( ITERATOR_2, "Morpho_Callback_Register" ) )

              return( 0 ) ;

          while( SliceO_Frame *frame = (SliceO_Frame *) Iterator_Class( ITERATOR_2, CLASS_ID_FRAME ) ) {

              frame->Fct_Draw_Stencil[Local_Callback_ID] = Morpho_Draw_Line ;

          }

          Iterator_End( ITERATOR_2 ) ;

          return( 1 ) ;

}

 

 

// ----------------------------------------------------------------------------

//

//          Function:          Morpho_Callback_Reset

//

//          Parameters:          (void)

//          Returns:          (int)                    0 for errors

//

//          This function will assign reset the fct of the Fct_Draw_Stencil

//          of each frames in the database.

//

// ----------------------------------------------------------------------------

int          Morpho_Callback_Reset( void )

{

          // --- for all frames ---

          if ( ! Iterator_Init( ITERATOR_2, "Morpho_Callback_Register" ) )

              return( 0 ) ;

          while( SliceO_Frame *frame = (SliceO_Frame *) Iterator_Class( ITERATOR_2, CLASS_ID_FRAME ) ) {

              frame->Fct_Draw_Stencil[Local_Callback_ID] = NULL ;

          }

          Iterator_End( ITERATOR_2 ) ;

          return( 1 ) ;

}

 

// ============================================================================

// ============================================================================

// ============================================================================

// ============================================================================

// ============================================================================

 

// ----------------------------------------------------------------------------

//

//          Morpho_Draw_Line

//

//          draw the water parting lines

//

//          Param:          pt (SliceO_Class *)

//                    flag (UInt64)

//                    window (SliceO_Window *)

//

//          Return:          (int)                    

//

//          Note: the lines are drawn as a series of line segments

//

// ----------------------------------------------------------------------------

int          Morpho_Draw_Line( SliceO_Class *pt, UInt64 flag, SliceO_Window *window )

{

          // --- only draw to windows in correct mode ---

          if ( window->Module_Get() != Ctrl_Query() )

              return( 0 ) ;

 

          SliceO_Frame *frame = (SliceO_Frame *) pt ;

 

          // --- get the "merge" buffer (if it not there, get out) ---

          SliceO_Buffer *buf_morpho_merge = frame->User_Get( ID_MORPHO_MERGE + Morpho_Merge_Cur ) ;

          if ( ! buf_morpho_merge )

              return( 1 ) ;

          unsigned short **morpho_merge = (unsigned short **) buf_morpho_merge->Matrix_Get() ;

          assert( morpho_merge ) ;

 

          Access_Init( "Morpho_Draw_Line" ) ;

 

          // ====================================================================

          // We receive the "region" of the image to redraw in "Frm" space.

          // We will need to find out where on the screen this goes, and what

          // pixels from the image's data to draw.

          // ====================================================================

 

          // --- first we go get the frame's dimensions in "Frm" space. ---

          Region_2D reg_frm = *(frame->Region_Redraw_Get()) ;

 

          // --- increase the size by 1 to prevent some rounding problems later on ---

          reg_frm[0] -= 1.0f ;

          reg_frm[1] -= 1.0f ;

          reg_frm[2] += 1.0f ;

          reg_frm[3] += 1.0f ;

 

          // --- stay inside the frame ---

          Region_2D   cull_frm( COORD_FRM, 0, 0, frame->m_x-1, frame->m_y-1 ) ;

 

          // --- cull the desire redraw to the frame's dimensions ---

          if ( ! reg_frm.Cull( cull_frm ) ){

              Access_End( "Morpho_Draw_Line" ) ;

              return( 1 ) ;

          }

 

          // ====================================================================

          // ===          We cull any  part of the image is outside the window              ===

          // ====================================================================

 

          // --- so I get the size of the window in Wnd space ---

          Region_2D cull_wnd( COORD_WND, 0, 0, window->m_dim_x, window->m_dim_y ) ;

 

          // --- bring it in Inf space ---

          Region_2D cull_inf( window->Wnd_2_Inf(cull_wnd) ) ;

 

          // --- bring it in Frm space ---

          cull_frm = frame->Inf_2_Frm(window, cull_inf) ;

 

          // --- cull the frm region to the window's dimensions ---

          if ( ! reg_frm.Cull( cull_frm ) ){

              Access_End( "Morpho_Draw_Line" ) ;

              return( 1 ) ;

          }

 

          // ====================================================================

          // ===          O.K. so I need to know where the image start in Wnd space.  ===

          // ===          We may have to add 1 pixel if the starting point is outside ===

          // ===          the window (see next comment).                                            ===

          // ====================================================================

 

          short frm_start_x = ((int) reg_frm[0]) ;

          short frm_start_y = ((int) reg_frm[1]) ;

          short frm_stop_x =  ((int) reg_frm[2]) ;

          short frm_stop_y =  ((int) reg_frm[3]) ;

 

          // --- we want to draw the partial pixels on the border, so we overstep

          // the "clipped" value (but we stay inside the frame) ---

          frm_stop_x = MIN( frame->m_x, frm_stop_x + 1 ) ;

          frm_stop_y = MIN( frame->m_y, frm_stop_y + 1 ) ;

 

          // --- now we want to know the start and size of the pixels in "display" space ---

          Region_2D delta_frm(COORD_FRM) ;

          delta_frm.Set( 0, 0, 1, 1 ) ;

          Region_2D delta_inf( frame->Frm_2_Inf(window, delta_frm) ) ;

          Region_2D delta_wnd( window->Inf_2_Wnd(delta_inf) ) ;

          

          float          p_x = delta_wnd[0] ;

          float          p_y = delta_wnd[1] ;

          float          d_x = delta_wnd[2] - delta_wnd[0] ;

          float          d_y = delta_wnd[3] - delta_wnd[1] ;

 

          // --- we will draw lines between the pixels ---

          glLineWidth( 1.0f ) ;

          glColor3ub( RED_BYTE(Morpho_Line_Color),

                          GRN_BYTE(Morpho_Line_Color),

                          BLU_BYTE(Morpho_Line_Color) ) ;

 

          // --- prepare the transfo matrix to go from image index to dsp pos ---

          glMatrixMode( GL_MODELVIEW ) ;

          glPushMatrix() ;

          glTranslatef( p_x, p_y, 0.0f ) ;

          glScalef( d_x, -d_y, 0.0f ) ;

          YGL_ERROR("Morpho_Draw_Line: matrix") ;

 

          glBegin( GL_LINES ) ;

 

          for ( int j=frm_start_y; j < frm_stop_y; j++ ) {

              for ( int i=frm_start_x; i < frm_stop_x; i++ ) {

 

                    int i_p = i+1 ;

                    i_p = MIN( frame->m_x-1, i_p ) ;

                    int j_p = j+1 ;

                    j_p = MIN( frame->m_y-1, j_p ) ;

 

                    // --- vertical line ---

                    if ( morpho_merge[j][i] != morpho_merge[j][i_p] ) {

                        glVertex2i( i+1, j-1 ) ;

                        glVertex2i( i+1, j ) ;

                    }

 

                    // --- horizontal line ---

                    if ( morpho_merge[j][i] != morpho_merge[j_p][i] ) {

                        glVertex2i( i,   j ) ;

                        glVertex2i( i+1, j ) ;

                    }

              }

          }

          glEnd() ;

          YGL_ERROR("Morpho_Draw_Line: glBegin/End") ;

 

          glPopMatrix() ;

          YGL_ERROR("Morpho_Draw_Line: matrix") ;

          glLineWidth( 1.0f ) ;

 

          Access_End( "Morpho_Draw_Line" ) ;

 

          return( 1 ) ;

}

 

See also