forcing users to use osgDB::readRef*File() methods. The later is preferable as it closes a potential threading bug when using paging databases in conjunction
with the osgDB::Registry Object Cache. This threading bug occurs when one thread gets an object from the Cache via an osgDB::read*File() call where only
a pointer to the object is passed back, so taking a reference to the object is delayed till it gets reassigned to a ref_ptr<>, but at the same time another
thread calls a flush of the Object Cache deleting this object as it's referenceCount is now zero. Using osgDB::readREf*File() makes sure the a ref_ptr<> is
passed back and the referenceCount never goes to zero.
To ensure the OSG builds when OSG_PROVIDE_READFILE is to OFF the many cases of osgDB::read*File() usage had to be replaced with a ref_ptr<> osgDB::readRef*File()
usage. The avoid this change causing lots of other client code to be rewritten to handle the use of ref_ptr<> in place of C pointer I introduced a serious of
templte methods in various class to adapt ref_ptr<> to the underly C pointer to be passed to old OSG API's, example of this is found in include/osg/Group:
bool addChild(Node* child); // old method which can only be used with a Node*
tempalte<class T> bool addChild(const osg::ref_ptr<T>& child) { return addChild(child.get()); } // adapter template method
These changes together cover 149 modified files, so it's a large submission. This extent of changes are warrent to make use of the Object Cache
and multi-threaded loaded more robust.
git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/branches/OpenSceneGraph-3.4@15165 16af8721-9629-0410-8352-f15c8da7e697
201 lines
6.8 KiB
C++
201 lines
6.8 KiB
C++
#include <sstream>
|
|
|
|
#include <osg/Image>
|
|
#include <osg/Group>
|
|
#include <osg/Notify>
|
|
|
|
#include <osgDB/FileNameUtils>
|
|
#include <osgDB/FileUtils>
|
|
#include <osgDB/ReadFile>
|
|
#include <osgDB/Registry>
|
|
#include <osgDB/Input>
|
|
#include <osgDB/Output>
|
|
|
|
#include <osgTerrain/TerrainTile>
|
|
|
|
class ReaderWriterTerrain : public osgDB::ReaderWriter
|
|
{
|
|
public:
|
|
|
|
ReaderWriterTerrain()
|
|
{
|
|
supportsExtension("osgTerrain","OpenSceneGraph terrain extension to .osg ascii format");
|
|
supportsExtension("terrain","OpenSceneGraph terrain ascii format");
|
|
}
|
|
|
|
virtual const char* className() const { return "Terrain ReaderWriter"; }
|
|
|
|
virtual osgDB::ReaderWriter::ReadResult readNode(const std::string& file, const osgDB::ReaderWriter::Options* opt) const
|
|
{
|
|
std::string ext = osgDB::getLowerCaseFileExtension(file);
|
|
|
|
if (osgDB::equalCaseInsensitive(ext,"terrain"))
|
|
{
|
|
#if 0
|
|
KeywordValueMap keywordValueMap;
|
|
parseTerrainString(osgDB::getNameLessExtension(file), keywordValueMap);
|
|
|
|
for(KeywordValueMap::iterator itr = keywordValueMap.begin();
|
|
itr != keywordValueMap.end();
|
|
++itr)
|
|
{
|
|
OSG_NOTICE<<"["<<itr->first<<"] = "<<"["<<itr->second<<"]"<<std::endl;
|
|
}
|
|
#else
|
|
std::istringstream fin(osgDB::getNameLessExtension(file));
|
|
if (fin) return readNode(fin,opt);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
|
|
|
|
std::string fileName = osgDB::findDataFile( file, opt );
|
|
if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
|
|
|
|
// code for setting up the database path so that internally referenced file are searched for on relative paths.
|
|
osg::ref_ptr<Options> local_opt = opt ? static_cast<Options*>(opt->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
|
|
local_opt->setDatabasePath(osgDB::getFilePath(fileName));
|
|
|
|
osgDB::ifstream fin(fileName.c_str());
|
|
if (fin)
|
|
{
|
|
return readNode(fin, local_opt.get());
|
|
}
|
|
return 0L;
|
|
|
|
}
|
|
|
|
virtual osgDB::ReaderWriter::ReadResult readNode(std::istream& fin, const Options* options) const
|
|
{
|
|
fin.imbue(std::locale::classic());
|
|
|
|
osgDB::Input fr;
|
|
fr.attach(&fin);
|
|
fr.setOptions(options);
|
|
|
|
osg::ref_ptr<osg::Group> group = new osg::Group;
|
|
|
|
while(!fr.eof())
|
|
{
|
|
|
|
bool itrAdvanced = false;
|
|
|
|
if (fr.matchSequence("file %s") || fr.matchSequence("file %w") )
|
|
{
|
|
osg::ref_ptr<osg::Node> node = osgDB::readRefNodeFile(fr[1].getStr());
|
|
|
|
if (node) group->addChild(node);
|
|
|
|
fr += 2;
|
|
itrAdvanced = true;
|
|
}
|
|
|
|
osg::ref_ptr<osg::Node> node = fr.readNode();
|
|
if (node.valid())
|
|
{
|
|
group->addChild(node);
|
|
itrAdvanced = true;
|
|
}
|
|
|
|
if (!itrAdvanced)
|
|
{
|
|
if (fr[0].getStr()) { OSG_NOTICE<<"Terrain file - unreconised token : "<<fr[0].getStr() <<""<< std::endl; }
|
|
++fr;
|
|
}
|
|
}
|
|
|
|
if (group->getNumChildren()>0) return group;
|
|
else return 0;
|
|
}
|
|
|
|
typedef std::map<std::string, std::string> KeywordValueMap;
|
|
bool parseTerrainString(const std::string& str, KeywordValueMap& keywordValueMap) const
|
|
{
|
|
bool success = false;
|
|
|
|
std::string::size_type pos = 0;
|
|
while(pos != std::string::npos)
|
|
{
|
|
pos = str.find_first_not_of(' ',pos);
|
|
if (pos == std::string::npos) break;
|
|
|
|
std::string::size_type semicolon = str.find_first_of(';', pos);
|
|
std::string::size_type startstatement = pos;
|
|
std::string::size_type endstatement = std::string::npos;
|
|
if (semicolon!=std::string::npos)
|
|
{
|
|
endstatement = semicolon-1;
|
|
pos = semicolon+1;
|
|
}
|
|
else
|
|
{
|
|
endstatement = str.length()-1;
|
|
pos = std::string::npos;
|
|
}
|
|
|
|
if (startstatement<endstatement) endstatement = str.find_last_not_of(' ',endstatement);
|
|
|
|
if (startstatement<=endstatement)
|
|
{
|
|
// OSG_NOTICE<<"statement = ["<<str.substr(startstatement, endstatement-startstatement+1)<<"]"<<std::endl;
|
|
std::string::size_type assignment = str.find_first_of('=', startstatement);
|
|
if (assignment!=std::string::npos && assignment>endstatement)
|
|
{
|
|
assignment = std::string::npos;
|
|
}
|
|
|
|
std::string::size_type startvariable = startstatement;
|
|
std::string::size_type endvariable = startstatement;
|
|
std::string::size_type startvalue = startstatement;
|
|
std::string::size_type endvalue = endstatement;
|
|
|
|
if (assignment!=std::string::npos)
|
|
{
|
|
endvariable = assignment-1;
|
|
startvalue = assignment+1;
|
|
|
|
if (startvariable<=endvariable)
|
|
{
|
|
endvariable = str.find_last_not_of(' ',endvariable);
|
|
}
|
|
|
|
if (startvariable<=endvariable)
|
|
{
|
|
++endvariable;
|
|
}
|
|
}
|
|
|
|
|
|
if (startvalue<=endvalue)
|
|
{
|
|
startvalue = str.find_first_not_of(' ',startvalue);
|
|
}
|
|
|
|
if (startvalue<=endvalue)
|
|
{
|
|
if (startvariable<endvariable)
|
|
{
|
|
keywordValueMap[str.substr(startvariable, endvariable-startvariable)] = str.substr(startvalue, endvalue-startvalue+1);
|
|
success = true;
|
|
}
|
|
else
|
|
{
|
|
keywordValueMap[""] = str.substr(startvalue, endvalue-startvalue+1);
|
|
success = true;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
};
|
|
|
|
// now register with Registry to instantiate the above
|
|
// reader/writer.
|
|
REGISTER_OSGPLUGIN(terrain, ReaderWriterTerrain)
|
|
|