src/waterplan.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2007 by                                                 *
00003  *         Pierre-yves JEZEQUEL, Julien MICHOT, Loic MOISAN,               *
00004  *         Julien PAPILLON, Sebastien PINEAUD, Barthelemy SERRES           *
00005  *                                                                         *
00006  *   https://sourceforge.net/projects/anidam                               *
00007  *                                                                         *
00008  *   This program is free software; you can redistribute it and/or modify  *
00009  *   it under the terms of the GNU General Public License as published by  *
00010  *   the Free Software Foundation; either version 2 of the License, or     *
00011  *   (at your option) any later version.                                   *
00012  *                                                                         *
00013  *   This program is distributed in the hope that it will be useful,       *
00014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00016  *   GNU General Public License for more details.                          *
00017  *                                                                         *
00018  *   You should have received a copy of the GNU General Public License     *
00019  *   along with this program; if not, write to the                         *
00020  *   Free Software Foundation, Inc.,                                       *
00021  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00022  ***************************************************************************/
00023 #include "waterplan.h"
00024 
00025 
00026 
00027 class ConstructStateCallback : public osgProducer::OsgCameraGroup::RealizeCallback
00028 {
00029         public:
00030                 ConstructStateCallback(osg::Node* node1,osg::Node* node2):_node1(node1),_node2(node2),_initialized(false) {}
00031         
00032                 osg::StateSet* constructState(osg::Node* _node)
00033                 {
00034         
00035             // read 4 2d images
00036                         osg::ref_ptr<osg::Image> image_0 = osgDB::readImageFile("Textures/eau.jpg");
00037                         osg::ref_ptr<osg::Image> image_1 = osgDB::readImageFile("Textures/eau2.jpg");
00038                         osg::ref_ptr<osg::Image> image_2 = osgDB::readImageFile("Textures/eau111.jpg");
00039                         osg::ref_ptr<osg::Image> image_3 = osgDB::readImageFile("Textures/eau2.jpg");
00040 
00041                         if (!image_0 || !image_1 || !image_2 || !image_3)
00042                         {
00043                                 std::cout << "Warning: could not open files."<<std::endl;
00044                                 return new osg::StateSet;
00045                         }
00046 
00047                         if (image_0->getPixelFormat()!=image_1->getPixelFormat() || image_0->getPixelFormat()!=image_2->getPixelFormat() || image_0->getPixelFormat()!=image_3->getPixelFormat())
00048                         {
00049                                 std::cout << "Warning: image pixel formats not compatible."<<std::endl;
00050                                 return new osg::StateSet;
00051                         }
00052                         
00053             // get max 3D texture size
00054                         GLint textureSize = osg::Texture3D::getExtensions(0,true)->maxTexture3DSize();
00055                         if (textureSize > 256)
00056                                 textureSize = 256;
00057 
00058             // scale them all to the same size.
00059                         image_0->scaleImage(textureSize,textureSize,1);
00060                         image_1->scaleImage(textureSize,textureSize,1);
00061                         image_2->scaleImage(textureSize,textureSize,1);
00062                         image_3->scaleImage(textureSize,textureSize,1);
00063 
00064 
00065             // then allocated a 3d image to use for texturing.
00066                         osg::Image* image_3d = new osg::Image;
00067                         image_3d->allocateImage(textureSize,textureSize,4,
00068                                         image_0->getPixelFormat(),image_0->getDataType());
00069 
00070             // copy the 2d images into the 3d image.
00071                         image_3d->copySubImage(0,0,0,image_0.get());
00072                         image_3d->copySubImage(0,0,1,image_1.get());
00073                         image_3d->copySubImage(0,0,2,image_2.get());
00074                         image_3d->copySubImage(0,0,3,image_3.get());
00075 
00076                         image_3d->setInternalTextureFormat(image_0->getInternalTextureFormat());        
00077 
00078             // set up the 3d texture itself,
00079             // note, well set the filtering up so that mip mapping is disabled,
00080             // gluBuild3DMipsmaps doesn't do a very good job of handled the
00081             // inbalanced dimensions of the 256x256x4 texture.
00082                         osg::Texture3D* texture3D = new osg::Texture3D;//WRAP_S, osg::Texture2D::REPEAT
00083                         texture3D->setFilter(osg::Texture3D::MIN_FILTER,osg::Texture3D::LINEAR);
00084                         texture3D->setFilter(osg::Texture3D::MAG_FILTER,osg::Texture3D::LINEAR);
00085                         texture3D->setWrap(osg::Texture3D::WRAP_S,osg::Texture3D::REPEAT);
00086                         texture3D->setWrap(osg::Texture3D::WRAP_T,osg::Texture3D::REPEAT);
00087                         texture3D->setWrap(osg::Texture3D::WRAP_R,osg::Texture3D::REPEAT);
00088                         texture3D->setImage(image_3d);
00089 
00090 
00091             // create a texgen to generate a R texture coordinate, the geometry
00092             // itself will supply the S & T texture coordinates.
00093             // in the animateStateSet callback well alter this R value to
00094             // move the texture through the 3d texture, 3d texture filtering
00095             // will do the blending for us.
00096                         osg::TexGen* texgen = new osg::TexGen;
00097                         texgen->setMode(osg::TexGen::OBJECT_LINEAR);
00098                         
00099                         if (_node1 == _node )
00100                                 texgen->setPlane(osg::TexGen::R, osg::Vec4(1.0f,0.0f,0.0f,0.2f));
00101                         else
00102                                 texgen->setPlane(osg::TexGen::R, osg::Vec4(-0.4f,0.3f,0.3f,0.1f));
00103                         //texgen->setPlane(osg::TexGen::R, osg::Vec4(0.5f,0.3f,0.0f,0.5f));
00104 
00105             // create the StateSet to store the texture data
00106                         osg::StateSet* stateset = _node->getOrCreateStateSet();//new osg::StateSet;
00107                         
00108                         stateset->setTextureMode(0,GL_TEXTURE_GEN_R,osg::StateAttribute::ON);
00109                         stateset->setTextureAttribute(0,texgen);
00110                         stateset->setTextureAttributeAndModes(0,texture3D,osg::StateAttribute::ON);
00111 
00112                         return stateset;
00113                 }
00114 
00115                 virtual void operator()( osgProducer::OsgCameraGroup&, osgProducer::OsgSceneHandler& sh, const Producer::RenderSurface& )
00116                 {
00117                         {
00118                                 OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
00119 
00120                                 if (!_initialized)
00121                                 {
00122 
00123                     // only initialize state once, only need for cases where multiple graphics contexts are
00124                     // if which case this callback can get called multiple times.
00125                                         _initialized = true;
00126 
00127                                         if (_node1) _node1->setStateSet(constructState(_node1));
00128                                         if (_node2) _node2->setStateSet(constructState(_node2));
00129                                 }          
00130                                      
00131 
00132                         }
00133             
00134             // now safe to con
00135                         sh.init();
00136             
00137                 }
00138         
00139         
00140                 OpenThreads::Mutex  _mutex;
00141                 bool                _initialized;
00142                 osg::Node*          _node1;
00143                 osg::Node*          _node2;
00144         
00145 };
00146 
00147 class UpdateStateCallback : public osg::NodeCallback
00148 {
00149         public:
00150                 osg::Vec4 depl ;
00151         public:
00152                 UpdateStateCallback(osg::Vec4 d):depl(d) {}
00153         
00154                 void animateState(osg::StateSet* stateset)
00155                 {
00156             // here we simply get any existing texgen, and then increment its
00157             // plane, pushing the R coordinate through the texture.
00158                         osg::StateAttribute* attribute = stateset->getTextureAttribute(0,osg::StateAttribute::TEXGEN);
00159                         osg::TexGen* texgen = dynamic_cast<osg::TexGen*>(attribute);
00160                         if (texgen)
00161                         {
00162                                 //0.5f,0.3f,0.0f,0.5f
00163                                 
00164                                 texgen->getPlane(osg::TexGen::R)[0] = depl.x();
00165                                 texgen->getPlane(osg::TexGen::R)[1] = depl.y();
00166                                 texgen->getPlane(osg::TexGen::R)[2] = depl.z();
00167                                 texgen->getPlane(osg::TexGen::R)[3] += depl.w();
00168                                 
00169                                 /*texgen->getPlane(osg::TexGen::R)[3] += 0.005f;
00170                                 texgen->getPlane(osg::TexGen::R)[0] = 0.021f;
00171                                 texgen->getPlane(osg::TexGen::R)[1] = 0.001f;
00172                                 texgen->getPlane(osg::TexGen::R)[2] = 0.021f;
00173                                 
00174                                 
00175                                 /*    
00176                                 texgen->getPlane(osg::TexGen::R)[0] += 0.0015f;
00177                                 texgen->getPlane(osg::TexGen::R)[1] += 0.001f;
00178                                 texgen->getPlane(osg::TexGen::R)[2] += 0.002f;
00179                                 texgen->getPlane(osg::TexGen::R)[3] += 0.001f;   */
00180                         }
00181 
00182                 }
00183 
00184                 virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
00185                 { 
00186 
00187                         osg::StateSet* stateset = node->getStateSet();
00188                         if (stateset)
00189                         {
00190                         // we have an exisitng stateset, so lets animate it.
00191                                 animateState(stateset);
00192                         }
00193 
00194                         // note, callback is repsonsible for scenegraph traversal so
00195                         // should always include call the traverse(node,nv) to ensure 
00196                         // that the rest of cullbacks and the scene graph are traversed.
00197                         traverse(node,nv);
00198                 }      
00199 };
00200 
00201 waterPlan::waterPlan()
00202 {
00203         water_geometry=NULL;
00204         water_geode=NULL;
00205         deplacement_texture =  osg::Vec4(0.021f,0.001f,0.021f,0.005f);
00206         densite_texture=25;
00207 }
00208 
00209 
00210 waterPlan::~waterPlan()
00211 {
00212 }
00213 
00214 
00215 void waterPlan::setPlan(float xMin,float xMax,float yMin,float yMax,float z)
00216 {
00217         this->xMin=xMin;
00218         this->xMax=xMax;
00219         this->yMin=yMin;
00220         this->yMax=yMax;
00221         this->z=z;
00222 }
00223 void waterPlan::setTexture(std::string tex, float densite)
00224 {
00225         this->densite_texture=densite;
00226         this->texture = tex;
00227         
00228 }
00229 void waterPlan::setDeplacementWater(osg::Vec4 depl)
00230 {
00231         deplacement_texture = depl;
00232         
00233 }
00234 osg::Drawable* waterPlan::createMirrorSurface()
00235 {
00236         // ou plan blender + recup statesate + modif la fausse texture pour mettre la notre
00237     
00238         float densite_texture2=densite_texture;
00239         float d_txtX = densite_texture/(xMax - xMin) ;
00240         float d_txtY = densite_texture/(yMax - yMin);
00241     // set up the drawstate.
00242 
00243     // set up the Geometry.
00244          water_geometry = new osg::Geometry;
00245 
00246          osg::Vec3Array* coords = new osg::Vec3Array(5);
00247          (*coords)[0].set(xMin-16.5,yMax-20,z);
00248          (*coords)[1].set(xMin-27.5,yMax+0,z);
00249         (*coords)[2].set(xMin,yMin,z);
00250         (*coords)[3].set(xMax,yMin,z);
00251         (*coords)[4].set(xMax+11,yMax,z);
00252         water_geometry->setVertexArray(coords);
00253 
00254         osg::Vec3Array* norms = new osg::Vec3Array(1);
00255         (*norms)[0].set(0.0f,0.0f,1.0f);
00256         water_geometry->setNormalArray(norms);
00257         water_geometry->setNormalBinding(osg::Geometry::BIND_OVERALL);
00258 
00259         osg::Vec2Array* tcoords = new osg::Vec2Array(5);
00260         (*tcoords)[0].set(0.0f-15.5*d_txtX,densite_texture2*4-20*d_txtY*4);
00261         (*tcoords)[1].set(0.0f-27.5*d_txtX,densite_texture2*4);
00262         (*tcoords)[2].set(0.0f,0.0f);
00263         (*tcoords)[3].set(densite_texture2,0.0f);
00264         (*tcoords)[4].set(densite_texture2+12*d_txtX,densite_texture2*4);
00265         water_geometry->setTexCoordArray(0,tcoords);
00266     
00267         
00268         osg::Vec4Array* colours = new osg::Vec4Array(1);
00269         (*colours)[0].set(0.8f,0.8f,0.8f,0.7f);
00270         water_geometry->setColorArray(colours);
00271         water_geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
00272         
00273 
00274         water_geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,0,5));
00275         
00276         
00277 
00278         return water_geometry;
00279 }
00280 
00281 osg::Drawable* waterPlan::createMirrorSurfaceForTheDam(float x)
00282 {
00283         // ou plan blender + recup statesate + modif la fausse texture pour mettre la notre
00284     
00285         float dx=6.3;
00286         float dy=3.0;
00287         float dx2=2.2;
00288         float dx_texture=densite_texture * dx/(xMax - xMin) ;
00289         float dx_texture2=densite_texture * dx2/(xMax - xMin) ;
00290         float dy_texture=densite_texture * dy/(yMax - yMin);
00291         float d_txtX = densite_texture/(xMax - xMin) ;
00292         float d_txtY = densite_texture/(yMax - yMin);
00293     // set up the drawstate.
00294 
00295     // set up the Geometry.
00296         water_geometry = new osg::Geometry;
00297         
00298         int i=0;
00299 
00300         osg::Vec3Array* coords = new osg::Vec3Array(11);
00301         (*coords)[i++].set(xMin,yMax-36,z);
00302         (*coords)[i++].set(xMin+35,yMin,z);
00303         (*coords)[i++].set(x-dx,yMin,z);
00304         (*coords)[i++].set(x-dx2,yMin+dy,z);
00305         (*coords)[i++].set(x,yMin+dy,z);
00306         (*coords)[i++].set(x,yMax+14,z);
00307         (*coords)[i++].set(x,yMin+dy,z);
00308         (*coords)[i++].set(x+dx2,yMin+dy,z);
00309         (*coords)[i++].set(x+dx,yMin,z);
00310         (*coords)[i++].set(xMax+23,yMin+10,z);
00311         (*coords)[i++].set(xMax-45,yMax+36,z);
00312         water_geometry->setVertexArray(coords);
00313 
00314         osg::Vec3Array* norms = new osg::Vec3Array(2);
00315         (*norms)[0].set(0.0f,0.0f,1.0f);
00316         (*norms)[1].set(0.0f,0.0f,1.0f);
00317         water_geometry->setNormalArray(norms);
00318         water_geometry->setNormalBinding(osg::Geometry::BIND_OVERALL);//BIND_PER_VERTEX);
00319 
00320         i=0;
00321         osg::Vec2Array* tcoords = new osg::Vec2Array(11);
00322         (*tcoords)[i++].set(0.0f,densite_texture-37*d_txtY);
00323         (*tcoords)[i++].set(0.0f+35*d_txtX,0.0f);
00324         (*tcoords)[i++].set(densite_texture/2.-dx_texture,0.0f);
00325         (*tcoords)[i++].set(densite_texture/2.-dx_texture2,dy_texture);
00326         (*tcoords)[i++].set(densite_texture/2.,dy_texture);
00327         (*tcoords)[i++].set(densite_texture/2.,densite_texture+14*d_txtY);
00328         (*tcoords)[i++].set(densite_texture/2.,dy_texture);
00329         (*tcoords)[i++].set(densite_texture/2.+dx_texture2,dy_texture);
00330         (*tcoords)[i++].set(densite_texture/2.+dx_texture,0.0f);
00331         (*tcoords)[i++].set(densite_texture+24*d_txtX,0.0f+10*d_txtY);
00332         (*tcoords)[i++].set(densite_texture-46*d_txtX,densite_texture+36*d_txtY);
00333         water_geometry->setTexCoordArray(0,tcoords);
00334     
00335         osg::Vec4Array* colours = new osg::Vec4Array(1);
00336         (*colours)[0].set(1.0f,1.0f,1.0,0.7f);
00337         water_geometry->setColorArray(colours);
00338         water_geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
00339         
00340         water_geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,0,6));
00341         water_geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,5,6));
00342         
00343 
00344         return water_geometry;
00345 }
00346 
00347 osg::Drawable* waterPlan::createSurfaceBehindForTheDam(float x,float dz)
00348 {
00349         // ou plan blender + recup statesate + modif la fausse texture pour mettre la notre
00350     
00351         float dx=6.3;
00352         float dy=3.0;
00353         float dx2=2.2;
00354         float dx_texture=densite_texture * dx/(xMax - xMin) ;
00355         float dx_texture2=densite_texture * dx2/(xMax - xMin) ;
00356         float dy_texture=densite_texture * dy/(yMax - yMin);
00357         float d_txtX = densite_texture/(xMax - xMin) ;
00358         float d_txtY = densite_texture/(yMax - yMin);
00359     // set up the drawstate.
00360 
00361     // set up the Geometry.
00362         water_geometry = new osg::Geometry;
00363         
00364         int i=0;
00365 
00366         osg::Vec3Array* coords = new osg::Vec3Array(11);
00367         (*coords)[i++].set(xMin,yMax-36,z+dz);
00368         (*coords)[i++].set(xMin+35,yMin,z+dz);
00369         (*coords)[i++].set(x-dx,yMin,z+dz);
00370         (*coords)[i++].set(x-dx2,yMin+dy,z+dz);
00371         (*coords)[i++].set(x,yMin+dy,z+dz);
00372         (*coords)[i++].set(x,yMax+14,z+dz);
00373         (*coords)[i++].set(x,yMin+dy,z+dz);
00374         (*coords)[i++].set(x+dx2,yMin+dy,z+dz);
00375         (*coords)[i++].set(x+dx,yMin,z+dz);
00376         (*coords)[i++].set(xMax+23,yMin+10,z+dz);
00377         (*coords)[i++].set(xMax-45,yMax+36,z+dz);
00378         water_geometry->setVertexArray(coords);
00379 
00380         osg::Vec3Array* norms = new osg::Vec3Array(1);
00381         (*norms)[0].set(0.0f,0.0f,-1.0f);
00382         water_geometry->setNormalArray(norms);
00383         water_geometry->setNormalBinding(osg::Geometry::BIND_OVERALL);//BIND_PER_VERTEX);
00384 
00385         i=0;
00386         osg::Vec2Array* tcoords = new osg::Vec2Array(11);
00387         (*tcoords)[i++].set(0.0f,densite_texture);
00388         (*tcoords)[i++].set(0.0f,0.0f);
00389         (*tcoords)[i++].set(densite_texture/2.-dx_texture,0.0f);
00390         (*tcoords)[i++].set(densite_texture/2.-dx_texture2,dy_texture);
00391         (*tcoords)[i++].set(densite_texture/2.,dy_texture);
00392         (*tcoords)[i++].set(densite_texture/2.,densite_texture);
00393         (*tcoords)[i++].set(densite_texture/2.,dy_texture);
00394         (*tcoords)[i++].set(densite_texture/2.+dx_texture2,dy_texture);
00395         (*tcoords)[i++].set(densite_texture/2.+dx_texture,0.0f);
00396         (*tcoords)[i++].set(densite_texture,0.0f);
00397         (*tcoords)[i++].set(densite_texture,densite_texture);
00398         water_geometry->setTexCoordArray(0,tcoords);
00399     
00400         osg::Vec4Array* colours = new osg::Vec4Array(1);
00401         (*colours)[0].set(0.0f,0.0f,0.05f,0.2f);
00402         water_geometry->setColorArray(colours);
00403         water_geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
00404         
00405         water_geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,0,6));
00406         water_geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON,5,6));
00407         
00408 
00409         return water_geometry;
00410 }
00411 osg::Drawable* waterPlan::getOrCreateDrawable()
00412 {
00413         if(water_geometry==NULL)
00414                 return createMirrorSurface();
00415         else
00416                 return water_geometry;
00417 }
00418 
00419 osg::StateSet* waterPlan::createMirrorTexturedState()
00420 {
00421         osg::StateSet* dstate = new osg::StateSet;
00422         
00423         
00424         //return dstate; //////////////////     
00425         
00426         dstate->setMode(GL_CULL_FACE,osg::StateAttribute::OFF|osg::StateAttribute::PROTECTED);
00427     // set up the texture.
00428         if(texture!="")
00429         {
00430                 osg::Image* image = osgDB::readImageFile(texture.c_str());
00431                 if (image)
00432                 {
00433                         osg::Texture2D* texture = new osg::Texture2D;
00434                         texture->setImage(image);
00435                         texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT);
00436                         texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT);
00437                         dstate->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON|osg::StateAttribute::PROTECTED);
00438                         
00439                 }
00440         }
00441         return dstate;
00442 }
00443 
00444 osg::Geode* waterPlan::getOrCreateGeodeWater(osg::StateSet* stateset)
00445 {
00446         if(water_geode==NULL)
00447         {
00448                 if(water_geometry==NULL)
00449                         createMirrorSurface();
00450                 
00451                 water_geode =  new osg::Geode;
00452                 water_geode->addDrawable(water_geometry);
00453                 
00454                 water_geode->setStateSet(stateset);
00455                 
00456                 
00457                 
00458                 
00459                 UpdateStateCallback* update= new UpdateStateCallback(deplacement_texture);
00460                 //if(update && update->depl )
00461                         //update->depl->set(deplacement_texture.x(),deplacement_texture.y(),deplacement_texture.z(),deplacement_texture.w());
00462                 water_geode->setUpdateCallback(update);
00463                 
00464                                 /*texgen->getPlane(osg::TexGen::R)[3] += 0.005f;
00465                 texgen->getPlane(osg::TexGen::R)[0] = 0.021f;
00466                 texgen->getPlane(osg::TexGen::R)[1] = 0.001f;
00467                 texgen->getPlane(osg::TexGen::R)[2] = 0.021f;
00468                 */
00469                 
00470                 return water_geode;
00471                 
00472         }else
00473                 return water_geode;
00474 }
00475 
00476 osg::Geode* waterPlan::createGeodeUnderWater(float x,float dz)
00477 {
00478         osg::StateSet* stateset = createMirrorTexturedState();//new osg::StateSet();
00479         
00480         osg::Geode * under_water_geode =  new osg::Geode;
00481         
00482         under_water_geode->addDrawable(createSurfaceBehindForTheDam(x,dz));
00483                 
00484         under_water_geode->setStateSet(stateset);
00485 
00486         return under_water_geode;
00487 }
00489 ConstructStateCallback* waterPlan::getStateCallback(osg::Node* node1,osg::Node* node2)
00490 {
00491         
00492         ConstructStateCallback* cscb = new ConstructStateCallback(node1,node2);
00493 
00494         
00495         return cscb;
00496         
00497 }

Generated on Tue Jun 5 16:56:49 2007 for Anidam by  doxygen 1.5.1