Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

gl_view.C

Go to the documentation of this file.
00001 #include "std/support.H"
00002 #include "glew/glew.H"
00003 
00004 #include "disp/animator.H"
00005 #include "disp/colors.H"
00006 #include "geom/gl_view.H"
00007 #include "geom/geom.H"
00008 #include "disp/recorder.H"
00009 #include "std/thread_mutex.H" 
00010 
00011 using namespace mlib;
00012 
00013 static bool multithread = Config::get_var_bool("JOT_MULTITHREAD",false);
00014 
00015 static ThreadMutex polyextmutex;
00016 static ThreadMutex gl_version_mutex;
00017 static Cstr_ptr in_swap_buffers("GL_VIEW::swap_buffers");
00018 
00019 bool    GL_VIEW::_checked_point_sizes = false;
00020 bool    GL_VIEW::_checked_line_widths = false;
00021 GLfloat GL_VIEW::_min_point_size = 0;
00022 GLfloat GL_VIEW::_max_point_size = 0;
00023 GLfloat GL_VIEW::_min_line_width = 0;
00024 GLfloat GL_VIEW::_max_line_width = 0;
00025 
00026 void
00027 GL_VIEW::load_proj_mat(CAMdata::eye e)
00028 {
00029    glLoadMatrixd(_view->wpt_proj(_view->screen(),e).transpose().matrix());
00030 }
00031 
00032 void
00033 GL_VIEW::load_cam_mat(CAMdata::eye e)
00034 {
00035    CCAMdataptr &camdata = ((CVIEWptr &) _view)->cam()->data();
00036    glLoadMatrixd(camdata->xform(_view->screen(), e).transpose().matrix());
00037 }
00038 
00039 /* ------------------ GL_VIEW static class definitions --------------------- */
00040 
00041 /*
00042  *  paint() - initializes GL for drawing, then draws all the objects
00043  *            (twice for stereo),  then invokes each stencil callback
00044  *            which may draw additional objects through a stencil mask.
00045  *      
00046  *       draw_setup()
00047  *          clear_buffer()       // clear display and call clear cb's
00048  *          setup stencil()      // initialize stencil masks
00049  *          setup scissor()      // scissor drawing to a sub-region of display
00050  *       draw_frame()            // draw display frame (twice for stereo, etc)
00051  *          draw_objects()       // draw all objects
00052  *          stencil_cbs()        // draw each stencil (call callback)
00053  *             stencil_draw()    // setup stencil mask
00054  *                draw_objects() // draw stencil-specific objects
00055  *       swap_buffers()          // unless synching with other displays
00056  */
00057 
00058 int
00059 GL_VIEW::paint()
00060 {
00061    int width, height;
00062    _view->get_size(width, height);
00063    int tris = 0;
00064 
00065    if ((!multithread && (VIEWS.num()>1)) ||
00066        _view->win()->needs_context()) 
00067    {   
00068       _view->win()->set_context(); // XXX Should only happen if > 1 view
00069    }
00070 
00071    if (_resizePending) 
00072    {
00073       _paintResize = true;
00074       set_size(_resizeW, _resizeH, _resizeX, _resizeY);
00075    }
00076 
00077    // Only draw the scene if we're not rendering to disk
00078    // Otherwise, the post_draw_cb with draw...
00079    Animator *anim = _view->animator();
00080    if (!(anim->on() && anim->play_on() && anim->rend_on()))
00081    {
00082       draw_setup();
00083 
00084       // Window may need to perform custom-rendering (e.g., to draw a cursor)
00085       _view->win()->draw();
00086 
00087       switch (_view->stereo()) {
00088        default              : cerr << "Unknown stereo mode in GL_VIEW.C" << endl;
00089        brcase NONE          : tris += draw_frame();
00090        brcase LEFT_EYE_MONO : tris += draw_frame(CAMdata::LEFT);
00091        brcase RIGHT_EYE_MONO: tris += draw_frame(CAMdata::RIGHT);
00092        brcase TWO_BUFFERS   : glDrawBuffer(GL_BACK_RIGHT);
00093                               tris += draw_frame(CAMdata::RIGHT);
00094                               glClear(GL_DEPTH_BUFFER_BIT);
00095                               glDrawBuffer(GL_BACK_LEFT);
00096                               tris += draw_frame(CAMdata::LEFT);
00097        brcase HMD: case LCD: {
00098           static const int RADJUST = Config::get_var_int("RADJUST",0,true);
00099           static const int LADJUST = Config::get_var_int("LADJUST",0,true);
00100           // used on POSSE w/ the black and yellow HMD
00101           // Stereo - must draw all the objects twice, once for each eye
00102           glViewport((GLsizei) (0),                 // top-window (right eye)
00103                      (GLsizei) (height/2+20+RADJUST),
00104                      (GLsizei) (width - 1),
00105                      (GLsizei) (height/2-21));
00106           tris += draw_frame(CAMdata::RIGHT);
00107      
00108           glViewport((GLsizei) (0),                 // bot-window (left eye)
00109                      (GLsizei) (0 + 20 + LADJUST),
00110                      (GLsizei) (width - 1),
00111                      (GLsizei) (height/2-21));
00112           tris += draw_frame(CAMdata::LEFT);
00113        }
00114       }
00115    }
00116 
00117    if (_focusPending) 
00118    {
00119       _view->win()->set_focus();
00120       _focusPending = false;
00121    }
00122 
00123 // HACK CITY
00124 //   if (!_view->dont_swap() || Config::get_var_bool("ASYNCH",false,true))
00125 //      swap_buffers();
00126    return tris;
00127 }
00128 
00129 /*
00130  * draw_setup() - initializes GL for the upcoming display update.
00131  *   initialization includes, setting the drawing buffer,
00132  *   configuring the Zbuffer, clearing to a background color,
00133  *   and configuring the stencil buffers and scissor regions.
00134  */
00135 void
00136 GL_VIEW::draw_setup()
00137 {
00138    // Initialization
00139    glDepthMask(GL_TRUE);
00140    glDepthFunc(GL_LEQUAL);
00141    glEnable(GL_DEPTH_TEST);
00142 
00143    // setup correct buffer, and clear its color & depth data.
00144    clear_draw_buffer();
00145 
00146    // initialize stencil mask for each registered stencil cb
00147    if (_view->stencil_cbs().num())
00148       setup_stencil();
00149    else
00150       glDisable(GL_STENCIL_TEST);
00151 
00152    // setup scissor region if applicable
00153    if (_view->has_scissor_region())
00154       setup_scissor();
00155 }
00156 
00157 /*
00158  * draw_frame() - draws all objects and stencils 
00159  *   this paints a complete display frame by drawing all the active
00160  * objects and all the active stencils.   The stencil_cbs() will
00161  * call stencil_draw() to actually paint on the display.
00162  */
00163 int
00164 GL_VIEW::draw_frame(
00165    CAMdata::eye  e
00166    )
00167 {
00168    int tris = draw_objects(_view->drawn(), e);
00169 
00170    if (_view->stencil_cbs().num())
00171       for (int i = 0; i < _view->stencil_cbs().num(); i++)
00172          tris += _view->stencil_cbs()[i]->stencil_cb();
00173 
00174    return tris;
00175 }
00176 
00177 
00178 //
00179 // Do whatever is needed at the end of drawing
00180 //
00181 void
00182 GL_VIEW::swap_buffers()
00183 {
00184 
00185    if (_view->has_scissor_region())
00186       glDisable(GL_SCISSOR_TEST);
00187 
00188    if (_view->win()->double_buffered())
00189       _view->win()->swap_buffers();
00190    else
00191       glFlush();
00192 
00193    print_gl_errors(in_swap_buffers);
00194 }
00195 
00196 void
00197 GL_VIEW::clear_draw_buffer()
00198 {
00199    if (_view->win()->double_buffered())
00200       glDrawBuffer(GL_BACK);
00201    else
00202       glDrawBuffer(GL_FRONT);
00203 
00204    // Set background color for clear
00205    if (_view->rendering() == RCOLOR_ID) {
00206       glClearColor(0, 0, 0, 0);
00207    } else {
00208       COLOR bkg(_view->color());
00209       //use the view's new _alpha?
00210       glClearColor((float)bkg[0], (float)bkg[1], (float)bkg[2], 0);
00211    }
00212 
00213    // Clear the color & depth buffers.
00214    // NOTE: If using a stereo mode, GL is supposed to clear both the
00215    // back left & back right buffers if glDrawBuffer(..) is set to GL_BACK.
00216    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00217 
00218    _view->notify_clearobs();
00219 }
00220 
00221 /*
00222  * setup_stencil() - initializes GL stencil planes
00223  *    the VIEW supports a list of stencil callbacks.  Each stencil 
00224  * callback is defines a polygon region on the display surface
00225  * that it alone can paint.  Thus, before rendering anything onto
00226  * the display, this routine asks each stencil callback for the 
00227  * display region that it uses.   For each such region, this 
00228  * routine sets a stencil mask that enables only the corresponding 
00229  * stencil cb to draw there.
00230  */
00231 void
00232 GL_VIEW::setup_stencil()
00233 {
00234    glEnable(GL_STENCIL_TEST);
00235    glClearStencil(0x0);
00236    glClear(GL_STENCIL_BUFFER_BIT);
00237 
00238    // Set up stencil buffer
00239 
00240    // First, set up orthogonal projection (-1 to 1 in x and y)
00241    glMatrixMode(GL_PROJECTION);
00242    glPushMatrix();
00243    glLoadMatrixd(_view->xypt_proj().transpose().matrix());
00244 
00245    glMatrixMode(GL_MODELVIEW);
00246    glPushMatrix();
00247    glLoadIdentity();
00248 
00249    XYpt_list pts;
00250    for (int i = 0; i < _view->stencil_cbs().num(); i++) {
00251       // Get bounds of the requested stencil buffer
00252       _view->stencil_cbs()[i]->stencil_bounds(pts);
00253 
00254       // Now, set up the stencil buffer
00255       // The stencil buffer will be set to i+1 where the following
00256       // rectangle(s) are drawn
00257       glStencilFunc(GL_ALWAYS, (GLint) i + 1, 0x127);
00258       glStencilOp  (GL_REPLACE, GL_REPLACE, GL_REPLACE);
00259       glDisable    (GL_LIGHTING);
00260       glBegin(GL_QUADS);
00261     for (int p = 0;  p < pts.num(); p++)
00262        glVertex2dv(pts[p].data());
00263       glEnd();
00264    }
00265 
00266    // Only draw where stencil buffer *is* 0 (where no rectangles were
00267    // drawn)
00268    glStencilFunc(GL_EQUAL, 0x0, (GLuint) 127);
00269    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
00270 
00271    glPopMatrix();               // Restore modelview matrix
00272    glMatrixMode(GL_PROJECTION); // Switch to projection matrix
00273    glPopMatrix();               // Restore projection matrix
00274 }
00275 
00276 /* 
00277  * setup_scissor() - clips drawing to a sub-region of display
00278  */
00279 void
00280 GL_VIEW::setup_scissor()
00281 {
00282    PIXEL lower_left (XYpt(_view->scissor_xmin(),-1));
00283    PIXEL upper_right(XYpt(_view->scissor_xmax(), 1));
00284 
00285    // IS THIS ACCURATE ENOUGH??  do we have to be more careful about
00286    // how ensuring that if one xrange is [a,b] and another is [b,c]
00287    // that they are perfectly adjacent to each other in all cases?
00288    GLsizei x,y,w,h;
00289    x = GLsizei(lower_left[0]);
00290    y = GLsizei(lower_left[1]);
00291    w = GLsizei(upper_right[0] - lower_left[0]);
00292    h = GLsizei(upper_right[1] - lower_left[1]);
00293 
00294    glScissor(x, y, w, h);
00295    glEnable (GL_SCISSOR_TEST);
00296 }
00297 
00298 inline void
00299 check(GEOMptr geom)
00300 {
00301    if (!geom)
00302       return;
00303    cerr << geom->name() << " (" << geom->class_name() << ")"
00304         << " has transp: " << (geom->has_transp() ? "true" : "false")
00305         << ", transp: " << geom->transp()
00306         << ", needs blend: " << (geom->needs_blend() ? "true" : "false")
00307         << endl;
00308 }
00309 
00310 /*
00311  * draw_objects() - draws all objects, but not stencils
00312  */
00313 int
00314 GL_VIEW::draw_objects(
00315    CGELlist     &objs, 
00316    CAMdata::eye  e
00317    )
00318 {
00319    static GLfloat SHININESS =
00320       (GLfloat)Config::get_var_dbl("SHININESS",20.0,true);
00321    int tris = 0;
00322 
00323    // load projection matrix
00324    glMatrixMode(GL_PROJECTION);
00325    load_proj_mat(e);
00326 
00327    // load the camera position matrix
00328    glMatrixMode(GL_MODELVIEW);
00329    load_cam_mat(e);
00330 
00331    // set default state
00332    glLineWidth(float(_view->line_scale()*1.0));
00333    glDisable(GL_NORMALIZE);      // MODELERs enable this only if needed
00334    glDisable(GL_BLEND);
00335    if (_view->lights_on()) 
00336    {
00337        GLfloat emission_color[] = {0,0,0,0};
00338        GLfloat specular_color[] = {0,0,0,0};
00339 
00340        glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, emission_color);
00341        glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
00342        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular_color);
00343        glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, SHININESS);
00344    } 
00345    else 
00346    { 
00347        GLfloat amb_diff_color[] = {0,0,0,0};
00348        GLfloat specular_color[] = {0,0,0,0};
00349        glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
00350        glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, amb_diff_color);
00351        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular_color);
00352        glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, SHININESS);
00353    }
00354    glEnable(GL_COLOR_MATERIAL);  // glColor will now set components 
00355                                  // specified by glColorMaterial flags
00356 
00357    glShadeModel(GL_SMOOTH);
00358    if (_view->is_clipping()) {
00359       glEnable(GL_CLIP_PLANE0);
00360 
00361       GLdouble equation[4];
00362       CWvec &vec = _view->clip_plane().normal();
00363       equation[0] = vec[0];
00364       equation[1] = vec[1];
00365       equation[2] = vec[2];
00366       equation[3] = _view->clip_plane().d();
00367       glClipPlane(GL_CLIP_PLANE0, equation);
00368       glDisable(GL_CULL_FACE);
00369    } else {
00370       glDisable(GL_CLIP_PLANE0);
00371 
00372       if (_view->rendering() == RWIRE_FRAME) glDisable(GL_CULL_FACE);
00373       else                                   glEnable (GL_CULL_FACE);
00374    }
00375 
00376    if (_view->lights_on())
00377       setup_lights(e);
00378    else
00379       glDisable(GL_LIGHTING);
00380 
00381    // sort objects into two lists, with blended
00382    // objects in order of decreasing depth:
00383    sort_blended_objects(objs);
00384 
00385    // experimental policy (10/2005):
00386    init_polygon_offset();
00387 
00388    glMatrixMode(GL_MODELVIEW);
00389    int i;
00390 
00391    static bool checked = false;
00392    if (0 && !checked) {
00393       checked = true;
00394       for (int i=0; i<objs.num(); i++) {
00395          check(GEOM::upcast(objs[i]));
00396       }
00397    }
00398 
00399    bool debug_blend = false;
00400    if (debug_blend)
00401       cerr << "---------- opaque: ----------" << endl;
00402    for (i = 0; i < _opaque.num(); i++) {
00403       // XXX - should sort all clip avoiding objects together so we
00404       // don't have to do this per-object 
00405       if (_view->is_clipping()) {
00406          if (DONOT_CLIP_OBJ.get(_opaque[i]))
00407               glDisable(GL_CLIP_PLANE0);
00408          else glEnable (GL_CLIP_PLANE0);
00409       }
00410 
00411       load_cam_mat(e);
00412       if (debug_blend)
00413          cerr << _opaque[i]->name() << endl;
00414       tris += _opaque[i]->draw(_view);
00415    }
00416 
00417    if (debug_blend)
00418       cerr << "---------- blended: ----------" << endl;
00419    if (!_blended.empty()) {
00420       glEnable(GL_BLEND);
00421       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00422       for (i = 0; i < _blended.num(); i++) {
00423          // XXX - should sort all clip avoiding objects together so we
00424          // don't have to do this
00425          if (_view->is_clipping()) {
00426             if (DONOT_CLIP_OBJ.get(_blended[i]))
00427                  glDisable(GL_CLIP_PLANE0);
00428             else glEnable (GL_CLIP_PLANE0);
00429          }
00430          load_cam_mat(e);
00431          if (debug_blend)
00432             cerr << _blended[i]->name() << endl;
00433          tris += _blended[i]->draw(_view);
00434       }
00435    }
00436 
00437    end_polygon_offset();
00438 
00439    // Final pass (for strokes or whatever)
00440    objs.draw_final(_view);
00441 
00442    return tris;
00443 }
00444 
00445 
00446 /*
00447  * stencil_draw() - paints a specific stencil region
00448  *    this is called by each stencil region after the stencil cb has
00449  * setup any region-specific rendering parameters.  In addition, the
00450  * stencil cb can supply a list of objects to be drawn instead of the
00451  * default scene objects.
00452  */
00453 int
00454 GL_VIEW::stencil_draw(
00455    STENCILCB *cb, 
00456    GELlist   *objs
00457    )
00458 {
00459    const int num = _view->stencil_cbs().get_index(cb);
00460    if (num != BAD_IND) {
00461       glStencilFunc(GL_EQUAL, (GLint) num + 1, 0x127);
00462       glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
00463       return draw_objects(objs ? *objs : _view->drawn());
00464    } else {
00465       cerr << "GL_VIEW::stencil_draw - couldn't find STENCILCB" << endl;
00466       return 0;
00467    }
00468 }
00469 
00470 bool
00471 GL_VIEW::print_gl_errors(Cstr_ptr &location)
00472 {
00473    bool ret = false;
00474 
00475    GLenum err;
00476 
00477    while((err = glGetError())) {
00478       str_ptr errstr;
00479       switch (err) {
00480          case GL_INVALID_ENUM:      errstr = "Invalid Enumerator";   break;
00481          case GL_INVALID_VALUE:     errstr = "Invalid Value";        break;
00482          case GL_INVALID_OPERATION: errstr = "Invalid Operation";    break;
00483          case GL_STACK_OVERFLOW:    errstr = "Stack Overflow";       break;
00484          case GL_STACK_UNDERFLOW:   errstr = "Stack Underflow";      break;
00485          case GL_OUT_OF_MEMORY:     errstr = "Out of Memory";        break;
00486          default:                   errstr = "Unknown Error";        break;
00487       }
00488       err_msg("%s ***NOTE*** OpenGL Error: [%x] '%s'", **location, err, **errstr);
00489       ret = true;
00490    }
00491 
00492    return ret;
00493 }
00494 
00495 inline bool
00496 is_valid_3D_object(CGELptr& gel)
00497 {
00498    return GEOM::isa(gel) && gel->bbox().valid();
00499 }
00500 
00501 int
00502 GL_VIEW::depth_compare(
00503    const void *a,
00504    const void *b
00505    )
00506 {
00507    CAMptr cam = VIEW::peek_cam();
00508 
00509    GELptr gel1 = *(GELptr*)a;
00510    GELptr gel2 = *(GELptr*)b;
00511 
00512    // XXX - Changed default sorting when a non
00513    // GEOM show up... This makes gesture strokes
00514    // appear on top.  Mind you, gel's should have bbox's
00515    // so I dunno why we can't just forge ahead...
00516 
00517    if (!is_valid_3D_object(gel1))
00518       return 1;
00519    
00520    if (!is_valid_3D_object(gel2))
00521       return -1;
00522    
00523    double x = (gel1)->bbox().center().dist_sqrd(cam->data()->from()) -
00524               (gel2)->bbox().center().dist_sqrd(cam->data()->from());
00525    
00526    return (x<0) ? 1 : (x>0) ? -1 : 0;
00527 }
00528 
00529 
00530 void       
00531 GL_VIEW::sort_blended_objects(
00532    CGELlist &list
00533    )
00534 {
00535     _blended.clear();
00536     _opaque.clear();
00537    
00538    for (int i=0; i < list.num(); i++ ) {
00539       if (list[i]->needs_blend())
00540          _blended += list[i];
00541       else
00542          _opaque  += list[i];
00543    }
00544    
00545    _blended.sort(GL_VIEW::depth_compare);
00546 }
00547 
00548 void
00549 GL_VIEW::setup_light(int i)
00550 {
00551    GLenum num = light_i(i);              // GL_LIGHT0, e.g.
00552    const Light& light = _view->get_light(i);
00553 
00554    // set modelview matrix before passing light coordinates
00555    glMatrixMode(GL_MODELVIEW);
00556    glPushMatrix();
00557    if (light._is_in_cam_space) {
00558       glLoadIdentity();
00559    } else {
00560       glLoadMatrixd(_view->world_to_eye().transpose().matrix());
00561    }
00562 
00563    // If a light is disabled, set its colors to black
00564    // (GLSL shaders need this since they don't know which lights are enabled)
00565    COLOR a = Color::black;
00566    COLOR d = Color::black;
00567    COLOR s = Color::black;
00568    if (light._is_enabled) {
00569       a = light._ambient_color;
00570       d = light._diffuse_color;
00571       s = light._specular_color;
00572       glEnable(num);
00573    } else {
00574       glDisable(num);
00575    }
00576 
00577    // set light parameters:
00578    glLightfv(num, GL_AMBIENT,  float4(a));
00579    glLightfv(num, GL_DIFFUSE,  float4(d));
00580    glLightfv(num, GL_SPECULAR, float4(s));
00581    if (light._is_positional) {
00582       glLightfv(num, GL_POSITION, float4(light.get_position()));
00583       glLightf (num, GL_CONSTANT_ATTENUATION,  light._k0);
00584       glLightf (num, GL_LINEAR_ATTENUATION,    light._k1);
00585       glLightf (num, GL_QUADRATIC_ATTENUATION, light._k2);
00586 
00587       glLightfv(num, GL_SPOT_DIRECTION, float4(light._spot_direction));
00588       glLightf (num, GL_SPOT_EXPONENT,  light._spot_exponent);
00589       glLightf (num, GL_SPOT_CUTOFF,    light._spot_cutoff);
00590    } else {
00591       glLightfv(num, GL_POSITION, float4(light.get_direction()));
00592    }
00593 
00594    glPopMatrix();
00595 }
00596 
00597 void
00598 GL_VIEW::setup_lights(CAMdata::eye e)
00599 {
00600    print_gl_errors("GL_VIEW::setup_lights: starting");
00601 
00602    if (_view->lights_on()) {
00603       glEnable(GL_LIGHTING);
00604    } else {
00605       glDisable(GL_LIGHTING);
00606    }
00607 
00608    // setup global ambient light:
00609    glLightModelfv(GL_LIGHT_MODEL_AMBIENT,
00610                   float4(_view->light_get_global_ambient()));
00611 
00612    // enable two-sided lighting and use local viewer model:
00613    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
00614    glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
00615 
00616    // setup individual lights:
00617    for (int i=0; i<VIEW::max_lights(); i++)
00618       setup_light(i);
00619    
00620    print_gl_errors("GL_VIEW::setup_lights: end");
00621 }
00622 
00623 void
00624 GL_VIEW::end_buf_read()
00625 {
00626    // restore default state:
00627    glPixelStorei(GL_PACK_ALIGNMENT,4);
00628 }
00629 
00630 void
00631 GL_VIEW::prepare_buf_read()
00632 {
00633    glReadBuffer(GL_BACK);
00634    glPixelStorei(GL_PACK_ALIGNMENT,1);  // needed to avoid seg faults
00635 }
00636 
00637 void
00638 GL_VIEW::read_pixels(
00639    uchar *data,
00640    bool  alpha
00641    )
00642 {
00643    //If alhpa=true, then the caller wants alpha too!!
00644 
00645    draw_setup();
00646 
00647    draw_frame();
00648 
00649    int width, height;
00650    _view->get_size(width, height);
00651 
00652    // back buffer now contains pixels of
00653    // the current tile. read the pixels:
00654    if (alpha)
00655       glReadPixels(0,0,width,height,GL_RGBA,GL_UNSIGNED_BYTE,data);
00656    else
00657       glReadPixels(0,0,width,height,GL_RGB,GL_UNSIGNED_BYTE,data);
00658 }
00659 
00660 //
00661 // Callback for when the size of the view changes
00662 //
00663 void
00664 GL_VIEW::set_size(
00665    int width,
00666    int height,
00667    int xpos,  // x position
00668    int ypos   // y position
00669    )
00670 {
00671    if (multithread && !_paintResize) 
00672    {
00673       _resizePending = true;
00674       _resizeW = width; _resizeH = height; _resizeX = xpos; _resizeY = ypos;
00675       return;
00676    }
00677    _paintResize = false;
00678    _resizePending = false;
00679 
00680    if ((!multithread && (VIEWS.num()>1)) ||
00681        _view->win()->needs_context()) 
00682    {   
00683       _view->win()->set_context();
00684    }
00685 
00686    // If using Yotta, make sure entire background color is set to
00687    // bkgnd color before resetting the viewport offset & dimensions so
00688    // the compositing h/w doesn't do the wrong thing because of any
00689    // non-bkgnd colored pixels outside the viewport.
00690    if (_view->stereo() == LEFT_EYE_MONO || _view->stereo() == RIGHT_EYE_MONO) 
00691    {
00692       glDrawBuffer(GL_FRONT);
00693       clear_draw_buffer();
00694       if (_view->win()->double_buffered()) 
00695       {
00696          glDrawBuffer(GL_BACK);
00697          clear_draw_buffer();
00698       }
00699    }
00700 
00701    // set new dimensions & offset for viewport
00702    glViewport(xpos, ypos, (GLsizei)width, (GLsizei)height);
00703 
00704    // XXX - tracked down the bad stuff, to here:
00705    //       CAMdata::aspect() is suposedly height/width.
00706    //       following lines get that ass-backwards.
00707 
00708    // XXX - needs work
00709 
00710    static double asp = Config::get_var_dbl("DISPLAY_ASPECT",-1.0,true);
00711    if (asp != -1.0)
00712    {
00713       _view->cam()->set_aspect(asp);
00714    }
00715    else 
00716    {
00717       static double pixel_warp_factor = Config::get_var_dbl("PIXEL_WARP_FACTOR",1.0,true);
00718       _view->cam()->set_aspect(double(width)/double(height)*pixel_warp_factor);
00719    }
00720 }
00721 
00722 //
00723 // Returns OpenGL version as a double
00724 //
00725 double
00726 GL_VIEW::gl_version()
00727 {
00728    CriticalSection cs(&gl_version_mutex);
00729    static double ret = glGetString(GL_VERSION) 
00730       ? atof((const char*)glGetString(GL_VERSION))
00731       : 0;
00732 
00733    return ret;
00734 }
00735 
00736 bool 
00737 GL_VIEW::poly_ext_available() 
00738 {
00739    CriticalSection cs(&polyextmutex);
00740    static bool ret = (strstr((const char *)glGetString(GL_EXTENSIONS),
00741                             "GL_EXT_polygon_offset") != 0);
00742    return ret;
00743 }
00744 
00745 void
00746 GL_VIEW::init_polygon_offset(
00747    float  factor,
00748    float  units,
00749    GLenum mode
00750    )
00751 {
00752    glEnable(mode);                              // GL_ENABLE_BIT
00753    glPolygonOffset(factor, units);              // GL_POLYGON_BIT
00754 }
00755 
00756 void
00757 GL_VIEW::end_polygon_offset()
00758 {
00759    glDisable(GL_POLYGON_OFFSET_FILL);        // GL_ENABLE_BIT
00760 }
00761 
00762 void 
00763 GL_VIEW::check_point_sizes()
00764 {
00765    if (_checked_point_sizes) {
00766       return;
00767    }
00768    _checked_point_sizes = true;
00769 
00770    GLfloat granularity = 0;
00771    GLfloat point_sizes[2];
00772    glGetFloatv(GL_POINT_SIZE_GRANULARITY, &granularity);
00773    glGetFloatv(GL_POINT_SIZE_RANGE, point_sizes);      // gets min and max
00774    _min_point_size = point_sizes[0];
00775    _max_point_size = point_sizes[1];
00776    if (Config::get_var_bool("JOT_PRINT_POINT_SIZES",false)) {
00777       cerr << "  GL point size: "
00778            << "min: " << _min_point_size << ", "
00779            << "max: " << _max_point_size << ", "
00780            << "granularity: " << granularity << endl;
00781    }
00782 }
00783 
00784 void 
00785 GL_VIEW::check_line_widths()
00786 {
00787    if (_checked_line_widths) {
00788       return;
00789    }
00790    _checked_line_widths = true;
00791 
00792    GLfloat granularity = 0;
00793    GLfloat line_widths[2];
00794    glGetFloatv(GL_LINE_WIDTH_GRANULARITY, &granularity);
00795    glGetFloatv(GL_LINE_WIDTH_RANGE, line_widths);      // gets min and max
00796    _min_line_width = line_widths[0];
00797    _max_line_width = line_widths[1];
00798    if (Config::get_var_bool("JOT_PRINT_LINE_WIDTHS",false)) {
00799       cerr << "  GL line width: "
00800            << "min: " << _min_line_width << ", "
00801            << "max: " << _max_line_width << ", "
00802            << "granularity: " << granularity << endl;
00803    }
00804 }
00805 
00806 void
00807 GL_VIEW::init_point_smooth(GLfloat size, GLbitfield mask, GLfloat* a)
00808 {
00809    // Turns on antialiasing for points and sets the point size to the
00810    // given amount. Calls glPushAttrib() with GL_ENABLE_BIT,
00811    // GL_POINT_BIT and GL_COLOR_BUFFER_BIT along with whatever bits
00812    // are passed in with 'mask'.
00813 
00814    check_point_sizes();
00815 
00816    size = max(GLfloat(0), size);
00817 
00818    glPushAttrib(mask | GL_ENABLE_BIT | GL_POINT_BIT |
00819                 GL_HINT_BIT | GL_COLOR_BUFFER_BIT);
00820    glEnable(GL_POINT_SMOOTH);                         // GL_ENABLE_BIT
00821    glEnable(GL_BLEND);                                // GL_ENABLE_BIT
00822    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_COLOR_BUFFER_BIT
00823    glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);           // GL_HINT_BIT
00824    if (size > _max_point_size) {
00825       size = _max_point_size;
00826    } else if (size < _min_point_size) {
00827       if (a) {
00828          *a = (size/_min_point_size);
00829       } else {
00830          static bool warned=false;
00831          if (!warned) {
00832             warned=true;
00833             err_msg("GL_VIEW::init_point_smooth: unsupported point size %f", size);
00834          }
00835       }
00836       size = _min_point_size;
00837    }
00838 
00839    glPointSize(size);                                    // GL_POINT_BIT
00840 }
00841 
00842 void
00843 GL_VIEW::end_point_smooth()
00844 {
00845    glPopAttrib();
00846 }
00847 
00848 void
00849 GL_VIEW::end_line_smooth()
00850 {
00851    glPopAttrib();
00852 }
00853 
00854 void
00855 GL_VIEW::draw_pts(
00856    CWpt_list&   pts,    // points to draw
00857    CCOLOR&      color,  // color to use
00858    double       alpha,  // transparency
00859    double       size    // width of points
00860    )
00861 {
00862    // Draws given points as disconnected dots w/ given
00863    // color, transparency and size. Assumes projection and
00864    // modelview matrices have been set as needed.
00865 
00866    if (!pts.empty()) {
00867       // Enable point smoothing and push gl state:
00868       init_point_smooth(float(size), GL_CURRENT_BIT);
00869       GL_COL(color, alpha);             // GL_CURRENT_BIT
00870       glDisable(GL_LIGHTING);           // GL_ENABLE_BIT
00871       glBegin(GL_POINTS);
00872       for (int i=0; i<pts.num(); i++)
00873          glVertex3dv(pts[i].data());
00874       glEnd();
00875       GL_VIEW::end_point_smooth();      // pop state
00876    }
00877 }
00878 
00879 void 
00880 GL_VIEW::draw_wpt_list(
00881    CWpt_list&      pts,        // polyline to draw
00882    CCOLOR&         color,      // color to use
00883    double          alpha,      // transparency
00884    double          width,      // width of points
00885    bool            do_stipple  // if true, draw tippled
00886    )
00887 {
00888    // Draws a Wpt_list w/ given color, transparency and
00889    // width. If do_stipple is set to true, the Wpt_list is
00890    // drawn stippled. Assumes projection and modelview
00891    // matrices have been set as needed.
00892 
00893    if (pts.num() < 2) 
00894       return;
00895 
00896    glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT | GL_CURRENT_BIT);
00897 
00898    GL_COL(color, alpha);             // GL_CURRENT_BIT
00899    glDisable(GL_LIGHTING);           // GL_ENABLE_BIT
00900    glLineWidth(float(width));        // GL_LINE_BIT
00901    if (do_stipple) {
00902       glLineStipple(1,0x00ff);        // GL_LINE_BIT
00903       glEnable(GL_LINE_STIPPLE);      // GL_ENABLE_BIT
00904    }
00905 
00906    // draw the polyline
00907    glBegin(GL_LINE_STRIP);
00908    for (int i=0; i<pts.num(); i++) {
00909       glVertex3dv(pts[i].data());
00910    }
00911    glEnd();
00912 
00913    glPopAttrib();
00914 }
00915 
00916 void 
00917 GL_VIEW::draw_lines(
00918    CARRAY<Wline>&  lines,      // lines to draw
00919    CCOLOR&         color,      // color to use
00920    double          alpha,      // transparency
00921    double          width,      // width of points
00922    bool            do_stipple  // if true, draw tippled
00923    )
00924 {
00925    // Draws given lines w/ given color, transparency and width. If
00926    // do_stipple is set to true, the lines are drawn stippled. Assumes
00927    // projection and modelview matrices have been set as needed.
00928 
00929    if (lines.empty()) 
00930       return;
00931 
00932    glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT | GL_CURRENT_BIT);
00933 
00934    GL_COL(color, alpha);             // GL_CURRENT_BIT
00935    glDisable(GL_LIGHTING);           // GL_ENABLE_BIT
00936    glLineWidth(float(width));        // GL_LINE_BIT
00937    if (do_stipple) {
00938       glLineStipple(1,0x00ff);        // GL_LINE_BIT
00939       glEnable(GL_LINE_STIPPLE);      // GL_ENABLE_BIT
00940    }
00941 
00942    // draw the lines
00943 
00944    glBegin(GL_LINES);
00945 
00946    for (int i=0; i<lines.num(); i++) {
00947       glVertex3dv(lines[i].point().data());
00948       glVertex3dv(lines[i].endpt().data());
00949    }
00950   
00951    glEnd();
00952 
00953    glPopAttrib();
00954 }
00955 
00956 void
00957 GL_VIEW::draw_bb(CWpt_list &bb_pts) const
00958 {
00959    glDisable(GL_LIGHTING);
00960    glLineWidth(float(_view->line_scale()*3.0));
00961    glEnable(GL_LINE_SMOOTH);
00962    glBegin(GL_LINES);
00963    // Lines from min pt
00964    glVertex3dv(bb_pts[0].data()); glVertex3dv(bb_pts[1].data());
00965    glVertex3dv(bb_pts[0].data()); glVertex3dv(bb_pts[2].data());
00966    glVertex3dv(bb_pts[0].data()); glVertex3dv(bb_pts[3].data());
00967    // Lines from max point
00968    glVertex3dv(bb_pts[7].data()); glVertex3dv(bb_pts[6].data());
00969    glVertex3dv(bb_pts[7].data()); glVertex3dv(bb_pts[5].data());
00970    glVertex3dv(bb_pts[7].data()); glVertex3dv(bb_pts[4].data());
00971    // Lines from top face
00972    glVertex3dv(bb_pts[2].data()); glVertex3dv(bb_pts[4].data());
00973    glVertex3dv(bb_pts[2].data()); glVertex3dv(bb_pts[6].data());
00974    // Missing lines from front face
00975    glVertex3dv(bb_pts[6].data()); glVertex3dv(bb_pts[1].data());
00976    // Missing line from bottom face
00977    glVertex3dv(bb_pts[5].data()); glVertex3dv(bb_pts[1].data());
00978    glVertex3dv(bb_pts[5].data()); glVertex3dv(bb_pts[3].data());
00979 
00980    // Last missing line
00981    glVertex3dv(bb_pts[4].data()); glVertex3dv(bb_pts[3].data());
00982    glEnd();
00983    glDisable(GL_LINE_SMOOTH);
00984    glLineWidth(float(_view->line_scale()*1.0));
00985    glEnable(GL_LIGHTING);
00986 }
00987 
00988 // end of file gl_view.C

Generated on Mon Sep 18 11:39:30 2006 for jot by  doxygen 1.4.4