Update of /cvsroot/playerstage/code/stage/libstage
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16951
Added Files:
Tag: opengl
canvas.cc
Log Message:
added missing file
--- NEW FILE: canvas.cc ---
#include "stage.hh"
#include <FL/fl_draw.H>
#include <FL/fl_Box.H>
#include <FL/Fl_Menu_Button.H>
void StgCanvas::TimerCallback( StgCanvas* c )
{
c->redraw();
Fl::repeat_timeout(((double)c->interval/1000),
(Fl_Timeout_Handler)StgCanvas::TimerCallback,
c);
}
StgCanvas::StgCanvas( StgWorld* world, int x, int y, int w, int h)
: Fl_Gl_Window(x,y,w,h)
{
end();
show(); // must do this so that the GL context is created before configuring
GL
this->world = world;
selected_models = NULL;
last_selection = NULL;
startx = starty = 0;
panx = pany = stheta = sphi = 0.0;
scale = 15.0;
interval = 100; //msec between redraws
graphics = true;
dragging = false;
rotating = false;
showflags = STG_SHOW_CLOCK | STG_SHOW_DATA | STG_SHOW_BLOCKS | STG_SHOW_GRID;
// start the timer that causes regular redraws
Fl::add_timeout( ((double)interval/1000),
(Fl_Timeout_Handler)StgCanvas::TimerCallback,
this);
}
StgCanvas::~StgCanvas()
{
}
StgModel* StgCanvas::Select( int x, int y )
{
// render all models in a unique color
make_current(); // make sure the GL context is current
glClearColor ( 0,0,0,1 );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glDisable(GL_DITHER);
// render all top-level, draggable models in a color that is their
// id + a 100% alpha value
for( GList* it=world->children; it; it=it->next )
{
StgModel* mod = (StgModel*)it->data;
if( mod->gui_mask & (STG_MOVE_TRANS | STG_MOVE_ROT ))
{
uint32_t col = (mod->id | 0xFF000000);
glColor4ubv( (GLubyte*)&col );
mod->DrawPicker();
}
}
// read the color of the pixel in the back buffer under the mouse
// pointer
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT,viewport);
uint32_t id;
glReadPixels( x,viewport[3]-y,1,1,
GL_RGBA,GL_UNSIGNED_BYTE,(void*)&id );
// strip off the alpha channel byte to retrieve the model id
id &= 0x00FFFFFF;
StgModel* mod = (StgModel*)
g_hash_table_lookup( world->models_by_id, &id );
//printf("%p %s %d\n", mod, mod ? mod->Token() : "", id );
glEnable(GL_DITHER);
glClearColor ( 0.7, 0.7, 0.8, 1.0);
if( mod ) // we clicked on a root model
{
// if it's already selected
if( GList* link = g_list_find( selected_models, mod ) )
{
// remove it from the selected list
selected_models =
g_list_remove_link( selected_models, link );
mod->disabled = false;
}
else
{
last_selection = mod;
selected_models = g_list_prepend( selected_models, mod );
mod->disabled = true;
}
invalidate();
}
return mod;
}
// convert from 2d window pixel to 3d world coordinates
void StgCanvas::CanvasToWorld( int px, int py,
double *wx, double *wy, double* wz )
{
int viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
GLdouble modelview[16];
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
GLdouble projection[16];
glGetDoublev(GL_PROJECTION_MATRIX, projection);
GLfloat pz;
glReadPixels( px, h()-py, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &pz );
gluUnProject( px, w()-py, pz, modelview, projection, viewport, wx,wy,wz );
}
int StgCanvas::handle(int event)
{
switch(event)
{
case FL_MOUSEWHEEL:
if( selected_models )
{
// rotate all selected models
for( GList* it = selected_models; it; it=it->next )
{
StgModel* mod = (StgModel*)it->data;
mod->AddToPose( 0,0,0, 0.1*(double)Fl::event_dy() );
}
redraw();
}
else
{
scale -= 0.5 * (double)Fl::event_dy();
if( scale < 1 )
scale = 1;
//if( width
invalidate();
}
return 1;
case FL_MOVE: // moused moved while no button was pressed
if( Fl::event_state( FL_CTRL ) )
{
int dx = Fl::event_x() - startx;
int dy = Fl::event_y() - starty;
stheta -= 0.01 * (double)dy;
sphi += 0.01 * (double)dx;
stheta = constrain( stheta, 0, M_PI/2.0 );
invalidate();
}
else if( Fl::event_state( FL_ALT ) )
{
int dx = Fl::event_x() - startx;
int dy = Fl::event_y() - starty;
panx -= dx;
pany += dy;
invalidate();
}
startx = Fl::event_x();
starty = Fl::event_y();
return 1;
case FL_PUSH: // button pressed
switch( Fl::event_button() )
{
case 1:
startx = Fl::event_x();
starty = Fl::event_y();
if( Select( startx, starty ) )
dragging = true;
return 1;
case 3:
{
puts( "button 3" );
startx = Fl::event_x();
starty = Fl::event_y();
if( Select( startx, starty ) )
{
printf( "rotating" );
rotating = true;
}
return 1;
}
default:
return 0;
}
case FL_DRAG: // mouse moved while button was pressed
{
int dx = Fl::event_x() - startx;
int dy = Fl::event_y() - starty;
switch( Fl::event_button() )
{
case 1:
if( dragging )
{
assert(selected_models);
double sx,sy,sz;
CanvasToWorld( startx, starty,
&sx, &sy, &sz );
double x,y,z;
CanvasToWorld( Fl::event_x(), Fl::event_y(),
&x, &y, &z );
// move all selected models to the mouse pointer
for( GList* it = selected_models; it; it=it->next )
{
StgModel* mod = (StgModel*)it->data;
mod->AddToPose( x-sx, y-sy, 0, 0 );
}
}
else
{
panx -= dx;
pany += dy;
invalidate(); // so the projection gets updated
}
break;
case 3: // right button
if( rotating )
{
// move all selected models to the mouse pointer
for( GList* it = selected_models; it; it=it->next )
{
StgModel* mod = (StgModel*)it->data;
mod->AddToPose( 0,0,0, 0.05*dx );
}
}
break;
}
}
startx = Fl::event_x();
starty = Fl::event_y();
return 1; // end case FL_DRAG
case FL_RELEASE: // mouse button released
// unselect everyone unless shift is pressed
if( ! Fl::event_state( FL_SHIFT ) )
{
for( GList* it=selected_models; it; it=it->next )
((StgModel*)it->data)->disabled = false;
g_list_free( selected_models );
selected_models = NULL;
dragging = false;
rotating = false;
redraw();
}
return 1;
case FL_FOCUS :
case FL_UNFOCUS :
//.... Return 1 if you want keyboard events, 0 otherwise
return 1;
case FL_KEYBOARD:
switch( Fl::event_key() )
{
case 'p': // pause
world->paused = !world->paused;
break;
case ' ': // space bar
sphi = stheta = 0.0;
invalidate();
break;
case FL_Left: panx += 10; break;
case FL_Right: panx -= 10; break;
case FL_Down: pany += 10; break;
case FL_Up: pany -= 10; break;
default:
return 0; // keypress unhandled
}
invalidate(); // update projection
return 1;
//case FL_SHORTCUT:
///... shortcut, key is in Fl::event_key(), ascii in Fl::event_text()
// ... Return 1 if you understand/use the shortcut event, 0 otherwise...
//return 1;
default:
// pass other events to the base class...
//printf( "EVENT %d\n", event );
return Fl_Gl_Window::handle(event);
}
}
void StgCanvas::FixViewport(int W,int H)
{
glLoadIdentity();
glViewport(0,0,W,H);
}
void StgCanvas::draw()
{
if (!valid())
{
valid(1);
FixViewport(w(), h());
// set gl state that won't change every redraw
glClearColor ( 0.7, 0.7, 0.8, 1.0);
glDisable(GL_LIGHTING);
glEnable (GL_DEPTH_TEST);
glDepthFunc (GL_LESS);
glCullFace( GL_BACK );
glEnable (GL_CULL_FACE);
glEnable( GL_BLEND );
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glEnable( GL_LINE_SMOOTH );
glHint (GL_LINE_SMOOTH_HINT, GL_FASTEST);
glDepthMask(GL_TRUE);
// install a font
gl_font( FL_HELVETICA, 12 );
// glClearColor ( 0.7, 0.7, 0.8, 1.0);
// glDisable(GL_LIGHTING);
// glEnable (GL_DEPTH_TEST);
// glDepthFunc (GL_LESS);
// glCullFace( GL_BACK );
// glEnable (GL_CULL_FACE);
// glEnable( GL_BLEND );
// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
// glEnable( GL_LINE_SMOOTH );
// glHint (GL_LINE_SMOOTH_HINT, GL_FASTEST);
// glDepthMask(GL_TRUE);
// install a font
// gl_font( FL_HELVETICA, 12 );
double zclip = hypot(world->width, world->height) * scale;
double pixels_width = w();
double pixels_height = h();
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
// map the viewport to pixel units by scaling it the same as the window
glOrtho( -pixels_width/2.0, pixels_width/2.0,
-pixels_height/2.0, pixels_height/2.0,
0, zclip );
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
glTranslatef( -panx,
-pany,
-zclip / 2.0 );
glRotatef( RTOD(-stheta), 1,0,0);
//glTranslatef( -panx * cos(sphi) - pany*sin(sphi),
// panx*sin(sphi) - pany*cos(sphi), 0 );
glRotatef( RTOD(sphi), 0.0, 0.0, 1.0); // rotate about z - pitch
// meter scale
glScalef ( scale, scale, scale ); // zoom
}
// Clear screen to bg color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
if( (showflags & STG_SHOW_FOLLOW) && last_selection )
{
glLoadIdentity ();
double zclip = hypot(world->width, world->height) * scale;
glTranslatef( 0,0,
-zclip / 2.0 );
// meter scale
glScalef ( scale, scale, scale ); // zoom
stg_pose_t gpose;
last_selection->GetGlobalPose( &gpose );
// and put it in the center of the window
glTranslatef( -gpose.x, -gpose.y, 0 );
}
// draw the world size rectangle in white, using the polygon offset
// so it doesn't z-fight with the models
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.0, 1.0);
glColor3f( 1,1,1 );
glRectf( -world->width/2.0, -world->height/2.0,
world->width/2.0, world->height/2.0 );
glDisable(GL_POLYGON_OFFSET_FILL);
if( (showflags & STG_SHOW_QUADTREE) || (showflags & STG_SHOW_OCCUPANCY) )
{
glDisable( GL_LINE_SMOOTH );
glLineWidth( 1 );
glPushMatrix();
glTranslatef( -world->width/2.0, -world->height/2.0, 1 );
glScalef( 1.0/world->ppm, 1.0/world->ppm, 0 );
glPolygonMode( GL_FRONT, GL_LINE );
colorstack.Push(1,0,0);
if( showflags & STG_SHOW_OCCUPANCY )
world->bgrid->Draw( false );
if( showflags & STG_SHOW_QUADTREE )
world->bgrid->Draw( true );
colorstack.Pop();
glPopMatrix();
glEnable( GL_LINE_SMOOTH );
}
colorstack.Push( 1, 0, 0 );
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glLineWidth( 4 );
for( GList* it=selected_models; it; it=it->next )
{
((StgModel*)it->data)->DrawSelected();
// ((StgModel*)it->data)->DrawPicker();
}
colorstack.Pop();
glLineWidth( 1 );
// draw the models
GList* it;
if( showflags ) // if any bits are set there's something to draw
for( it=world->children; it; it=it->next )
((StgModel*)it->data)->Draw( showflags );
if( showflags && STG_SHOW_CLOCK )
redraw_overlay();
}
void StgCanvas::draw_overlay()
{
char clockstr[50];
world->ClockString( clockstr, 50 );
glPushMatrix();
glLoadIdentity();
colorstack.Push( 0,0,0 ); // black
gl_draw( clockstr, -w()/2.0 + 5, -h()/2 + 5 );
colorstack.Pop();
glPopMatrix();
}
void StgCanvas::resize(int X,int Y,int W,int H)
{
Fl_Gl_Window::resize(X,Y,W,H);
FixViewport(W,H);
invalidate();
}
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Playerstage-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit