00001 #include "std/support.H"
00002 #include "std/config.H"
00003 #include "disp/cam_focus.H"
00004 #include "net/stream.H"
00005 #include "net/net_types.H"
00006
00007
00008 using namespace mlib;
00009
00010 CAMdata::CAMdata(CAM* c) :
00011 _cam(c),
00012 _from(0,0,5),
00013 _at(0,0,0),
00014 _up(0,1,5),
00015 _center(0,0,0),
00016 _focal(1),
00017 _width(1),
00018 _height(1),
00019 _perspective(true),
00020 _tilt_up(0),
00021 _tilt_left(0),
00022 _iod(2.25),
00023 _feature_scale(0.5),
00024 _film_normal(0,0,1),
00025 _film_normal_flag(false),
00026 _loaded_from_file(false),
00027 _cblist(0),
00028 _cached(0),
00029 _stamp(0)
00030 {
00031 _iod = Config::get_var_dbl("IOD",2.25,true);
00032 changed();
00033 }
00034
00035
00036 void
00037 CAMdata::cache() const
00038 {
00039 if (!_cached) {
00040 CAMdata *me = (CAMdata *)this;
00041 me->_cached = 1;
00042 me->_dist = (_center-_from).length();
00043 me->_at_v = (_at-_from).normalized();
00044 me->_up_v = (_up-_from).normalized();
00045 me->_pup_v = _up_v.orthogonalized(_at_v).normalized();
00046 me->_right_v = cross(_at_v, _pup_v).normalized();
00047 }
00048 }
00049
00050 void
00051 CAMdata::changed()
00052 {
00053 _cached = 0;
00054 int i;
00055 for (i = LEFT; i < NUM_EYE_POSITIONS; i++) {
00056 _pos_mat_dirty[i] = 1;
00057 _proj_mat_dirty = 1;
00058 }
00059 if (_cam)
00060 _cam->data_changed();
00061
00062 ++_stamp;
00063
00064 for (i=0; i<_cblist.num(); i++)
00065 _cblist[i]->notify(this);
00066 }
00067
00068 void
00069 CAMdata::start_manip()
00070 {
00071 for (int i=0; i<_cblist.num(); ++i)
00072 _cblist[i]->notify_manip_start(this);
00073 }
00074
00075 void
00076 CAMdata::end_manip()
00077 {
00078 for (int i=0; i<_cblist.num(); ++i)
00079 _cblist[i]->notify_manip_end(this);
00080
00081 }
00082
00083
00084
00085
00086
00087
00088
00089 bool
00090 CAMdata::film_normal(
00091 CWvec &at,
00092 CWvec &up,
00093 Wvec &normal
00094 ) const
00095 {
00096 double x = tan(_tilt_left);
00097 double y = tan(_tilt_up);
00098
00099 Wvec v1 = cross(at, up).normalized();
00100 Wvec v2 = cross(v1, at).normalized();
00101
00102 normal = (x * v1 + y * v2 + sqrt(1 - x*x - y*y) * at).normalized();
00103
00104 return true;
00105 }
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 bool
00116 CAMdata::film_vectors(
00117 CWvec& up,
00118 CWvec& normal,
00119 Wvec& f_up,
00120 Wvec& f_right
00121 ) const
00122 {
00123 double dot = -(up * normal);
00124
00125
00126 if (fabs(dot) > 1.0-epsAbsSqrdMath()) {
00127 cerr << "CAMdata::film_vectors: bad dot product" << endl;
00128 cerr << "up: " << up << endl;
00129 cerr << "normal: " << normal << endl;
00130 cerr << "fabs_dot: " << fabs(dot) << endl;
00131
00132
00133 f_up = normal.perpend();
00134 ((CAMdata*)this)->_up = _from + f_up;
00135 } else {
00136 f_up = up.orthogonalized(normal).normalized();
00137 }
00138 f_right = cross(normal, f_up).normalized();
00139
00140 return true;
00141 }
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 bool
00153 CAMdata::setup_vectors(
00154 Wvec &at,
00155 Wvec &up,
00156 Wpt ¢er,
00157 Wvec &normal,
00158 Wvec &f_up,
00159 Wvec &f_right
00160 ) const
00161 {
00162 up = (_up - _from).normalized();
00163 at = (_at - _from).normalized();
00164
00165 center = _from + _focal * at;
00166
00167
00168
00169 if (_film_normal_flag) {
00170 normal = _film_normal;
00171 film_vectors(up, _film_normal, f_up, f_right);
00172 }
00173 else {
00174 film_normal(at, up, normal);
00175 film_vectors(up, normal, f_up, f_right);
00176 }
00177
00178 return true;
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 CWtransf&
00193 CAMdata::xform(SCREENptr screen, eye e) const
00194 {
00195 if (!_pos_mat_dirty[e])
00196 return _pos_matrix[e];
00197
00198 Wvec upv;
00199 Wvec atv;
00200 Wvec normalv;
00201 Wvec proj_upv;
00202 Wvec rightv;
00203
00204 Wpt center;
00205 Wtransf rot;
00206
00207 CAMdata *me =(CAMdata *)this;
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225 setup_vectors(atv, upv, center, normalv, proj_upv, rightv);
00226
00227
00228
00229 rot(2, 0) = -normalv[0];
00230 rot(2, 1) = -normalv[1];
00231 rot(2, 2) = -normalv[2];
00232
00233 rot(0, 0) = rightv[0];
00234 rot(0, 1) = rightv[1];
00235 rot(0, 2) = rightv[2];
00236
00237 rot(1, 0) = proj_upv[0];
00238 rot(1, 1) = proj_upv[1];
00239 rot(1, 2) = proj_upv[2];
00240
00241
00242 atv = rot * atv;
00243
00244
00245 me->_pos_matrix[e] =
00246 Wtransf::shear(Wvec(0,0,-1), Wvec(atv[0]/atv[2], atv[1]/atv[2], 0.0)) *
00247 rot *
00248 Wtransf::translation(Wpt(0,0,0)-center);
00249
00250
00251
00252
00253
00254
00255
00256
00257 me->_pos_mat_dirty[e] = false;
00258
00259 return _pos_matrix[e];
00260 }
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 CWtransf&
00297 CAMdata::projection_xform(
00298 SCREENptr &screen,
00299 CNDCpt &min,
00300 double width,
00301 double height,
00302 eye e
00303 ) const
00304 {
00305 if (!_proj_mat_dirty)
00306 return _proj_matrix;
00307
00308
00309
00310
00311 if (screen)
00312 screen->push_eye_offset(_cam, e);
00313
00314 CAMdata *me =(CAMdata *)this;
00315
00316
00317 me->_proj_matrix = Wtransf::scaling(Wvec(2./_width, 2./_height, 1.0));
00318
00319
00320 if (_perspective) {
00321
00322 double dp = (_film_normal_flag ?
00323 fabs(_film_normal.normalized() * at_v()) :
00324 1.0
00325 );
00326
00327 Wtransf persp;
00328 persp(0, 0) = _focal * dp;
00329 persp(1, 1) = _focal * dp;
00330 persp(3, 3) = _focal * dp;
00331 persp(3, 2) = -1;
00332 persp.set_perspective(true);
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 me->_proj_matrix = persp * _proj_matrix;
00348 }
00349
00350
00351
00352
00353
00354 #ifdef posse
00355 double scaling = -1.0 / (_perspective ? 1000.0 : 1000.0);
00356 #else
00357 double scaling = -1.0 / (_perspective ? 1.0 : 1000.0);
00358 #endif
00359 me->_proj_matrix =
00360 Wtransf::translation(Wvec(1, 1, 0.0)) *
00361 Wtransf::scaling (Wvec(width * .5, height * .5, scaling)) *
00362 Wtransf::translation(Wvec(min[0], min[1], 0.0)) *
00363 _proj_matrix;
00364
00365 if (_perspective) {
00366
00367
00368
00369
00370
00371
00372
00373 me->_proj_matrix = Wtransf::translation(Wvec(0,0,-1)) *
00374 Wtransf::scaling (Wvec(1,1,2)) * _proj_matrix;
00375 }
00376
00377
00378 if (screen)
00379 screen->pop_eye_offset(&*_cam);
00380
00381 me->_proj_mat_dirty = false;
00382
00383 return _proj_matrix;
00384 }
00385
00386
00387 bool
00388 CAMdata::operator == (const CAMdata &cam) const
00389 {
00390 return _from == cam._from &&
00391 _at == cam._at &&
00392 _up == cam._up &&
00393 _center == cam._center &&
00394 _focal == cam._focal &&
00395 _width == cam._width &&
00396 _height == cam._height &&
00397 _perspective == cam._perspective &&
00398 _tilt_up == cam._tilt_up &&
00399 _tilt_left == cam._tilt_left &&
00400 _iod == cam._iod;
00401 }
00402
00403 CAMdata &
00404 CAMdata::operator= (const CAMdata &cam)
00405 {
00406
00407
00408
00409
00410
00411
00412 if (!(&cam == this || cam == *this)) {
00413 _from = cam._from;
00414 _at = cam._at;
00415 _up = cam._up;
00416 _center = cam._center;
00417 _focal = cam._focal;
00418 _width = cam._width;
00419 _height = cam._height;
00420 _perspective = cam._perspective;
00421 _tilt_up = cam._tilt_up;
00422 _tilt_left = cam._tilt_left;
00423 _iod = cam._iod;
00424 changed();
00425 }
00426 return *this;
00427 }
00428
00429 void
00430 CAMdata::rotate(
00431 CWline &axis,
00432 double ang
00433 )
00434 {
00435 Wtransf combined(Wtransf::rotation(axis, ang));
00436 _from = combined * from();
00437 _at = combined * at ();
00438 _up = combined * up ();
00439 changed();
00440 }
00441
00442 void
00443 CAMdata::translate(
00444 CWvec &t
00445 )
00446 {
00447 if (t.length() > 0) {
00448 _from += t;
00449 _at += t;
00450 _center += t;
00451 _up += t;
00452 changed();
00453 }
00454 }
00455
00456 void
00457 CAMdata::swivel(
00458 double rads
00459 )
00460 {
00461 if (rads != 0) {
00462 Wtransf rot(Wtransf::rotation(Wline(from(), up_v()), rads));
00463 _from = rot * _from;
00464 _at = rot * _at;
00465 _up = rot * _up;
00466 changed();
00467 }
00468 }
00469
00470 STDdstream &
00471 operator<<(STDdstream &ds, CCAMdataptr &cam)
00472 {
00473 return ds << cam->_from
00474 << cam->_at
00475 << cam->_up
00476 << cam->_center
00477 << cam->_focal
00478 << (int)cam->_perspective
00479 << cam->_iod;
00480 }
00481
00482 STDdstream &
00483 operator>>(STDdstream &ds, CAMdataptr &cam)
00484 {
00485
00486 int persp;
00487 ds >> cam->_from
00488 >> cam->_at
00489 >> cam->_up
00490 >> cam->_center
00491 >> cam->_focal
00492 >> persp
00493 >> cam->_iod;
00494
00495 cam->_perspective = persp ? true : false;
00496 cam->_loaded_from_file = true;
00497 cam->changed();
00498 return ds;
00499 }
00500
00501 void
00502 CAM::set_aspect(
00503 double a
00504 )
00505 {
00506 if ( a > 1 ) {
00507 _width = 2.0/a;
00508 _height = 2.0;
00509 _min = NDCpt(-a, -1);
00510 } else {
00511 _width = 2.0;
00512 _height = 2.0*a;
00513 _min = NDCpt(-1, -1/a);
00514 }
00515 _data->changed();
00516 }
00517
00518 CAM &
00519 CAM::operator = (const CAM &cam)
00520 {
00521 _min = cam._min;
00522 _width = cam._width;
00523 _height= cam._height;
00524
00525
00526 _min = cam._min;
00527 _width = cam._width;
00528 _height= cam._height;
00529 _zoom = cam._zoom;
00530 _ndc_proj_dirty = true;
00531
00532 *_data = *cam._data;
00533 return *this;
00534 }
00535
00536 int
00537 CAM::operator == (const CAM &cam)
00538 {
00539 return _min == cam._min &&
00540 _width == cam._width && _height == cam._height &&
00541 *_data == *cam._data;
00542 }
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552 Wvec
00553 CAM::film_dir(
00554 CXYpt &p
00555 ) const
00556 {
00557 CNDCpt ndc_p(p);
00558 CCAMdataptr &dat = data();
00559 if (!dat->persp())
00560 return dat->at_v();
00561
00562 Wpt fpt(dat->from() + dat->at_v() * dat->focal());
00563 Wvec fr (dat->right_v() * ndc_p[0]/2 * dat->width() );
00564 Wvec fu (dat->pup_v() * ndc_p[1]/2 * dat->height());
00565 return ((fpt + fr + fu) - dat->from()).normalized();
00566 }
00567
00568
00569
00570
00571
00572
00573
00574
00575 Wpt
00576 CAM::xy_to_w(
00577 CXYpt &pt,
00578 CWpt &wpt
00579 ) const
00580 {
00581 CCAMdataptr &dat = data();
00582 CWvec wvec = wpt - dat->from();
00583 double length = wvec * dat->at_v();
00584
00585 if (!dat->persp())
00586 return dat->from() + length * dat->at_v() +
00587 dat->right_v() * pt[0] / width() * dat->width() +
00588 dat->pup_v() * pt[1] / height() * dat->height();
00589 else {
00590 Wvec rdir(pt);
00591 return dat->from() + rdir * (length/(rdir* dat->at_v()));
00592 }
00593 }
00594
00595
00596
00597
00598
00599
00600
00601 Wpt
00602 CAM::xy_to_w(
00603 CXYpt &pt
00604 ) const
00605 {
00606 CCAMdataptr dat = data();
00607 if (!dat->persp())
00608 return xy_to_w(pt, dat->from());
00609 else return xy_to_w(pt, dat->from() + dat->at_v() * dat->focal() * 1.01);
00610 }
00611
00612 Wpt
00613 CAM::xy_to_w(
00614 CXYpt &pt,
00615 double d
00616 ) const
00617 {
00618 CCAMdataptr dat = data();
00619 if (!d)
00620 d = dat->distance();
00621 return xy_to_w(pt, dat->from() + dat->at_v() * d);
00622 }
00623
00624
00625
00626
00627
00628 XYpt
00629 CAM::w_to_xy(
00630 CWpt &wpt
00631 ) const
00632 {
00633 CCAMdataptr &dat = data();
00634 Wvec wvec(wpt - dat->from());
00635
00636 if (!dat->persp())
00637 return XYpt(wvec * dat->right_v() / dat->width () * width(),
00638 wvec * dat->pup_v() / dat->height() * height());
00639
00640 else {
00641 NDCpt aspect(XYpt(1,1));
00642
00643
00644 Wvec svec((wvec.normalized() *
00645 (wvec.length() / (wvec * dat->at_v())) - dat->at_v()) *
00646 dat->focal());
00647
00648 return XYpt(svec * dat->right_v()/dat-> width() * 2/aspect[0],
00649 svec * dat->pup_v ()/dat->height() * 2/aspect[1]);
00650 }
00651 }
00652
00653 CWtransf&
00654 CAM::ndc_projection() const
00655 {
00656 if (_ndc_proj_dirty) {
00657 int w, h;
00658 VIEW_SIZE(w,h);
00659 Wvec scale = (w>h) ? Wvec(w/(double)h, 1, 1) : Wvec(1, h/(double) w, 1);
00660 ((CAM*)this)->_ndc_proj = Wtransf::scaling(scale)*projection_xform()*xform();
00661 ((CAM*)this)->_ndc_proj_inv = _ndc_proj.inverse();
00662 ((CAM*)this)->_ndc_proj_dirty = 0;
00663 }
00664 return _ndc_proj;
00665 }
00666
00667 CWtransf&
00668 CAM::ndc_projection_inv() const
00669 {
00670
00671 ndc_projection();
00672
00673 return _ndc_proj_inv;
00674 }
00675
00676
00677 void
00678 SCREEN::push_eye_offset(
00679 CCAMptr &cam,
00680 CAMdata::eye e
00681 )
00682 {
00683
00684 CAMdata *data = (CAMdata *) cam->data_ptr();
00685
00686 *_saved_cam->data() = *data;
00687
00688 double clip_ratio = data->focal() / (data->from() - data->at()).length();
00689
00690
00691
00692 Wvec up_vec = data->up_v();
00693
00694 double dist_to_screen = (data->from() - data->at()).length();
00695 data->set_focal(dist_to_screen * clip_ratio);
00696 }
00697
00698 void
00699 SCREEN::pop_eye_offset(
00700 const CAM *c
00701 )
00702 {
00703
00704 *((CAMdata *)c->data_ptr()) = *_saved_cam->data_ptr();
00705 }
00706
00707