historical/toontown-classic.git/panda/include/lens.I
2024-01-16 11:20:27 -06:00

722 lines
21 KiB
Text

/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file lens.I
* @author drose
* @date 2001-11-29
*/
/**
* Given a 2-d point in the range (-1,1) in both dimensions, where (0,0) is
* the center of the lens and (-1,-1) is the lower-left corner, compute the
* corresponding vector in space that maps to this point, if such a vector can
* be determined. The vector is returned by indicating the points on the near
* plane and far plane that both map to the indicated 2-d point.
*
* Returns true if the vector is defined, or false otherwise.
*/
INLINE bool Lens::
extrude(const LPoint2 &point2d, LPoint3 &near_point, LPoint3 &far_point) const {
CDReader cdata(_cycler);
return do_extrude(cdata, LPoint3(point2d[0], point2d[1], 0.0f),
near_point, far_point);
}
/**
* Given a 2-d point in the range (-1,1) in both dimensions, where (0,0) is
* the center of the lens and (-1,-1) is the lower-left corner, compute the
* corresponding vector in space that maps to this point, if such a vector can
* be determined. The vector is returned by indicating the points on the near
* plane and far plane that both map to the indicated 2-d point.
*
* The z coordinate of the 2-d point is ignored.
*
* Returns true if the vector is defined, or false otherwise.
*/
INLINE bool Lens::
extrude(const LPoint3 &point2d, LPoint3 &near_point, LPoint3 &far_point) const {
CDReader cdata(_cycler);
return do_extrude(cdata, point2d, near_point, far_point);
}
/**
* Uses the depth component of the 3-d result from project() to compute the
* original point in 3-d space corresponding to a particular point on the
* lens. This exactly reverses project(), assuming the point does fall
* legitimately within the lens.
*/
INLINE bool Lens::
extrude_depth(const LPoint3 &point2d, LPoint3 &point3d) const {
CDReader cdata(_cycler);
return do_extrude_depth(cdata, point2d, point3d);
}
/**
* Given a 2-d point in the range (-1,1) in both dimensions, where (0,0) is
* the center of the lens and (-1,-1) is the lower-left corner, compute the
* vector that corresponds to the view direction. This will be parallel to
* the normal on the surface (the far plane) corresponding to the lens shape
* at this point.
*
* See the comment block on Lens::extrude_vec_impl() for a more in-depth
* comment on the meaning of this vector.
*
* Returns true if the vector is defined, or false otherwise.
*/
INLINE bool Lens::
extrude_vec(const LPoint2 &point2d, LVector3 &vec) const {
CDReader cdata(_cycler);
return do_extrude_vec(cdata, LPoint3(point2d[0], point2d[1], 0.0f), vec);
}
/**
* Given a 2-d point in the range (-1,1) in both dimensions, where (0,0) is
* the center of the lens and (-1,-1) is the lower-left corner, compute the
* vector that corresponds to the view direction. This will be parallel to
* the normal on the surface (the far plane) corresponding to the lens shape
* at this point.
*
* See the comment block on Lens::extrude_vec_impl() for a more in-depth
* comment on the meaning of this vector.
*
* The z coordinate of the 2-d point is ignored.
*
* Returns true if the vector is defined, or false otherwise.
*/
INLINE bool Lens::
extrude_vec(const LPoint3 &point2d, LVector3 &vec) const {
CDReader cdata(_cycler);
return do_extrude_vec(cdata, point2d, vec);
}
/**
* Given a 3-d point in space, determine the 2-d point this maps to, in the
* range (-1,1) in both dimensions, where (0,0) is the center of the lens and
* (-1,-1) is the lower-left corner.
*
* Returns true if the 3-d point is in front of the lens and within the
* viewing frustum (in which case point2d is filled in), or false otherwise
* (in which case point2d will be filled in with something, which may or may
* not be meaningful).
*/
INLINE bool Lens::
project(const LPoint3 &point3d, LPoint2 &point2d) const {
CDReader cdata(_cycler);
LPoint3 result;
bool okflag = do_project(cdata, point3d, result);
point2d.set(result[0], result[1]);
return okflag;
}
/**
* Given a 3-d point in space, determine the 2-d point this maps to, in the
* range (-1,1) in both dimensions, where (0,0) is the center of the lens and
* (-1,-1) is the lower-left corner.
*
* The z coordinate will also be set to a value in the range (-1, 1), where 1
* represents a point on the near plane, and -1 represents a point on the far
* plane.
*
* Returns true if the 3-d point is in front of the lens and within the
* viewing frustum (in which case point2d is filled in), or false otherwise
* (in which case point2d will be filled in with something, which may or may
* not be meaningful).
*/
INLINE bool Lens::
project(const LPoint3 &point3d, LPoint3 &point2d) const {
CDReader cdata(_cycler);
return do_project(cdata, point3d, point2d);
}
/**
* Sets the name of the event that will be generated whenever any properties
* of the Lens have changed. If this is not set for a particular lens, no
* event will be generated.
*
* The event is thrown with one parameter, the lens itself. This can be used
* to automatically track changes to camera fov, etc. in the application.
*/
INLINE void Lens::
set_change_event(const std::string &event) {
CDWriter cdata(_cycler, true);
cdata->_change_event = event;
}
/**
* Returns the name of the event that will be generated whenever any
* properties of this particular Lens have changed.
*/
INLINE const std::string &Lens::
get_change_event() const {
CDReader cdata(_cycler);
return cdata->_change_event;
}
/**
* Returns the coordinate system that all 3-d computations are performed
* within for this Lens. Normally, this is CS_default.
*/
INLINE CoordinateSystem Lens::
get_coordinate_system() const {
CDReader cdata(_cycler);
return cdata->_cs;
}
/**
* Sets the horizontal size of the film without changing its shape. The
* aspect ratio remains unchanged; this computes the vertical size of the film
* to automatically maintain the aspect ratio.
*/
INLINE void Lens::
set_film_size(PN_stdfloat width) {
CDWriter cdata(_cycler, true);
do_set_film_size(cdata, width);
}
/**
* Sets the size and shape of the "film" within the lens. This both
* establishes the units used by calls like set_focal_length(), and
* establishes the aspect ratio of the frame.
*
* In a physical camera, the field of view of a lens is determined by the
* lens' focal length and by the size of the film area exposed by the lens.
* For instance, a 35mm camera exposes a rectangle on the film about 24mm x
* 36mm, which means a 50mm lens gives about a 40-degree horizontal field of
* view.
*
* In the virtual camera, you may set the film size to any units here, and
* specify a focal length in the same units to simulate the same effect. Or,
* you may ignore this parameter, and specify the field of view and aspect
* ratio of the lens directly.
*/
INLINE void Lens::
set_film_size(PN_stdfloat width, PN_stdfloat height) {
set_film_size(LVecBase2(width, height));
}
/**
* Sets the size and shape of the "film" within the lens. This both
* establishes the units used by calls like set_focal_length(), and
* establishes the aspect ratio of the frame.
*
* In a physical camera, the field of view of a lens is determined by the
* lens' focal length and by the size of the film area exposed by the lens.
* For instance, a 35mm camera exposes a rectangle on the film about 24mm x
* 36mm, which means a 50mm lens gives about a 40-degree horizontal field of
* view.
*
* In the virtual camera, you may set the film size to any units here, and
* specify a focal length in the same units to simulate the same effect. Or,
* you may ignore this parameter, and specify the field of view and aspect
* ratio of the lens directly.
*/
INLINE void Lens::
set_film_size(const LVecBase2 &film_size) {
CDWriter cdata(_cycler, true);
do_set_film_size(cdata, film_size);
}
/**
* Returns the horizontal and vertical film size of the virtual film. See
* set_film_size().
*/
INLINE const LVecBase2 &Lens::
get_film_size() const {
CDReader cdata(_cycler);
return do_get_film_size(cdata);
}
/**
* Sets the horizontal and vertical offset amounts of this Lens. These are
* both in the same units specified in set_film_size().
*
* This can be used to establish an off-axis lens.
*/
INLINE void Lens::
set_film_offset(PN_stdfloat x, PN_stdfloat y) {
set_film_offset(LVecBase2(x, y));
}
/**
* Sets the horizontal and vertical offset amounts of this Lens. These are
* both in the same units specified in set_film_size().
*
* This can be used to establish an off-axis lens.
*/
INLINE void Lens::
set_film_offset(const LVecBase2 &film_offset) {
CDWriter cdata(_cycler, true);
do_set_film_offset(cdata, film_offset);
}
/**
* Returns the horizontal and vertical offset amounts of this Lens. See
* set_film_offset().
*/
INLINE const LVector2 &Lens::
get_film_offset() const {
CDReader cdata(_cycler);
return do_get_film_offset(cdata);
}
/**
* Sets the focal length of the lens. This may adjust the field-of-view
* correspondingly, and is an alternate way to specify field of view.
*
* For certain kinds of lenses (e.g. OrthographicLens), the focal length has
* no meaning.
*/
INLINE void Lens::
set_focal_length(PN_stdfloat focal_length) {
CDWriter cdata(_cycler, true);
do_set_focal_length(cdata, focal_length);
}
/**
* Returns the focal length of the lens. This may have been set explicitly by
* a previous call to set_focal_length(), or it may be computed based on the
* lens' fov and film_size. For certain kinds of lenses, the focal length has
* no meaning.
*/
INLINE PN_stdfloat Lens::
get_focal_length() const {
CDReader cdata(_cycler);
return do_get_focal_length(cdata);
}
/**
* Sets the horizontal field of view of the lens without changing the aspect
* ratio. The vertical field of view is adjusted to maintain the same aspect
* ratio.
*/
INLINE void Lens::
set_fov(PN_stdfloat hfov) {
CDWriter cdata(_cycler, true);
do_set_fov(cdata, hfov);
}
/**
* Sets the field of view of the lens in both dimensions. This establishes
* both the field of view and the aspect ratio of the lens. This is one way
* to specify the field of view of a lens; set_focal_length() is another way.
*
* For certain kinds of lenses (like OrthoLens), the field of view has no
* meaning.
*/
INLINE void Lens::
set_fov(PN_stdfloat hfov, PN_stdfloat vfov) {
set_fov(LVecBase2(hfov, vfov));
}
/**
* Sets the field of view of the lens in both dimensions. This establishes
* both the field of view and the aspect ratio of the lens. This is one way
* to specify the field of view of a lens; set_focal_length() is another way.
*
* For certain kinds of lenses (like OrthographicLens), the field of view has
* no meaning.
*/
INLINE void Lens::
set_fov(const LVecBase2 &fov) {
CDWriter cdata(_cycler, true);
do_set_fov(cdata, fov);
}
/**
* Returns the horizontal and vertical film size of the virtual film. See
* set_fov().
*/
INLINE const LVecBase2 &Lens::
get_fov() const {
CDReader cdata(_cycler);
return do_get_fov(cdata);
}
/**
* Returns the horizontal component of fov only. See get_fov().
*/
INLINE PN_stdfloat Lens::
get_hfov() const {
return get_fov()[0];
}
/**
* Returns the vertical component of fov only. See get_fov().
*/
INLINE PN_stdfloat Lens::
get_vfov() const {
return get_fov()[1];
}
/**
* Sets the aspect ratio of the lens. This is the ratio of the height to the
* width of the generated image. Setting this overrides the two-parameter fov
* or film size setting.
*/
INLINE void Lens::
set_aspect_ratio(PN_stdfloat aspect_ratio) {
CDWriter cdata(_cycler, true);
do_set_aspect_ratio(cdata, aspect_ratio);
}
/**
* Returns the aspect ratio of the Lens. This is determined based on the
* indicated film size; see set_film_size().
*/
INLINE PN_stdfloat Lens::
get_aspect_ratio() const {
CDReader cdata(_cycler);
return do_get_aspect_ratio(cdata);
}
/**
* Defines the position of the near plane (or cylinder, sphere, whatever).
* Points closer to the lens than this may not be rendered.
*/
INLINE void Lens::
set_near(PN_stdfloat near_distance) {
CDWriter cdata(_cycler, true);
do_set_near(cdata, near_distance);
}
/**
* Returns the position of the near plane (or cylinder, sphere, whatever).
*/
INLINE PN_stdfloat Lens::
get_near() const {
CDReader cdata(_cycler);
return do_get_near(cdata);
}
/**
* Defines the position of the far plane (or cylinder, sphere, whatever).
* Points farther from the lens than this may not be rendered.
*/
INLINE void Lens::
set_far(PN_stdfloat far_distance) {
CDWriter cdata(_cycler, true);
do_set_far(cdata, far_distance);
}
/**
* Returns the position of the far plane (or cylinder, sphere, whatever).
*/
INLINE PN_stdfloat Lens::
get_far() const {
CDReader cdata(_cycler);
return do_get_far(cdata);
}
/**
* Simultaneously changes the near and far planes.
*/
INLINE void Lens::
set_near_far(PN_stdfloat near_distance, PN_stdfloat far_distance) {
CDWriter cdata(_cycler, true);
do_set_near_far(cdata, near_distance, far_distance);
}
/**
* Sets the direction in which the lens is facing. Normally, this is down the
* forward axis (usually the Y axis), but it may be rotated. This is only one
* way of specifying the rotation; you may also specify an explicit vector in
* which to look, or you may give a complete transformation matrix.
*/
INLINE void Lens::
set_view_hpr(PN_stdfloat h, PN_stdfloat p, PN_stdfloat r) {
set_view_hpr(LVecBase3(h, p, r));
}
/**
* 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.
*
* See also set_view_hpr().
*/
INLINE void Lens::
set_view_vector(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z, PN_stdfloat i, PN_stdfloat j, PN_stdfloat k) {
set_view_vector(LVector3(x, y, z), LVector3(i, j, k));
}
/**
* Sets the distance between the left and right eyes of a stereo camera. This
* distance is used to apply a stereo effect when the lens is rendered on a
* stereo display region. It only has an effect on a PerspectiveLens.
*
* The left eye and the right eye are each offset along the X axis by half of
* this distance, so that this parameter specifies the total distance between
* them.
*
* Also see set_convergence_distance(), which relates.
*/
INLINE void Lens::
set_interocular_distance(PN_stdfloat interocular_distance) {
CDWriter cdata(_cycler, true);
do_set_interocular_distance(cdata, interocular_distance);
do_throw_change_event(cdata);
}
/**
* See set_interocular_distance().
*/
INLINE PN_stdfloat Lens::
get_interocular_distance() const {
CDReader cdata(_cycler);
return cdata->_interocular_distance;
}
/**
* Sets the distance between between the camera plane and the point in the
* distance that the left and right eyes are both looking at. This distance
* is used to apply a stereo effect when the lens is rendered on a stereo
* display region. It only has an effect on a PerspectiveLens.
*
* This parameter must be greater than 0, but may be as large as you like. It
* controls the distance at which the two stereo images will appear to
* converge, which is a normal property of stereo vision. Normally this
* should be set to the distance from the camera to the area of interest in
* your scene. Anything beyond this distance will appear to go into the
* screen, and anything closer will appear to come out of the screen. If you
* want to simulate parallel stereo, set this to infinity.
*
* Note that this creates an off-axis frustum, which means that the lenses are
* still pointing in the same direction, which is usually more desirable than
* the more naive toe-in approach, where the two lenses are simply tilted
* toward each other.
*
* Prior to Panda3D 1.9.0, the convergence was being calculated incorrectly.
* It has since been corrected. To restore the legacy behavior you can set
* the stereo-lens-old-convergence variable to true.
*
* Also see set_interocular_distance(), which relates.
*/
INLINE void Lens::
set_convergence_distance(PN_stdfloat convergence_distance) {
CDWriter cdata(_cycler, true);
do_set_convergence_distance(cdata, convergence_distance);
do_throw_change_event(cdata);
}
/**
* See set_convergence_distance().
*/
INLINE PN_stdfloat Lens::
get_convergence_distance() const {
CDReader cdata(_cycler);
return cdata->_convergence_distance;
}
/**
* Sets an arbitrary transformation on the lens. This replaces the individual
* transformation components like set_view_hpr().
*
* Setting a transformation here will have a slightly different effect than
* putting one on the LensNode that contains this lens. In particular,
* lighting and other effects computations will still be performed on the lens
* in its untransformed (facing forward) position, but the actual projection
* matrix will be transformed by this matrix.
*/
INLINE void Lens::
set_view_mat(const LMatrix4 &view_mat) {
CDWriter cdata(_cycler, true);
do_set_view_mat(cdata, view_mat);
}
/**
* Returns the direction in which the lens is facing.
*/
INLINE const LMatrix4 &Lens::
get_view_mat() const {
CDReader cdata(_cycler);
return do_get_view_mat(cdata);
}
/**
* Returns the keystone correction specified for the lens.
*/
INLINE const LVecBase2 &Lens::
get_keystone() const {
CDReader cdata(_cycler);
return cdata->_keystone;
}
/**
* Returns the custom_film_mat specified for the lens.
*/
INLINE const LMatrix4 &Lens::
get_custom_film_mat() const {
CDReader cdata(_cycler);
return cdata->_custom_film_mat;
}
/**
* Returns the complete transformation matrix from a 3-d point in space to a
* point on the film, if such a matrix exists, or the identity matrix if the
* lens is nonlinear.
*/
INLINE const LMatrix4 &Lens::
get_projection_mat(StereoChannel channel) const {
CDReader cdata(_cycler);
return do_get_projection_mat(cdata, channel);
}
/**
* Returns the matrix that transforms from a 2-d point on the film to a 3-d
* vector in space, if such a matrix exists.
*/
INLINE const LMatrix4 &Lens::
get_projection_mat_inv(StereoChannel stereo_channel) const {
CDReader cdata(_cycler);
return do_get_projection_mat_inv(cdata, stereo_channel);
}
/**
* Returns the matrix that transforms from a point behind the lens to a point
* on the film.
*/
INLINE const LMatrix4 &Lens::
get_film_mat() const {
CDReader cdata(_cycler);
return do_get_film_mat(cdata);
}
/**
* Returns the matrix that transforms from a point on the film to a point
* behind the lens.
*/
INLINE const LMatrix4 &Lens::
get_film_mat_inv() const {
CDReader cdata(_cycler);
return do_get_film_mat_inv(cdata);
}
/**
* Returns the matrix that transforms from a point in front of the lens to a
* point in space.
*/
INLINE const LMatrix4 &Lens::
get_lens_mat() const {
CDReader cdata(_cycler);
return do_get_lens_mat(cdata);
}
/**
* Returns the matrix that transforms from a point in space to a point in
* front of the lens.
*/
INLINE const LMatrix4 &Lens::
get_lens_mat_inv() const {
CDReader cdata(_cycler);
return do_get_lens_mat_inv(cdata);
}
/**
* Returns the UpdateSeq that is incremented whenever the lens properties are
* changed. As long as this number remains the same, you may assume the lens
* properties are unchanged.
*/
INLINE UpdateSeq Lens::
get_last_change() const {
CDReader cdata(_cycler);
return cdata->_last_change;
}
/**
* Clears from _user_flags the bits in the first parameter, and sets the bits
* in the second parameter.
*/
INLINE void Lens::
do_adjust_user_flags(CData *cdata, int clear_flags, int set_flags) {
cdata->_user_flags = (cdata->_user_flags & ~clear_flags) | (short)set_flags;
}
/**
* Clears from _comp_flags the bits in the first parameter, and sets the bits
* in the second parameter.
*/
INLINE void Lens::
do_adjust_comp_flags(CData *cdata, int clear_flags, int set_flags) {
cdata->_comp_flags = (cdata->_comp_flags & ~clear_flags) | (short)set_flags;
}
/**
*
*/
INLINE void Lens::
do_set_film_offset(CData *cdata, const LVecBase2 &film_offset) {
cdata->_film_offset = film_offset;
do_adjust_comp_flags(cdata, CF_mat, 0);
do_throw_change_event(cdata);
}
/**
*
*/
INLINE const LVector2 &Lens::
do_get_film_offset(const CData *cdata) const {
return cdata->_film_offset;
}
/**
*
*/
INLINE void Lens::
do_set_near(CData *cdata, PN_stdfloat near_distance) {
if (near_distance != cdata->_near_distance) {
cdata->_near_distance = near_distance;
do_adjust_comp_flags(cdata, CF_projection_mat | CF_projection_mat_inv, 0);
do_throw_change_event(cdata);
}
}
/**
*
*/
INLINE PN_stdfloat Lens::
do_get_near(const CData *cdata) const {
return cdata->_near_distance;
}
/**
*
*/
INLINE void Lens::
do_set_far(CData *cdata, PN_stdfloat far_distance) {
if (far_distance != cdata->_far_distance) {
cdata->_far_distance = far_distance;
do_adjust_comp_flags(cdata, CF_projection_mat | CF_projection_mat_inv, 0);
do_throw_change_event(cdata);
}
}
/**
*
*/
INLINE PN_stdfloat Lens::
do_get_far(const CData *cdata) const {
return cdata->_far_distance;
}
/**
*
*/
INLINE void Lens::
do_set_near_far(CData *cdata, PN_stdfloat near_distance, PN_stdfloat far_distance) {
if (near_distance != cdata->_near_distance || far_distance != cdata->_far_distance) {
cdata->_near_distance = near_distance;
cdata->_far_distance = far_distance;
do_adjust_comp_flags(cdata, CF_projection_mat | CF_projection_mat_inv, 0);
do_throw_change_event(cdata);
}
}
INLINE std::ostream &
operator << (std::ostream &out, const Lens &lens) {
lens.output(out);
return out;
}