diff --git a/Make/makedirdefs b/Make/makedirdefs index 250358c0e..6c0836042 100644 --- a/Make/makedirdefs +++ b/Make/makedirdefs @@ -77,6 +77,7 @@ DEMOS_DIRS = \ osgconv\ osgcopy\ osgcube\ + osgcubemap\ osggeometry\ osghangglide\ osghud\ diff --git a/VisualStudio/Demos/osgcubemap/osgcubemap.dsp b/VisualStudio/Demos/osgcubemap/osgcubemap.dsp new file mode 100755 index 000000000..324dde9a2 --- /dev/null +++ b/VisualStudio/Demos/osgcubemap/osgcubemap.dsp @@ -0,0 +1,95 @@ +# Microsoft Developer Studio Project File - Name="Demo osgcubemap" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=Demo osgcubemap - 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 "osgcubemap.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 "osgcubemap.mak" CFG="Demo osgcubemap - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Demo osgcubemap - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "Demo osgcubemap - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Demo osgcubemap - 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 "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# 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 /subsystem:console /machine:I386 +# ADD LINK32 /nologo /subsystem:console /pdb:none /machine:I386 /out:"../../../bin/osgcubemap.exe" /libpath:"../../../lib" + +!ELSEIF "$(CFG)" == "Demo osgcubemap - 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 "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MDd /W3 /Gm /vd0 /GR /GX /Zi /Od /I "../../../include" /D "_CONSOLE" /D "_MBCS" /D "FL_DLL" /D "WIN32" /D "_DEBUG" /FR /YX /FD /c +# 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 /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"libcmt" /out:"../../../bin/osgcubemapd.exe" /pdbtype:sept /libpath:"../../../lib" +# SUBTRACT LINK32 /incremental:no + +!ENDIF + +# Begin Target + +# Name "Demo osgcubemap - Win32 Release" +# Name "Demo osgcubemap - Win32 Debug" +# Begin Source File + +SOURCE=..\..\..\src\Demos\osgcubemap\osgcubemap.cpp +# End Source File +# End Target +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Project diff --git a/VisualStudio/VisualStudio.dsw b/VisualStudio/VisualStudio.dsw index 4801abcba..efafb1971 100644 --- a/VisualStudio/VisualStudio.dsw +++ b/VisualStudio/VisualStudio.dsw @@ -381,6 +381,33 @@ Package=<4> ############################################################################### +Project: "Demo osgcubemap"=.\Demos\osgcubemap\osgcubemap.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 + Begin Project Dependency + Project_Dep_Name Core osgGA + End Project Dependency + Begin Project Dependency + Project_Dep_Name Core osgGLUT + End Project Dependency + Begin Project Dependency + Project_Dep_Name Core osgUtil + End Project Dependency +}}} + +############################################################################### + Project: "Demo osgteapot"=.\Demos\osgteapot\osgteapot.dsp - Package Owner=<4> Package=<5> diff --git a/include/osgUtil/CubeMapGenerator b/include/osgUtil/CubeMapGenerator new file mode 100644 index 000000000..1ea30bff5 --- /dev/null +++ b/include/osgUtil/CubeMapGenerator @@ -0,0 +1,109 @@ +#ifndef OSGUTIL_CUBEMAPGENERATOR_ +#define OSGUTIL_CUBEMAPGENERATOR_ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace osgUtil +{ + + /** This is the base class for cube map generators. + It exposes the necessary interface to access the six generated images; + descendants should only override the compute_color() method. + */ + class OSGUTIL_EXPORT CubeMapGenerator: public osg::Referenced { + public: + explicit CubeMapGenerator(int texture_size = 64); + CubeMapGenerator(const CubeMapGenerator ©, const osg::CopyOp ©op = osg::CopyOp::SHALLOW_COPY); + + inline osg::Image *getImage(osg::TextureCubeMap::Face face); + inline const osg::Image *getImage(osg::TextureCubeMap::Face face) const; + + /** generate the six cube images. + If use_osg_system is true, then the OSG's coordinate system is used instead + of the default OpenGL one. + */ + void generateMap(bool use_osg_system = true); + + protected: + virtual ~CubeMapGenerator() {} + CubeMapGenerator &operator=(const CubeMapGenerator &) { return *this; } + + inline void set_pixel(int index, int c, int r, const osg::Vec4 &color); + inline static osg::Vec4 vector_to_color(const osg::Vec3 &vec); + + /** override this method to define how colors are computed. + The parameter R is the reflection vector, pointing from the center of the cube. + The return value should be the RGBA color associated with that reflection ray. + */ + virtual osg::Vec4 compute_color(const osg::Vec3 &R) const = 0; + + private: + int texture_size_; + + typedef std::vector > Image_list; + Image_list images_; + }; + + // INLINE METHODS + + inline osg::Image *CubeMapGenerator::getImage(osg::TextureCubeMap::Face face) + { + switch (face) { + case osg::TextureCubeMap::POSITIVE_X: return images_[0].get(); + case osg::TextureCubeMap::NEGATIVE_X: return images_[1].get(); + case osg::TextureCubeMap::POSITIVE_Y: return images_[2].get(); + case osg::TextureCubeMap::NEGATIVE_Y: return images_[3].get(); + case osg::TextureCubeMap::POSITIVE_Z: return images_[4].get(); + case osg::TextureCubeMap::NEGATIVE_Z: return images_[5].get(); + default: return 0; + } + } + + inline const osg::Image *CubeMapGenerator::getImage(osg::TextureCubeMap::Face face) const + { + switch (face) { + case osg::TextureCubeMap::POSITIVE_X: return images_[0].get(); + case osg::TextureCubeMap::NEGATIVE_X: return images_[1].get(); + case osg::TextureCubeMap::POSITIVE_Y: return images_[2].get(); + case osg::TextureCubeMap::NEGATIVE_Y: return images_[3].get(); + case osg::TextureCubeMap::POSITIVE_Z: return images_[4].get(); + case osg::TextureCubeMap::NEGATIVE_Z: return images_[5].get(); + default: return 0; + } + } + + inline void CubeMapGenerator::set_pixel(int index, int c, int r, const osg::Vec4 &color) + { + osg::Image *i = images_[index].get(); + if (i) { + *(i->data(c, r)+0) = static_cast(color.x() * 255); + *(i->data(c, r)+1) = static_cast(color.y() * 255); + *(i->data(c, r)+2) = static_cast(color.z() * 255); + *(i->data(c, r)+3) = static_cast(color.w() * 255); + } else { + osg::notify(osg::WARN) << "Warning: CubeMapGenerator::set_pixel(): invalid image index\n"; + } + } + + inline osg::Vec4 CubeMapGenerator::vector_to_color(const osg::Vec3 &vec) + { + return osg::Vec4( + vec.x() / vec.length() / 2 + 0.5f, + vec.y() / vec.length() / 2 + 0.5f, + vec.z() / vec.length() / 2 + 0.5f, + 1); + } + +} + +#endif diff --git a/include/osgUtil/HalfWayMapGenerator b/include/osgUtil/HalfWayMapGenerator new file mode 100644 index 000000000..1efcbbbfd --- /dev/null +++ b/include/osgUtil/HalfWayMapGenerator @@ -0,0 +1,41 @@ +#ifndef OSGUTIL_HALFWAYMAPGENERATOR_ +#define OSGUTIL_HALFWAYMAPGENERATOR_ + +#include + +#include + +namespace osgUtil +{ + + /** This cube map generator produces an Half-way vector map, useful for + hardware-based specular lighting effects. + It computes: C = normalize(R - L), where C is the resulting color, + R is the reflection vector and L is the light direction. + */ + class OSGUTIL_EXPORT HalfWayMapGenerator: public CubeMapGenerator { + public: + HalfWayMapGenerator(const osg::Vec3 &light_direction, int texture_size = 64); + HalfWayMapGenerator(const HalfWayMapGenerator ©, const osg::CopyOp ©op); + + protected: + virtual ~HalfWayMapGenerator() {} + HalfWayMapGenerator &operator=(const HalfWayMapGenerator &) { return *this; } + + inline virtual osg::Vec4 compute_color(const osg::Vec3 &R) const; + + private: + osg::Vec3 ldir_; + }; + + // INLINE METHODS + + inline osg::Vec4 HalfWayMapGenerator::compute_color(const osg::Vec3 &R) const + { + const osg::Vec3 V = (R / R.length()) - ldir_; + return vector_to_color(V / V.length()); + } + +} + +#endif diff --git a/include/osgUtil/HighlightMapGenerator b/include/osgUtil/HighlightMapGenerator new file mode 100644 index 000000000..8e219bace --- /dev/null +++ b/include/osgUtil/HighlightMapGenerator @@ -0,0 +1,51 @@ +#ifndef OSGUTIL_HIGHLIGHTMAPGENERATOR_ +#define OSGUTIL_HIGHLIGHTMAPGENERATOR_ + +#include + +#include + +namespace osgUtil +{ + + /** This cube map generator produces a specular highlight map. + The vector-color association is: C = (R dot (-L)) ^ n, where C is the + resulting color, R is the reflection vector, L is the light direction + and n is the specular exponent. + */ + class OSGUTIL_EXPORT HighlightMapGenerator: public CubeMapGenerator { + public: + HighlightMapGenerator( + const osg::Vec3 &light_direction, + const osg::Vec4 &light_color, + float specular_exponent, + int texture_size = 64); + + HighlightMapGenerator(const HighlightMapGenerator ©, const osg::CopyOp ©op = osg::CopyOp::SHALLOW_COPY); + + protected: + virtual ~HighlightMapGenerator() {} + HighlightMapGenerator &operator=(const HighlightMapGenerator &) { return *this; } + + inline virtual osg::Vec4 compute_color(const osg::Vec3 &R) const; + + private: + osg::Vec3 ldir_; + osg::Vec4 lcol_; + float sexp_; + }; + + // INLINE METHODS + + inline osg::Vec4 HighlightMapGenerator::compute_color(const osg::Vec3 &R) const + { + float v = -ldir_ * (R / R.length()); + if (v < 0) v = 0; + osg::Vec4 color(lcol_ * powf(v, sexp_)); + color.w() = 1; + return color; + } + +} + +#endif diff --git a/include/osgUtil/ReflectionMapGenerator b/include/osgUtil/ReflectionMapGenerator new file mode 100644 index 000000000..047301f5f --- /dev/null +++ b/include/osgUtil/ReflectionMapGenerator @@ -0,0 +1,43 @@ +#ifndef OSGUTIL_REFLECTIONMAPGENERATOR_ +#define OSGUTIL_REFLECTIONMAPGENERATOR_ + +#include + +namespace osgUtil +{ + + /** This is the most simple cube map generator. It performs a direct association + between reflection vector and RGBA color (C = R). + */ + class ReflectionMapGenerator: public CubeMapGenerator { + public: + inline ReflectionMapGenerator(int texture_size = 64); + inline ReflectionMapGenerator(const ReflectionMapGenerator ©, const osg::CopyOp ©op = osg::CopyOp::SHALLOW_COPY); + + protected: + virtual ~ReflectionMapGenerator() {} + ReflectionMapGenerator &operator=(const ReflectionMapGenerator &) { return *this; } + + inline virtual osg::Vec4 compute_color(const osg::Vec3 &R) const; + }; + + // INLINE METHODS + + inline ReflectionMapGenerator::ReflectionMapGenerator(int texture_size) + : CubeMapGenerator(texture_size) + { + } + + inline ReflectionMapGenerator::ReflectionMapGenerator(const ReflectionMapGenerator ©, const osg::CopyOp ©op) + : CubeMapGenerator(copy, copyop) + { + } + + inline osg::Vec4 ReflectionMapGenerator::compute_color(const osg::Vec3 &R) const + { + return vector_to_color(R / R.length()); + } + +} + +#endif diff --git a/src/Demos/osgcubemap/Makefile b/src/Demos/osgcubemap/Makefile new file mode 100644 index 000000000..3c745cb9d --- /dev/null +++ b/src/Demos/osgcubemap/Makefile @@ -0,0 +1,16 @@ +TOPDIR = ../../.. +include $(TOPDIR)/Make/makedefs + +CXXFILES =\ + osgcubemap.cpp\ + +LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) + +INSTFILES = \ + $(CXXFILES)\ + Makefile.inst=Makefile + +EXEC = osgcubemap + +include $(TOPDIR)/Make/makerules + diff --git a/src/Demos/osgcubemap/Makefile.inst b/src/Demos/osgcubemap/Makefile.inst new file mode 100644 index 000000000..0d4476d07 --- /dev/null +++ b/src/Demos/osgcubemap/Makefile.inst @@ -0,0 +1,12 @@ +TOPDIR = ../.. +include $(TOPDIR)/Make/makedefs + +CXXFILES =\ + osgcubemap.cpp\ + +LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) + +EXEC = osgcubemap + + +include $(TOPDIR)/Make/makerules diff --git a/src/Demos/osgcubemap/osgcubemap.cpp b/src/Demos/osgcubemap/osgcubemap.cpp new file mode 100644 index 000000000..e2b0664ee --- /dev/null +++ b/src/Demos/osgcubemap/osgcubemap.cpp @@ -0,0 +1,157 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +void write_usage(std::ostream& out, const std::string& name) +{ + out << std::endl; + out <<"usage:"<< std::endl; + out <<" "<getOrCreateStateSet(); + + // create and setup the texture object + osg::TextureCubeMap *tcm = osgNew osg::TextureCubeMap; + tcm->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP); + tcm->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP); + tcm->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP); + tcm->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR); + tcm->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); + + // generate the six highlight map images (light direction = [1, 1, -1]) + osgUtil::HighlightMapGenerator *mapgen = osgNew osgUtil::HighlightMapGenerator( + osg::Vec3(1, 1, -1), // light direction + osg::Vec4(1, 0.9f, 0.8f, 1), // light color + 8); // specular exponent + + mapgen->generateMap(); + + // assign the six images to the texture object + tcm->setImage(osg::TextureCubeMap::POSITIVE_X, mapgen->getImage(osg::TextureCubeMap::POSITIVE_X)); + tcm->setImage(osg::TextureCubeMap::NEGATIVE_X, mapgen->getImage(osg::TextureCubeMap::NEGATIVE_X)); + tcm->setImage(osg::TextureCubeMap::POSITIVE_Y, mapgen->getImage(osg::TextureCubeMap::POSITIVE_Y)); + tcm->setImage(osg::TextureCubeMap::NEGATIVE_Y, mapgen->getImage(osg::TextureCubeMap::NEGATIVE_Y)); + tcm->setImage(osg::TextureCubeMap::POSITIVE_Z, mapgen->getImage(osg::TextureCubeMap::POSITIVE_Z)); + tcm->setImage(osg::TextureCubeMap::NEGATIVE_Z, mapgen->getImage(osg::TextureCubeMap::NEGATIVE_Z)); + + // enable texturing, replacing any textures in the subgraphs + ss->setTextureAttributeAndModes(0, tcm, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON); + ss->setTextureMode(0, GL_TEXTURE_CUBE_MAP, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON); + + // texture coordinate generation + osg::TexGen *tg = osgNew osg::TexGen; + tg->setMode(osg::TexGen::REFLECTION_MAP); + ss->setTextureAttributeAndModes(0, tg, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON); + + // use TexEnvCombine to add the highlights to the original lighting + osg::TexEnvCombine *te = osgNew osg::TexEnvCombine; + te->setCombine_RGB(osg::TexEnvCombine::ADD); + te->setOperand0_RGB(osg::TexEnvCombine::TEXTURE0); + te->setOperand1_RGB(osg::TexEnvCombine::PRIMARY_COLOR); + ss->setTextureAttributeAndModes(0, te, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON); +} + +int main(int argc, char *argv[]) +{ + // initialize the GLUT + glutInit( &argc, argv ); + + if (argc<2) { + write_usage(std::cout, argv[0]); + return 0; + } + + // create the commandline args. + std::vector commandLine; + for(int i=1; i + +#include +#include + +using namespace osgUtil; + +CubeMapGenerator::CubeMapGenerator(int texture_size) +: osg::Referenced(), + texture_size_(texture_size) +{ + for (int i=0; i<6; ++i) { + osg::ref_ptr image = osgNew osg::Image; + std::auto_ptr data(static_cast(std::malloc(texture_size*texture_size*4))); + image->setImage(texture_size, texture_size, 1, 4, GL_RGBA, GL_UNSIGNED_BYTE, data.get()); + data.release(); + images_.push_back(image); + } +} + +CubeMapGenerator::CubeMapGenerator(const CubeMapGenerator ©, const osg::CopyOp ©op) +: osg::Referenced(copy), + texture_size_(copy.texture_size_) +{ + Image_list::const_iterator i; + for (i=copy.images_.begin(); i!=copy.images_.end(); ++i) { + images_.push_back(static_cast(copyop(i->get()))); + } +} + +void CubeMapGenerator::generateMap(bool use_osg_system) +{ + const float duv = 2.0f/(texture_size_-1); + + float v = 1; + for (int i=0; i + +using namespace osgUtil; + +HalfWayMapGenerator::HalfWayMapGenerator(const osg::Vec3 &light_direction, int texture_size) +: CubeMapGenerator(texture_size), + ldir_(light_direction) +{ + ldir_.normalize(); +} + +HalfWayMapGenerator::HalfWayMapGenerator(const HalfWayMapGenerator ©, const osg::CopyOp ©op) +: CubeMapGenerator(copy, copyop), + ldir_(copy.ldir_) +{ +} diff --git a/src/osgUtil/HighlightMapGenerator.cpp b/src/osgUtil/HighlightMapGenerator.cpp new file mode 100644 index 000000000..28d4ad81c --- /dev/null +++ b/src/osgUtil/HighlightMapGenerator.cpp @@ -0,0 +1,23 @@ +#include + +using namespace osgUtil; + +HighlightMapGenerator::HighlightMapGenerator(const osg::Vec3 &light_direction, + const osg::Vec4 &light_color, + float specular_exponent, + int texture_size) +: CubeMapGenerator(texture_size), + ldir_(light_direction), + lcol_(light_color), + sexp_(specular_exponent) +{ + ldir_.normalize(); +} + +HighlightMapGenerator::HighlightMapGenerator(const HighlightMapGenerator ©, const osg::CopyOp ©op) +: CubeMapGenerator(copy, copyop), + ldir_(copy.ldir_), + lcol_(copy.lcol_), + sexp_(copy.sexp_) +{ +} diff --git a/src/osgUtil/Makefile b/src/osgUtil/Makefile index fced6495c..cd26ab76a 100644 --- a/src/osgUtil/Makefile +++ b/src/osgUtil/Makefile @@ -22,6 +22,9 @@ CXXFILES = \ Tesselator.cpp\ TransformCallback.cpp\ TriStripVisitor.cpp\ + CubeMapGenerator.cpp\ + HalfWayMapGenerator.cpp\ + HighlightMapGenerator.cpp\ Version.cpp\ DEF += -DOSGUTIL_LIBRARY