From 515c6cd83ac45674ae98c42cd90395fb3af80b56 Mon Sep 17 00:00:00 2001 From: David Rose Date: Wed, 27 Aug 2008 01:38:08 +0000 Subject: [PATCH] TexturePeeker --- panda/src/gobj/Sources.pp | 6 +- panda/src/gobj/gobj_composite2.cxx | 1 + panda/src/gobj/texture.cxx | 29 ++ panda/src/gobj/texture.h | 4 + panda/src/gobj/texturePeeker.I | 64 ++++ panda/src/gobj/texturePeeker.cxx | 521 +++++++++++++++++++++++++++++ panda/src/gobj/texturePeeker.h | 102 ++++++ 7 files changed, 726 insertions(+), 1 deletion(-) create mode 100644 panda/src/gobj/texturePeeker.I create mode 100644 panda/src/gobj/texturePeeker.cxx create mode 100644 panda/src/gobj/texturePeeker.h diff --git a/panda/src/gobj/Sources.pp b/panda/src/gobj/Sources.pp index aaa49e1fa7..90729349dd 100644 --- a/panda/src/gobj/Sources.pp +++ b/panda/src/gobj/Sources.pp @@ -55,6 +55,7 @@ sliderTable.I sliderTable.h \ texture.I texture.h \ textureContext.I textureContext.h \ + texturePeeker.I texturePeeker.h \ texturePool.I texturePool.h \ texturePoolFilter.I texturePoolFilter.h \ textureStage.I textureStage.h \ @@ -116,7 +117,9 @@ simpleAllocator.cxx \ simpleLru.cxx \ sliderTable.cxx \ - texture.cxx textureContext.cxx texturePool.cxx \ + texture.cxx textureContext.cxx \ + texturePeeker.cxx \ + texturePool.cxx \ texturePoolFilter.cxx \ textureStage.cxx \ transformBlend.cxx \ @@ -181,6 +184,7 @@ sliderTable.I sliderTable.h \ texture.I texture.h \ textureContext.I textureContext.h \ + texturePeeker.I texturePeeker.h \ texturePool.I texturePool.h \ texturePoolFilter.I texturePoolFilter.h \ textureStage.I textureStage.h \ diff --git a/panda/src/gobj/gobj_composite2.cxx b/panda/src/gobj/gobj_composite2.cxx index 71ae116768..da30afad53 100644 --- a/panda/src/gobj/gobj_composite2.cxx +++ b/panda/src/gobj/gobj_composite2.cxx @@ -14,6 +14,7 @@ #include "sliderTable.cxx" #include "texture.cxx" #include "textureContext.cxx" +#include "texturePeeker.cxx" #include "texturePool.cxx" #include "texturePoolFilter.cxx" #include "textureStage.cxx" diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index 6f1cac87f1..318be8ab19 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -37,6 +37,7 @@ #include "pStatTimer.h" #include "pbitops.h" #include "streamReader.h" +#include "texturePeeker.h" #include @@ -1946,6 +1947,34 @@ clear_simple_ram_image() { ++_simple_image_modified; } +//////////////////////////////////////////////////////////////////// +// Function: Texture::peek +// Access: Published +// Description: Returns a TexturePeeker object that can be used to +// examine the individual texels stored within this +// Texture by (u, v) coordinate. +// +// If the texture has a ram image resident, that image +// is used. If it does not have a full ram image but +// does have a simple_ram_image resident, that image is +// used instead. If neither image is resident the full +// image is reloaded. +// +// Returns NULL if the texture cannot find an image to +// load, or the texture format is incompatible. +//////////////////////////////////////////////////////////////////// +PT(TexturePeeker) Texture:: +peek() { + ReMutexHolder holder(_lock); + + PT(TexturePeeker) peeker = new TexturePeeker(this); + if (peeker->is_valid()) { + return peeker; + } + + return NULL; +} + //////////////////////////////////////////////////////////////////// // Function: Texture::prepare // Access: Published diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index 7eafd71797..ac69e1fe30 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -38,6 +38,7 @@ class PreparedGraphicsObjects; class CullTraverser; class CullTraverserData; class BamCacheRecord; +class TexturePeeker; struct DDSHeader; //////////////////////////////////////////////////////////////////// @@ -337,6 +338,8 @@ PUBLISHED: void generate_simple_ram_image(); void clear_simple_ram_image(); + PT(TexturePeeker) peek(); + INLINE UpdateSeq get_properties_modified() const; INLINE UpdateSeq get_image_modified() const; INLINE UpdateSeq get_simple_image_modified() const; @@ -670,6 +673,7 @@ private: friend class TextureContext; friend class PreparedGraphicsObjects; friend class TexturePool; + friend class TexturePeeker; }; extern EXPCL_PANDA_GOBJ ConfigVariableEnum texture_quality_level; diff --git a/panda/src/gobj/texturePeeker.I b/panda/src/gobj/texturePeeker.I new file mode 100644 index 0000000000..4e12e6a61d --- /dev/null +++ b/panda/src/gobj/texturePeeker.I @@ -0,0 +1,64 @@ +// Filename: texturePeeker.I +// Created by: drose (26Aug08) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: TexturePeeker::is_valid +// Access: Public +// Description: Returns true if the TexturePeeker was able to +// initialize itself and is ready to return texel +// colors. +//////////////////////////////////////////////////////////////////// +INLINE bool TexturePeeker:: +is_valid() const { + return !_image.is_null(); +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePeeker::get_x_size +// Access: Published +// Description: Returns the width of the texture image that is +// contributing to the TexturePeeker's information. +// This may be either the Texture's full width, or its +// simple ram image's width. +//////////////////////////////////////////////////////////////////// +INLINE int TexturePeeker:: +get_x_size() const { + return _x_size; +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePeeker::get_y_size +// Access: Published +// Description: Returns the height of the texture image that is +// contributing to the TexturePeeker's information. +// This may be either the Texture's full height, or its +// simple ram image's height. +//////////////////////////////////////////////////////////////////// +INLINE int TexturePeeker:: +get_y_size() const { + return _y_size; +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePeeker::get_z_size +// Access: Published +// Description: Returns the depth of the texture image that is +// contributing to the TexturePeeker's information. +//////////////////////////////////////////////////////////////////// +INLINE int TexturePeeker:: +get_z_size() const { + return _z_size; +} + diff --git a/panda/src/gobj/texturePeeker.cxx b/panda/src/gobj/texturePeeker.cxx new file mode 100644 index 0000000000..518e244add --- /dev/null +++ b/panda/src/gobj/texturePeeker.cxx @@ -0,0 +1,521 @@ +// Filename: texturePeeker.cxx +// Created by: drose (26Aug08) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#include "texturePeeker.h" + + +//////////////////////////////////////////////////////////////////// +// Function: TexturePeeker::Constructor +// Access: Private +// Description: Use Texture::peek() to construct a TexturePeeker. +//////////////////////////////////////////////////////////////////// +TexturePeeker:: +TexturePeeker(Texture *tex) { + _x_size = tex->_x_size; + _y_size = tex->_y_size; + _z_size = tex->_z_size; + _component_width = tex->_component_width; + _num_components = tex->_num_components; + _format = tex->_format; + _component_type = tex->_component_type; + + if (tex->_texture_type == Texture::TT_cube_map) { + // Cube map texture. We'll need to map from (u, v, w) to (u, v) + // within the appropriate page, where w indicates the page. + + // TODO: handle cube maps. + return; + + } else { + // Regular 1-d, 2-d, or 3-d texture. The coordinates map + // directly. Simple ram images are possible if it is a 2-d + // texture. + if (!(tex->has_ram_image() && tex->get_ram_image_compression() == Texture::CM_off) && tex->has_simple_ram_image()) { + _image = tex->_simple_ram_image._image; + _x_size = tex->_simple_x_size; + _y_size = tex->_simple_y_size; + _z_size = 1; + + _component_width = 1; + _num_components = 4; + _format = Texture::F_rgba; + _component_type = Texture::T_unsigned_byte; + + } else { + _image = tex->get_uncompressed_ram_image(); + } + } + + if (_image.is_null()) { + return; + } + _pixel_width = _component_width * _num_components; + + switch (_component_type) { + case Texture::T_unsigned_byte: + _get_component = Texture::get_unsigned_byte; + break; + + case Texture::T_unsigned_short: + _get_component = Texture::get_unsigned_short; + break; + + case Texture::T_float: + // Not supported. + _image.clear(); + return; + } + + switch (_format) { + case Texture::F_depth_stencil: + case Texture::F_color_index: + // Not supported. + _image.clear(); + return; + + case Texture::F_red: + _get_texel = get_texel_r; + break; + + case Texture::F_green: + _get_texel = get_texel_g; + break; + + case Texture::F_blue: + _get_texel = get_texel_b; + break; + + case Texture::F_alpha: + _get_texel = get_texel_a; + break; + + case Texture::F_luminance: + _get_texel = get_texel_l; + break; + + case Texture::F_luminance_alpha: + case Texture::F_luminance_alphamask: + _get_texel = get_texel_la; + break; + + case Texture::F_rgb: + case Texture::F_rgb5: + case Texture::F_rgb8: + case Texture::F_rgb12: + case Texture::F_rgb332: + _get_texel = get_texel_rgb; + break; + + case Texture::F_rgba: + case Texture::F_rgbm: + case Texture::F_rgba4: + case Texture::F_rgba5: + case Texture::F_rgba8: + case Texture::F_rgba12: + case Texture::F_rgba16: + case Texture::F_rgba32: + _get_texel = get_texel_rgba; + break; + } +} + + +//////////////////////////////////////////////////////////////////// +// Function: TexturePeeker::lookup +// Access: Published +// Description: Fills "color" with the RGBA color of the texel at +// point (u, v). +// +// The texel color is determined via nearest-point +// sampling (no filtering of adjacent pixels), +// regardless of the filter type associated with the +// texture. u, v, and w will wrap around regardless of +// the texture's wrap mode. +//////////////////////////////////////////////////////////////////// +void TexturePeeker:: +lookup(Colorf &color, float u, float v) const { + int x = int((u - cfloor(u)) * (float)_x_size + 0.5f) % _x_size; + int y = int((v - cfloor(v)) * (float)_y_size + 0.5f) % _y_size; + + const unsigned char *p = _image.p() + (y * _x_size + x) * _pixel_width; + + (*_get_texel)(color, p, _get_component); +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePeeker::lookup +// Access: Published +// Description: Fills "color" with the RGBA color of the texel at +// point (u, v, w). +// +// The texel color is determined via nearest-point +// sampling (no filtering of adjacent pixels), +// regardless of the filter type associated with the +// texture. u, v, and w will wrap around regardless of +// the texture's wrap mode. +//////////////////////////////////////////////////////////////////// +void TexturePeeker:: +lookup(Colorf &color, float u, float v, float w) const { + int x = int((u - cfloor(u)) * (float)_x_size + 0.5f) % _x_size; + int y = int((v - cfloor(v)) * (float)_y_size + 0.5f) % _y_size; + int z = int((w - cfloor(w)) * (float)_z_size + 0.5f) % _z_size; + + const unsigned char *p = _image.p() + (z * _x_size * _y_size + y * _x_size + x) * _pixel_width; + + (*_get_texel)(color, p, _get_component); +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePeeker::filter_rect +// Access: Published +// Description: Fills "color" with the average RGBA color of the +// texels within the rectangle defined by the specified +// coordinate range. +// +// The texel color is linearly filtered over the entire +// region. u, v, and w will wrap around regardless of +// the texture's wrap mode. +//////////////////////////////////////////////////////////////////// +void TexturePeeker:: +filter_rect(Colorf &color, + float min_u, float min_v, float max_u, float max_v) const { + int min_x, max_x; + init_rect_minmax(min_x, max_x, min_u, max_u, _x_size); + + int min_y, max_y; + init_rect_minmax(min_y, max_y, min_v, max_v, _y_size); + + color.set(0.0f, 0.0f, 0.0f, 0.0f); + float net = 0.0f; + accum_filter_y(color, net, 0, + min_x, max_x, min_u, max_u, + min_y, max_y, min_v, max_v, + 1.0f); + + if (net != 0.0f) { + color /= net; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePeeker::filter_rect +// Access: Published +// Description: Fills "color" with the average RGBA color of the +// texels within the rectangle defined by the specified +// coordinate range. +// +// The texel color is linearly filtered over the entire +// region. u, v, and w will wrap around regardless of +// the texture's wrap mode. +//////////////////////////////////////////////////////////////////// +void TexturePeeker:: +filter_rect(Colorf &color, + float min_u, float min_v, float min_w, + float max_u, float max_v, float max_w) const { + int min_x, max_x; + init_rect_minmax(min_x, max_x, min_u, max_u, _x_size); + + int min_y, max_y; + init_rect_minmax(min_y, max_y, min_v, max_v, _y_size); + + int min_z, max_z; + init_rect_minmax(min_z, max_z, min_w, max_w, _z_size); + + color.set(0.0f, 0.0f, 0.0f, 0.0f); + float net = 0.0f; + accum_filter_z(color, net, + min_x, max_x, min_u, max_u, + min_y, max_y, min_v, max_v, + min_z, max_z, min_w, max_w); + + if (net != 0.0f) { + color /= net; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePeeker::init_rect_minmax +// Access: Private, Static +// Description: Sanity-checks min_u, max_u and computes min_x and +// min_y based on them. Also works for y and z. +//////////////////////////////////////////////////////////////////// +void TexturePeeker:: +init_rect_minmax(int &min_x, int &max_x, float &min_u, float &max_u, + int x_size) { + if (min_u > max_u) { + float t = min_u; + min_u = max_u; + max_u = t; + } + if (max_u - min_u >= 1.0f) { + min_u = 0.0f; + max_u = 1.0f; + } + min_x = (int)cfloor(min_u * (float)x_size); + max_x = (int)cceil(max_u * (float)x_size); + nassertv(min_x <= max_x); +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePeeker::accum_filter_z +// Access: Private +// Description: Accumulates the range of pixels from min_z to max_z. +//////////////////////////////////////////////////////////////////// +void TexturePeeker:: +accum_filter_z(Colorf &color, float &net, + int min_x, int max_x, float min_u, float max_u, + int min_y, int max_y, float min_v, float max_v, + int min_z, int max_z, float min_w, float max_w) const { + int zi = min_z; + + if (min_z >= max_z - 1) { + // Within a single texel. + accum_filter_y(color, net, zi % _z_size, + min_x, max_x, min_u, max_u, + min_y, max_y, min_v, max_v, + 1.0f); + + } else { + // First part-texel. + float w = (min_z + 1) - min_w * _z_size; + accum_filter_y(color, net, zi % _z_size, + min_x, max_x, min_u, max_u, + min_y, max_y, min_v, max_v, + w); + int zs = max_z - 1; + + // Run of full texels. + zi = min_z + 1; + while (zi < zs) { + accum_filter_y(color, net, zi % _z_size, + min_x, max_x, min_u, max_u, + min_y, max_y, min_v, max_v, + 1.0f); + ++zi; + } + + // Last part-texel. + w = max_w * _z_size - (max_z - 1); + accum_filter_y(color, net, zi % _z_size, + min_x, max_x, min_u, max_u, + min_y, max_y, min_v, max_v, + w); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePeeker::accum_filter_y +// Access: Private +// Description: Accumulates the range of pixels from min_y to max_y. +//////////////////////////////////////////////////////////////////// +void TexturePeeker:: +accum_filter_y(Colorf &color, float &net, int zi, + int min_x, int max_x, float min_u, float max_u, + int min_y, int max_y, float min_v, float max_v, + float weight) const { + int yi = min_y; + + if (min_y >= max_y - 1) { + // Within a single texel. + accum_filter_x(color, net, yi % _y_size, zi, min_x, max_x, min_u, max_u, weight); + + } else { + // First part-texel. + float w = (min_y + 1) - min_v * _y_size; + accum_filter_x(color, net, yi % _y_size, zi, min_x, max_x, min_u, max_u, weight * w); + int ys = max_y - 1; + + // Run of full texels. + yi = min_y + 1; + while (yi < ys) { + accum_filter_x(color, net, yi % _y_size, zi, min_x, max_x, min_u, max_u, weight); + ++yi; + } + + // Last part-texel. + w = max_v * _y_size - (max_y - 1); + accum_filter_x(color, net, yi % _y_size, zi, min_x, max_x, min_u, max_u, weight * w); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePeeker::accum_filter_x +// Access: Private +// Description: Accumulates the range of pixels from min_x to max_x. +//////////////////////////////////////////////////////////////////// +void TexturePeeker:: +accum_filter_x(Colorf &color, float &net, int yi, int zi, + int min_x, int max_x, float min_u, float max_u, + float weight) const { + // Compute the p corresponding to min_x. + int xi = min_x % _x_size; + const unsigned char *p = _image.p() + (zi * _x_size * _y_size + yi * _x_size + xi) * _pixel_width; + + if (min_x >= max_x - 1) { + // Within a single texel. + accum_texel(color, net, p, weight); + + } else { + // First part-texel. + float w = (min_x + 1) - min_u * _x_size; + accum_texel(color, net, p, weight * w); + int xs = max_x - 1; + + // Run of full texels. + xi = min_x + 1; + while (xi < xs) { + if (xi == _x_size) { + xi = 0; + p = _image.p() + (zi * _x_size * _y_size + yi * _x_size + xi) * _pixel_width; + xs -= _x_size; + } + accum_texel(color, net, p, weight); + ++xi; + } + + // Last part-texel. + if (xi == _x_size) { + xi = 0; + p = _image.p() + (zi * _x_size * _y_size + yi * _x_size + xi) * _pixel_width; + } + w = max_u * _x_size - (max_x - 1); + accum_texel(color, net, p, weight * w); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePeeker::accum_texel +// Access: Private +// Description: Accumulates a single texel into the total computed by +// filter_rect(). +//////////////////////////////////////////////////////////////////// +void TexturePeeker:: +accum_texel(Colorf &color, float &net, const unsigned char *&p, float weight) const { + Colorf c; + (*_get_texel)(c, p, _get_component); + color += c * weight; + net += weight; +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePeeker::get_texel_r +// Access: Private, Static +// Description: Gets the color of the texel at byte p, given that the +// texture is in format F_red. +//////////////////////////////////////////////////////////////////// +void TexturePeeker:: +get_texel_r(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component) { + color[0] = (*get_component)(p); + color[1] = 0.0f; + color[2] = 0.0f; + color[3] = 1.0f; +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePeeker::get_texel_g +// Access: Private, Static +// Description: Gets the color of the texel at byte p, given that the +// texture is in format F_green. +//////////////////////////////////////////////////////////////////// +void TexturePeeker:: +get_texel_g(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component) { + color[0] = 0.0f; + color[1] = (*get_component)(p); + color[2] = 0.0f; + color[3] = 1.0f; +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePeeker::get_texel_b +// Access: Private, Static +// Description: Gets the color of the texel at byte p, given that the +// texture is in format F_blue. +//////////////////////////////////////////////////////////////////// +void TexturePeeker:: +get_texel_b(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component) { + color[0] = 0.0f; + color[1] = 0.0f; + color[2] = (*get_component)(p); + color[3] = 1.0f; +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePeeker::get_texel_a +// Access: Private, Static +// Description: Gets the color of the texel at byte p, given that the +// texture is in format F_alpha. +//////////////////////////////////////////////////////////////////// +void TexturePeeker:: +get_texel_a(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component) { + color[0] = 0.0f; + color[1] = 0.0f; + color[2] = 1.0f; + color[3] = (*get_component)(p); +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePeeker::get_texel_l +// Access: Private, Static +// Description: Gets the color of the texel at byte p, given that the +// texture is in format F_luminance. +//////////////////////////////////////////////////////////////////// +void TexturePeeker:: +get_texel_l(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component) { + color[0] = (*get_component)(p); + color[1] = color[0]; + color[2] = color[0]; + color[3] = 1.0f; +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePeeker::get_texel_la +// Access: Private, Static +// Description: Gets the color of the texel at byte p, given that the +// texture is in format F_luminance_alpha or similar. +//////////////////////////////////////////////////////////////////// +void TexturePeeker:: +get_texel_la(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component) { + color[0] = (*get_component)(p); + color[1] = color[0]; + color[2] = color[0]; + color[3] = (*get_component)(p); +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePeeker::get_texel_rgb +// Access: Private, Static +// Description: Gets the color of the texel at byte p, given that the +// texture is in format F_rgb or similar. +//////////////////////////////////////////////////////////////////// +void TexturePeeker:: +get_texel_rgb(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component) { + color[2] = (*get_component)(p); + color[1] = (*get_component)(p); + color[0] = (*get_component)(p); + color[3] = 1.0f; +} + +//////////////////////////////////////////////////////////////////// +// Function: TexturePeeker::get_texel_rgba +// Access: Private, Static +// Description: Gets the color of the texel at byte p, given that the +// texture is in format F_rgba or similar. +//////////////////////////////////////////////////////////////////// +void TexturePeeker:: +get_texel_rgba(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component) { + color[2] = (*get_component)(p); + color[1] = (*get_component)(p); + color[0] = (*get_component)(p); + color[3] = (*get_component)(p); +} diff --git a/panda/src/gobj/texturePeeker.h b/panda/src/gobj/texturePeeker.h new file mode 100644 index 0000000000..a4e488e076 --- /dev/null +++ b/panda/src/gobj/texturePeeker.h @@ -0,0 +1,102 @@ +// Filename: texturePeeker.h +// Created by: drose (26Aug08) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#ifndef TEXTUREPEEKER_H +#define TEXTUREPEEKER_H + +#include "pandabase.h" + +#include "referenceCount.h" +#include "texture.h" + +//////////////////////////////////////////////////////////////////// +// Class : TexturePeeker +// Description : An instance of this object is returned by +// Texture::peek(). This object allows quick and easy +// inspection of a texture's texels by (u, v) +// coordinates. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA_GOBJ TexturePeeker : public ReferenceCount { +private: + TexturePeeker(Texture *tex); + +public: + INLINE bool is_valid() const; + +PUBLISHED: + INLINE int get_x_size() const; + INLINE int get_y_size() const; + INLINE int get_z_size() const; + + void lookup(Colorf &color, float u, float v) const; + void lookup(Colorf &color, float u, float v, float w) const; + void filter_rect(Colorf &color, + float min_u, float min_v, + float max_u, float max_v) const; + void filter_rect(Colorf &color, + float min_u, float min_v, float min_w, + float max_u, float max_v, float max_w) const; + +private: + static void init_rect_minmax(int &min_x, int &max_x, + float &min_u, float &max_u, + int x_size); + + void accum_filter_z(Colorf &color, float &net, + int min_x, int max_x, float min_u, float max_u, + int min_y, int max_y, float min_v, float max_v, + int min_z, int max_z, float min_w, float max_w) const; + void accum_filter_y(Colorf &color, float &net, int zi, + int min_x, int max_x, float min_u, float max_u, + int min_y, int max_y, float min_v, float max_v, + float weight) const; + void accum_filter_x(Colorf &color, float &net, int yi, int zi, + int min_x, int max_x, float min_u, float max_u, + float weight) const; + void accum_texel(Colorf &color, float &net, const unsigned char *&p, + float weight) const; + + typedef double GetComponentFunc(const unsigned char *&p); + typedef void GetTexelFunc(Colorf &color, const unsigned char *&p, + GetComponentFunc *get_component); + + static void get_texel_r(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component); + static void get_texel_g(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component); + static void get_texel_b(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component); + static void get_texel_a(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component); + static void get_texel_l(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component); + static void get_texel_la(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component); + static void get_texel_rgb(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component); + static void get_texel_rgba(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component); + + int _x_size; + int _y_size; + int _z_size; + int _component_width; + int _num_components; + int _pixel_width; + Texture::Format _format; + Texture::ComponentType _component_type; + CPTA_uchar _image; + + GetComponentFunc *_get_component; + GetTexelFunc *_get_texel; + + friend class Texture; +}; + +#include "texturePeeker.I" + +#endif +