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
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
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();
00069 }
00070
00071 if (_resizePending)
00072 {
00073 _paintResize = true;
00074 set_size(_resizeW, _resizeH, _resizeX, _resizeY);
00075 }
00076
00077
00078
00079 Animator *anim = _view->animator();
00080 if (!(anim->on() && anim->play_on() && anim->rend_on()))
00081 {
00082 draw_setup();
00083
00084
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
00101
00102 glViewport((GLsizei) (0),
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),
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
00124
00125
00126 return tris;
00127 }
00128
00129
00130
00131
00132
00133
00134
00135 void
00136 GL_VIEW::draw_setup()
00137 {
00138
00139 glDepthMask(GL_TRUE);
00140 glDepthFunc(GL_LEQUAL);
00141 glEnable(GL_DEPTH_TEST);
00142
00143
00144 clear_draw_buffer();
00145
00146
00147 if (_view->stencil_cbs().num())
00148 setup_stencil();
00149 else
00150 glDisable(GL_STENCIL_TEST);
00151
00152
00153 if (_view->has_scissor_region())
00154 setup_scissor();
00155 }
00156
00157
00158
00159
00160
00161
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
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
00205 if (_view->rendering() == RCOLOR_ID) {
00206 glClearColor(0, 0, 0, 0);
00207 } else {
00208 COLOR bkg(_view->color());
00209
00210 glClearColor((float)bkg[0], (float)bkg[1], (float)bkg[2], 0);
00211 }
00212
00213
00214
00215
00216 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00217
00218 _view->notify_clearobs();
00219 }
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
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
00239
00240
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
00252 _view->stencil_cbs()[i]->stencil_bounds(pts);
00253
00254
00255
00256
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
00267
00268 glStencilFunc(GL_EQUAL, 0x0, (GLuint) 127);
00269 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
00270
00271 glPopMatrix();
00272 glMatrixMode(GL_PROJECTION);
00273 glPopMatrix();
00274 }
00275
00276
00277
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
00286
00287
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
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
00324 glMatrixMode(GL_PROJECTION);
00325 load_proj_mat(e);
00326
00327
00328 glMatrixMode(GL_MODELVIEW);
00329 load_cam_mat(e);
00330
00331
00332 glLineWidth(float(_view->line_scale()*1.0));
00333 glDisable(GL_NORMALIZE);
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);
00355
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
00382
00383 sort_blended_objects(objs);
00384
00385
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
00404
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
00424
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
00440 objs.draw_final(_view);
00441
00442 return tris;
00443 }
00444
00445
00446
00447
00448
00449
00450
00451
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
00513
00514
00515
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);
00552 const Light& light = _view->get_light(i);
00553
00554
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
00564
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
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
00609 glLightModelfv(GL_LIGHT_MODEL_AMBIENT,
00610 float4(_view->light_get_global_ambient()));
00611
00612
00613 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
00614 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
00615
00616
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
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);
00635 }
00636
00637 void
00638 GL_VIEW::read_pixels(
00639 uchar *data,
00640 bool alpha
00641 )
00642 {
00643
00644
00645 draw_setup();
00646
00647 draw_frame();
00648
00649 int width, height;
00650 _view->get_size(width, height);
00651
00652
00653
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
00662
00663 void
00664 GL_VIEW::set_size(
00665 int width,
00666 int height,
00667 int xpos,
00668 int ypos
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
00687
00688
00689
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
00702 glViewport(xpos, ypos, (GLsizei)width, (GLsizei)height);
00703
00704
00705
00706
00707
00708
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
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);
00753 glPolygonOffset(factor, units);
00754 }
00755
00756 void
00757 GL_VIEW::end_polygon_offset()
00758 {
00759 glDisable(GL_POLYGON_OFFSET_FILL);
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);
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);
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
00810
00811
00812
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);
00821 glEnable(GL_BLEND);
00822 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00823 glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
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);
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,
00857 CCOLOR& color,
00858 double alpha,
00859 double size
00860 )
00861 {
00862
00863
00864
00865
00866 if (!pts.empty()) {
00867
00868 init_point_smooth(float(size), GL_CURRENT_BIT);
00869 GL_COL(color, alpha);
00870 glDisable(GL_LIGHTING);
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();
00876 }
00877 }
00878
00879 void
00880 GL_VIEW::draw_wpt_list(
00881 CWpt_list& pts,
00882 CCOLOR& color,
00883 double alpha,
00884 double width,
00885 bool do_stipple
00886 )
00887 {
00888
00889
00890
00891
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);
00899 glDisable(GL_LIGHTING);
00900 glLineWidth(float(width));
00901 if (do_stipple) {
00902 glLineStipple(1,0x00ff);
00903 glEnable(GL_LINE_STIPPLE);
00904 }
00905
00906
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,
00919 CCOLOR& color,
00920 double alpha,
00921 double width,
00922 bool do_stipple
00923 )
00924 {
00925
00926
00927
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);
00935 glDisable(GL_LIGHTING);
00936 glLineWidth(float(width));
00937 if (do_stipple) {
00938 glLineStipple(1,0x00ff);
00939 glEnable(GL_LINE_STIPPLE);
00940 }
00941
00942
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
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
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
00972 glVertex3dv(bb_pts[2].data()); glVertex3dv(bb_pts[4].data());
00973 glVertex3dv(bb_pts[2].data()); glVertex3dv(bb_pts[6].data());
00974
00975 glVertex3dv(bb_pts[6].data()); glVertex3dv(bb_pts[1].data());
00976
00977 glVertex3dv(bb_pts[5].data()); glVertex3dv(bb_pts[1].data());
00978 glVertex3dv(bb_pts[5].data()); glVertex3dv(bb_pts[3].data());
00979
00980
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