349 lines
14 KiB
C++
349 lines
14 KiB
C++
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
|
|
*
|
|
* This library is open source and may be redistributed and/or modified under
|
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
|
* (at your option) any later version. The full license is in LICENSE file
|
|
* included with this distribution, and on the openscenegraph.org website.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* OpenSceneGraph Public License for more details.
|
|
*/
|
|
|
|
#ifndef OSG_IMAGE
|
|
#define OSG_IMAGE 1
|
|
|
|
#include <osg/BufferObject>
|
|
#include <osg/Vec2>
|
|
#include <osg/Vec3>
|
|
#include <osg/Vec4>
|
|
#include <osg/FrameStamp>
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#ifndef GL_VERSION_1_2
|
|
// 1.2 definitions...
|
|
#define GL_BGR 0x80E0
|
|
#define GL_BGRA 0x80E1
|
|
#define GL_UNSIGNED_BYTE_3_3_2 0x8032
|
|
#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
|
|
#define GL_UNSIGNED_SHORT_5_6_5 0x8363
|
|
#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
|
|
#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
|
|
#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
|
|
#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
|
|
#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
|
|
#define GL_UNSIGNED_INT_8_8_8_8 0x8035
|
|
#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
|
|
#define GL_UNSIGNED_INT_10_10_10_2 0x8036
|
|
#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
|
|
#endif
|
|
|
|
#ifndef GL_COMPRESSED_ALPHA
|
|
#define GL_COMPRESSED_ALPHA 0x84E9
|
|
#define GL_COMPRESSED_LUMINANCE 0x84EA
|
|
#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB
|
|
#define GL_COMPRESSED_INTENSITY 0x84EC
|
|
#define GL_COMPRESSED_RGB 0x84ED
|
|
#define GL_COMPRESSED_RGBA 0x84EE
|
|
#endif
|
|
|
|
|
|
namespace osg {
|
|
|
|
// forward declare
|
|
class NodeVisitor;
|
|
|
|
/** Image class for encapsulating the storage texture image data. */
|
|
class OSG_EXPORT Image : public Object
|
|
{
|
|
|
|
public :
|
|
|
|
Image();
|
|
|
|
/** Copy constructor using CopyOp to manage deep vs shallow copy. */
|
|
Image(const Image& image,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
|
|
|
|
virtual Object* cloneType() const { return new Image(); }
|
|
virtual Object* clone(const CopyOp& copyop) const { return new Image(*this,copyop); }
|
|
virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const Image*>(obj)!=0; }
|
|
virtual const char* libraryName() const { return "osg"; }
|
|
virtual const char* className() const { return "Image"; }
|
|
|
|
/** Return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs. */
|
|
virtual int compare(const Image& rhs) const;
|
|
|
|
void setFileName(const std::string& fileName);
|
|
inline const std::string& getFileName() const { return _fileName; }
|
|
|
|
enum AllocationMode {
|
|
NO_DELETE,
|
|
USE_NEW_DELETE,
|
|
USE_MALLOC_FREE
|
|
};
|
|
|
|
/** Set the method used for deleting data once it goes out of scope. */
|
|
void setAllocationMode(AllocationMode mode) { _allocationMode = mode; }
|
|
|
|
/** Get the method used for deleting data once it goes out of scope. */
|
|
AllocationMode getAllocationMode() const { return _allocationMode; }
|
|
|
|
|
|
/** Allocate a pixel block of specified size and type. */
|
|
void allocateImage(int s,int t,int r,
|
|
GLenum pixelFormat,GLenum type,
|
|
int packing=1);
|
|
|
|
|
|
/** Set the image dimensions, format and data. */
|
|
void setImage(int s,int t,int r,
|
|
GLint internalTextureformat,
|
|
GLenum pixelFormat,GLenum type,
|
|
unsigned char* data,
|
|
AllocationMode mode,
|
|
int packing=1);
|
|
|
|
/** Read pixels from current frame buffer at specified position and size, using glReadPixels.
|
|
* Create memory for storage if required, reuse existing pixel coords if possible.
|
|
*/
|
|
void readPixels(int x,int y,int width,int height,
|
|
GLenum pixelFormat,GLenum type);
|
|
|
|
|
|
/** Read the contents of the current bound texture, handling compressed pixelFormats if present.
|
|
* Create memory for storage if required, reuse existing pixel coords if possible.
|
|
*/
|
|
void readImageFromCurrentTexture(unsigned int contextID, bool copyMipMapsIfAvailable, GLenum type = GL_UNSIGNED_BYTE);
|
|
|
|
|
|
/** Scale image to specified size. */
|
|
void scaleImage(int s,int t,int r) { scaleImage(s,t,r, getDataType()); }
|
|
|
|
/** Scale image to specified size and with specified data type. */
|
|
void scaleImage(int s,int t,int r, GLenum newDataType);
|
|
|
|
/** Copy a source Image into a subpart of this Image at specified position.
|
|
* Typically used to copy to an already allocated image, such as creating
|
|
* a 3D image from a stack 2D images.
|
|
* If this Image is empty then image data is created to
|
|
* accomodate the source image in its offset position.
|
|
* If source is NULL then no operation happens, this Image is left unchanged.
|
|
*/
|
|
void copySubImage(int s_offset,int t_offset,int r_offset,osg::Image* source);
|
|
|
|
|
|
enum Origin
|
|
{
|
|
BOTTOM_LEFT,
|
|
TOP_LEFT
|
|
};
|
|
|
|
/** Set the origin of the image.
|
|
* The default value is BOTTOM_LEFT and is consistent with OpenGL.
|
|
* TOP_LEFT is used for imagery that follows standard Imagery convention, such as movies,
|
|
* and hasn't been flipped yet. For such images one much flip the t axis of the tex coords.
|
|
* to handle this origin position. */
|
|
void setOrigin(Origin origin) { _origin = origin; }
|
|
|
|
/** Get the origin of the image.*/
|
|
Origin getOrigin() const { return _origin; }
|
|
|
|
|
|
/** Width of image. */
|
|
inline int s() const { return _s; }
|
|
|
|
/** Height of image. */
|
|
inline int t() const { return _t; }
|
|
|
|
/** Depth of image. */
|
|
inline int r() const { return _r; }
|
|
|
|
void setInternalTextureFormat(GLint internalFormat);
|
|
inline GLint getInternalTextureFormat() const { return _internalTextureFormat; }
|
|
|
|
void setPixelFormat(GLenum pixelFormat);
|
|
inline GLenum getPixelFormat() const { return _pixelFormat; }
|
|
|
|
void setDataType(GLenum dataType);
|
|
inline GLenum getDataType() const { return _dataType; }
|
|
|
|
void setPacking(unsigned int packing) { _packing = packing; }
|
|
inline unsigned int getPacking() const { return _packing; }
|
|
|
|
/** Return the number of bits required for each pixel. */
|
|
inline unsigned int getPixelSizeInBits() const { return computePixelSizeInBits(_pixelFormat,_dataType); }
|
|
|
|
/** Return the number of bytes each row of pixels occupies once it has been packed. */
|
|
inline unsigned int getRowSizeInBytes() const { return computeRowWidthInBytes(_s,_pixelFormat,_dataType,_packing); }
|
|
|
|
/** Return the number of bytes each image (_s*_t) of pixels occupies. */
|
|
inline unsigned int getImageSizeInBytes() const { return getRowSizeInBytes()*_t; }
|
|
|
|
/** Return the number of bytes the whole row/image/volume of pixels occupies. */
|
|
inline unsigned int getTotalSizeInBytes() const { return getImageSizeInBytes()*_r; }
|
|
|
|
/** Return the number of bytes the whole row/image/volume of pixels occupies, including all mip maps if included. */
|
|
unsigned int getTotalSizeInBytesIncludingMipmaps() const;
|
|
|
|
/** Return true if the Image represent a valid and usable imagery.*/
|
|
bool valid() const { return _s!=0 && _t!=0 && _r!=0 && _data!=0 && _dataType!=0; }
|
|
|
|
/** Raw image data. */
|
|
inline unsigned char* data() { return _data; }
|
|
|
|
/** Raw const image data. */
|
|
inline const unsigned char* data() const { return _data; }
|
|
|
|
|
|
inline unsigned char* data(int column, int row=0,int image=0)
|
|
{
|
|
if (!_data) return NULL;
|
|
return _data+(column*getPixelSizeInBits())/8+row*getRowSizeInBytes()+image*getImageSizeInBytes();
|
|
}
|
|
|
|
inline const unsigned char* data(int column, int row=0,int image=0) const
|
|
{
|
|
if (!_data) return NULL;
|
|
return _data+(column*getPixelSizeInBits())/8+row*getRowSizeInBytes()+image*getImageSizeInBytes();
|
|
}
|
|
|
|
/** Get the color value for specified texcoord.*/
|
|
Vec4 getColor(unsigned int s,unsigned t=0,unsigned r=0) const;
|
|
|
|
/** Get the color value for specified texcoord.*/
|
|
Vec4 getColor(const Vec2& texcoord) const { return getColor(Vec3(texcoord.x(),texcoord.y(),0.0f)); }
|
|
|
|
/** Get the color value for specified texcoord.*/
|
|
Vec4 getColor(const Vec3& texcoord) const;
|
|
|
|
|
|
/** Flip the image horizontally. */
|
|
void flipHorizontal();
|
|
|
|
/** Flip the image vertically. */
|
|
void flipVertical();
|
|
|
|
|
|
/** Ensure image dimensions are a power of two.
|
|
* Mipmapped textures require the image dimensions to be
|
|
* power of two and are within the maxiumum texture size for
|
|
* the host machine.
|
|
*/
|
|
void ensureValidSizeForTexturing(GLint maxTextureSize);
|
|
|
|
/** Dirty the image, which increments the modified count, to force osg::Texture to reload the image. */
|
|
inline void dirty() { ++_modifiedCount; if (_bufferObject.valid()) _bufferObject->dirty(); }
|
|
|
|
/** Set the modified count value. Used by osg::Texture when using texture subloading. */
|
|
inline void setModifiedCount(unsigned int value) { _modifiedCount=value; }
|
|
|
|
/** Get modified count value. Used by osg::Texture when using texture subloading. */
|
|
inline unsigned int getModifiedCount() const { return _modifiedCount; }
|
|
|
|
|
|
static bool isPackedType(GLenum type);
|
|
static GLenum computePixelFormat(GLenum pixelFormat);
|
|
static unsigned int computeNumComponents(GLenum pixelFormat);
|
|
static unsigned int computePixelSizeInBits(GLenum pixelFormat,GLenum type);
|
|
static unsigned int computeRowWidthInBytes(int width,GLenum pixelFormat,GLenum type,int packing);
|
|
static int computeNearestPowerOfTwo(int s,float bias=0.5f);
|
|
static int computeNumberOfMipmapLevels(int s,int t = 1, int r = 1);
|
|
|
|
/** Precomputed mipmaps stuff. */
|
|
typedef std::vector< unsigned int > MipmapDataType;
|
|
|
|
inline bool isMipmap() const {return !_mipmapData.empty();};
|
|
|
|
unsigned int getNumMipmapLevels() const
|
|
{
|
|
return _mipmapData.size()+1;
|
|
};
|
|
|
|
/** Send offsets into data. It is assumed that first mipmap offset (index 0) is 0.*/
|
|
inline void setMipmapLevels(const MipmapDataType& mipmapDataVector) { _mipmapData = mipmapDataVector; }
|
|
|
|
inline const MipmapDataType& getMipmapLevels() const { return _mipmapData; }
|
|
|
|
inline unsigned int getMipmapOffset(unsigned int mipmapLevel) const
|
|
{
|
|
if(mipmapLevel == 0)
|
|
return 0;
|
|
else if (mipmapLevel < getNumMipmapLevels())
|
|
return _mipmapData[mipmapLevel-1];
|
|
return 0;
|
|
};
|
|
|
|
inline unsigned char* getMipmapData(unsigned int mipmapLevel)
|
|
{
|
|
return _data+getMipmapOffset(mipmapLevel);
|
|
}
|
|
|
|
inline const unsigned char* getMipmapData(unsigned int mipmapLevel) const
|
|
{
|
|
return _data+getMipmapOffset(mipmapLevel);
|
|
}
|
|
|
|
/** Return true if this image is translucent - i.e. it has alpha values that are less 1.0 (when normalized). */
|
|
bool isImageTranslucent() const;
|
|
|
|
/** Set the optional PixelBufferObject used to map the image memory efficiently to graphics memory. */
|
|
void setPixelBufferObject(PixelBufferObject* buffer) { _bufferObject = buffer; if (_bufferObject.valid()) _bufferObject->setImage(this); }
|
|
|
|
/** Get the PixelBufferObject.*/
|
|
PixelBufferObject* getPixelBufferObject() { return _bufferObject.get(); }
|
|
|
|
/** Get the const PixelBufferObject.*/
|
|
const PixelBufferObject* getPixelBufferObject() const { return _bufferObject.get(); }
|
|
|
|
virtual void update(NodeVisitor* nv) {}
|
|
|
|
protected :
|
|
|
|
virtual ~Image();
|
|
|
|
Image& operator = (const Image&) { return *this; }
|
|
|
|
std::string _fileName;
|
|
|
|
Origin _origin;
|
|
|
|
int _s, _t, _r;
|
|
GLint _internalTextureFormat;
|
|
GLenum _pixelFormat;
|
|
GLenum _dataType;
|
|
unsigned int _packing;
|
|
|
|
AllocationMode _allocationMode;
|
|
unsigned char* _data;
|
|
|
|
void deallocateData();
|
|
|
|
void setData(unsigned char* data,AllocationMode allocationMode);
|
|
|
|
unsigned int _modifiedCount;
|
|
|
|
MipmapDataType _mipmapData;
|
|
|
|
ref_ptr<PixelBufferObject> _bufferObject;
|
|
};
|
|
|
|
class Geode;
|
|
|
|
/** Convenience function to be used by image loaders to generate a valid geode
|
|
* to return for readNode().
|
|
* Use the image's s and t values to scale the dimensions of the image.
|
|
*/
|
|
extern OSG_EXPORT Geode* createGeodeForImage(Image* image);
|
|
/** Convenience function to be used by image loaders to generate a valid geode
|
|
* to return for readNode().
|
|
* Use the specified s and t values to scale the dimensions of the image.
|
|
*/
|
|
extern OSG_EXPORT Geode* createGeodeForImage(Image* image,float s,float t);
|
|
|
|
}
|
|
|
|
#endif // __SG_IMAGE_H
|