X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;ds=sidebyside;f=simgear%2Fscene%2Fmaterial%2Fmat.cxx;h=738dd5d028b01cb236664ee32468682e4c1a4fd7;hb=eef73953cba8782da01503c6bb6d86e2d41d1851;hp=5947579e1f5c4af23d94d222aa4945791a75ffb2;hpb=536b8a213b939b9d2580cbf84206f19224c6c339;p=simgear.git diff --git a/simgear/scene/material/mat.cxx b/simgear/scene/material/mat.cxx index 5947579e..738dd5d0 100644 --- a/simgear/scene/material/mat.cxx +++ b/simgear/scene/material/mat.cxx @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include "mat.hxx" @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -49,11 +50,18 @@ #include #include #include -#include +#include + +#include #include +#include #include +#include #include #include +#include +#include +#include #include "Effect.hxx" #include "Technique.hxx" @@ -68,29 +76,42 @@ using namespace simgear; // Constructors and destructor. //////////////////////////////////////////////////////////////////////// -SGMaterial::_internal_state::_internal_state(Effect *e, const string &t, bool l, - const SGReaderWriterXMLOptions* o) - : effect(e), texture_path(t), effect_realized(l), options(o) +SGMaterial::_internal_state::_internal_state(Effect *e, bool l, + const SGReaderWriterOptions* o) + : effect(e), effect_realized(l), options(o) +{ +} + +SGMaterial::_internal_state::_internal_state(Effect *e, const string &t, bool l, + const SGReaderWriterOptions* o) + : effect(e), effect_realized(l), options(o) +{ + texture_paths.push_back(std::make_pair(t,0)); +} + +void SGMaterial::_internal_state::add_texture(const std::string &t, int i) { + texture_paths.push_back(std::make_pair(t,i)); } -SGMaterial::SGMaterial( const SGReaderWriterXMLOptions* options, - const SGPropertyNode *props ) +SGMaterial::SGMaterial( const SGReaderWriterOptions* options, + const SGPropertyNode *props, + SGPropertyNode *prop_root ) { init(); - read_properties( options, props ); + read_properties( options, props, prop_root ); buildEffectProperties(options); } -SGMaterial::SGMaterial( const osgDB::ReaderWriter::Options* options, - const SGPropertyNode *props ) +SGMaterial::SGMaterial( const osgDB::Options* options, + const SGPropertyNode *props, + SGPropertyNode *prop_root) { - osg::ref_ptr sgOptions; - if (options) - sgOptions = new SGReaderWriterXMLOptions(*options); + osg::ref_ptr opt; + opt = SGReaderWriterOptions::copyOrCreate(options); init(); - read_properties( sgOptions.get(), props ); - buildEffectProperties(sgOptions.get()); + read_properties(opt.get(), props, prop_root); + buildEffectProperties(opt.get()); } SGMaterial::~SGMaterial (void) @@ -103,105 +124,295 @@ SGMaterial::~SGMaterial (void) //////////////////////////////////////////////////////////////////////// void -SGMaterial::read_properties(const SGReaderWriterXMLOptions* options, - const SGPropertyNode *props) +SGMaterial::read_properties(const SGReaderWriterOptions* options, + const SGPropertyNode *props, + SGPropertyNode *prop_root) { - // Gather the path(s) to the texture(s) - vector textures = props->getChildren("texture"); - for (unsigned int i = 0; i < textures.size(); i++) - { - string tname = textures[i]->getStringValue(); - if (tname.empty()) { - tname = "unknown.rgb"; + std::vector dds; + std::vector 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.set("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 ); + } } - SGPath tpath("Textures.high"); - tpath.append(tname); - string fullTexPath = osgDB::findDataFile(tpath.str(), options); - if (fullTexPath.empty()) { - tpath = SGPath("Textures"); - tpath.append(tname); - fullTexPath = osgDB::findDataFile(tpath.str(), options); + + std::vector texturesets = props->getChildren("texture-set"); + for (unsigned int i = 0; i < texturesets.size(); i++) + { + _internal_state st( NULL, false, options ); + std::vector 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.set("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 (!fullTexPath.empty() ) { - _internal_state st( NULL, fullTexPath, false, options ); - _status.push_back( st ); + if (textures.empty() && texturesets.empty()) { + SGPath tpath("Textures"); + tpath.append("Terrain"); + tpath.append("unknown.rgb"); + _internal_state st( NULL, tpath.str(), true, options ); + _status.push_back( st ); + } + + std::vector 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.set("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 (i < dds.size() && 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 a copy of the image + // (otherwise a second reference to the object mask would flip it + // back!). + SG_LOG(SG_GENERAL, SG_DEBUG, "Flipping object mask" << omname); + image = (osg::Image* ) image->clone(osg::CopyOp::SHALLOW_COPY); + 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); + } + } + } } - } - if (textures.size() == 0) { - SGPath tpath("Textures"); - tpath.append("Terrain"); - tpath.append("unknown.rgb"); - _internal_state st( NULL, tpath.str(), true, options ); - _status.push_back( st ); - } + xsize = props->getDoubleValue("xsize", 0.0); + ysize = props->getDoubleValue("ysize", 0.0); + wrapu = props->getBoolValue("wrapu", true); + wrapv = props->getBoolValue("wrapv", true); + mipmap = props->getBoolValue("mipmap", true); + light_coverage = props->getDoubleValue("light-coverage", 0.0); + + // Building properties + building_coverage = props->getDoubleValue("building-coverage", 0.0); + building_spacing = props->getDoubleValue("building-spacing-m", 5.0); + + string bt = props->getStringValue("building-texture", "Textures/buildings.png"); + building_texture = SGModelLib::findDataFile(bt, options); + + if (building_texture.empty()) { + SG_LOG(SG_GENERAL, SG_ALERT, "Cannot find texture \"" << bt); + } + + bt = props->getStringValue("building-lightmap", "Textures/buildings-lightmap.png"); + building_lightmap = SGModelLib::findDataFile(bt, options); + + if (building_lightmap.empty()) { + SG_LOG(SG_GENERAL, SG_ALERT, "Cannot find texture \"" << bt); + } + + building_small_ratio = props->getDoubleValue("building-small-ratio", 0.8); + building_medium_ratio = props->getDoubleValue("building-medium-ratio", 0.15); + building_large_ratio = props->getDoubleValue("building-large-ratio", 0.05); + + building_small_pitch = props->getDoubleValue("building-small-pitch", 0.8); + building_medium_pitch = props->getDoubleValue("building-medium-pitch", 0.2); + building_large_pitch = props->getDoubleValue("building-large-pitch", 0.1); + + building_small_min_floors = props->getIntValue("building-small-min-floors", 1); + building_small_max_floors = props->getIntValue("building-small-max-floors", 3); + building_medium_min_floors = props->getIntValue("building-medium-min-floors", 3); + building_medium_max_floors = props->getIntValue("building-medium-max-floors", 8); + building_large_min_floors = props->getIntValue("building-large-min-floors", 5); + building_large_max_floors = props->getIntValue("building-large-max-floors", 20); + + building_small_min_width = props->getFloatValue("building-small-min-width-m", 15.0); + building_small_max_width = props->getFloatValue("building-small-max-width-m", 60.0); + building_small_min_depth = props->getFloatValue("building-small-min-depth-m", 10.0); + building_small_max_depth = props->getFloatValue("building-small-max-depth-m", 20.0); + + building_medium_min_width = props->getFloatValue("building-medium-min-width-m", 25.0); + building_medium_max_width = props->getFloatValue("building-medium-max-width-m", 50.0); + building_medium_min_depth = props->getFloatValue("building-medium-min-depth-m", 20.0); + building_medium_max_depth = props->getFloatValue("building-medium-max-depth-m", 50.0); + + building_large_min_width = props->getFloatValue("building-large-min-width-m", 50.0); + building_large_max_width = props->getFloatValue("building-large-max-width-m", 75.0); + building_large_min_depth = props->getFloatValue("building-large-min-depth-m", 50.0); + building_large_max_depth = props->getFloatValue("building-large-max-depth-m", 75.0); + + building_range = props->getDoubleValue("building-range-m", 10000.0); + + cos_object_max_density_slope_angle = cos(props->getFloatValue("object-max-density-angle-deg", 20.0) * osg::PI/180.0); + cos_object_zero_density_slope_angle = cos(props->getFloatValue("object-zero-density-angle-deg", 30.0) * osg::PI/180.0); + + // Random vegetation properties + wood_coverage = props->getDoubleValue("wood-coverage", 0.0); + tree_height = props->getDoubleValue("tree-height-m", 0.0); + tree_width = props->getDoubleValue("tree-width-m", 0.0); + tree_range = props->getDoubleValue("tree-range-m", 0.0); + tree_varieties = props->getIntValue("tree-varieties", 1); + cos_tree_max_density_slope_angle = cos(props->getFloatValue("tree-max-density-angle-deg", 30.0) * osg::PI/180.0); + cos_tree_zero_density_slope_angle = cos(props->getFloatValue("tree-zero-density-angle-deg", 45.0) * osg::PI/180.0); + + const SGPropertyNode* treeTexNode = props->getChild("tree-texture"); + + if (treeTexNode) { + string treeTexPath = props->getStringValue("tree-texture"); + + if (! treeTexPath.empty()) { + SGPath treePath("Textures.high"); + treePath.append(treeTexPath); + tree_texture = SGModelLib::findDataFile(treePath.str(), options); + + if (tree_texture.empty()) { + treePath.set("Textures"); + treePath.append(treeTexPath); + tree_texture = SGModelLib::findDataFile(treePath.str(), options); + } + } + } - xsize = props->getDoubleValue("xsize", 0.0); - ysize = props->getDoubleValue("ysize", 0.0); - wrapu = props->getBoolValue("wrapu", true); - wrapv = props->getBoolValue("wrapv", true); - mipmap = props->getBoolValue("mipmap", true); - light_coverage = props->getDoubleValue("light-coverage", 0.0); - wood_coverage = props->getDoubleValue("wood-coverage", 0.0); - wood_size = props->getDoubleValue("wood-size", 0.0); - tree_density = props->getDoubleValue("tree-density", 1.0); - tree_height = props->getDoubleValue("tree-height-m", 0.0); - tree_width = props->getDoubleValue("tree-width-m", 0.0); - tree_range = props->getDoubleValue("tree-range-m", 0.0); - tree_varieties = props->getIntValue("tree-varieties", 1); - - const SGPropertyNode* treeTexNode = props->getChild("tree-texture"); - if (treeTexNode) { - string treeTexPath = props->getStringValue("tree-texture"); - tree_texture = osgDB::findDataFile(treeTexPath, options); - } + // surface values for use with ground reactions + _solid = props->getBoolValue("solid", _solid); + _friction_factor = props->getDoubleValue("friction-factor", _friction_factor); + _rolling_friction = props->getDoubleValue("rolling-friction", _rolling_friction); + _bumpiness = props->getDoubleValue("bumpiness", _bumpiness); + _load_resistance = props->getDoubleValue("load-resistance", _load_resistance); + + // Taken from default values as used in ac3d + ambient[0] = props->getDoubleValue("ambient/r", 0.2); + ambient[1] = props->getDoubleValue("ambient/g", 0.2); + ambient[2] = props->getDoubleValue("ambient/b", 0.2); + ambient[3] = props->getDoubleValue("ambient/a", 1.0); + + diffuse[0] = props->getDoubleValue("diffuse/r", 0.8); + diffuse[1] = props->getDoubleValue("diffuse/g", 0.8); + diffuse[2] = props->getDoubleValue("diffuse/b", 0.8); + diffuse[3] = props->getDoubleValue("diffuse/a", 1.0); + + specular[0] = props->getDoubleValue("specular/r", 0.0); + specular[1] = props->getDoubleValue("specular/g", 0.0); + specular[2] = props->getDoubleValue("specular/b", 0.0); + specular[3] = props->getDoubleValue("specular/a", 1.0); + + emission[0] = props->getDoubleValue("emissive/r", 0.0); + emission[1] = props->getDoubleValue("emissive/g", 0.0); + emission[2] = props->getDoubleValue("emissive/b", 0.0); + emission[3] = props->getDoubleValue("emissive/a", 1.0); + + shininess = props->getDoubleValue("shininess", 1.0); + + if (props->hasChild("effect")) + effect = props->getStringValue("effect"); + + std::vector object_group_nodes = + ((SGPropertyNode *)props)->getChildren("object-group"); + for (unsigned int i = 0; i < object_group_nodes.size(); i++) + object_groups.push_back(new SGMatModelGroup(object_group_nodes[i])); + + // read glyph table for taxi-/runway-signs + std::vector glyph_nodes = props->getChildren("glyph"); + for (unsigned int i = 0; i < glyph_nodes.size(); i++) { + const char *name = glyph_nodes[i]->getStringValue("name"); + if (name) + glyphs[name] = new SGMaterialGlyph(glyph_nodes[i]); + } + + // Read parameters entry, which is passed into the effect + if (props->hasChild("parameters")) { + parameters = props->getChild("parameters"); + } else { + parameters = new SGPropertyNode(); + } - // surface values for use with ground reactions - solid = props->getBoolValue("solid", true); - friction_factor = props->getDoubleValue("friction-factor", 1.0); - rolling_friction = props->getDoubleValue("rolling-friction", 0.02); - bumpiness = props->getDoubleValue("bumpiness", 0.0); - load_resistance = props->getDoubleValue("load-resistance", 1e30); - - // Taken from default values as used in ac3d - ambient[0] = props->getDoubleValue("ambient/r", 0.2); - ambient[1] = props->getDoubleValue("ambient/g", 0.2); - ambient[2] = props->getDoubleValue("ambient/b", 0.2); - ambient[3] = props->getDoubleValue("ambient/a", 1.0); - - diffuse[0] = props->getDoubleValue("diffuse/r", 0.8); - diffuse[1] = props->getDoubleValue("diffuse/g", 0.8); - diffuse[2] = props->getDoubleValue("diffuse/b", 0.8); - diffuse[3] = props->getDoubleValue("diffuse/a", 1.0); - - specular[0] = props->getDoubleValue("specular/r", 0.0); - specular[1] = props->getDoubleValue("specular/g", 0.0); - specular[2] = props->getDoubleValue("specular/b", 0.0); - specular[3] = props->getDoubleValue("specular/a", 1.0); - - emission[0] = props->getDoubleValue("emissive/r", 0.0); - emission[1] = props->getDoubleValue("emissive/g", 0.0); - emission[2] = props->getDoubleValue("emissive/b", 0.0); - emission[3] = props->getDoubleValue("emissive/a", 1.0); - - shininess = props->getDoubleValue("shininess", 1.0); - - if (props->hasChild("effect")) - effect = props->getStringValue("effect"); - - vector object_group_nodes = - ((SGPropertyNode *)props)->getChildren("object-group"); - for (unsigned int i = 0; i < object_group_nodes.size(); i++) - object_groups.push_back(new SGMatModelGroup(object_group_nodes[i])); - - // read glyph table for taxi-/runway-signs - vector glyph_nodes = props->getChildren("glyph"); - for (unsigned int i = 0; i < glyph_nodes.size(); i++) { - const char *name = glyph_nodes[i]->getStringValue("name"); - if (name) - glyphs[name] = new SGMaterialGlyph(glyph_nodes[i]); - } + // Read conditions node + const SGPropertyNode *conditionNode = props->getChild("condition"); + if (conditionNode) { + condition = sgReadCondition(prop_root, conditionNode); + } } @@ -214,7 +425,6 @@ void SGMaterial::init () { _status.clear(); - _current_ptr = 0; xsize = 0; ysize = 0; wrapu = true; @@ -222,12 +432,7 @@ SGMaterial::init () mipmap = true; light_coverage = 0.0; - - solid = true; - friction_factor = 1; - rolling_friction = 0.02; - bumpiness = 0; - load_resistance = 1e30; + building_coverage = 0.0; shininess = 1.0; for (int i = 0; i < 4; i++) { @@ -239,36 +444,65 @@ SGMaterial::init () effect = "Effects/terrain-default"; } -Effect* SGMaterial::get_effect(int n) -{ - if (_status.size() == 0) { - SG_LOG( SG_GENERAL, SG_WARN, "No effect available."); - return 0; - } - int i = n >= 0 ? n : _current_ptr; +Effect* SGMaterial::get_effect(int i) +{ if(!_status[i].effect_realized) { + if (!_status[i].effect.valid()) + return 0; _status[i].effect->realizeTechniques(_status[i].options.get()); _status[i].effect_realized = true; } - // XXX This business of returning a "random" alternate texture is - // really bogus. It means that the appearance of the terrain - // depends on the order in which it is paged in! - _current_ptr = (_current_ptr + 1) % _status.size(); return _status[i].effect.get(); } -void SGMaterial::buildEffectProperties(const SGReaderWriterXMLOptions* options) +Effect* SGMaterial::get_effect(const SGTexturedTriangleBin& triangleBin) +{ + SGGuard g(_lock); + if (_status.empty()) { + SG_LOG( SG_GENERAL, SG_WARN, "No effect available."); + return 0; + } + + int i = triangleBin.getTextureIndex() % _status.size(); + return get_effect(i); +} + +Effect* SGMaterial::get_effect() +{ + SGGuard g(_lock); + return get_effect(0); +} + + +osg::Texture2D* SGMaterial::get_object_mask(const SGTexturedTriangleBin& triangleBin) +{ + if (_status.empty()) { + SG_LOG( SG_GENERAL, SG_WARN, "No mask available."); + return 0; + } + + // Note that the object mask is closely linked to the texture/effect + // so we index based on the texture index, + unsigned int i = triangleBin.getTextureIndex() % _status.size(); + if (i < _masks.size()) { + return _masks[i]; + } else { + return 0; + } +} + +void SGMaterial::buildEffectProperties(const SGReaderWriterOptions* options) { using namespace osg; - ref_ptr xmlOptions; - if (options) - xmlOptions = new SGReaderWriterXMLOptions(*options); ref_ptr user = new SGMaterialUserData(this); SGPropertyNode_ptr propRoot = new SGPropertyNode(); makeChild(propRoot, "inherits-from")->setStringValue(effect); + SGPropertyNode* paramProp = makeChild(propRoot, "parameters"); + copyProperties(parameters, paramProp); + SGPropertyNode* materialProp = makeChild(paramProp, "material"); - makeChild(materialProp, "ambient")->setValue(SGVec4d(ambient)); + makeChild(materialProp, "ambient")->setValue(SGVec4d(ambient)); makeChild(materialProp, "diffuse")->setValue(SGVec4d(diffuse)); makeChild(materialProp, "specular")->setValue(SGVec4d(specular)); makeChild(materialProp, "emissive")->setValue(SGVec4d(emission)); @@ -285,27 +519,44 @@ void SGMaterial::buildEffectProperties(const SGReaderWriterXMLOptions* options) SGPropertyNode_ptr effectProp = new SGPropertyNode(); copyProperties(propRoot, effectProp); SGPropertyNode* effectParamProp = effectProp->getChild("parameters", 0); - SGPropertyNode* texProp = makeChild(effectParamProp, "texture"); - makeChild(texProp, "image")->setStringValue(matState.texture_path); - makeChild(texProp, "filter") - ->setStringValue(mipmap ? "linear-mipmap-linear" : "nearest"); - makeChild(texProp, "wrap-s") - ->setStringValue(wrapu ? "repeat" : "clamp"); - makeChild(texProp, "wrap-t") - ->setStringValue(wrapv ? "repeat" : "clamp"); - matState.effect = makeEffect(effectProp, false, xmlOptions.get()); - matState.effect->setUserData(user.get()); + for (unsigned int i = 0; i < matState.texture_paths.size(); i++) { + SGPropertyNode* texProp = makeChild(effectParamProp, "texture", matState.texture_paths[i].second); + makeChild(texProp, "image")->setStringValue(matState.texture_paths[i].first); + makeChild(texProp, "filter") + ->setStringValue(mipmap ? "linear-mipmap-linear" : "nearest"); + makeChild(texProp, "wrap-s") + ->setStringValue(wrapu ? "repeat" : "clamp-to-edge"); + makeChild(texProp, "wrap-t") + ->setStringValue(wrapv ? "repeat" : "clamp-to-edge"); + } + makeChild(effectParamProp, "xsize")->setDoubleValue(xsize); + makeChild(effectParamProp, "ysize")->setDoubleValue(ysize); + makeChild(effectParamProp, "scale")->setValue(SGVec3d(xsize,ysize,0.0)); + makeChild(effectParamProp, "light-coverage")->setDoubleValue(light_coverage); + + matState.effect = makeEffect(effectProp, false, options); + if (matState.effect.valid()) + matState.effect->setUserData(user.get()); } } SGMaterialGlyph* SGMaterial::get_glyph (const string& name) const { - map >::const_iterator it; - it = glyphs.find(name); - if (it == glyphs.end()) - return 0; + map >::const_iterator it; + it = glyphs.find(name); + if (it == glyphs.end()) + return 0; - return it->second; + return it->second; +} + +bool SGMaterial::valid() const +{ + if (condition) { + return condition->test(); + } else { + return true; + } } @@ -321,10 +572,10 @@ SGMaterialGlyph::SGMaterialGlyph(SGPropertyNode *p) : void SGSetTextureFilter( int max) { - SGSceneFeatures::instance()->setTextureFilter( max); + SGSceneFeatures::instance()->setTextureFilter( max); } int SGGetTextureFilter() { - return SGSceneFeatures::instance()->getTextureFilter(); + return SGSceneFeatures::instance()->getTextureFilter(); }