diff --git a/AUTHORS.txt b/AUTHORS.txt index 46ed8cc82..076056870 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -127,6 +127,9 @@ Tree Vladimir Vukicevic - md2 loader. +Rune Schmidt Jensen + - dds loader. + Indirect Contributors --------------------- diff --git a/Make/makedirdefs b/Make/makedirdefs index 355a46222..5e114efc1 100644 --- a/Make/makedirdefs +++ b/Make/makedirdefs @@ -26,6 +26,7 @@ PLUGIN_DIRS = \ ac3d\ bmp\ directx\ + dds\ dw\ flt\ geo\ diff --git a/NEWS.txt b/NEWS.txt index 89c358e99..8b491f0ef 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -30,6 +30,8 @@ OSG News (most significant items from ChangeLog) New MD2 plugin which allows Quake animated characters to be loaded into the OSG. + + New DDS plugin for loading compressed and non-compressed images. Completely new osgText implemention which is simpler to use, faster, and thread safe. Support for high quality true type fonts has now been moved diff --git a/VisualStudio/VisualStudio.dsw b/VisualStudio/VisualStudio.dsw index 59f460879..e1d3a7dac 100644 --- a/VisualStudio/VisualStudio.dsw +++ b/VisualStudio/VisualStudio.dsw @@ -1584,6 +1584,24 @@ Package=<4> ############################################################################### +Project: "osgPlugin dds"=.\osgPlugins\dds\dds.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name Core osg + End Project Dependency + Begin Project Dependency + Project_Dep_Name Core osgDB + End Project Dependency +}}} + +############################################################################### + Project: "osgPlugin tga"=.\osgPlugins\tga\tga.dsp - Package Owner=<4> Package=<5> diff --git a/VisualStudio/osgPlugins/dds/dds.dsp b/VisualStudio/osgPlugins/dds/dds.dsp new file mode 100644 index 000000000..2d3b296d5 --- /dev/null +++ b/VisualStudio/osgPlugins/dds/dds.dsp @@ -0,0 +1,109 @@ +# Microsoft Developer Studio Project File - Name="osgPlugin dds" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=osgPlugin dds - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "dds.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "dds.mak" CFG="osgPlugin dds - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "osgPlugin dds - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "osgPlugin dds - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "osgPlugin dds - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "../../../lib" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 /nologo /dll /pdb:none /machine:I386 /nodefaultlib:"LIBC" /out:"../../../bin/osgdb_dds.dll" /libpath:"../../../lib" +# SUBTRACT LINK32 /nodefaultlib + +!ELSEIF "$(CFG)" == "osgPlugin dds - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "../../../lib" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /vmg /vd0 /GR /GX /Zi /Od /I "../../../include" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WIN32" /D "_DEBUG" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 /nologo /dll /debug /machine:I386 /nodefaultlib:"LIBC" /out:"../../../bin/osgdb_ddsd.dll" /pdbtype:sept /libpath:"../../../lib" +# SUBTRACT LINK32 /nodefaultlib + +!ENDIF + +# Begin Target + +# Name "osgPlugin dds - Win32 Release" +# Name "osgPlugin dds - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\dds\ReaderWriterDDS.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/include/osg/Image b/include/osg/Image index a4a1ddbe5..183c5bf1a 100644 --- a/include/osg/Image +++ b/include/osg/Image @@ -99,12 +99,16 @@ class SG_EXPORT Image : public Object int packing=1); /** readPixels from screen at specified position and size, using glReadPixels. - * Create memory for storage if required, reuse existing pixel coords if possible. - * if pixelFormat or dataType*/ + * Create memory for storage if required, reuse existing pixel coords if possible.*/ void readPixels(int x,int y,int width,int height, GLenum format,GLenum type); + /** read the contents of the current bound texture, handling compressed formats if present. + * Create memory for storage if required, reuse existing pixel coords if possible.*/ + void readImageFromCurrentTexture(unsigned int contextID=0); + + /** Scale image to specified size. */ void scaleImage(int s,int t,int r); @@ -117,6 +121,9 @@ class SG_EXPORT Image : public Object void copySubImage(int s_offset,int t_offset,int r_offset,osg::Image* source); + + + /** Width of image.*/ inline int s() const { return _s; } diff --git a/include/osg/Texture b/include/osg/Texture index 124662920..955cd9172 100644 --- a/include/osg/Texture +++ b/include/osg/Texture @@ -264,6 +264,7 @@ class SG_EXPORT Texture : public osg::StateAttribute void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) const; void glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei type, const GLvoid *data) const; + void glGetCompressedTexImage(GLenum target, GLint level, GLvoid *data) const; protected: @@ -281,6 +282,7 @@ class SG_EXPORT Texture : public osg::StateAttribute void* _glCompressedTexImage2D; void* _glCompressedTexSubImage2D; + void* _glGetCompressedTexImage; }; diff --git a/src/osg/Image.cpp b/src/osg/Image.cpp index 6622c552b..b88095b87 100644 --- a/src/osg/Image.cpp +++ b/src/osg/Image.cpp @@ -141,6 +141,9 @@ unsigned int Image::computeNumComponents(GLenum format) { switch(format) { + case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT): return 3; + case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT): return 4; + case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT): return 4; case(GL_COLOR_INDEX): return 1; case(GL_STENCIL_INDEX): return 1; case(GL_DEPTH_COMPONENT): return 1; @@ -163,6 +166,12 @@ unsigned int Image::computePixelSizeInBits(GLenum format,GLenum type) { switch(type) { + case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT): return 4; + + case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT): return 8; + + case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT): return 8; + case(GL_BITMAP): return computeNumComponents(format); case(GL_BYTE): @@ -320,6 +329,51 @@ void Image::readPixels(int x,int y,int width,int height, } +void Image::readImageFromCurrentTexture(unsigned int contextID) +{ + const osg::Texture::Extensions* extensions = osg::Texture::getExtensions(contextID,true); + + GLint internalformat; + GLint width; + GLint height; + + if (extensions->isCompressedTexImage2DSupported()) + { + GLint compressed; + GLint compressed_size; + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_ARB,&compressed); + + /* if the compression has been successful */ + if (compressed == GL_TRUE) + { + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internalformat); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, &compressed_size); + + allocateImage(width,height,1,internalformat,internalformat); + + extensions->glGetCompressedTexImage(GL_TEXTURE_2D, 0, _data); + + return; + } + + } + + // non compressed texture implemention. + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internalformat); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); + + allocateImage(width,height,1,internalformat,GL_UNSIGNED_BYTE); + + _internalTextureFormat = internalformat; + + glGetTexImage(GL_TEXTURE_2D,0,_pixelFormat,_dataType,_data); + +} + + void Image::scaleImage(int s,int t,int r) { if (_s==s && _t==t && _r==r) return; diff --git a/src/osg/Texture.cpp b/src/osg/Texture.cpp index 1fcf17944..2a7b56deb 100644 --- a/src/osg/Texture.cpp +++ b/src/osg/Texture.cpp @@ -918,7 +918,7 @@ void Texture::Extensions::setupGLExtenions() _glCompressedTexImage2D = getGLExtensionFuncPtr("glCompressedTexImage2D","glCompressedTexImage2DARB"); _glCompressedTexSubImage2D = getGLExtensionFuncPtr("glCompressedTexSubImage2D","glCompressedTexSubImage2DARB");; - + _glGetCompressedTexImage = getGLExtensionFuncPtr("glGetCompressedTexImage","glGetCompressedTexImageARB");; } void Texture::Extensions::glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) const @@ -948,3 +948,15 @@ void Texture::Extensions::glCompressedTexSubImage2D(GLenum target, GLint level, } } +void Texture::Extensions::glGetCompressedTexImage(GLenum target, GLint level, GLvoid *data) const +{ + if (_glGetCompressedTexImage) + { + typedef void (APIENTRY * GetCompressedTexImageArbProc) (GLenum target, GLint level, GLvoid *data); + ((GetCompressedTexImageArbProc)_glGetCompressedTexImage)(target, level, data); + } + else + { + notify(WARN)<<"Error: glGetCompressedTexImage not supported by OpenGL driver"< + +#include +#include + +#include + +// NOTICE ON WIN32: +// typedef DWORD unsigned long; +// sizeof(DWORD) = 4 +typedef struct _DDCOLORKEY +{ + unsigned long dwColorSpaceLowValue; + unsigned long dwColorSpaceHighValue; +} DDCOLORKEY; + + +typedef struct _DDPIXELFORMAT +{ + unsigned long dwSize; + unsigned long dwFlags; + unsigned long dwFourCC; + union + { + unsigned long dwRGBBitCount; + unsigned long dwYUVBitCount; + unsigned long dwZBufferBitDepth; + unsigned long dwAlphaBitDepth; + }; + union + { + unsigned long dwRBitMask; + unsigned long dwYBitMask; + }; + union + { + unsigned long dwGBitMask; + unsigned long dwUBitMask; + }; + union + { + unsigned long dwBBitMask; + unsigned long dwVBitMask; + }; + union + { + unsigned long dwRGBAlphaBitMask; + unsigned long dwYUVAlphaBitMask; + unsigned long dwRGBZBitMask; + unsigned long dwYUVZBitMask; + }; +} DDPIXELFORMAT; + +typedef struct _DDSCAPS2 +{ + unsigned long dwCaps; + unsigned long dwCaps2; + unsigned long dwCaps3; + union + { + unsigned long dwCaps4; + unsigned long dwVolumeDepth; + }; +} DDSCAPS2; + +typedef struct _DDSURFACEDESC2 { + unsigned long dwSize; + unsigned long dwFlags; + unsigned long dwHeight; + unsigned long dwWidth; + union + { + long lPitch; + unsigned long dwLinearSize; + }; + unsigned long dwBackBufferCount; + union + { + unsigned long dwMipMapCount; + unsigned long dwRefreshRate; + }; + unsigned long dwAlphaBitDepth; + unsigned long dwReserved; + unsigned long* lpSurface; + DDCOLORKEY ddckCKDestOverlay; + DDCOLORKEY ddckCKDestBlt; + DDCOLORKEY ddckCKSrcOverlay; + DDCOLORKEY ddckCKSrcBlt; + DDPIXELFORMAT ddpfPixelFormat; + DDSCAPS2 ddsCaps; + unsigned long dwTextureStage; +} DDSURFACEDESC2; + +#ifndef MAKEFOURCC + #define MAKEFOURCC(ch0, ch1, ch2, ch3) \ + ((unsigned long)(char)(ch0) | ((unsigned long)(char)(ch1) << 8) | \ + ((unsigned long)(char)(ch2) << 16) | ((unsigned long)(char)(ch3) << 24 )) +#endif //defined(MAKEFOURCC) + +/* + * FOURCC codes for DX compressed-texture pixel formats + */ +#define FOURCC_DXT1 (MAKEFOURCC('D','X','T','1')) +#define FOURCC_DXT2 (MAKEFOURCC('D','X','T','2')) +#define FOURCC_DXT3 (MAKEFOURCC('D','X','T','3')) +#define FOURCC_DXT4 (MAKEFOURCC('D','X','T','4')) +#define FOURCC_DXT5 (MAKEFOURCC('D','X','T','5')) + +osg::Image* ReadDDSFile(const char *filename){ + osg::Image* osgImage = new osg::Image(); + + DDSURFACEDESC2 ddsd; + + char filecode[4]; + FILE *fp; + + // Open file. + fp = fopen(filename, "rb"); + if (fp == NULL) + return NULL; + + // Verify that this is a DDS file. + fread(filecode, 1, 4, fp); + if (strncmp(filecode, "DDS ", 4) != 0) { + fclose(fp); + return NULL; + } + + // Get the surface desc. + fread(&ddsd, sizeof(ddsd), 1, fp); + + // Read image data. + unsigned int size = ddsd.dwMipMapCount > 1 ? ddsd.dwLinearSize * 2 : ddsd.dwLinearSize; + unsigned char* imageData = (unsigned char*) malloc(size * sizeof(unsigned char)); + fread(imageData, 1, size, fp); + // Close the file. + fclose(fp); + + // Retreive image properties. + int s = ddsd.dwWidth; + int t = ddsd.dwHeight; + int r = ddsd.dwMipMapCount>1?ddsd.dwMipMapCount:0; + unsigned int dataType = GL_UNSIGNED_BYTE; + unsigned int pixelFormat; + unsigned int internalFormat; + switch(ddsd.ddpfPixelFormat.dwFourCC){ + case FOURCC_DXT1: + internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + pixelFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + break; + case FOURCC_DXT3: + internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + pixelFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + break; + case FOURCC_DXT5: + internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + pixelFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + break; + default: + free(imageData); + return NULL; + } + + // Set image data and properties. + osgImage->setImage(s,t,r, internalFormat, pixelFormat, dataType, imageData, osg::Image::USE_NEW_DELETE); + + // Return Image. + return osgImage; +} + +class ReaderWriterDDS : public osgDB::ReaderWriter +{ + public: + virtual const char* className() { + return "DDS Image Reader"; + } + + virtual bool acceptsExtension(const std::string& extension) { + return osgDB::equalCaseInsensitive(extension,"dds"); + } + + virtual ReadResult readImage(const std::string& fileName, const osgDB::ReaderWriter::Options*) { + osg::Image* osgImage = ReadDDSFile(fileName.c_str()); + if (osgImage==NULL) return ReadResult::FILE_NOT_HANDLED; + return osgImage; + + } +}; + +// now register with Registry to instantiate the above +// reader/writer. +osgDB::RegisterReaderWriterProxy g_readerWriter_DDS_Proxy;