X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;ds=sidebyside;f=simgear%2Fscene%2Fmaterial%2Fmat.cxx;h=8d53f86195a9bb0d0e7d8b61b56ab89b94568943;hb=542124e90cf467e590c4493774210f1e025cdc96;hp=7a0628f0dec1463e0fe1d7caf4428f5d9aa2b18b;hpb=c3b1802e956db11c2b06d354d90bca3ca9622a7b;p=simgear.git diff --git a/simgear/scene/material/mat.cxx b/simgear/scene/material/mat.cxx index 7a0628f0..8d53f861 100644 --- a/simgear/scene/material/mat.cxx +++ b/simgear/scene/material/mat.cxx @@ -32,6 +32,7 @@ #include #include +#include #include "mat.hxx" #include @@ -40,14 +41,18 @@ #include #include #include +#include #include +#include #include #include #include #include - +#include +#include #include +#include #include #include "Effect.hxx" @@ -55,6 +60,7 @@ #include "Pass.hxx" using std::map; +using std::string; using namespace simgear; @@ -62,33 +68,41 @@ using namespace simgear; // Constructors and destructor. //////////////////////////////////////////////////////////////////////// -SGMaterial::_internal_state::_internal_state(osg::StateSet *s, - const std::string &t, bool l ) : - state(s), texture_path(t), texture_loaded(l) +SGMaterial::_internal_state::_internal_state(Effect *e, bool l, + const SGReaderWriterXMLOptions* o) + : effect(e), effect_realized(l), options(o) { } -SGMaterial::SGMaterial( const string &fg_root, const SGPropertyNode *props ) +SGMaterial::_internal_state::_internal_state(Effect *e, const string &t, bool l, + const SGReaderWriterXMLOptions* o) + : effect(e), effect_realized(l), options(o) { - init(); - read_properties( fg_root, props ); - build_state( false ); + texture_paths.push_back(std::make_pair(t,0)); } -SGMaterial::SGMaterial( const string &texpath ) +void SGMaterial::_internal_state::add_texture(const std::string &t, int i) { - init(); - - _internal_state st( NULL, texpath, false ); - _status.push_back( st ); + texture_paths.push_back(std::make_pair(t,i)); +} - build_state( true ); +SGMaterial::SGMaterial( const SGReaderWriterXMLOptions* options, + const SGPropertyNode *props ) +{ + init(); + read_properties( options, props ); + buildEffectProperties(options); } -SGMaterial::SGMaterial( osg::StateSet *s ) +SGMaterial::SGMaterial( const osgDB::ReaderWriter::Options* options, + const SGPropertyNode *props ) { + osg::ref_ptr sgOptions; + if (options) + sgOptions = new SGReaderWriterXMLOptions(*options); init(); - set_state( s ); + read_properties( sgOptions.get(), props ); + buildEffectProperties(sgOptions.get()); } SGMaterial::~SGMaterial (void) @@ -101,7 +115,8 @@ SGMaterial::~SGMaterial (void) //////////////////////////////////////////////////////////////////////// void -SGMaterial::read_properties( const string &fg_root, const SGPropertyNode *props) +SGMaterial::read_properties(const SGReaderWriterXMLOptions* options, + const SGPropertyNode *props) { // Gather the path(s) to the texture(s) vector textures = props->getChildren("texture"); @@ -111,29 +126,53 @@ SGMaterial::read_properties( const string &fg_root, const SGPropertyNode *props) if (tname.empty()) { tname = "unknown.rgb"; } - - SGPath tpath( fg_root ); - tpath.append("Textures.high"); + SGPath tpath("Textures.high"); tpath.append(tname); - if ( !osgDB::fileExists(tpath.str()) ) { - tpath = SGPath( fg_root ); - tpath.append("Textures"); + string fullTexPath = osgDB::findDataFile(tpath.str(), options); + if (fullTexPath.empty()) { + tpath = SGPath("Textures"); tpath.append(tname); + fullTexPath = osgDB::findDataFile(tpath.str(), options); } - if ( osgDB::fileExists(tpath.str()) ) { - _internal_state st( NULL, tpath.str(), false ); + if (!fullTexPath.empty() ) { + _internal_state st( NULL, fullTexPath, false, options ); _status.push_back( st ); } } - if (textures.size() == 0) { - string tname = "unknown.rgb"; - SGPath tpath( fg_root ); - tpath.append("Textures"); + vector texturesets = props->getChildren("texture-set"); + for (unsigned int i = 0; i < texturesets.size(); i++) + { + _internal_state st( NULL, false, options ); + 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 = osgDB::findDataFile(tpath.str(), options); + if (fullTexPath.empty()) { + tpath = SGPath("Textures"); + tpath.append(tname); + fullTexPath = osgDB::findDataFile(tpath.str(), options); + } + 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(tname); - _internal_state st( NULL, tpath.str(), true ); + tpath.append("unknown.rgb"); + _internal_state st( NULL, tpath.str(), true, options ); _status.push_back( st ); } @@ -143,15 +182,19 @@ SGMaterial::read_properties( const string &fg_root, const SGPropertyNode *props) wrapv = props->getBoolValue("wrapv", true); mipmap = props->getBoolValue("mipmap", true); light_coverage = props->getDoubleValue("light-coverage", 0.0); - tree_coverage = props->getDoubleValue("tree-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); - SGPath tpath( fg_root ); - tpath.append(props->getStringValue("tree-texture")); - tree_texture = tpath.str(); + 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", true); @@ -183,6 +226,9 @@ SGMaterial::read_properties( const string &fg_root, const SGPropertyNode *props) 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++) @@ -229,6 +275,7 @@ SGMaterial::init () diffuse[i] = (i < 3) ? 0.8 : 1.0; emission[i] = (i < 3) ? 0.0 : 1.0; } + effect = "Effects/terrain-default"; } Effect* SGMaterial::get_effect(int n) @@ -238,10 +285,9 @@ Effect* SGMaterial::get_effect(int n) return 0; } int i = n >= 0 ? n : _current_ptr; - if(!_status[i].texture_loaded) { - assignTexture(_status[i].state.get(), _status[i].texture_path, - wrapu, wrapv, mipmap); - _status[i].texture_loaded = true; + if(!_status[i].effect_realized) { + _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 @@ -250,72 +296,49 @@ Effect* SGMaterial::get_effect(int n) return _status[i].effect.get(); } -void -SGMaterial::build_state( bool defer_tex_load ) +void SGMaterial::buildEffectProperties(const SGReaderWriterXMLOptions* options) { - StateAttributeFactory *attrFact = StateAttributeFactory::instance(); - SGMaterialUserData* user = new SGMaterialUserData(this); - for (unsigned int i = 0; i < _status.size(); i++) + 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"); + SGPropertyNode* materialProp = makeChild(paramProp, "material"); + makeChild(materialProp, "ambient")->setValue(SGVec4d(ambient)); + makeChild(materialProp, "diffuse")->setValue(SGVec4d(diffuse)); + makeChild(materialProp, "specular")->setValue(SGVec4d(specular)); + makeChild(materialProp, "emissive")->setValue(SGVec4d(emission)); + makeChild(materialProp, "shininess")->setFloatValue(shininess); + if (ambient[3] < 1 || diffuse[3] < 1 || + specular[3] < 1 || emission[3] < 1) { + makeChild(paramProp, "transparent")->setBoolValue(true); + SGPropertyNode* binProp = makeChild(paramProp, "render-bin"); + makeChild(binProp, "bin-number")->setIntValue(TRANSPARENT_BIN); + makeChild(binProp, "bin-name")->setStringValue("DepthSortedBin"); + } + BOOST_FOREACH(_internal_state& matState, _status) { - Pass *pass = new Pass; - pass->setUserData(user); - - // Set up the textured state - pass->setAttribute(attrFact->getSmoothShadeModel()); - pass->setAttributeAndModes(attrFact->getCullFaceBack()); - - pass->setMode(GL_LIGHTING, osg::StateAttribute::ON); - - _status[i].texture_loaded = false; - - osg::Material* material = new osg::Material; - material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE); - material->setAmbient(osg::Material::FRONT_AND_BACK, ambient.osg()); - material->setDiffuse(osg::Material::FRONT_AND_BACK, diffuse.osg()); - material->setSpecular(osg::Material::FRONT_AND_BACK, specular.osg()); - material->setEmission(osg::Material::FRONT_AND_BACK, emission.osg()); - material->setShininess(osg::Material::FRONT_AND_BACK, shininess ); - pass->setAttribute(material); - - if (ambient[3] < 1 || diffuse[3] < 1 || - specular[3] < 1 || emission[3] < 1) { - pass->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); - pass->setMode(GL_BLEND, osg::StateAttribute::ON); - pass->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON); - } else { - pass->setRenderingHint(osg::StateSet::OPAQUE_BIN); - pass->setMode(GL_BLEND, osg::StateAttribute::OFF); - pass->setMode(GL_ALPHA_TEST, osg::StateAttribute::OFF); + SGPropertyNode_ptr effectProp = new SGPropertyNode(); + copyProperties(propRoot, effectProp); + SGPropertyNode* effectParamProp = effectProp->getChild("parameters", 0); + 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"); + makeChild(texProp, "wrap-t") + ->setStringValue(wrapv ? "repeat" : "clamp"); } - - _status[i].state = pass; - Technique* tniq = new Technique(true); - tniq->passes.push_back(pass); - Effect* effect = new Effect; - effect->techniques.push_back(tniq); - effect->setUserData(user); - _status[i].effect = effect; + matState.effect = makeEffect(effectProp, false, xmlOptions.get()); + matState.effect->setUserData(user.get()); } } - -void SGMaterial::set_state( osg::StateSet *s ) -{ - _status.push_back( _internal_state( s, "", true ) ); -} - -void SGMaterial::assignTexture( osg::StateSet *state, const std::string &fname, - bool _wrapu, bool _wrapv, bool _mipmap ) -{ - osg::Texture2D* texture = SGLoadTexture2D(fname, 0, _wrapu, _wrapv, - mipmap ? -1 : 0); - texture->setMaxAnisotropy( SGGetTextureFilter()); - state->setTextureAttributeAndModes(0, texture); - - StateAttributeFactory *attrFact = StateAttributeFactory::instance(); - state->setTextureAttributeAndModes(0, attrFact->getStandardTexEnv()); -} - SGMaterialGlyph* SGMaterial::get_glyph (const string& name) const { map >::const_iterator it;