diff --git a/panda/src/distort/cylindricalLens.cxx b/panda/src/distort/cylindricalLens.cxx index 08460b1a44..e0143c8110 100644 --- a/panda/src/distort/cylindricalLens.cxx +++ b/panda/src/distort/cylindricalLens.cxx @@ -69,9 +69,10 @@ do_extrude(const Lens::CData *lens_cdata, // And we'll need to account for the lens's rotations, etc. at the // end of the day. const LMatrix4 &lens_mat = do_get_lens_mat(lens_cdata); + const LMatrix4 &proj_inv_mat = do_get_projection_mat_inv(lens_cdata); - near_point = (v * do_get_near(lens_cdata)) * lens_mat; - far_point = (v * do_get_far(lens_cdata)) * lens_mat; + near_point = (v * do_get_near(lens_cdata)) * proj_inv_mat * lens_mat; + far_point = (v * do_get_far(lens_cdata)) * proj_inv_mat * lens_mat; return true; } @@ -106,7 +107,7 @@ do_extrude_vec(const Lens::CData *lens_cdata, const LPoint3 &point2d, LVector3 & PN_stdfloat sinAngle, cosAngle; csincos(deg_2_rad(angle), &sinAngle, &cosAngle); - vec = LVector3(sinAngle, cosAngle, 0.0f) * do_get_lens_mat(lens_cdata); + vec = LVector3(sinAngle, cosAngle, 0.0f) * do_get_projection_mat_inv(lens_cdata) * do_get_lens_mat(lens_cdata); return true; } @@ -131,7 +132,7 @@ do_extrude_vec(const Lens::CData *lens_cdata, const LPoint3 &point2d, LVector3 & bool CylindricalLens:: do_project(const Lens::CData *lens_cdata, const LPoint3 &point3d, LPoint3 &point2d) const { // First, account for any rotations, etc. on the lens. - LPoint3 p = point3d * do_get_lens_mat_inv(lens_cdata); + LPoint3 p = point3d * do_get_lens_mat_inv(lens_cdata) * do_get_projection_mat(lens_cdata); // To compute the x position on the frame, we only need to consider // the angle of the vector about the Z axis. Project the vector diff --git a/panda/src/distort/fisheyeLens.cxx b/panda/src/distort/fisheyeLens.cxx index 46122246d0..6ba58911d3 100644 --- a/panda/src/distort/fisheyeLens.cxx +++ b/panda/src/distort/fisheyeLens.cxx @@ -101,9 +101,10 @@ do_extrude(const Lens::CData *lens_cdata, // And we'll need to account for the lens's rotations, etc. at the // end of the day. const LMatrix4 &lens_mat = do_get_lens_mat(lens_cdata); + const LMatrix4 &proj_inv_mat = do_get_projection_mat_inv(lens_cdata); - near_point = (v * do_get_near(lens_cdata)) * lens_mat; - far_point = (v * do_get_far(lens_cdata)) * lens_mat; + near_point = (v * do_get_near(lens_cdata)) * proj_inv_mat * lens_mat; + far_point = (v * do_get_far(lens_cdata)) * proj_inv_mat * lens_mat; return true; } @@ -159,7 +160,7 @@ do_extrude_vec(const Lens::CData *lens_cdata, const LPoint3 &point2d, LVector3 & bool FisheyeLens:: do_project(const Lens::CData *lens_cdata, const LPoint3 &point3d, LPoint3 &point2d) const { // First, account for any rotations, etc. on the lens. - LVector3 v2 = point3d * do_get_lens_mat_inv(lens_cdata); + LVector3 v2 = point3d * do_get_lens_mat_inv(lens_cdata) * do_get_projection_mat(lens_cdata); // A fisheye lens projection has the property that the distance from // the center point to any other point on the projection is diff --git a/panda/src/distort/oSphereLens.cxx b/panda/src/distort/oSphereLens.cxx index 8672766725..fc8bfbb46b 100755 --- a/panda/src/distort/oSphereLens.cxx +++ b/panda/src/distort/oSphereLens.cxx @@ -74,9 +74,10 @@ do_extrude(const Lens::CData *lens_cdata, // And we'll need to account for the lens's rotations, etc. at the // end of the day. const LMatrix4 &lens_mat = do_get_lens_mat(lens_cdata); + const LMatrix4 &proj_inv_mat = do_get_projection_mat_inv(lens_cdata); - near_point = near_point * lens_mat; - far_point = far_point * lens_mat; + near_point = near_point * proj_inv_mat * lens_mat; + far_point = far_point * proj_inv_mat * lens_mat; return true; } @@ -100,7 +101,7 @@ do_extrude(const Lens::CData *lens_cdata, bool OSphereLens:: do_project(const Lens::CData *lens_cdata, const LPoint3 &point3d, LPoint3 &point2d) const { // First, account for any rotations, etc. on the lens. - LPoint3 p = point3d * do_get_lens_mat_inv(lens_cdata); + LPoint3 p = point3d * do_get_lens_mat_inv(lens_cdata) * do_get_projection_mat(lens_cdata); PN_stdfloat dist = p.length(); if (dist == 0.0f) { point2d.set(0.0f, 0.0f, 0.0f); diff --git a/panda/src/distort/pSphereLens.cxx b/panda/src/distort/pSphereLens.cxx index 5e0159a1f7..946a8556f5 100644 --- a/panda/src/distort/pSphereLens.cxx +++ b/panda/src/distort/pSphereLens.cxx @@ -67,9 +67,10 @@ do_extrude(const Lens::CData *lens_cdata, // And we'll need to account for the lens's rotations, etc. at the // end of the day. const LMatrix4 &lens_mat = do_get_lens_mat(lens_cdata); + const LMatrix4 &proj_inv_mat = do_get_projection_mat_inv(lens_cdata); - near_point = (v * do_get_near(lens_cdata)) * lens_mat; - far_point = (v * do_get_far(lens_cdata)) * lens_mat; + near_point = (v * do_get_near(lens_cdata)) * proj_inv_mat * lens_mat; + far_point = (v * do_get_far(lens_cdata)) * proj_inv_mat * lens_mat; return true; } @@ -93,7 +94,7 @@ do_extrude(const Lens::CData *lens_cdata, bool PSphereLens:: do_project(const Lens::CData *lens_cdata, const LPoint3 &point3d, LPoint3 &point2d) const { // First, account for any rotations, etc. on the lens. - LVector3 v3 = point3d * do_get_lens_mat_inv(lens_cdata); + LVector3 v3 = point3d * do_get_lens_mat_inv(lens_cdata) * do_get_projection_mat(lens_cdata); PN_stdfloat dist = v3.length(); if (dist == 0.0f) { point2d.set(0.0f, 0.0f, 0.0f); diff --git a/panda/src/gobj/lens.cxx b/panda/src/gobj/lens.cxx index 92ed798076..f430d18f1c 100644 --- a/panda/src/gobj/lens.cxx +++ b/panda/src/gobj/lens.cxx @@ -1527,16 +1527,29 @@ do_compute_view_vector(CData *cdata) { // point to 2-d point, if the lens is linear. //////////////////////////////////////////////////////////////////// void Lens:: -do_compute_projection_mat(CData *cdata) { - cdata->_projection_mat = - cdata->_projection_mat_left = - cdata->_projection_mat_right = - cdata->_projection_mat_inv = - cdata->_projection_mat_left_inv = - cdata->_projection_mat_right_inv = - LMatrix4::ident_mat(); - do_adjust_comp_flags(cdata, 0, CF_projection_mat | CF_projection_mat_inv | - CF_projection_mat_left_inv |CF_projection_mat_right_inv); +do_compute_projection_mat(CData *lens_cdata) { + // This is the implementation used by non-linear lenses. The linear + // lenses (PerspectiveLens and OrthographicLens) will customize this + // method appropriate for themselves. + + // By convention, the coordinate-system conversion is baked into the + // projection mat. Our non-linear lenses are implemented with code + // that assumes CS_zup_right, so we bake the appropriate rotation in + // here. + CoordinateSystem cs = lens_cdata->_cs; + if (cs == CS_default) { + cs = get_default_coordinate_system(); + } + lens_cdata->_projection_mat = LMatrix4::convert_mat(cs, CS_zup_right); + lens_cdata->_projection_mat_inv = LMatrix4::convert_mat(CS_zup_right, cs); + + // We don't apply any left/right offsets for non-linear lenses by + // default, at least not here in the projection matrix. + lens_cdata->_projection_mat_left = lens_cdata->_projection_mat_right = lens_cdata->_projection_mat; + lens_cdata->_projection_mat_left_inv = lens_cdata->_projection_mat_right_inv = lens_cdata->_projection_mat_inv; + + do_adjust_comp_flags(lens_cdata, 0, CF_projection_mat | CF_projection_mat_inv | + CF_projection_mat_left_inv | CF_projection_mat_right_inv); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/grutil/pfmFile.cxx b/panda/src/grutil/pfmFile.cxx index 8005bfc80b..63e13bc2b5 100755 --- a/panda/src/grutil/pfmFile.cxx +++ b/panda/src/grutil/pfmFile.cxx @@ -726,12 +726,45 @@ compute_planar_bounds(const LPoint2 ¢er, PN_stdfloat point_dist, PN_stdfloat } } } - - PT(BoundingHexahedron) bounds = new BoundingHexahedron - (LPoint3(min_x, min_y, min_z), LPoint3(max_x, min_y, min_z), - LPoint3(min_x, min_y, max_z), LPoint3(max_x, min_y, max_z), - LPoint3(min_x, max_y, min_z), LPoint3(max_x, max_y, min_z), - LPoint3(min_x, max_y, max_z), LPoint3(max_x, max_y, max_z)); + + PT(BoundingHexahedron) bounds; + + // We create a BoundingHexahedron with the points in a particular + // well-defined order, based on the current coordinate system. + CoordinateSystem cs = get_default_coordinate_system(); + switch (cs) { + case CS_yup_right: + bounds = new BoundingHexahedron + (LPoint3(min_x, min_y, min_z), LPoint3(max_x, min_y, min_z), + LPoint3(min_x, max_y, min_z), LPoint3(max_x, max_y, min_z), + LPoint3(min_x, min_y, max_z), LPoint3(max_x, min_y, max_z), + LPoint3(min_x, max_y, max_z), LPoint3(max_x, max_y, max_z)); + break; + + case CS_zup_right: + bounds = new BoundingHexahedron + (LPoint3(min_x, min_y, min_z), LPoint3(max_x, min_y, min_z), + LPoint3(min_x, min_y, max_z), LPoint3(max_x, min_y, max_z), + LPoint3(min_x, max_y, min_z), LPoint3(max_x, max_y, min_z), + LPoint3(min_x, max_y, max_z), LPoint3(max_x, max_y, max_z)); + break; + + case CS_yup_left: + bounds = new BoundingHexahedron + (LPoint3(max_x, min_y, max_z), LPoint3(min_x, min_y, max_z), + LPoint3(max_x, max_y, max_z), LPoint3(min_x, max_y, max_z), + LPoint3(max_x, min_y, min_z), LPoint3(min_x, min_y, min_z), + LPoint3(max_x, max_y, min_z), LPoint3(min_x, max_y, min_z)); + break; + + case CS_zup_left: + bounds = new BoundingHexahedron + (LPoint3(max_x, max_y, min_z), LPoint3(min_x, max_y, min_z), + LPoint3(max_x, max_y, max_z), LPoint3(min_x, max_y, max_z), + LPoint3(max_x, min_y, min_z), LPoint3(min_x, min_y, min_z), + LPoint3(max_x, min_y, max_z), LPoint3(min_x, min_y, max_z)); + break; + } // Rotate the bounding volume back into the original space of the // screen. @@ -885,6 +918,12 @@ make_vis_mesh_geom(GeomNode *gnode, bool inverted) const { return; } + bool reverse_normals = inverted; + bool reverse_faces = inverted; + if (!is_right_handed(get_default_coordinate_system())) { + reverse_faces = !reverse_faces; + } + // This is the max number of vertex indices we might add to the // GeomTriangles. (We might actually add fewer than this due to // omitting the occasional missing data point.) @@ -1025,7 +1064,7 @@ make_vis_mesh_geom(GeomNode *gnode, bool inverted) const { } n.normalize(); nassertv(!n.is_nan()); - if (inverted) { + if (reverse_normals) { n = -n; } normal.add_data3(n); @@ -1062,7 +1101,7 @@ make_vis_mesh_geom(GeomNode *gnode, bool inverted) const { int vi2 = ((xi0 + 1) + (yi0 + 1) * x_size); int vi3 = ((xi0 + 1) + (yi0) * x_size); - if (inverted) { + if (reverse_faces) { tris->add_vertices(vi2, vi0, vi1); tris->close_primitive(); diff --git a/panda/src/linmath/lquaternion_src.cxx b/panda/src/linmath/lquaternion_src.cxx index dcc869fb19..78edbc05d1 100644 --- a/panda/src/linmath/lquaternion_src.cxx +++ b/panda/src/linmath/lquaternion_src.cxx @@ -102,7 +102,11 @@ set_hpr(const FLOATNAME(LVecBase3) &hpr, CoordinateSystem cs) { csincos(a, &s, &c); quat_r.set(c, v[0] * s, v[1] * s, v[2] * s); - (*this) = quat_r * quat_p * quat_h; + if (is_right_handed(cs)) { + (*this) = quat_r * quat_p * quat_h; + } else { + (*this) = invert(quat_h * quat_p * quat_r); + } if (!temp_hpr_fix) { // Compute the old, broken hpr. diff --git a/panda/src/linmath/lvector3_src.I b/panda/src/linmath/lvector3_src.I index 00d72c4e71..bf4dbcc067 100644 --- a/panda/src/linmath/lvector3_src.I +++ b/panda/src/linmath/lvector3_src.I @@ -474,6 +474,7 @@ rfu(FLOATTYPE right_v, FLOATTYPE fwd_v, FLOATTYPE up_v, case CS_zup_left: vy = -fwd_v; vz = up_v; + break; default: linmath_cat.error()