Browse Source

add undist_lut to ProjectionScreen, PfmVizzer

David Rose 12 years ago
parent
commit
a515048908

+ 52 - 0
panda/src/distort/projectionScreen.I

@@ -26,6 +26,58 @@ get_projector() const {
   return _projector;
   return _projector;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: ProjectionScreen::clear_undist_lut
+//       Access: Published
+//  Description: Removes the distortion lookup table from the
+//               projector, if specified.
+////////////////////////////////////////////////////////////////////
+INLINE void ProjectionScreen::
+clear_undist_lut() {
+  _has_undist_lut = false;
+  _undist_lut = PfmFile();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ProjectionScreen::set_undist_lut
+//       Access: Published
+//  Description: Applies a distortion lookup table to the
+//               projector.  This mapping warps the lens effect by
+//               passing each ray through an indirection table: the
+//               point (u,v) in the indicated lookup table stores the
+//               actual (u,v) that the lens produces.
+//
+//               This does not affect the operation of
+//               generate_screen().
+////////////////////////////////////////////////////////////////////
+INLINE void ProjectionScreen::
+set_undist_lut(const PfmFile &undist_lut) {
+  _has_undist_lut = undist_lut.is_valid();
+  _undist_lut = undist_lut;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ProjectionScreen::has_undist_lut
+//       Access: Published
+//  Description: Returns true if a valid distortion lookup table was
+//               provided via set_undist_lut(), false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool ProjectionScreen::
+has_undist_lut() const {
+  return _has_undist_lut;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ProjectionScreen::get_undist_lut
+//       Access: Published
+//  Description: Returns the distortion lookup table provided via
+//               set_undist_lut(), if any.
+////////////////////////////////////////////////////////////////////
+INLINE const PfmFile &ProjectionScreen::
+get_undist_lut() const {
+  return _undist_lut;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ProjectionScreen::set_texcoord_name
 //     Function: ProjectionScreen::set_texcoord_name
 //       Access: Published
 //       Access: Published

+ 49 - 2
panda/src/distort/projectionScreen.cxx

@@ -39,6 +39,7 @@ ProjectionScreen(const string &name) : PandaNode(name)
 
 
   _texcoord_name = InternalName::get_texcoord();
   _texcoord_name = InternalName::get_texcoord();
 
 
+  _has_undist_lut = false;
   _invert_uvs = project_invert_uvs;
   _invert_uvs = project_invert_uvs;
   _texcoord_3d = false;
   _texcoord_3d = false;
   _vignette_on = false;
   _vignette_on = false;
@@ -214,7 +215,7 @@ generate_screen(const NodePath &projector, const string &screen_name,
   for (int yi = 0; yi < num_y_verts; yi++) {
   for (int yi = 0; yi < num_y_verts; yi++) {
     for (int xi = 0; xi < num_x_verts; xi++) {
     for (int xi = 0; xi < num_x_verts; xi++) {
       LPoint2 film = LPoint2((PN_stdfloat)xi * x_scale - 1.0f,
       LPoint2 film = LPoint2((PN_stdfloat)xi * x_scale - 1.0f,
-                               (PN_stdfloat)yi * y_scale - 1.0f);
+                             (PN_stdfloat)yi * y_scale - 1.0f);
       
       
       // Reduce the image by the fill ratio.
       // Reduce the image by the fill ratio.
       film *= fill_ratio;
       film *= fill_ratio;
@@ -590,6 +591,22 @@ recompute_geom(Geom *geom, const LMatrix4 &rel_mat) {
     // Now the lens gives us coordinates in the range [-1, 1].
     // Now the lens gives us coordinates in the range [-1, 1].
     // Rescale these to [0, 1].
     // Rescale these to [0, 1].
     LPoint3 uvw = film * to_uv;
     LPoint3 uvw = film * to_uv;
+
+    if (good && _has_undist_lut) {
+      int x_size = _undist_lut.get_x_size();
+      int y_size = _undist_lut.get_y_size();
+      
+      int dist_xi = (int)cfloor(uvw[0] * (PN_float32)x_size);
+      int dist_yi = (int)cfloor(uvw[1] * (PN_float32)y_size);
+      if (!_undist_lut.has_point(dist_xi, y_size - 1 - dist_yi)) {
+        // Point is missing.
+        uvw.set(0, 0, 0);
+        good = false;
+      } else {
+        uvw = _undist_lut.get_point(dist_xi, y_size - 1 - dist_yi);
+        uvw[1] = 1.0 - uvw[1];
+      }
+    }
     texcoord.set_data3(uvw);
     texcoord.set_data3(uvw);
     
     
     // If we have vignette color in effect, color the vertex according
     // If we have vignette color in effect, color the vertex according
@@ -722,6 +739,13 @@ make_mesh_geom_node(const WorkingNodePath &np, const NodePath &camera,
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 PT(Geom) ProjectionScreen::
 PT(Geom) ProjectionScreen::
 make_mesh_geom(const Geom *geom, Lens *lens, LMatrix4 &rel_mat) {
 make_mesh_geom(const Geom *geom, Lens *lens, LMatrix4 &rel_mat) {
+  static const LMatrix4 lens_to_uv
+    (0.5f, 0.0f, 0.0f, 0.0f,
+     0.0f, 0.5f, 0.0f, 0.0f, 
+     0.0f, 0.0f, 1.0f, 0.0f, 
+     0.5f, 0.5f, 0.0f, 1.0f);
+  static const LMatrix4 uv_to_lens = invert(lens_to_uv);
+
   Thread *current_thread = Thread::get_current_thread();
   Thread *current_thread = Thread::get_current_thread();
   PT(Geom) new_geom = geom->make_copy();
   PT(Geom) new_geom = geom->make_copy();
   PT(GeomVertexData) vdata = new_geom->modify_vertex_data();
   PT(GeomVertexData) vdata = new_geom->modify_vertex_data();
@@ -735,7 +759,30 @@ make_mesh_geom(const Geom *geom, Lens *lens, LMatrix4 &rel_mat) {
     // dimensions so the Z coordinate remains meaningful.
     // dimensions so the Z coordinate remains meaningful.
     LPoint3 vert3d = vert * rel_mat;
     LPoint3 vert3d = vert * rel_mat;
     LPoint3 film(0.0f, 0.0f, 0.0f);
     LPoint3 film(0.0f, 0.0f, 0.0f);
-    lens->project(vert3d, film);
+    bool good = lens->project(vert3d, film);
+
+    if (good && _has_undist_lut) {
+    
+      // Now the lens gives us coordinates in the range [-1, 1].
+      // Rescale these to [0, 1].
+      LPoint3 uvw = film * lens_to_uv;
+      
+      int x_size = _undist_lut.get_x_size();
+      int y_size = _undist_lut.get_y_size();
+      
+      int dist_xi = (int)cfloor(uvw[0] * (PN_float32)x_size);
+      int dist_yi = (int)cfloor(uvw[1] * (PN_float32)y_size);
+      if (!_undist_lut.has_point(dist_xi, y_size - 1 - dist_yi)) {
+        // Point is missing.
+        uvw.set(0, 0, 0);
+        good = false;
+      } else {
+        uvw = _undist_lut.get_point(dist_xi, y_size - 1 - dist_yi);
+        uvw[1] = 1.0 - uvw[1];
+      }
+
+      film = uvw * uv_to_lens;
+    }
 
 
     vertex.set_data3(film);
     vertex.set_data3(film);
   }      
   }      

+ 8 - 0
panda/src/distort/projectionScreen.h

@@ -23,6 +23,7 @@
 #include "nodePath.h"
 #include "nodePath.h"
 #include "internalName.h"
 #include "internalName.h"
 #include "pointerTo.h"
 #include "pointerTo.h"
+#include "pfmFile.h"
 
 
 class Geom;
 class Geom;
 class WorkingNodePath;
 class WorkingNodePath;
@@ -67,6 +68,11 @@ PUBLISHED:
   void set_projector(const NodePath &projector);
   void set_projector(const NodePath &projector);
   INLINE const NodePath &get_projector() const;
   INLINE const NodePath &get_projector() const;
 
 
+  INLINE void clear_undist_lut();
+  INLINE void set_undist_lut(const PfmFile &undist_lut);
+  INLINE bool has_undist_lut() const;
+  INLINE const PfmFile &get_undist_lut() const;
+
   PT(GeomNode) generate_screen(const NodePath &projector,
   PT(GeomNode) generate_screen(const NodePath &projector,
                                const string &screen_name,
                                const string &screen_name,
                                int num_x_verts, int num_y_verts,
                                int num_x_verts, int num_y_verts,
@@ -124,6 +130,8 @@ private:
 
 
   NodePath _projector;
   NodePath _projector;
   PT(LensNode) _projector_node;
   PT(LensNode) _projector_node;
+  bool _has_undist_lut;
+  PfmFile _undist_lut;
   PT(InternalName) _texcoord_name;
   PT(InternalName) _texcoord_name;
   bool _invert_uvs;
   bool _invert_uvs;
   bool _texcoord_3d;
   bool _texcoord_3d;

+ 10 - 0
panda/src/grutil/pfmVizzer.I

@@ -180,3 +180,13 @@ INLINE const PNMImage *PfmVizzer::
 get_vis_blend() const {
 get_vis_blend() const {
   return _vis_blend;
   return _vis_blend;
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: PfmVizzer::VisColumn::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE PfmVizzer::VisColumn::
+VisColumn() {
+  _undist_lut = NULL;
+}

+ 25 - 4
panda/src/grutil/pfmVizzer.cxx

@@ -230,8 +230,8 @@ clear_vis_columns() {
 void PfmVizzer::
 void PfmVizzer::
 add_vis_column(ColumnType source, ColumnType target,
 add_vis_column(ColumnType source, ColumnType target,
                InternalName *name, const TransformState *transform,
                InternalName *name, const TransformState *transform,
-               const Lens *lens) {
-  add_vis_column(_vis_columns, source, target, name, transform, lens);
+               const Lens *lens, const PfmFile *undist_lut) {
+  add_vis_column(_vis_columns, source, target, name, transform, lens, undist_lut);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -726,7 +726,7 @@ make_vis_mesh_geom(GeomNode *gnode, bool inverted) const {
 void PfmVizzer::
 void PfmVizzer::
 add_vis_column(VisColumns &vis_columns, ColumnType source, ColumnType target,
 add_vis_column(VisColumns &vis_columns, ColumnType source, ColumnType target,
                InternalName *name, const TransformState *transform,
                InternalName *name, const TransformState *transform,
-               const Lens *lens) {
+               const Lens *lens, const PfmFile *undist_lut) {
   VisColumn column;
   VisColumn column;
   column._source = source;
   column._source = source;
   column._target = target;
   column._target = target;
@@ -736,6 +736,9 @@ add_vis_column(VisColumns &vis_columns, ColumnType source, ColumnType target,
     column._transform = TransformState::make_identity();
     column._transform = TransformState::make_identity();
   }
   }
   column._lens = lens;
   column._lens = lens;
+  if (undist_lut != NULL && undist_lut->is_valid()) {
+    column._undist_lut = undist_lut;
+  }
   vis_columns.push_back(column);
   vis_columns.push_back(column);
 }
 }
 
 
@@ -986,10 +989,12 @@ add_data(const PfmVizzer &vizzer, GeomVertexWriter &vwriter, int xi, int yi, boo
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool PfmVizzer::VisColumn::
 bool PfmVizzer::VisColumn::
 transform_point(LPoint2f &point) const {
 transform_point(LPoint2f &point) const {
+  bool success = true;
   if (!_transform->is_identity()) {
   if (!_transform->is_identity()) {
     LCAST(PN_float32, _transform->get_mat3()).xform_point_in_place(point);
     LCAST(PN_float32, _transform->get_mat3()).xform_point_in_place(point);
   }
   }
-  return true;
+
+  return success;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1016,6 +1021,22 @@ transform_point(LPoint3f &point) const {
     point = to_uv.xform_point(LCAST(PN_float32, film));
     point = to_uv.xform_point(LCAST(PN_float32, film));
   }
   }
 
 
+  if (_undist_lut != NULL) {
+    int x_size = _undist_lut->get_x_size();
+    int y_size = _undist_lut->get_y_size();
+
+    int dist_xi = (int)cfloor(point[0] * (PN_float32)x_size);
+    int dist_yi = (int)cfloor(point[1] * (PN_float32)y_size);
+    if (!_undist_lut->has_point(dist_xi, y_size - 1 - dist_yi)) {
+      // Point is missing.
+      point.set(0, 0, 0);
+      success = false;
+    } else {
+      point = _undist_lut->get_point(dist_xi, y_size - 1 - dist_yi);
+      point[1] = 1.0 - point[1];
+    }
+  }
+
   return success;
   return success;
 }
 }
 
 

+ 6 - 2
panda/src/grutil/pfmVizzer.h

@@ -63,7 +63,8 @@ PUBLISHED:
   void clear_vis_columns();
   void clear_vis_columns();
   void add_vis_column(ColumnType source, ColumnType target,
   void add_vis_column(ColumnType source, ColumnType target,
                       InternalName *name, 
                       InternalName *name, 
-                      const TransformState *transform = NULL, const Lens *lens = NULL);
+                      const TransformState *transform = NULL, const Lens *lens = NULL,
+                      const PfmFile *undist_lut = NULL);
 
 
   BLOCKING NodePath generate_vis_points() const;
   BLOCKING NodePath generate_vis_points() const;
 
 
@@ -88,6 +89,7 @@ private:
 
 
   class VisColumn {
   class VisColumn {
   public:
   public:
+    INLINE VisColumn();
     bool add_data(const PfmVizzer &vizzer, GeomVertexWriter &vwriter, int xi, int yi, bool reverse_normals) const;
     bool add_data(const PfmVizzer &vizzer, GeomVertexWriter &vwriter, int xi, int yi, bool reverse_normals) const;
     bool transform_point(LPoint2f &point) const;
     bool transform_point(LPoint2f &point) const;
     bool transform_point(LPoint3f &point) const;
     bool transform_point(LPoint3f &point) const;
@@ -99,13 +101,15 @@ private:
     PT(InternalName) _name;
     PT(InternalName) _name;
     CPT(TransformState) _transform;
     CPT(TransformState) _transform;
     CPT(Lens) _lens;
     CPT(Lens) _lens;
+    const PfmFile *_undist_lut;
   };
   };
   typedef pvector<VisColumn> VisColumns;
   typedef pvector<VisColumn> VisColumns;
 
 
   static void add_vis_column(VisColumns &vis_columns, 
   static void add_vis_column(VisColumns &vis_columns, 
                              ColumnType source, ColumnType target,
                              ColumnType source, ColumnType target,
                              InternalName *name, 
                              InternalName *name, 
-                             const TransformState *transform = NULL, const Lens *lens = NULL);
+                             const TransformState *transform = NULL,
+                             const Lens *lens = NULL, const PfmFile *undist_lut = NULL);
   void build_auto_vis_columns(VisColumns &vis_columns, bool for_points) const;
   void build_auto_vis_columns(VisColumns &vis_columns, bool for_points) const;
   CPT(GeomVertexFormat) make_array_format(const VisColumns &vis_columns) const;
   CPT(GeomVertexFormat) make_array_format(const VisColumns &vis_columns) const;
 
 

+ 18 - 11
panda/src/pnmimage/pfmFile.cxx

@@ -79,7 +79,7 @@ clear() {
   _x_size = 0;
   _x_size = 0;
   _y_size = 0;
   _y_size = 0;
   _scale = 1.0;
   _scale = 1.0;
-  _num_channels = 3;
+  _num_channels = 0;
   _table.clear();
   _table.clear();
   clear_no_data_value();
   clear_no_data_value();
 }
 }
@@ -1044,6 +1044,11 @@ xform(const LMatrix4f &transform) {
 //               file at (x,y), where (x,y) is the point value from
 //               file at (x,y), where (x,y) is the point value from
 //               the dist map.
 //               the dist map.
 //
 //
+//               By convention, the y axis in inverted in the
+//               distortion map relative to the coordinates here.  A y
+//               value of 0 in the distortion map corresponds with a v
+//               value of 1 in this file.
+//
 //               If scale_factor is not 1, it should be a value > 1,
 //               If scale_factor is not 1, it should be a value > 1,
 //               and it specifies the factor to upscale the working
 //               and it specifies the factor to upscale the working
 //               table while processing, to reduce artifacts from
 //               table while processing, to reduce artifacts from
@@ -1091,16 +1096,11 @@ forward_distort(const PfmFile &dist, PN_float32 scale_factor) {
       LPoint2f uv = dist_p->get_point2(xi, yi);
       LPoint2f uv = dist_p->get_point2(xi, yi);
       int dist_xi = (int)cfloor(uv[0] * (PN_float32)working_x_size);
       int dist_xi = (int)cfloor(uv[0] * (PN_float32)working_x_size);
       int dist_yi = (int)cfloor(uv[1] * (PN_float32)working_y_size);
       int dist_yi = (int)cfloor(uv[1] * (PN_float32)working_y_size);
-      if (dist_xi < 0 || dist_xi >= working_x_size || 
-          dist_yi < 0 || dist_yi >= working_y_size) {
+      if (!source_p->has_point(dist_xi, working_y_size - 1 - dist_yi)) {
         continue;
         continue;
       }
       }
 
 
-      if (!source_p->has_point(dist_xi, dist_yi)) {
-        continue;
-      }
-
-      result.set_point(xi, yi, source_p->get_point(dist_xi, dist_yi));
+      result.set_point(xi, working_y_size - 1 - yi, source_p->get_point(dist_xi, working_y_size - 1 - dist_yi));
     }
     }
   }
   }
 
 
@@ -1122,6 +1122,11 @@ forward_distort(const PfmFile &dist, PN_float32 scale_factor) {
 //               file at (u,v), where (x,y) is the point value from
 //               file at (u,v), where (x,y) is the point value from
 //               the dist map.
 //               the dist map.
 //
 //
+//               By convention, the y axis in inverted in the
+//               distortion map relative to the coordinates here.  A y
+//               value of 0 in the distortion map corresponds with a v
+//               value of 1 in this file.
+//
 //               If scale_factor is not 1, it should be a value > 1,
 //               If scale_factor is not 1, it should be a value > 1,
 //               and it specifies the factor to upscale the working
 //               and it specifies the factor to upscale the working
 //               table while processing, to reduce artifacts from
 //               table while processing, to reduce artifacts from
@@ -1163,7 +1168,7 @@ reverse_distort(const PfmFile &dist, PN_float32 scale_factor) {
 
 
   for (int yi = 0; yi < working_y_size; ++yi) {
   for (int yi = 0; yi < working_y_size; ++yi) {
     for (int xi = 0; xi < working_x_size; ++xi) {
     for (int xi = 0; xi < working_x_size; ++xi) {
-      if (!source_p->has_point(xi, yi)) {
+      if (!source_p->has_point(xi, working_y_size - 1 - yi)) {
         continue;
         continue;
       }
       }
       if (!dist_p->has_point(xi, yi)) {
       if (!dist_p->has_point(xi, yi)) {
@@ -1177,11 +1182,13 @@ reverse_distort(const PfmFile &dist, PN_float32 scale_factor) {
         continue;
         continue;
       }
       }
 
 
-      if (!source_p->has_point(dist_xi, dist_yi)) {
+      /*
+      if (!source_p->has_point(dist_xi, working_y_size - 1 - dist_yi)) {
         continue;
         continue;
       }
       }
+      */
 
 
-      result.set_point(dist_xi, dist_yi, source_p->get_point(xi, yi));
+      result.set_point(dist_xi, working_y_size - 1 - dist_yi, source_p->get_point(xi, working_y_size - 1 - yi));
     }
     }
   }
   }