some more texture/pfm integration

This commit is contained in:
David Rose 2012-08-12 17:56:56 +00:00
parent 7ba693137c
commit 2ff43ca88e
6 changed files with 250 additions and 9 deletions

View File

@ -315,6 +315,42 @@ load(const PNMImage &pnmimage, int z, int n, const LoaderOptions &options) {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: Texture::load
// Access: Published
// Description: Replaces the texture with the indicated image.
////////////////////////////////////////////////////////////////////
INLINE bool Texture::
load(const PfmFile &pfm, const LoaderOptions &options) {
CDWriter cdata(_cycler, true);
do_clear(cdata);
++(cdata->_properties_modified);
++(cdata->_image_modified);
if (do_load_one(cdata, pfm, get_name(), 0, 0, options)) {
bool generate_mipmaps = ((options.get_texture_flags() & LoaderOptions::TF_generate_mipmaps) != 0);
consider_auto_process_ram_image(generate_mipmaps || uses_mipmaps(), true);
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: Texture::load
// Access: Published
// Description: Stores the indicated image in the given page and
// mipmap level. See read().
////////////////////////////////////////////////////////////////////
INLINE bool Texture::
load(const PfmFile &pfm, int z, int n, const LoaderOptions &options) {
CDWriter cdata(_cycler, true);
++(cdata->_properties_modified);
++(cdata->_image_modified);
if (do_load_one(cdata, pfm, get_name(), z, n, options)) {
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: Texture::store
// Access: Published
@ -339,6 +375,30 @@ store(PNMImage &pnmimage, int z, int n) const {
return ((Texture *)this)->do_store_one(cdata, pnmimage, z, n);
}
////////////////////////////////////////////////////////////////////
// Function: Texture::store
// Access: Published
// Description: Saves the texture to the indicated PfmFile, but does
// not write it to disk.
////////////////////////////////////////////////////////////////////
INLINE bool Texture::
store(PfmFile &pfm) const {
CDWriter cdata(((Texture *)this)->_cycler, false);
return ((Texture *)this)->do_store_one(cdata, pfm, 0, 0);
}
////////////////////////////////////////////////////////////////////
// Function: Texture::store
// Access: Published
// Description: Saves the indicated page and mipmap level of the
// texture to the PfmFile.
////////////////////////////////////////////////////////////////////
INLINE bool Texture::
store(PfmFile &pfm, int z, int n) const {
CDWriter cdata(((Texture *)this)->_cycler, false);
return ((Texture *)this)->do_store_one(cdata, pfm, z, n);
}
////////////////////////////////////////////////////////////////////
// Function: Texture::reload
// Access: Published

View File

@ -2924,10 +2924,8 @@ do_read_one(CData *cdata, const Filename &fullpath, const Filename &alpha_fullpa
}
image.copy_header_from(*image_reader);
// If it's a single-channel floating-point image file, read it by
// default into a floating-point texture. (Multi-channel image
// files are ready as integers by default, since current graphics
// API's don't support multi-channel float textures.)
// If it's a floating-point image file, read it by default into a
// floating-point texture.
bool read_floating_point;
int texture_load_type = (options.get_texture_flags() & (LoaderOptions::TF_integer | LoaderOptions::TF_float));
switch (texture_load_type) {
@ -2942,7 +2940,7 @@ do_read_one(CData *cdata, const Filename &fullpath, const Filename &alpha_fullpa
default:
// Neither TF_integer nor TF_float was specified; determine which
// way the texture wants to be loaded.
read_floating_point = (image_reader->is_floating_point() && image_reader->get_num_channels() == 1);
read_floating_point = (image_reader->is_floating_point());
if (!alpha_fullpath.empty()) {
read_floating_point = false;
}
@ -3843,6 +3841,21 @@ do_store_one(CData *cdata, PNMImage &pnmimage, int z, int n) {
nassertr(z >= 0 && z < do_get_expected_mipmap_num_pages(cdata, n), false);
nassertr(cdata->_ram_image_compression == CM_off, false);
if (cdata->_component_type == T_float) {
// PNMImage by way of PfmFile.
PfmFile pfm;
bool success = convert_to_pfm(pfm,
do_get_expected_mipmap_x_size(cdata, n),
do_get_expected_mipmap_y_size(cdata, n),
cdata->_num_components, cdata->_component_width,
cdata->_ram_images[n]._image,
do_get_ram_mipmap_page_size(cdata, n), z);
if (!success) {
return false;
}
return pfm.store(pnmimage);
}
return convert_to_pnmimage(pnmimage,
do_get_expected_mipmap_x_size(cdata, n),
do_get_expected_mipmap_y_size(cdata, n),
@ -3869,6 +3882,21 @@ do_store_one(CData *cdata, PfmFile &pfm, int z, int n) {
nassertr(z >= 0 && z < do_get_expected_mipmap_num_pages(cdata, n), false);
nassertr(cdata->_ram_image_compression == CM_off, false);
if (cdata->_component_type != T_float) {
// PfmFile by way of PNMImage.
PNMImage pnmimage;
bool success = convert_to_pnmimage(pnmimage,
do_get_expected_mipmap_x_size(cdata, n),
do_get_expected_mipmap_y_size(cdata, n),
cdata->_num_components, cdata->_component_width,
cdata->_ram_images[n]._image,
do_get_ram_mipmap_page_size(cdata, n), z);
if (!success) {
return false;
}
return pfm.load(pnmimage);
}
return convert_to_pfm(pfm,
do_get_expected_mipmap_x_size(cdata, n),
do_get_expected_mipmap_y_size(cdata, n),
@ -5901,7 +5929,11 @@ bool Texture::
convert_to_pnmimage(PNMImage &pnmimage, int x_size, int y_size,
int num_components, int component_width,
CPTA_uchar image, size_t page_size, int z) {
pnmimage.clear(x_size, y_size, num_components);
xelval maxval = 0xff;
if (component_width > 1) {
maxval = 0xffff;
}
pnmimage.clear(x_size, y_size, num_components, maxval);
bool has_alpha = pnmimage.has_alpha();
bool is_grayscale = pnmimage.is_grayscale();

View File

@ -260,8 +260,12 @@ PUBLISHED:
BLOCKING INLINE bool load(const PNMImage &pnmimage, const LoaderOptions &options = LoaderOptions());
BLOCKING INLINE bool load(const PNMImage &pnmimage, int z, int n, const LoaderOptions &options = LoaderOptions());
BLOCKING INLINE bool load(const PfmFile &pfm, const LoaderOptions &options = LoaderOptions());
BLOCKING INLINE bool load(const PfmFile &pfm, int z, int n, const LoaderOptions &options = LoaderOptions());
BLOCKING INLINE bool store(PNMImage &pnmimage) const;
BLOCKING INLINE bool store(PNMImage &pnmimage, int z, int n) const;
BLOCKING INLINE bool store(PfmFile &pfm) const;
BLOCKING INLINE bool store(PfmFile &pfm, int z, int n) const;
BLOCKING INLINE bool reload();
BLOCKING Texture *load_related(const InternalName *suffix) const;

View File

@ -113,6 +113,76 @@ set_point1(int x, int y, PN_float32 point) {
_table[(y * _x_size + x) * _num_channels] = point;
}
////////////////////////////////////////////////////////////////////
// Function: PfmFile::get_point2
// Access: Published
// Description: Returns the 2-component point value at the indicated
// point. In a 1-channel image, the channel value is in
// the x component.
////////////////////////////////////////////////////////////////////
INLINE const LPoint2f &PfmFile::
get_point2(int x, int y) const {
nassertr(x >= 0 && x < _x_size &&
y >= 0 && y < _y_size, LPoint2f::zero());
return *(LPoint2f *)&_table[(y * _x_size + x) * _num_channels];
}
////////////////////////////////////////////////////////////////////
// Function: PfmFile::set_point2
// Access: Published
// Description: Replaces the 2-component point value at the indicated
// point. In a 1-channel image, the channel value is in
// the x component.
////////////////////////////////////////////////////////////////////
INLINE void PfmFile::
set_point2(int x, int y, const LVecBase2f &point) {
nassertv(!point.is_nan());
nassertv(x >= 0 && x < _x_size &&
y >= 0 && y < _y_size);
switch (_num_channels) {
case 1:
_table[(y * _x_size + x)] = point[0];
break;
case 3:
(*(LPoint3f *)&_table[(y * _x_size + x) * _num_channels]).set(point[0], point[1], point[2]);
break;
case 2:
*(LPoint2f *)&_table[(y * _x_size + x) * _num_channels] = point;
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: PfmFile::set_point2
// Access: Published
// Description: Replaces the 2-component point value at the indicated
// point. In a 1-channel image, the channel value is in
// the x component.
////////////////////////////////////////////////////////////////////
INLINE void PfmFile::
set_point2(int x, int y, const LVecBase2d &point) {
set_point2(x, y, LCAST(PN_float32, point));
}
////////////////////////////////////////////////////////////////////
// Function: PfmFile::modify_point2
// Access: Published
// Description: Returns a modifiable 2-component point value at the
// indicated point.
////////////////////////////////////////////////////////////////////
INLINE LPoint2f &PfmFile::
modify_point2(int x, int y) {
#ifndef NDEBUG
static LPoint2f dummy_value = LPoint2f::zero();
nassertr(x >= 0 && x < _x_size &&
y >= 0 && y < _y_size, dummy_value);
#endif
return *(LPoint2f *)&_table[(y * _x_size + x) * _num_channels];
}
////////////////////////////////////////////////////////////////////
// Function: PfmFile::get_point
// Access: Published

View File

@ -993,6 +993,27 @@ merge(const PfmFile &other) {
}
}
////////////////////////////////////////////////////////////////////
// Function: PfmFile::copy_channel
// Access: Published
// Description: Copies just the specified channel values from the
// indicated PfmFile (which could be same as this
// PfmFile) into the specified channel of this one.
////////////////////////////////////////////////////////////////////
void PfmFile::
copy_channel(int to_channel, const PfmFile &other, int from_channel) {
nassertv(is_valid() && other.is_valid());
nassertv(other._x_size == _x_size && other._y_size == _y_size);
nassertv(to_channel >= 0 && to_channel < get_num_channels() &&
from_channel >= 0 && from_channel < other.get_num_channels());
for (int yi = 0; yi < _y_size; ++yi) {
for (int xi = 0; xi < _x_size; ++xi) {
set_component(xi, yi, to_channel, other.get_component(xi, yi, from_channel));
}
}
}
////////////////////////////////////////////////////////////////////
// Function: PfmFile::apply_crop
// Access: Published
@ -1027,6 +1048,34 @@ apply_crop(int x_begin, int x_end, int y_begin, int y_end) {
_y_size = new_y_size;
}
////////////////////////////////////////////////////////////////////
// Function: PfmFile::clear_to_texcoords
// Access: Published
// Description: Replaces this PfmFile with a new PfmFile of size
// x_size x y_size x 3, containing the x y 0 values in
// the range 0 .. 1 according to the x y index.
////////////////////////////////////////////////////////////////////
void PfmFile::
clear_to_texcoords(int x_size, int y_size) {
clear(x_size, y_size, 3);
LPoint2f uv_scale(1.0, 1.0);
if (_x_size > 1) {
uv_scale[0] = 1.0f / PN_float32(_x_size - 1);
}
if (_y_size > 1) {
uv_scale[1] = 1.0f / PN_float32(_y_size - 1);
}
for (int yi = 0; yi < _y_size; ++yi) {
for (int xi = 0; xi < _x_size; ++xi) {
LPoint3f uv(PN_float32(xi) * uv_scale[0],
PN_float32(yi) * uv_scale[1], 0.0f);
set_point(xi, yi, uv);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: PfmFile::compute_planar_bounds
// Access: Published
@ -1366,6 +1415,16 @@ generate_vis_mesh(MeshFace face) const {
nassertr(is_valid(), NodePath());
nassertr(face != 0, NodePath());
if (_num_channels == 1 && _vis_columns.empty()) {
// If we're generating a default mesh from a one-channel pfm file,
// expand it to a three-channel pfm file to make the visualization
// useful.
PfmFile expanded;
expanded.clear_to_texcoords(_x_size, _y_size);
expanded.copy_channel(2, *this, 0);
return expanded.generate_vis_mesh(face);
}
if (_x_size == 1 || _y_size == 1) {
// Can't generate a 1-d mesh, so generate points in this case.
return generate_vis_points();
@ -1864,7 +1923,7 @@ build_auto_vis_columns(VisColumns &vis_columns, bool for_points) const {
if (_vis_2d) {
// No normals needed if we're just generating a 2-d mesh.
add_vis_column(vis_columns, CT_vertex3, CT_vertex3, InternalName::get_vertex());
add_vis_column(vis_columns, CT_vertex2, CT_vertex2, InternalName::get_vertex());
add_vis_column(vis_columns, CT_texcoord2, CT_texcoord2, InternalName::get_texcoord());
} else {
@ -1920,6 +1979,7 @@ make_array_format(const VisColumns &vis_columns) const {
contents = GeomEnums::C_texcoord;
break;
case CT_vertex1:
case CT_vertex2:
case CT_vertex3:
num_components = 3;
@ -2069,10 +2129,18 @@ add_data(const PfmFile &file, GeomVertexWriter &vwriter, int xi, int yi, bool re
}
break;
case CT_vertex1:
{
PN_float32 p = file.get_point1(xi, yi);
LPoint2f point(p, 0.0);
transform_point(point);
vwriter.set_data2f(point);
}
break;
case CT_vertex2:
{
const LPoint3f &point3 = file.get_point(xi, yi);
LPoint2f point(point3[0], point3[1]);
LPoint2f point = file.get_point2(xi, yi);
transform_point(point);
vwriter.set_data2f(point);
}

View File

@ -65,6 +65,10 @@ PUBLISHED:
INLINE void set_component(int x, int y, int c, PN_float32 value);
INLINE PN_float32 get_point1(int x, int y) const;
INLINE void set_point1(int x, int y, PN_float32 point);
INLINE const LPoint2f &get_point2(int x, int y) const;
INLINE void set_point2(int x, int y, const LVecBase2f &point);
INLINE void set_point2(int x, int y, const LVecBase2d &point);
INLINE LPoint2f &modify_point2(int x, int y);
INLINE const LPoint3f &get_point(int x, int y) const;
INLINE void set_point(int x, int y, const LVecBase3f &point);
INLINE void set_point(int x, int y, const LVecBase3d &point);
@ -99,7 +103,9 @@ PUBLISHED:
INLINE BLOCKING void xform(const LMatrix4d &transform);
BLOCKING void project(const Lens *lens);
BLOCKING void merge(const PfmFile &other);
BLOCKING void copy_channel(int to_channel, const PfmFile &other, int from_channel);
BLOCKING void apply_crop(int x_begin, int x_end, int y_begin, int y_end);
BLOCKING void clear_to_texcoords(int x_size, int y_size);
BLOCKING PT(BoundingHexahedron) compute_planar_bounds(const LPoint2f &center, PN_float32 point_dist, PN_float32 sample_radius, bool points_only) const;
INLINE BLOCKING PT(BoundingHexahedron) compute_planar_bounds(const LPoint2d &center, PN_float32 point_dist, PN_float32 sample_radius, bool points_only) const;
@ -117,6 +123,7 @@ PUBLISHED:
enum ColumnType {
CT_texcoord2,
CT_texcoord3,
CT_vertex1,
CT_vertex2,
CT_vertex3,
CT_normal3,