16 #include "throw_event.h" 17 #include "compose_matrix.h" 20 #include "geomLinestrips.h" 21 #include "geomVertexWriter.h" 22 #include "boundingHexahedron.h" 24 #include "config_gobj.h" 46 Lens(
const Lens ©) : _cycler(copy._cycler) {
48 CDWriter cdata(_cycler,
true);
49 cdata->_geom_data = NULL;
58 operator = (
const Lens ©) {
59 _cycler = copy._cycler;
62 CDWriter cdata(_cycler,
true);
63 cdata->_geom_data = NULL;
77 do_adjust_comp_flags(cdata, CF_mat | CF_view_hpr | CF_view_vector, 0);
78 do_throw_change_event(cdata);
92 do_set_interocular_distance(cdata, default_iod);
93 do_set_convergence_distance(cdata, default_converge);
94 do_throw_change_event(cdata);
114 nassertv(!cnan(min_fov));
116 cdata->_min_fov = min_fov;
120 do_resequence_fov_triad(cdata, cdata->_fov_seq, cdata->_focal_length_seq, cdata->_film_size_seq);
122 if (cdata->_focal_length_seq == 0) {
124 do_adjust_user_flags(cdata, UF_focal_length | UF_vfov | UF_hfov,
128 nassertv(cdata->_film_size_seq == 0);
131 do_compute_aspect_ratio(cdata);
132 do_adjust_user_flags(cdata, UF_film_width | UF_film_height | UF_vfov | UF_hfov,
135 do_adjust_comp_flags(cdata, CF_mat | CF_focal_length | CF_fov | CF_film_size,
140 do_throw_change_event(cdata);
153 if ((cdata->_comp_flags & CF_fov) == 0) {
154 ((
Lens *)
this)->do_compute_fov((CData *)cdata.
p());
156 return cdata->_min_fov;
195 nassertv(!view_hpr.
is_nan());
197 cdata->_view_hpr = view_hpr;
198 do_adjust_user_flags(cdata, UF_view_vector | UF_view_mat,
200 do_adjust_comp_flags(cdata, CF_mat | CF_view_vector,
202 do_throw_change_event(cdata);
213 if ((cdata->_comp_flags & CF_view_hpr) == 0) {
214 ((
Lens *)
this)->do_compute_view_hpr((CData *)cdata.
p());
216 return cdata->_view_hpr;
230 nassertv(!view_vector.
is_nan());
232 cdata->_view_vector = view_vector;
233 cdata->_up_vector = up_vector;
234 do_adjust_user_flags(cdata, UF_view_hpr | UF_view_mat,
236 do_adjust_comp_flags(cdata, CF_mat | CF_view_hpr,
238 do_throw_change_event(cdata);
249 if ((cdata->_comp_flags & CF_view_vector) == 0) {
250 ((
Lens *)
this)->do_compute_view_vector((CData *)cdata.
p());
252 return cdata->_view_vector;
264 if ((cdata->_comp_flags & CF_view_vector) == 0) {
265 ((
Lens *)
this)->do_compute_view_vector((CData *)cdata.
p());
267 return cdata->_up_vector;
290 do_adjust_user_flags(cdata, 0, UF_view_vector | UF_view_hpr | UF_view_mat);
291 do_adjust_comp_flags(cdata, CF_projection_mat | CF_projection_mat_inv |
292 CF_projection_mat_left_inv | CF_projection_mat_right_inv |
293 CF_lens_mat_inv | CF_view_hpr | CF_view_vector,
295 do_throw_change_event(cdata);
317 nassertv(!keystone.
is_nan());
319 cdata->_keystone = keystone;
320 do_adjust_user_flags(cdata, 0, UF_keystone);
321 do_adjust_comp_flags(cdata, CF_projection_mat | CF_projection_mat_inv |
322 CF_projection_mat_left_inv | CF_projection_mat_right_inv |
323 CF_film_mat | CF_film_mat_inv, 0);
324 do_throw_change_event(cdata);
335 cdata->_keystone.set(0.0f, 0.0f);
336 do_adjust_user_flags(cdata, UF_keystone, 0);
337 do_adjust_comp_flags(cdata, CF_projection_mat | CF_projection_mat_inv |
338 CF_projection_mat_left_inv | CF_projection_mat_right_inv |
339 CF_film_mat | CF_film_mat_inv, 0);
340 do_throw_change_event(cdata);
357 nassertv(!custom_film_mat.
is_nan());
359 cdata->_custom_film_mat = custom_film_mat;
360 do_adjust_user_flags(cdata, 0, UF_custom_film_mat);
361 do_adjust_comp_flags(cdata, CF_projection_mat | CF_projection_mat_inv |
362 CF_projection_mat_left_inv | CF_projection_mat_right_inv |
363 CF_film_mat | CF_film_mat_inv, 0);
364 do_throw_change_event(cdata);
376 do_adjust_user_flags(cdata, UF_custom_film_mat, 0);
377 do_adjust_comp_flags(cdata, CF_projection_mat | CF_projection_mat_inv |
378 CF_projection_mat_left_inv | CF_projection_mat_right_inv |
379 CF_film_mat | CF_film_mat_inv, 0);
380 do_throw_change_event(cdata);
452 const LMatrix4 &lens_mat_inv = do_get_lens_mat_inv(cdata);
454 lens_mat_inv.
get_row3(eye_offset, 3);
461 if ((flags & FC_camera_plane) != 0) {
462 view_vector = (ul + ur + ll + lr) * 0.25;
464 LPlane plane(ll, ul, ur);
465 view_vector = plane.get_normal();
474 if (view_vector == up_vector || ((flags & FC_roll) != 0)) {
476 up_vector = view_vector.cross(top);
477 nassertv(!up_vector.is_nan() && up_vector.length_squared() != 0.0f);
482 look_at(rot_mat, view_vector, up_vector, CS_zup_right);
497 nassertv(cul[1] != 0.0f && cur[1] != 0.0f && cll[1] != 0.0f && clr[1] != 0.0f);
507 if ((flags & FC_shear) != 0) {
508 build_shear_mat(shear_mat, cul, cur, cll, clr);
518 inv_view_mat.
set_row(3, eye_offset);
522 do_set_view_mat(cdata, view_mat);
530 nassertv(ful[1] != 0.0f && fur[1] != 0.0f && fll[1] != 0.0f && flr[1] != 0.0f);
538 PN_stdfloat min_x = min(min(ful[0], fur[0]), min(fll[0], flr[0]));
539 PN_stdfloat max_x = max(max(ful[0], fur[0]), max(fll[0], flr[0]));
540 PN_stdfloat min_z = min(min(ful[2], fur[2]), min(fll[2], flr[2]));
541 PN_stdfloat max_z = max(max(ful[2], fur[2]), max(fll[2], flr[2]));
543 PN_stdfloat x_spread, x_center, z_spread, z_center;
545 if ((flags & FC_off_axis) != 0) {
548 x_center = (max_x + min_x) * 0.5f;
549 z_center = (max_z + min_z) * 0.5f;
550 x_spread = x_center - min_x;
551 z_spread = z_center - min_z;
556 x_spread = max(cabs(max_x), cabs(min_x));
557 z_spread = max(cabs(max_z), cabs(min_z));
560 PN_stdfloat aspect_ratio = do_get_aspect_ratio(cdata);
561 nassertv(aspect_ratio != 0.0f);
562 if ((flags & FC_aspect_ratio) == 0) {
565 if (x_spread < z_spread * aspect_ratio) {
567 x_spread = z_spread * aspect_ratio;
568 }
else if (z_spread < x_spread / aspect_ratio) {
570 z_spread = x_spread / aspect_ratio;
574 PN_stdfloat hfov = rad_2_deg(catan(x_spread)) * 2.0f;
575 PN_stdfloat vfov = rad_2_deg(catan(z_spread)) * 2.0f;
577 do_set_fov(cdata,
LVecBase2(hfov, vfov));
579 if ((flags & FC_aspect_ratio) == 0) {
583 do_set_aspect_ratio(cdata, aspect_ratio);
586 const LVecBase2 &film_size = do_get_film_size(cdata);
587 nassertv(x_spread != 0.0f && z_spread != 0.0f);
588 do_set_film_offset(cdata,
LVecBase2(film_size[0] * x_center / (x_spread * 2.0f),
589 film_size[1] * z_center / (z_spread * 2.0f)));
603 cdata->_comp_flags = 0;
665 int num_segments = do_define_geom_data(cdata);
666 if (num_segments == 0) {
668 cdata->_geom_data.clear();
677 for (i = 0; i < 4; ++i) {
678 for (si = 0; si < num_segments; ++si) {
679 line->add_vertex(i * 2 + si * (4 * 2) + 0);
683 line->close_primitive();
686 for (i = 0; i < 4; ++i) {
687 for (si = 0; si < num_segments; ++si) {
688 line->add_vertex(i * 2 + si * (4 * 2) + 1);
692 line->close_primitive();
695 line->add_vertex(0 * 2 + 0);
696 line->add_vertex(0 * 2 + 1);
697 line->close_primitive();
699 line->add_vertex(1 * 2 + 0);
700 line->add_vertex(1 * 2 + 1);
701 line->close_primitive();
703 line->add_vertex(2 * 2 + 0);
704 line->add_vertex(2 * 2 + 1);
705 line->close_primitive();
707 line->add_vertex(3 * 2 + 0);
708 line->add_vertex(3 * 2 + 1);
709 line->close_primitive();
712 line->add_vertex(num_segments * (4 * 2) + 0);
713 line->add_vertex(num_segments * (4 * 2) + 1);
714 line->close_primitive();
716 PT(
Geom) geom =
new Geom(cdata->_geom_data);
717 geom->add_primitive(line);
731 make_bounds()
const {
741 corner.set(-1.0f, 1.0f, 0.0f);
742 if (!do_extrude(cdata, corner, nul, ful)) {
747 corner.set(1.0f, 1.0f, 0.0f);
748 if (!do_extrude(cdata, corner, nur, fur)) {
753 corner.set(1.0f, -1.0f, 0.0f);
754 if (!do_extrude(cdata, corner, nlr, flr)) {
759 corner.set(-1.0f, -1.0f, 0.0f);
760 if (!do_extrude(cdata, corner, nll, fll)) {
773 output(ostream &out)
const {
783 write(ostream &out,
int indent_level)
const {
784 indent(out, indent_level) << get_type() <<
" fov = " <<
get_fov() <<
"\n";
793 do_set_film_size(CData *cdata, PN_stdfloat width) {
794 nassertv(!cnan(width));
795 cdata->_film_size.set(width, width / do_get_aspect_ratio(cdata));
799 do_resequence_fov_triad(cdata, cdata->_film_size_seq, cdata->_focal_length_seq, cdata->_fov_seq);
801 if (cdata->_fov_seq == 0) {
803 do_adjust_user_flags(cdata, UF_hfov | UF_vfov | UF_min_fov | UF_film_height,
807 nassertv(cdata->_focal_length_seq == 0);
808 do_adjust_user_flags(cdata, UF_focal_length | UF_film_height,
811 do_adjust_comp_flags(cdata, CF_mat | CF_focal_length | CF_fov,
813 do_throw_change_event(cdata);
822 do_set_film_size(CData *cdata,
const LVecBase2 &film_size) {
823 nassertv(!film_size.
is_nan());
824 cdata->_film_size = film_size;
828 do_resequence_fov_triad(cdata, cdata->_film_size_seq, cdata->_focal_length_seq, cdata->_fov_seq);
830 if (cdata->_fov_seq == 0) {
832 do_adjust_user_flags(cdata, UF_hfov | UF_vfov | UF_min_fov | UF_aspect_ratio,
833 UF_film_width | UF_film_height);
836 nassertv(cdata->_focal_length_seq == 0);
837 do_adjust_user_flags(cdata, UF_focal_length | UF_vfov | UF_aspect_ratio,
838 UF_film_width | UF_film_height);
840 do_adjust_comp_flags(cdata, CF_mat | CF_focal_length | CF_fov | CF_aspect_ratio,
845 do_compute_aspect_ratio(cdata);
846 do_adjust_user_flags(cdata, 0, UF_aspect_ratio);
848 do_throw_change_event(cdata);
857 do_get_film_size(
const CData *cdata)
const {
858 if ((cdata->_comp_flags & CF_film_size) == 0) {
862 ((
Lens *)
this)->do_compute_film_size((CData *)cdata);
864 return cdata->_film_size;
873 do_set_focal_length(CData *cdata, PN_stdfloat focal_length) {
874 nassertv(!cnan(focal_length));
875 cdata->_focal_length = focal_length;
879 do_resequence_fov_triad(cdata, cdata->_focal_length_seq, cdata->_film_size_seq, cdata->_fov_seq);
881 if (cdata->_film_size_seq == 0) {
883 do_adjust_user_flags(cdata, UF_film_width | UF_film_height,
887 nassertv(cdata->_fov_seq == 0);
888 do_adjust_user_flags(cdata, UF_hfov | UF_vfov | UF_min_fov,
892 do_adjust_comp_flags(cdata, CF_mat | CF_fov | CF_film_size,
894 do_throw_change_event(cdata);
903 do_get_focal_length(
const CData *cdata)
const {
904 if ((cdata->_comp_flags & CF_focal_length) == 0) {
905 ((
Lens *)
this)->do_compute_focal_length((CData *)cdata);
907 return cdata->_focal_length;
916 do_set_fov(CData *cdata, PN_stdfloat hfov) {
917 nassertv(!cnan(hfov));
918 cdata->_fov[0] = hfov;
922 do_resequence_fov_triad(cdata, cdata->_fov_seq, cdata->_focal_length_seq, cdata->_film_size_seq);
924 if (cdata->_focal_length_seq == 0) {
926 do_adjust_user_flags(cdata, UF_focal_length | UF_vfov | UF_min_fov,
930 nassertv(cdata->_film_size_seq == 0);
933 do_compute_aspect_ratio(cdata);
934 do_adjust_user_flags(cdata, UF_film_width | UF_film_height | UF_vfov | UF_min_fov,
937 do_adjust_comp_flags(cdata, CF_mat | CF_focal_length | CF_fov | CF_film_size,
942 do_throw_change_event(cdata);
951 do_set_fov(CData *cdata,
const LVecBase2 &fov) {
957 do_resequence_fov_triad(cdata, cdata->_fov_seq, cdata->_focal_length_seq, cdata->_film_size_seq);
959 if (cdata->_focal_length_seq == 0) {
961 do_adjust_user_flags(cdata, UF_focal_length | UF_film_height | UF_min_fov | UF_aspect_ratio,
965 nassertv(cdata->_film_size_seq == 0);
966 do_adjust_user_flags(cdata, UF_film_width | UF_film_height | UF_min_fov | UF_aspect_ratio,
969 do_adjust_comp_flags(cdata, CF_mat | CF_focal_length | CF_film_size | CF_aspect_ratio,
974 do_compute_aspect_ratio(cdata);
975 do_adjust_user_flags(cdata, 0, UF_aspect_ratio);
977 do_throw_change_event(cdata);
986 do_get_fov(
const CData *cdata)
const {
987 if ((cdata->_comp_flags & CF_fov) == 0) {
988 ((
Lens *)
this)->do_compute_fov((CData *)cdata);
999 do_set_aspect_ratio(CData *cdata, PN_stdfloat aspect_ratio) {
1000 nassertv(!cnan(aspect_ratio));
1001 cdata->_aspect_ratio = aspect_ratio;
1002 do_adjust_user_flags(cdata, UF_film_height | UF_vfov,
1004 do_adjust_comp_flags(cdata, CF_mat | CF_film_size | CF_fov | CF_focal_length,
1006 do_throw_change_event(cdata);
1015 do_get_aspect_ratio(
const CData *cdata)
const {
1016 if ((cdata->_comp_flags & CF_aspect_ratio) == 0) {
1017 ((
Lens *)
this)->do_compute_aspect_ratio((CData *)cdata);
1019 return cdata->_aspect_ratio;
1028 do_get_projection_mat(
const CData *cdata, StereoChannel channel)
const {
1029 if ((cdata->_comp_flags & CF_projection_mat) == 0) {
1030 ((
Lens *)
this)->do_compute_projection_mat((CData *)cdata);
1035 return cdata->_projection_mat_left;
1037 return cdata->_projection_mat_right;
1040 return cdata->_projection_mat;
1043 return cdata->_projection_mat;
1052 do_get_projection_mat_inv(
const CData *cdata, StereoChannel stereo_channel)
const {
1053 switch (stereo_channel) {
1056 if ((cdata->_comp_flags & CF_projection_mat_left_inv) == 0) {
1057 const LMatrix4 &projection_mat_left = do_get_projection_mat(cdata, SC_left);
1058 ((CData *)cdata)->_projection_mat_left_inv.invert_from(projection_mat_left);
1059 ((
Lens *)
this)->do_adjust_comp_flags((CData *)cdata, 0, CF_projection_mat_left_inv);
1062 return cdata->_projection_mat_left_inv;
1066 if ((cdata->_comp_flags & CF_projection_mat_right_inv) == 0) {
1067 const LMatrix4 &projection_mat_right = do_get_projection_mat(cdata, SC_right);
1068 ((CData *)cdata)->_projection_mat_right_inv.invert_from(projection_mat_right);
1069 ((
Lens *)
this)->do_adjust_comp_flags((CData *)cdata, 0, CF_projection_mat_right_inv);
1072 return cdata->_projection_mat_right_inv;
1079 if ((cdata->_comp_flags & CF_projection_mat_inv) == 0) {
1080 const LMatrix4 &projection_mat = do_get_projection_mat(cdata);
1081 ((CData *)cdata)->_projection_mat_inv.invert_from(projection_mat);
1082 ((
Lens *)
this)->do_adjust_comp_flags((CData *)cdata, 0, CF_projection_mat_inv);
1084 return cdata->_projection_mat_inv;
1093 do_get_film_mat(
const CData *cdata)
const {
1094 if ((cdata->_comp_flags & CF_film_mat) == 0) {
1095 ((
Lens *)
this)->do_compute_film_mat((CData *)cdata);
1097 return cdata->_film_mat;
1106 do_get_film_mat_inv(
const CData *cdata)
const {
1107 if ((cdata->_comp_flags & CF_film_mat_inv) == 0) {
1108 const LMatrix4 &film_mat = do_get_film_mat(cdata);
1109 ((CData *)cdata)->_film_mat_inv.invert_from(film_mat);
1110 ((
Lens *)
this)->do_adjust_comp_flags((CData *)cdata, 0, CF_film_mat_inv);
1112 return cdata->_film_mat_inv;
1121 do_get_lens_mat(
const CData *cdata)
const {
1122 if ((cdata->_comp_flags & CF_lens_mat) == 0) {
1123 ((
Lens *)
this)->do_compute_lens_mat((CData *)cdata);
1125 return cdata->_lens_mat;
1134 do_get_lens_mat_inv(
const CData *cdata)
const {
1135 if ((cdata->_comp_flags & CF_lens_mat_inv) == 0) {
1136 const LMatrix4 &lens_mat = do_get_lens_mat(cdata);
1137 ((CData *)cdata)->_lens_mat_inv.invert_from(lens_mat);
1138 ((
Lens *)
this)->do_adjust_comp_flags((CData *)cdata, 0, CF_lens_mat_inv);
1140 return cdata->_lens_mat_inv;
1149 do_set_interocular_distance(CData *cdata, PN_stdfloat interocular_distance) {
1150 nassertv(!cnan(interocular_distance));
1151 cdata->_interocular_distance = interocular_distance;
1152 if (cdata->_interocular_distance == 0.0f) {
1153 do_adjust_user_flags(cdata, UF_interocular_distance, 0);
1155 do_adjust_user_flags(cdata, 0, UF_interocular_distance);
1158 do_adjust_comp_flags(cdata, CF_mat, 0);
1167 do_set_convergence_distance(CData *cdata, PN_stdfloat convergence_distance) {
1168 nassertv(!cnan(convergence_distance));
1169 cdata->_convergence_distance = convergence_distance;
1170 if (cdata->_convergence_distance == 0.0f) {
1171 do_adjust_user_flags(cdata, UF_convergence_distance, 0);
1173 do_adjust_user_flags(cdata, 0, UF_convergence_distance);
1176 do_adjust_comp_flags(cdata, CF_mat, 0);
1185 do_set_view_mat(CData *cdata,
const LMatrix4 &view_mat) {
1186 nassertv(!view_mat.
is_nan());
1187 cdata->_lens_mat = view_mat;
1188 do_adjust_user_flags(cdata, UF_view_vector | UF_view_hpr,
1190 do_adjust_comp_flags(cdata, CF_projection_mat | CF_projection_mat_inv |
1191 CF_projection_mat_left_inv | CF_projection_mat_right_inv |
1192 CF_lens_mat_inv | CF_view_hpr | CF_view_vector,
1194 do_throw_change_event(cdata);
1203 do_get_view_mat(
const CData *cdata)
const {
1204 if ((cdata->_comp_flags & CF_lens_mat) == 0) {
1205 ((
Lens *)
this)->do_compute_lens_mat((CData *)cdata);
1207 return cdata->_lens_mat;
1217 do_throw_change_event(CData *cdata) {
1218 ++(cdata->_last_change);
1220 if (!cdata->_change_event.empty()) {
1221 throw_event(cdata->_change_event,
this);
1224 if (!cdata->_geom_data.is_null()) {
1225 if (cdata->_geom_data->get_ref_count() == 1) {
1229 cdata->_geom_data.clear();
1233 do_define_geom_data(cdata);
1256 do_extrude(
const CData *cdata,
1258 const LMatrix4 &projection_mat_inv = do_get_projection_mat_inv(cdata);
1260 LVecBase4 full(point2d[0], point2d[1], -1.0f, 1.0f);
1261 full = projection_mat_inv.
xform(full);
1263 PN_stdfloat recip_full3 = 1.0 / max((
double)full[3], (
double)lens_far_limit);
1264 near_point.set(full[0] * recip_full3,
1265 full[1] * recip_full3,
1266 full[2] * recip_full3);
1269 LVecBase4 full(point2d[0], point2d[1], 1.0f, 1.0f);
1270 full = projection_mat_inv.
xform(full);
1277 PN_stdfloat recip_full3 = 1.0 / max((
double)full[3], (
double)lens_far_limit);
1278 far_point.set(full[0] * recip_full3,
1279 full[1] * recip_full3,
1280 full[2] * recip_full3);
1293 do_extrude_depth(
const CData *cdata,
1295 LPoint3 near_point, far_point;
1296 bool result =
extrude(point2d, near_point, far_point);
1300 PN_stdfloat t = point2d[2] * 0.5 + 0.5;
1301 point3d = near_point + (far_point - near_point) * t;
1313 do_extrude_depth_with_mat(
const CData *cdata,
1315 const LMatrix4 &projection_mat_inv = do_get_projection_mat_inv(cdata);
1350 do_extrude_vec(
const CData *cdata,
const LPoint3 &point2d,
LVector3 &vec)
const {
1374 do_project(
const CData *cdata,
const LPoint3 &point3d,
LPoint3 &point2d)
const {
1375 const LMatrix4 &projection_mat = do_get_projection_mat(cdata);
1376 LVecBase4 full(point3d[0], point3d[1], point3d[2], 1.0f);
1377 full = projection_mat.
xform(full);
1378 if (full[3] == 0.0f) {
1379 point2d.set(0.0f, 0.0f, 0.0f);
1382 PN_stdfloat recip_full3 = 1.0f/full[3];
1383 point2d.set(full[0] * recip_full3, full[1] * recip_full3, full[2] * recip_full3);
1386 (point2d[0] >= -1.0f) && (point2d[0] <= 1.0f) &&
1387 (point2d[1] >= -1.0f) && (point2d[1] <= 1.0f);
1397 do_compute_film_size(CData *cdata) {
1398 if ((cdata->_user_flags & (UF_min_fov | UF_focal_length)) == (UF_min_fov | UF_focal_length)) {
1402 PN_stdfloat fs = fov_to_film(cdata->_min_fov, cdata->_focal_length,
true);
1403 nassertv((cdata->_user_flags & UF_aspect_ratio) != 0 ||
1404 (cdata->_comp_flags & CF_aspect_ratio) != 0);
1406 if (cdata->_aspect_ratio < 1.0f) {
1407 cdata->_film_size[1] = fs / cdata->_aspect_ratio;
1408 cdata->_film_size[0] = fs;
1411 cdata->_film_size[0] = fs * cdata->_aspect_ratio;
1412 cdata->_film_size[1] = fs;
1416 if ((cdata->_user_flags & UF_film_width) == 0) {
1417 if ((cdata->_user_flags & (UF_hfov | UF_focal_length)) == (UF_hfov | UF_focal_length)) {
1418 cdata->_film_size[0] = fov_to_film(cdata->_fov[0], cdata->_focal_length,
true);
1420 cdata->_film_size[0] = 1.0f;
1424 if ((cdata->_user_flags & UF_film_height) == 0) {
1425 if ((cdata->_user_flags & (UF_vfov | UF_focal_length)) == (UF_vfov | UF_focal_length)) {
1426 cdata->_film_size[1] = fov_to_film(cdata->_fov[1], cdata->_focal_length,
false);
1428 }
else if ((cdata->_user_flags & (UF_hfov | UF_vfov)) == (UF_hfov | UF_vfov)) {
1432 if ((cdata->_comp_flags & CF_focal_length) == 0) {
1433 cdata->_focal_length = fov_to_focal_length(cdata->_fov[0], cdata->_film_size[0],
true);
1434 do_adjust_comp_flags(cdata, 0, CF_focal_length);
1436 cdata->_film_size[1] = fov_to_film(cdata->_fov[1], cdata->_focal_length,
false);
1438 }
else if ((cdata->_user_flags & UF_aspect_ratio) != 0 ||
1439 (cdata->_comp_flags & CF_aspect_ratio) != 0) {
1440 cdata->_film_size[1] = cdata->_film_size[0] / cdata->_aspect_ratio;
1444 cdata->_film_size[1] = cdata->_film_size[0];
1449 do_adjust_comp_flags(cdata, 0, CF_film_size);
1460 do_compute_focal_length(CData *cdata) {
1461 if ((cdata->_user_flags & UF_focal_length) == 0) {
1462 const LVecBase2 &film_size = do_get_film_size(cdata);
1463 const LVecBase2 &fov = do_get_fov(cdata);
1464 cdata->_focal_length = fov_to_focal_length(fov[0], film_size[0],
true);
1467 do_adjust_comp_flags(cdata, 0, CF_focal_length);
1477 do_compute_fov(CData *cdata) {
1478 const LVecBase2 &film_size = do_get_film_size(cdata);
1480 bool got_hfov = ((cdata->_user_flags & UF_hfov) != 0);
1481 bool got_vfov = ((cdata->_user_flags & UF_vfov) != 0);
1482 bool got_min_fov = ((cdata->_user_flags & UF_min_fov) != 0);
1484 if (!got_hfov && !got_vfov && !got_min_fov) {
1486 if ((cdata->_user_flags & UF_focal_length) != 0) {
1488 cdata->_fov[0] = film_to_fov(film_size[0], cdata->_focal_length,
true);
1489 cdata->_fov[1] = film_to_fov(film_size[1], cdata->_focal_length,
true);
1495 cdata->_min_fov = default_fov;
1503 if (film_size[0] < film_size[1]) {
1504 cdata->_fov[0] = cdata->_min_fov;
1507 cdata->_fov[1] = cdata->_min_fov;
1514 if ((cdata->_user_flags & UF_focal_length) == 0 &&
1515 (cdata->_comp_flags & CF_focal_length) == 0) {
1519 cdata->_focal_length = fov_to_focal_length(cdata->_fov[1], film_size[1],
true);
1520 do_adjust_comp_flags(cdata, 0, CF_focal_length);
1522 cdata->_fov[0] = film_to_fov(film_size[0], cdata->_focal_length,
false);
1527 if ((cdata->_user_flags & UF_focal_length) == 0 &&
1528 (cdata->_comp_flags & CF_focal_length) == 0) {
1532 cdata->_focal_length = fov_to_focal_length(cdata->_fov[0], film_size[0],
true);
1533 do_adjust_comp_flags(cdata, 0, CF_focal_length);
1535 cdata->_fov[1] = film_to_fov(film_size[1], cdata->_focal_length,
false);
1540 cdata->_min_fov = film_size[0] < film_size[1] ? cdata->_fov[0] : cdata->_fov[1];
1544 nassertv(got_hfov && got_vfov && got_min_fov);
1545 do_adjust_comp_flags(cdata, 0, CF_fov);
1555 do_compute_aspect_ratio(CData *cdata) {
1556 if ((cdata->_user_flags & UF_aspect_ratio) == 0) {
1557 const LVecBase2 &film_size = do_get_film_size(cdata);
1558 if (film_size[1] == 0.0f) {
1559 cdata->_aspect_ratio = 1.0f;
1561 cdata->_aspect_ratio = film_size[0] / film_size[1];
1564 do_adjust_comp_flags(cdata, 0, CF_aspect_ratio);
1574 do_compute_view_hpr(CData *cdata) {
1575 if ((cdata->_user_flags & UF_view_hpr) == 0) {
1576 const LMatrix4 &view_mat = do_get_view_mat(cdata);
1578 decompose_matrix(view_mat, scale, shear, cdata->_view_hpr, translate, cdata->_cs);
1580 do_adjust_comp_flags(cdata, 0, CF_view_hpr);
1589 do_compute_view_vector(CData *cdata) {
1590 if ((cdata->_user_flags & UF_view_vector) == 0) {
1591 const LMatrix4 &view_mat = do_get_view_mat(cdata);
1593 cdata->_up_vector =
LVector3::up(cdata->_cs) * view_mat;
1595 do_adjust_comp_flags(cdata, 0, CF_view_vector);
1605 do_compute_projection_mat(CData *lens_cdata) {
1614 CoordinateSystem cs = lens_cdata->_cs;
1615 if (cs == CS_default) {
1616 cs = get_default_coordinate_system();
1623 lens_cdata->_projection_mat_left = lens_cdata->_projection_mat_right = lens_cdata->_projection_mat;
1624 lens_cdata->_projection_mat_left_inv = lens_cdata->_projection_mat_right_inv = lens_cdata->_projection_mat_inv;
1626 do_adjust_comp_flags(lens_cdata, 0, CF_projection_mat | CF_projection_mat_inv |
1627 CF_projection_mat_left_inv | CF_projection_mat_right_inv);
1637 do_compute_film_mat(CData *cdata) {
1644 LVecBase2 film_size = do_get_film_size(cdata);
1645 LVector2 film_offset = do_get_film_offset(cdata);
1647 PN_stdfloat scale_x = 2.0f / film_size[0];
1648 PN_stdfloat scale_y = 2.0f / film_size[1];
1649 cdata->_film_mat.set(scale_x, 0.0f, 0.0f, 0.0f,
1650 0.0f, scale_y, 0.0f, 0.0f,
1651 0.0f, 0.0f, 1.0f, 0.0f,
1652 -film_offset[0] * scale_x, -film_offset[1] * scale_y, 0.0f, 1.0f);
1654 if ((cdata->_user_flags & UF_keystone) != 0) {
1655 cdata->_film_mat =
LMatrix4(1.0f, 0.0f, cdata->_keystone[0], cdata->_keystone[0],
1656 0.0f, 1.0f, cdata->_keystone[1], cdata->_keystone[1],
1657 0.0f, 0.0f, 1.0f, 0.0f,
1658 0.0f, 0.0f, 0.0f, 1.0f) * cdata->_film_mat;
1661 if ((cdata->_user_flags & UF_custom_film_mat) != 0) {
1662 cdata->_film_mat = cdata->_film_mat * cdata->_custom_film_mat;
1665 do_adjust_comp_flags(cdata, CF_film_mat_inv, CF_film_mat);
1675 do_compute_lens_mat(CData *cdata) {
1676 if ((cdata->_user_flags & UF_view_mat) == 0) {
1677 if ((cdata->_user_flags & UF_view_hpr) != 0) {
1678 compose_matrix(cdata->_lens_mat,
1682 LVecBase3(0.0f, 0.0f, 0.0f), cdata->_cs);
1684 }
else if ((cdata->_user_flags & UF_view_vector) != 0) {
1685 look_at(cdata->_lens_mat, cdata->_view_vector, cdata->_up_vector, cdata->_cs);
1691 do_adjust_comp_flags(cdata, CF_lens_mat_inv, CF_lens_mat);
1704 fov_to_film(PN_stdfloat, PN_stdfloat,
bool)
const {
1718 fov_to_focal_length(PN_stdfloat, PN_stdfloat,
bool)
const {
1732 film_to_fov(PN_stdfloat, PN_stdfloat,
bool)
const {
1751 do_resequence_fov_triad(
const CData *cdata,
char &newest,
char &older_a,
char &older_b)
const {
1752 nassertv(newest + older_a + older_b == 3);
1758 nassertv(older_a + older_b == 1);
1764 nassertv(older_b == 0);
1767 nassertv(older_a == 0 && older_b == 2);
1773 nassertv(older_a + older_b == 1);
1778 <<
"Invalid fov sequence numbers in lens: " 1779 << (int)newest <<
", " << (
int)older_a <<
", " << (int)older_b <<
"\n";
1784 if (gobj_cat.is_debug()) {
1786 <<
"Lens.do_resequence_fov_triad():";
1787 for (
int i = 2; i >= 0; --i) {
1788 if (cdata->_fov_seq == i) {
1789 gobj_cat.debug(
false)
1791 }
else if (cdata->_focal_length_seq == i) {
1792 gobj_cat.debug(
false)
1794 }
else if (cdata->_film_size_seq == i) {
1795 gobj_cat.debug(
false)
1799 gobj_cat.debug(
false)
1815 do_define_geom_data(CData *cdata) {
1816 int num_segments = 1;
1818 num_segments = lens_geom_segments;
1823 (
"lens", GeomVertexFormat::get_v3(),
1826 cdata->_geom_data->unclean_set_num_rows(num_segments * 8 + 2);
1829 LPoint3 near_point, far_point;
1830 for (
int si = 0; si < num_segments; si++) {
1831 PN_stdfloat t = 2.0f * (PN_stdfloat)si / (PN_stdfloat)num_segments;
1834 LPoint3 p1(-1.0f + t, 1.0f, 0.0f);
1835 if (!do_extrude(cdata, p1, near_point, far_point)) {
1843 LPoint3 p2(1.0f, 1.0f - t, 0.0f);
1844 if (!do_extrude(cdata, p2, near_point, far_point)) {
1852 LPoint3 p3(1.0f - t, -1.0f, 0.0f);
1853 if (!do_extrude(cdata, p3, near_point, far_point)) {
1861 LPoint3 p4(-1.0f, -1.0f + t, 0.0f);
1862 if (!do_extrude(cdata, p4, near_point, far_point)) {
1874 if (!do_extrude(cdata, pc, near_point, far_point)) {
1882 return num_segments;
1893 build_shear_mat(
LMatrix4 &shear_mat,
1904 PN_stdfloat max_edge_length = -1.0f;
1906 for (
int i = 0; i < 4; i++) {
1907 LVector3 edge = points[(i + 1) % 4] - points[i];
1909 if (length > max_edge_length) {
1911 max_edge_length = length;
1915 const LPoint3 &base_origin = points[base_edge];
1916 LVector3 base_vec = points[(base_edge + 1) % 4] - base_origin;
1918 PN_stdfloat base_edge_length = csqrt(max_edge_length);
1923 int a = (base_edge + 2) % 4;
1924 int b = (base_edge + 3) % 4;
1926 PN_stdfloat a_dist = sqr_dist_to_line(points[a], base_origin, base_vec);
1927 PN_stdfloat b_dist = sqr_dist_to_line(points[b], base_origin, base_vec);
1931 if (a_dist > b_dist) {
1933 dist = csqrt(a_dist);
1936 dist = csqrt(b_dist);
1944 LPoint3 parallel_origin = points[base_edge] + perpendic;
1948 LVector3 base_norm_vec = base_vec / base_edge_length;
1950 LVector3 far_point_delta = points[far_point] - parallel_origin;
1951 PN_stdfloat far_point_pos = far_point_delta.dot(base_norm_vec);
1953 if (far_point_pos < 0.0f) {
1955 parallel_origin += base_norm_vec * far_point_pos;
1957 }
else if (far_point_pos > base_edge_length) {
1960 parallel_origin += base_norm_vec * (far_point_pos - base_edge_length);
1965 PN_stdfloat Ox = parallel_origin[0];
1966 PN_stdfloat Oy = parallel_origin[2];
1967 PN_stdfloat Vx = base_vec[0];
1968 PN_stdfloat Vy = base_vec[2];
1969 PN_stdfloat Ax, Ay, Bx, By;
1971 if (far_point == a) {
1973 LVector3 v = points[b] - base_origin;
1980 LVector3 v = points[a] - (base_origin + base_vec);
1986 t = ((Ox - Ax) * By + (Ay - Oy) * Bx) / (Bx * Vy - By * Vx);
1991 parallel_origin += base_vec * t;
1992 }
else if (t > 1.0f) {
1995 parallel_origin += base_vec * (1.0f - t);
1998 LVector3 adjacent_norm_vec = parallel_origin - base_origin;
2006 switch (base_edge) {
2010 shear_mat.
set_row(0, base_norm_vec);
2011 shear_mat.
set_row(2, -adjacent_norm_vec);
2017 shear_mat.
set_row(0, -adjacent_norm_vec);
2018 shear_mat.
set_row(2, -base_norm_vec);
2024 shear_mat.
set_row(0, -base_norm_vec);
2025 shear_mat.
set_row(2, adjacent_norm_vec);
2031 shear_mat.
set_row(0, adjacent_norm_vec);
2032 shear_mat.
set_row(2, base_norm_vec);
2054 PN_stdfloat leg = d.dot(norm);
2055 return hyp_2 - leg * leg;
2099 CData(
const Lens::CData ©) {
2100 _change_event = copy._change_event;
2102 _film_size = copy._film_size;
2103 _film_offset = copy._film_offset;
2104 _focal_length = copy._focal_length;
2106 _min_fov = copy._min_fov;
2107 _aspect_ratio = copy._aspect_ratio;
2108 _near_distance = copy._near_distance;
2109 _far_distance = copy._far_distance;
2111 _view_hpr = copy._view_hpr;
2112 _view_vector = copy._view_vector;
2113 _interocular_distance = copy._interocular_distance;
2114 _convergence_distance = copy._convergence_distance;
2115 _keystone = copy._keystone;
2120 _lens_mat = copy._lens_mat;
2122 _user_flags = copy._user_flags;
2125 _focal_length_seq = copy._focal_length_seq;
2126 _fov_seq = copy._fov_seq;
2127 _film_size_seq = copy._film_size_seq;
2129 _geom_data = copy._geom_data;
2139 return new CData(*
this);
2152 _film_size.write_datagram(dg);
2153 _film_offset.write_datagram(dg);
2155 _fov.write_datagram(dg);
2172 _cs = (CoordinateSystem)scan.
get_uint8();
2173 _film_size.read_datagram(scan);
2174 _film_offset.read_datagram(scan);
2176 _fov.read_datagram(scan);
2194 _film_size.set(1.0f, 1.0f);
2195 _film_offset.set(0.0f, 0.0f);
2196 _focal_length = 1.0f;
2197 _fov.set(default_fov, default_fov);
2198 _aspect_ratio = 1.0f;
2199 _near_distance = default_near;
2200 _far_distance = default_far;
2201 _view_hpr.set(0.0f, 0.0f, 0.0f);
2202 _view_vector.set(0.0f, 1.0f, 0.0f);
2203 _up_vector.set(0.0f, 0.0f, 1.0f);
2204 _keystone.set(0.0f, 0.0f);
2208 _comp_flags = CF_fov;
2210 _interocular_distance = 0.0;
2211 _convergence_distance = 0.0;
2214 _keystone.set(default_keystone[0], default_keystone[1]);
2215 _user_flags |= UF_keystone;
2220 _focal_length_seq = 1;
bool invert_affine_from(const LMatrix4f &other)
Performs an invert of the indicated matrix, storing the result in this matrix.
virtual bool is_linear() const
Returns true if the lens represents a linear projection (e.g.
float length_squared() const
Returns the square of the vector's length, cheap and easy.
const CycleDataType * p() const
This allows the CycleDataReader to be passed to any function that expects a const CycleDataType point...
static const LMatrix4f & ident_mat()
Returns an identity matrix.
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
void set_keystone(const LVecBase2 &keystone)
Indicates the ratio of keystone correction to perform on the lens, in each of three axes...
void add_uint8(PN_uint8 value)
Adds an unsigned 8-bit integer to the datagram.
This is the base class for all three-component vectors and points.
void add_string(const string &str)
Adds a variable-length string to the datagram.
PN_stdfloat get_stdfloat()
Extracts either a 32-bit or a 64-bit floating-point number, according to Datagram::set_stdfloat_doubl...
A base class for any number of different kinds of lenses, linear and otherwise.
virtual bool is_orthographic() const
Returns true if the lens represents a orthographic projection (i.e.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
void set_data3(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Sets the write row to a particular 3-component value, and advances the write row. ...
void read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler)
Reads in the indicated CycleData object.
LPoint3 get_nodal_point() const
Returns the center point of the lens: the point from which the lens is viewing.
void clear()
Resets all lens parameters to their initial default settings.
const LVecBase2 & get_fov() const
Returns the horizontal and vertical film size of the virtual film.
A single page of data maintained by a PipelineCycler.
void write_cdata(Datagram &packet, const PipelineCyclerBase &cycler)
Writes out the indicated CycleData object.
void set_coordinate_system(CoordinateSystem cs)
Specifies the coordinate system that all 3-d computations are performed within for this Lens...
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
bool is_nan() const
Returns true if any component of the vector is not-a-number, false otherwise.
PN_uint8 get_uint8()
Extracts an unsigned 8-bit integer.
static const LMatrix4f & convert_mat(CoordinateSystem from, CoordinateSystem to)
Returns a matrix that transforms from the indicated coordinate system to the indicated coordinate sys...
bool is_nan() const
Returns true if any component of the matrix is not-a-number, false otherwise.
string get_string()
Extracts a variable-length string.
virtual void fillin(DatagramIterator &scan, BamReader *manager)
This internal function is intended to be called by each class's make_from_bam() method to read in all...
PN_uint16 get_uint16()
Extracts an unsigned 16-bit integer.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
static PN_stdfloat get_default_far()
Returns the default far plane distance that will be assigned to each newly-created lens...
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
const LVector3 & get_up_vector() const
Returns the axis perpendicular to the camera's view vector that indicates the "up" direction...
static LVector3f forward(CoordinateSystem cs=CS_default)
Returns the forward vector for the given coordinate system.
void add_stdfloat(PN_stdfloat value)
Adds either a 32-bit or a 64-bit floating-point number, according to set_stdfloat_double().
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
void set_frustum_from_corners(const LVecBase3 &ul, const LVecBase3 &ur, const LVecBase3 &ll, const LVecBase3 &lr, int flags)
Sets up the lens to use the frustum defined by the four indicated points.
void set_view_hpr(PN_stdfloat h, PN_stdfloat p, PN_stdfloat r)
Sets the direction in which the lens is facing.
virtual bool is_perspective() const
Returns true if the lens represents a perspective projection (i.e.
const LVecBase3 & get_view_hpr() const
Returns the direction in which the lens is facing.
PN_stdfloat get_min_fov() const
Returns the field of view of the narrowest dimension of the window.
LVecBase3f xform_point(const LVecBase3f &v) const
The matrix transforms a 3-component point (including translation component) and returns the result...
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
This is a 4-by-4 transform matrix.
void set_min_fov(PN_stdfloat min_fov)
Sets the field of view of the smallest dimension of the window.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
A container for geometry primitives.
bool invert_from(const LMatrix4f &other)
Computes the inverse of the other matrix, and stores the result in this matrix.
This is the base class for all two-component vectors and points.
static PN_stdfloat get_default_near()
Returns the default near plane distance that will be assigned to each newly-created lens...
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
LVecBase4f xform(const LVecBase4f &v) const
4-component vector or point times matrix.
void add_uint16(PN_uint16 value)
Adds an unsigned 16-bit integer to the datagram.
This is the base class for all three-component vectors and points.
This is a two-component vector offset.
bool has_value() const
Returns true if this variable has an explicit value, either from a prc file or locally set...
Defines a series of line strips.
void recompute_all()
Forces all internal parameters of the Lens to be recomputed.
bool extrude(const LPoint2 &point2d, LPoint3 &near_point, LPoint3 &far_point) const
Given a 2-d point in the range (-1,1) in both dimensions, where (0,0) is the center of the lens and (...
void clear_keystone()
Disables the lens keystone correction.
void set_row(int row, const LVecBase4f &v)
Replaces the indicated row of the matrix.
bool is_nan() const
Returns true if any component of the vector is not-a-number, false otherwise.
A class to retrieve the individual data elements previously stored in a Datagram. ...
TypeHandle is the identifier used to differentiate C++ class types.
bool normalize()
Normalizes the vector in place.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
void set_view_vector(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z, PN_stdfloat i, PN_stdfloat j, PN_stdfloat k)
Specifies the direction in which the lens is facing by giving an axis to look along, and a perpendicular (or at least non-parallel) up axis.
LVecBase3f get_row3(int row) const
Retrieves the row column of the matrix as a 3-component vector, ignoring the last column...
void clear_custom_film_mat()
Disables the lens custom_film_mat correction.
static LVector3f up(CoordinateSystem cs=CS_default)
Returns the up vector for the given coordinate system.
const LVector3 & get_view_vector() const
Returns the axis along which the lens is facing.
LVecBase3f xform_point_general(const LVecBase3f &v) const
The matrix transforms a 3-component point (including translation component) and returns the result...
This defines a bounding convex hexahedron.
void set_custom_film_mat(const LMatrix4 &custom_film_mat)
Specifies a custom matrix to transform the points on the film after they have been converted into nom...
const LMatrix4 & get_view_mat() const
Returns the direction in which the lens is facing.
void clear_view_mat()
Resets the lens transform to identity.