|
// --- 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 ) ;
}
|