From 1f3109c18a69c17d4789c82673fd9a8f6d59fd37 Mon Sep 17 00:00:00 2001 From: David Rose Date: Wed, 12 Dec 2001 22:11:37 +0000 Subject: [PATCH] add PSphereLens --- panda/src/distort/Sources.pp | 1 + panda/src/distort/config_distort.cxx | 2 + panda/src/distort/pSphereLens.I | 46 +++++++ panda/src/distort/pSphereLens.cxx | 180 +++++++++++++++++++++++++++ panda/src/distort/pSphereLens.h | 82 ++++++++++++ 5 files changed, 311 insertions(+) create mode 100644 panda/src/distort/pSphereLens.I create mode 100644 panda/src/distort/pSphereLens.cxx create mode 100644 panda/src/distort/pSphereLens.h diff --git a/panda/src/distort/Sources.pp b/panda/src/distort/Sources.pp index 2a1417f8fd..59572a2227 100644 --- a/panda/src/distort/Sources.pp +++ b/panda/src/distort/Sources.pp @@ -10,6 +10,7 @@ config_distort.cxx config_distort.h \ cylindricalLens.cxx cylindricalLens.h cylindricalLens.I \ fisheyeLens.cxx fisheyeLens.h fisheyeLens.I \ + pSphereLens.cxx pSphereLens.h pSphereLens.I \ projectionScreen.cxx projectionScreen.h projectionScreen.I #define INSTALL_HEADERS diff --git a/panda/src/distort/config_distort.cxx b/panda/src/distort/config_distort.cxx index 3a09eab184..b718c2fd0d 100644 --- a/panda/src/distort/config_distort.cxx +++ b/panda/src/distort/config_distort.cxx @@ -19,6 +19,7 @@ #include "config_distort.h" #include "cylindricalLens.h" #include "fisheyeLens.h" +#include "pSphereLens.h" #include "projectionScreen.h" #include "dconfig.h" @@ -48,5 +49,6 @@ init_libdistort() { CylindricalLens::init_type(); FisheyeLens::init_type(); + PSphereLens::init_type(); ProjectionScreen::init_type(); } diff --git a/panda/src/distort/pSphereLens.I b/panda/src/distort/pSphereLens.I new file mode 100644 index 0000000000..b5f622c489 --- /dev/null +++ b/panda/src/distort/pSphereLens.I @@ -0,0 +1,46 @@ +// Filename: pSphereLens.I +// Created by: drose (12Dec01) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////// +// Function: PSphereLens::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE PSphereLens:: +PSphereLens() { +} + +//////////////////////////////////////////////////////////////////// +// Function: PSphereLens::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE PSphereLens:: +PSphereLens(const PSphereLens ©) : Lens(copy) { +} + +//////////////////////////////////////////////////////////////////// +// Function: PSphereLens::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void PSphereLens:: +operator = (const PSphereLens ©) { + Lens::operator = (copy); +} + diff --git a/panda/src/distort/pSphereLens.cxx b/panda/src/distort/pSphereLens.cxx new file mode 100644 index 0000000000..a6e119e06d --- /dev/null +++ b/panda/src/distort/pSphereLens.cxx @@ -0,0 +1,180 @@ +// Filename: pSphereLens.cxx +// Created by: drose (12Dec01) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "pSphereLens.h" +#include "deg_2_rad.h" + +TypeHandle PSphereLens::_type_handle; + +// This is the focal-length constant for fisheye lenses. See +// fisheyeLens.cxx. +static const float k = 60.0f; +// focal_length = film_size * k / fov; + + +//////////////////////////////////////////////////////////////////// +// Function: PSphereLens::make_copy +// Access: Public, Virtual +// Description: Allocates a new Lens just like this one. +//////////////////////////////////////////////////////////////////// +PT(Lens) PSphereLens:: +make_copy() const { + return new PSphereLens(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: PSphereLens::extrude_impl +// Access: Protected, Virtual +// Description: 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. +//////////////////////////////////////////////////////////////////// +bool PSphereLens:: +extrude_impl(const LPoint3f &point2d, LPoint3f &near_point, LPoint3f &far_point) const { + // Undo the shifting from film offsets, etc. This puts the point + // into the range [-film_size/2, film_size/2] in x and y. + LPoint3f f = point2d * get_film_mat_inv(); + + float focal_length = get_focal_length(); + + // Rotate the forward vector through the rotation angles + // corresponding to this point. + LPoint3f v = LPoint3f(0.0f, 1.0f, 0.0f) * + LMatrix3f::rotate_mat(f[1] * k / focal_length, LVector3f(1.0f, 0.0f, 0.0f)) * + LMatrix3f::rotate_mat(f[0] * k / focal_length, LVector3f(0.0f, 0.0f, -1.0f)); + + // And we'll need to account for the lens's rotations, etc. at the + // end of the day. + const LMatrix4f &lens_mat = get_lens_mat(); + + near_point = (v * get_near()) * lens_mat; + far_point = (v * get_far()) * lens_mat; + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: PSphereLens::project_impl +// Access: Protected, Virtual +// Description: 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. +// +// Some lens types also set the z coordinate of the 2-d +// point 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. +//////////////////////////////////////////////////////////////////// +bool PSphereLens:: +project_impl(const LPoint3f &point3d, LPoint3f &point2d) const { + // First, account for any rotations, etc. on the lens. + LVector3f v3 = point3d * get_lens_mat_inv(); + float dist = v3.length(); + if (dist == 0.0f) { + point2d.set(0.0f, 0.0f, 0.0f); + return false; + } + + v3 /= dist; + + float focal_length = get_focal_length(); + + // 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 + // into the XY plane to do this. + LVector2f xy(v3[0], v3[1]); + + // Unroll the Z angle, and the y position is the angle about the X + // axis. + xy.normalize(); + LVector2d yz(v3[0]*xy[0] + v3[1]*xy[1], v3[2]); + + point2d.set + ( + // The x position is the angle about the Z axis. + rad_2_deg(catan2(xy[0], xy[1])) * focal_length / k, + // The y position is the angle about the X axis. + rad_2_deg(catan2(yz[1], yz[0])) * focal_length / k, + // Z is the distance scaled into the range (1, -1). + (get_near() - dist) / (get_far() - get_near()) + ); + + // Now we have to transform the point according to the film + // adjustments. + point2d = point2d * get_film_mat(); + + return + point2d[0] >= -1.0f && point2d[0] <= 1.0f && + point2d[1] >= -1.0f && point2d[1] <= 1.0f; +} + +//////////////////////////////////////////////////////////////////// +// Function: PSphereLens::fov_to_film +// Access: Protected, Virtual +// Description: Given a field of view in degrees and a focal length, +// compute the correspdonding width (or height) on the +// film. If horiz is true, this is in the horizontal +// direction; otherwise, it is in the vertical direction +// (some lenses behave differently in each direction). +//////////////////////////////////////////////////////////////////// +float PSphereLens:: +fov_to_film(float fov, float focal_length, bool) const { + return focal_length * fov / k; +} + +//////////////////////////////////////////////////////////////////// +// Function: PSphereLens::fov_to_focal_length +// Access: Protected, Virtual +// Description: Given a field of view in degrees and a width (or +// height) on the film, compute the focal length of the +// lens. If horiz is true, this is in the horizontal +// direction; otherwise, it is in the vertical direction +// (some lenses behave differently in each direction). +//////////////////////////////////////////////////////////////////// +float PSphereLens:: +fov_to_focal_length(float fov, float film_size, bool) const { + return film_size * k / fov; +} + +//////////////////////////////////////////////////////////////////// +// Function: PSphereLens::film_to_fov +// Access: Protected, Virtual +// Description: Given a width (or height) on the film and a focal +// length, compute the field of view in degrees. If +// horiz is true, this is in the horizontal direction; +// otherwise, it is in the vertical direction (some +// lenses behave differently in each direction). +//////////////////////////////////////////////////////////////////// +float PSphereLens:: +film_to_fov(float film_size, float focal_length, bool) const { + return film_size * k / focal_length; +} diff --git a/panda/src/distort/pSphereLens.h b/panda/src/distort/pSphereLens.h new file mode 100644 index 0000000000..5185e0686d --- /dev/null +++ b/panda/src/distort/pSphereLens.h @@ -0,0 +1,82 @@ +// Filename: pSphereLens.h +// Created by: drose (12Dec01) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#ifndef PSPHERELENS_H +#define PSPHERELENS_H + +#include "pandabase.h" + +#include "lens.h" + +//////////////////////////////////////////////////////////////////// +// Class : PSphereLens +// Description : A PSphereLens is a special nonlinear lens that +// doesn't correspond to any real physical lenses. It's +// primarily useful for generating 360-degree wraparound +// images while avoiding the distortion associated with +// fisheye images. +// +// A PSphereLens is similar to a cylindrical lens, +// except it is also curved in the vertical direction. +// This allows it to extend to both poles in the +// vertical direction. The mapping is similar to what +// many modeling packages call a sphere mapping: the x +// coordinate is proportional to azimuth, while the y +// coordinate is proportional to altitude. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDAFX PSphereLens : public Lens { +PUBLISHED: + INLINE PSphereLens(); + +public: + INLINE PSphereLens(const PSphereLens ©); + INLINE void operator = (const PSphereLens ©); + +public: + virtual PT(Lens) make_copy() const; + +protected: + virtual bool extrude_impl(const LPoint3f &point2d, + LPoint3f &near_point, LPoint3f &far_point) const; + virtual bool project_impl(const LPoint3f &point3d, LPoint3f &point2d) const; + + virtual float fov_to_film(float fov, float focal_length, bool horiz) const; + virtual float fov_to_focal_length(float fov, float film_size, bool horiz) const; + virtual float film_to_fov(float film_size, float focal_length, bool horiz) const; + +public: + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + Lens::init_type(); + register_type(_type_handle, "PSphereLens", + Lens::get_class_type()); + } + +private: + static TypeHandle _type_handle; +}; + +#include "pSphereLens.I" + +#endif