+ // 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;
+ }
+ 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(fileName) == "ac") {
+ // we get optimal geometry from the loader.
+ needTristrip = false;
+ osg::Matrix m(1, 0, 0, 0,
+ 0, 0, 1, 0,
+ 0, -1, 0, 0,
+ 0, 0, 0, 1);
+
+ osg::ref_ptr<osg::Group> root = new osg::Group;
+ osg::MatrixTransform* transform = new osg::MatrixTransform;
+ root->addChild(transform);
+
+ transform->setDataVariance(osg::Object::STATIC);
+ transform->setMatrix(m);
+ transform->addChild(res.getNode());
+
+ res = osgDB::ReaderWriter::ReadResult(0);
+
+ 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()) {
+ res = osgDB::ReaderWriter::ReadResult(root->getChild(0));
+ } else
+ res = osgDB::ReaderWriter::ReadResult(root.get());
+
+ // Ok, this step is questionable.
+ // It is there to have the same visual appearance of ac objects for the
+ // first cut. Osg's ac3d loader will correctly set materials from the
+ // ac file. But the old plib loader used GL_AMBIENT_AND_DIFFUSE for the
+ // materials that in effect igored the ambient part specified in the
+ // file. We emulate that for the first cut here by changing all
+ // ac models here. But in the long term we should use the
+ // unchanged model and fix the input files instead ...
+ SGAcMaterialCrippleVisitor matCriple;
+ res.getNode()->accept(matCriple);
+ }