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;
}
////////////////////////////////////////////////////////////////////
// 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
// Access: Published

View File

@ -39,6 +39,7 @@ ProjectionScreen(const string &name) : PandaNode(name)
_texcoord_name = InternalName::get_texcoord();
_has_undist_lut = false;
_invert_uvs = project_invert_uvs;
_texcoord_3d = 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 xi = 0; xi < num_x_verts; xi++) {
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.
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].
// Rescale these to [0, 1].
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);
// 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::
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();
PT(Geom) new_geom = geom->make_copy();
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.
LPoint3 vert3d = vert * rel_mat;
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);
}

View File

@ -23,6 +23,7 @@
#include "nodePath.h"
#include "internalName.h"
#include "pointerTo.h"
#include "pfmFile.h"
class Geom;
class WorkingNodePath;
@ -67,6 +68,11 @@ PUBLISHED:
void set_projector(const NodePath &projector);
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,
const string &screen_name,
int num_x_verts, int num_y_verts,
@ -124,6 +130,8 @@ private:
NodePath _projector;
PT(LensNode) _projector_node;
bool _has_undist_lut;
PfmFile _undist_lut;
PT(InternalName) _texcoord_name;
bool _invert_uvs;
bool _texcoord_3d;

View File

@ -180,3 +180,13 @@ INLINE const PNMImage *PfmVizzer::
get_vis_blend() const {
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::
add_vis_column(ColumnType source, ColumnType target,
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::
add_vis_column(VisColumns &vis_columns, ColumnType source, ColumnType target,
InternalName *name, const TransformState *transform,
const Lens *lens) {
const Lens *lens, const PfmFile *undist_lut) {
VisColumn column;
column._source = source;
column._target = target;
@ -736,6 +736,9 @@ add_vis_column(VisColumns &vis_columns, ColumnType source, ColumnType target,
column._transform = TransformState::make_identity();
}
column._lens = lens;
if (undist_lut != NULL && undist_lut->is_valid()) {
column._undist_lut = undist_lut;
}
vis_columns.push_back(column);
}
@ -986,10 +989,12 @@ add_data(const PfmVizzer &vizzer, GeomVertexWriter &vwriter, int xi, int yi, boo
////////////////////////////////////////////////////////////////////
bool PfmVizzer::VisColumn::
transform_point(LPoint2f &point) const {
bool success = true;
if (!_transform->is_identity()) {
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));
}
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;
}

View File

@ -63,7 +63,8 @@ PUBLISHED:
void clear_vis_columns();
void add_vis_column(ColumnType source, ColumnType target,
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;
@ -88,6 +89,7 @@ private:
class VisColumn {
public:
INLINE VisColumn();
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(LPoint3f &point) const;
@ -99,13 +101,15 @@ private:
PT(InternalName) _name;
CPT(TransformState) _transform;
CPT(Lens) _lens;
const PfmFile *_undist_lut;
};
typedef pvector<VisColumn> VisColumns;
static void add_vis_column(VisColumns &vis_columns,
ColumnType source, ColumnType target,
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;
CPT(GeomVertexFormat) make_array_format(const VisColumns &vis_columns) const;

View File

@ -79,7 +79,7 @@ clear() {
_x_size = 0;
_y_size = 0;
_scale = 1.0;
_num_channels = 3;
_num_channels = 0;
_table.clear();
clear_no_data_value();
}
@ -1044,6 +1044,11 @@ xform(const LMatrix4f &transform) {
// file at (x,y), where (x,y) is the point value from
// 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,
// and it specifies the factor to upscale the working
// 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);
int dist_xi = (int)cfloor(uv[0] * (PN_float32)working_x_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;
}
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
// 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,
// and it specifies the factor to upscale the working
// 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 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;
}
if (!dist_p->has_point(xi, yi)) {
@ -1177,11 +1182,13 @@ reverse_distort(const PfmFile &dist, PN_float32 scale_factor) {
continue;
}
if (!source_p->has_point(dist_xi, dist_yi)) {
/*
if (!source_p->has_point(dist_xi, working_y_size - 1 - dist_yi)) {
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));
}
}