if (!texture)
return;
+ // Hmm, true??
+ texture->setDataVariance(osg::Object::STATIC);
+
osg::Image* image = texture->getImage(0);
if (!image)
return;
readNode(const std::string& fileName,
const osgDB::ReaderWriter::Options* opt)
{
- std::string absFileName = osgDB::findDataFile(fileName);
+ osgDB::Registry* registry = osgDB::Registry::instance();
+ osgDB::ReaderWriter::ReadResult res;
+ osg::Node* cached = 0;
+ // The BTG loader automatically looks for ".btg.gz" if a file with
+ // the .btg extension doesn't exist. Also, we don't want to add
+ // nodes, run the optimizer, etc. on the btg model.So, let it do
+ // its thing.
+ if (osgDB::equalCaseInsensitive(osgDB::getFileExtension(fileName), "btg")) {
+ return registry->readNodeImplementation(fileName, opt);
+ }
+ // First, look for a file with the same name, and the extension
+ // ".osg" and, if it exists, load it instead. This allows for
+ // substitution of optimized models for ones named in the scenery.
+ bool optimizeModel = true;
+ std::string fileSansExtension = osgDB::getNameLessExtension(fileName);
+ std::string osgFileName = fileSansExtension + ".osg";
+ std::string absFileName = osgDB::findDataFile(osgFileName);
+ if (osgDB::fileExists(absFileName)) {
+ optimizeModel = false;
+ } else {
+ absFileName = osgDB::findDataFile(fileName);
+ }
if (!osgDB::fileExists(absFileName)) {
SG_LOG(SG_IO, SG_ALERT, "Cannot find model file \""
<< fileName << "\"");
return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
}
-
- osgDB::Registry* registry = osgDB::Registry::instance();
- osgDB::ReaderWriter::ReadResult res;
- res = registry->readNodeImplementation(absFileName, opt);
- if (!res.validNode())
- return res;
-
- if (res.loadedFromCache()) {
- SG_LOG(SG_IO, SG_INFO, "Returning cached model \""
+ cached
+ = dynamic_cast<osg::Node*>(registry->getFromObjectCache(absFileName));
+ if (cached) {
+ SG_LOG(SG_IO, SG_INFO, "Got cached model \""
<< absFileName << "\"");
} else {
SG_LOG(SG_IO, SG_INFO, "Reading model \""
<< absFileName << "\"");
+ res = registry->readNodeImplementation(absFileName, opt);
+ if (!res.validNode())
+ return res;
bool needTristrip = true;
- if (osgDB::getLowerCaseFileExtension(absFileName) == "ac") {
+ if (osgDB::getLowerCaseFileExtension(fileName) == "ac") {
// we get optimal geometry from the loader.
needTristrip = false;
osg::Matrix m(1, 0, 0, 0,
transform->addChild(res.getNode());
res = osgDB::ReaderWriter::ReadResult(0);
-
- osgUtil::Optimizer optimizer;
- unsigned opts = osgUtil::Optimizer::FLATTEN_STATIC_TRANSFORMS;
- optimizer.optimize(root.get(), opts);
+
+ if (optimizeModel) {
+ osgUtil::Optimizer optimizer;
+ unsigned opts = osgUtil::Optimizer::FLATTEN_STATIC_TRANSFORMS;
+ optimizer.optimize(root.get(), opts);
+ }
// strip away unneeded groups
if (root->getNumChildren() == 1 && root->getName().empty()) {
SGAcMaterialCrippleVisitor matCriple;
res.getNode()->accept(matCriple);
}
-
- osgUtil::Optimizer optimizer;
- unsigned opts = 0;
- // Don't use this one. It will break animation names ...
- // opts |= osgUtil::Optimizer::REMOVE_REDUNDANT_NODES;
-
- // opts |= osgUtil::Optimizer::REMOVE_LOADED_PROXY_NODES;
- // opts |= osgUtil::Optimizer::COMBINE_ADJACENT_LODS;
- // opts |= osgUtil::Optimizer::SHARE_DUPLICATE_STATE;
- opts |= osgUtil::Optimizer::MERGE_GEOMETRY;
- // opts |= osgUtil::Optimizer::CHECK_GEOMETRY;
- // opts |= osgUtil::Optimizer::SPATIALIZE_GROUPS;
- // opts |= osgUtil::Optimizer::COPY_SHARED_NODES;
- opts |= osgUtil::Optimizer::FLATTEN_STATIC_TRANSFORMS;
- if (needTristrip)
- opts |= osgUtil::Optimizer::TRISTRIP_GEOMETRY;
- // opts |= osgUtil::Optimizer::TESSELATE_GEOMETRY;
- // opts |= osgUtil::Optimizer::OPTIMIZE_TEXTURE_SETTINGS;
- optimizer.optimize(res.getNode(), opts);
+ if (optimizeModel) {
+ osgUtil::Optimizer optimizer;
+ unsigned opts = 0;
+ // Don't use this one. It will break animation names ...
+ // opts |= osgUtil::Optimizer::REMOVE_REDUNDANT_NODES;
+
+ // opts |= osgUtil::Optimizer::REMOVE_LOADED_PROXY_NODES;
+ // opts |= osgUtil::Optimizer::COMBINE_ADJACENT_LODS;
+ // opts |= osgUtil::Optimizer::SHARE_DUPLICATE_STATE;
+ opts |= osgUtil::Optimizer::MERGE_GEOMETRY;
+ // opts |= osgUtil::Optimizer::CHECK_GEOMETRY;
+ // opts |= osgUtil::Optimizer::SPATIALIZE_GROUPS;
+ // opts |= osgUtil::Optimizer::COPY_SHARED_NODES;
+ opts |= osgUtil::Optimizer::FLATTEN_STATIC_TRANSFORMS;
+ if (needTristrip)
+ opts |= osgUtil::Optimizer::TRISTRIP_GEOMETRY;
+ // opts |= osgUtil::Optimizer::TESSELATE_GEOMETRY;
+ // opts |= osgUtil::Optimizer::OPTIMIZE_TEXTURE_SETTINGS;
+ optimizer.optimize(res.getNode(), opts);
+ }
// Make sure the data variance of sharable objects is set to STATIC ...
SGTexDataVarianceVisitor dataVarianceVisitor;
res.getNode()->accept(dataVarianceVisitor);
SGTexCompressionVisitor texComp;
res.getNode()->accept(texComp);
+ cached = res.getNode();
+ registry->addEntryToObjectCache(absFileName, cached);
}
-
// Add an extra reference to the model stored in the database.
// That it to avoid expiring the object from the cache even if it is still
// in use. Note that the object cache will think that a model is unused
// if the reference count is 1. If we clone all structural nodes here
// we need that extra reference to the original object
SGDatabaseReference* databaseReference;
- databaseReference = new SGDatabaseReference(res.getNode());
+ databaseReference = new SGDatabaseReference(cached);
osg::CopyOp::CopyFlags flags = osg::CopyOp::DEEP_COPY_ALL;
flags &= ~osg::CopyOp::DEEP_COPY_TEXTURES;
flags &= ~osg::CopyOp::DEEP_COPY_IMAGES;
// This will safe display lists ...
flags &= ~osg::CopyOp::DEEP_COPY_DRAWABLES;
flags &= ~osg::CopyOp::DEEP_COPY_SHAPES;
- res = osgDB::ReaderWriter::ReadResult(osg::CopyOp(flags)(res.getNode()));
+ res = osgDB::ReaderWriter::ReadResult(osg::CopyOp(flags)(cached));
res.getNode()->addObserver(databaseReference);
// Update liveries
osgDB::Registry* registry = osgDB::Registry::instance();
osgDB::ReaderWriter::Options* options = new osgDB::ReaderWriter::Options;
- options->setObjectCacheHint(osgDB::ReaderWriter::Options::CACHE_ALL);
+ // We manage node caching ourselves
+ int cacheOptions = osgDB::ReaderWriter::Options::CACHE_ALL
+ & ~osgDB::ReaderWriter::Options::CACHE_NODES;
+ options->
+ setObjectCacheHint((osgDB::ReaderWriter::Options::CacheHintOptions)cacheOptions);
registry->setOptions(options);
registry->getOrCreateSharedStateManager()->setShareMode(osgDB::SharedStateManager::SHARE_TEXTURES);
registry->setReadFileCallback(new SGReadFileCallback);
osg::Image* image = osgDB::readImageFile(path);
osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
texture->setImage(image);
+ texture->setDataVariance(osg::Object::STATIC);
if (wrapu)
texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
else
// OSGFIXME: don't forget that mutex here
osgDB::Registry* registry = osgDB::Registry::instance();
- registry->getOrCreateSharedStateManager()->share(tmpNode.get(), 0);
+ registry->getSharedStateManager()->share(tmpNode.get(), 0);
// should be the same, but be paranoid ...
stateSet = tmpNode->getStateSet();