1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version. The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * OpenSceneGraph Public License for more details.
14#ifndef OSGTERRAIN_LAYER
15#define OSGTERRAIN_LAYER 1
20#include <osg/TransferFunction>
22#include <osgTerrain/Locator>
23#include <osgTerrain/ValidDataOperator>
27#define MAXIMUM_NUMBER_OF_LEVELS 30
29/** Extact the setname and filename from a compound string in the from set:setname:filename".
30 * Returns a setname of "" when non set:setname: entry is present.*/
31extern OSGTERRAIN_EXPORT void extractSetNameAndFileName(const std::string& compoundstring, std::string& setname, std::string& filename);
33/** Create a compound string in the form set:setname:filename, or just filename if setname is "".*/
34extern OSGTERRAIN_EXPORT std::string createCompoundSetNameAndFileName(const std::string& setname, const std::string& filename);
36class OSGTERRAIN_EXPORT Layer : public osg::Object
42 /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
43 Layer(const Layer&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
45 META_Object(osgTerrain, Layer);
47 /** Set the name of this layer. */
48 void setSetName(const std::string& setname) { setName(setname); }
50 /** Get the name of this layer. */
51 const std::string& getSetName() const { return getName(); }
53 /** Set the file name of the data associated with this layer. */
54 virtual void setFileName(const std::string& filename) { _filename = filename; }
56 /** Get the file name of the layer. */
57 virtual const std::string& getFileName() const { return _filename; }
59 /** Return the compound name of the layer in the form set::name::filename string.*/
60 std::string getCompoundName() const { return createCompoundSetNameAndFileName(getName(), getFileName()); }
62 void setLocator(Locator* locator) { _locator = locator; }
64 template<class T> void setLocator(const osg::ref_ptr<T>& locator) { setLocator(locator.get()); }
66 Locator* getLocator() { return _locator.get(); }
67 const Locator* getLocator() const { return _locator.get(); }
69 void setMinLevel(unsigned int minLevel) { _minLevel = minLevel; }
70 unsigned int getMinLevel() const { return _minLevel; }
72 void setMaxLevel(unsigned int maxLevel) { _maxLevel = maxLevel; }
73 unsigned int getMaxLevel() const { return _maxLevel; }
75 /** Set the data validation operator. */
76 void setValidDataOperator(ValidDataOperator* validDataOp) { _validDataOperator = validDataOp; }
78 /** Get the data validation operator. */
79 ValidDataOperator* getValidDataOperator() { return _validDataOperator.get(); }
81 /** Get the const data validation operator. */
82 const ValidDataOperator* getValidDataOperator() const { return _validDataOperator.get(); }
85 /** Get the number of columns. */
86 virtual unsigned int getNumColumns() const { return 0; }
88 /** Get the number of rows. */
89 virtual unsigned int getNumRows() const { return 0; }
91 void setDefaultValue(const osg::Vec4& value) { _defaultValue = value; }
92 const osg::Vec4& getDefaultValue() const { return _defaultValue; }
95 /** Set the minification texture filter to use when a texture is associated with this layer.*/
96 void setMinFilter(osg::Texture::FilterMode filter) { _minFilter = filter; }
98 /** Get the minification texture filter to use when a texture is associated with this layer.*/
99 osg::Texture::FilterMode getMinFilter() const { return _minFilter; }
102 /** Set the magnification texture filter to use when a texture is associated with this layer.*/
103 void setMagFilter(osg::Texture::FilterMode filter) { _magFilter = filter; }
105 /** Get the magnification texture filter to use when a texture is associated with this layer.*/
106 osg::Texture::FilterMode getMagFilter() const { return _magFilter; }
110 /** Return image associated with layer if supported. */
111 virtual osg::Image* getImage() { return 0; }
113 /** Return const image associated with layer if supported. */
114 virtual const osg::Image* getImage() const { return 0; }
117 virtual bool transform(float /*offset*/, float /*scale*/) { return false; }
120 * Get the layer value at position i,j.
121 * param i X-axis (or column) index.
122 * param j Y-axis (or row) index.
123 * param value Returned layer value.
124 * @return true if value is valid, else false
126 virtual bool getValue(unsigned int /*i*/, unsigned int /*j*/, float& /*value*/) const { return false; }
127 virtual bool getValue(unsigned int /*i*/, unsigned int /*j*/, osg::Vec2& /*value*/) const { return false; }
128 virtual bool getValue(unsigned int /*i*/, unsigned int /*j*/, osg::Vec3& /*value*/) const { return false; }
129 virtual bool getValue(unsigned int /*i*/, unsigned int /*j*/, osg::Vec4& /*value*/) const { return false; }
131 inline bool getValidValue(unsigned int i, unsigned int j, float& value) const
133 if (getValue(i,j,value)) return _validDataOperator.valid() ? (*_validDataOperator)(value) : true;
137 inline bool getValidValue(unsigned int i, unsigned int j, osg::Vec2& value) const
139 if (getValue(i,j,value)) return _validDataOperator.valid() ? (*_validDataOperator)(value) : true;
143 inline bool getValidValue(unsigned int i, unsigned int j, osg::Vec3& value) const
145 if (getValue(i,j,value)) return _validDataOperator.valid() ? (*_validDataOperator)(value) : true;
149 inline bool getValidValue(unsigned int i, unsigned int j, osg::Vec4& value) const
151 if (getValue(i,j,value)) return _validDataOperator.valid() ? (*_validDataOperator)(value) : true;
157 * Compute column,row indices from normalized coordinates.
158 * @param[in] ndc_x Normalized X-axis coordinate.
159 * @param[in] ndc_y Normalized Y-axis coordinate.
160 * @param[out] i Returned X-axis (or column) index.
161 * @param[out] j Returned Y-axis (or row) index.
162 * @param[out] ir Returned X-axis fraction.
163 * @param[out] jr Returned Y-axis fraction.
165 inline void computeIndices(double ndc_x, double ndc_y, unsigned int& i, unsigned int& j, double& ir, double& jr) const
167 ndc_x *= double(getNumColumns()-1);
168 ndc_y *= double(getNumRows()-1);
169 i = (unsigned int)(ndc_x);
170 j = (unsigned int)(ndc_y);
171 ir = ndc_x - double(i);
172 jr = ndc_y - double(j);
176 * Calculate the interpolated layer value at the given normalized coordinates.
177 * @param[in] ndc_x Normalized X-axis coordinate.
178 * @param[in] ndc_y Normalized Y-axis coordinate.
179 * @param[out] value Returned layer value.
180 * @return true if value is valid, else false
182 inline bool getInterpolatedValue(double ndc_x, double ndc_y, float& value) const
186 computeIndices(ndc_x, ndc_y, i, j, ir, jr);
191 r = (1.0f-ir)*(1.0f-jr);
192 if (r>0.0 && getValue(i,j,v))
199 if (r>0.0 && getValue(i+1,j,v))
206 if (r>0.0 && getValue(i+1,j+1,v))
213 if (r>0.0 && getValue(i,j+1,v))
229 inline bool getInterpolatedValidValue(double ndc_x, double ndc_y, float& value) const
233 computeIndices(ndc_x, ndc_y, i, j, ir, jr);
238 r = (1.0f-ir)*(1.0f-jr);
239 if (r>0.0 && getValidValue(i,j,v))
246 if (r>0.0 && getValidValue(i+1,j,v))
253 if (r>0.0 && getValidValue(i+1,j+1,v))
260 if (r>0.0 && getValidValue(i,j+1,v))
276 /** increment the modified count."*/
277 virtual void dirty() {}
279 /** Set the modified count value. */
280 virtual void setModifiedCount(unsigned int /*value*/) {}
282 /** Get modified count value. */
283 virtual unsigned int getModifiedCount() const { return 0; }
285 virtual osg::BoundingSphere computeBound(bool treatAsElevationLayer) const;
291 std::string _filename;
292 osg::ref_ptr<Locator> _locator;
293 unsigned int _minLevel;
294 unsigned int _maxLevel;
295 osg::ref_ptr<ValidDataOperator> _validDataOperator;
296 osg::Vec4 _defaultValue;
297 osg::Texture::FilterMode _minFilter;
298 osg::Texture::FilterMode _magFilter;
302class OSGTERRAIN_EXPORT ImageLayer : public Layer
306 ImageLayer(osg::Image* image=0);
308 /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
309 ImageLayer(const ImageLayer& imageLayer,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
311 META_Object(osgTerrain, ImageLayer);
313 void setFileName(const std::string& filename) { _filename = filename; if (_image.valid()) _image->setFileName(filename); }
314 virtual const std::string& getFileName() const { return _image.get() ? _image->getFileName() : _filename; }
316 virtual bool transform(float offset, float scale);
318 void setImage(osg::Image* image);
320 template<class T> void setImage(const osg::ref_ptr<T>& image) { return setImage(image.get()); }
322 /** Return image associated with layer. */
323 virtual osg::Image* getImage() { return _image.get(); }
325 /** Return const image associated with layer. */
326 virtual const osg::Image* getImage() const { return _image.get(); }
328 virtual unsigned int getNumColumns() const { return _image.valid() ? _image->s() : 0; }
329 virtual unsigned int getNumRows() const { return _image.valid() ? _image->t() : 0; }
331 virtual bool getValue(unsigned int i, unsigned int j, float& value) const;
332 virtual bool getValue(unsigned int i, unsigned int j, osg::Vec2& value) const;
333 virtual bool getValue(unsigned int i, unsigned int j, osg::Vec3& value) const;
334 virtual bool getValue(unsigned int i, unsigned int j, osg::Vec4& value) const;
336 virtual void dirty();
337 virtual void setModifiedCount(unsigned int value);
338 virtual unsigned int getModifiedCount() const;
342 virtual ~ImageLayer() {}
344 osg::ref_ptr<osg::Image> _image;
348class OSGTERRAIN_EXPORT ContourLayer : public Layer
352 ContourLayer(osg::TransferFunction1D* tf=0);
354 /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
355 ContourLayer(const ContourLayer& tfLayer,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
357 META_Object(osgTerrain, ContourLayer);
359 virtual bool transform(float offset, float scale);
361 void setTransferFunction(osg::TransferFunction1D* tf);
363 template<class T> void setTransferFunction(const osg::ref_ptr<T>& tf) { return setTransferFunction(tf.get()); }
365 osg::TransferFunction1D* getTransferFunction() { return _tf.get(); }
366 const osg::TransferFunction1D* getTransferFunction() const { return _tf.get(); }
368 /** Return image associated with layer. */
369 virtual osg::Image* getImage() { return _tf.valid() ? _tf->getImage() : 0; }
371 /** Return const image associated with layer. */
372 virtual const osg::Image* getImage() const { return _tf.valid() ? _tf->getImage() : 0; }
375 virtual unsigned int getNumColumns() const { return _tf.valid() ? _tf->getNumberImageCells() : 0; }
376 virtual unsigned int getNumRows() const { return _tf.valid() ? 1 : 0; }
378 virtual bool getValue(unsigned int i, unsigned int j, float& value) const;
379 virtual bool getValue(unsigned int i, unsigned int j, osg::Vec2& value) const;
380 virtual bool getValue(unsigned int i, unsigned int j, osg::Vec3& value) const;
381 virtual bool getValue(unsigned int i, unsigned int j, osg::Vec4& value) const;
383 virtual void dirty();
384 virtual void setModifiedCount(unsigned int value);
385 virtual unsigned int getModifiedCount() const;
389 virtual ~ContourLayer() {}
391 osg::ref_ptr<osg::TransferFunction1D> _tf;
395class OSGTERRAIN_EXPORT HeightFieldLayer : public Layer
399 HeightFieldLayer(osg::HeightField* hf=0);
401 /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
402 HeightFieldLayer(const HeightFieldLayer& hfLayer,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
404 META_Object(osgTerrain, HeightFieldLayer);
406 void setFileName(const std::string& filename) { _filename = filename; }
407 virtual const std::string& getFileName() const { return _filename; }
409 virtual bool transform(float offset, float scale);
411 void setHeightField(osg::HeightField* hf);
413 template<class T> void setHeightField(const osg::ref_ptr<T>& hf) { return setHeightField(hf.get()); }
415 osg::HeightField* getHeightField() { return _heightField.get(); }
416 const osg::HeightField* getHeightField() const { return _heightField.get(); }
418 virtual unsigned int getNumColumns() const { return _heightField.valid() ? _heightField->getNumColumns() : 0; }
419 virtual unsigned int getNumRows() const { return _heightField.valid() ? _heightField->getNumRows() : 0; }
421 virtual bool getValue(unsigned int i, unsigned int j, float& value) const;
422 virtual bool getValue(unsigned int i, unsigned int j, osg::Vec2& value) const;
423 virtual bool getValue(unsigned int i, unsigned int j, osg::Vec3& value) const;
424 virtual bool getValue(unsigned int i, unsigned int j, osg::Vec4& value) const;
426 virtual void dirty();
427 virtual void setModifiedCount(unsigned int value);
428 virtual unsigned int getModifiedCount() const;
432 virtual ~HeightFieldLayer() {}
434 unsigned int _modifiedCount;
435 osg::ref_ptr<osg::HeightField> _heightField;
440class OSGTERRAIN_EXPORT ProxyLayer : public Layer
446 /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
447 ProxyLayer(const ProxyLayer& proxyLayer,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
449 META_Object(osgTerrain, ProxyLayer);
451 /** Return image associated with layer if supported. */
452 virtual osg::Image* getImage()
454 return _implementation.valid() ? _implementation->getImage() : 0;
457 /** Return const image associated with layer if supported. */
458 virtual const osg::Image* getImage() const
460 return _implementation.valid() ? _implementation->getImage() : 0;
463 /** Set the implementation layer that does the actual work.*/
464 void setImplementation(Layer* layer) { _implementation = layer; }
466 /** Get the implementation layer that does the actual work.*/
467 Layer* getImplementation() { return _implementation.get(); }
469 /** Get the const implementation layer that does the actual work.*/
470 const Layer* getImplementation() const { return _implementation.get(); }
472 virtual void setFileName(const std::string& filename);
473 virtual const std::string& getFileName() const { return _filename; }
475 virtual unsigned int getNumColumns() const;
476 virtual unsigned int getNumRows() const;
478 virtual bool transform(float offset, float scale);
480 virtual bool getValue(unsigned int i, unsigned int j, float& value) const;
481 virtual bool getValue(unsigned int i, unsigned int j, osg::Vec2& value) const;
482 virtual bool getValue(unsigned int i, unsigned int j, osg::Vec3& value) const;
483 virtual bool getValue(unsigned int i, unsigned int j, osg::Vec4& value) const;
485 virtual void dirty();
486 virtual void setModifiedCount(unsigned int value);
487 virtual unsigned int getModifiedCount() const;
489 virtual osg::BoundingSphere computeBound(bool treatAsElevationLayer) const;
493 virtual ~ProxyLayer();
495 osg::ref_ptr<Layer> _implementation;
500class OSGTERRAIN_EXPORT CompositeLayer : public Layer
506 /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
507 CompositeLayer(const CompositeLayer& compositeLayer,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
509 META_Object(osgTerrain, CompositeLayer);
513 /** Set the set name of layer 'i'. */
514 void setSetName(unsigned int i, const std::string& setname) { _layers[i].setname = setname; if (_layers[i].layer.valid()) _layers[i].layer->setName(setname); }
516 /** Get the set name of layer 'i'. */
517 const std::string& getSetName(unsigned int i) const { return _layers[i].layer.valid() ? _layers[i].layer->getName() : _layers[i].setname; }
519 /** Set the file name of the data associated with layer 'i'. */
520 void setFileName(unsigned int i, const std::string& filename) { _layers[i].filename = filename; if (_layers[i].layer.valid()) _layers[i].layer->setFileName(filename); }
522 /** Get the file name of the data associated with layer 'i'. */
523 const std::string& getFileName(unsigned int i) const { return _layers[i].layer.valid() ? _layers[i].layer->getFileName() : _layers[i].filename; }
525 void setCompoundName(unsigned int i, const std::string& compoundname);
526 std::string getCompoundName(unsigned int i) const;
529 void setLayer(unsigned int i, Layer* layer) { if (i>=_layers.size()) _layers.resize(i+1); _layers[i].layer = layer; }
531 template<class T> void setLayer(unsigned int i, const osg::ref_ptr<T>& layer) { setLayer(i, layer.get()); }
533 Layer* getLayer(unsigned int i) { return i<_layers.size() ? _layers[i].layer.get() : 0; }
535 const Layer* getLayer(unsigned int i) const { return i<_layers.size() ? _layers[i].layer.get() : 0; }
537 void addLayer(const std::string& compoundname);
539 void addLayer(const std::string& setname, const std::string& filename);
541 void addLayer(Layer* layer) { _layers.push_back(CompoundNameLayer(layer->getName(),layer->getFileName(),layer)); }
543 template<class T> void addLayer(const osg::ref_ptr<T>& layer) { return addLayer(layer.get()); }
545 void removeLayer(unsigned int i) { _layers.erase(_layers.begin()+i); }
547 unsigned int getNumLayers() const { return static_cast<unsigned int>(_layers.size()); }
551 virtual ~CompositeLayer() {}
553 struct CompoundNameLayer
555 CompoundNameLayer() {}
557 CompoundNameLayer(const CompoundNameLayer& cnl):
558 setname(cnl.setname),
559 filename(cnl.filename),
562 CompoundNameLayer(const std::string& sn, const std::string& fn, Layer* l):
567 CompoundNameLayer& operator = (const CompoundNameLayer& cnl)
569 if (&cnl==this) return *this;
571 setname = cnl.setname;
572 filename = cnl.filename;
578 std::string filename;
579 osg::ref_ptr<Layer> layer;
582 typedef std::vector< CompoundNameLayer > Layers;
588class OSGTERRAIN_EXPORT SwitchLayer : public CompositeLayer
594 /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
595 SwitchLayer(const SwitchLayer& switchLayer,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
597 META_Object(osgTerrain, SwitchLayer);
599 void setActiveLayer(int i) { _activeLayer = i; }
600 int getActiveLayer() const { return _activeLayer; }
602 /** Return image associated with layer if supported. */
603 virtual osg::Image* getImage()
605 if (_activeLayer < 0) return 0;
606 if (_activeLayer >= static_cast<int>(getNumLayers())) return 0;
607 return _layers[_activeLayer].layer->getImage();
610 /** Return const image associated with layer if supported. */
611 virtual const osg::Image* getImage() const
613 if (_activeLayer < 0) return 0;
614 if (_activeLayer >= static_cast<int>(getNumLayers())) return 0;
615 return _layers[_activeLayer].layer->getImage();
620 virtual ~SwitchLayer() {}