00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "lens.h"
00016 #include "throw_event.h"
00017 #include "compose_matrix.h"
00018 #include "look_at.h"
00019 #include "geom.h"
00020 #include "geomLinestrips.h"
00021 #include "geomVertexWriter.h"
00022 #include "boundingHexahedron.h"
00023 #include "indent.h"
00024 #include "config_gobj.h"
00025 #include "plane.h"
00026
00027 TypeHandle Lens::_type_handle;
00028
00029
00030
00031
00032
00033
00034 Lens::
00035 Lens() {
00036 clear();
00037 }
00038
00039
00040
00041
00042
00043
00044 Lens::
00045 Lens(const Lens ©) {
00046 (*this) = copy;
00047 }
00048
00049
00050
00051
00052
00053
00054 void Lens::
00055 operator = (const Lens ©) {
00056 _change_event = copy._change_event;
00057 _cs = copy._cs;
00058 _film_size = copy._film_size;
00059 _film_offset = copy._film_offset;
00060 _focal_length = copy._focal_length;
00061 _fov = copy._fov;
00062 _aspect_ratio = copy._aspect_ratio;
00063 _near_distance = copy._near_distance;
00064 _far_distance = copy._far_distance;
00065
00066 _view_hpr = copy._view_hpr;
00067 _view_vector = copy._view_vector;
00068 _interocular_distance = copy._interocular_distance;
00069 _convergence_distance = copy._convergence_distance;
00070 _keystone = copy._keystone;
00071
00072 _user_flags = copy._user_flags;
00073 _comp_flags = 0;
00074
00075 _focal_length_seq = copy._focal_length_seq;
00076 _fov_seq = copy._fov_seq;
00077 _film_size_seq = copy._film_size_seq;
00078
00079
00080 }
00081
00082
00083
00084
00085
00086
00087
00088
00089 void Lens::
00090 set_coordinate_system(CoordinateSystem cs) {
00091 _cs = cs;
00092 adjust_comp_flags(CF_mat | CF_view_hpr | CF_view_vector, 0);
00093 }
00094
00095
00096
00097
00098
00099
00100
00101 void Lens::
00102 clear() {
00103 _change_event = "";
00104 _cs = CS_default;
00105 _film_size.set(1.0f, 1.0f);
00106 _film_offset.set(0.0f, 0.0f);
00107 _focal_length = 1.0f;
00108 _fov.set(default_fov, default_fov);
00109 _aspect_ratio = 1.0f;
00110 _near_distance = default_near;
00111 _far_distance = default_far;
00112 _view_hpr.set(0.0f, 0.0f, 0.0f);
00113 _view_vector.set(0.0f, 1.0f, 0.0f);
00114 _up_vector.set(0.0f, 0.0f, 1.0f);
00115 _keystone.set(0.0f, 0.0f);
00116
00117 _user_flags = 0;
00118 _comp_flags = CF_fov;
00119
00120 set_interocular_distance(default_iod);
00121 set_convergence_distance(default_converge);
00122
00123 if (default_keystone.has_value()) {
00124 _keystone.set(default_keystone[0], default_keystone[1]);
00125 _user_flags |= UF_keystone;
00126 }
00127
00128
00129 _film_size_seq = 0;
00130 _focal_length_seq = 1;
00131 _fov_seq = 2;
00132 }
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 void Lens::
00143 set_film_size(float width) {
00144 nassertv(!cnan(width));
00145 _film_size.set(width, width / get_aspect_ratio());
00146
00147
00148
00149 resequence_fov_triad(_film_size_seq, _focal_length_seq, _fov_seq);
00150
00151 if (_fov_seq == 0) {
00152
00153 adjust_user_flags(UF_hfov | UF_vfov | UF_min_fov | UF_film_height,
00154 UF_film_width);
00155 } else {
00156
00157 nassertv(_focal_length_seq == 0);
00158 adjust_user_flags(UF_focal_length | UF_film_height,
00159 UF_film_width);
00160 }
00161 adjust_comp_flags(CF_mat | CF_focal_length | CF_fov,
00162 CF_film_size);
00163 throw_change_event();
00164 }
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187 void Lens::
00188 set_film_size(const LVecBase2f &film_size) {
00189 nassertv(!film_size.is_nan());
00190 _film_size = film_size;
00191
00192
00193
00194 resequence_fov_triad(_film_size_seq, _focal_length_seq, _fov_seq);
00195
00196 if (_fov_seq == 0) {
00197
00198 adjust_user_flags(UF_hfov | UF_vfov | UF_min_fov | UF_aspect_ratio,
00199 UF_film_width | UF_film_height);
00200 } else {
00201
00202 nassertv(_focal_length_seq == 0);
00203 adjust_user_flags(UF_focal_length | UF_vfov | UF_aspect_ratio,
00204 UF_film_width | UF_film_height);
00205 }
00206 adjust_comp_flags(CF_mat | CF_focal_length | CF_fov | CF_aspect_ratio,
00207 CF_film_size);
00208
00209
00210
00211 compute_aspect_ratio();
00212 adjust_user_flags(0, UF_aspect_ratio);
00213
00214 throw_change_event();
00215 }
00216
00217
00218
00219
00220
00221
00222
00223 const LVecBase2f &Lens::
00224 get_film_size() const {
00225 if ((_comp_flags & CF_film_size) == 0) {
00226
00227
00228
00229 ((Lens *)this)->compute_film_size();
00230 }
00231 return _film_size;
00232 }
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 void Lens::
00245 set_focal_length(float focal_length) {
00246 nassertv(!cnan(focal_length));
00247 _focal_length = focal_length;
00248
00249
00250
00251 resequence_fov_triad(_focal_length_seq, _film_size_seq, _fov_seq);
00252
00253 if (_film_size_seq == 0) {
00254
00255 adjust_user_flags(UF_film_width | UF_film_height,
00256 UF_focal_length);
00257 } else {
00258
00259 nassertv(_fov_seq == 0);
00260 adjust_user_flags(UF_hfov | UF_vfov | UF_min_fov,
00261 UF_focal_length);
00262 }
00263
00264 adjust_comp_flags(CF_mat | CF_fov | CF_film_size,
00265 CF_focal_length);
00266 throw_change_event();
00267 }
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278 float Lens::
00279 get_focal_length() const {
00280 if ((_comp_flags & CF_focal_length) == 0) {
00281 ((Lens *)this)->compute_focal_length();
00282 }
00283 return _focal_length;
00284 }
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 void Lens::
00302 set_min_fov(float min_fov) {
00303 nassertv(!cnan(min_fov));
00304 _min_fov = min_fov;
00305
00306
00307
00308 resequence_fov_triad(_fov_seq, _focal_length_seq, _film_size_seq);
00309
00310 if (_focal_length_seq == 0) {
00311
00312 adjust_user_flags(UF_focal_length | UF_vfov | UF_hfov,
00313 UF_min_fov);
00314 } else {
00315
00316 nassertv(_film_size_seq == 0);
00317
00318
00319 compute_aspect_ratio();
00320 adjust_user_flags(UF_film_width | UF_film_height | UF_vfov | UF_hfov,
00321 UF_min_fov);
00322 }
00323 adjust_comp_flags(CF_mat | CF_focal_length | CF_fov | CF_film_size,
00324 0);
00325
00326
00327
00328 throw_change_event();
00329 }
00330
00331
00332
00333
00334
00335
00336
00337
00338 void Lens::
00339 set_fov(float hfov) {
00340 nassertv(!cnan(hfov));
00341 _fov[0] = hfov;
00342
00343
00344
00345 resequence_fov_triad(_fov_seq, _focal_length_seq, _film_size_seq);
00346
00347 if (_focal_length_seq == 0) {
00348
00349 adjust_user_flags(UF_focal_length | UF_vfov | UF_min_fov,
00350 UF_hfov);
00351 } else {
00352
00353 nassertv(_film_size_seq == 0);
00354
00355
00356 compute_aspect_ratio();
00357 adjust_user_flags(UF_film_width | UF_film_height | UF_vfov | UF_min_fov,
00358 UF_hfov);
00359 }
00360 adjust_comp_flags(CF_mat | CF_focal_length | CF_fov | CF_film_size,
00361 0);
00362
00363
00364
00365 throw_change_event();
00366 }
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380 void Lens::
00381 set_fov(const LVecBase2f &fov) {
00382 nassertv(!fov.is_nan());
00383 _fov = fov;
00384
00385
00386
00387 resequence_fov_triad(_fov_seq, _focal_length_seq, _film_size_seq);
00388
00389 if (_focal_length_seq == 0) {
00390
00391 adjust_user_flags(UF_focal_length | UF_film_height | UF_min_fov | UF_aspect_ratio,
00392 UF_hfov | UF_vfov);
00393 } else {
00394
00395 nassertv(_film_size_seq == 0);
00396 adjust_user_flags(UF_film_width | UF_film_height | UF_min_fov | UF_aspect_ratio,
00397 UF_hfov | UF_vfov);
00398 }
00399 adjust_comp_flags(CF_mat | CF_focal_length | CF_film_size | CF_aspect_ratio,
00400 CF_fov);
00401
00402
00403
00404 compute_aspect_ratio();
00405 adjust_user_flags(0, UF_aspect_ratio);
00406
00407 throw_change_event();
00408 }
00409
00410
00411
00412
00413
00414
00415
00416 const LVecBase2f &Lens::
00417 get_fov() const {
00418 if ((_comp_flags & CF_fov) == 0) {
00419 ((Lens *)this)->compute_fov();
00420 }
00421 return _fov;
00422 }
00423
00424
00425
00426
00427
00428
00429
00430 float Lens::
00431 get_min_fov() const {
00432 if ((_comp_flags & CF_fov) == 0) {
00433 ((Lens *)this)->compute_fov();
00434 }
00435 return _min_fov;
00436 }
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447 void Lens::
00448 set_aspect_ratio(float aspect_ratio) {
00449 nassertv(!cnan(aspect_ratio));
00450 _aspect_ratio = aspect_ratio;
00451 adjust_user_flags(UF_film_height | UF_vfov,
00452 UF_aspect_ratio);
00453 adjust_comp_flags(CF_mat | CF_film_size | CF_fov | CF_focal_length,
00454 CF_aspect_ratio);
00455 throw_change_event();
00456 }
00457
00458
00459
00460
00461
00462
00463
00464
00465 float Lens::
00466 get_aspect_ratio() const {
00467 if ((_comp_flags & CF_aspect_ratio) == 0) {
00468 ((Lens *)this)->compute_aspect_ratio();
00469 }
00470 return _aspect_ratio;
00471 }
00472
00473
00474
00475
00476
00477
00478
00479
00480 float Lens::
00481 get_default_near() {
00482 return default_near;
00483 }
00484
00485
00486
00487
00488
00489
00490
00491
00492 float Lens::
00493 get_default_far() {
00494 return default_far;
00495 }
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 void Lens::
00508 set_view_hpr(const LVecBase3f &view_hpr) {
00509 nassertv(!view_hpr.is_nan());
00510 _view_hpr = view_hpr;
00511 adjust_user_flags(UF_view_vector | UF_view_mat,
00512 UF_view_hpr);
00513 adjust_comp_flags(CF_mat | CF_view_vector,
00514 CF_view_hpr);
00515 throw_change_event();
00516 }
00517
00518
00519
00520
00521
00522
00523 const LVecBase3f &Lens::
00524 get_view_hpr() const {
00525 if ((_comp_flags & CF_view_hpr) == 0) {
00526 ((Lens *)this)->compute_view_hpr();
00527 }
00528 return _view_hpr;
00529 }
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540 void Lens::
00541 set_view_vector(const LVector3f &view_vector, const LVector3f &up_vector) {
00542 nassertv(!view_vector.is_nan());
00543 _view_vector = view_vector;
00544 _up_vector = up_vector;
00545 adjust_user_flags(UF_view_hpr | UF_view_mat,
00546 UF_view_vector);
00547 adjust_comp_flags(CF_mat | CF_view_hpr,
00548 CF_view_vector);
00549 throw_change_event();
00550 }
00551
00552
00553
00554
00555
00556
00557 const LVector3f &Lens::
00558 get_view_vector() const {
00559 if ((_comp_flags & CF_view_vector) == 0) {
00560 ((Lens *)this)->compute_view_vector();
00561 }
00562 return _view_vector;
00563 }
00564
00565
00566
00567
00568
00569
00570
00571 const LVector3f &Lens::
00572 get_up_vector() const {
00573 if ((_comp_flags & CF_view_vector) == 0) {
00574 ((Lens *)this)->compute_view_vector();
00575 }
00576 return _up_vector;
00577 }
00578
00579
00580
00581
00582
00583
00584
00585 LPoint3f Lens::
00586 get_nodal_point() const {
00587 return get_view_mat().get_row3(3);
00588 }
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605 void Lens::
00606 set_interocular_distance(float interocular_distance) {
00607 nassertv(!cnan(interocular_distance));
00608 _interocular_distance = interocular_distance;
00609 if (_interocular_distance == 0.0f) {
00610 adjust_user_flags(UF_interocular_distance, 0);
00611 } else {
00612 adjust_user_flags(0, UF_interocular_distance);
00613 }
00614
00615 adjust_comp_flags(CF_mat, 0);
00616 throw_change_event();
00617 }
00618
00619
00620
00621
00622
00623
00624 float Lens::
00625 get_interocular_distance() const {
00626 return _interocular_distance;
00627 }
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651 void Lens::
00652 set_convergence_distance(float convergence_distance) {
00653 nassertv(!cnan(convergence_distance));
00654 _convergence_distance = convergence_distance;
00655 if (_convergence_distance == 0.0f) {
00656 adjust_user_flags(UF_convergence_distance, 0);
00657 } else {
00658 adjust_user_flags(0, UF_convergence_distance);
00659 }
00660
00661 adjust_comp_flags(CF_mat, 0);
00662 throw_change_event();
00663 }
00664
00665
00666
00667
00668
00669
00670 float Lens::
00671 get_convergence_distance() const {
00672 return _convergence_distance;
00673 }
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690 void Lens::
00691 set_view_mat(const LMatrix4f &view_mat) {
00692 nassertv(!view_mat.is_nan());
00693 _lens_mat = view_mat;
00694 adjust_user_flags(UF_view_vector | UF_view_hpr,
00695 UF_view_mat);
00696 adjust_comp_flags(CF_projection_mat | CF_projection_mat_inv |
00697 CF_projection_mat_left_inv | CF_projection_mat_right_inv |
00698 CF_lens_mat_inv | CF_view_hpr | CF_view_vector,
00699 CF_lens_mat);
00700 throw_change_event();
00701 }
00702
00703
00704
00705
00706
00707
00708 const LMatrix4f &Lens::
00709 get_view_mat() const {
00710 if ((_comp_flags & CF_lens_mat) == 0) {
00711 ((Lens *)this)->compute_lens_mat();
00712 }
00713 return _lens_mat;
00714 }
00715
00716
00717
00718
00719
00720
00721 void Lens::
00722 clear_view_mat() {
00723 _lens_mat = LMatrix4f::ident_mat();
00724 adjust_user_flags(0, UF_view_vector | UF_view_hpr | UF_view_mat);
00725 adjust_comp_flags(CF_projection_mat | CF_projection_mat_inv |
00726 CF_projection_mat_left_inv | CF_projection_mat_right_inv |
00727 CF_lens_mat_inv | CF_view_hpr | CF_view_vector,
00728 CF_lens_mat);
00729 throw_change_event();
00730 }
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749 void Lens::
00750 set_keystone(const LVecBase2f &keystone) {
00751 nassertv(!keystone.is_nan());
00752 _keystone = keystone;
00753 adjust_user_flags(0, UF_keystone);
00754 adjust_comp_flags(CF_projection_mat | CF_projection_mat_inv |
00755 CF_projection_mat_left_inv | CF_projection_mat_right_inv |
00756 CF_film_mat | CF_film_mat_inv, 0);
00757 throw_change_event();
00758 }
00759
00760
00761
00762
00763
00764
00765 void Lens::
00766 clear_keystone() {
00767 _keystone.set(0.0f, 0.0f);
00768 adjust_user_flags(UF_keystone, 0);
00769 adjust_comp_flags(CF_projection_mat | CF_projection_mat_inv |
00770 CF_projection_mat_left_inv | CF_projection_mat_right_inv |
00771 CF_film_mat | CF_film_mat_inv, 0);
00772 throw_change_event();
00773 }
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834 void Lens::
00835 set_frustum_from_corners(const LVecBase3f &ul, const LVecBase3f &ur,
00836 const LVecBase3f &ll, const LVecBase3f &lr,
00837 int flags) {
00838 nassertv(!ul.is_nan() && !ur.is_nan() && !ll.is_nan() && !lr.is_nan());
00839
00840
00841
00842 const LMatrix4f &lens_mat_inv = get_lens_mat_inv();
00843 LVector3f eye_offset;
00844 lens_mat_inv.get_row3(eye_offset, 3);
00845
00846
00847
00848
00849
00850 LVector3f view_vector;
00851 if ((flags & FC_camera_plane) != 0) {
00852 view_vector = (ul + ur + ll + lr) * 0.25f;
00853 } else {
00854 Planef plane(ll, ul, ur);
00855 view_vector = plane.get_normal();
00856 nassertv(!view_vector.is_nan() && view_vector.length_squared() != 0.0f);
00857 }
00858
00859
00860
00861
00862
00863 LVector3f up_vector = LVector3f::up(_cs);
00864 if (view_vector == up_vector || ((flags & FC_roll) != 0)) {
00865 LVector3f top = ul - ur;
00866 up_vector = view_vector.cross(top);
00867 nassertv(!up_vector.is_nan() && up_vector.length_squared() != 0.0f);
00868 }
00869
00870
00871 LMatrix4f rot_mat;
00872 look_at(rot_mat, view_vector, up_vector, CS_zup_right);
00873
00874
00875 LMatrix4f inv_rot_mat;
00876 inv_rot_mat.invert_affine_from(rot_mat);
00877
00878
00879
00880 LPoint3f cul = inv_rot_mat.xform_point(ul);
00881 LPoint3f cur = inv_rot_mat.xform_point(ur);
00882 LPoint3f cll = inv_rot_mat.xform_point(ll);
00883 LPoint3f clr = inv_rot_mat.xform_point(lr);
00884
00885
00886
00887 nassertv(cul[1] != 0.0f && cur[1] != 0.0f && cll[1] != 0.0f && clr[1] != 0.0f);
00888 cul /= cul[1];
00889 cur /= cur[1];
00890 cll /= cll[1];
00891 clr /= clr[1];
00892
00893 LMatrix4f shear_mat = LMatrix4f::ident_mat();
00894 LMatrix4f inv_shear_mat = LMatrix4f::ident_mat();
00895
00896
00897 if ((flags & FC_shear) != 0) {
00898 build_shear_mat(shear_mat, cul, cur, cll, clr);
00899 inv_shear_mat.invert_from(shear_mat);
00900 }
00901
00902
00903 LMatrix4f inv_view_mat =
00904 inv_rot_mat *
00905 inv_shear_mat;
00906
00907
00908 inv_view_mat.set_row(3, eye_offset);
00909
00910 LMatrix4f view_mat;
00911 view_mat.invert_from(inv_view_mat);
00912 set_view_mat(view_mat);
00913
00914 LPoint3f ful = inv_view_mat.xform_point(ul);
00915 LPoint3f fur = inv_view_mat.xform_point(ur);
00916 LPoint3f fll = inv_view_mat.xform_point(ll);
00917 LPoint3f flr = inv_view_mat.xform_point(lr);
00918
00919
00920 nassertv(ful[1] != 0.0f && fur[1] != 0.0f && fll[1] != 0.0f && flr[1] != 0.0f);
00921 ful /= ful[1];
00922 fur /= fur[1];
00923 fll /= fll[1];
00924 flr /= flr[1];
00925
00926
00927
00928 float min_x = min(min(ful[0], fur[0]), min(fll[0], flr[0]));
00929 float max_x = max(max(ful[0], fur[0]), max(fll[0], flr[0]));
00930 float min_z = min(min(ful[2], fur[2]), min(fll[2], flr[2]));
00931 float max_z = max(max(ful[2], fur[2]), max(fll[2], flr[2]));
00932
00933 float x_spread, x_center, z_spread, z_center;
00934
00935 if ((flags & FC_off_axis) != 0) {
00936
00937
00938 x_center = (max_x + min_x) * 0.5f;
00939 z_center = (max_z + min_z) * 0.5f;
00940 x_spread = x_center - min_x;
00941 z_spread = z_center - min_z;
00942 } else {
00943
00944 x_center = 0.0f;
00945 z_center = 0.0f;
00946 x_spread = max(cabs(max_x), cabs(min_x));
00947 z_spread = max(cabs(max_z), cabs(min_z));
00948 }
00949
00950 float aspect_ratio = get_aspect_ratio();
00951 nassertv(aspect_ratio != 0.0f);
00952 if ((flags & FC_aspect_ratio) == 0) {
00953
00954
00955 if (x_spread < z_spread * aspect_ratio) {
00956
00957 x_spread = z_spread * aspect_ratio;
00958 } else if (z_spread < x_spread / aspect_ratio) {
00959
00960 z_spread = x_spread / aspect_ratio;
00961 }
00962 }
00963
00964 float hfov = rad_2_deg(catan(x_spread)) * 2.0f;
00965 float vfov = rad_2_deg(catan(z_spread)) * 2.0f;
00966
00967 set_fov(hfov, vfov);
00968
00969 if ((flags & FC_aspect_ratio) == 0) {
00970
00971
00972
00973 set_aspect_ratio(aspect_ratio);
00974 }
00975
00976 const LVecBase2f &film_size = get_film_size();
00977 nassertv(x_spread != 0.0f && z_spread != 0.0f);
00978 set_film_offset(film_size[0] * x_center / (x_spread * 2.0f),
00979 film_size[1] * z_center / (z_spread * 2.0f));
00980 }
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990 void Lens::
00991 recompute_all() {
00992 _comp_flags = 0;
00993 }
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003 bool Lens::
01004 is_linear() const {
01005 return false;
01006 }
01007
01008
01009
01010
01011
01012
01013
01014
01015 bool Lens::
01016 is_perspective() const {
01017 return false;
01018 }
01019
01020
01021
01022
01023
01024
01025
01026
01027 bool Lens::
01028 is_orthographic() const {
01029 return false;
01030 }
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041 PT(Geom) Lens::
01042 make_geometry() {
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052 int num_segments = define_geom_data();
01053 if (num_segments == 0) {
01054
01055 _geom_data.clear();
01056 return (Geom *)NULL;
01057 }
01058
01059
01060 PT(GeomLinestrips) line = new GeomLinestrips(Geom::UH_static);
01061
01062
01063 int i, si;
01064 for (i = 0; i < 4; ++i) {
01065 for (si = 0; si < num_segments; ++si) {
01066 line->add_vertex(i * 2 + si * (4 * 2) + 0);
01067 }
01068 }
01069 line->add_vertex(0);
01070 line->close_primitive();
01071
01072
01073 for (i = 0; i < 4; ++i) {
01074 for (si = 0; si < num_segments; ++si) {
01075 line->add_vertex(i * 2 + si * (4 * 2) + 1);
01076 }
01077 }
01078 line->add_vertex(1);
01079 line->close_primitive();
01080
01081
01082 line->add_vertex(0 * 2 + 0);
01083 line->add_vertex(0 * 2 + 1);
01084 line->close_primitive();
01085
01086 line->add_vertex(1 * 2 + 0);
01087 line->add_vertex(1 * 2 + 1);
01088 line->close_primitive();
01089
01090 line->add_vertex(2 * 2 + 0);
01091 line->add_vertex(2 * 2 + 1);
01092 line->close_primitive();
01093
01094 line->add_vertex(3 * 2 + 0);
01095 line->add_vertex(3 * 2 + 1);
01096 line->close_primitive();
01097
01098
01099 line->add_vertex(num_segments * (4 * 2) + 0);
01100 line->add_vertex(num_segments * (4 * 2) + 1);
01101 line->close_primitive();
01102
01103 PT(Geom) geom = new Geom(_geom_data);
01104 geom->add_primitive(line);
01105
01106 return geom.p();
01107 }
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117 PT(BoundingVolume) Lens::
01118 make_bounds() const {
01119
01120
01121 LPoint3f fll, flr, ful, fur;
01122 LPoint3f nll, nlr, nul, nur;
01123 LPoint2f corner;
01124
01125 corner[0] = -1.0f; corner[1] = 1.0f;
01126
01127
01128 if (!extrude(corner, nul, ful)) {
01129 return (BoundingVolume *)NULL;
01130 }
01131
01132 corner[0] = 1.0f; corner[1] = 1.0f;
01133
01134
01135 if (!extrude(corner, nur, fur)) {
01136 return (BoundingVolume *)NULL;
01137 }
01138
01139 corner[0] = 1.0f; corner[1] = -1.0f;
01140
01141
01142 if (!extrude(corner, nlr, flr)) {
01143 return (BoundingVolume *)NULL;
01144 }
01145
01146 corner[0] = -1.0f; corner[1] = -1.0f;
01147
01148
01149 if (!extrude(corner, nll, fll)) {
01150 return (BoundingVolume *)NULL;
01151 }
01152
01153 return new BoundingHexahedron(fll, flr, fur, ful, nll, nlr, nur, nul);
01154 }
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164 const LMatrix4f &Lens::
01165 get_projection_mat(StereoChannel channel) const {
01166 if ((_comp_flags & CF_projection_mat) == 0) {
01167 ((Lens *)this)->compute_projection_mat();
01168 }
01169
01170 switch (channel) {
01171 case SC_left:
01172 return _projection_mat_left;
01173 case SC_right:
01174 return _projection_mat_right;
01175 case SC_mono:
01176 case SC_stereo:
01177 return _projection_mat;
01178 }
01179
01180 return _projection_mat;
01181 }
01182
01183
01184
01185
01186
01187
01188
01189
01190 const LMatrix4f &Lens::
01191 get_projection_mat_inv(StereoChannel stereo_channel) const {
01192 switch (stereo_channel) {
01193 case SC_left:
01194 {
01195 if ((_comp_flags & CF_projection_mat_left_inv) == 0) {
01196 Lens *non_const = (Lens *)this;
01197 const LMatrix4f &projection_mat_left = get_projection_mat(SC_left);
01198 non_const->_projection_mat_left_inv.invert_from(projection_mat_left);
01199 non_const->adjust_comp_flags(0, CF_projection_mat_left_inv);
01200 }
01201 }
01202 return _projection_mat_left_inv;
01203
01204 case SC_right:
01205 {
01206 if ((_comp_flags & CF_projection_mat_right_inv) == 0) {
01207 Lens *non_const = (Lens *)this;
01208 const LMatrix4f &projection_mat_right = get_projection_mat(SC_right);
01209 non_const->_projection_mat_right_inv.invert_from(projection_mat_right);
01210 non_const->adjust_comp_flags(0, CF_projection_mat_right_inv);
01211 }
01212 }
01213 return _projection_mat_right_inv;
01214
01215 case SC_mono:
01216 case SC_stereo:
01217 break;
01218 }
01219
01220 if ((_comp_flags & CF_projection_mat_inv) == 0) {
01221 Lens *non_const = (Lens *)this;
01222 const LMatrix4f &projection_mat = get_projection_mat();
01223 non_const->_projection_mat_inv.invert_from(projection_mat);
01224 non_const->adjust_comp_flags(0, CF_projection_mat_inv);
01225 }
01226 return _projection_mat_inv;
01227 }
01228
01229
01230
01231
01232
01233
01234
01235 const LMatrix4f &Lens::
01236 get_film_mat() const {
01237 if ((_comp_flags & CF_film_mat) == 0) {
01238 ((Lens *)this)->compute_film_mat();
01239 }
01240 return _film_mat;
01241 }
01242
01243
01244
01245
01246
01247
01248
01249 const LMatrix4f &Lens::
01250 get_film_mat_inv() const {
01251 if ((_comp_flags & CF_film_mat_inv) == 0) {
01252 Lens *non_const = (Lens *)this;
01253 const LMatrix4f &film_mat = get_film_mat();
01254 non_const->_film_mat_inv.invert_from(film_mat);
01255 non_const->adjust_comp_flags(0, CF_film_mat_inv);
01256 }
01257 return _film_mat_inv;
01258 }
01259
01260
01261
01262
01263
01264
01265
01266 const LMatrix4f &Lens::
01267 get_lens_mat() const {
01268 if ((_comp_flags & CF_lens_mat) == 0) {
01269 ((Lens *)this)->compute_lens_mat();
01270 }
01271 return _lens_mat;
01272 }
01273
01274
01275
01276
01277
01278
01279
01280 const LMatrix4f &Lens::
01281 get_lens_mat_inv() const {
01282 if ((_comp_flags & CF_lens_mat_inv) == 0) {
01283 Lens *non_const = (Lens *)this;
01284 const LMatrix4f &lens_mat = get_lens_mat();
01285 non_const->_lens_mat_inv.invert_from(lens_mat);
01286 non_const->adjust_comp_flags(0, CF_lens_mat_inv);
01287 }
01288 return _lens_mat_inv;
01289 }
01290
01291
01292
01293
01294
01295
01296 void Lens::
01297 output(ostream &out) const {
01298 out << get_type();
01299 }
01300
01301
01302
01303
01304
01305
01306 void Lens::
01307 write(ostream &out, int indent_level) const {
01308 indent(out, indent_level) << get_type() << " fov = " << get_fov() << "\n";
01309 }
01310
01311
01312
01313
01314
01315
01316
01317 void Lens::
01318 throw_change_event() {
01319 ++_last_change;
01320
01321 if (!_change_event.empty()) {
01322 throw_event(_change_event, this);
01323 }
01324
01325 if (!_geom_data.is_null()) {
01326 if (_geom_data->get_ref_count() == 1) {
01327
01328
01329
01330 _geom_data.clear();
01331 } else {
01332
01333
01334 define_geom_data();
01335 }
01336 }
01337 }
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356 bool Lens::
01357 extrude_impl(const LPoint3f &point2d, LPoint3f &near_point, LPoint3f &far_point) const {
01358 const LMatrix4f &projection_mat_inv = get_projection_mat_inv();
01359 {
01360 LVecBase4f full(point2d[0], point2d[1], -1.0f, 1.0f);
01361 full = projection_mat_inv.xform(full);
01362
01363 float recip_full3 = 1.0 / max((double)full[3], (double)lens_far_limit);
01364 near_point.set(full[0] * recip_full3,
01365 full[1] * recip_full3,
01366 full[2] * recip_full3);
01367 }
01368 {
01369 LVecBase4f full(point2d[0], point2d[1], 1.0f, 1.0f);
01370 full = projection_mat_inv.xform(full);
01371
01372
01373
01374
01375
01376
01377 float recip_full3 = 1.0 / max((double)full[3], (double)lens_far_limit);
01378 far_point.set(full[0] * recip_full3,
01379 full[1] * recip_full3,
01380 full[2] * recip_full3);
01381 }
01382 return true;
01383 }
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414 bool Lens::
01415 extrude_vec_impl(const LPoint3f &point2d, LVector3f &vec) const {
01416 vec = LVector3f::forward(_cs) * get_lens_mat();
01417 return true;
01418 }
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438 bool Lens::
01439 project_impl(const LPoint3f &point3d, LPoint3f &point2d) const {
01440 const LMatrix4f &projection_mat = get_projection_mat();
01441 LVecBase4f full(point3d[0], point3d[1], point3d[2], 1.0f);
01442 full = projection_mat.xform(full);
01443 if (full[3] == 0.0f) {
01444 point2d.set(0.0f, 0.0f, 0.0f);
01445 return false;
01446 }
01447 float recip_full3 = 1.0f/full[3];
01448 point2d.set(full[0] * recip_full3, full[1] * recip_full3, full[2] * recip_full3);
01449 return
01450 (full[3] > 0.0f) &&
01451 (point2d[0] >= -1.0f) && (point2d[0] <= 1.0f) &&
01452 (point2d[1] >= -1.0f) && (point2d[1] <= 1.0f);
01453 }
01454
01455
01456
01457
01458
01459
01460
01461 void Lens::
01462 compute_film_size() {
01463 if ((_user_flags & (UF_min_fov | UF_focal_length)) == (UF_min_fov | UF_focal_length)) {
01464
01465
01466
01467 float fs = fov_to_film(_min_fov, _focal_length, true);
01468 nassertv((_user_flags & UF_aspect_ratio) != 0 ||
01469 (_comp_flags & CF_aspect_ratio) != 0);
01470
01471 if (_aspect_ratio < 1.0f) {
01472 _film_size[1] = fs / _aspect_ratio;
01473 _film_size[0] = fs;
01474
01475 } else {
01476 _film_size[0] = fs * _aspect_ratio;
01477 _film_size[1] = fs;
01478 }
01479
01480 } else {
01481 if ((_user_flags & UF_film_width) == 0) {
01482 if ((_user_flags & (UF_hfov | UF_focal_length)) == (UF_hfov | UF_focal_length)) {
01483 _film_size[0] = fov_to_film(_fov[0], _focal_length, true);
01484 } else {
01485 _film_size[0] = 1.0f;
01486 }
01487 }
01488
01489 if ((_user_flags & UF_film_height) == 0) {
01490 if ((_user_flags & (UF_vfov | UF_focal_length)) == (UF_vfov | UF_focal_length)) {
01491 _film_size[1] = fov_to_film(_fov[1], _focal_length, false);
01492
01493 } else if ((_user_flags & (UF_hfov | UF_vfov)) == (UF_hfov | UF_vfov)) {
01494
01495
01496
01497 if ((_comp_flags & CF_focal_length) == 0) {
01498 _focal_length = fov_to_focal_length(_fov[0], _film_size[0], true);
01499 adjust_comp_flags(0, CF_focal_length);
01500 }
01501 _film_size[1] = fov_to_film(_fov[1], _focal_length, false);
01502
01503 } else if ((_user_flags & UF_aspect_ratio) != 0 ||
01504 (_comp_flags & CF_aspect_ratio) != 0) {
01505 _film_size[1] = _film_size[0] / _aspect_ratio;
01506
01507 } else {
01508
01509 _film_size[1] = _film_size[0];
01510 }
01511 }
01512 }
01513
01514 adjust_comp_flags(0, CF_film_size);
01515 }
01516
01517
01518
01519
01520
01521
01522
01523
01524 void Lens::
01525 compute_focal_length() {
01526 if ((_user_flags & UF_focal_length) == 0) {
01527 const LVecBase2f &film_size = get_film_size();
01528 const LVecBase2f &fov = get_fov();
01529 _focal_length = fov_to_focal_length(fov[0], film_size[0], true);
01530 }
01531
01532 adjust_comp_flags(0, CF_focal_length);
01533 }
01534
01535
01536
01537
01538
01539
01540
01541 void Lens::
01542 compute_fov() {
01543 const LVecBase2f &film_size = get_film_size();
01544
01545 bool got_hfov = ((_user_flags & UF_hfov) != 0);
01546 bool got_vfov = ((_user_flags & UF_vfov) != 0);
01547 bool got_min_fov = ((_user_flags & UF_min_fov) != 0);
01548
01549 if (!got_hfov && !got_vfov && !got_min_fov) {
01550
01551 if ((_user_flags & UF_focal_length) != 0) {
01552
01553 _fov[0] = film_to_fov(film_size[0], _focal_length, true);
01554 _fov[1] = film_to_fov(film_size[1], _focal_length, true);
01555 got_hfov = true;
01556 got_vfov = true;
01557
01558 } else {
01559
01560 _min_fov = default_fov;
01561 got_min_fov = true;
01562 }
01563 }
01564
01565 if (got_min_fov) {
01566
01567
01568 if (film_size[0] < film_size[1]) {
01569 _fov[0] = _min_fov;
01570 got_hfov = true;
01571 } else {
01572 _fov[1] = _min_fov;
01573 got_vfov = true;
01574 }
01575 }
01576
01577
01578 if (!got_hfov) {
01579 if ((_user_flags & UF_focal_length) == 0 &&
01580 (_comp_flags & CF_focal_length) == 0) {
01581
01582
01583 nassertv(got_vfov);
01584 _focal_length = fov_to_focal_length(_fov[1], film_size[1], true);
01585 adjust_comp_flags(0, CF_focal_length);
01586 }
01587 _fov[0] = film_to_fov(film_size[0], _focal_length, false);
01588 got_hfov = true;
01589 }
01590
01591 if (!got_vfov) {
01592 if ((_user_flags & UF_focal_length) == 0 &&
01593 (_comp_flags & CF_focal_length) == 0) {
01594
01595
01596 nassertv(got_hfov);
01597 _focal_length = fov_to_focal_length(_fov[0], film_size[0], true);
01598 adjust_comp_flags(0, CF_focal_length);
01599 }
01600 _fov[1] = film_to_fov(film_size[1], _focal_length, false);
01601 got_vfov = true;
01602 }
01603
01604 if (!got_min_fov) {
01605 _min_fov = film_size[0] < film_size[1] ? _fov[0] : _fov[1];
01606 got_min_fov = true;
01607 }
01608
01609 nassertv(got_hfov && got_vfov && got_min_fov);
01610 adjust_comp_flags(0, CF_fov);
01611 }
01612
01613
01614
01615
01616
01617
01618
01619 void Lens::
01620 compute_aspect_ratio() {
01621 if ((_user_flags & UF_aspect_ratio) == 0) {
01622 const LVecBase2f &film_size = get_film_size();
01623 if (film_size[1] == 0.0f) {
01624 _aspect_ratio = 1.0f;
01625 } else {
01626 _aspect_ratio = film_size[0] / film_size[1];
01627 }
01628 }
01629 adjust_comp_flags(0, CF_aspect_ratio);
01630 }
01631
01632
01633
01634
01635
01636
01637
01638 void Lens::
01639 compute_view_hpr() {
01640 if ((_user_flags & UF_view_hpr) == 0) {
01641 const LMatrix4f &view_mat = get_view_mat();
01642 LVecBase3f scale, shear, translate;
01643 decompose_matrix(view_mat, scale, shear, _view_hpr, translate, _cs);
01644 }
01645 adjust_comp_flags(0, CF_view_hpr);
01646 }
01647
01648
01649
01650
01651
01652
01653 void Lens::
01654 compute_view_vector() {
01655 if ((_user_flags & UF_view_vector) == 0) {
01656 const LMatrix4f &view_mat = get_view_mat();
01657 _view_vector = LVector3f::forward(_cs) * view_mat;
01658 _up_vector = LVector3f::up(_cs) * view_mat;
01659 }
01660 adjust_comp_flags(0, CF_view_vector);
01661 }
01662
01663
01664
01665
01666
01667
01668
01669 void Lens::
01670 compute_projection_mat() {
01671 _projection_mat =
01672 _projection_mat_left =
01673 _projection_mat_right =
01674 _projection_mat_inv =
01675 _projection_mat_left_inv =
01676 _projection_mat_right_inv =
01677 LMatrix4f::ident_mat();
01678 adjust_comp_flags(0, CF_projection_mat | CF_projection_mat_inv |
01679 CF_projection_mat_left_inv |CF_projection_mat_right_inv);
01680 }
01681
01682
01683
01684
01685
01686
01687
01688 void Lens::
01689 compute_film_mat() {
01690
01691
01692
01693
01694
01695
01696 LVecBase2f film_size = get_film_size();
01697 LVector2f film_offset = get_film_offset();
01698
01699 float scale_x = 2.0f / film_size[0];
01700 float scale_y = 2.0f / film_size[1];
01701 _film_mat.set(scale_x, 0.0f, 0.0f, 0.0f,
01702 0.0f, scale_y, 0.0f, 0.0f,
01703 0.0f, 0.0f, 1.0f, 0.0f,
01704 -film_offset[0] * scale_x, -film_offset[1] * scale_y, 0.0f, 1.0f);
01705
01706 if ((_user_flags & UF_keystone) != 0) {
01707 _film_mat = LMatrix4f(1.0f, 0.0f, _keystone[0], _keystone[0],
01708 0.0f, 1.0f, _keystone[1], _keystone[1],
01709 0.0f, 0.0f, 1.0f, 0.0f,
01710 0.0f, 0.0f, 0.0f, 1.0f) * _film_mat;
01711 }
01712
01713 adjust_comp_flags(CF_film_mat_inv,
01714 CF_film_mat);
01715 }
01716
01717
01718
01719
01720
01721
01722
01723 void Lens::
01724 compute_lens_mat() {
01725 if ((_user_flags & UF_view_mat) == 0) {
01726 if ((_user_flags & UF_view_hpr) != 0) {
01727 compose_matrix(_lens_mat,
01728 LVecBase3f(1.0f, 1.0f, 1.0f),
01729 LVecBase3f(0.0f, 0.0f, 0.0f),
01730 _view_hpr,
01731 LVecBase3f(0.0f, 0.0f, 0.0f), _cs);
01732
01733 } else if ((_user_flags & UF_view_vector) != 0) {
01734 look_at(_lens_mat, _view_vector, _up_vector, _cs);
01735
01736 } else {
01737 _lens_mat = LMatrix4f::ident_mat();
01738 }
01739 }
01740 adjust_comp_flags(CF_lens_mat_inv,
01741 CF_lens_mat);
01742 }
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753 float Lens::
01754 fov_to_film(float, float, bool) const {
01755 return 1.0f;
01756 }
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767 float Lens::
01768 fov_to_focal_length(float, float, bool) const {
01769 return 1.0f;
01770 }
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781 float Lens::
01782 film_to_fov(float, float, bool) const {
01783 return default_fov;
01784 }
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800 void Lens::
01801 resequence_fov_triad(char &newest, char &older_a, char &older_b) {
01802 nassertv(newest + older_a + older_b == 3);
01803 switch (newest) {
01804 case 0:
01805 newest = 2;
01806 older_a--;
01807 older_b--;
01808 nassertv(older_a + older_b == 1);
01809 break;
01810
01811 case 1:
01812 newest = 2;
01813 if (older_a == 2) {
01814 nassertv(older_b == 0);
01815 older_a = 1;
01816 } else {
01817 nassertv(older_a == 0 && older_b == 2);
01818 older_b = 1;
01819 }
01820 break;
01821
01822 case 2:
01823 nassertv(older_a + older_b == 1);
01824 break;
01825
01826 default:
01827 gobj_cat.error()
01828 << "Invalid fov sequence numbers in lens: "
01829 << (int)newest << ", " << (int)older_a << ", " << (int)older_b << "\n";
01830 nassertv(false);
01831 return;
01832 }
01833 }
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845 int Lens::
01846 define_geom_data() {
01847 int num_segments = 1;
01848 if (!is_linear()) {
01849 num_segments = 10;
01850 }
01851
01852 if (_geom_data == (GeomVertexData *)NULL) {
01853 _geom_data = new GeomVertexData
01854 ("lens", GeomVertexFormat::get_v3(),
01855 Geom::UH_dynamic);
01856 }
01857
01858 GeomVertexWriter vertex(_geom_data, InternalName::get_vertex());
01859 LPoint3f near_point, far_point;
01860 for (int si = 0; si < num_segments; si++) {
01861 float t = 2.0f * (float)si / (float)num_segments;
01862
01863
01864 LPoint2f p1(-1.0f + t, 1.0f);
01865 if (!extrude(p1, near_point, far_point)) {
01866
01867 return 0;
01868 }
01869 vertex.add_data3f(near_point);
01870 vertex.add_data3f(far_point);
01871
01872
01873 LPoint2f p2(1.0f, 1.0f - t);
01874 if (!extrude(p2, near_point, far_point)) {
01875
01876 return 0;
01877 }
01878 vertex.add_data3f(near_point);
01879 vertex.add_data3f(far_point);
01880
01881
01882 LPoint2f p3(1.0f - t, -1.0f);
01883 if (!extrude(p3, near_point, far_point)) {
01884
01885 return 0;
01886 }
01887 vertex.add_data3f(near_point);
01888 vertex.add_data3f(far_point);
01889
01890
01891 LPoint2f p4(-1.0f, -1.0f + t);
01892 if (!extrude(p4, near_point, far_point)) {
01893
01894 return 0;
01895 }
01896 vertex.add_data3f(near_point);
01897 vertex.add_data3f(far_point);
01898 }
01899
01900
01901 LPoint3f near_axis = LPoint3f::origin(_cs) + LVector3f::forward(_cs) * _near_distance;
01902 LPoint3f far_axis = LPoint3f::origin(_cs) + LVector3f::forward(_cs) * _far_distance;
01903 const LMatrix4f &lens_mat = get_lens_mat();
01904 near_axis = near_axis * lens_mat;
01905 far_axis = far_axis * lens_mat;
01906 vertex.add_data3f(near_axis);
01907 vertex.add_data3f(far_axis);
01908
01909 return num_segments;
01910 }
01911
01912
01913
01914
01915
01916
01917
01918
01919 void Lens::
01920 build_shear_mat(LMatrix4f &shear_mat,
01921 const LPoint3f &cul, const LPoint3f &cur,
01922 const LPoint3f &cll, const LPoint3f &clr) {
01923
01924
01925
01926
01927 LPoint3f points[4] = {
01928 cul, cur, clr, cll
01929 };
01930
01931 float max_edge_length = -1.0f;
01932 int base_edge = -1;
01933 for (int i = 0; i < 4; i++) {
01934 LVector3f edge = points[(i + 1) % 4] - points[i];
01935 float length = edge.length_squared();
01936 if (length > max_edge_length) {
01937 base_edge = i;
01938 max_edge_length = length;
01939 }
01940 }
01941
01942 const LPoint3f &base_origin = points[base_edge];
01943 LVector3f base_vec = points[(base_edge + 1) % 4] - base_origin;
01944
01945 float base_edge_length = csqrt(max_edge_length);
01946
01947
01948
01949
01950 int a = (base_edge + 2) % 4;
01951 int b = (base_edge + 3) % 4;
01952
01953 float a_dist = sqr_dist_to_line(points[a], base_origin, base_vec);
01954 float b_dist = sqr_dist_to_line(points[b], base_origin, base_vec);
01955
01956 int far_point;
01957 float dist;
01958 if (a_dist > b_dist) {
01959 far_point = a;
01960 dist = csqrt(a_dist);
01961 } else {
01962 far_point = b;
01963 dist = csqrt(b_dist);
01964 }
01965
01966
01967
01968 LVector3f perpendic = base_vec.cross(LVector3f(0.0f, -1.0f, 0.0f));
01969 perpendic.normalize();
01970 perpendic *= dist;
01971 LPoint3f parallel_origin = points[base_edge] + perpendic;
01972
01973
01974
01975 LVector3f base_norm_vec = base_vec / base_edge_length;
01976
01977 LVector3f far_point_delta = points[far_point] - parallel_origin;
01978 float far_point_pos = far_point_delta.dot(base_norm_vec);
01979
01980 if (far_point_pos < 0.0f) {
01981
01982 parallel_origin += base_norm_vec * far_point_pos;
01983
01984 } else if (far_point_pos > base_edge_length) {
01985
01986
01987 parallel_origin += base_norm_vec * (far_point_pos - base_edge_length);
01988 }
01989
01990
01991 float t;
01992 float Ox = parallel_origin[0];
01993 float Oy = parallel_origin[2];
01994 float Vx = base_vec[0];
01995 float Vy = base_vec[2];
01996 float Ax, Ay, Bx, By;
01997
01998 if (far_point == a) {
01999
02000 LVector3f v = points[b] - base_origin;
02001 Ax = points[b][0];
02002 Ay = points[b][2];
02003 Bx = v[0];
02004 By = v[2];
02005 } else {
02006
02007 LVector3f v = points[a] - (base_origin + base_vec);
02008 Ax = points[a][0];
02009 Ay = points[a][2];
02010 Bx = v[0];
02011 By = v[2];
02012 }
02013 t = ((Ox - Ax) * By + (Ay - Oy) * Bx) / (Bx * Vy - By * Vx);
02014
02015 if (t < 0.0f) {
02016
02017
02018 parallel_origin += base_vec * t;
02019 } else if (t > 1.0f) {
02020
02021
02022 parallel_origin += base_vec * (1.0f - t);
02023 }
02024
02025 LVector3f adjacent_norm_vec = parallel_origin - base_origin;
02026 adjacent_norm_vec.normalize();
02027
02028
02029
02030 shear_mat = LMatrix4f::ident_mat();
02031
02032
02033 switch (base_edge) {
02034 case 0:
02035
02036
02037 shear_mat.set_row(0, base_norm_vec);
02038 shear_mat.set_row(2, -adjacent_norm_vec);
02039 break;
02040
02041 case 1:
02042
02043
02044 shear_mat.set_row(0, -adjacent_norm_vec);
02045 shear_mat.set_row(2, -base_norm_vec);
02046 break;
02047
02048 case 2:
02049
02050
02051 shear_mat.set_row(0, -base_norm_vec);
02052 shear_mat.set_row(2, adjacent_norm_vec);
02053 break;
02054
02055 case 3:
02056
02057
02058 shear_mat.set_row(0, adjacent_norm_vec);
02059 shear_mat.set_row(2, base_norm_vec);
02060 break;
02061
02062 default:
02063 nassertv(false);
02064 }
02065 }
02066
02067
02068
02069
02070
02071
02072
02073
02074 float Lens::
02075 sqr_dist_to_line(const LPoint3f &point, const LPoint3f &origin,
02076 const LVector3f &vec) {
02077 LVector3f norm = vec;
02078 norm.normalize();
02079 LVector3f d = point - origin;
02080 float hyp_2 = d.length_squared();
02081 float leg = d.dot(norm);
02082 return hyp_2 - leg * leg;
02083 }
02084
02085
02086
02087
02088
02089
02090
02091 void Lens::
02092 write_datagram(BamWriter *manager, Datagram &dg) {
02093 TypedWritable::write_datagram(manager, dg);
02094
02095 dg.add_string(_change_event);
02096 dg.add_uint8((int)_cs);
02097 _film_size.write_datagram(dg);
02098 _film_offset.write_datagram(dg);
02099 dg.add_float32(_focal_length);
02100 _fov.write_datagram(dg);
02101 dg.add_float32(_aspect_ratio);
02102 dg.add_float32(_near_distance);
02103 dg.add_float32(_far_distance);
02104 dg.add_uint16(_user_flags);
02105 }
02106
02107
02108
02109
02110
02111
02112
02113
02114 void Lens::
02115 fillin(DatagramIterator &scan, BamReader *manager) {
02116 TypedWritable::fillin(scan, manager);
02117
02118 _change_event = scan.get_string();
02119 _cs = (CoordinateSystem)scan.get_uint8();
02120 _film_size.read_datagram(scan);
02121 _film_offset.read_datagram(scan);
02122 _focal_length = scan.get_float32();
02123 _fov.read_datagram(scan);
02124 _aspect_ratio = scan.get_float32();
02125 _near_distance = scan.get_float32();
02126 _far_distance = scan.get_float32();
02127 _user_flags = scan.get_uint16();
02128
02129 _comp_flags = 0;
02130 }