#include <simgear_config.h>
#endif
-#include <string.h> // for strcmp()
-
#include <osg/observer_ptr>
#include <osg/ref_ptr>
#include <osg/Group>
#include <osgDB/SharedStateManager>
#include <osgUtil/Optimizer>
+#include <simgear/scene/util/SGSceneFeatures.hxx>
#include <simgear/scene/util/SGStateAttributeVisitor.hxx>
#include <simgear/scene/util/SGTextureStateAttributeVisitor.hxx>
class SGTexCompressionVisitor : public SGTextureStateAttributeVisitor {
public:
- SGTexCompressionVisitor(osg::Texture::InternalFormatMode formatMode) :
- mFormatMode(formatMode)
- { }
-
virtual void apply(int, osg::StateSet::RefAttributePair& refAttr)
{
osg::Texture2D* texture;
int s = image->s();
int t = image->t();
+
if (s <= t && 32 <= s) {
- texture->setInternalFormatMode(mFormatMode);
+ SGSceneFeatures::instance()->setTextureCompression(texture);
} else if (t < s && 32 <= t) {
- texture->setInternalFormatMode(mFormatMode);
+ SGSceneFeatures::instance()->setTextureCompression(texture);
}
}
+};
-private:
- osg::Texture::InternalFormatMode mFormatMode;
+class SGTexDataVarianceVisitor : public SGTextureStateAttributeVisitor {
+public:
+ virtual void apply(int, osg::StateSet::RefAttributePair& refAttr)
+ {
+ osg::Texture* texture;
+ texture = dynamic_cast<osg::Texture*>(refAttr.first.get());
+ if (!texture)
+ return;
+
+ texture->setDataVariance(osg::Object::STATIC);
+ }
};
class SGAcMaterialCrippleVisitor : public SGStateAttributeVisitor {
readNode(const std::string& fileName,
const osgDB::ReaderWriter::Options* opt)
{
+ osgDB::Registry* registry = osgDB::Registry::instance();
+ osgDB::ReaderWriter::ReadResult res;
+ // 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);
+ }
std::string absFileName = osgDB::findDataFile(fileName);
if (!osgDB::fileExists(absFileName)) {
SG_LOG(SG_IO, SG_ALERT, "Cannot find model file \""
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 (needTristrip)
opts |= osgUtil::Optimizer::TRISTRIP_GEOMETRY;
// opts |= osgUtil::Optimizer::TESSELATE_GEOMETRY;
- opts |= osgUtil::Optimizer::OPTIMIZE_TEXTURE_SETTINGS;
+ // opts |= osgUtil::Optimizer::OPTIMIZE_TEXTURE_SETTINGS;
optimizer.optimize(res.getNode(), opts);
- // OSGFIXME
+ // Make sure the data variance of sharable objects is set to STATIC ...
+ SGTexDataVarianceVisitor dataVarianceVisitor;
+ res.getNode()->accept(dataVarianceVisitor);
+ // ... so that textures are now globally shared
registry->getSharedStateManager()->share(res.getNode());
- // OSGFIXME: guard that with a flag
- // OSGFIXME: in the long term it is unclear if we have an OpenGL
- // context here...
- osg::Texture::Extensions* e = osg::Texture::getExtensions(0, true);
- if (e->isTextureCompressionARBSupported()) {
- SGTexCompressionVisitor texComp(osg::Texture::USE_ARB_COMPRESSION);
- res.getNode()->accept(texComp);
- } else if (e->isTextureCompressionS3TCSupported()) {
- SGTexCompressionVisitor texComp(osg::Texture::USE_S3TC_DXT5_COMPRESSION);
- res.getNode()->accept(texComp);
- }
+ SGTexCompressionVisitor texComp;
+ res.getNode()->accept(texComp);
}
// Add an extra reference to the model stored in the database.
res = osgDB::ReaderWriter::ReadResult(osg::CopyOp(flags)(res.getNode()));
res.getNode()->addObserver(databaseReference);
+ // Update liveries
SGTextureUpdateVisitor liveryUpdate(osgDB::getDataFilePathList());
res.getNode()->accept(liveryUpdate);
- // OSGFIXME: don't forget that mutex here
+ // Make sure the data variance of sharable objects is set to STATIC ...
+ SGTexDataVarianceVisitor dataVarianceVisitor;
+ res.getNode()->accept(dataVarianceVisitor);
+ // ... so that textures are now globally shared
registry->getOrCreateSharedStateManager()->share(res.getNode(), 0);
return res;
SGLoadTexture2D(const std::string& path, bool wrapu, bool wrapv, int)
{
osg::Image* image = osgDB::readImageFile(path);
- osg::Texture2D* texture = new osg::Texture2D;
+ osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
texture->setImage(image);
if (wrapu)
texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
int s = image->s();
int t = image->t();
- // OSGFIXME: guard with a flag
- if (osg::Texture::getExtensions(0, true)->isTextureCompressionARBSupported()) {
- if (s <= t && 32 <= s) {
- texture->setInternalFormatMode(osg::Texture::USE_ARB_COMPRESSION);
- } else if (t < s && 32 <= t) {
- texture->setInternalFormatMode(osg::Texture::USE_ARB_COMPRESSION);
- }
- } else if (osg::Texture::getExtensions(0, true)->isTextureCompressionS3TCSupported()) {
- if (s <= t && 32 <= s) {
- texture->setInternalFormatMode(osg::Texture::USE_S3TC_DXT5_COMPRESSION);
- } else if (t < s && 32 <= t) {
- texture->setInternalFormatMode(osg::Texture::USE_S3TC_DXT5_COMPRESSION);
- }
+ if (s <= t && 32 <= s) {
+ SGSceneFeatures::instance()->setTextureCompression(texture.get());
+ } else if (t < s && 32 <= t) {
+ SGSceneFeatures::instance()->setTextureCompression(texture.get());
}
}
- return texture;
+
+ // Make sure the texture is shared if we already have the same texture
+ // somewhere ...
+ {
+ osg::ref_ptr<osg::Node> tmpNode = new osg::Node;
+ osg::StateSet* stateSet = tmpNode->getOrCreateStateSet();
+ stateSet->setTextureAttribute(0, texture.get());
+
+ // OSGFIXME: don't forget that mutex here
+ osgDB::Registry* registry = osgDB::Registry::instance();
+ registry->getOrCreateSharedStateManager()->share(tmpNode.get(), 0);
+
+ // should be the same, but be paranoid ...
+ stateSet = tmpNode->getStateSet();
+ osg::StateAttribute* stateAttr;
+ stateAttr = stateSet->getTextureAttribute(0, osg::StateAttribute::TEXTURE);
+ osg::Texture2D* texture2D = dynamic_cast<osg::Texture2D*>(stateAttr);
+ if (texture2D)
+ texture = texture2D;
+ }
+
+ return texture.release();
}
class SGSwitchUpdateCallback : public osg::NodeCallback {
SGModelData *data,
const SGPath& externalTexturePath )
{
- osg::Node* model = 0;
+ osg::ref_ptr<osg::Node> model;
SGPropertyNode props;
// Load the 3D aircraft object itself
texturepath.append(props.getStringValue("/texture-path"));
}
} else {
- if (model == 0)
+ if (!model)
model = new osg::Switch;
}
}
// Assume that textures are in
// the same location as the XML file.
- if (model == 0) {
+ if (!model) {
if (texturepath.extension() != "")
texturepath = texturepath.dir();
osgDB::Registry::instance()->getDataFilePathList().push_front(externalTexturePath.str());
// Set up the alignment node
- osg::MatrixTransform* alignmainmodel = new osg::MatrixTransform;
- alignmainmodel->addChild(model);
+ osg::ref_ptr<osg::MatrixTransform> alignmainmodel = new osg::MatrixTransform;
+ alignmainmodel->addChild(model.get());
osg::Matrix res_matrix;
res_matrix.makeRotate(
- props.getFloatValue("/offsets/heading-deg", 0.0)*SG_DEGREES_TO_RADIANS,
- osg::Vec3(0, 0, 1),
+ props.getFloatValue("/offsets/pitch-deg", 0.0)*SG_DEGREES_TO_RADIANS,
+ osg::Vec3(0, 1, 0),
props.getFloatValue("/offsets/roll-deg", 0.0)*SG_DEGREES_TO_RADIANS,
osg::Vec3(1, 0, 0),
- props.getFloatValue("/offsets/pitch-deg", 0.0)*SG_DEGREES_TO_RADIANS,
- osg::Vec3(0, 1, 0));
+ props.getFloatValue("/offsets/heading-deg", 0.0)*SG_DEGREES_TO_RADIANS,
+ osg::Vec3(0, 0, 1));
osg::Matrix tmat;
tmat.makeTranslate(props.getFloatValue("/offsets/x-m", 0.0),
vector<SGPropertyNode_ptr> model_nodes = props.getChildren("model");
for (unsigned i = 0; i < model_nodes.size(); i++) {
SGPropertyNode_ptr node = model_nodes[i];
- osg::MatrixTransform* align = new osg::MatrixTransform;
+ osg::ref_ptr<osg::MatrixTransform> align = new osg::MatrixTransform;
res_matrix.makeIdentity();
res_matrix.makeRotate(
- node->getDoubleValue("offsets/heading-deg", 0.0)*SG_DEGREES_TO_RADIANS,
- osg::Vec3(0, 0, 1),
+ node->getDoubleValue("offsets/pitch-deg", 0.0)*SG_DEGREES_TO_RADIANS,
+ osg::Vec3(0, 1, 0),
node->getDoubleValue("offsets/roll-deg", 0.0)*SG_DEGREES_TO_RADIANS,
osg::Vec3(1, 0, 0),
- node->getDoubleValue("offsets/pitch-deg", 0.0)*SG_DEGREES_TO_RADIANS,
- osg::Vec3(0, 1, 0));
+ node->getDoubleValue("offsets/heading-deg", 0.0)*SG_DEGREES_TO_RADIANS,
+ osg::Vec3(0, 0, 1));
tmat.makeIdentity();
tmat.makeTranslate(node->getDoubleValue("offsets/x-m", 0),
node->getDoubleValue("offsets/z-m", 0));
align->setMatrix(res_matrix*tmat);
- osg::Node* kid;
+ osg::ref_ptr<osg::Node> kid;
const char* submodel = node->getStringValue("path");
try {
kid = sgLoad3DModel( fg_root, submodel, prop_root, sim_time_sec, load_panel );
SG_LOG(SG_INPUT, SG_ALERT, "Failed to load submodel: " << t.getFormattedMessage());
throw;
}
- align->addChild(kid);
+ align->addChild(kid.get());
align->setName(node->getStringValue("name", ""));
SGPropertyNode *cond = node->getNode("condition", false);
if (cond) {
- osg::Switch* sw = new osg::Switch;
+ osg::ref_ptr<osg::Switch> sw = new osg::Switch;
sw->setUpdateCallback(new SGSwitchUpdateCallback(sgReadCondition(prop_root, cond)));
- alignmainmodel->addChild(sw);
- sw->addChild(align);
+ alignmainmodel->addChild(sw.get());
+ sw->addChild(align.get());
sw->setName("submodel condition switch");
} else {
- alignmainmodel->addChild(align);
+ alignmainmodel->addChild(align.get());
}
}
vector<SGPropertyNode_ptr> panel_nodes = props.getChildren("panel");
for (unsigned i = 0; i < panel_nodes.size(); i++) {
SG_LOG(SG_INPUT, SG_DEBUG, "Loading a panel");
- osg::Node * panel = load_panel(panel_nodes[i]);
+ osg::ref_ptr<osg::Node> panel = load_panel(panel_nodes[i]);
if (panel_nodes[i]->hasValue("name"))
panel->setName((char *)panel_nodes[i]->getStringValue("name"));
- alignmainmodel->addChild(panel);
+ alignmainmodel->addChild(panel.get());
}
}
if (data) {
alignmainmodel->setUserData(data);
- data->modelLoaded(path, &props, alignmainmodel);
+ data->modelLoaded(path, &props, alignmainmodel.get());
}
std::vector<SGPropertyNode_ptr> animation_nodes;
animation_nodes = props.getChildren("animation");
for (unsigned i = 0; i < animation_nodes.size(); ++i)
/// OSGFIXME: duh, why not only model?????
- SGAnimation::animate(alignmainmodel, animation_nodes[i], prop_root);
+ SGAnimation::animate(alignmainmodel.get(), animation_nodes[i], prop_root);
// restore old path list
osgDB::setDataFilePathList(pathList);
osgDB::writeNodeFile(*alignmainmodel, outputfile);
}
- return alignmainmodel;
+ return alignmainmodel.release();
}
// end of model.cxx