+ std::vector<bool> dds;
+ std::vector<SGPropertyNode_ptr> textures = props->getChildren("texture");
+ for (unsigned int i = 0; i < textures.size(); i++)
+ {
+ string tname = textures[i]->getStringValue();
+
+ if (tname.empty()) {
+ tname = "unknown.rgb";
+ }
+
+ SGPath tpath("Textures.high");
+ tpath.append(tname);
+ string fullTexPath = SGModelLib::findDataFile(tpath.str(), options);
+ if (fullTexPath.empty()) {
+ tpath = SGPath("Textures");
+ tpath.append(tname);
+ fullTexPath = SGModelLib::findDataFile(tpath.str(), options);
+ if (fullTexPath.empty()) {
+ SG_LOG(SG_GENERAL, SG_ALERT, "Cannot find texture \""
+ << tname << "\" in Textures or Textures.high folders.");
+ }
+ }
+
+ if (tpath.lower_extension() == "dds") {
+ dds.push_back(true);
+ } else {
+ dds.push_back(false);
+ }
+
+ if (!fullTexPath.empty() ) {
+ _internal_state st( NULL, fullTexPath, false, options );
+ _status.push_back( st );
+ }
+ }
+
+ std::vector<SGPropertyNode_ptr> texturesets = props->getChildren("texture-set");
+ for (unsigned int i = 0; i < texturesets.size(); i++)
+ {
+ _internal_state st( NULL, false, options );
+ std::vector<SGPropertyNode_ptr> textures = texturesets[i]->getChildren("texture");
+ for (unsigned int j = 0; j < textures.size(); j++)
+ {
+ string tname = textures[j]->getStringValue();
+ if (tname.empty()) {
+ tname = "unknown.rgb";
+ }
+
+ SGPath tpath("Textures.high");
+ tpath.append(tname);
+ string fullTexPath = SGModelLib::findDataFile(tpath.str(), options);
+ if (fullTexPath.empty()) {
+ tpath = SGPath("Textures");
+ tpath.append(tname);
+ fullTexPath = SGModelLib::findDataFile(tpath.str(), options);
+ if (fullTexPath.empty() ) {
+ SG_LOG(SG_GENERAL, SG_ALERT, "Cannot find texture \""
+ << tname << "\" in Textures or Textures.high folders.");
+ }
+ }
+
+ if (j == 0) {
+ if (tpath.lower_extension() == "dds") {
+ dds.push_back(true);
+ } else {
+ dds.push_back(false);
+ }
+ }
+
+ st.add_texture(fullTexPath, textures[j]->getIndex());
+ }
+
+ if (!st.texture_paths.empty() ) {
+ _status.push_back( st );
+ }
+ }
+
+ if (textures.size() == 0 && texturesets.size() == 0) {
+ SGPath tpath("Textures");
+ tpath.append("Terrain");
+ tpath.append("unknown.rgb");
+ _internal_state st( NULL, tpath.str(), true, options );
+ _status.push_back( st );
+ }
+
+ std::vector<SGPropertyNode_ptr> masks = props->getChildren("object-mask");
+ for (unsigned int i = 0; i < masks.size(); i++)
+ {
+ string omname = masks[i]->getStringValue();
+
+ if (! omname.empty()) {
+ SGPath ompath("Textures.high");
+ ompath.append(omname);
+ string fullMaskPath = SGModelLib::findDataFile(ompath.str(), options);
+
+ if (fullMaskPath.empty()) {
+ ompath = SGPath("Textures");
+ ompath.append(omname);
+ fullMaskPath = SGModelLib::findDataFile(ompath.str(), options);
+ }
+
+ if (fullMaskPath.empty()) {
+ SG_LOG(SG_GENERAL, SG_ALERT, "Cannot find texture \""
+ << omname << "\" in Textures or Textures.high folders.");
+ }
+ else
+ {
+ osg::Image* image = osgDB::readImageFile(fullMaskPath, options);
+ if (image && image->valid())
+ {
+ osg::Texture2D* object_mask = new osg::Texture2D;
+
+ bool dds_mask = (ompath.lower_extension() == "dds");
+
+ if (dds[i] != dds_mask) {
+ // Texture format does not match mask format. This is relevant for
+ // the object mask, as DDS textures have an origin at the bottom
+ // left rather than top left, therefore we flip the object mask
+ // vertically.
+ image->flipVertical();
+ }
+
+ object_mask->setImage(image);
+
+ // We force the filtering to be nearest, as the red channel (rotation)
+ // in particular, doesn't make sense to be interpolated between pixels.
+ object_mask->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);
+ object_mask->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);
+
+ object_mask->setDataVariance(osg::Object::STATIC);
+ object_mask->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
+ object_mask->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
+ _masks.push_back(object_mask);
+ }
+ }
+ }