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

view.C

Go to the documentation of this file.
00001 
00002 #include "std/config.H"
00003 
00004 #include "std/stop_watch.H"
00005 #include "std/thread.H"
00006 
00007 #include "disp/ray.H"
00008 #include "disp/gel.H"
00009 #include "disp/cam_focus.H"
00010 #include "disp/recorder.H"
00011 #include "disp/animator.H"
00012 #include "disp/frame_time_observer.H"
00013 #include "disp/paper_effect_base.H"
00014 #include "disp/jitter.H"
00015 #include "net/io_manager.H"
00016 
00017 using namespace mlib;
00018 
00019 #define DEFAULT_LIGHT_COORD_0          Wvec::Z()
00020 #define DEFAULT_LIGHT_POSITIONAL_0     false
00021 #define DEFAULT_LIGHT_IN_CAM_SPACE_0   true
00022 #define DEFAULT_LIGHT_DIFFUSE_0        COLOR(0.9,0.9,0.9)
00023 #define DEFAULT_LIGHT_AMBIENT_0        COLOR::black
00024 #define DEFAULT_LIGHT_SPECULAR_0       COLOR(0.9,0.9,0.9)
00025 #define DEFAULT_LIGHT_ENABLE_0         true
00026 
00027 #define DEFAULT_LIGHT_COORD_1          Wvec::Z()
00028 #define DEFAULT_LIGHT_POSITIONAL_1     false
00029 #define DEFAULT_LIGHT_IN_CAM_SPACE_1   true
00030 #define DEFAULT_LIGHT_DIFFUSE_1        COLOR(0.9,0.0,0.0)
00031 #define DEFAULT_LIGHT_AMBIENT_1        COLOR::black
00032 #define DEFAULT_LIGHT_SPECULAR_1       COLOR::black
00033 #define DEFAULT_LIGHT_ENABLE_1         false
00034 
00035 #define DEFAULT_LIGHT_COORD_2          Wvec::Z()
00036 #define DEFAULT_LIGHT_POSITIONAL_2     false
00037 #define DEFAULT_LIGHT_IN_CAM_SPACE_2   true
00038 #define DEFAULT_LIGHT_DIFFUSE_2        COLOR(0.0,0.9,0.0)
00039 #define DEFAULT_LIGHT_AMBIENT_2        COLOR::black
00040 #define DEFAULT_LIGHT_SPECULAR_2       COLOR::black
00041 #define DEFAULT_LIGHT_ENABLE_2         false
00042 
00043 #define DEFAULT_LIGHT_COORD_3          Wvec::Z()
00044 #define DEFAULT_LIGHT_POSITIONAL_3     false
00045 #define DEFAULT_LIGHT_IN_CAM_SPACE_3   true
00046 #define DEFAULT_LIGHT_DIFFUSE_3        COLOR(0.0,0.0,0.9)
00047 #define DEFAULT_LIGHT_AMBIENT_3        COLOR::black
00048 #define DEFAULT_LIGHT_SPECULAR_3       COLOR::black
00049 #define DEFAULT_LIGHT_ENABLE_3         false
00050 
00051 #define DEFAULT_LIGHT_GLOBAL_AMBIENT   COLOR(0.1,0.1,0.1)
00052 
00053 
00054 hashvar<int>  DONOT_CLIP_OBJ("DONOT_CLIP_OBJ", 0, 1);
00055 int VIEW::_num_views = 0;
00056 Threadobs_list *ThreadObs::_all_thread;
00057 
00058 bool multithread = Config::get_var_bool("JOT_MULTITHREAD",false,true);
00059 
00060 //
00061 // VIEW - contains a list of objects to be displayed and handles events that
00062 // operate on those objects
00063 //
00064 
00065 //
00066 // Standard rendering modes
00067 //
00068 Cstr_ptr RSMOOTH_SHADE   ("Smooth Shading");
00069 Cstr_ptr RFLAT_SHADE     ("Flat Shading");
00070 Cstr_ptr RSPEC_SHADE     ("Specular Shading");
00071 Cstr_ptr RHIDDEN_LINE    ("Hidden Line");
00072 Cstr_ptr RWIRE_FRAME     ("Wireframe");
00073 Cstr_ptr RNORMALS        ("Normals");
00074 Cstr_ptr RNORMALS_ONLY   ("Normals Only");
00075 Cstr_ptr RCOLOR_ID       ("Color ID");
00076 Cstr_ptr RSHOW_TRI_STRIPS("Show tri-strips");
00077 Cstr_ptr RKEY_LINE       ("Key Line");
00078 Cstr_ptr RSIL_FRAME      ("Sil Frame");
00079 Cstr_ptr RLINE_DRAWING   ("Line Drawing");
00080 Cstr_ptr RCURVATURE      ("Curvature");
00081 Cstr_ptr SKYBOX_GRADIENT ("SkyBox_Texture");
00082 
00083 //
00084 // List of rendering types
00085 //
00086 str_list                   VIEW::_rend_types(25); 
00087 VIEWlist                   VIEW::_views;
00088 VIEWlist                   VIEWS;
00089 VIEWobs::view_list        *VIEWobs::_view_obs;
00090 
00091 unsigned int    VIEW::_stamp                    = 0;
00092 double          VIEW::_pix_to_ndc_scale         = 0;
00093 
00094 void 
00095 FRAME_TIME_OBSERVER_list::frame_time_changed() const 
00096 {
00097    for (int i=0; i<num(); i++)
00098       (*this)[i]->frame_time_changed();
00099 }
00100 
00101 #ifdef USE_PTHREAD
00102 class ThreadToView : public ThreadObs {
00103    public:
00104       virtual void notify_render_thread(CVIEWptr &v) {
00105          assert(_instance); 
00106          _data.set((VIEW *) &*v);
00107       }
00108       static VIEW *get() { assert(_instance); return (VIEW *) _data.get();}
00109       static void make_if_needed() {
00110          if (!_instance) {_instance = new ThreadToView();}
00111       }
00112    protected:
00113       ThreadToView() { thread_obs(); }
00114       static ThreadData    _data;
00115       static ThreadToView *_instance;
00116 };
00117 
00118 ThreadData ThreadToView::_data;
00119 ThreadToView *ThreadToView::_instance = 0;
00120 #endif
00121 
00122 
00123 /* ------------------ VIEW class definitions --------------------- */
00124 
00125 TAGlist *            VIEW::_v_tags = 0;
00126 
00127 ARRAY<ARRAY<VEXEL>*> VIEW::_jitters;
00128 
00129 /////////////////////////////////////
00130 // tags()
00131 /////////////////////////////////////
00132 CTAGlist &
00133 VIEW::tags() const
00134 {
00135    if (!_v_tags) {
00136       _v_tags = new TAGlist;
00137 
00138       *_v_tags += new TAG_meth<VIEW>(
00139          "view_animator",
00140          &VIEW::put_view_animator,
00141          &VIEW::get_view_animator,
00142          1);
00143 
00144       *_v_tags += new TAG_meth<VIEW>(
00145          "view_data_file",
00146          &VIEW::put_view_data_file,
00147          &VIEW::get_view_data_file,
00148          1);
00149 
00150       *_v_tags += new TAG_meth<VIEW>(
00151          "view_color",
00152          &VIEW::put_view_color,
00153          &VIEW::get_view_color,
00154          1);
00155 
00156       *_v_tags += new TAG_meth<VIEW>(
00157          "view_alpha",
00158          &VIEW::put_view_alpha,
00159          &VIEW::get_view_alpha,
00160          1);
00161 
00162       *_v_tags += new TAG_meth<VIEW>(
00163          "view_paper_use",
00164          &VIEW::put_view_paper_use,
00165          &VIEW::get_view_paper_use,
00166          1);
00167 
00168       *_v_tags += new TAG_meth<VIEW>(
00169          "view_paper_name",
00170          &VIEW::put_view_paper_name,
00171          &VIEW::get_view_paper_name,
00172          1);
00173 
00174       *_v_tags += new TAG_meth<VIEW>(
00175          "view_paper_active",
00176          &VIEW::put_view_paper_active,
00177          &VIEW::get_view_paper_active,
00178          1);
00179 
00180       *_v_tags += new TAG_meth<VIEW>(
00181          "view_paper_brig",
00182          &VIEW::put_view_paper_brig,
00183          &VIEW::get_view_paper_brig,
00184          1);
00185 
00186       *_v_tags += new TAG_meth<VIEW>(
00187          "view_paper_cont",
00188          &VIEW::put_view_paper_cont,
00189          &VIEW::get_view_paper_cont,
00190          1);
00191 
00192       *_v_tags += new TAG_meth<VIEW>(
00193          "view_texture",
00194          &VIEW::put_view_texture,
00195          &VIEW::get_view_texture,
00196          1);
00197 
00198       *_v_tags += new TAG_meth<VIEW>(
00199          "view_light_coords",
00200          &VIEW::put_view_light_coords,
00201          &VIEW::get_view_light_coords,
00202          1);
00203 
00204       *_v_tags += new TAG_meth<VIEW>(
00205          "view_light_positional",
00206          &VIEW::put_view_light_positional,
00207          &VIEW::get_view_light_positional,
00208          1);
00209 
00210       *_v_tags += new TAG_meth<VIEW>(
00211          "view_light_cam_space",
00212          &VIEW::put_view_light_cam_space,
00213          &VIEW::get_view_light_cam_space,
00214          1);
00215 
00216       *_v_tags += new TAG_meth<VIEW>(
00217          "view_light_color_diff",
00218          &VIEW::put_view_light_color_diff,
00219          &VIEW::get_view_light_color_diff,
00220          1);
00221 
00222       *_v_tags += new TAG_meth<VIEW>(
00223          "view_light_color_amb",
00224          &VIEW::put_view_light_color_amb,
00225          &VIEW::get_view_light_color_amb,
00226          1);
00227 
00228       *_v_tags += new TAG_meth<VIEW>(
00229          "view_light_global",
00230          &VIEW::put_view_light_color_global,
00231          &VIEW::get_view_light_color_global,
00232          1);
00233 
00234       *_v_tags += new TAG_meth<VIEW>(
00235          "view_light_enable",
00236          &VIEW::put_view_light_enable,
00237          &VIEW::get_view_light_enable,
00238          1);
00239 
00240       *_v_tags += new TAG_meth<VIEW>(
00241          "view_antialias_enable",
00242          &VIEW::put_view_antialias_enable,
00243          &VIEW::get_view_antialias_enable,
00244          1);
00245 
00246       *_v_tags += new TAG_meth<VIEW>(
00247          "view_antialias_mode",
00248          &VIEW::put_view_antialias_mode,
00249          &VIEW::get_view_antialias_mode,
00250          1);
00251 
00252 
00253    }
00254    return *_v_tags;
00255 }
00256 
00257 
00258 /////////////////////////////////////
00259 // get_view_data_file()
00260 /////////////////////////////////////
00261 void
00262 VIEW::get_view_data_file (TAGformat &d) 
00263 {
00264    // Sanity check...
00265    assert(!_in_data_file);
00266 
00267    str_ptr str;
00268    *d >> str;      
00269 
00270    if (str == "NULL_STR") {
00271       err_mesg(ERR_LEV_SPAM, "VIEW::get_view_data_file() - Loaded NULL string.");
00272       _data_file = NULL_STR;
00273    } else {
00274       err_mesg(ERR_LEV_SPAM, "VIEW::get_view_data_file() - Loaded string: '%s'.", **str);
00275       _data_file = str;
00276 
00277       str_ptr fname = IOManager::load_prefix() + str + ".view";
00278 
00279       err_mesg(ERR_LEV_SPAM, "VIEW::get_view_data_file() - Opening: '%s'...", **fname);
00280 
00281       fstream fin;
00282 #if (defined (WIN32) && defined(_MSC_VER) && (_MSC_VER <=1300)) /*VS 6.0*/
00283       fin.open(**(fname),ios::in | ios::nocreate);
00284 #else
00285       fin.open(**(fname),ios::in);
00286 #endif
00287       if (!fin) 
00288       {
00289          err_msg("VIEW::get_view_data_file() - Could not open: '%s'!!", **fname);
00290          //but leave the _data_file as is so future
00291          //serialization could create it
00292       }
00293       else
00294       {
00295          STDdstream s(&fin);
00296          s >> str;
00297 
00298          if (str != VIEW::static_name()) 
00299          {
00300             err_msg("VIEW::get_view_data_file() - Not 'VIEW': '%s'!!", **str);
00301          }
00302          else
00303          {
00304             _in_data_file = true;
00305             decode(s);
00306             _in_data_file = false;
00307          }
00308       }
00309    }
00310 }
00311 
00312 /////////////////////////////////////
00313 // put_view_data_file()
00314 /////////////////////////////////////
00315 void
00316 VIEW::put_view_data_file (TAGformat &d) const
00317 {
00318    //Ignore this tag if we're presently writing to
00319    //an external view file...
00320    if (_in_data_file) return;
00321 
00322    //If there's not view file, dump the null string
00323    if (_data_file == NULL_STR)
00324    {
00325       d.id();
00326       *d << str_ptr("NULL_STR");
00327       d.end_id();
00328    }
00329    //Otherwise, try to open the file, then write the
00330    //tags to the external file, and dump the filename 
00331    //to the given tag stream
00332    else
00333    {
00334       str_ptr fname = IOManager::save_prefix() + _data_file + ".view";
00335       fstream fout;
00336       fout.open(**fname,ios::out);
00337       //If this fails, then dump the null string
00338       if (!fout) 
00339       {
00340          err_msg("VIEW::put_view_data_file -  Could not open: '%s', so changing to using no external npr file...!", **fname);   
00341 
00342          //and actually change view's policy so the
00343          //view tags serialize into the main stream
00344          ((str_ptr)_data_file) = NULL_STR;
00345 
00346          d.id();
00347          *d << str_ptr("NULL_STR");
00348          d.end_id();
00349       }
00350       //Otherwise, do the right thing
00351       else
00352       {
00353          d.id();
00354          *d << _data_file;
00355          d.end_id();
00356 
00357          //Set the flag so tags will know we're in a data file
00358          
00359          // the ((VIEW*)this)-> stuff is to "cast away" the 
00360          // const of this function so that the _in_data_file
00361          // member can be modified
00362          ((VIEW*)this)->_in_data_file = true;
00363          STDdstream stream(&fout);
00364          format(stream);
00365          ((VIEW*)this)->_in_data_file = false;
00366 
00367       }
00368    }
00369 }
00370 
00371 /////////////////////////////////////
00372 // get_view_animator()
00373 /////////////////////////////////////
00374 void
00375 VIEW::get_view_animator(TAGformat &d) 
00376 {
00377    //Sanity check...
00378    assert(!_in_data_file);
00379 
00380    str_ptr str;
00381    *d >> str;      
00382 
00383    if (str != Animator::static_name()) 
00384    {
00385       err_msg("VIEW::get_view_animator() - 'Not Animator': '%s'!!", **str);
00386    }
00387    else
00388    {
00389       assert(_animator);
00390 
00391       _animator->decode(*d);
00392    }
00393 }
00394 
00395 /////////////////////////////////////
00396 // put_view_animator()
00397 /////////////////////////////////////
00398 void
00399 VIEW::put_view_animator(TAGformat &d) const
00400 {
00401    //Ignore this tag if we're presently writing to
00402    //an external view file...
00403    if (_in_data_file) return;
00404 
00405    assert(_animator);
00406 
00407    d.id();
00408    _animator->format(*d);
00409    d.end_id();
00410 
00411 }
00412 
00413 /////////////////////////////////////
00414 // get_view_color()
00415 /////////////////////////////////////
00416 void
00417 VIEW::get_view_color(TAGformat &d) 
00418 {
00419    //Sanity check - might change policy on 2nd part
00420    assert( ( _in_data_file && (_data_file != NULL_STR)) ||
00421            (!_in_data_file && (_data_file == NULL_STR))    );
00422 
00423    COLOR c;
00424    *d >> c;
00425    set_color(c);
00426  
00427 }
00428 
00429 /////////////////////////////////////
00430 // put_view_color()
00431 /////////////////////////////////////
00432 void
00433 VIEW::put_view_color(TAGformat &d) const 
00434 {
00435    if ((!_in_data_file) && (_data_file != NULL_STR)) return;
00436    //Sanity check
00437    assert(!(_in_data_file && _data_file == NULL_STR));
00438 
00439    d.id();
00440    *d << color();
00441    d.end_id();
00442   
00443 }
00444 
00445 /////////////////////////////////////
00446 // get_view_alpha()
00447 /////////////////////////////////////
00448 void
00449 VIEW::get_view_alpha (TAGformat &d) 
00450 {
00451    //Sanity check - might change policy on 2nd part
00452    assert( ( _in_data_file && (_data_file != NULL_STR)) ||
00453            (!_in_data_file && (_data_file == NULL_STR))    );
00454 
00455    double a;
00456    *d >> a;
00457    set_alpha(a);
00458 }
00459 
00460 /////////////////////////////////////
00461 // put_view_alpha()
00462 /////////////////////////////////////
00463 void
00464 VIEW::put_view_alpha (TAGformat &d) const
00465 {
00466    if ((!_in_data_file) && (_data_file != NULL_STR)) return;
00467    //Sanity checl
00468    assert(!(_in_data_file && _data_file == NULL_STR));
00469 
00470    d.id();
00471    *d << get_alpha();
00472    d.end_id();
00473    
00474 }
00475 
00476 /////////////////////////////////////
00477 // get_view_paper_use()
00478 /////////////////////////////////////
00479 void
00480 VIEW::get_view_paper_use (TAGformat &d) 
00481 {
00482    //Sanity check - might change policy on 2nd part
00483    assert( ( _in_data_file && (_data_file != NULL_STR)) ||
00484            (!_in_data_file && (_data_file == NULL_STR))    );
00485 
00486    int p;
00487    *d >> p;
00488    set_use_paper((p==1)?true:false);   
00489 }
00490 
00491 /////////////////////////////////////
00492 // put_view_paper_use()
00493 /////////////////////////////////////
00494 void
00495 VIEW::put_view_paper_use (TAGformat &d) const
00496 {
00497    if ((!_in_data_file) && (_data_file != NULL_STR)) return;
00498    //Sanity checl
00499    assert(!(_in_data_file && _data_file == NULL_STR));
00500 
00501    d.id();
00502    *d << ((get_use_paper())?(1):(0));
00503    d.end_id();
00504    
00505 }
00506 
00507 /////////////////////////////////////
00508 // get_view_paper_name()
00509 /////////////////////////////////////
00510 void
00511 VIEW::get_view_paper_name (TAGformat &d) 
00512 {
00513    //Sanity check - might change policy on 2nd part
00514    assert( ( _in_data_file && (_data_file != NULL_STR)) ||
00515            (!_in_data_file && (_data_file == NULL_STR))    );
00516 
00517    //XXX - May need something to handle filenames with spaces
00518    str_ptr str, tex, space;
00519    *d >> str;      
00520 
00521    //XXX - Ooops... serializing "NULL_STR" and str_ptr("NULL_STR")
00522    //      yields different results.  The former doesn't put a trialing
00523    //      space, so we've been adding it manually, but that
00524    //      needs to be parsed on binary streams... I should go thourgh and
00525    //      clean all of this up in backward compatible way, chanigng
00526    //      all cases to the later...
00527    if (!(*d).ascii()) *d >> space; 
00528 
00529    if (str == "NULL_STR") 
00530    {
00531       tex = NULL_STR;
00532       err_mesg(ERR_LEV_SPAM, "VIEW::get_view_paper_name() - Loaded NULL string.");
00533    }
00534    else
00535    {
00536       tex = str;
00537       err_mesg(ERR_LEV_SPAM, "VIEW::get_view_paper_name() - Loaded string: '%s'", **tex);
00538    }
00539    PaperEffectBase::set_paper_tex(tex);
00540    
00541 }
00542 
00543 /////////////////////////////////////
00544 // put_view_paper_name()
00545 /////////////////////////////////////
00546 void
00547 VIEW::put_view_paper_name (TAGformat &d) const
00548 {
00549    if ((!_in_data_file) && (_data_file != NULL_STR)) return;
00550    //Sanity checl
00551    assert(!(_in_data_file && _data_file == NULL_STR));
00552    //XXX - May need something to handle filenames with spaces
00553 
00554    d.id();
00555    if (PaperEffectBase::get_paper_tex() == NULL_STR)
00556    {
00557       err_mesg(ERR_LEV_SPAM, "VIEW::put_view_paper_name() - Wrote NULL string.");
00558       *d << "NULL_STR";
00559       *d << " ";
00560    }
00561    else
00562    {
00563       //Here we strip off JOT_ROOT
00564       *d << PaperEffectBase::get_paper_tex();
00565       *d << " ";
00566       err_mesg(ERR_LEV_SPAM, "VIEW::put_view_paper_name() - Wrote string: '%s'", **PaperEffectBase::get_paper_tex());
00567    }
00568    d.end_id();
00569 }
00570 
00571 /////////////////////////////////////
00572 // get_view_paper_active()
00573 /////////////////////////////////////
00574 void
00575 VIEW::get_view_paper_active (TAGformat &d) 
00576 {
00577    //Sanity check - might change policy on 2nd part
00578    assert( ( _in_data_file && (_data_file != NULL_STR)) ||
00579            (!_in_data_file && (_data_file == NULL_STR))    );
00580 
00581    int a;
00582    *d >> a;
00583    PaperEffectBase::set_delayed_activate(a==1);
00584 }
00585 
00586 /////////////////////////////////////
00587 // put_view_paper_active()
00588 /////////////////////////////////////
00589 void
00590 VIEW::put_view_paper_active (TAGformat &d) const 
00591 {
00592    if ((!_in_data_file) && (_data_file != NULL_STR)) return;
00593    //Sanity checl
00594    assert(!(_in_data_file && _data_file == NULL_STR));
00595 
00596    d.id();
00597    *d << ((PaperEffectBase::is_active())?(1):(0));
00598    d.end_id();
00599    
00600 }
00601 
00602 /////////////////////////////////////
00603 // get_view_paper_cont()
00604 /////////////////////////////////////
00605 void
00606 VIEW::get_view_paper_cont (TAGformat &d) 
00607 {
00608    //Sanity check - might change policy on 2nd part
00609    assert( ( _in_data_file && (_data_file != NULL_STR)) ||
00610            (!_in_data_file && (_data_file == NULL_STR))    );
00611 
00612    float c;
00613    *d >> c;
00614    PaperEffectBase::set_cont(c);
00615 }
00616 
00617 /////////////////////////////////////
00618 // put_view_paper_cont()
00619 /////////////////////////////////////
00620 void
00621 VIEW::put_view_paper_cont (TAGformat &d) const 
00622 {
00623    if ((!_in_data_file) && (_data_file != NULL_STR)) return;
00624    //Sanity check
00625    assert(!(_in_data_file && _data_file == NULL_STR));
00626 
00627    d.id();
00628    *d << PaperEffectBase::get_cont();
00629    d.end_id();
00630    
00631 }
00632 
00633 /////////////////////////////////////
00634 // get_view_paper_brig()
00635 /////////////////////////////////////
00636 void
00637 VIEW::get_view_paper_brig (TAGformat &d) 
00638 {
00639    //Sanity check - might change policy on 2nd part
00640    assert( ( _in_data_file && (_data_file != NULL_STR)) ||
00641            (!_in_data_file && (_data_file == NULL_STR))    );
00642 
00643    float b;
00644    *d >> b;
00645    PaperEffectBase::set_brig(b);
00646 }
00647 
00648 /////////////////////////////////////
00649 // put_view_paper_brig()
00650 /////////////////////////////////////
00651 void
00652 VIEW::put_view_paper_brig (TAGformat &d) const 
00653 {
00654    if ((!_in_data_file) && (_data_file != NULL_STR)) return;
00655    //Sanity check
00656    assert(!(_in_data_file && _data_file == NULL_STR));
00657 
00658    d.id();
00659    *d << PaperEffectBase::get_brig();
00660    d.end_id();
00661    
00662 }
00663 /////////////////////////////////////
00664 // get_view_texture()
00665 /////////////////////////////////////
00666 void
00667 VIEW::get_view_texture (TAGformat &d) 
00668 {
00669    //Sanity check - might change policy on 2nd part
00670    assert( ( _in_data_file && (_data_file != NULL_STR)) ||
00671            (!_in_data_file && (_data_file == NULL_STR))    );
00672 
00673    str_ptr str, space;
00674    *d >> str;      
00675 
00676    if (!(*d).ascii()) *d >> space; 
00677    
00678    if (str == "NULL_STR") 
00679    {
00680       err_mesg(ERR_LEV_SPAM, "VIEW::get_view_texture() - Loaded NULL string.");
00681       set_bkg_file(NULL_STR);
00682    }
00683    else
00684    {
00685       err_mesg(ERR_LEV_SPAM, "VIEW::get_view_texture() - Loaded string: '%s'", **str);
00686       set_bkg_file(Config::JOT_ROOT() + str);
00687    }
00688    
00689 }
00690 
00691 /////////////////////////////////////
00692 // put_view_texture()
00693 /////////////////////////////////////
00694 void
00695 VIEW::put_view_texture (TAGformat &d) const
00696 {
00697    if ((!_in_data_file) && (_data_file != NULL_STR)) return;
00698    //Sanity check
00699    assert(!(_in_data_file && _data_file == NULL_STR));
00700 
00701    //XXX - May need something to handle filenames with spaces
00702 
00703    d.id();
00704    if (get_bkg_file() == NULL_STR)
00705    {
00706       err_mesg(ERR_LEV_SPAM, "VIEW::put_view_texture() - Wrote NULL string.");
00707       *d << "NULL_STR";
00708       *d << " ";
00709    }
00710    else
00711    {
00712       //Here we strip off JOT_ROOT
00713       str_ptr tex = get_bkg_file();
00714       str_ptr str;
00715       int i;
00716       for (i=Config::JOT_ROOT().len(); i<(int)tex.len(); i++)
00717          str = str + str_ptr(tex[i]);
00718       *d << **str;
00719       *d << " ";
00720       err_mesg(ERR_LEV_SPAM, "VIEW::put_view_texture() - Wrote string: '%s'", **str);
00721    }
00722    d.end_id();
00723    
00724 }
00725 
00726 /////////////////////////////////////
00727 // get_view_light_coords()
00728 /////////////////////////////////////
00729 void
00730 VIEW::get_view_light_coords (TAGformat &d) 
00731 {
00732    //Sanity check - might change policy on 2nd part
00733    assert( ( _in_data_file && (_data_file != NULL_STR)) ||
00734            (!_in_data_file && (_data_file == NULL_STR))    );
00735 
00736    ARRAY<Wvec> c;
00737    *d >> c;
00738    assert(c.num() <= MAX_LIGHTS);
00739    for (int i=0; i<c.num(); i++)
00740       light_set_coordinates_v(i,c[i]);
00741    
00742 }
00743 
00744 /////////////////////////////////////
00745 // put_view_light_coords()
00746 /////////////////////////////////////
00747 void
00748 VIEW::put_view_light_coords (TAGformat &d) const
00749 {
00750    if ((!_in_data_file) && (_data_file != NULL_STR))
00751       return;
00752 
00753    ARRAY<Wvec> c;
00754    for (int i=0; i<MAX_LIGHTS; i++)
00755       c.add(light_get_coordinates_v(i));
00756     d.id();
00757    *d << c;
00758    d.end_id();
00759 }
00760 
00761 /////////////////////////////////////
00762 // get_view_light_positional()
00763 /////////////////////////////////////
00764 void
00765 VIEW::get_view_light_positional (TAGformat &d) 
00766 {
00767    //Sanity check - might change policy on 2nd part
00768    assert( ( _in_data_file && (_data_file != NULL_STR)) ||
00769            (!_in_data_file && (_data_file == NULL_STR))    );
00770 
00771    ARRAY<int> p;
00772    *d >> p;
00773    assert(p.num() <= MAX_LIGHTS);
00774    for (int i=0; i<MAX_LIGHTS; i++)
00775       light_set_positional(i,(p[i]==1)?(true):(false));
00776 }
00777 
00778 /////////////////////////////////////
00779 // put_view_light_positional()
00780 /////////////////////////////////////
00781 void
00782 VIEW::put_view_light_positional (TAGformat &d) const
00783 {
00784    if ((!_in_data_file) && (_data_file != NULL_STR))
00785       return;
00786 
00787    ARRAY<int> p;
00788    for (int i=0; i<MAX_LIGHTS; i++)
00789       p.add((light_get_positional(i))?(1):(0));
00790    d.id();
00791    *d << p;
00792    d.end_id();
00793   
00794 }
00795 
00796 /////////////////////////////////////
00797 // get_view_light_cam_space()
00798 /////////////////////////////////////
00799 void
00800 VIEW::get_view_light_cam_space (TAGformat &d) 
00801 {
00802    //Sanity check - might change policy on 2nd part
00803    assert( ( _in_data_file && (_data_file != NULL_STR)) ||
00804            (!_in_data_file && (_data_file == NULL_STR))    );
00805 
00806    ARRAY<int> c;
00807    *d >> c;
00808    assert(c.num() <= MAX_LIGHTS);
00809    for (int i=0; i<MAX_LIGHTS; i++)
00810       light_set_in_cam_space(i,((c[i]==1)?(true):(false)));
00811    
00812 }
00813 
00814 /////////////////////////////////////
00815 // put_view_light_cam_space()
00816 /////////////////////////////////////
00817 void
00818 VIEW::put_view_light_cam_space (TAGformat &d) const 
00819 {
00820    if ((!_in_data_file) && (_data_file != NULL_STR)) return;
00821    //Sanity checl
00822    assert(!(_in_data_file && _data_file == NULL_STR));
00823 
00824    ARRAY<int> c;
00825    for (int i=0; i<MAX_LIGHTS; i++)
00826       c.add((light_get_in_cam_space(i))?(1):(0));
00827     d.id();
00828    *d << c;
00829    d.end_id();
00830       
00831 }
00832 
00833 /////////////////////////////////////
00834 // get_view_light_color_diff()
00835 /////////////////////////////////////
00836 void
00837 VIEW::get_view_light_color_diff (TAGformat &d) 
00838 {
00839    //Sanity check - might change policy on 2nd part
00840    assert( ( _in_data_file && (_data_file != NULL_STR)) ||
00841            (!_in_data_file && (_data_file == NULL_STR))    );
00842 
00843    ARRAY<COLOR> c;
00844    *d >> c;
00845    assert(c.num() <= MAX_LIGHTS);
00846    for (int i=0; i<MAX_LIGHTS; i++)
00847       light_set_diffuse(i,c[i]);
00848 }
00849 
00850 /////////////////////////////////////
00851 // put_view_light_color_diff()
00852 /////////////////////////////////////
00853 void
00854 VIEW::put_view_light_color_diff (TAGformat &d) const 
00855 {
00856    if ((!_in_data_file) && (_data_file != NULL_STR)) return;
00857    //Sanity checl
00858    assert(!(_in_data_file && _data_file == NULL_STR));
00859 
00860    ARRAY<COLOR> c;
00861    for (int i=0; i<MAX_LIGHTS; i++)
00862       c.add(light_get_diffuse(i));
00863    d.id();
00864    *d << c;
00865    d.end_id();   
00866    
00867 }
00868 
00869 /////////////////////////////////////
00870 // get_view_light_color_amb()
00871 /////////////////////////////////////
00872 void
00873 VIEW::get_view_light_color_amb (TAGformat &d) 
00874 {
00875    //Sanity check - might change policy on 2nd part
00876    assert( ( _in_data_file && (_data_file != NULL_STR)) ||
00877            (!_in_data_file && (_data_file == NULL_STR))    );
00878 
00879    ARRAY<COLOR> a;
00880    *d >> a;
00881    assert(a.num() <= MAX_LIGHTS);
00882    for (int i=0; i<MAX_LIGHTS; i++)
00883       light_set_ambient(i,a[i]);
00884    
00885 }
00886 
00887 /////////////////////////////////////
00888 // put_view_light_color_amb()
00889 /////////////////////////////////////
00890 void
00891 VIEW::put_view_light_color_amb (TAGformat &d) const 
00892 {
00893    if ((!_in_data_file) && (_data_file != NULL_STR)) return;
00894    //Sanity checl
00895    assert(!(_in_data_file && _data_file == NULL_STR));
00896 
00897    ARRAY<COLOR> a;
00898    for (int i=0; i<MAX_LIGHTS; i++)
00899       a.add(light_get_ambient(i));
00900 
00901    d.id();
00902    *d << a;
00903    d.end_id();   
00904    
00905 }
00906 
00907 /////////////////////////////////////
00908 // get_view_light_color_global()
00909 /////////////////////////////////////
00910 void
00911 VIEW::get_view_light_color_global (TAGformat &d) 
00912 {
00913    //Sanity check - might change policy on 2nd part
00914    assert( ( _in_data_file && (_data_file != NULL_STR)) ||
00915            (!_in_data_file && (_data_file == NULL_STR))    );
00916 
00917    COLOR g;
00918    *d >> g;
00919    light_set_global_ambient(g);
00920  
00921 }
00922 
00923 /////////////////////////////////////
00924 // put_view_light_color_global()
00925 /////////////////////////////////////
00926 void
00927 VIEW::put_view_light_color_global (TAGformat &d) const 
00928 {
00929    if ((!_in_data_file) && (_data_file != NULL_STR)) return;
00930    //Sanity checl
00931    assert(!(_in_data_file && _data_file == NULL_STR));
00932 
00933    d.id();
00934    *d << light_get_global_ambient();
00935    d.end_id();
00936   
00937 }
00938 
00939 /////////////////////////////////////
00940 // get_view_light_enable()
00941 /////////////////////////////////////
00942 void
00943 VIEW::get_view_light_enable (TAGformat &d) 
00944 {
00945    //Sanity check - might change policy on 2nd part
00946    assert( ( _in_data_file && (_data_file != NULL_STR)) ||
00947            (!_in_data_file && (_data_file == NULL_STR))    );
00948 
00949    ARRAY<int> e;
00950    *d >> e;
00951    assert(e.num() <= MAX_LIGHTS);
00952    for (int i=0; i<MAX_LIGHTS; i++)
00953       light_set_enable(i,(e[i]==1)?(true):(false));
00954   
00955 }
00956 
00957 /////////////////////////////////////
00958 // put_view_light_enable()
00959 /////////////////////////////////////
00960 void
00961 VIEW::put_view_light_enable (TAGformat &d) const 
00962 {
00963    if ((!_in_data_file) && (_data_file != NULL_STR)) return;
00964    //Sanity checl
00965    assert(!(_in_data_file && _data_file == NULL_STR));
00966 
00967    ARRAY<int> e;
00968    for (int i=0; i<MAX_LIGHTS; i++)
00969       e.add((light_get_enable(i))?(1):(0));
00970    d.id();
00971    *d << e;
00972    d.end_id();
00973    
00974 }
00975 
00976 /////////////////////////////////////
00977 // get_view_antialias_enable()
00978 /////////////////////////////////////
00979 void
00980 VIEW::get_view_antialias_enable (TAGformat &d) 
00981 {
00982    //Sanity check - might change policy on 2nd part
00983    assert( ( _in_data_file && (_data_file != NULL_STR)) ||
00984            (!_in_data_file && (_data_file == NULL_STR))    );
00985 
00986    int e;
00987    *d >> e;
00988 
00989    set_antialias_enable(e!=0);
00990   
00991 }
00992 
00993 /////////////////////////////////////
00994 // put_view_antialias_enable()
00995 /////////////////////////////////////
00996 void
00997 VIEW::put_view_antialias_enable (TAGformat &d) const 
00998 {
00999    if ((!_in_data_file) && (_data_file != NULL_STR)) return;
01000    //Sanity check
01001    assert(!(_in_data_file && _data_file == NULL_STR));
01002 
01003    d.id();
01004    *d << get_antialias_enable();
01005    d.end_id();
01006 }
01007 
01008 
01009 /////////////////////////////////////
01010 // get_view_antialias_mode()
01011 /////////////////////////////////////
01012 void
01013 VIEW::get_view_antialias_mode (TAGformat &d) 
01014 {
01015    //Sanity check - might change policy on 2nd part
01016    assert( ( _in_data_file && (_data_file != NULL_STR)) ||
01017            (!_in_data_file && (_data_file == NULL_STR))    );
01018 
01019    int m;
01020    *d >> m;
01021 
01022    set_antialias_mode(m);
01023   
01024 }
01025 
01026 /////////////////////////////////////
01027 // put_view_antialias_mode()
01028 /////////////////////////////////////
01029 void
01030 VIEW::put_view_antialias_mode (TAGformat &d) const 
01031 {
01032    if ((!_in_data_file) && (_data_file != NULL_STR)) return;
01033    //Sanity check
01034    assert(!(_in_data_file && _data_file == NULL_STR));
01035 
01036    d.id();
01037    *d << get_antialias_mode();
01038    d.end_id();
01039 }
01040 
01041 #ifdef USE_PTHREAD
01042 VIEWptr
01043 VIEW::peek()
01044 {
01045    VIEW   *thread_view = ThreadToView::get();
01046    return thread_view ? VIEWptr(thread_view) : _views.last();
01047 }
01048 
01049 const VIEW *
01050 VIEW::peek_ptr()
01051 {
01052    VIEW   *thread_view = ThreadToView::get();
01053    return thread_view ? thread_view : &*_views.last();
01054 }
01055 #endif
01056 
01057 
01058 VIEW::VIEW(
01059    Cstr_ptr &s,
01060    WINSYS   *w,
01061    VIEWimpl *i ) :
01062    _in_data_file(false),
01063    _impl(i),
01064    _view_id(_num_views), 
01065    _cam(new CAM(str_ptr("camera"))),
01066    _cam_hist(100),
01067    _cam_hist_cur(0), // current camera starts at first index to set
01068    _width(0), 
01069    _height(0),
01070    _tris(0),
01071    _is_clipping(0), 
01072    _dont_swap(0), 
01073    _dont_draw(0),
01074    _messages_sent(0), 
01075    _has_scissor_region(0),
01076    _sxmin(-1), 
01077    _sxmax(1),// left- & right-most edges of scissored view
01078    _recorder(0), 
01079    _alpha(1), 
01080    _use_paper(false), 
01081    _bkg_file(NULL_STR), 
01082    _bkg_tex(NULL),
01083    _data_file(NULL_STR),
01084    _animator(0),
01085    _render_mode(NORMAL_MODE),
01086    _antialias_mode(2),
01087    _antialias_enable(0),
01088    _antialias_init(false),
01089    _line_scale(1.0), 
01090    _grabbing_screen(0),
01091    _spf(1.0 / Config::get_var_dbl("JOT_FPS",60)),
01092    _frame_time(0),
01093    _win(w)
01094 {
01095 #ifdef USE_PTHREAD
01096    ThreadToView::make_if_needed();
01097 #endif
01098    init_lights();
01099    init_jitter();
01100 
01101    _stereo      = VIEWimpl::NONE;
01102    _render_type = Config::get_var_str("JOT_RENDER_STYLE",RSMOOTH_SHADE);
01103    _name        = s;
01104    _tris        = 0;
01105 
01106    disp_obs();  // observe all changes to DRAWN
01107 
01108    _animator = new Animator(this);
01109    assert(_animator);
01110 
01111    _recorder = new Recorder(this);
01112    assert(_recorder);
01113 
01114    _num_views++;
01115 
01116    if (_rend_types.empty()) {
01117       
01118       add_rend_type(RSMOOTH_SHADE);
01119       add_rend_type(RFLAT_SHADE);
01120       add_rend_type(RHIDDEN_LINE);
01121 
01122       if (!Config::get_var_bool("JOT_MINIMAL_RENDER_STYLES",false)) {
01123          add_rend_type(RWIRE_FRAME);
01124          add_rend_type(RNORMALS);
01125          add_rend_type(RSHOW_TRI_STRIPS);
01126          add_rend_type(RKEY_LINE);
01127          add_rend_type(RSIL_FRAME);
01128       }
01129       if (Config::get_var_bool("ENABLE_CURVATURE_TEXTURE",false))
01130          add_rend_type(RCURVATURE);
01131       if (Config::get_var_bool("ENABLE_LINE_DRAWING",false))
01132          add_rend_type(RLINE_DRAWING);
01133       if (Config::get_var_bool("ENABLE_SKYBOX_TEXTURE",false))
01134          add_rend_type(SKYBOX_GRADIENT);
01135    }
01136    
01137    VIEWS.add(this);
01138 
01139    _impl->set_view(this);
01140 }
01141 
01142 void
01143 VIEW::set_jitter(
01144    int n,
01145    int i
01146    )
01147 {
01148    if (n==-1)
01149    {
01150       _jitter(0,3) = 0;
01151       _jitter(1,3) = 0;
01152    }
01153    else
01154    {
01155       assert(_jitters.valid_index(n));
01156       assert((*(_jitters[n])).valid_index(i));
01157       XYvec jit((*(_jitters[n]))[i]);
01158 
01159       _jitter(0,3) = -jit[0];
01160       _jitter(1,3) = -jit[1];
01161    }
01162 }
01163 
01164 
01165 void
01166 VIEW::init_jitter()
01167 {
01168    
01169    for(int n=0; n<JITTER_NUM; n++)
01170    {
01171       ARRAY<VEXEL>* jits = new ARRAY<VEXEL>(jnum[n]);
01172       _jitters.add(jits);
01173 
01174       for (int i=0; i<jnum[n]; i++)
01175          jits->add(VEXEL(j[n][i].x,j[n][i].y));
01176    }
01177 
01178 }
01179 
01180 void
01181 VIEW::init_lights()
01182 {
01183    _lights[0] = Light(
01184       DEFAULT_LIGHT_COORD_0,
01185       DEFAULT_LIGHT_ENABLE_0,
01186       DEFAULT_LIGHT_IN_CAM_SPACE_0,
01187       DEFAULT_LIGHT_AMBIENT_0,
01188       DEFAULT_LIGHT_DIFFUSE_0,
01189       DEFAULT_LIGHT_SPECULAR_0
01190       );
01191 
01192    _lights[1] = Light(
01193       DEFAULT_LIGHT_COORD_1,
01194       DEFAULT_LIGHT_ENABLE_1,
01195       DEFAULT_LIGHT_IN_CAM_SPACE_1,
01196       DEFAULT_LIGHT_AMBIENT_1,
01197       DEFAULT_LIGHT_DIFFUSE_1,
01198       DEFAULT_LIGHT_SPECULAR_1
01199       );
01200 
01201    _lights[2] = Light(
01202       DEFAULT_LIGHT_COORD_2,
01203       DEFAULT_LIGHT_ENABLE_2,
01204       DEFAULT_LIGHT_IN_CAM_SPACE_2,
01205       DEFAULT_LIGHT_AMBIENT_2,
01206       DEFAULT_LIGHT_DIFFUSE_2,
01207       DEFAULT_LIGHT_SPECULAR_2
01208       );
01209 
01210    _lights[3] = Light(
01211       DEFAULT_LIGHT_COORD_3,
01212       DEFAULT_LIGHT_ENABLE_3,
01213       DEFAULT_LIGHT_IN_CAM_SPACE_3,
01214       DEFAULT_LIGHT_AMBIENT_3,
01215       DEFAULT_LIGHT_DIFFUSE_3,
01216       DEFAULT_LIGHT_SPECULAR_3
01217       );
01218 
01219    _light_global_ambient   =  DEFAULT_LIGHT_GLOBAL_AMBIENT;
01220 }
01221 
01222 void 
01223 VIEW::set_frame_time(double t) 
01224 {
01225    if (_frame_time != t) {
01226       _frame_time = t;
01227       _frame_time_observers.frame_time_changed();
01228    }
01229 }
01230 
01231 void
01232 VIEW::paint()
01233 { 
01234    if (dont_draw())     // don't bother drawing if we haven't 
01235       return;           // flushed the previous frame yet
01236 
01237    // do nothing if time since last draw < secs per frame:
01238    if (_spf_timer.elapsed_time() < _spf)
01239       return;
01240    _spf_timer.set();
01241 
01242    _stamp++; 
01243 
01244    if (!_antialias_init)
01245       if (_impl && !_impl->antialias_check())
01246          _antialias_enable = 0;
01247 
01248    _pix_to_ndc_scale = (_width > _height ? 2.0/_height : 2.0/_width);
01249 
01250    // Animation/Camera animation stuff...
01251 
01252    // Sanity check
01253    assert(!(_recorder->on() && _animator->on()));
01254 
01255    if (_animator->on()) {
01256       set_frame_time(_animator->pre_draw_CB());
01257    } else if (_recorder->on()) { 
01258 
01259       // _recorder->pre_draw_CB() MAY set the frame time for this view
01260       // but it MAY NOT, depending on some convoluted logic that only
01261       // it knows.  So pre-emptively set it here first. (Meaning frame
01262       // time observers may get a notification with a wrong time
01263       // followed by a notification with a correct time.)
01264       set_frame_time(stop_watch::sys_time());
01265       _recorder->pre_draw_CB();
01266    } else {
01267       // XXX - should scale by time scale for slow-mo effects:
01268       set_frame_time(stop_watch::sys_time());
01269    }
01270 
01271    // It's handy to be able to display only the opaque or transparent
01272    // objects en mass for compositing runs.  The _render_mode decides
01273    // what in the active list gets drawn...
01274    _drawn.clear();
01275    if (_render_mode == NORMAL_MODE)
01276    {
01277       for (int i = 0; i < _active.num(); i++)
01278          if (!_active[i]->cull(this))   // bcz: handle CAVE culling properly
01279             _drawn += _active[i];
01280    }
01281    else if (_render_mode == OPAQUE_MODE)
01282    {
01283       for (int i = 0; i < _active.num(); i++)
01284          if ((!_active[i]->cull(this)) && (!_active[i]->needs_blend()))
01285             _drawn += _active[i];
01286    }
01287    else if (_render_mode == TRANSPARENT_MODE)
01288    {
01289       for (int i = 0; i < _active.num(); i++)
01290          if ((!_active[i]->cull(this)) && (_active[i]->needs_blend()))
01291             _drawn += _active[i];
01292    }
01293    else
01294    {
01295       assert(0);
01296    }
01297 
01298    // configure camera to render for _screen
01299    if (_screen) _screen->config_cam(_cam);
01300 
01301 
01302 
01303    if (!multithread) push(this);
01304 
01305    if (_impl) _tris = _impl->paint();
01306 
01307    if (!multithread) pop();
01308    
01309    if (!dont_swap())
01310       swap();
01311 }
01312 
01313 void        
01314 VIEW::swap()
01315 { 
01316    //Sanity check
01317    assert(!(_recorder->on() && _animator->on()));
01318    
01319    if ( _animator->on() )
01320    {
01321       _animator->post_draw_CB();
01322    }
01323    else if ( _recorder->on() ) 
01324    { 
01325       _recorder->post_draw_CB();
01326    }
01327    
01328    if (_impl) 
01329       _impl->swap_buffers(); 
01330 }
01331 
01332 
01333 
01334 
01335 RAYhit
01336 VIEW::intersect(
01337    RAYhit            &r,
01338    const GELFILTlist &filt
01339    ) const
01340 {
01341 #ifdef USE_PTHREAD
01342    assert(ThreadToView::get() == 0);
01343 #endif
01344    CVIEWptr this_view((VIEW *)this);
01345 
01346    push(this_view);
01347 
01348    GELFILTlist filter_list(filt);
01349 
01350    // Only add default GELFILTpickable filter if no such filter already exists
01351    bool has_pickable = false;
01352    for (int f = 0; !has_pickable && f < filter_list.num(); f++)
01353       has_pickable = 
01354          filter_list[f]->class_name() == GELFILTpickable::static_name();
01355 
01356    GELFILTpickable pick(0);  // The default filter
01357    if (!has_pickable)
01358       filter_list += &pick;
01359 
01360    for (int i = 0; i < _drawn.num(); i++ ) {
01361       if (filter_list.accept(_drawn[i]))
01362          _drawn[i]->intersect(r, Identity);
01363    }
01364 
01365    pop();
01366    return r;
01367 }
01368 
01369 
01370 //
01371 // Intersect all objects displayed in this view other than a particular one,
01372 // either interesecting text or not
01373 //
01374 RAYhit
01375 VIEW::intersect_others(
01376    RAYhit   &r,
01377    CGELlist &exclude,
01378    filt      filter
01379    ) const
01380 {
01381    GELFILTlist      filter_list;
01382 
01383    GELFILTothers          others(exclude);
01384    GELFILTpickable        pick  (1);
01385 
01386    // XXX -
01387    //   should use TEXT2D::static_name() below,
01388    //   but can't reference geom/text2d.H
01389    GELFILTclass_desc_excl no_text("TEXT2D");    
01390 
01391    filter_list += &others;
01392 
01393    if ((filter & H_TEXT) == 0)
01394       filter_list += &no_text; 
01395    if (filter & H_UNPICKABLE) 
01396       filter_list += &pick;
01397       
01398    return intersect(r, filter_list);
01399 }
01400 
01401 //
01402 // Intersect all objects displayed in this view, either interesecting text or
01403 // not
01404 //
01405 RAYhit
01406 VIEW::intersect(
01407    CXYpt  &xy,
01408    filt    filter
01409    ) const
01410 {
01411    RAYhit ray(xy);
01412    return intersect(ray,filter);
01413 }
01414 
01415 //
01416 // Intersect all objects displayed in this view, either interesecting text or
01417 // not
01418 //
01419 RAYhit
01420 VIEW::intersect(
01421    RAYhit &r,
01422    filt    filter
01423    ) const
01424 {
01425    GELFILTlist      filter_list;
01426    GELFILTpickable  pick(1);
01427 
01428    // XXX -
01429    //   should use TEXT2D::static_name() below,
01430    //   but can't reference geom/text2d.H
01431    GELFILTclass_desc_excl no_text("TEXT2D");    
01432 
01433    if ((filter & H_TEXT) == 0)
01434       filter_list += &no_text;
01435    if (filter & H_UNPICKABLE)
01436       filter_list += &pick;
01437 
01438    return intersect(r, filter_list);
01439 }
01440 
01441 //
01442 // Intersect all objects displayed in this view, either interesecting text or
01443 // not (set g parameter to be intersected GEOM)
01444 //
01445 RAYhit
01446 VIEW::intersect(
01447    RAYhit  &r,
01448    GELptr  &g,
01449    filt     filter
01450    ) const
01451 {
01452    intersect(r, filter);
01453    g = r.geom();
01454 
01455    return r;
01456 }
01457 
01458 //
01459 // Intersect all objects displayed in this view with a particular class name,
01460 // either interesecting text or not
01461 //
01462 RAYhit
01463 VIEW::intersect(
01464    RAYhit   &r,
01465    Cstr_ptr &cn,
01466    filt      filter
01467    ) const
01468 {
01469    for (int i = 0; i < _drawn.num(); i++)
01470       if (_drawn[i]->class_name() == cn && 
01471           (PICKABLE.get(_drawn[i]) || (filter & H_UNPICKABLE)))
01472          _drawn[i]->intersect(r, Identity);
01473 
01474    return r;
01475 }
01476 
01477 
01478 RAYnear
01479 VIEW::nearest(
01480    RAYnear   &r,
01481    filt       filter
01482    ) const
01483 {
01484    for (int i = 0; i < _drawn.num(); i++)
01485       if (PICKABLE.get(_drawn[i]) || (filter & H_UNPICKABLE))
01486          _drawn[i]->nearest(r, Identity);
01487 
01488    return r;
01489 }
01490 
01491 RAYnear
01492 VIEW::nearest(
01493    RAYnear    &r,
01494    Cstr_ptr   &cn,
01495    filt        filter
01496    ) const
01497 {
01498    for (int i = 0; i < _drawn.num(); i++)
01499       if (_drawn[i]->class_name() == cn &&
01500           (PICKABLE.get(_drawn[i]) || (filter & H_UNPICKABLE)))
01501          _drawn[i]->nearest(r, Identity);
01502 
01503    return r;
01504 }
01505 
01506 
01507 //
01508 // Returns GEOM's that are within the lasso and can be copied
01509 //
01510 GELlist
01511 VIEW::inside(
01512    CXYpt_list &lasso
01513    ) const
01514 {
01515    GELlist objs;
01516    VIEWptr  v((VIEW *)this);
01517    for (int i = 0; i < _drawn.num(); i++)
01518       if (!NO_COPY.get(_drawn[i]) && _drawn[i]->inside(lasso))
01519          objs += _drawn[i];
01520 
01521    return objs;
01522 }
01523 
01524 void
01525 VIEW::save_cam(CCAMptr c)
01526 {
01527    /* delete rest of fwd history if we backed up */
01528    if (_cam_hist.valid_index(_cam_hist_cur ))
01529       _cam_hist.truncate(_cam_hist_cur );
01530 
01531    CAMptr cptr = new CAM("history");
01532    *cptr = (c ? *c : *_cam);
01533    _cam_hist += cptr;
01534    _cam_hist_cur++;
01535 
01536    err_mesg_cond(Config::get_var_bool("DEBUG_CAM_HISTORY",false,true), 
01537       ERR_LEV_ERROR, "VIEW::save_cam() - Saved camera. cam_hist = %d.", _cam_hist_cur);
01538 }
01539 
01540 void
01541 VIEW::fwd_cam_hist()
01542 {
01543   if (_cam_hist_cur >= (_cam_hist.num()-1) ){
01544     /* already at max */
01545   } else {
01546     new CamFocus(this, _cam_hist[++_cam_hist_cur]);
01547   }
01548 }
01549 
01550 void
01551 VIEW::bk_cam_hist()
01552 {
01553   if(_cam_hist_cur<=0) return;
01554 
01555   /* if we're at the end, make sure we've saved the current one */
01556   if(_cam_hist_cur >= _cam_hist.num()){
01557     save_cam();
01558     _cam_hist_cur--;
01559   }
01560   new CamFocus(this, _cam_hist[--_cam_hist_cur]);
01561 }
01562 
01563 void
01564 VIEW::copy_cam(CCAMptr &c)
01565 {
01566    assert(_cam != NULL);
01567 
01568    if (c != NULL)
01569       *_cam = *c;
01570    else
01571       err_msg("VIEW::copy_cam: given CAMptr is null");
01572 }
01573 
01574 void
01575 VIEW::use_cam(CCAMptr &c)
01576 {
01577    if (c == NULL) {
01578       err_msg("VIEW::use_cam: can't use null CAM");
01579       return;
01580    }
01581 
01582    _cam = c;
01583 }
01584 
01585 void
01586 VIEW::set_size(
01587    int w, 
01588    int h, 
01589    int x, 
01590    int y
01591    )
01592 {
01593    _width  = w;
01594    _height = h;
01595 
01596    _cam->data()->changed();
01597 
01598    if (_impl)
01599       _impl->set_size(w,h, x, y);
01600 
01601 //XXX - Changing size (say during some AuxRefImage stuff)
01602 //      mucks up some cached values, so we update the 
01603 //      stamp, etc.
01604 //      Some cached stuff may still be dangling...(?)
01605 
01606    _stamp++; 
01607 
01608    _pix_to_ndc_scale = (_width > _height ? 2.0/_height : 2.0/_width);
01609 
01610 }
01611 
01612 
01613 Wtransf   
01614 VIEW::wpt_proj(SCREENptr s, CAMdata::eye e) const 
01615 {
01616    return _jitter * _lens * _cam->projection_xform(s,e); 
01617 }
01618 
01619 Wtransf 
01620 VIEW::xypt_proj() const 
01621 { 
01622    return _jitter * _lens; 
01623 }
01624 
01625 // returns projection matrix to use for
01626 // drawing normalized device coords to the window
01627 Wtransf     
01628 VIEW::ndc_proj()  const
01629 {
01630    Wtransf ret;
01631 
01632    if (_width > _height) ret(0,0) = double(_height)/_width;
01633    else                  ret(1,1) = double(_width)/_height;
01634 
01635    return _jitter * _lens * ret;
01636 }
01637 
01638 // returns projection matrix to use for
01639 // drawing pixel coords to the window
01640 Wtransf     
01641 VIEW::pix_proj()  const
01642 {
01643    Wtransf ret;
01644 
01645    ret(0,0) = 2.0/_width;
01646    ret(0,3) = -1;
01647    ret(1,1) = 2.0/_height;
01648    ret(1,3) = -1;
01649 
01650    return _jitter * _lens * ret;
01651 }
01652 
01653 
01654 // returns projection matrix to use for
01655 // converting Wpt to its pixel coordinates
01656 Wtransf     
01657 VIEW::wpt_to_pix_proj(SCREENptr s, CAMdata::eye e)  const
01658 {
01659   Wtransf world, ndc, pix;
01660 
01661   world = _cam->projection_xform(s,e)*_cam->xform(s,e);
01662 
01663   if (_width > _height) ndc(0,0) = double(_width)/_height;
01664   else                  ndc(1,1) = double(_height)/_width; 
01665 
01666   pix(0,0) = _width/2.0;
01667   pix(0,3) = _width/2.0;
01668   pix(1,1) = _height/2.0;
01669   pix(1,3) = _height/2.0;
01670 
01671   Wtransf ret = pix*ndc*world;
01672   // TODO: why w=0 after cam xform ?
01673   return ret;
01674 }
01675 
01676 //
01677 // Removes GEOM from the VIEW's drawn list - use WORLD::undisplay instead
01678 //
01679 int
01680 VIEW::undisplay(
01681    CGELptr &o
01682    )
01683 { 
01684    for (int i=0; i < _active.num(); i++)
01685       if (_active[i] == o) {
01686          _active.rem(o);
01687          _drawn .rem(o);
01688          return 1;
01689       }
01690    return 0;
01691 }
01692 
01693 //
01694 // Adds GEOM to the VIEW's drawn list - use WORLD::display instead
01695 //
01696 int
01697 VIEW::display(
01698    CGELptr &o
01699    )
01700 { 
01701    if (o != GELptr(0)) {
01702       for (int i=0; i < _active.num(); i++)
01703          if (_active[i] == o)
01704             return 0;
01705       _active.add(o); 
01706       return 1;
01707    } 
01708    return 0;
01709 }
01710 
01711 // we're overriding the tick method on the GEL object.  In addition to
01712 // allowing the app to associate some callback with this VIEW, we also let
01713 // other objects register with us, and then we exec() them.
01714 int
01715 VIEW::tick(void)
01716 {
01717    // for some reason this is sometimes called twice within the same frame:
01718 
01719    if (0) {
01720       cerr << "VIEW::tick: frame number " << stamp() << endl;
01721 
01722       static uint last_stamp = 0;
01723       if (last_stamp == stamp()) {
01724          cerr << "VIEW::tick: repeating frame: " << stamp() << endl;
01725       }
01726       last_stamp = stamp();
01727    }
01728    for (int i = 0; i < _scheduled.num(); i++)
01729       if (_scheduled[i]->tick() == -1) {
01730          _scheduled.rem(_scheduled[i]);
01731          i--; // cause the last object in the
01732               // list gets put where the object
01733               // that was deleted was
01734       }
01735    return 1;
01736 }
01737 
01738 void
01739 VIEW::screen_grab(
01740    int       scale_factor, 
01741    Image    &output
01742    )
01743 {
01744    bool alpha = Config::get_var_bool("GRAB_ALPHA",true,true);
01745 
01746 
01747    // sanity check:
01748    const int n = max(1,scale_factor);
01749 
01750    // make sure output is large output image (n times larger in each dimension)
01751    assert(int(output.width()) >= n * _width && int(output.height()) >= n * _height);
01752 
01753    // for drawing lines:
01754    _line_scale = n;
01755 
01756    _grabbing_screen = 1;
01757 
01758    // XXX - make sure silhouettes are up-to-date
01759    //       should do this right
01760    // _stamp++;
01761 
01762    // prepare "tile" image (same size as whole window),
01763    int a = (alpha)?(4):(3);
01764    Image    tile(_width,_height,a);             // format for RGB
01765 
01766    if (_impl)
01767       _impl->prepare_buf_read();
01768 
01769    // matrix _lens is the "lens" that selects a particular sub-region (or
01770    // "tile") of the screen to be rendered at full window-resolution. we simply
01771    // set _lens to select each tile of the window in turn, render it at full
01772    // resolution, then copy the data into the appropriate slot of the output
01773    // image.
01774 
01775    // _lens is initially the Identity matrix.
01776    _lens(0,0) = n;         // scale x and y by n
01777    _lens(1,1) = n;         // (translational component added below)
01778    
01779    // divide visible window into n^2 tiles (n x n).
01780    // render each one at the resolution of the window.
01781    // copy the pixels of each tile into the output image.
01782    // finally write the output image.
01783    //
01784    // i varies horizontally from 0 to n-1
01785    // j varies vertically from 0 to n-1
01786    // thus (i,j) designates a particular tile
01787 
01788    for (int j=0; j<n; j++) {
01789       // set vertical translation for lens:
01790       _lens(1,3) = n - 2*j - 1;
01791       for (int i=0; i<n; i++) {
01792          // set horizontal translation for lens:
01793          _lens(0,3) = n - 2*i - 1;
01794 
01795          if (_impl) // clear back buffer, set state, draw objects:
01796             _impl->read_pixels(tile.data(),alpha);
01797 
01798          // copy the pixels into the large output image:
01799          output.copy_tile(tile,i,j);
01800       }
01801    }
01802    
01803    // restore lens:
01804    _lens(0,0) = _lens(1,1) = 1;
01805    _lens(0,3) = _lens(1,3) = 0;
01806 
01807    // restore line scale:
01808    _line_scale = 1.0;
01809 
01810    _grabbing_screen = 0;
01811 
01812    if (_impl)
01813       _impl->end_buf_read();
01814 }
01815 
01816 
01817 int
01818 VIEW::screen_grab(
01819    int       scale_factor, 
01820    Cstr_ptr& filename
01821    )
01822 {
01823    bool alpha = Config::get_var_bool("GRAB_ALPHA",true,true);
01824 
01825    // Grabs current scene as a hi-res image --
01826    // scaled n times the size of the current window
01827    // in each dimension.
01828 
01829    // sanity check:
01830    const int n = max(1,scale_factor);
01831    int a = (alpha)?(4):(3);
01832    Image    output(n*_width, n*_height,a);      // format for RGB
01833 
01834    screen_grab(scale_factor, output);
01835 
01836    // write output. return 1 for success, 0 for failure:
01837    if (!output.write_png(**filename)) {
01838       // failed.  try writing as pnm (actually a ppm file)
01839       return output.write_pnm(**filename);
01840    } else {
01841       // success writing as png file
01842       return 1;
01843    }
01844 }
01845 
01846 void
01847 VIEW::viewall()
01848 {
01849    // Bring the camera back to where it can see everything
01850    // in the scene. (Useful when the camera gets lost in space):
01851 
01852    BBOX bb;
01853    for (int i=0; i<_active.num(); i++)
01854       bb += _active[i]->bbox();
01855    
01856    CAMdataptr camdata = cam()->data();
01857    double size = bb.dim().length();
01858    double dist = size * camdata->focal() / camdata->height();
01859    Wvec   dirvec = -Wvec::Z();
01860 
01861    Wpt from = bb.center() + dist * dirvec;
01862    new CamFocus(
01863       this,
01864       from,
01865       bb.center(),
01866       from + Wvec::Y(),
01867       bb.center(),
01868       camdata->width(),
01869       camdata->height()
01870       );
01871 }
01872 
01873 void
01874 VIEW::set_color(CCOLOR &c) 
01875 {
01876    if (c != _bkgnd_col) {
01877       _bkgnd_col = c;
01878       VIEWobs::notify_viewobs(this, COLOR_ALPHA_CHANGED);
01879    }
01880 }
01881 
01882 void
01883 VIEW::set_alpha(double a)
01884 {
01885    if (_alpha != a) {
01886       _alpha = a;
01887       VIEWobs::notify_viewobs(this, COLOR_ALPHA_CHANGED);
01888    }
01889 }
01890 
01891 void
01892 VIEW::set_render_mode(render_mode_t r)
01893 {
01894    if (_render_mode != r) {
01895       _render_mode = r;
01896       VIEWobs::notify_viewobs(this, UNKNOWN_CHANGED);
01897    }
01898 }
01899 
01900 Wpt
01901 xy_to_w_1(CXYpt& x, CWpt& w) 
01902 {
01903    return VIEW::peek_cam_const()->xy_to_w(x,w); 
01904 }
01905 
01906 Wpt
01907 xy_to_w_2(CXYpt& x, double d) 
01908 {
01909    return VIEW::peek_cam_const()->xy_to_w(x,d); 
01910 }
01911 
01912 Wpt
01913 xy_to_w_3(CXYpt& x) 
01914 {
01915    return VIEW::peek_cam_const()->xy_to_w(x); 
01916 }
01917 
01918 Wvec
01919 xy_to_wvec(CXYpt& x) 
01920 {
01921    return VIEW::peek_cam_const()->film_dir(x); 
01922 }
01923 
01924 XYpt 
01925 w_to_xy(CWpt& w) 
01926 {
01927    return VIEW::peek_cam_const()->w_to_xy(w); 
01928 }
01929 
01930 void 
01931 view_size (int& w, int& h)
01932 {
01933    VIEW::peek_size(w,h); 
01934 }
01935 
01936 double
01937 view_aspect()
01938 {
01939    return VIEW::peek_cam_const()->aspect(); 
01940 }
01941 
01942 void
01943 view_pixels(double& z, NDCpt& p)
01944 {
01945    z=VIEW::peek_cam_const()->zoom();
01946    p=VIEW::peek_cam_const()->min(); 
01947 }
01948 
01949 CWtransf& 
01950 view_ndc_trans()
01951 {
01952    return VIEW::peek_cam()->ndc_projection();
01953 }
01954 
01955 CWtransf& 
01956 view_ndc_trans_inv()
01957 {
01958    return VIEW::peek_cam()->ndc_projection_inv();
01959 }
01960 
01961 /*****************************************************************
01962  * Function pointers used in mlib for converting between
01963  * coordinate types:
01964  *****************************************************************/
01965 Wpt     (*XYtoW_1       )(CXYpt &, CWpt &)   = xy_to_w_1;
01966 Wpt     (*XYtoW_2       )(CXYpt &, double)   = xy_to_w_2;
01967 Wpt     (*XYtoW_3       )(CXYpt &)           = xy_to_w_3;
01968 Wvec    (*XYtoWvec      )(CXYpt &)           = xy_to_wvec;
01969 XYpt    (*WtoXY         )(CWpt  &)           = w_to_xy;
01970 void    (*VIEW_SIZE     )(int &, int &)      = view_size;
01971 double  (*VIEW_ASPECT   )()                  = view_aspect;
01972 void    (*VIEW_PIXELS   )(double &, NDCpt &) = view_pixels;
01973 CWtransf& (*VIEW_NDC_TRANS)()                = view_ndc_trans;
01974 CWtransf& (*VIEW_NDC_TRANS_INV)()            = view_ndc_trans_inv;
01975 
01976 double at_length(CWpt& p, double length)
01977 {   
01978    CWpt from = VIEW::peek_cam()->data()->from();
01979    Wvec at_v = VIEW::peek_cam()->data()->at_v();
01980    Wvec right= VIEW::peek_cam()->data()->right_v();
01981    
01982    double dist = from.dist(p);
01983    CWpt new_p = from + (at_v * dist);
01984    CWpt new_q = new_p + (right * length);
01985    return PIXEL(new_p).dist(new_q);
01986 }
01987 
01988 /* end of file view.C */

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