/**************************************************************************\ * * This file is part of the Coin 3D visualization library. * Copyright (C) 1998-2007 by Systems in Motion. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * ("GPL") version 2 as published by the Free Software Foundation. * See the file LICENSE.GPL at the root directory of this source * distribution for additional information about the GNU GPL. * * For using Coin with software that can not be combined with the GNU * GPL, and for taking advantage of the additional benefits of our * support services, please contact Systems in Motion about acquiring * a Coin Professional Edition License. * * See http://www.coin3d.org/ for more information. * * Systems in Motion, Postboks 1283, Pirsenteret, 7462 Trondheim, NORWAY. * http://www.sim.no/ sales@sim.no coin-support@coin3d.org * \**************************************************************************/ /*! \class SoTextureCoordinateEnvironment SoTextureCoordinateEnvironment.h Inventor/nodes/SoTextureCoordinateEnvironment.h \brief The SoTextureCoordinateEnvironment class generates texture coordinates by projecting onto a surrounding texture. \ingroup nodes The texture specifying the enviroment will be mapped around the scenegraph below this node using a sphere. The texture will be mapped onto the scenegraph taking camera position into account. This will lead to an object reflecting its enviroment. Here is a scenegraph example showing how enviroment mapping can be applied to an object: #Inventor V2.1 ascii Separator { Texture2 { filename "ocean.jpg" # the enviroment, in this case ocean } TextureCoordinateEnvironment {} Cube {} # the enviromentally mapped object } FILE FORMAT/DEFAULTS: \code TextureCoordinateEnvironment { } \endcode */ // ************************************************************************* // FIXME: Can this somehow relate to 3D textures? (kintel 20020203) #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #include #include // ************************************************************************* class SoTextureCoordinateEnvironmentP { public: static SbVec4f * dummy_texcoords; static void cleanup_func(void); }; SbVec4f * SoTextureCoordinateEnvironmentP::dummy_texcoords = NULL; void SoTextureCoordinateEnvironmentP::cleanup_func(void) { delete SoTextureCoordinateEnvironmentP::dummy_texcoords; } // ************************************************************************* SO_NODE_SOURCE(SoTextureCoordinateEnvironment); /*! Constructor. */ SoTextureCoordinateEnvironment::SoTextureCoordinateEnvironment() { SO_NODE_INTERNAL_CONSTRUCTOR(SoTextureCoordinateEnvironment); } /*! Destructor. */ SoTextureCoordinateEnvironment::~SoTextureCoordinateEnvironment() { } // doc in super void SoTextureCoordinateEnvironment::initClass(void) { SO_NODE_INTERNAL_INIT_CLASS(SoTextureCoordinateEnvironment, SO_FROM_INVENTOR_1); SoTextureCoordinateEnvironmentP::dummy_texcoords = new SbVec4f(0.0f, 0.0f, 0.0f, 1.0f); coin_atexit((coin_atexit_f *)SoTextureCoordinateEnvironmentP::cleanup_func, CC_ATEXIT_NORMAL); } // generates texture coordinates for GLRender, callback and pick actions const SbVec4f & SoTextureCoordinateEnvironment::generate(void *userdata, const SbVec3f & /* p */, const SbVec3f &n) { // // from formula in the Red Book // SoState *state = (SoState*)userdata; SbVec3f wn; // normal in world (eye) coordinates SoModelMatrixElement::get(state).multDirMatrix(n, wn); SbVec3f u = n; u.normalize(); wn.normalize(); // reflection vector SbVec3f r = u - SbVec3f(2.0f*wn[0]*wn[0]*u[0], 2.0f*wn[1]*wn[1]*u[1], 2.0f*wn[2]*wn[2]*u[2]); r.normalize(); float tmp = 1.0f + r[2]; float m = 2.0f * (float)sqrt(r[0]*r[0] + r[1]*r[1] + tmp*tmp); // in case an empty normal was supplied if (fabs(m) <= FLT_EPSILON) m = 1.0f; (*SoTextureCoordinateEnvironmentP::dummy_texcoords)[0] = r[0] / m + 0.5f; (*SoTextureCoordinateEnvironmentP::dummy_texcoords)[1] = r[1] / m + 0.5f; return *SoTextureCoordinateEnvironmentP::dummy_texcoords; } // doc from parent void SoTextureCoordinateEnvironment::doAction(SoAction * action) { SoTextureCoordinateElement::setFunction(action->getState(), this, generate, action->getState()); } // doc from parent void SoTextureCoordinateEnvironment::GLRender(SoGLRenderAction * action) { SoState * state = action->getState(); int unit = SoTextureUnitElement::get(state); if (unit == 0) { SoTextureCoordinateEnvironment::doAction((SoAction *)action); SoGLTextureCoordinateElement::setTexGen(action->getState(), this, handleTexgen, NULL, generate, action->getState()); } else { SoMultiTextureCoordinateElement::setFunction(action->getState(), this, unit, generate, action->getState()); SoGLMultiTextureCoordinateElement::setTexGen(action->getState(), this, unit, handleTexgen, NULL, generate, action->getState()); } } // doc from parent void SoTextureCoordinateEnvironment::callback(SoCallbackAction * action) { SoTextureCoordinateEnvironment::doAction((SoAction *)action); } // doc from parent void SoTextureCoordinateEnvironment::pick(SoPickAction * action) { SoTextureCoordinateEnvironment::doAction((SoAction *)action); } void SoTextureCoordinateEnvironment::handleTexgen(void * /* data */) { #if 0 // from red book glTexGenfv(GL_S, GL_SPHERE_MAP, 0); glTexGenfv(GL_T, GL_SPHERE_MAP, 0); #else // from siggraph 96 glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); #endif // supply dummy plane for R and Q so that texture generation works // properly glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); float plane[4]; plane[0] = 0.0f; plane[1] = 0.0f; plane[2] = 0.0f; plane[3] = 1.0f; glTexGenfv(GL_R, GL_OBJECT_PLANE, plane); glTexGenfv(GL_Q, GL_OBJECT_PLANE, plane); }