diff --git a/panda/src/grutil/pfmVizzer.I b/panda/src/grutil/pfmVizzer.I index 26446a257f..d392379ecb 100644 --- a/panda/src/grutil/pfmVizzer.I +++ b/panda/src/grutil/pfmVizzer.I @@ -17,7 +17,7 @@ // Function: PfmVizzer::get_pfm // Access: Published // Description: Returns the reference to the PfmFile manipulated by -// thiz PfmVizzer. +// this PfmVizzer. //////////////////////////////////////////////////////////////////// INLINE PfmFile &PfmVizzer:: get_pfm() { @@ -28,7 +28,7 @@ get_pfm() { // Function: PfmVizzer::get_pfm // Access: Published // Description: Returns the reference to the PfmFile manipulated by -// thiz PfmVizzer. +// this PfmVizzer. //////////////////////////////////////////////////////////////////// INLINE const PfmFile &PfmVizzer:: get_pfm() const { @@ -206,6 +206,49 @@ get_vis_blend() const { return _vis_blend; } +//////////////////////////////////////////////////////////////////// +// Function: PfmVizzer::set_aux_pfm +// Access: Published +// Description: Assigns an auxiliary PfmFile to this PfmVizzer. This +// file will be queried by column types +// CT_aux_vertex1/2/3, but has no other meaning to the +// vizzer. This size of this PfmFile should exactly +// match the base PfmFile. No reference count is held +// and no copy is made; the caller is responsible for +// ensuring that the auxiliary PfmFile will persist +// throughout the lifetime of the PfmVizzer it is +// assigned to. +//////////////////////////////////////////////////////////////////// +INLINE void PfmVizzer:: +set_aux_pfm(const PfmFile *pfm) { + assert(pfm == NULL || (pfm->get_x_size() == _pfm.get_x_size() && + pfm->get_y_size() == _pfm.get_y_size())); + _aux_pfm = pfm; +} + +//////////////////////////////////////////////////////////////////// +// Function: PfmVizzer::clear_aux_pfm +// Access: Published +// Description: Removes the auxiliary PfmFile from this PfmVizzer. +//////////////////////////////////////////////////////////////////// +INLINE void PfmVizzer:: +clear_aux_pfm() { + _aux_pfm = NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: PfmVizzer::get_aux_pfm +// Access: Published +// Description: Returns the reference to the auxiliary PfmFile +// queried by this PfmVizzer. This contains the values +// that will be reflected in CT_aux_vertex3 etc. See +// set_aux_pfm(). +//////////////////////////////////////////////////////////////////// +INLINE const PfmFile *PfmVizzer:: +get_aux_pfm() const { + return _aux_pfm; +} + //////////////////////////////////////////////////////////////////// // Function: PfmVizzer::VisColumn::Constructor // Access: Public diff --git a/panda/src/grutil/pfmVizzer.cxx b/panda/src/grutil/pfmVizzer.cxx index 3033af5845..dfd0f50399 100644 --- a/panda/src/grutil/pfmVizzer.cxx +++ b/panda/src/grutil/pfmVizzer.cxx @@ -38,6 +38,7 @@ PfmVizzer(PfmFile &pfm) : _pfm(pfm) { _vis_2d = false; _keep_beyond_lens = false; _vis_blend = NULL; + _aux_pfm = NULL; } //////////////////////////////////////////////////////////////////// @@ -253,6 +254,9 @@ NodePath PfmVizzer:: generate_vis_points() const { nassertr(_pfm.is_valid(), NodePath()); + bool check_aux_pfm = uses_aux_pfm(); + nassertr(!check_aux_pfm || (_aux_pfm != NULL && _aux_pfm->is_valid()), NodePath()); + CPT(GeomVertexFormat) format; if (_vis_inverse) { if (_vis_2d) { @@ -291,6 +295,9 @@ generate_vis_points() const { if (!_pfm.has_point(xi, yi)) { continue; } + if (check_aux_pfm && !_aux_pfm->has_point(xi, yi)) { + continue; + } const LPoint3f &point = _pfm.get_point(xi, yi); LPoint2f uv((PN_float32(xi) + 0.5) * uv_scale[0], @@ -330,6 +337,8 @@ generate_vis_points() const { NodePath PfmVizzer:: generate_vis_mesh(MeshFace face) const { nassertr(_pfm.is_valid(), NodePath()); + bool check_aux_pfm = uses_aux_pfm(); + nassertr(!check_aux_pfm || (_aux_pfm != NULL && _aux_pfm->is_valid()), NodePath()); nassertr(face != 0, NodePath()); if (_pfm.get_num_channels() == 1 && _vis_columns.empty()) { @@ -512,6 +521,31 @@ make_displacement(PNMImage &result, double max_u, double max_v) const { } } +//////////////////////////////////////////////////////////////////// +// Function: PfmVizzer::uses_aux_pfm +// Access: Private +// Description: Returns true if any of the vis_column tokens +// reference the aux_pfm file, false otherwise. +//////////////////////////////////////////////////////////////////// +bool PfmVizzer:: +uses_aux_pfm() const { + for (VisColumns::const_iterator vci = _vis_columns.begin(); + vci != _vis_columns.end(); + ++vci) { + const VisColumn &column = *vci; + switch (column._source) { + case CT_aux_vertex1: + case CT_aux_vertex2: + case CT_aux_vertex3: + return true; + default: + break; + } + } + + return false; +} + //////////////////////////////////////////////////////////////////// // Function: PfmVizzer::r_fill_displacement // Access: Private @@ -616,6 +650,7 @@ make_vis_mesh_geom(GeomNode *gnode, bool inverted) const { if (vis_columns.empty()) { build_auto_vis_columns(vis_columns, true); } + bool check_aux_pfm = uses_aux_pfm(); CPT(GeomVertexFormat) format = make_array_format(vis_columns); @@ -685,7 +720,13 @@ make_vis_mesh_geom(GeomNode *gnode, bool inverted) const { !_pfm.has_point(xi + 1, yi)) { continue; } - + if (check_aux_pfm && (!_aux_pfm->has_point(xi, yi) || + !_aux_pfm->has_point(xi, yi + 1) || + !_aux_pfm->has_point(xi + 1, yi + 1) || + !_aux_pfm->has_point(xi + 1, yi))) { + continue; + } + if (!keep_beyond_lens && (skip_points[(yi - y_begin) * x_size + (xi - x_begin)] || skip_points[(yi - y_begin + 1) * x_size + (xi - x_begin)] || @@ -833,18 +874,21 @@ make_array_format(const VisColumns &vis_columns) const { break; case CT_vertex1: + case CT_aux_vertex1: num_components = 1; numeric_type = GeomEnums::NT_float32; contents = GeomEnums::C_point; break; case CT_vertex2: + case CT_aux_vertex2: num_components = 2; numeric_type = GeomEnums::NT_float32; contents = GeomEnums::C_point; break; case CT_vertex3: + case CT_aux_vertex3: num_components = 3; numeric_type = GeomEnums::NT_float32; contents = GeomEnums::C_point; @@ -917,6 +961,18 @@ add_data(const PfmVizzer &vizzer, GeomVertexWriter &vwriter, int xi, int yi, boo } break; + case CT_aux_vertex1: + { + nassertr(vizzer.get_aux_pfm() != NULL, false); + PN_float32 p = vizzer.get_aux_pfm()->get_point1(xi, yi); + LPoint2f point(p, 0.0); + if (!transform_point(point)) { + success = false; + } + vwriter.set_data2f(point); + } + break; + case CT_vertex2: { LPoint2f point = pfm.get_point2(xi, yi); @@ -927,6 +983,17 @@ add_data(const PfmVizzer &vizzer, GeomVertexWriter &vwriter, int xi, int yi, boo } break; + case CT_aux_vertex2: + { + nassertr(vizzer.get_aux_pfm() != NULL, false); + LPoint2f point = vizzer.get_aux_pfm()->get_point2(xi, yi); + if (!transform_point(point)) { + success = false; + } + vwriter.set_data2f(point); + } + break; + case CT_vertex3: { LPoint3f point = pfm.get_point(xi, yi); @@ -937,6 +1004,16 @@ add_data(const PfmVizzer &vizzer, GeomVertexWriter &vwriter, int xi, int yi, boo } break; + case CT_aux_vertex3: + { + LPoint3f point = vizzer.get_aux_pfm()->get_point(xi, yi); + if (!transform_point(point)) { + success = false; + } + vwriter.set_data3f(point); + } + break; + case CT_normal3: { // Calculate the normal based on two neighboring vertices. diff --git a/panda/src/grutil/pfmVizzer.h b/panda/src/grutil/pfmVizzer.h index 551606755e..2d20b4d1d6 100644 --- a/panda/src/grutil/pfmVizzer.h +++ b/panda/src/grutil/pfmVizzer.h @@ -53,6 +53,10 @@ PUBLISHED: INLINE void clear_vis_blend(); INLINE const PNMImage *get_vis_blend() const; + INLINE void set_aux_pfm(const PfmFile *pfm); + INLINE void clear_aux_pfm(); + INLINE const PfmFile *get_aux_pfm() const; + enum ColumnType { CT_texcoord2, CT_texcoord3, @@ -61,6 +65,9 @@ PUBLISHED: CT_vertex3, CT_normal3, CT_blend1, + CT_aux_vertex1, + CT_aux_vertex2, + CT_aux_vertex3, }; void clear_vis_columns(); void add_vis_column(ColumnType source, ColumnType target, @@ -82,6 +89,7 @@ PUBLISHED: BLOCKING void make_displacement(PNMImage &result, double max_u, double max_v) const; private: + bool uses_aux_pfm() const; void r_fill_displacement(PNMImage &result, int xi, int yi, double nxi, double nyi, double u_scale, double v_scale, int distance) const; @@ -117,6 +125,7 @@ private: private: PfmFile &_pfm; + const PfmFile *_aux_pfm; bool _vis_inverse; PT(InternalName) _flat_texcoord_name; diff --git a/panda/src/pnmimage/pfmFile.I b/panda/src/pnmimage/pfmFile.I index d53bd44523..928677ca65 100644 --- a/panda/src/pnmimage/pfmFile.I +++ b/panda/src/pnmimage/pfmFile.I @@ -478,6 +478,7 @@ INLINE void PfmFile:: set_no_data_chan4(bool chan4) { if (chan4 && _num_channels == 4) { _has_no_data_value = true; + _has_no_data_threshold = false; _no_data_value.set(0.0, 0.0, 0.0, -1.0); _has_point = has_point_chan4; } else { @@ -496,6 +497,18 @@ set_no_data_value(const LPoint4d &no_data_value) { set_no_data_value(LCAST(PN_float32, no_data_value)); } +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::set_no_data_threshold +// Access: Published +// Description: Sets the special threshold value. Points that are +// below this value in all components are considered "no +// value". +//////////////////////////////////////////////////////////////////// +INLINE void PfmFile:: +set_no_data_threshold(const LPoint4d &no_data_threshold) { + set_no_data_threshold(LCAST(PN_float32, no_data_threshold)); +} + //////////////////////////////////////////////////////////////////// // Function: PfmFile::set_no_data_value // Access: Published @@ -506,6 +519,7 @@ set_no_data_value(const LPoint4d &no_data_value) { INLINE void PfmFile:: clear_no_data_value() { _has_no_data_value = false; + _has_no_data_threshold = false; _no_data_value = LPoint4f::zero(); _has_point = has_point_noop; } @@ -521,6 +535,17 @@ has_no_data_value() const { return _has_no_data_value; } +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::has_no_data_threshold +// Access: Published +// Description: Returns whether a "no data" threshold value has been +// established by set_no_data_threshold(). +//////////////////////////////////////////////////////////////////// +INLINE bool PfmFile:: +has_no_data_threshold() const { + return _has_no_data_threshold; +} + //////////////////////////////////////////////////////////////////// // Function: PfmFile::get_no_data_value // Access: Published diff --git a/panda/src/pnmimage/pfmFile.cxx b/panda/src/pnmimage/pfmFile.cxx index 06e13106bd..bae7793e45 100644 --- a/panda/src/pnmimage/pfmFile.cxx +++ b/panda/src/pnmimage/pfmFile.cxx @@ -33,6 +33,7 @@ PfmFile:: PfmFile() { _has_no_data_value = false; + _has_no_data_threshold = false; _no_data_value = LPoint4f::zero(); _has_point = has_point_noop; clear(); @@ -49,6 +50,7 @@ PfmFile(const PfmFile ©) : _table(copy._table), _scale(copy._scale), _has_no_data_value(copy._has_no_data_value), + _has_no_data_threshold(copy._has_no_data_threshold), _no_data_value(copy._no_data_value), _has_point(copy._has_point) { @@ -65,6 +67,7 @@ operator = (const PfmFile ©) { _table = copy._table; _scale = copy._scale; _has_no_data_value = copy._has_no_data_value; + _has_no_data_threshold = copy._has_no_data_threshold; _no_data_value = copy._no_data_value; _has_point = copy._has_point; } @@ -908,6 +911,7 @@ set_no_data_nan(int num_channels) { if (num_channels > 0) { num_channels = min(num_channels, _num_channels); _has_no_data_value = true; + _has_no_data_threshold = false; _no_data_value = LPoint4f::zero(); PN_float32 nan = make_nan((PN_float32)0.0); for (int i = 0; i < num_channels; ++i) { @@ -945,6 +949,7 @@ set_no_data_value(const LPoint4f &no_data_value) { nassertv(is_valid()); _has_no_data_value = true; + _has_no_data_threshold = false; _no_data_value = no_data_value; switch (_num_channels) { case 1: @@ -964,6 +969,38 @@ set_no_data_value(const LPoint4f &no_data_value) { } } +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::set_no_data_threshold +// Access: Published +// Description: Sets the special threshold value. Points that are +// below this value in all components are considered "no +// value". +//////////////////////////////////////////////////////////////////// +void PfmFile:: +set_no_data_threshold(const LPoint4f &no_data_value) { + nassertv(is_valid()); + + _has_no_data_value = true; + _has_no_data_threshold = true; + _no_data_value = no_data_value; + switch (_num_channels) { + case 1: + _has_point = has_point_threshold_1; + break; + case 2: + _has_point = has_point_threshold_2; + break; + case 3: + _has_point = has_point_threshold_3; + break; + case 4: + _has_point = has_point_threshold_4; + break; + default: + nassertv(false); + } +} + //////////////////////////////////////////////////////////////////// // Function: PfmFile::resize // Access: Published @@ -2395,6 +2432,76 @@ has_point_4(const PfmFile *self, int x, int y) { return false; } +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::has_point_threshold_1 +// Access: Private, Static +// Description: The implementation of has_point_threshold() for 1-component +// files with a no_data_value. +//////////////////////////////////////////////////////////////////// +bool PfmFile:: +has_point_threshold_1(const PfmFile *self, int x, int y) { + if ((x >= 0 && x < self->_x_size) && + (y >= 0 && y < self->_y_size)) { + const float *table = &self->_table[(y * self->_x_size + x)]; + return table[0] >= self->_no_data_value[0]; + } + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::has_point_threshold_2 +// Access: Private, Static +// Description: The implementation of has_point_threshold() for 2-component +// files with a no_data_value. +//////////////////////////////////////////////////////////////////// +bool PfmFile:: +has_point_threshold_2(const PfmFile *self, int x, int y) { + if ((x >= 0 && x < self->_x_size) && + (y >= 0 && y < self->_y_size)) { + const float *table = &self->_table[(y * self->_x_size + x) * 2]; + return (table[0] >= self->_no_data_value[0] || + table[1] >= self->_no_data_value[1]); + } + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::has_point_threshold_3 +// Access: Private, Static +// Description: The implementation of has_point_threshold() for 3-component +// files with a no_data_value. +//////////////////////////////////////////////////////////////////// +bool PfmFile:: +has_point_threshold_3(const PfmFile *self, int x, int y) { + if ((x >= 0 && x < self->_x_size) && + (y >= 0 && y < self->_y_size)) { + const float *table = &self->_table[(y * self->_x_size + x) * 3]; + return (table[0] >= self->_no_data_value[0] || + table[1] >= self->_no_data_value[1] || + table[2] >= self->_no_data_value[2]); + } + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: PfmFile::has_point_threshold_4 +// Access: Private, Static +// Description: The implementation of has_point_threshold() for 4-component +// files with a no_data_value. +//////////////////////////////////////////////////////////////////// +bool PfmFile:: +has_point_threshold_4(const PfmFile *self, int x, int y) { + if ((x >= 0 && x < self->_x_size) && + (y >= 0 && y < self->_y_size)) { + const float *table = &self->_table[(y * self->_x_size + x) * 4]; + return (table[0] >= self->_no_data_value[0] || + table[1] >= self->_no_data_value[1] || + table[2] >= self->_no_data_value[2] || + table[3] >= self->_no_data_value[3]); + } + return false; +} + //////////////////////////////////////////////////////////////////// // Function: PfmFile::has_point_chan4 // Access: Private, Static diff --git a/panda/src/pnmimage/pfmFile.h b/panda/src/pnmimage/pfmFile.h index 7f22ef79c0..3cf0a5d1c0 100644 --- a/panda/src/pnmimage/pfmFile.h +++ b/panda/src/pnmimage/pfmFile.h @@ -104,8 +104,11 @@ PUBLISHED: void set_no_data_nan(int num_channels); void set_no_data_value(const LPoint4f &no_data_value); INLINE void set_no_data_value(const LPoint4d &no_data_value); + void set_no_data_threshold(const LPoint4f &no_data_value); + INLINE void set_no_data_threshold(const LPoint4d &no_data_value); INLINE void clear_no_data_value(); INLINE bool has_no_data_value() const; + INLINE bool has_no_data_threshold() const; INLINE const LPoint4f &get_no_data_value() const; BLOCKING void resize(int new_x_size, int new_y_size); @@ -195,6 +198,10 @@ private: static bool has_point_2(const PfmFile *file, int x, int y); static bool has_point_3(const PfmFile *file, int x, int y); static bool has_point_4(const PfmFile *file, int x, int y); + static bool has_point_threshold_1(const PfmFile *file, int x, int y); + static bool has_point_threshold_2(const PfmFile *file, int x, int y); + static bool has_point_threshold_3(const PfmFile *file, int x, int y); + static bool has_point_threshold_4(const PfmFile *file, int x, int y); static bool has_point_chan4(const PfmFile *file, int x, int y); static bool has_point_nan_1(const PfmFile *file, int x, int y); static bool has_point_nan_2(const PfmFile *file, int x, int y); @@ -208,6 +215,7 @@ private: PN_float32 _scale; bool _has_no_data_value; + bool _has_no_data_threshold; LPoint4f _no_data_value; typedef bool HasPointFunc(const PfmFile *file, int x, int y);