add undist_lut to ProjectionScreen, PfmVizzer

This commit is contained in:
David Rose 2013-04-11 14:41:46 +00:00
parent abf29fa3fe
commit a515048908
7 changed files with 168 additions and 19 deletions

View File

@ -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

View File

@ -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);
} }

View File

@ -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;

View File

@ -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;
}

View File

@ -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) { const Lens *lens, const PfmFile *undist_lut) {
add_vis_column(_vis_columns, source, target, name, transform, lens); 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;
} }

View File

@ -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;

View File

@ -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 || if (!source_p->has_point(dist_xi, working_y_size - 1 - dist_yi)) {
dist_yi < 0 || dist_yi >= working_y_size) {
continue; continue;
} }
if (!source_p->has_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));
continue;
}
result.set_point(xi, yi, source_p->get_point(dist_xi, 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));
} }
} }