Changeset 106
- Timestamp:
- Jun 14, 2005, 1:28:07 PM (20 years ago)
- Location:
- Swollen
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
Swollen/include/swwreader.h
r105 r106 103 103 virtual triangle_list getConnectivity(unsigned int index) {return _connectivity.at(index);} 104 104 105 const std::string getSwollenDir() {return *_swollendir;} 106 virtual void setSwollenDir(const std::string path) {_swollendir = new std::string(path);} 107 105 108 106 109 protected: … … 109 112 110 113 std::string* _filename; 114 std::string* _swollendir; 111 115 112 116 // constructor determines SWW validity (netcdf + proper structure) -
Swollen/swollen/createSky.cpp
r65 r106 44 44 45 45 46 osg::Transform* createSky(float radius, c har*filename)46 osg::Transform* createSky(float radius, const std::string filename) 47 47 { 48 48 osg::Geode* geode = new osg::Geode; … … 53 53 texture->setDataVariance(osg::Object::DYNAMIC); // protect from being optimized away as static state. 54 54 texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); 55 texture->setImage(osgDB::readImageFile(filename ));55 texture->setImage(osgDB::readImageFile(filename.c_str())); 56 56 57 57 osg::StateSet* stateset = new osg::StateSet; -
Swollen/swollen/main.cpp
r105 r106 1 1 /* 2 3 4 5 2 SWWViewer 3 4 An OpenSceneGraph viewer for pyVolution SWW files. 5 copyright (C) 2004-2005 Geoscience Australia 6 6 */ 7 7 … … 12 12 #include <osg/PositionAttitudeTransform> 13 13 #include <osg/StateAttribute> 14 #include <osgDB/FileNameUtils> 14 15 15 16 #include <project.h> … … 24 25 25 26 // prototypes 26 osg::Transform* createSky(float radius, c har*filename);27 osg::Transform* createSky(float radius, const std::string filename); 27 28 extern const char* version(); 28 29 … … 31 32 { 32 33 33 // use an ArgumentParser object to manage the program arguments 34 osg::ArgumentParser arguments(&argc,argv); 35 36 // set up the usage document 37 std::string appname = arguments.getApplicationName(); 38 arguments.getApplicationUsage()->setDescription( appname ); 39 arguments.getApplicationUsage()->setCommandLineUsage("swollen [options] swwfile ..."); 40 arguments.getApplicationUsage()->addCommandLineOption("-help","Display this information"); 41 arguments.getApplicationUsage()->addCommandLineOption("-scale <float>","Vertical scale factor"); 42 arguments.getApplicationUsage()->addCommandLineOption("-tps <rate>","Timesteps per second"); 43 arguments.getApplicationUsage()->addCommandLineOption("-hmin <float>","Height below which transparency is set to zero"); 44 arguments.getApplicationUsage()->addCommandLineOption("-hmax <float>","Height above which transparency is set to alphamax"); 45 arguments.getApplicationUsage()->addCommandLineOption("-alphamin <float 0-1>","Transparency value at hmin"); 46 arguments.getApplicationUsage()->addCommandLineOption("-alphamax <float 0-1>","Maximum transparency clamp value"); 47 arguments.getApplicationUsage()->addCommandLineOption("-lightpos <float>,<float>,<float>","x,y,z of bedslope directional light (z is up, default is overhead)"); 48 arguments.getApplicationUsage()->addCommandLineOption("-nosky","Omit background sky"); 49 arguments.getApplicationUsage()->addCommandLineOption("-cullangle <float angle 0-90>","Cull triangles steeper than this value"); 50 arguments.getApplicationUsage()->addCommandLineOption("-texture <file>","Image to use for bedslope topography"); 51 arguments.getApplicationUsage()->addCommandLineOption("-version","Revision number and creation (not compile) date"); 52 53 // construct the viewer. 54 CustomViewer viewer(arguments); 55 56 // set up with sensible default event handlers 57 viewer.setUpViewer( osgProducer::Viewer::STANDARD_SETTINGS ); 58 viewer.setClearColor( osg::Vec4(DEF_BACKGROUND_COLOUR) ); 59 //viewer.getCamera(0)->getRenderSurface()->setWindowRectangle(200,300,400,300); 60 viewer.getCullSettings().setComputeNearFarMode( osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES ); 61 62 63 // get details on keyboard and mouse bindings used by the viewer 64 viewer.getUsage(*arguments.getApplicationUsage()); 65 66 // if user requested help, write it out to cout 67 if( arguments.read("-help") ) 68 { 69 arguments.getApplicationUsage()->write(std::cout); 70 return 1; 71 } 72 73 // same for version info 74 if( arguments.read("-version") ) 75 { 76 std::cout << version() << std::endl; 77 return 1; 78 } 79 80 81 // load sww file specified as final argument on command line (static bedslope 82 // geometry only, per timestep height field geometry is done in loop below) 83 int lastarg = arguments.argc()-1; 84 std::string swwfile = arguments.argv()[lastarg]; 85 arguments.remove(lastarg); 86 if( swwfile.substr(swwfile.size()-4,4).find(".sww",0) == -1 ) // ensure filename ends in .sww 87 { 88 std::cout << "Require last argument be an .sww file ... quitting" << std::endl; 89 return 1; 90 } 91 SWWReader *sww = new SWWReader(swwfile); 92 if (sww->isValid() == false) 93 { 94 std::cout << "Unable to load " << swwfile << " ... is this really an .sww file?" << std::endl; 95 return 1; 96 } 97 98 99 // default arguments and command line parameters 100 float tmpfloat, tps, vscale; 101 if( !arguments.read("-tps", tps) || tps <= 0.0 ) tps = DEF_TPS; 102 if( !arguments.read("-scale", vscale) ) vscale = 1.0; 103 if( arguments.read("-hmin",tmpfloat) ) sww->setHeightMin( tmpfloat ); 104 if( arguments.read("-hmax",tmpfloat) ) sww->setHeightMax( tmpfloat ); 105 if( arguments.read("-alphamin",tmpfloat) ) sww->setAlphaMin( tmpfloat ); 106 if( arguments.read("-alphamax",tmpfloat) ) sww->setAlphaMax( tmpfloat ); 107 if( arguments.read("-cullangle",tmpfloat) ) sww->setCullAngle( tmpfloat ); 108 109 std::string bedslopetexture; 110 if( arguments.read("-texture",bedslopetexture) ) sww->setBedslopeTexture( bedslopetexture ); 111 112 // root node 113 osg::Group* rootnode = new osg::Group; 114 115 // transform 116 osg::PositionAttitudeTransform* model = new osg::PositionAttitudeTransform; 117 model->setName("position_attitude_transform"); 118 119 // enscapsulates OpenGL state 120 osg::StateSet* rootStateSet = new osg::StateSet; 121 122 // Bedslope geometry 123 BedSlope* bedslope = new BedSlope(sww); 124 125 // Water geometry 126 WaterSurface* water = new WaterSurface(sww); 127 128 // Heads Up Display (text overlay) 129 HeadsUpDisplay* hud = new HeadsUpDisplay(); 130 hud->setTitle("pyVolution SWW Viewer"); 131 132 133 // Lighting 134 DirectionalLight* light = new DirectionalLight(rootStateSet); 135 light->setPosition( osg::Vec3(1,1,1) ); // z is up 136 137 std::string lightposstr; 138 while (arguments.read("-lightpos",lightposstr)) 139 { 140 float x, y, z; 141 int count = sscanf( lightposstr.c_str(), "%f,%f,%f", &x, &y, &z ); 142 if( count == 3 ) light->setPosition( osg::Vec3(x,y,z) ); // z is up 143 else osg::notify(osg::WARN) << "Invalid bedslope light position \"" << lightposstr << "\"" << std::endl; 144 } 145 146 147 148 // scenegraph hierarchy 149 rootnode->setStateSet(rootStateSet); 150 rootnode->addChild( hud->get() ); 151 rootnode->addChild( light->get() ); 152 rootnode->addChild(model); 153 model->addChild( bedslope->get() ); 154 model->addChild( water->get() ); 155 156 157 // allow vertical scaling from command line parameter 158 model->setScale( osg::Vec3(1.0, 1.0, vscale) ); 159 160 // surrounding sky sphere 161 if( !arguments.read("-nosky") ) 162 rootnode->addChild( createSky(10.0, "sky_small.jpg") ); 163 164 165 // add model to viewer. 166 viewer.setSceneData(rootnode); 34 // use an ArgumentParser object to manage the program arguments 35 osg::ArgumentParser arguments( &argc, argv ); 36 37 // set up the usage document 38 std::string appname = arguments.getApplicationName(); 39 arguments.getApplicationUsage()->setDescription( appname ); 40 arguments.getApplicationUsage()->setCommandLineUsage("swollen [options] swwfile ..."); 41 arguments.getApplicationUsage()->addCommandLineOption("-help","Display this information"); 42 arguments.getApplicationUsage()->addCommandLineOption("-scale <float>","Vertical scale factor"); 43 arguments.getApplicationUsage()->addCommandLineOption("-tps <rate>","Timesteps per second"); 44 arguments.getApplicationUsage()->addCommandLineOption("-hmin <float>","Height below which transparency is set to zero"); 45 arguments.getApplicationUsage()->addCommandLineOption("-hmax <float>","Height above which transparency is set to alphamax"); 46 arguments.getApplicationUsage()->addCommandLineOption("-alphamin <float 0-1>","Transparency value at hmin"); 47 arguments.getApplicationUsage()->addCommandLineOption("-alphamax <float 0-1>","Maximum transparency clamp value"); 48 arguments.getApplicationUsage()->addCommandLineOption("-lightpos <float>,<float>,<float>","x,y,z of bedslope directional light (z is up, default is overhead)"); 49 arguments.getApplicationUsage()->addCommandLineOption("-nosky","Omit background sky"); 50 arguments.getApplicationUsage()->addCommandLineOption("-cullangle <float angle 0-90>","Cull triangles steeper than this value"); 51 arguments.getApplicationUsage()->addCommandLineOption("-texture <file>","Image to use for bedslope topography"); 52 arguments.getApplicationUsage()->addCommandLineOption("-version","Revision number and creation (not compile) date"); 53 54 // construct the viewer. 55 CustomViewer viewer(arguments); 56 57 // set up with sensible default event handlers 58 viewer.setUpViewer( osgProducer::Viewer::STANDARD_SETTINGS ); 59 viewer.setClearColor( osg::Vec4(DEF_BACKGROUND_COLOUR) ); 60 //viewer.getCamera(0)->getRenderSurface()->setWindowRectangle(200,300,400,300); 61 viewer.getCullSettings().setComputeNearFarMode( osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES ); 62 63 64 // get details on keyboard and mouse bindings used by the viewer 65 viewer.getUsage(*arguments.getApplicationUsage()); 66 67 // if user requested help, write it out to cout 68 if( arguments.read("-help") ) 69 { 70 arguments.getApplicationUsage()->write(std::cout); 71 return 1; 72 } 73 74 // same for version info 75 if( arguments.read("-version") ) 76 { 77 std::cout << version() << std::endl; 78 return 1; 79 } 80 81 82 // load sww file specified as final argument on command line (static bedslope 83 // geometry only, per timestep height field geometry is done in loop below) 84 int lastarg = arguments.argc()-1; 85 std::string swwfile = arguments.argv()[lastarg]; 86 arguments.remove(lastarg); 87 if( swwfile.substr(swwfile.size()-4,4).find(".sww",0) == -1 ) // ensure filename ends in .sww 88 { 89 std::cout << "Require last argument be an .sww file ... quitting" << std::endl; 90 return 1; 91 } 92 SWWReader *sww = new SWWReader(swwfile); 93 if (sww->isValid() == false) 94 { 95 std::cout << "Unable to load " << swwfile << " ... is this really an .sww file?" << std::endl; 96 return 1; 97 } 98 99 100 // relative directory to swollen binary 101 if( osgDB::getFilePath(argv[0]) == "" ) 102 sww->setSwollenDir( std::string(".") ); 103 else 104 sww->setSwollenDir( osgDB::getFilePath(argv[0]) ); 105 106 107 // default arguments and command line parameters 108 float tmpfloat, tps, vscale; 109 if( !arguments.read("-tps", tps) || tps <= 0.0 ) tps = DEF_TPS; 110 if( !arguments.read("-scale", vscale) ) vscale = 1.0; 111 if( arguments.read("-hmin",tmpfloat) ) sww->setHeightMin( tmpfloat ); 112 if( arguments.read("-hmax",tmpfloat) ) sww->setHeightMax( tmpfloat ); 113 if( arguments.read("-alphamin",tmpfloat) ) sww->setAlphaMin( tmpfloat ); 114 if( arguments.read("-alphamax",tmpfloat) ) sww->setAlphaMax( tmpfloat ); 115 if( arguments.read("-cullangle",tmpfloat) ) sww->setCullAngle( tmpfloat ); 116 117 std::string bedslopetexture; 118 if( arguments.read("-texture",bedslopetexture) ) sww->setBedslopeTexture( bedslopetexture ); 119 120 // root node 121 osg::Group* rootnode = new osg::Group; 122 123 // transform 124 osg::PositionAttitudeTransform* model = new osg::PositionAttitudeTransform; 125 model->setName("position_attitude_transform"); 126 127 // enscapsulates OpenGL state 128 osg::StateSet* rootStateSet = new osg::StateSet; 129 130 // Bedslope geometry 131 BedSlope* bedslope = new BedSlope(sww); 132 133 // Water geometry 134 WaterSurface* water = new WaterSurface(sww); 135 136 // Heads Up Display (text overlay) 137 HeadsUpDisplay* hud = new HeadsUpDisplay(); 138 hud->setTitle("pyVolution SWW Viewer"); 139 140 141 // Lighting 142 DirectionalLight* light = new DirectionalLight(rootStateSet); 143 light->setPosition( osg::Vec3(1,1,1) ); // z is up 144 145 std::string lightposstr; 146 while (arguments.read("-lightpos",lightposstr)) 147 { 148 float x, y, z; 149 int count = sscanf( lightposstr.c_str(), "%f,%f,%f", &x, &y, &z ); 150 if( count == 3 ) light->setPosition( osg::Vec3(x,y,z) ); // z is up 151 else osg::notify(osg::WARN) << "Invalid bedslope light position \"" << lightposstr << "\"" << std::endl; 152 } 153 154 155 156 // scenegraph hierarchy 157 rootnode->setStateSet(rootStateSet); 158 rootnode->addChild( hud->get() ); 159 rootnode->addChild( light->get() ); 160 rootnode->addChild(model); 161 model->addChild( bedslope->get() ); 162 model->addChild( water->get() ); 163 164 165 // allow vertical scaling from command line parameter 166 model->setScale( osg::Vec3(1.0, 1.0, vscale) ); 167 168 // surrounding sky sphere 169 if( !arguments.read("-nosky") ) 170 rootnode->addChild( createSky(10.0, sww->getSwollenDir() + std::string("/sky_small.jpg") )); 171 172 173 // add model to viewer. 174 viewer.setSceneData(rootnode); 167 175 168 169 176 // any option left unread are converted into errors to write out later. 177 arguments.reportRemainingOptionsAsUnrecognized(); 170 178 171 172 173 174 175 176 177 178 179 180 179 // report any errors if they have occured when parsing the program aguments. 180 if (arguments.errors()) 181 { 182 arguments.writeErrorMessages(std::cout); 183 return 1; 184 } 185 186 // register additional event handler 187 KeyboardEventHandler* event_handler = new KeyboardEventHandler(sww->getNumberOfTimesteps(), tps); 188 viewer.getEventHandlerList().push_front(event_handler); 181 189 182 190 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 191 // create the windows and run the threads. 192 viewer.realize(); 193 194 195 // initial camera position 196 CustomTerrainManipulator* terrainmanipulator = viewer.getTerrainManipulator(); 197 terrainmanipulator->setNode( model ); 198 terrainmanipulator->setAutoComputeHomePosition( false ); 199 terrainmanipulator->setHomePosition( 200 osg::Vec3d(0,-3,3), // camera location 201 osg::Vec3d(0,0,0), // camera target 202 osg::Vec3d(0,1,1) ); // camera up vector 203 terrainmanipulator->moveToHome(); 204 terrainmanipulator->enable(); 205 206 207 unsigned int timestep = 0; 208 while( !viewer.done() ) 209 { 202 210 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 211 // wait for all cull and draw threads to complete. 212 viewer.sync(); 213 214 215 // current time 216 double time = viewer.getFrameStamp()->getReferenceTime(); 217 218 // advance sww frame? 219 event_handler->setTime( time ); 220 if( event_handler->timestepChanged() ) 221 { 222 timestep = event_handler->getTimestep(); 223 water->setTimeStep(timestep); 224 hud->setTime( sww->getTime(timestep) ); 225 } 226 227 // events 228 if( event_handler->toggleWireframe() ) 229 water->toggleWireframe(); 230 231 if( event_handler->toggleCulling() ) 232 { 233 sww->toggleCulling(); 234 water->setTimeStep(timestep); // refresh 235 } 236 237 // update the scene by traversing with the update visitor 238 viewer.update(); 231 239 232 233 234 240 // fire off the cull and draw traversals of the scene. 241 viewer.frame(); 242 } 235 243 236 237 238 239 244 // wait for all cull and draw threads to complete before exit. 245 viewer.sync(); 246 247 return 0; 240 248 } -
Swollen/swollen/version.cpp
r103 r106 1 const char* version() { const char* s = "Revision: 10 2M"; return s; }1 const char* version() { const char* s = "Revision: 105M"; return s; } -
Swollen/swollen/watersurface.cpp
r105 r106 46 46 texture->setBorderColor(osg::Vec4(1.0f,1.0f,1.0f,0.5f)); 47 47 texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); 48 texture->setImage(osgDB::readImageFile("envmap.jpg")); 48 std::string* envmap = new std::string( _sww->getSwollenDir() + std::string("/") + std::string("envmap.jpg") ); 49 texture->setImage(osgDB::readImageFile( envmap->c_str() )); 49 50 _stateset->setTextureAttributeAndModes( 1, texture, osg::StateAttribute::ON ); 50 51 _stateset->setMode( GL_LIGHTING, osg::StateAttribute::ON ); -
Swollen/swwreader/swwreader.cpp
r105 r106 1 1 /* 2 3 4 5 6 2 SWWReader 3 4 Reader of SWW files from within OpenSceneGraph. 5 6 copyright (C) 2004-2005 Geoscience Australia 7 7 */ 8 8 … … 36 36 SWWReader::SWWReader(const std::string& filename) 37 37 { 38 // assume failure until end of constructor 39 _valid = false; 40 41 // netcdf filename 42 _filename = new std::string(filename); 43 44 // netcdf open 45 _status.push_back( nc_open(_filename->c_str(), NC_NOWRITE, &_ncid) ); 46 if (this->_statusHasError()) return; 47 48 // dimension ids 49 _status.push_back( nc_inq_dimid(_ncid, "number_of_volumes", &_nvolumesid) ); 50 _status.push_back( nc_inq_dimid(_ncid, "number_of_vertices", &_nverticesid) ); 51 _status.push_back( nc_inq_dimid(_ncid, "number_of_points", &_npointsid) ); 52 _status.push_back( nc_inq_dimid(_ncid, "number_of_timesteps", &_ntimestepsid) ); 53 if (this->_statusHasError()) return; 54 55 // dimension values 56 _status.push_back( nc_inq_dimlen(_ncid, _nvolumesid, &_nvolumes) ); 57 _status.push_back( nc_inq_dimlen(_ncid, _nverticesid, &_nvertices) ); 58 _status.push_back( nc_inq_dimlen(_ncid, _npointsid, &_npoints) ); 59 _status.push_back( nc_inq_dimlen(_ncid, _ntimestepsid, &_ntimesteps) ); 60 if (this->_statusHasError()) return; 61 62 // variable ids 63 _status.push_back( nc_inq_varid (_ncid, "x", &_xid) ); 64 _status.push_back( nc_inq_varid (_ncid, "y", &_yid) ); 65 _status.push_back( nc_inq_varid (_ncid, "z", &_zid) ); 66 _status.push_back( nc_inq_varid (_ncid, "volumes", &_volumesid) ); 67 _status.push_back( nc_inq_varid (_ncid, "time", &_timeid) ); 68 _status.push_back( nc_inq_varid (_ncid, "stage", &_stageid) ); 69 if (this->_statusHasError()) return; 70 71 // allocation of variable arrays, destructor responsible for cleanup 72 _px = new float[_npoints]; 73 _py = new float[_npoints]; 74 _pz = new float[_npoints]; 75 _ptime = new float[_ntimesteps]; 76 _pvolumes = new unsigned int[_nvertices * _nvolumes]; 77 _pstage = new float[_npoints]; 78 79 // loading variables from netcdf file 80 _status.push_back( nc_get_var_float (_ncid, _xid, _px) ); // x vertices 81 _status.push_back( nc_get_var_float (_ncid, _yid, _py) ); // y vertices 82 _status.push_back( nc_get_var_float (_ncid, _zid, _pz) ); // bedslope heights 83 _status.push_back( nc_get_var_float (_ncid, _timeid, _ptime) ); // time array 84 _status.push_back( nc_get_var_int (_ncid, _volumesid, (int *) _pvolumes) ); // triangle indices 85 if (this->_statusHasError()) return; 86 87 88 // sww file can optionally contain bedslope texture image filename 89 size_t attlen; // length of text attribute (if it exists) 90 if( nc_inq_attlen(_ncid, NC_GLOBAL, "texture", &attlen) != NC_ENOTATT ) 91 { 92 char* texfilename; 93 if( (texfilename = (char*) malloc(attlen+1)) != NULL){ 94 int status; 95 status = nc_get_att_text(_ncid, NC_GLOBAL, "texture", texfilename); 96 if( status == NC_NOERR ) 97 { 98 texfilename[attlen] = '\0'; // ensure string is terminated, not a requirement for netcdf attributes 99 osg::notify(osg::INFO) << "[SWWReader] embedded image filename: " << texfilename << std::endl; 100 setBedslopeTexture( osgDB::getFilePath(filename) + std::string("/") + std::string(texfilename) ); 101 } 102 free( texfilename ); 103 } 104 } 105 106 // sww file can optionally contain georeference offset 107 int status1 = nc_get_att_float(_ncid, NC_GLOBAL, "xllcorner", &_xllcorner); 108 int status2 = nc_get_att_float(_ncid, NC_GLOBAL, "yllcorner", &_yllcorner); 109 if( status1 == NC_NOERR && status2 == NC_NOERR) 110 { 111 osg::notify(osg::INFO) << "[SWWReader] xllcorner: " << _xllcorner << std::endl; 112 osg::notify(osg::INFO) << "[SWWReader] yllcorner: " << _yllcorner << std::endl; 113 } 114 else 115 { 116 _xllcorner = 0.0; // default value 117 _yllcorner = 0.0; 118 } 119 120 121 // alpha-scaling defaults, can be overridden after construction by command line parameters 122 _alphamin = DEFAULT_ALPHAMIN; 123 _alphamax = DEFAULT_ALPHAMAX; 124 _heightmin = DEFAULT_HEIGHTMIN; 125 _heightmax = DEFAULT_HEIGHTMAX; 126 127 // steepness culling default, can be overridden after construction by command line parameter 128 _cullangle = DEFAULT_CULLANGLE; 129 _culling = DEFAULT_CULLONSTART; 130 131 // loop index 132 size_t iv; 133 134 // vertex indices 135 unsigned int v1index, v2index, v3index; 136 137 // bedslope range and resultant scale factors (note, these don't take into 138 // account any xllcorner, yllcorner offsets - used during texture coord assignment) 139 float xmin, xmax, xrange; 140 float ymin, ymax, yrange; 141 float zmin, zmax, zrange; 142 float aspect_ratio; 143 xmin = _px[0]; 144 xmax = _px[0]; 145 ymin = _py[0]; 146 ymax = _py[0]; 147 zmin = _pz[0]; 148 zmax = _pz[0]; 149 for( iv=1; iv < _npoints; iv++ ) 150 { 151 if( _px[iv] < xmin ) xmin = _px[iv]; 152 if( _px[iv] > xmax ) xmax = _px[iv]; 153 if( _py[iv] < ymin ) ymin = _py[iv]; 154 if( _py[iv] > ymax ) ymax = _py[iv]; 155 if( _pz[iv] < zmin ) zmin = _pz[iv]; 156 if( _pz[iv] > zmax ) zmax = _pz[iv]; 157 } 158 159 xrange = xmax - xmin; 160 yrange = ymax - ymin; 161 zrange = zmax - zmin; 162 aspect_ratio = xrange/yrange; 163 _xscale = 1.0 / xrange; 164 _yscale = 1.0 / yrange; 38 // assume failure until end of constructor 39 _valid = false; 40 41 // netcdf filename 42 _filename = new std::string(filename); 43 44 // netcdf open 45 _status.push_back( nc_open(_filename->c_str(), NC_NOWRITE, &_ncid) ); 46 if (this->_statusHasError()) return; 47 48 // dimension ids 49 _status.push_back( nc_inq_dimid(_ncid, "number_of_volumes", &_nvolumesid) ); 50 _status.push_back( nc_inq_dimid(_ncid, "number_of_vertices", &_nverticesid) ); 51 _status.push_back( nc_inq_dimid(_ncid, "number_of_points", &_npointsid) ); 52 _status.push_back( nc_inq_dimid(_ncid, "number_of_timesteps", &_ntimestepsid) ); 53 if (this->_statusHasError()) return; 54 55 // dimension values 56 _status.push_back( nc_inq_dimlen(_ncid, _nvolumesid, &_nvolumes) ); 57 _status.push_back( nc_inq_dimlen(_ncid, _nverticesid, &_nvertices) ); 58 _status.push_back( nc_inq_dimlen(_ncid, _npointsid, &_npoints) ); 59 _status.push_back( nc_inq_dimlen(_ncid, _ntimestepsid, &_ntimesteps) ); 60 if (this->_statusHasError()) return; 61 62 // variable ids 63 _status.push_back( nc_inq_varid (_ncid, "x", &_xid) ); 64 _status.push_back( nc_inq_varid (_ncid, "y", &_yid) ); 65 _status.push_back( nc_inq_varid (_ncid, "z", &_zid) ); 66 _status.push_back( nc_inq_varid (_ncid, "volumes", &_volumesid) ); 67 _status.push_back( nc_inq_varid (_ncid, "time", &_timeid) ); 68 _status.push_back( nc_inq_varid (_ncid, "stage", &_stageid) ); 69 if (this->_statusHasError()) return; 70 71 // allocation of variable arrays, destructor responsible for cleanup 72 _px = new float[_npoints]; 73 _py = new float[_npoints]; 74 _pz = new float[_npoints]; 75 _ptime = new float[_ntimesteps]; 76 _pvolumes = new unsigned int[_nvertices * _nvolumes]; 77 _pstage = new float[_npoints]; 78 79 // loading variables from netcdf file 80 _status.push_back( nc_get_var_float (_ncid, _xid, _px) ); // x vertices 81 _status.push_back( nc_get_var_float (_ncid, _yid, _py) ); // y vertices 82 _status.push_back( nc_get_var_float (_ncid, _zid, _pz) ); // bedslope heights 83 _status.push_back( nc_get_var_float (_ncid, _timeid, _ptime) ); // time array 84 _status.push_back( nc_get_var_int (_ncid, _volumesid, (int *) _pvolumes) ); // triangle indices 85 if (this->_statusHasError()) return; 86 87 88 // sww file can optionally contain bedslope texture image filename 89 size_t attlen; // length of text attribute (if it exists) 90 if( nc_inq_attlen(_ncid, NC_GLOBAL, "texture", &attlen) != NC_ENOTATT ) 91 { 92 char* texfilename; 93 if( (texfilename = (char*) malloc(attlen+1)) != NULL){ 94 int status; 95 status = nc_get_att_text(_ncid, NC_GLOBAL, "texture", texfilename); 96 if( status == NC_NOERR ) 97 { 98 texfilename[attlen] = '\0'; // ensure string is terminated, not a requirement for netcdf attributes 99 osg::notify(osg::INFO) << "[SWWReader] embedded image filename: " << texfilename << std::endl; 100 101 // if sww isn't in current directory, need to prepend sww path to the bedslope texture 102 if( osgDB::getFilePath(filename) == "" ) 103 setBedslopeTexture( std::string(texfilename) ); 104 else 105 setBedslopeTexture( osgDB::getFilePath(filename) + std::string("/") + std::string(texfilename) ); 106 } 107 free( texfilename ); 108 } 109 } 110 111 // sww file can optionally contain georeference offset 112 int status1 = nc_get_att_float(_ncid, NC_GLOBAL, "xllcorner", &_xllcorner); 113 int status2 = nc_get_att_float(_ncid, NC_GLOBAL, "yllcorner", &_yllcorner); 114 if( status1 == NC_NOERR && status2 == NC_NOERR) 115 { 116 osg::notify(osg::INFO) << "[SWWReader] xllcorner: " << _xllcorner << std::endl; 117 osg::notify(osg::INFO) << "[SWWReader] yllcorner: " << _yllcorner << std::endl; 118 } 119 else 120 { 121 _xllcorner = 0.0; // default value 122 _yllcorner = 0.0; 123 } 124 125 126 // alpha-scaling defaults, can be overridden after construction by command line parameters 127 _alphamin = DEFAULT_ALPHAMIN; 128 _alphamax = DEFAULT_ALPHAMAX; 129 _heightmin = DEFAULT_HEIGHTMIN; 130 _heightmax = DEFAULT_HEIGHTMAX; 131 132 // steepness culling default, can be overridden after construction by command line parameter 133 _cullangle = DEFAULT_CULLANGLE; 134 _culling = DEFAULT_CULLONSTART; 135 136 // loop index 137 size_t iv; 138 139 // vertex indices 140 unsigned int v1index, v2index, v3index; 141 142 // bedslope range and resultant scale factors (note, these don't take into 143 // account any xllcorner, yllcorner offsets - used during texture coord assignment) 144 float xmin, xmax, xrange; 145 float ymin, ymax, yrange; 146 float zmin, zmax, zrange; 147 float aspect_ratio; 148 xmin = _px[0]; 149 xmax = _px[0]; 150 ymin = _py[0]; 151 ymax = _py[0]; 152 zmin = _pz[0]; 153 zmax = _pz[0]; 154 for( iv=1; iv < _npoints; iv++ ) 155 { 156 if( _px[iv] < xmin ) xmin = _px[iv]; 157 if( _px[iv] > xmax ) xmax = _px[iv]; 158 if( _py[iv] < ymin ) ymin = _py[iv]; 159 if( _py[iv] > ymax ) ymax = _py[iv]; 160 if( _pz[iv] < zmin ) zmin = _pz[iv]; 161 if( _pz[iv] > zmax ) zmax = _pz[iv]; 162 } 163 164 xrange = xmax - xmin; 165 yrange = ymax - ymin; 166 zrange = zmax - zmin; 167 aspect_ratio = xrange/yrange; 168 _xscale = 1.0 / xrange; 169 _yscale = 1.0 / yrange; 165 170 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 171 // handle case of a flat bed that doesn't necessarily pass through z=0 172 _zscale = (zrange == 0.0) ? 1.0 : 1.0/zrange; 173 174 _xoffset = xmin; 175 _yoffset = ymin; 176 _zoffset = zmin; 177 _xcenter = 0.5; 178 _ycenter = 0.5; 179 _zcenter = 0.0; 180 181 if( aspect_ratio > 1.0 ) 182 { 183 _scale = 1.0/xrange; 184 _ycenter /= aspect_ratio; 185 } 186 else 187 { 188 _scale = 1.0/yrange; 189 _xcenter /= aspect_ratio; 190 } 191 192 osg::notify(osg::INFO) << "[SWWReader] xscale: " << _xscale << std::endl; 193 osg::notify(osg::INFO) << "[SWWReader] yscale: " << _yscale << std::endl; 194 osg::notify(osg::INFO) << "[SWWReader] zmin: " << zmin << std::endl; 195 osg::notify(osg::INFO) << "[SWWReader] zmax: " << zmax << std::endl; 196 osg::notify(osg::INFO) << "[SWWReader] zscale: " << _zscale << std::endl; 197 198 199 // compute triangle connectivity, a list (indexed by vertex number) 200 // of lists (indices of triangles sharing this vertex) 201 _connectivity = std::vector<triangle_list>(_npoints); 202 for (iv=0; iv < _nvolumes; iv++) 203 { 204 v1index = _pvolumes[3*iv+0]; 205 v2index = _pvolumes[3*iv+1]; 206 v3index = _pvolumes[3*iv+2]; 207 _connectivity.at(v1index).push_back(iv); 208 _connectivity.at(v2index).push_back(iv); 209 _connectivity.at(v3index).push_back(iv); 210 } 211 212 // bedslope vertex array, shifting and scaling vertices to unit cube 213 // centred about the origin 214 _bedslopevertices = new osg::Vec3Array; 215 for (iv=0; iv < _npoints; iv++) 216 _bedslopevertices->push_back( osg::Vec3( (_px[iv]-_xoffset)*_scale - _xcenter, 217 (_py[iv]-_yoffset)*_scale - _ycenter, 218 (_pz[iv]-_zoffset)*_scale - _zcenter - DEFAULT_BEDSLOPEOFFSET) ); 219 220 // bedslope index array, pvolumes array indexes into x, y and z 221 _bedslopeindices = new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLES, _nvolumes*_nvertices); 222 for (iv=0; iv < _nvolumes*_nvertices; iv++) 223 (*_bedslopeindices)[iv] = _pvolumes[iv]; 224 225 226 // calculate bedslope primitive normal and centroid arrays 227 _bedslopenormals = new osg::Vec3Array; 228 _bedslopecentroids = new osg::Vec3Array; 229 osg::Vec3 v1, v2, v3, side1, side2, nrm; 230 for (iv=0; iv < _nvolumes; iv++) 231 { 232 v1index = _pvolumes[3*iv+0]; 233 v2index = _pvolumes[3*iv+1]; 234 v3index = _pvolumes[3*iv+2]; 235 236 v1 = _bedslopevertices->at(v1index); 237 v2 = _bedslopevertices->at(v2index); 238 v3 = _bedslopevertices->at(v3index); 239 240 side1 = v2 - v1; 241 side2 = v3 - v2; 242 nrm = side1^side2; 243 nrm.normalize(); 244 245 _bedslopenormals->push_back( nrm ); 246 _bedslopecentroids->push_back( (v1+v2+v3)/3.0 ); 247 } 248 249 // success! 250 _valid = true; 246 251 247 252 } … … 251 256 SWWReader::~SWWReader() 252 257 { 253 254 258 _status.push_back( nc_close(_ncid) ); 259 delete[]( _px, _py, _pz, _ptime, _pvolumes, _pstage ); 255 260 } 256 261 … … 259 264 void SWWReader::setBedslopeTexture( std::string filename ) 260 265 { 261 266 osg::notify(osg::INFO) << "[SWWReader::setBedslopetexture] filename: " << filename << std::endl; 262 267 _bedslopetexture = new std::string(filename); 263 268 _bedslopegeodata.hasData = false; … … 278 283 _bedslopegeodata.xresolution = pGDAL->GetRasterXSize(); 279 284 _bedslopegeodata.yresolution = pGDAL->GetRasterYSize(); 280 osg::notify(osg::INFO) << "[SWWReader::setBedslopetexture] xresolution: " << 281 _bedslopegeodata.xresolution << std::endl; 282 osg::notify(osg::INFO) << "[SWWReader::setBedslopetexture] yresolution: " << 283 _bedslopegeodata.yresolution << std::endl; 285 osg::notify(osg::INFO) << "[SWWReader::setBedslopetexture] xresolution: " << _bedslopegeodata.xresolution << std::endl; 286 osg::notify(osg::INFO) << "[SWWReader::setBedslopetexture] yresolution: " << _bedslopegeodata.yresolution << std::endl; 284 287 285 288 // check if image contains geodata … … 287 290 if( pGDAL->GetGeoTransform( geodata ) == CE_None ) 288 291 { 289 _bedslopegeodata.xorigin = geodata[0]; 290 _bedslopegeodata.yorigin = geodata[3]; 291 _bedslopegeodata.rotation = geodata[2]; 292 _bedslopegeodata.xpixel = geodata[1]; 293 _bedslopegeodata.ypixel = geodata[5]; 294 _bedslopegeodata.hasData = true; 295 296 osg::notify(osg::INFO) << "[SWWReader::setBedslopetexture] xorigin: " << _bedslopegeodata.xorigin << std::endl; 297 osg::notify(osg::INFO) << "[SWWReader::setBedslopetexture] yorigin: " << _bedslopegeodata.yorigin << std::endl; 298 osg::notify(osg::INFO) << "[SWWReader::setBedslopetexture] xpixel: " << _bedslopegeodata.xpixel << std::endl; 299 osg::notify(osg::INFO) << "[SWWReader::setBedslopetexture] ypixel: " << _bedslopegeodata.ypixel << std::endl; 300 osg::notify(osg::INFO) << "[SWWReader::setBedslopetexture] rotation: " << _bedslopegeodata.rotation << std::endl; 301 } 302 } 303 292 _bedslopegeodata.xorigin = geodata[0]; 293 _bedslopegeodata.yorigin = geodata[3]; 294 _bedslopegeodata.rotation = geodata[2]; 295 _bedslopegeodata.xpixel = geodata[1]; 296 _bedslopegeodata.ypixel = geodata[5]; 297 _bedslopegeodata.hasData = true; 298 299 osg::notify(osg::INFO) << "[SWWReader::setBedslopetexture] xorigin: " << _bedslopegeodata.xorigin << std::endl; 300 osg::notify(osg::INFO) << "[SWWReader::setBedslopetexture] yorigin: " << _bedslopegeodata.yorigin << std::endl; 301 osg::notify(osg::INFO) << "[SWWReader::setBedslopetexture] xpixel: " << _bedslopegeodata.xpixel << std::endl; 302 osg::notify(osg::INFO) << "[SWWReader::setBedslopetexture] ypixel: " << _bedslopegeodata.ypixel << std::endl; 303 osg::notify(osg::INFO) << "[SWWReader::setBedslopetexture] rotation: " << _bedslopegeodata.rotation << std::endl; 304 } 305 } 304 306 } 305 307 … … 316 318 { 317 319 _bedslopetexcoords = new osg::Vec2Array; 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 320 if( _bedslopegeodata.hasData ) // georeferenced bedslope texture 321 { 322 float xorigin = _bedslopegeodata.xorigin; 323 float yorigin = _bedslopegeodata.yorigin; 324 float xrange = _bedslopegeodata.xpixel * _bedslopegeodata.xresolution; 325 float yrange = _bedslopegeodata.ypixel * _bedslopegeodata.yresolution; 326 for( unsigned int iv=0; iv < _npoints; iv++ ) 327 _bedslopetexcoords->push_back( osg::Vec2( (_px[iv] + _xllcorner - xorigin)/xrange, 328 (_py[iv] + _yllcorner - yorigin)/yrange ) ); 329 } 330 else 331 { 332 // decal'd using (x,y) locations scaled by extents into range [0,1] 333 for( unsigned int iv=0; iv < _npoints; iv++ ) 334 _bedslopetexcoords->push_back( osg::Vec2( (_px[iv]-_xoffset)*_xscale, (_py[iv]-_yoffset)*_yscale ) ); 335 } 334 336 335 337 return _bedslopetexcoords; … … 340 342 osg::ref_ptr<osg::Vec3Array> SWWReader::getStageVertexArray(unsigned int index) 341 343 { 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 344 size_t start[2], count[2], iv; 345 const ptrdiff_t stride[2] = {1,1}; 346 start[0] = index; 347 start[1] = 0; 348 count[0] = 1; 349 count[1] = _npoints; 350 351 // empty array for storing list of steep triangles 352 osg::ref_ptr<osg::IntArray> steeptri = new osg::IntArray; 353 354 // stage heights from netcdf file (x and y are same as bedslope) 355 int status = nc_get_vars_float (_ncid, _stageid, start, count, stride, _pstage); 356 357 // load stage vertex array, scaling and shifting vertices to lie in the unit cube 358 _stagevertices = new osg::Vec3Array; 359 for (iv=0; iv < _npoints; iv++) 360 _stagevertices->push_back( osg::Vec3( (_px[iv]-_xoffset)*_scale - _xcenter, 361 (_py[iv]-_yoffset)*_scale - _ycenter, 362 (_pstage[iv]-_zoffset)*_scale - _zcenter) ); 363 364 // stage index, per primitive normal and centroid arrays 365 _stageprimitivenormals = new osg::Vec3Array; 366 _stagecentroids = new osg::Vec3Array; 367 osg::Vec3 v1b, v2b, v3b; 368 osg::Vec3 v1s, v2s, v3s; 369 osg::Vec3 side1, side2, nrm; 370 unsigned int v1index, v2index, v3index; 371 372 // cullangle given in degrees, test is against dot product 373 float cullthreshold = cos(osg::DegreesToRadians(_cullangle)); 374 375 // over all stage triangles 376 for (iv=0; iv < _nvolumes; iv++) 377 { 378 v1index = _pvolumes[3*iv+0]; 379 v2index = _pvolumes[3*iv+1]; 380 v3index = _pvolumes[3*iv+2]; 381 382 v1s = _stagevertices->at(v1index); 383 v2s = _stagevertices->at(v2index); 384 v3s = _stagevertices->at(v3index); 385 v1b = _bedslopevertices->at(v1index); 386 v2b = _bedslopevertices->at(v2index); 387 v3b = _bedslopevertices->at(v3index); 388 389 // current triangle primitive normal 390 side1 = v2s - v1s; 391 side2 = v3s - v2s; 392 nrm = side1^side2; 393 nrm.normalize(); 394 395 // store centroid and primitive normal 396 _stagecentroids->push_back( (v1s+v2s+v3s)/3.0 ); 397 _stageprimitivenormals->push_back( nrm ); 398 399 // identify steep triangles, store index 400 if( fabs(nrm * osg::Vec3f(0,0,1)) < cullthreshold ) 401 steeptri->push_back( iv ); 402 } 403 404 // stage height above bedslope mapped as alpha value 405 // alpha = min( a(h-hmin) + alphamin, alphamax), h >= hmin 406 // alpha = 0, h < hmin 407 // where a = (alphamax-alphamin)/(hmax-hmin) 408 float alpha, height, alphascale; 409 alphascale = (_alphamax - _alphamin) / (_heightmax - _heightmin); 410 _stagecolors = new osg::Vec4Array; 411 for (iv=0; iv < _npoints; iv++) 412 { 413 // water height above corresponding bedslope 414 height = _stagevertices->at(iv).z() - _bedslopevertices->at(iv).z(); 413 415 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 416 if (height < _heightmin) 417 alpha = 0.0; 418 else 419 { 420 alpha = alphascale * (height - _heightmin) + _alphamin; 421 if( alpha > _alphamax ) 422 alpha = _alphamax; 423 } 424 425 _stagecolors->push_back( osg::Vec4( 1.0, 1.0, 1.0, alpha ) ); 426 } 427 428 // steep triangle vertices should have alpha=0, overwrite such vertex colours 429 if( _culling ) 430 { 431 for (iv=0; iv < steeptri->size() ; iv++) 432 { 433 int tri = steeptri->at(iv); 434 v1index = _pvolumes[3*tri+0]; 435 v2index = _pvolumes[3*tri+1]; 436 v3index = _pvolumes[3*tri+2]; 437 438 _stagecolors->at(v1index) = osg::Vec4( 1, 1, 1, 0 ); 439 _stagecolors->at(v2index) = osg::Vec4( 1, 1, 1, 0 ); 440 _stagecolors->at(v3index) = osg::Vec4( 1, 1, 1, 0 ); 441 } 442 } 443 444 // per-vertex normals calculated as average of primitive normals 445 // from contributing triangles 446 _stagevertexnormals = new osg::Vec3Array; 447 int num_shared_triangles, triangle_index; 448 for (iv=0; iv < _npoints; iv++) 449 { 450 nrm.set(0,0,0); 451 num_shared_triangles = _connectivity.at(iv).size(); 452 for (int i=0; i<num_shared_triangles; i++ ) 453 { 454 triangle_index = _connectivity.at(iv).at(i); 455 nrm += _stageprimitivenormals->at(triangle_index); 456 } 457 458 nrm = nrm / num_shared_triangles; // average 459 nrm.normalize(); 460 _stagevertexnormals->push_back(nrm); 461 } 462 463 return _stagevertices; 462 464 } 463 465 … … 467 469 bool SWWReader::_statusHasError() 468 470 { 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 } 471 bool haserror = false; // assume success, trap failure 472 473 std::vector<int>::iterator iter; 474 for (iter=_status.begin(); iter != _status.end(); iter++) 475 { 476 if (*iter != NC_NOERR) 477 { 478 osg::notify(osg::WARN) << nc_strerror(*iter) << std::endl; 479 haserror = true; 480 nc_close(_ncid); 481 break; 482 } 483 } 484 485 // on return start gathering result values afresh 486 _status.clear(); 487 488 return haserror; 489 }
Note: See TracChangeset
for help on using the changeset viewer.