From c5ec803f6fe6e4c15ebae7491cab25c11273b184 Mon Sep 17 00:00:00 2001 From: David Rose Date: Wed, 12 Dec 2001 19:49:15 +0000 Subject: [PATCH] new distort library, separate out pandafx --- panda/metalibs/panda/Sources.pp | 2 +- panda/metalibs/pandafx/Sources.pp | 16 ++ panda/metalibs/pandafx/pandafx.cxx | 21 ++ panda/metalibs/pandafx/pandafx.h | 13 + panda/src/distort/Sources.pp | 20 ++ panda/src/distort/config_distort.cxx | 52 ++++ panda/src/distort/config_distort.h | 29 ++ panda/src/distort/cylindricalLens.I | 46 +++ panda/src/distort/cylindricalLens.cxx | 190 +++++++++++++ panda/src/distort/cylindricalLens.h | 84 ++++++ panda/src/distort/fisheyeLens.I | 46 +++ panda/src/distort/fisheyeLens.cxx | 228 +++++++++++++++ panda/src/distort/fisheyeLens.h | 74 +++++ panda/src/distort/projectionScreen.I | 133 +++++++++ panda/src/distort/projectionScreen.cxx | 376 +++++++++++++++++++++++++ panda/src/distort/projectionScreen.h | 114 ++++++++ panda/src/effects/Sources.pp | 2 + panda/src/effects/config_effects.cxx | 13 + panda/src/effects/config_effects.h | 4 +- panda/src/effects/lensFlareNode.h | 3 +- panda/src/gobj/imageBuffer.h | 2 +- panda/src/gobj/lens.I | 23 +- panda/src/gobj/lens.cxx | 18 +- panda/src/gobj/perspectiveLens.cxx | 4 +- panda/src/pandabase/pandasymbols.h | 53 ++-- 25 files changed, 1520 insertions(+), 46 deletions(-) create mode 100644 panda/metalibs/pandafx/Sources.pp create mode 100644 panda/metalibs/pandafx/pandafx.cxx create mode 100644 panda/metalibs/pandafx/pandafx.h create mode 100644 panda/src/distort/Sources.pp create mode 100644 panda/src/distort/config_distort.cxx create mode 100644 panda/src/distort/config_distort.h create mode 100644 panda/src/distort/cylindricalLens.I create mode 100644 panda/src/distort/cylindricalLens.cxx create mode 100644 panda/src/distort/cylindricalLens.h create mode 100644 panda/src/distort/fisheyeLens.I create mode 100644 panda/src/distort/fisheyeLens.cxx create mode 100644 panda/src/distort/fisheyeLens.h create mode 100644 panda/src/distort/projectionScreen.I create mode 100644 panda/src/distort/projectionScreen.cxx create mode 100644 panda/src/distort/projectionScreen.h diff --git a/panda/metalibs/panda/Sources.pp b/panda/metalibs/panda/Sources.pp index 0e83cb5667..cc4d0d06b9 100644 --- a/panda/metalibs/panda/Sources.pp +++ b/panda/metalibs/panda/Sources.pp @@ -15,7 +15,7 @@ gsgmisc light linmath mathutil net \ parametrics pnm \ pnmimagetypes pnmimage sgattrib sgmanip sgraph sgraphutil \ - switchnode text tform tiff lerp loader putil effects \ + switchnode text tform tiff lerp loader putil \ audio pgui pandabase diff --git a/panda/metalibs/pandafx/Sources.pp b/panda/metalibs/pandafx/Sources.pp new file mode 100644 index 0000000000..e79f442a5e --- /dev/null +++ b/panda/metalibs/pandafx/Sources.pp @@ -0,0 +1,16 @@ +// DIR_TYPE "metalib" indicates we are building a shared library that +// consists mostly of references to other shared libraries. Under +// Windows, this directly produces a DLL (as opposed to the regular +// src libraries, which don't produce anything but a pile of OBJ files +// under Windows). + +#define DIR_TYPE metalib +#define BUILDING_DLL BUILDING_PANDAFX + +#define COMPONENT_LIBS \ + distort effects + +#begin metalib_target + #define TARGET pandafx + #define SOURCES pandafx.cxx +#end metalib_target diff --git a/panda/metalibs/pandafx/pandafx.cxx b/panda/metalibs/pandafx/pandafx.cxx new file mode 100644 index 0000000000..b4a9601dd3 --- /dev/null +++ b/panda/metalibs/pandafx/pandafx.cxx @@ -0,0 +1,21 @@ +// Filename: pandafx.cxx +// Created by: drose (11Dec01) +// +//////////////////////////////////////////////////////////////////// + +#include "pandafx.h" + +#include + +//////////////////////////////////////////////////////////////////// +// Function: init_libpandafx +// Description: Initializes the library. This must be called at +// least once before any of the functions or classes in +// this library can be used. Normally it will be +// called by the static initializers and need not be +// called explicitly, but special cases exist. +//////////////////////////////////////////////////////////////////// +void +init_libpandafx() { + init_libdistort(); +} diff --git a/panda/metalibs/pandafx/pandafx.h b/panda/metalibs/pandafx/pandafx.h new file mode 100644 index 0000000000..af93a63f7d --- /dev/null +++ b/panda/metalibs/pandafx/pandafx.h @@ -0,0 +1,13 @@ +// Filename: pandafx.h +// Created by: drose (11Dec01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef PANDAFX_H +#define PANDAFX_H + +#include + +EXPCL_PANDAFX void init_libpandafx(); + +#endif diff --git a/panda/src/distort/Sources.pp b/panda/src/distort/Sources.pp new file mode 100644 index 0000000000..2a1417f8fd --- /dev/null +++ b/panda/src/distort/Sources.pp @@ -0,0 +1,20 @@ +#define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \ + dtoolutil:c dtoolbase:c dtool:m + +#begin lib_target + #define TARGET distort + #define LOCAL_LIBS \ + sgraphutil sgraph sgattrib gobj linmath + + #define SOURCES \ + config_distort.cxx config_distort.h \ + cylindricalLens.cxx cylindricalLens.h cylindricalLens.I \ + fisheyeLens.cxx fisheyeLens.h fisheyeLens.I \ + projectionScreen.cxx projectionScreen.h projectionScreen.I + + #define INSTALL_HEADERS + + #define IGATESCAN all + +#end lib_target + diff --git a/panda/src/distort/config_distort.cxx b/panda/src/distort/config_distort.cxx new file mode 100644 index 0000000000..3a09eab184 --- /dev/null +++ b/panda/src/distort/config_distort.cxx @@ -0,0 +1,52 @@ +// Filename: config_distort.cxx +// Created by: drose (11Dec01) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "config_distort.h" +#include "cylindricalLens.h" +#include "fisheyeLens.h" +#include "projectionScreen.h" + +#include "dconfig.h" + +Configure(config_distort); +NotifyCategoryDef(distort, ""); + +ConfigureFn(config_distort) { + init_libdistort(); +} + +//////////////////////////////////////////////////////////////////// +// Function: init_libdistort +// Description: Initializes the library. This must be called at +// least once before any of the functions or classes in +// this library can be used. Normally it will be +// called by the static initializers and need not be +// called explicitly, but special cases exist. +//////////////////////////////////////////////////////////////////// +void +init_libdistort() { + static bool initialized = false; + if (initialized) { + return; + } + initialized = true; + + CylindricalLens::init_type(); + FisheyeLens::init_type(); + ProjectionScreen::init_type(); +} diff --git a/panda/src/distort/config_distort.h b/panda/src/distort/config_distort.h new file mode 100644 index 0000000000..e1ba1f8e06 --- /dev/null +++ b/panda/src/distort/config_distort.h @@ -0,0 +1,29 @@ +// Filename: config_distort.h +// Created by: drose (11Dec01) +// +//////////////////////////////////////////////////////////////////// +// +// 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 CONFIG_DISTORT_H +#define CONFIG_DISTORT_H + +#include "pandabase.h" +#include "notifyCategoryProxy.h" + +NotifyCategoryDecl(distort, EXPCL_PANDAFX, EXPTP_PANDAFX); + +extern EXPCL_PANDAFX void init_libdistort(); + +#endif /* CONFIG_DISTORT_H */ diff --git a/panda/src/distort/cylindricalLens.I b/panda/src/distort/cylindricalLens.I new file mode 100644 index 0000000000..d54a830e04 --- /dev/null +++ b/panda/src/distort/cylindricalLens.I @@ -0,0 +1,46 @@ +// Filename: cylindricalLens.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: CylindricalLens::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE CylindricalLens:: +CylindricalLens() { +} + +//////////////////////////////////////////////////////////////////// +// Function: CylindricalLens::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE CylindricalLens:: +CylindricalLens(const CylindricalLens ©) : Lens(copy) { +} + +//////////////////////////////////////////////////////////////////// +// Function: CylindricalLens::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void CylindricalLens:: +operator = (const CylindricalLens ©) { + Lens::operator = (copy); +} + diff --git a/panda/src/distort/cylindricalLens.cxx b/panda/src/distort/cylindricalLens.cxx new file mode 100644 index 0000000000..34853ae268 --- /dev/null +++ b/panda/src/distort/cylindricalLens.cxx @@ -0,0 +1,190 @@ +// Filename: cylindricalLens.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 "cylindricalLens.h" +#include "deg_2_rad.h" + +TypeHandle CylindricalLens::_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: CylindricalLens::make_copy +// Access: Public, Virtual +// Description: Allocates a new Lens just like this one. +//////////////////////////////////////////////////////////////////// +PT(Lens) CylindricalLens:: +make_copy() const { + return new CylindricalLens(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: CylindricalLens::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 CylindricalLens:: +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(); + float angle = f[0] * k / focal_length; + float sinAngle, cosAngle; + csincos(deg_2_rad(angle), &sinAngle, &cosAngle); + + // Define a unit vector (well, a unit vector in the XY plane, at + // least) that reprents the vector corresponding to this point. + LPoint3f v(sinAngle, cosAngle, f[1] / focal_length); + + // 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: CylindricalLens::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 CylindricalLens:: +project_impl(const LPoint3f &point3d, LPoint3f &point2d) const { + // First, account for any rotations, etc. on the lens. + LPoint3f p = point3d * get_lens_mat_inv(); + + // 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(p[0], p[1]); + + // The perspective distance is the length of this vector in the XY + // plane. + float pdist = xy.length(); + if (pdist == 0.0f) { + point2d.set(0.0f, 0.0f, 0.0f); + return false; + } + + float focal_length = get_focal_length(); + + 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 Z height divided by the perspective + // distance. + p[2] * focal_length / pdist, + // Z is the perspective distance scaled into the range (1, -1). + (get_near() - pdist) / (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: CylindricalLens::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 CylindricalLens:: +fov_to_film(float fov, float focal_length, bool horiz) const { + if (horiz) { + return focal_length * fov / k; + } else { + return (ctan(deg_2_rad(fov * 0.5f)) * focal_length) * 2.0f; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: CylindricalLens::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 CylindricalLens:: +fov_to_focal_length(float fov, float film_size, bool horiz) const { + if (horiz) { + return film_size * k / fov; + } else { + return film_size * 0.5f / ctan(deg_2_rad(fov * 0.5f)); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: CylindricalLens::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 CylindricalLens:: +film_to_fov(float film_size, float focal_length, bool horiz) const { + if (horiz) { + return film_size * k / focal_length; + } else { + return rad_2_deg(catan(film_size * 0.5f / focal_length)) * 2.0f; + } +} diff --git a/panda/src/distort/cylindricalLens.h b/panda/src/distort/cylindricalLens.h new file mode 100644 index 0000000000..4d99829c2f --- /dev/null +++ b/panda/src/distort/cylindricalLens.h @@ -0,0 +1,84 @@ +// Filename: cylindricalLens.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 CYLINDRICALLENS_H +#define CYLINDRICALLENS_H + +#include "pandabase.h" + +#include "lens.h" + +//////////////////////////////////////////////////////////////////// +// Class : CylindricalLens +// Description : A cylindrical lens. This is the kind of lens +// generally used for extremely wide panoramic shots. +// It behaves like a normal perspective lens in the +// vertical direction, but it is non-linear in the +// horizontal dimension: a point on the film corresponds +// to a point in space in linear proportion to its angle +// to the camera, not to its straight-line distance from +// the center. +// +// This allows up to 360 degree lenses in the horizontal +// dimension, with relatively little distortion. The +// distortion is not very apparent between two +// relatively nearby points on the film, but it becomes +// increasingly evident as you compare points widely +// spaced on the film. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDAFX CylindricalLens : public Lens { +PUBLISHED: + INLINE CylindricalLens(); + +public: + INLINE CylindricalLens(const CylindricalLens ©); + INLINE void operator = (const CylindricalLens ©); + +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, "CylindricalLens", + Lens::get_class_type()); + } + +private: + static TypeHandle _type_handle; +}; + +#include "cylindricalLens.I" + +#endif diff --git a/panda/src/distort/fisheyeLens.I b/panda/src/distort/fisheyeLens.I new file mode 100644 index 0000000000..496acff0a1 --- /dev/null +++ b/panda/src/distort/fisheyeLens.I @@ -0,0 +1,46 @@ +// Filename: fisheyeLens.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: FisheyeLens::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE FisheyeLens:: +FisheyeLens() { +} + +//////////////////////////////////////////////////////////////////// +// Function: FisheyeLens::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE FisheyeLens:: +FisheyeLens(const FisheyeLens ©) : Lens(copy) { +} + +//////////////////////////////////////////////////////////////////// +// Function: FisheyeLens::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void FisheyeLens:: +operator = (const FisheyeLens ©) { + Lens::operator = (copy); +} + diff --git a/panda/src/distort/fisheyeLens.cxx b/panda/src/distort/fisheyeLens.cxx new file mode 100644 index 0000000000..0ebe9c8efb --- /dev/null +++ b/panda/src/distort/fisheyeLens.cxx @@ -0,0 +1,228 @@ +// Filename: fisheyeLens.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 "fisheyeLens.h" +#include "deg_2_rad.h" + +TypeHandle FisheyeLens::_type_handle; + +// This is the focal-length constant for fisheye lenses. The focal +// length of a fisheye lens relates to its fov by the equation: + +// w = Fd/k + +// Where w is the width of the negative, F is the focal length, and d +// is the total field of view in degrees. + +// k is chosen to make the focal lengths for a fisheye lens roughly +// correspond to the equivalent field of view for a conventional, +// perspective lens. It was determined empirically by simple +// examination of a couple of actual lenses for 35mm film. I don't +// know how well this extends to other lenses and other negative +// sizes. + +static const float k = 60.0f; +// focal_length = film_size * k / fov; + + +//////////////////////////////////////////////////////////////////// +// Function: FisheyeLens::make_copy +// Access: Public, Virtual +// Description: Allocates a new Lens just like this one. +//////////////////////////////////////////////////////////////////// +PT(Lens) FisheyeLens:: +make_copy() const { + return new FisheyeLens(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: FisheyeLens::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 FisheyeLens:: +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(); + + // First, get the vector from the center of the film to the point, + // and normalize it. + LVector2f v2(f[0], f[1]); + + LPoint3f v; + + float r = v2.length(); + if (r == 0.0f) { + // Special case: directly forward. + v.set(0.0f, 1.0f, 0.0f); + + } else { + v2 /= r; + + // Now get the point r units around the circle in the YZ plane. + float focal_length = get_focal_length(); + float angle = r * k / focal_length; + float sinAngle, cosAngle; + csincos(deg_2_rad(angle), &sinAngle, &cosAngle); + + LVector3f p(0.0, cosAngle, sinAngle); + + // And rotate this point around the Y axis. + v.set(p[0]*v2[1] + p[2]*v2[0], + p[1], + p[2]*v2[1] - p[0]*v2[0]); + } + + // 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: FisheyeLens::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 FisheyeLens:: +project_impl(const LPoint3f &point3d, LPoint3f &point2d) const { + // First, account for any rotations, etc. on the lens. + LVector3f v2 = point3d * get_lens_mat_inv(); + + // A fisheye lens projection has the property that the distance from + // the center point to any other point on the projection is + // proportional to the actual distance on the sphere along the great + // circle. Also, the angle to the point on the projection is equal + // to the angle to the point on the sphere. + + // First, get the straight-line distance from the lens, and use it + // to normalize the vector. + float dist = v2.length(); + v2 /= dist; + + // Now, project the point into the XZ plane and measure its angle + // to the Z axis. This is the same angle it will have to the + // vertical axis on the film. + LVector2f y(v2[0], v2[2]); + y.normalize(); + + if (y == LVector2f(0.0f, 0.0f)) { + // Special case. This point is either directly ahead or directly + // behind. + point2d.set(0.0f, 0.0f, + (get_near() - dist) / (get_far() - get_near())); + return v2[1] >= 0.0f; + } + + // Now bring the vector into the YZ plane by rotating about the Y + // axis. + LVector2f x(v2[1], v2[0]*y[0]+v2[2]*y[1]); + + // Now the angle of x to the forward vector represents the distance + // along the great circle to the point. + float r = 90.0f - rad_2_deg(catan2(x[0], x[1])); + + float focal_length = get_focal_length(); + float factor = r * focal_length / k; + + point2d.set + (y[0] * factor, + y[1] * factor, + // 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: FisheyeLens::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 FisheyeLens:: +fov_to_film(float fov, float focal_length, bool) const { + return focal_length * fov / k; +} + +//////////////////////////////////////////////////////////////////// +// Function: FisheyeLens::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 FisheyeLens:: +fov_to_focal_length(float fov, float film_size, bool) const { + return film_size * k / fov; +} + +//////////////////////////////////////////////////////////////////// +// Function: FisheyeLens::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 FisheyeLens:: +film_to_fov(float film_size, float focal_length, bool) const { + return film_size * k / focal_length; +} + diff --git a/panda/src/distort/fisheyeLens.h b/panda/src/distort/fisheyeLens.h new file mode 100644 index 0000000000..edb412abd4 --- /dev/null +++ b/panda/src/distort/fisheyeLens.h @@ -0,0 +1,74 @@ +// Filename: fisheyeLens.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 FISHEYELENS_H +#define FISHEYELENS_H + +#include "pandabase.h" + +#include "lens.h" + +//////////////////////////////////////////////////////////////////// +// Class : FisheyeLens +// Description : A fisheye lens. This nonlinear lens introduces a +// spherical distortion to the image, which is minimal +// at small angles from the lens, and increases at +// larger angles from the lens. The field of view may +// extend to 360 degrees. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDAFX FisheyeLens : public Lens { +PUBLISHED: + INLINE FisheyeLens(); + +public: + INLINE FisheyeLens(const FisheyeLens ©); + INLINE void operator = (const FisheyeLens ©); + +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, "FisheyeLens", + Lens::get_class_type()); + } + +private: + static TypeHandle _type_handle; +}; + +#include "fisheyeLens.I" + +#endif diff --git a/panda/src/distort/projectionScreen.I b/panda/src/distort/projectionScreen.I new file mode 100644 index 0000000000..3442c75cfb --- /dev/null +++ b/panda/src/distort/projectionScreen.I @@ -0,0 +1,133 @@ +// Filename: projectionScreen.I +// Created by: drose (11Dec01) +// +//////////////////////////////////////////////////////////////////// +// +// 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: ProjectionScreen::set_projector +// Access: Published +// Description: Specifies the LensNode that is to serve as the +// projector for this screen. The relative position of +// the LensNode to the ProjectionScreen, as well as the +// properties of the lens associated with the LensNode, +// determines the UV's that will be assigned to the +// geometry within the ProjectionScreen. +//////////////////////////////////////////////////////////////////// +INLINE void ProjectionScreen:: +set_projector(LensNode *projector) { + _projector = projector; + _stale = true; +} + + +//////////////////////////////////////////////////////////////////// +// Function: ProjectionScreen::get_projector +// Access: Published +// Description: Returns the LensNode that is to serve as the +// projector for this screen, or NULL if no LensNode is +// associated. +//////////////////////////////////////////////////////////////////// +INLINE LensNode *ProjectionScreen:: +get_projector() const { + return _projector; +} + +//////////////////////////////////////////////////////////////////// +// Function: ProjectionScreen::set_vignette_on +// Access: Published +// Description: Specifies whether vertex-based vignetting should be +// on. When this is enabled, vertex color will be set +// on the screen vertices to color the screen two +// distinct colors, usually white and black, for the +// parts of the screen in front of and outside the lens' +// frustum, respectively. When this is not enabled, the +// screen color will be left alone. +// +// This effect generally looks terrible, but it does +// at least make the boundaries of the lens clear. +//////////////////////////////////////////////////////////////////// +INLINE void ProjectionScreen:: +set_vignette_on(bool vignette_on) { + _vignette_on = vignette_on; + _stale = true; +} + + +//////////////////////////////////////////////////////////////////// +// Function: ProjectionScreen::get_vignette_on +// Access: Published +// Description: Returns true if vertex-based vignetting is on, false +// otherwise. See set_vignette_on(). +//////////////////////////////////////////////////////////////////// +INLINE bool ProjectionScreen:: +get_vignette_on() const { + return _vignette_on; +} + +//////////////////////////////////////////////////////////////////// +// Function: ProjectionScreen::set_vignette_color +// Access: Published +// Description: Specifies the color the screen will be painted at the +// portions outside of the lens' frustum; i.e. where the +// lens can't see it or illuminate it. This color is +// only used if the vignette_on flag is true; see +// set_vignette_on(). +//////////////////////////////////////////////////////////////////// +INLINE void ProjectionScreen:: +set_vignette_color(const Colorf &vignette_color) { + _vignette_color = vignette_color; + _stale = true; +} + +//////////////////////////////////////////////////////////////////// +// Function: ProjectionScreen::get_vignette_color +// Access: Published +// Description: Returns the color the screen will be painted at the +// portions outside of the lens' frustum. See +// set_vignette_color(). +//////////////////////////////////////////////////////////////////// +INLINE const Colorf &ProjectionScreen:: +get_vignette_color() const { + return _vignette_color; +} + +//////////////////////////////////////////////////////////////////// +// Function: ProjectionScreen::set_frame_color +// Access: Published +// Description: Specifies the color the screen will be painted at the +// portions outside of the lens' frustum; i.e. where the +// lens can't see it or illuminate it. This color is +// only used if the vignette_on flag is true; see +// set_vignette_on(). +//////////////////////////////////////////////////////////////////// +INLINE void ProjectionScreen:: +set_frame_color(const Colorf &frame_color) { + _frame_color = frame_color; + _stale = true; +} + +//////////////////////////////////////////////////////////////////// +// Function: ProjectionScreen::get_frame_color +// Access: Published +// Description: Returns the color the screen will be painted at the +// portions outside of the lens' frustum. See +// set_frame_color(). +//////////////////////////////////////////////////////////////////// +INLINE const Colorf &ProjectionScreen:: +get_frame_color() const { + return _frame_color; +} diff --git a/panda/src/distort/projectionScreen.cxx b/panda/src/distort/projectionScreen.cxx new file mode 100644 index 0000000000..4d37007f07 --- /dev/null +++ b/panda/src/distort/projectionScreen.cxx @@ -0,0 +1,376 @@ +// Filename: projectionScreen.cxx +// Created by: drose (11Dec01) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "projectionScreen.h" +#include "geomNode.h" +#include "geom.h" +#include "geomTristrip.h" +#include "renderRelation.h" +#include "transformTransition.h" +#include "get_rel_pos.h" + +TypeHandle ProjectionScreen::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: ProjectionScreen::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +ProjectionScreen:: +ProjectionScreen(const string &name) : NamedNode(name) +{ + _vignette_on = false; + _vignette_color.set(0.0f, 0.0f, 0.0f, 1.0f); + _frame_color.set(1.0f, 1.0f, 1.0f, 1.0f); + _computed_rel_top_mat = false; + _stale = true; +} + +//////////////////////////////////////////////////////////////////// +// Function: ProjectionScreen::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +ProjectionScreen:: +~ProjectionScreen() { +} + +//////////////////////////////////////////////////////////////////// +// Function: ProjectionScreen::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +ProjectionScreen:: +ProjectionScreen(const ProjectionScreen ©) : + NamedNode(copy), + _projector(copy._projector), + _vignette_on(copy._vignette_on), + _vignette_color(copy._vignette_color), + _frame_color(copy._frame_color) +{ + _computed_rel_top_mat = false; + _stale = true; +} + +//////////////////////////////////////////////////////////////////// +// Function: ProjectionScreen::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void ProjectionScreen:: +operator = (const ProjectionScreen ©) { + NamedNode::operator = (copy); + _projector = copy._projector; + _vignette_on = copy._vignette_on; + _vignette_color = copy._vignette_color; + _frame_color = copy._frame_color; +} + +//////////////////////////////////////////////////////////////////// +// Function: ProjectionScreen::make_copy +// Access: Public, Virtual +// Description: Returns a newly-allocated Node that is a shallow copy +// of this one. It will be a different Node pointer, +// but its internal data may or may not be shared with +// that of the original Node. +//////////////////////////////////////////////////////////////////// +Node *ProjectionScreen:: +make_copy() const { + return new ProjectionScreen(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: ProjectionScreen::app_traverse +// Access: Public, Virtual +// Description: This is called by the App traversal by virtue of the +// ProjectionScreen node's being present in the scene graph. +//////////////////////////////////////////////////////////////////// +void ProjectionScreen:: +app_traverse(const ArcChain &) { + recompute_if_stale(); +} + +//////////////////////////////////////////////////////////////////// +// Function: ProjectionScreen::generate_screen +// Access: Published +// Description: Synthesizes a polygon mesh based on the projection +// area of the indicated projector. This generates a +// new GeomNode and automatically parents it to the +// ProjectionScreen; the new GeomNode is also returned +// for reference. +// +// The specified projector need not be the same as the +// projector given to the ProjectionScreen with +// set_projector() (although this is often what you +// want). +// +// num_x_verts and num_y_verts specify the number of +// vertices to make in the grid across the horizontal +// and vertical dimension of the projector, +// respectively; distance represents the approximate +// distance of the screen from the lens center. +//////////////////////////////////////////////////////////////////// +GeomNode *ProjectionScreen:: +generate_screen(LensNode *projector, const string &screen_name, + int num_x_verts, int num_y_verts, float distance) { + nassertr(projector != (LensNode *)NULL, NULL); + nassertr(projector->get_lens() != NULL, NULL); + + // First, get the relative coordinate space of the projector. + LMatrix4f rel_mat; + get_rel_mat(projector, this, rel_mat); + + // Now compute all the vertices for the screen. These are arranged + // in order from left to right and bottom to top. + int num_verts = num_x_verts * num_y_verts; + Lens *lens = projector->get_lens(); + float t = (distance - lens->get_near()) / (lens->get_far() - lens->get_near()); + + PTA_Vertexf coords; + coords.reserve(num_verts); + float x_scale = 2.0f / (num_x_verts - 1); + float y_scale = 2.0f / (num_y_verts - 1); + for (int yi = 0; yi < num_y_verts; yi++) { + for (int xi = 0; xi < num_x_verts; xi++) { + LPoint2f film = LPoint2f((float)xi * x_scale - 1.0f, + (float)yi * y_scale - 1.0f); + LPoint3f near_point, far_point; + lens->extrude(film, near_point, far_point); + + LPoint3f point = near_point + t * (far_point - near_point); + point = point * rel_mat; + + coords.push_back(point); + } + } + nassertr((int)coords.size() == num_verts, NULL); + + // Now synthesize a triangle mesh. We run triangle strips + // horizontally across the grid. + int num_tstrips = (num_y_verts-1); + int tstrip_length = 2*(num_x_verts-1)+2; + + PTA_int lengths; + PTA_ushort vindex; + + // Set the lengths array. we are creating num_tstrips t-strips, + // each of which has tstrip_length vertices. + lengths.reserve(num_tstrips); + int n; + for (n = 0; n < num_tstrips; n++) { + lengths.push_back(tstrip_length); + } + nassertr((int)lengths.size() == num_tstrips, NULL); + + // Now fill up the index array into the vertices. This lays out the + // order of the vertices in each t-strip. + vindex.reserve(num_tstrips * tstrip_length); + n = 0; + int ti, si; + for (ti = 1; ti < num_y_verts; ti++) { + vindex.push_back(ti * num_x_verts); + for (si = 1; si < num_x_verts; si++) { + vindex.push_back((ti - 1) * num_x_verts + (si-1)); + vindex.push_back(ti * num_x_verts + si); + } + vindex.push_back((ti - 1) * num_x_verts + (num_x_verts-1)); + } + nassertr((int)vindex.size() == num_tstrips * tstrip_length, NULL); + + GeomTristrip *geom = new GeomTristrip; + geom->set_num_prims(num_tstrips); + geom->set_lengths(lengths); + + geom->set_coords(coords, G_PER_VERTEX, vindex); + + // Make it white. + PTA_Colorf colors; + colors.push_back(Colorf(1.0f, 1.0f, 1.0f, 1.0f)); + geom->set_colors(colors, G_OVERALL); + + // Now create a GeomNode to hold this mesh. + GeomNode *geom_node = new GeomNode(screen_name); + geom_node->add_geom(geom); + + // And parent it to ourselves. + new RenderRelation(this, geom_node); + _stale = true; + + return geom_node; +} + +//////////////////////////////////////////////////////////////////// +// Function: ProjectionScreen::recompute +// Access: Published +// Description: Recomputes all the UV's for geometry below the +// ProjectionScreen node, as if the texture were +// projected from the associated projector. +// +// This function is normally called automatically +// whenever the relevant properties change, so it should +// not normally need to be called directly by the user. +// However, it does no harm to call this if there is any +// doubt. +//////////////////////////////////////////////////////////////////// +void ProjectionScreen:: +recompute() { + if (_projector != (LensNode *)NULL && + _projector->get_lens() != (Lens *)NULL) { + _colors.clear(); + _colors.push_back(_vignette_color); + _colors.push_back(_frame_color); + + recompute_node(this, _rel_top_mat, _computed_rel_top_mat); + // Make sure this flag is set to false for next time. + _computed_rel_top_mat = false; + + _projector_lens_change = _projector->get_lens()->get_last_change(); + _stale = false; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: ProjectionScreen::recompute_if_stale +// Access: Private +// Description: Calls recompute() only if the relative transform +// between the ProjectionScreen and the projector has +// changed, or if any other relevant property has +// changed. +//////////////////////////////////////////////////////////////////// +void ProjectionScreen:: +recompute_if_stale() { + if (_projector != (LensNode *)NULL && + _projector->get_lens() != (Lens *)NULL) { + UpdateSeq lens_change = _projector->get_lens()->get_last_change(); + if (_stale || lens_change != _projector_lens_change) { + recompute(); + + } else { + // Get the relative transform to ensure it hasn't changed. + LMatrix4f top_mat; + get_rel_mat(this, _projector, top_mat); + if (!_rel_top_mat.almost_equal(top_mat)) { + _rel_top_mat = top_mat; + _computed_rel_top_mat = true; + recompute(); + } + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: ProjectionScreen::recompute_node +// Access: Private +// Description: Recurses over all geometry at the indicated node and +// below, looking for GeomNodes that want to have new +// UV's computed. When a new transform space is +// encountered, a new relative matrix is computed. +//////////////////////////////////////////////////////////////////// +void ProjectionScreen:: +recompute_node(Node *node, LMatrix4f &rel_mat, bool &computed_rel_mat) { + if (node->is_of_type(GeomNode::get_class_type())) { + recompute_geom_node(DCAST(GeomNode, node), rel_mat, computed_rel_mat); + } + + // Now recurse on children. + int num_children = node->get_num_children(RenderRelation::get_class_type()); + for (int i = 0; i < num_children; i++) { + NodeRelation *arc = node->get_child(RenderRelation::get_class_type(), i); + + if (arc->has_transition(TransformTransition::get_class_type())) { + // This arc has a transform; therefore, we must recompute the + // relative matrix from this point. + LMatrix4f new_rel_mat; + bool computed_new_rel_mat = false; + recompute_node(arc->get_child(), new_rel_mat, computed_new_rel_mat); + } else { + // This arc has no transform, so we can use the same transform + // space from before. + recompute_node(arc->get_child(), rel_mat, computed_rel_mat); + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: ProjectionScreen::recompute_geom_node +// Access: Private +// Description: Recomputes the UV's just for the indicated GeomNode. +//////////////////////////////////////////////////////////////////// +void ProjectionScreen:: +recompute_geom_node(GeomNode *node, LMatrix4f &rel_mat, bool &computed_rel_mat) { + if (!computed_rel_mat) { + // All right, time to compute the matrix. + get_rel_mat(node, _projector, rel_mat); + computed_rel_mat = true; + } + + int num_geoms = node->get_num_geoms(); + for (int i = 0; i < num_geoms; i++) { + dDrawable *drawable = node->get_geom(i); + if (drawable->is_of_type(Geom::get_class_type())) { + recompute_geom(DCAST(Geom, drawable), rel_mat); + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: ProjectionScreen::recompute_geom +// Access: Private +// Description: Recomputes the UV's just for the indicated Geom. +//////////////////////////////////////////////////////////////////// +void ProjectionScreen:: +recompute_geom(Geom *geom, const LMatrix4f &rel_mat) { + static const LMatrix3f LensToUv + (0.5f, 0.0f, 0.0f, + 0.0f, 0.5f, 0.0f, + 0.5f, 0.5f, 1.0f); + + PTA_TexCoordf uvs; + PTA_ushort color_index; + Lens *lens = _projector->get_lens(); + nassertv(lens != (Lens *)NULL); + + // Iterate through all the vertices in the Geom. + int num_vertices = geom->get_num_vertices(); + Geom::VertexIterator vi = geom->make_vertex_iterator(); + + for (int i = 0; i < num_vertices; i++) { + const Vertexf &vert = geom->get_next_vertex(vi); + + // For each vertex, project to the film plane. + LPoint2f film(0.0, 0.0); + bool good = lens->project(vert * rel_mat, film); + + // Now the lens gives us coordinates in the range [-1, 1]. + // Rescale these to [0, 1]. + uvs.push_back(film * LensToUv); + + // If we have vignette color in effect, color the vertex according + // to whether it fell in front of the lens or not. + if (_vignette_on) { + color_index.push_back(good ? 1 : 0); + } + } + + // Now set the UV's. + geom->set_texcoords(uvs, G_PER_VERTEX); + + if (_vignette_on) { + geom->set_colors(_colors, G_PER_VERTEX, color_index); + } +} diff --git a/panda/src/distort/projectionScreen.h b/panda/src/distort/projectionScreen.h new file mode 100644 index 0000000000..7b931557fa --- /dev/null +++ b/panda/src/distort/projectionScreen.h @@ -0,0 +1,114 @@ +// Filename: projectionScreen.h +// Created by: drose (11Dec01) +// +//////////////////////////////////////////////////////////////////// +// +// 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 PROJECTIONSCREEN_H +#define PROJECTIONSCREEN_H + +#include "pandabase.h" + +#include "namedNode.h" +#include "lensNode.h" + +class GeomNode; +class Geom; + +//////////////////////////////////////////////////////////////////// +// Class : ProjectionScreen +// Description : A ProjectionScreen implements a simple system for +// projective texturing. The ProjectionScreen node is +// the parent of a hierarchy of geometry that is +// considered a "screen"; the ProjectionScreen will +// automatically recompute all the UV's on its +// subordinate geometry according to the relative +// position and lens parameters of the indicated +// LensNode. +// +// This does not take advantage of any hardware-assisted +// projective texturing; nor does it presently support +// multitexturing. However, it does support any kind of +// lens, linear or nonlinear, that might be defined +// using the Lens interface, including fisheye and +// cylindrical lenses. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDAFX ProjectionScreen : public NamedNode { +PUBLISHED: + ProjectionScreen(const string &name = ""); + virtual ~ProjectionScreen(); + +public: + ProjectionScreen(const ProjectionScreen ©); + void operator = (const ProjectionScreen ©); + + virtual Node *make_copy() const; + virtual void app_traverse(const ArcChain &chain); + +PUBLISHED: + INLINE void set_projector(LensNode *projector); + INLINE LensNode *get_projector() const; + + GeomNode *generate_screen(LensNode *projector, const string &screen_name, + int num_x_verts, int num_y_verts, float distance); + + INLINE void set_vignette_on(bool vignette_on); + INLINE bool get_vignette_on() const; + + INLINE void set_vignette_color(const Colorf &vignette_color); + INLINE const Colorf &get_vignette_color() const; + INLINE void set_frame_color(const Colorf &frame_color); + INLINE const Colorf &get_frame_color() const; + + void recompute(); + +private: + void recompute_if_stale(); + void recompute_node(Node *node, LMatrix4f &rel_mat, bool &computed_rel_mat); + void recompute_geom_node(GeomNode *node, LMatrix4f &rel_mat, bool &computed_rel_mat); + void recompute_geom(Geom *geom, const LMatrix4f &rel_mat); + + PT(LensNode) _projector; + bool _vignette_on; + Colorf _vignette_color; + Colorf _frame_color; + + PTA_Colorf _colors; + LMatrix4f _rel_top_mat; + bool _computed_rel_top_mat; + bool _stale; + UpdateSeq _projector_lens_change; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + NamedNode::init_type(); + register_type(_type_handle, "ProjectionScreen", + NamedNode::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "projectionScreen.I" + +#endif diff --git a/panda/src/effects/Sources.pp b/panda/src/effects/Sources.pp index 3d6b468c1e..20896a3659 100644 --- a/panda/src/effects/Sources.pp +++ b/panda/src/effects/Sources.pp @@ -14,5 +14,7 @@ #define INSTALL_HEADERS \ config_effects.h lensFlareNode.I lensFlareNode.h + #define IGATESCAN all + #end lib_target diff --git a/panda/src/effects/config_effects.cxx b/panda/src/effects/config_effects.cxx index 30deb40dde..a3ff7159a2 100644 --- a/panda/src/effects/config_effects.cxx +++ b/panda/src/effects/config_effects.cxx @@ -25,6 +25,19 @@ Configure(config_effects); NotifyCategoryDef(effects, ""); ConfigureFn(config_effects) { + init_libeffects(); +} + +//////////////////////////////////////////////////////////////////// +// Function: init_libeffects +// Description: Initializes the library. This must be called at +// least once before any of the functions or classes in +// this library can be used. Normally it will be +// called by the static initializers and need not be +// called explicitly, but special cases exist. +//////////////////////////////////////////////////////////////////// +void +init_libeffects() { LensFlareNode::init_type(); //Registration of writeable object's creation diff --git a/panda/src/effects/config_effects.h b/panda/src/effects/config_effects.h index febdafa421..aa2d47ccb9 100644 --- a/panda/src/effects/config_effects.h +++ b/panda/src/effects/config_effects.h @@ -23,6 +23,8 @@ #include #include -NotifyCategoryDecl(effects, EXPCL_PANDA, EXPTP_PANDA); +NotifyCategoryDecl(effects, EXPCL_PANDAFX, EXPTP_PANDAFX); + +extern EXPCL_PANDAFX void init_libeffects(); #endif /* CONFIG_EFFECTS_H */ diff --git a/panda/src/effects/lensFlareNode.h b/panda/src/effects/lensFlareNode.h index 1972c09788..ae566e186f 100644 --- a/panda/src/effects/lensFlareNode.h +++ b/panda/src/effects/lensFlareNode.h @@ -32,7 +32,7 @@ class GraphicsStateGuardian; class ClockObject; -class EXPCL_PANDA LensFlareNode : public Node +class EXPCL_PANDAFX LensFlareNode : public Node { PUBLISHED: INLINE LensFlareNode(void); @@ -41,7 +41,6 @@ PUBLISHED: PTA_float angle_scales, PTA_Colorf colors); void add_blind(PT(Texture) blind); - INLINE void set_angle_scale(float scale); INLINE void set_texel_scale(float texel_to_world); INLINE void set_global_scale(float scale); diff --git a/panda/src/gobj/imageBuffer.h b/panda/src/gobj/imageBuffer.h index 09cd93a6d4..d61486fd80 100644 --- a/panda/src/gobj/imageBuffer.h +++ b/panda/src/gobj/imageBuffer.h @@ -47,10 +47,10 @@ PUBLISHED: ImageBuffer( void ) : dDrawable() { } virtual ~ImageBuffer( void ) { } +public: virtual bool read( const string& name ) = 0; virtual bool write( const string& name = "" ) const = 0; -public: virtual void config( void ) { WritableConfigurable::config(); } virtual void copy(GraphicsStateGuardianBase *, const DisplayRegion *)=0; diff --git a/panda/src/gobj/lens.I b/panda/src/gobj/lens.I index 6de4c2b38e..6270800bc5 100644 --- a/panda/src/gobj/lens.I +++ b/panda/src/gobj/lens.I @@ -70,16 +70,16 @@ extrude(const LPoint3f &point2d, LPoint3f &near_point, LPoint3f &far_point) cons // // 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. +// 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 LPoint3f &point3d, LPoint2f &point2d) const { LPoint3f result; - if (project_impl(point3d, result)) { - point2d.set(result[0], result[1]); - return true; - } - return false; + bool okflag = project_impl(point3d, result); + point2d.set(result[0], result[1]); + return okflag; } //////////////////////////////////////////////////////////////////// @@ -90,14 +90,15 @@ project(const LPoint3f &point3d, LPoint2f &point2d) const { // 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. +// 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. +// 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 LPoint3f &point3d, LPoint3f &point2d) const { diff --git a/panda/src/gobj/lens.cxx b/panda/src/gobj/lens.cxx index bdaecc8bc4..c2c3e77184 100644 --- a/panda/src/gobj/lens.cxx +++ b/panda/src/gobj/lens.cxx @@ -1034,7 +1034,7 @@ get_lens_mat_inv() const { } //////////////////////////////////////////////////////////////////// -// Function: Lens::extrude +// Function: Lens::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 @@ -1080,14 +1080,15 @@ extrude_impl(const LPoint3f &point2d, LPoint3f &near_point, LPoint3f &far_point) // 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. +// 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. +// is filled in), or false otherwise (in which case +// point2d will be filled in with something, which may +// or may not be meaningful). //////////////////////////////////////////////////////////////////// bool Lens:: project_impl(const LPoint3f &point3d, LPoint3f &point2d) const { @@ -1095,10 +1096,13 @@ project_impl(const LPoint3f &point3d, LPoint3f &point2d) const { LVecBase4f full(point3d[0], point3d[1], point3d[2], 1.0f); full = projection_mat.xform(full); if (full[3] == 0.0f) { + point2d.set(0.0f, 0.0f, 0.0f); return false; } point2d.set(full[0] / full[3], full[1] / full[3], full[2] / full[3]); - return point2d[0] >= -1.0f && point2d[0] <= 1.0f && + return + full[3] > 0.0f && + point2d[0] >= -1.0f && point2d[0] <= 1.0f && point2d[1] >= -1.0f && point2d[1] <= 1.0f; } diff --git a/panda/src/gobj/perspectiveLens.cxx b/panda/src/gobj/perspectiveLens.cxx index 580450ee8e..a9be72cba8 100644 --- a/panda/src/gobj/perspectiveLens.cxx +++ b/panda/src/gobj/perspectiveLens.cxx @@ -58,8 +58,8 @@ compute_projection_mat() { } float fl = get_focal_length(); - float a = (_far_distance + _near_distance) / (_far_distance - _near_distance); - float b = -2.0f * _far_distance * _near_distance / (_far_distance - _near_distance); + float a = (get_far() + get_near()) / (get_far() - get_near()); + float b = -2.0f * get_far() * get_near() / (get_far() - get_near()); LMatrix4f canonical; switch (cs) { diff --git a/panda/src/pandabase/pandasymbols.h b/panda/src/pandabase/pandasymbols.h index 2ff26cc7ba..356a61c104 100644 --- a/panda/src/pandabase/pandasymbols.h +++ b/panda/src/pandabase/pandasymbols.h @@ -31,12 +31,12 @@ #define EXPTP_PANDA extern #endif -#ifdef BUILDING_PANDAEXPRESS - #define EXPCL_PANDAEXPRESS __declspec(dllexport) - #define EXPTP_PANDAEXPRESS +#ifdef BUILDING_PANDADX + #define EXPCL_PANDADX __declspec(dllexport) + #define EXPTP_PANDADX #else - #define EXPCL_PANDAEXPRESS __declspec(dllimport) - #define EXPTP_PANDAEXPRESS extern + #define EXPCL_PANDADX __declspec(dllimport) + #define EXPTP_PANDADX extern #endif #ifdef BUILDING_PANDAEGG @@ -47,12 +47,20 @@ #define EXPTP_PANDAEGG extern #endif -#ifdef BUILDING_PANDAPHYSICS - #define EXPCL_PANDAPHYSICS __declspec(dllexport) - #define EXPTP_PANDAPHYSICS +#ifdef BUILDING_PANDAEXPRESS + #define EXPCL_PANDAEXPRESS __declspec(dllexport) + #define EXPTP_PANDAEXPRESS #else - #define EXPCL_PANDAPHYSICS __declspec(dllimport) - #define EXPTP_PANDAPHYSICS extern + #define EXPCL_PANDAEXPRESS __declspec(dllimport) + #define EXPTP_PANDAEXPRESS extern +#endif + +#ifdef BUILDING_PANDAFX + #define EXPCL_PANDAFX __declspec(dllexport) + #define EXPTP_PANDAFX +#else + #define EXPCL_PANDAFX __declspec(dllimport) + #define EXPTP_PANDAFX extern #endif #ifdef BUILDING_PANDAGL @@ -71,12 +79,12 @@ #define EXPTP_PANDAGLUT extern #endif -#ifdef BUILDING_PANDADX - #define EXPCL_PANDADX __declspec(dllexport) - #define EXPTP_PANDADX +#ifdef BUILDING_PANDAPHYSICS + #define EXPCL_PANDAPHYSICS __declspec(dllexport) + #define EXPTP_PANDAPHYSICS #else - #define EXPCL_PANDADX __declspec(dllimport) - #define EXPTP_PANDADX extern + #define EXPCL_PANDAPHYSICS __declspec(dllimport) + #define EXPTP_PANDAPHYSICS extern #endif #ifdef BUILDING_PANDARIB @@ -116,14 +124,17 @@ #define EXPCL_PANDA #define EXPTP_PANDA -#define EXPCL_PANDAEXPRESS -#define EXPTP_PANDAEXPRESS +#define EXPCL_PANDADX +#define EXPTP_PANDADX #define EXPCL_PANDAEGG #define EXPTP_PANDAEGG -#define EXPCL_PANDAPHYSICS -#define EXPTP_PANDAPHYSICS +#define EXPCL_PANDAEXPRESS +#define EXPTP_PANDAEXPRESS + +#define EXPCL_PANDAFX +#define EXPTP_PANDAFX #define EXPCL_PANDAGL #define EXPTP_PANDAGL @@ -131,8 +142,8 @@ #define EXPCL_PANDAGLUT #define EXPTP_PANDAGLUT -#define EXPCL_PANDADX -#define EXPTP_PANDADX +#define EXPCL_PANDAPHYSICS +#define EXPTP_PANDAPHYSICS #define EXPCL_PANDARIB #define EXPTP_PANDARIB