diff --git a/examples/osgterrain/osgterrain.cpp b/examples/osgterrain/osgterrain.cpp index 990694e6f..a46438786 100644 --- a/examples/osgterrain/osgterrain.cpp +++ b/examples/osgterrain/osgterrain.cpp @@ -646,7 +646,7 @@ int main(int argc, char** argv) std::string filterName; - osgTerrain::Layer::Filter filter = osgTerrain::Layer::LINEAR; + osg::Texture::FilterMode filter = osg::Texture::LINEAR; bool readParameter = false; float minValue, maxValue; @@ -705,7 +705,7 @@ int main(int argc, char** argv) hfl->setLocator(locator.get()); hfl->setValidDataOperator(validDataOperator.get()); - hfl->setFilter(filter); + hfl->setMagFilter(filter); if (offset!=0.0f || scale!=1.0f) { @@ -740,7 +740,7 @@ int main(int argc, char** argv) imageLayer->setImage(image.get()); imageLayer->setLocator(locator.get()); imageLayer->setValidDataOperator(validDataOperator.get()); - imageLayer->setFilter(filter); + imageLayer->setMagFilter(filter); if (offset!=0.0f || scale!=1.0f) { @@ -775,7 +775,7 @@ int main(int argc, char** argv) imageLayer->setImage(image.get()); imageLayer->setLocator(locator.get()); imageLayer->setValidDataOperator(validDataOperator.get()); - imageLayer->setFilter(filter); + imageLayer->setMagFilter(filter); if (offset!=0.0f || scale!=1.0f) { @@ -805,11 +805,11 @@ int main(int argc, char** argv) if (filterName=="NEAREST") { osg::notify(osg::NOTICE)<<"--filter "<getColorLayer(layerNum)) { - terrainTile->getColorLayer(layerNum)->setFilter(filter); + terrainTile->getColorLayer(layerNum)->setMagFilter(filter); } } diff --git a/include/osg/GraphicsContext b/include/osg/GraphicsContext index 56b7d9649..2e4568772 100644 --- a/include/osg/GraphicsContext +++ b/include/osg/GraphicsContext @@ -267,7 +267,8 @@ class OSG_EXPORT GraphicsContext : public Object inline const Vec4& getClearColor() const { return _clearColor; } /** Set the clear mask used in glClear(..). - * Defaults to GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT. */ + * Defaults to 0 - so no clear is done by default by the GraphicsContext, instead the Camera's attached the GraphicsContext will do the clear. + * GraphicsContext::setClearMask() is useful for when the Camera's Viewports don't conver the whole context, so the context will fill in the gaps. */ inline void setClearMask(GLbitfield mask) { _clearMask = mask; } /** Get the clear mask.*/ diff --git a/include/osgTerrain/Layer b/include/osgTerrain/Layer index 1eae4b07f..0aec06692 100644 --- a/include/osgTerrain/Layer +++ b/include/osgTerrain/Layer @@ -77,17 +77,20 @@ class OSGTERRAIN_EXPORT Layer : public osg::Object void setDefaultValue(const osg::Vec4& value) { _defaultValue = value; } const osg::Vec4& getDefaultValue() const { return _defaultValue; } - enum Filter - { - NEAREST, - LINEAR - }; - /** Set the texture filter to use when do texture associated with this layer.*/ - void setFilter(Filter filter) { _filter = filter; } + /** Set the minification texture filter to use when do texture associated with this layer.*/ + void setMinFilter(osg::Texture::FilterMode filter) { _minFilter = filter; } + + /** Get the minification texture filter to use when do texture associated with this layer.*/ + osg::Texture::FilterMode getMinFilter() const { return _minFilter; } + + + /** Set the magniification texture filter to use when do texture associated with this layer.*/ + void setMagFilter(osg::Texture::FilterMode filter) { _magFilter = filter; } + + /** Get the magnification texture filter to use when do texture associated with this layer.*/ + osg::Texture::FilterMode getMagFilter() const { return _magFilter; } - /** Get the texture filter to use when do texture associated with this layer.*/ - Filter getFilter() const { return _filter; } /** Return image associated with layer if supported. */ @@ -209,7 +212,8 @@ class OSGTERRAIN_EXPORT Layer : public osg::Object unsigned int _maxLevel; osg::ref_ptr _validDataOperator; osg::Vec4 _defaultValue; - Filter _filter; + osg::Texture::FilterMode _minFilter; + osg::Texture::FilterMode _magFilter; }; diff --git a/src/osg/Image.cpp b/src/osg/Image.cpp index 2208a239f..a77155810 100644 --- a/src/osg/Image.cpp +++ b/src/osg/Image.cpp @@ -617,6 +617,8 @@ void Image::readPixels(int x,int y,int width,int height, void Image::readImageFromCurrentTexture(unsigned int contextID, bool copyMipMapsIfAvailable, GLenum type) { + // osg::notify(osg::NOTICE)<<"Image::readImageFromCurrentTexture()"<isNonPowerOfTwoTextureSupported(_min_filter)="<isNonPowerOfTwoTextureSupported(_min_filter) <data(); + // osg::notify(osg::NOTICE)<<"inwidth="<getFileName()"<getFileName()<s() || inheight!=image->t(); if (needImageRescale) diff --git a/src/osgPlugins/dds/ReaderWriterDDS.cpp b/src/osgPlugins/dds/ReaderWriterDDS.cpp index cddf31b62..29ac4b29d 100644 --- a/src/osgPlugins/dds/ReaderWriterDDS.cpp +++ b/src/osgPlugins/dds/ReaderWriterDDS.cpp @@ -596,11 +596,11 @@ osg::Image* ReadDDSFile(std::istream& _istream) float power2_s = logf((float)s)/logf((float)2); float power2_t = logf((float)t)/logf((float)2); - osg::notify(osg::INFO) << "ReadDDSFile info : ddsd.dwMipMapCount = "<resize(size); + + if (size == 0) + return true; + + if (readBool()) + { + float value = readFloat(); + + for(int i=0; irdstate() & _istream->failbit) + throw Exception("DataInputStream::readFloatArray(): Failed to read float array."); + + if (_verboseOutput) std::cout<<"read/writeFloatArray() ["< > ImageMap; typedef std::map > StateSetMap; typedef std::map > StateAttributeMap; diff --git a/src/osgPlugins/ive/DataOutputStream.cpp b/src/osgPlugins/ive/DataOutputStream.cpp index 003fc2e04..3bbeed492 100644 --- a/src/osgPlugins/ive/DataOutputStream.cpp +++ b/src/osgPlugins/ive/DataOutputStream.cpp @@ -128,6 +128,7 @@ DataOutputStream::DataOutputStream(std::ostream * ostream, const osgDB::ReaderWr _includeExternalReferences = false; _writeExternalReferenceFiles = false; _useOriginalExternalReferences = true; + _maximumErrorToSizeRatio = 0.001; _options = options; @@ -135,26 +136,50 @@ DataOutputStream::DataOutputStream(std::ostream * ostream, const osgDB::ReaderWr if (_options.get()) { - if(_options->getOptionString().find("noTexturesInIVEFile")!=std::string::npos) { + std::string optionsString = _options->getOptionString(); + + if(optionsString.find("noTexturesInIVEFile")!=std::string::npos) { setIncludeImageMode(IMAGE_REFERENCE_FILE); - } else if(_options->getOptionString().find("includeImageFileInIVEFile")!=std::string::npos) { + } else if(optionsString.find("includeImageFileInIVEFile")!=std::string::npos) { setIncludeImageMode(IMAGE_INCLUDE_FILE); - } else if(_options->getOptionString().find("compressImageData")!=std::string::npos) { + } else if(optionsString.find("compressImageData")!=std::string::npos) { setIncludeImageMode(IMAGE_COMPRESS_DATA); } osg::notify(osg::DEBUG_INFO) << "ive::DataOutpouStream.setIncludeImageMode()=" << getIncludeImageMode() << std::endl; - setIncludeExternalReferences(_options->getOptionString().find("inlineExternalReferencesInIVEFile")!=std::string::npos); + setIncludeExternalReferences(optionsString.find("inlineExternalReferencesInIVEFile")!=std::string::npos); osg::notify(osg::DEBUG_INFO) << "ive::DataOutpouStream.setIncludeExternalReferences()=" << getIncludeExternalReferences() << std::endl; - setWriteExternalReferenceFiles(_options->getOptionString().find("noWriteExternalReferenceFiles")==std::string::npos); + setWriteExternalReferenceFiles(optionsString.find("noWriteExternalReferenceFiles")==std::string::npos); osg::notify(osg::DEBUG_INFO) << "ive::DataOutpouStream.setWriteExternalReferenceFiles()=" << getWriteExternalReferenceFiles() << std::endl; - setUseOriginalExternalReferences(_options->getOptionString().find("useOriginalExternalReferences")!=std::string::npos); + setUseOriginalExternalReferences(optionsString.find("useOriginalExternalReferences")!=std::string::npos); osg::notify(osg::DEBUG_INFO) << "ive::DataOutpouStream.setUseOriginalExternalReferences()=" << getUseOriginalExternalReferences() << std::endl; - _compressionLevel = (_options->getOptionString().find("compressed")!=std::string::npos) ? 1 : 0; + _compressionLevel = (optionsString.find("compressed")!=std::string::npos) ? 1 : 0; osg::notify(osg::DEBUG_INFO) << "ive::DataOutpouStream._compressionLevel=" << _compressionLevel << std::endl; + + std::string::size_type terrainErrorPos = optionsString.find("TerrainMaximumErrorToSizeRatio="); + if (terrainErrorPos!=std::string::npos) + { + std::string::size_type endOfToken = optionsString.find_first_of('=', terrainErrorPos); + std::string::size_type endOfNumber = optionsString.find_first_of(' ', endOfToken); + std::string::size_type numOfCharInNumber = (endOfNumber != std::string::npos) ? + endOfNumber-endOfToken-1 : + optionsString.size()-endOfToken-1; + + if (numOfCharInNumber>0) + { + std::string numberString = optionsString.substr(endOfToken+1, numOfCharInNumber); + _maximumErrorToSizeRatio = atof(numberString.c_str()); + + osg::notify(osg::DEBUG_INFO)<<"TerrainMaximumErrorToSizeRatio = "<<_maximumErrorToSizeRatio<getNumElements(); + writeInt(size); + if (size==0) return; + + float minValue = (*a)[0]; + float maxValue = minValue; + for(int i=1; imaxValue) maxValue = (*a)[i]; + } + + if (minValue==maxValue) + { + osg::notify(osg::DEBUG_INFO)<<"Writing out "<0.0f) + { + + float byteError = 0.0f; + float byteMultiplier = 255.0f/(maxValue-minValue); + float byteInvMultiplier = 1.0f/byteMultiplier; + + float shortError = 0.0f; + float shortMultiplier = 65535.0f/(maxValue-minValue); + float shortInvMultiplier = 1.0f/shortMultiplier; + + float max_error_byte = 0.0f; + float max_error_short = 0.0f; + + for(int i=0; imax_error_byte) max_error_byte = error_byte; + if (error_short>max_error_short) max_error_short = error_short; + } + + osg::notify(osg::DEBUG_INFO)<<"maxError "<getNumElements(); diff --git a/src/osgPlugins/ive/DataOutputStream.h b/src/osgPlugins/ive/DataOutputStream.h index 611a69a12..df094b4b5 100644 --- a/src/osgPlugins/ive/DataOutputStream.h +++ b/src/osgPlugins/ive/DataOutputStream.h @@ -71,6 +71,9 @@ public: void writeVec2b(const osg::Vec2b& v); void writeVec3b(const osg::Vec3b& v); void writeVec4b(const osg::Vec4b& v); + + void writePackedFloatArray(const osg::FloatArray* a, float maxError); + void writeFloatArray(const osg::FloatArray* a); void writeVec2Array(const osg::Vec2Array* a); void writeVec3Array(const osg::Vec3Array* a); @@ -122,6 +125,10 @@ public: void setUseOriginalExternalReferences(bool b) {_useOriginalExternalReferences=b;}; bool getUseOriginalExternalReferences() const {return _useOriginalExternalReferences;}; + void setTerrainMaximumErrorToSizeRatio(double ratio) { _maximumErrorToSizeRatio = ratio; } + double getTerrainMaximumErrorToSizeRatio() const { return _maximumErrorToSizeRatio; } + + bool _verboseOutput; bool compress(std::ostream& fout, const std::string& source) const; @@ -159,6 +166,7 @@ private: bool _includeExternalReferences; bool _writeExternalReferenceFiles; bool _useOriginalExternalReferences; + double _maximumErrorToSizeRatio; IncludeImageMode _includeImageMode; diff --git a/src/osgPlugins/ive/DataTypeSize.h b/src/osgPlugins/ive/DataTypeSize.h index eea68041b..3d116d916 100644 --- a/src/osgPlugins/ive/DataTypeSize.h +++ b/src/osgPlugins/ive/DataTypeSize.h @@ -12,7 +12,16 @@ //Don't know where else to put this namespace ive{ -enum IncludeImageMode { IMAGE_REFERENCE_FILE=0,IMAGE_INCLUDE_DATA,IMAGE_INCLUDE_FILE,IMAGE_COMPRESS_DATA }; + +enum IncludeImageMode +{ + IMAGE_REFERENCE_FILE=0, + IMAGE_INCLUDE_DATA, + IMAGE_INCLUDE_FILE, + IMAGE_COMPRESS_DATA +}; + + } #endif diff --git a/src/osgPlugins/ive/HeightFieldLayer.cpp b/src/osgPlugins/ive/HeightFieldLayer.cpp index 56a373034..1fe19bc3c 100644 --- a/src/osgPlugins/ive/HeightFieldLayer.cpp +++ b/src/osgPlugins/ive/HeightFieldLayer.cpp @@ -16,6 +16,7 @@ #include "Layer.h" #include +#include using namespace ive; @@ -34,9 +35,45 @@ void HeightFieldLayer::write(DataOutputStream* out) if (getFileName().empty() && getHeightField()) { + osg::HeightField* hf = getHeightField(); + // using inline heightfield out->writeBool(true); - out->writeShape(getHeightField()); + if (out->getVersion()>=VERSION_0035) + { + // Write HeightField's properties. + out->writeUInt(hf->getNumColumns()); + out->writeUInt(hf->getNumRows()); + out->writeVec3(hf->getOrigin()); + out->writeFloat(hf->getXInterval()); + out->writeFloat(hf->getYInterval()); + out->writeQuat(hf->getRotation()); + out->writeFloat(hf->getSkirtHeight()); + out->writeUInt(hf->getBorderWidth()); + + int packingSize = 1; + + float maxError = 0.0f; + + if (getLocator()) + { + osg::Vec3d world_origin, world_corner; + + getLocator()->convertLocalToModel(osg::Vec3d(0.0,0.0,0.0), world_origin); + getLocator()->convertLocalToModel(osg::Vec3d(1.0,1.0,0.0), world_corner); + + double distance = (world_origin-world_corner).length(); + + maxError = distance * out->getTerrainMaximumErrorToSizeRatio(); + } + + out->writePackedFloatArray(hf->getFloatArray(), maxError); + } + else + { + out->writeShape(getHeightField()); + } + } else { @@ -69,8 +106,39 @@ void HeightFieldLayer::read(DataInputStream* in) if (useInlineHeightField) { - osg::Shape* shape = in->readShape(); - setHeightField(dynamic_cast(shape)); + + if (in->getVersion()>=VERSION_0035) + { + osg::HeightField* hf = new osg::HeightField; + + // Read HeightField's properties + //setColor(in->readVec4()); + unsigned int col = in->readUInt(); + unsigned int row = in->readUInt(); + hf->allocate(col,row); + + hf->setOrigin(in->readVec3()); + hf->setXInterval(in->readFloat()); + hf->setYInterval(in->readFloat()); + hf->setRotation(in->readQuat()); + + hf->setSkirtHeight(in->readFloat()); + hf->setBorderWidth(in->readUInt()); + + if (in->getVersion()>=VERSION_0035) + { + in->readPackedFloatArray(hf->getFloatArray()); + } + + setHeightField(hf); + + } + else + { + osg::Shape* shape = in->readShape(); + setHeightField(dynamic_cast(shape)); + } + } else { diff --git a/src/osgPlugins/ive/IveVersion.h b/src/osgPlugins/ive/IveVersion.h index 4391bee06..82bdea84a 100644 --- a/src/osgPlugins/ive/IveVersion.h +++ b/src/osgPlugins/ive/IveVersion.h @@ -42,8 +42,10 @@ #define VERSION_0031 31 #define VERSION_0032 32 #define VERSION_0033 33 +#define VERSION_0034 34 +#define VERSION_0035 35 -#define VERSION VERSION_0033 +#define VERSION VERSION_0035 /* The BYTE_SEX tag is used to check the endian of the IVE file being read in. The IVE format diff --git a/src/osgPlugins/ive/Layer.cpp b/src/osgPlugins/ive/Layer.cpp index c5467a92b..521ab4896 100644 --- a/src/osgPlugins/ive/Layer.cpp +++ b/src/osgPlugins/ive/Layer.cpp @@ -41,13 +41,24 @@ void Layer::write(DataOutputStream* out) if (out->getVersion() >= VERSION_0023) { out->writeLocator(getLocator()); - out->writeUInt(getFilter()); + + if (out->getVersion() >= VERSION_0034) + { + out->writeUInt(getMinFilter()); + out->writeUInt(getMagFilter()); + } + else + { + out->writeUInt((getMagFilter()==osg::Texture::LINEAR) ? 1 : 0); + } } else { LayerHelper helper; helper.writeLocator(out, getLocator()); } + + out->writeUInt(getMinLevel()); out->writeUInt(getMaxLevel()); @@ -78,7 +89,16 @@ void Layer::read(DataInputStream* in) if (in->getVersion() >= VERSION_0023) { setLocator(in->readLocator()); - setFilter(osgTerrain::Layer::Filter(in->readUInt())); + + if (in->getVersion() >= VERSION_0034) + { + setMinFilter(osg::Texture::FilterMode(in->readUInt())); + setMagFilter(osg::Texture::FilterMode(in->readUInt())); + } + else + { + setMagFilter(in->readUInt()==0 ? osg::Texture::NEAREST : osg::Texture::LINEAR); + } } else { diff --git a/src/osgPlugins/ive/ReaderWriterIVE.cpp b/src/osgPlugins/ive/ReaderWriterIVE.cpp index 33a472449..5cf738a76 100644 --- a/src/osgPlugins/ive/ReaderWriterIVE.cpp +++ b/src/osgPlugins/ive/ReaderWriterIVE.cpp @@ -24,6 +24,7 @@ class ReaderWriterIVE : public ReaderWriter supportsOption("inlineExternalReferencesInIVEFile","Export option"); supportsOption("noWriteExternalReferenceFiles","Export option"); supportsOption("useOriginalExternalReferences","Export option"); + supportsOption("TerrainMaximumErrorToSizeRatio=value","Export option that controls error matric used to determine terrain HieghtField storage precision."); supportsOption("noLoadExternalReferenceFiles","Import option"); } diff --git a/src/osgPlugins/osgTerrain/Layer.cpp b/src/osgPlugins/osgTerrain/Layer.cpp index e9eb501c0..6ec2c3226 100644 --- a/src/osgPlugins/osgTerrain/Layer.cpp +++ b/src/osgPlugins/osgTerrain/Layer.cpp @@ -15,6 +15,8 @@ bool Layer_readLocalData(osg::Object &obj, osgDB::Input &fr); bool Layer_writeLocalData(const osg::Object &obj, osgDB::Output &fw); +bool Layer_matchFilterStr(const char* str, osg::Texture::FilterMode& filter); +const char* Layer_getFilterStr(osg::Texture::FilterMode filter); osgDB::RegisterDotOsgWrapperProxy Layer_Proxy ( @@ -35,23 +37,19 @@ bool Layer_readLocalData(osg::Object& obj, osgDB::Input &fr) osgTerrain::Locator* locator = dynamic_cast(readObject.get()); if (locator) layer.setLocator(locator); - if (fr[0].matchWord("Filter")) + osg::Texture::FilterMode filter; + if (fr[0].matchWord("MinFilter") && Layer_matchFilterStr(fr[1].getStr(),filter)) { - unsigned int layerNum = 0; - if (fr.matchSequence("Filter %i")) - { - fr[1].getUInt(layerNum); - fr += 2; - } - else - { - ++fr; - } + layer.setMinFilter(filter); + fr+=2; + itrAdvanced = true; + } - if (fr[0].matchWord("NEAREST")) layer.setFilter(osgTerrain::Layer::NEAREST); - else if (fr[0].matchWord("LINEAR")) layer.setFilter(osgTerrain::Layer::LINEAR); - - ++fr; + if ((fr[0].matchWord("Filter") || fr[0].matchWord("MagFilter")) && + Layer_matchFilterStr(fr[1].getStr(),filter)) + { + layer.setMagFilter(filter); + fr+=2; itrAdvanced = true; } @@ -82,17 +80,8 @@ bool Layer_writeLocalData(const osg::Object& obj, osgDB::Output& fw) fw.writeObject(*layer.getLocator()); } - if (layer.getFilter()!=osgTerrain::Layer::LINEAR) - { - if (layer.getFilter()==osgTerrain::Layer::LINEAR) - { - fw.indent()<<"Filter LINEAER"<setImage(image); texture2D->setMaxAnisotropy(16.0f); texture2D->setResizeNonPowerOfTwoHint(false); - texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR); - texture2D->setFilter(osg::Texture::MAG_FILTER, colorLayer->getFilter()==Layer::LINEAR ? osg::Texture::LINEAR : osg::Texture::NEAREST); + + texture2D->setFilter(osg::Texture::MIN_FILTER, colorLayer->getMinFilter()); + texture2D->setFilter(osg::Texture::MAG_FILTER, colorLayer->getMagFilter()); + texture2D->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE); texture2D->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_EDGE); layerToTextureMap[colorLayer] = texture2D; - // osg::notify(osg::NOTICE)<<"Creating new ImageLayer texture "<s()="<s()<<" image->t()="<t()<setImage(image); texture1D->setResizeNonPowerOfTwoHint(false); texture1D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST); - texture1D->setFilter(osg::Texture::MAG_FILTER, colorLayer->getFilter()==Layer::LINEAR ? osg::Texture::LINEAR : osg::Texture::NEAREST); + texture1D->setFilter(osg::Texture::MAG_FILTER, colorLayer->getMagFilter()); layerToTextureMap[colorLayer] = texture1D; } diff --git a/src/osgTerrain/Layer.cpp b/src/osgTerrain/Layer.cpp index 14f9acda3..c19880eb2 100644 --- a/src/osgTerrain/Layer.cpp +++ b/src/osgTerrain/Layer.cpp @@ -55,7 +55,8 @@ std::string osgTerrain::createCompondSetNameAndFileName(const std::string& setna Layer::Layer(): _minLevel(0), _maxLevel(MAXIMUM_NUMBER_OF_LEVELS), - _filter(LINEAR) + _minFilter(osg::Texture::LINEAR_MIPMAP_LINEAR), + _magFilter(osg::Texture::LINEAR) { } @@ -64,7 +65,8 @@ Layer::Layer(const Layer& layer,const osg::CopyOp& copyop): _filename(layer._filename), _minLevel(layer._minLevel), _maxLevel(layer._maxLevel), - _filter(layer._filter) + _minFilter(layer._minFilter), + _magFilter(layer._magFilter) { } @@ -305,7 +307,8 @@ unsigned int ImageLayer::getModifiedCount() const ContourLayer::ContourLayer(osg::TransferFunction1D* tf): _tf(tf) { - _filter = NEAREST; + _minFilter = osg::Texture::NEAREST; + _magFilter = osg::Texture::NEAREST; } ContourLayer::ContourLayer(const ContourLayer& contourLayer,const osg::CopyOp& copyop):