From 9315342da7d51a71c36af45190a3a15ffd579af8 Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 1 Apr 2004 01:58:42 +0000 Subject: [PATCH] define normals for projection screens --- panda/src/distort/cylindricalLens.cxx | 38 +++++++++++++++++++- panda/src/distort/cylindricalLens.h | 1 + panda/src/distort/fisheyeLens.cxx | 32 +++++++++++++++++ panda/src/distort/fisheyeLens.h | 1 + panda/src/distort/nonlinearImager.cxx | 20 +++++++---- panda/src/distort/projectionScreen.cxx | 14 +++++--- panda/src/gobj/lens.I | 48 ++++++++++++++++++++++++++ panda/src/gobj/lens.cxx | 35 +++++++++++++++++++ panda/src/gobj/lens.h | 3 ++ 9 files changed, 181 insertions(+), 11 deletions(-) diff --git a/panda/src/distort/cylindricalLens.cxx b/panda/src/distort/cylindricalLens.cxx index bf0723b681..b188d9fd19 100644 --- a/panda/src/distort/cylindricalLens.cxx +++ b/panda/src/distort/cylindricalLens.cxx @@ -66,7 +66,7 @@ extrude_impl(const LPoint3f &point2d, LPoint3f &near_point, LPoint3f &far_point) 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. + // least) that represents 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 @@ -78,6 +78,42 @@ extrude_impl(const LPoint3f &point2d, LPoint3f &near_point, LPoint3f &far_point) return true; } +//////////////////////////////////////////////////////////////////// +// Function: CylindricalLens::extrude_vec_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 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. +//////////////////////////////////////////////////////////////////// +bool CylindricalLens:: +extrude_vec_impl(const LPoint3f &point2d, LVector3f &vec) 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] * cylindrical_k / focal_length; + float sinAngle, cosAngle; + csincos(deg_2_rad(angle), &sinAngle, &cosAngle); + + vec = LVector3f(sinAngle, cosAngle, 0.0f) * get_lens_mat(); + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: CylindricalLens::project_impl // Access: Protected, Virtual diff --git a/panda/src/distort/cylindricalLens.h b/panda/src/distort/cylindricalLens.h index fb857b5fd3..47026f48f8 100644 --- a/panda/src/distort/cylindricalLens.h +++ b/panda/src/distort/cylindricalLens.h @@ -55,6 +55,7 @@ public: protected: virtual bool extrude_impl(const LPoint3f &point2d, LPoint3f &near_point, LPoint3f &far_point) const; + virtual bool extrude_vec_impl(const LPoint3f &point2d, LVector3f &vec) const; virtual bool project_impl(const LPoint3f &point3d, LPoint3f &point2d) const; virtual float fov_to_film(float fov, float focal_length, bool horiz) const; diff --git a/panda/src/distort/fisheyeLens.cxx b/panda/src/distort/fisheyeLens.cxx index a78c4329c0..a3ce056169 100644 --- a/panda/src/distort/fisheyeLens.cxx +++ b/panda/src/distort/fisheyeLens.cxx @@ -110,6 +110,38 @@ extrude_impl(const LPoint3f &point2d, LPoint3f &near_point, LPoint3f &far_point) return true; } +//////////////////////////////////////////////////////////////////// +// Function: FisheyeLens::extrude_vec_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 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. +//////////////////////////////////////////////////////////////////// +bool FisheyeLens:: +extrude_vec_impl(const LPoint3f &point2d, LVector3f &vec) const { + LPoint3f near_point, far_point; + if (!extrude_impl(point2d, near_point, far_point)) { + return false; + } + + vec = far_point - near_point; + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: FisheyeLens::project_impl // Access: Protected, Virtual diff --git a/panda/src/distort/fisheyeLens.h b/panda/src/distort/fisheyeLens.h index ac9b735959..b22c4a43ad 100644 --- a/panda/src/distort/fisheyeLens.h +++ b/panda/src/distort/fisheyeLens.h @@ -45,6 +45,7 @@ public: protected: virtual bool extrude_impl(const LPoint3f &point2d, LPoint3f &near_point, LPoint3f &far_point) const; + virtual bool extrude_vec_impl(const LPoint3f &point2d, LVector3f &vec) const; virtual bool project_impl(const LPoint3f &point3d, LPoint3f &point2d) const; virtual float fov_to_film(float fov, float focal_length, bool horiz) const; diff --git a/panda/src/distort/nonlinearImager.cxx b/panda/src/distort/nonlinearImager.cxx index 26cb9e7c76..740774baba 100644 --- a/panda/src/distort/nonlinearImager.cxx +++ b/panda/src/distort/nonlinearImager.cxx @@ -259,10 +259,11 @@ set_source_camera(int index, const NodePath &source_camera) { void NonlinearImager:: set_screen_active(int index, bool active) { nassertv(index >= 0 && index < (int)_screens.size()); - _screens[index]._active = active; + + Screen &screen = _screens[index]; + screen._active = active; if (!active) { - Screen &screen = _screens[index]; // If we've just made this screen inactive, remove its meshes. for (size_t vi = 0; vi < screen._meshes.size(); vi++) { screen._meshes[vi]._mesh.remove_node(); @@ -275,9 +276,16 @@ set_screen_active(int index, bool active) { nassertv(removed); } + // Hide the screen in the dark room. This doesn't really matter, + // since the dark room isn't normally rendered, but hide it anyway + // in case the user stuck a camera in there for fun. + screen._screen.hide(); + } else { // If we've just made it active, it needs to be recomputed. _stale = true; + + screen._screen.show(); } } @@ -688,10 +696,10 @@ recompute_screen(NonlinearImager::Screen &screen, size_t vi) { if (screen._buffer != (GraphicsOutput *)NULL) { screen._meshes[vi]._mesh.set_texture(screen._buffer->get_texture()); - // We don't really need to set the texture on the external screen, - // since that's normally not rendered, but we do anyway just for - // debugging purposes (in case the user does try to render it, to - // see what's going on). + // We don't really need to set the texture on the dark room + // screen, since that's normally not rendered, but we do anyway + // just for debugging purposes (in case the user does try to + // render it, to see what's going on). screen._screen.set_texture(screen._buffer->get_texture()); } diff --git a/panda/src/distort/projectionScreen.cxx b/panda/src/distort/projectionScreen.cxx index 52b93a1cb2..a73878266a 100644 --- a/panda/src/distort/projectionScreen.cxx +++ b/panda/src/distort/projectionScreen.cxx @@ -197,6 +197,7 @@ generate_screen(const NodePath &projector, const string &screen_name, float t = (distance - lens->get_near()) / (lens->get_far() - lens->get_near()); PTA_Vertexf coords; + PTA_Normalf norms; coords.reserve(num_verts); float x_scale = 2.0f / (num_x_verts - 1); float y_scale = 2.0f / (num_y_verts - 1); @@ -211,11 +212,15 @@ generate_screen(const NodePath &projector, const string &screen_name, 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); + + // Normals aren't often needed on projection screens, but you + // never know. + LVector3f normal; + lens->extrude_vec(film, normal); + + coords.push_back(point * rel_mat); + norms.push_back(-normalize(normal * rel_mat)); } } nassertr((int)coords.size() == num_verts, NULL); @@ -257,6 +262,7 @@ generate_screen(const NodePath &projector, const string &screen_name, geom->set_lengths(lengths); geom->set_coords(coords, G_PER_VERTEX, vindex); + geom->set_normals(norms, G_PER_VERTEX, vindex); // Make it white. PTA_Colorf colors; diff --git a/panda/src/gobj/lens.I b/panda/src/gobj/lens.I index 71fb9dbed9..f1b01685b7 100644 --- a/panda/src/gobj/lens.I +++ b/panda/src/gobj/lens.I @@ -60,6 +60,54 @@ extrude(const LPoint3f &point2d, LPoint3f &near_point, LPoint3f &far_point) cons return extrude_impl(point2d, near_point, far_point); } +//////////////////////////////////////////////////////////////////// +// Function: Lens::extrude_vec +// Access: Published +// 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 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 LPoint2f &point2d, LVector3f &vec) const { + return extrude_vec_impl(LPoint3f(point2d[0], point2d[1], 0.0f), vec); +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::extrude_vec +// Access: Published +// 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 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 LPoint3f &point2d, LVector3f &vec) const { + return extrude_vec_impl(point2d, vec); +} + //////////////////////////////////////////////////////////////////// // Function: Lens::project // Access: Published diff --git a/panda/src/gobj/lens.cxx b/panda/src/gobj/lens.cxx index 9bfde0e45d..aca141a1bc 100644 --- a/panda/src/gobj/lens.cxx +++ b/panda/src/gobj/lens.cxx @@ -1117,6 +1117,41 @@ extrude_impl(const LPoint3f &point2d, LPoint3f &near_point, LPoint3f &far_point) return true; } +//////////////////////////////////////////////////////////////////// +// Function: Lens::extrude_vec_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 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. +// +// Generally, for all rational lenses, the center of the +// film at (0,0) computes a vector that is in the same +// direction as the vector specified by +// set_view_vector(). +// +// For all linear lenses, including perspective and +// ortographic lenses, all points on the film compute +// this same vector (the far plane is a flat plane, so +// the normal is the same everywhere). For curved +// lenses like fisheye and cylindrical lenses, different +// points may compute different vectors (the far "plane" +// on these lenses is a curved surface). +// +// The z coordinate of the 2-d point is ignored. +// +// Returns true if the vector is defined, or false +// otherwise. +//////////////////////////////////////////////////////////////////// +bool Lens:: +extrude_vec_impl(const LPoint3f &point2d, LVector3f &vec) const { + vec = LVector3f::forward(_cs) * get_lens_mat(); + return true; +} + //////////////////////////////////////////////////////////////////// // Function: Lens::project_impl // Access: Protected, Virtual diff --git a/panda/src/gobj/lens.h b/panda/src/gobj/lens.h index 063dc7a4e9..64f8c4d27c 100644 --- a/panda/src/gobj/lens.h +++ b/panda/src/gobj/lens.h @@ -53,6 +53,8 @@ PUBLISHED: LPoint3f &near_point, LPoint3f &far_point) const; INLINE bool extrude(const LPoint3f &point2d, LPoint3f &near_point, LPoint3f &far_point) const; + INLINE bool extrude_vec(const LPoint2f &point2d, LVector3f &vec3d) const; + INLINE bool extrude_vec(const LPoint3f &point2d, LVector3f &vec3d) const; INLINE bool project(const LPoint3f &point3d, LPoint3f &point2d) const; INLINE bool project(const LPoint3f &point3d, LPoint2f &point2d) const; @@ -153,6 +155,7 @@ protected: virtual bool extrude_impl(const LPoint3f &point2d, LPoint3f &near_point, LPoint3f &far_point) const; + virtual bool extrude_vec_impl(const LPoint3f &point2d, LVector3f &vec) const; virtual bool project_impl(const LPoint3f &point3d, LPoint3f &point2d) const; virtual void compute_film_size();