00001 #include "disp/cam_focus.H"
00002 #include "disp/ray.H"
00003 #include "disp/view.H"
00004 #include "geom/geom.H"
00005 #include "geom/body.H"
00006 #include "geom/gl_view.H"
00007 #include "geom/gl_util.H"
00008 #include "std/config.H"
00009
00010 #include "std/thread_mutex.H"
00011
00012 using namespace mlib;
00013
00014 BODY* BODY::_factory = 0;
00015 CXYpt_list BODY::_dummy(0);
00016
00017 int MOD::_TICK = 0;
00018 int MOD::_START = 0;
00019 GEOM* GEOM::null;
00020 TAGlist* GEOM::_geom_tags;
00021
00022 bool GEOM::_do_halo_view = Config::get_var_bool("DO_VIEW_HALOS",false);
00023 bool GEOM::_do_halo_ref = Config::get_var_bool("DO_REF_HALOS", true);
00024
00025
00026
00027
00028 MAKE_NET_HASHVAR (XFORM_ON_BODY, int, 0);
00029 MAKE_NET_HASHVAR (HIGHLIGHTED , int, 0);
00030 XformConstraint CONSTRAINT("CONSTRAINT", GEOM::TRANS_FREE, 1);
00031
00032
00033 static int gm=DECODER_ADD(GEOM);
00034
00035 STDdstream &
00036 operator>>(STDdstream &ds, GEOMptr &p)
00037 {
00038 DATA_ITEM *d = DATA_ITEM::Decode(ds);
00039 if (d && GEOM::isa(d))
00040 p = (GEOM *)d;
00041 else {
00042 cerr << "operator >> Couldn't find GEOM in stream" << endl;
00043 p = 0;
00044 }
00045
00046 return ds;
00047 }
00048
00049
00050
00051
00052
00053 RAYnear &
00054 GEOM::nearest(RAYnear &r, CWtransf &) const
00055 {
00056 return r;
00057 }
00058
00059 void
00060 GEOM::set_body(CBODYptr& b)
00061 {
00062 if (b == _body)
00063 return;
00064 if (_body)
00065 _body->set_geom(0);
00066 _body = b;
00067 if (_body)
00068 _body->set_geom(this);
00069 }
00070
00071 CWtransf&
00072 GEOM::inv_xform () const
00073 {
00074 if (_inv_xf_dirty) {
00075 GEOM *me = (GEOM*)this;
00076 me->_inv_xf=xform().inverse();
00077 me->_inv_xf_dirty = 0;
00078 }
00079 return _inv_xf;
00080 }
00081
00082 bool
00083 GEOM::find_cam_focus(CVIEWptr& view, mlib::CXYpt& x)
00084 {
00085 static const bool debug = Config::get_var_bool("DEBUG_CAM_FOCUS",false);
00086
00087 RAYhit r(view->intersect(x));
00088 GEOMptr geom = GEOM::upcast(r.geom());
00089 if (geom) {
00090 return geom->do_cam_focus(view, r);
00091 }
00092
00093 if (debug) {
00094 cerr << "GEOM::find_cam_focus: nothing to focus on" << endl;
00095 }
00096 return false;
00097 }
00098
00099 bool
00100 GEOM::do_cam_focus(CVIEWptr& view, CRAYhit& r)
00101 {
00102 if (Config::get_var_bool("DEBUG_CAM_FOCUS",false))
00103 cerr << "GEOM::do_cam_focus (" << name() << ")"
00104 << endl;
00105
00106 assert(r.geom() == this);
00107
00108 CAMptr cam (view->cam());
00109 CAMdataptr data(cam->data());
00110
00111
00112
00113
00114 XYvec D(VEXEL(25,0));
00115 RAYhit sil_r(r.screen_point() + D);
00116 RAYhit sil_l(r.screen_point() - D);
00117 intersect(sil_r);
00118 intersect(sil_l);
00119
00120
00121
00122
00123 if (rad2deg(r.norm().angle(Wvec::Y())) > 12.0 &&
00124 XOR(sil_r.success(), sil_l.success())) {
00125 Wvec sil_comp;
00126 if (sil_r.success())
00127 sil_comp = -data->right_v() * 6.0 * r.dist();
00128 else
00129 sil_comp = data->right_v() * 6.0 * r.dist();
00130
00131 Wvec v(sil_comp + r.norm() * 4.0 * r.dist());
00132 Wpt newpos(r.surf() + r.dist() * v.normalized());
00133 newpos[1] = data->from()[1];
00134 newpos = r.surf() + (newpos - r.surf()).normalized() * r.dist();
00135
00136 new CamFocus(view, newpos, r.surf(), newpos + Wvec::Y(), r.surf(),
00137 data->width(), data->height());
00138 } else {
00139
00140 Wpt center(r.surf());
00141 Wvec norm (r.norm().normalized());
00142 if (norm * Wvec::Y() > 0.98)
00143 norm = -data->at_v();
00144
00145 Wvec off (cross(Wvec::Y(),norm).normalized() * 3);
00146 Wvec atv (data->at_v() - Wvec::Y() * (data->at_v() * Wvec::Y()));
00147 Wvec newvec(norm*6 + 4.0*Wvec::Y());
00148 if ((center + newvec + off - data->from()).length() >
00149 (center + newvec - off - data->from()).length())
00150 off = newvec - off;
00151 if (data->persp())
00152 off = (newvec + off).normalized() *
00153 (data->from()-Wline(data->from(),data->at()).project(center)).
00154 length();
00155
00156 new CamFocus(view, center + off, center, center + off + Wvec::Y(),
00157 center, data->width(), data->height());
00158 }
00159 return true;
00160 }
00161
00162
00163
00164 GEOM::GEOM() :
00165 GEL(),
00166 _inv_xf_dirty(1),
00167 _bbox_id(-1)
00168 {
00169 }
00170
00171 GEOM::GEOM(Cstr_ptr &n, CBODYptr& b) :
00172 GEL(),
00173 _name(n),
00174 _body(b),
00175 _inv_xf_dirty(1),
00176 _bbox_id(-1)
00177 {
00178 if (_body)
00179 _body->set_geom(this);
00180 }
00181
00182 GEOM::GEOM(
00183 CGEOMptr &o,
00184 Cstr_ptr &name
00185 ) :
00186 GEL(o),
00187 APPEAR(o),
00188 _name(name),
00189 _xform(o->_xform),
00190 _inv_xf_dirty(1),
00191 _bbox_id(-1)
00192 {
00193 if (o && o->body()) {
00194 _body = (BODY*)o->body()->dup();
00195 assert(_body != 0);
00196 _body->set_geom(this);
00197 *_body = *o->body();
00198 }
00199 }
00200
00201 GEOM::~GEOM()
00202 {
00203 }
00204
00205 CTAGlist &
00206 GEOM::tags() const
00207 {
00208 if (!_geom_tags) {
00209 _geom_tags = new TAGlist;
00210 *_geom_tags += GEL::tags();
00211 *_geom_tags += new TAG_meth<GEOM>("name", &GEOM::put_name,
00212 &GEOM::get_name, 0);
00213 *_geom_tags += new TAG_meth<GEOM>("xform", &GEOM::put_xf,
00214 &GEOM::get_xf, 0);
00215 *_geom_tags += new TAG_meth<GEOM>("color", &GEOM::put_color,
00216 &GEOM::get_color);
00217 *_geom_tags += new TAG_meth<GEOM>("texture",&GEOM::put_texture,
00218 &GEOM::get_texture,1);
00219 *_geom_tags += new TAG_meth<GEOM>("transp",&GEOM::put_transp,
00220 &GEOM::get_transp);
00221 }
00222 return *_geom_tags;
00223 }
00224
00225
00226
00227 int
00228 GEOM::draw(CVIEWptr &v)
00229 {
00230 if (!_body)
00231 return 0;
00232
00233 glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT);
00234
00235
00236 GL_VIEW::init_polygon_offset();
00237
00238
00239 if (!xform().is_orthonormal())
00240 glEnable (GL_NORMALIZE);
00241
00242
00243 GL_COL(_has_color ? _color : COLOR::white, _has_transp ? _transp : 1);
00244
00245
00246 glMatrixMode(GL_MODELVIEW);
00247 glPushMatrix();
00248 glMultMatrixd(xform().transpose().matrix());
00249
00250
00251 int ret = _body->draw(v);
00252
00253 glPopMatrix();
00254
00255 GL_VIEW::end_polygon_offset();
00256
00257 glPopAttrib();
00258
00259 return ret;
00260 }
00261
00262 int
00263 GEOM::draw_vis_ref()
00264 {
00265 if (!_body)
00266 return 0;
00267
00268 glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT);
00269 glMatrixMode(GL_MODELVIEW);
00270 glPushMatrix();
00271
00272 glMultMatrixd(xform().transpose().matrix());
00273
00274
00275 GL_VIEW::init_polygon_offset();
00276 int ret = _body->draw_vis_ref();
00277 GL_VIEW::end_polygon_offset();
00278
00279 glPopMatrix();
00280 glPopAttrib();
00281
00282 return ret;
00283 }
00284
00285 int
00286 GEOM::draw_ref_img(ref_img_t t)
00287 {
00288 if (!_body)
00289 return 0;
00290
00291 glMatrixMode(GL_MODELVIEW);
00292 glPushMatrix();
00293 glMultMatrixd(xform().transpose().matrix());
00294
00295 GL_VIEW::init_polygon_offset();
00296 int ret = _body->draw_ref_img(t);
00297 GL_VIEW::end_polygon_offset();
00298
00299 glPopMatrix();
00300
00301 return ret;
00302 }
00303
00304 RefImageClient::ref_img_t
00305 GEOM::use_ref_image()
00306 {
00307 return _body ? _body->use_ref_image() : REF_IMG_NONE;
00308 }
00309
00310 int
00311 GEOM::draw_final(CVIEWptr &v)
00312 {
00313 if (!_body)
00314 return 0;
00315
00316 glMatrixMode(GL_MODELVIEW);
00317 glPushMatrix();
00318 glMultMatrixd(xform().transpose().matrix());
00319
00320 int ret = _body->draw_final(v);
00321
00322 glPopMatrix();
00323
00324 return ret;
00325 }
00326
00327 RAYhit&
00328 GEOM::intersect(RAYhit& ray, CWtransf&, int) const
00329 {
00330 if (_body) {
00331 _body->intersect(ray, xform());
00332 }
00333 return ray;
00334 }
00335
00336 MAKE_NET_HASHVAR(NO_CULL, int, 0);
00337
00338 bool
00339 GEOM::cull(
00340 const VIEW *
00341 ) const
00342 {
00343
00344 CBODYptr &bod = body();
00345 if (!bod || NO_CULL.get(((GEOM *)this)))
00346 return 0;
00347
00348
00349 return bbox().is_off_screen();
00350 }
00351
00352
00353 static ThreadMutex bbox_mutex;
00354
00355
00356
00357
00358
00359 BBOX
00360 GEOM::bbox(int) const
00361 {
00362 if (!body()) {
00363 ((GEOM *) this)->_bbox.reset();
00364 } else {
00365 CriticalSection cs(&bbox_mutex);
00366 if (!body()->bb_valid()) {
00367 BBOX bb = body()->get_bb();
00368 double s = 1.0;
00369 Wtransf xf = Wtransf::scaling(xform() * bb.center(), s) * xform();
00370 ((GEOM*)this)->_bbox = xf * bb;
00371 }
00372 }
00373 return _bbox;
00374 }
00375
00376
00377
00378
00379
00380 ostream &
00381 GEOM::print(ostream &os) const
00382 {
00383 os << class_name() << "::" << name() << "\n\t";
00384 return os;
00385 }
00386
00387
00388
00389
00390
00391 void
00392 GEOM::write_xform(
00393 CWtransf &x,
00394 CWtransf &y,
00395 CMOD &m
00396 )
00397 {
00398 _xform = x;
00399 _inv_xf_dirty = true;
00400 REFlock lock(this);
00401 XFORMobs::notify_xform_every_obs(this);
00402 }
00403
00404 void
00405 GEOM::mult_by(
00406 CWtransf &x
00407 )
00408 {
00409 write_xform(x * _xform, Wtransf(), MOD());
00410 }
00411
00412 void
00413 GEOM::set_color(
00414 CCOLOR &c
00415 )
00416 {
00417 REFlock lock(this);
00418 APPEAR::set_color(c);
00419 COLORobs::notify_color_obs(this);
00420 }
00421
00422 void
00423 GEOM::unset_color()
00424 {
00425 REFlock lock(this);
00426 APPEAR::unset_color();
00427 COLORobs::notify_color_obs(this);
00428 }
00429
00430 void
00431 GEOM::set_texture(CTEXTUREptr& t)
00432 {
00433 REFlock lock(this);
00434 APPEAR::set_texture(t);
00435 TEXTUREobs::notify_texture_obs(this);
00436 }
00437
00438 void
00439 GEOM::unset_texture()
00440 {
00441 REFlock lock(this);
00442 APPEAR::unset_texture();
00443 TEXTUREobs::notify_texture_obs(this);
00444 }
00445
00446
00447
00448
00449 GEOMobs_list GEOMobs::_all_geom(32);
00450
00451
00452
00453 TRANSPobs_list TRANSPobs::_all_transp(32);
00454
00455
00456
00457 COLORobs_list *COLORobs::_all_col = 0;
00458
00459
00460
00461 TEXTUREobs_list *TEXTUREobs::_all_texture = 0;
00462
00463
00464
00465 XFORMobs_list XFORMobs::_every_xf(32);
00466 XFORMobs_list XFORMobs::_all_xf(32);
00467 HASH XFORMobs::_hash_xf(32);
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479 void
00480 XFORMobs::notify_xform_obs(
00481 CGEOMptr &g,
00482 XFORMobs::STATE st
00483 )
00484 {
00485
00486 int i;
00487 for (i = 0; i < _all_xf.num(); i++)
00488 _all_xf[i]->notify_xform(g, st);
00489
00490
00491 XFORMobs_list &list = xform_obs_list(g);
00492 for (i = 0; i <list.num(); i++) {
00493 XFORMobs *obs = list[i];
00494 obs->notify_xform(g, st);
00495 }
00496 }
00497
00498 void
00499 XFORMobs::notify_xform_every_obs(
00500 CGEOMptr &g
00501 )
00502 {
00503
00504 int i;
00505 for (i = 0; i < _every_xf.num(); i++)
00506 _every_xf[i]->notify_xform(g, EVERY);
00507 }