X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;ds=inline;f=simgear%2Fscene%2Fmaterial%2Fmat.cxx;h=8d53f86195a9bb0d0e7d8b61b56ab89b94568943;hb=542124e90cf467e590c4493774210f1e025cdc96;hp=eceed3c5601962d72a0e64329d13aadcbecaf8c9;hpb=b7dd267807e5c8e454de08d0d33b94e6cfe7de27;p=simgear.git diff --git a/simgear/scene/material/mat.cxx b/simgear/scene/material/mat.cxx index eceed3c5..8d53f861 100644 --- a/simgear/scene/material/mat.cxx +++ b/simgear/scene/material/mat.cxx @@ -2,7 +2,7 @@ // // Written by Curtis Olson, started May 1998. // -// Copyright (C) 1998 - 2000 Curtis L. Olson - curt@flightgear.org +// Copyright (C) 1998 - 2000 Curtis L. Olson - http://www.flightgear.org/~curt // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -16,7 +16,7 @@ // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // $Id$ @@ -27,94 +27,152 @@ #include +#include #include -SG_USING_STD(map); +#include +#include -#include +#include +#include "mat.hxx" -#ifdef SG_MATH_EXCEPTION_CLASH -# include -#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include +#include +#include +#include +#include +#include -#include "mat.hxx" +#include "Effect.hxx" +#include "Technique.hxx" +#include "Pass.hxx" + +using std::map; +using std::string; +using namespace simgear; //////////////////////////////////////////////////////////////////////// // Constructors and destructor. //////////////////////////////////////////////////////////////////////// - -SGMaterial::SGMaterial( const string &fg_root, const SGPropertyNode *props ) +SGMaterial::_internal_state::_internal_state(Effect *e, bool l, + const SGReaderWriterXMLOptions* o) + : effect(e), effect_realized(l), options(o) { - init(); - read_properties( fg_root, props ); - build_ssg_state( false ); } -SGMaterial::SGMaterial( const string &texpath ) +SGMaterial::_internal_state::_internal_state(Effect *e, const string &t, bool l, + const SGReaderWriterXMLOptions* o) + : effect(e), effect_realized(l), options(o) { - init(); + texture_paths.push_back(std::make_pair(t,0)); +} - _internal_state st = { NULL, "", false }; - st.texture_path = texpath; - _status.push_back( st ); +void SGMaterial::_internal_state::add_texture(const std::string &t, int i) +{ + texture_paths.push_back(std::make_pair(t,i)); +} - build_ssg_state( true ); +SGMaterial::SGMaterial( const SGReaderWriterXMLOptions* options, + const SGPropertyNode *props ) +{ + init(); + read_properties( options, props ); + buildEffectProperties(options); } -SGMaterial::SGMaterial( ssgSimpleState *s ) +SGMaterial::SGMaterial( const osgDB::ReaderWriter::Options* options, + const SGPropertyNode *props ) { + osg::ref_ptr sgOptions; + if (options) + sgOptions = new SGReaderWriterXMLOptions(*options); init(); - set_ssg_state( s ); + read_properties( sgOptions.get(), props ); + buildEffectProperties(sgOptions.get()); } SGMaterial::~SGMaterial (void) { - for (unsigned int i = 0; i < object_groups.size(); i++) { - delete object_groups[i]; - object_groups[i] = 0; - } } - //////////////////////////////////////////////////////////////////////// // Public methods. //////////////////////////////////////////////////////////////////////// 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"); - for (int i = 0; i < textures.size(); i++) + for (unsigned int i = 0; i < textures.size(); i++) { string tname = textures[i]->getStringValue(); - if (tname == "") + if (tname.empty()) { tname = "unknown.rgb"; - - SGPath tpath( fg_root ); - tpath.append("Textures.high"); + } + SGPath tpath("Textures.high"); tpath.append(tname); - if (!ulFileExists(tpath.c_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 (!fullTexPath.empty() ) { + _internal_state st( NULL, fullTexPath, false, options ); + _status.push_back( st ); } - _internal_state st = { NULL, tpath.str(), false }; - _status.push_back( st ); } - if (textures.size() == 0) { - string tname = "unknown.rgb"; - SGPath tpath( fg_root ); - tpath.append("Textures"); - tpath.append(tname); - _internal_state st = { NULL, tpath.str(), true }; + 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("unknown.rgb"); + _internal_state st( NULL, tpath.str(), true, options ); _status.push_back( st ); } @@ -124,6 +182,26 @@ 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); + 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", 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); @@ -148,10 +226,21 @@ 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++) 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]); + } } @@ -164,13 +253,21 @@ void SGMaterial::init () { _status.clear(); + _current_ptr = 0; xsize = 0; ysize = 0; wrapu = true; wrapv = true; + mipmap = true; light_coverage = 0.0; - refcount = 0; + + solid = true; + friction_factor = 1; + rolling_friction = 0.02; + bumpiness = 0; + load_resistance = 1e30; + shininess = 1.0; for (int i = 0; i < 4; i++) { ambient[i] = (i < 3) ? 0.2 : 1.0; @@ -178,97 +275,97 @@ SGMaterial::init () diffuse[i] = (i < 3) ? 0.8 : 1.0; emission[i] = (i < 3) ? 0.0 : 1.0; } + effect = "Effects/terrain-default"; } -bool -SGMaterial::load_texture ( int n ) +Effect* SGMaterial::get_effect(int n) { - int i = (n >= 0) ? n : 0 ; - int end = (n >= 0) ? n+1 : _status.size(); - - for (; i < end; i++) - { - if ( !_status[i].texture_loaded ) { - SG_LOG( SG_GENERAL, SG_INFO, "Loading deferred texture " - << _status[i].texture_path ); - _status[i].state->setTexture( - (char *)_status[i].texture_path.c_str(), - wrapu, wrapv, mipmap ); - _status[i].texture_loaded = true; - } + if (_status.size() == 0) { + SG_LOG( SG_GENERAL, SG_WARN, "No effect available."); + return 0; + } + int i = n >= 0 ? n : _current_ptr; + if(!_status[i].effect_realized) { + _status[i].effect->realizeTechniques(_status[i].options.get()); + _status[i].effect_realized = true; } - return 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(); } -ssgSimpleState * -SGMaterial::get_state (int n) const +void SGMaterial::buildEffectProperties(const SGReaderWriterXMLOptions* options) { - static unsigned current = 0; - - if (_status.size() == 0) { - SG_LOG( SG_GENERAL, SG_WARN, "No state available."); - return NULL; + 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) + { + 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"); + } + matState.effect = makeEffect(effectProp, false, xmlOptions.get()); + matState.effect->setUserData(user.get()); } - - if ( ++current >= _status.size()) - current = 0; - - return (n >= 0) ? _status[n].state : _status[current].state; } - -void -SGMaterial::build_ssg_state( bool defer_tex_load ) +SGMaterialGlyph* SGMaterial::get_glyph (const string& name) const { - GLenum shade_model = GL_SMOOTH; - - for (int i = 0; i < _status.size(); i++) - { - ssgSimpleState *state = new ssgSimpleState(); - state->ref(); - - // Set up the textured state - state->setShadeModel( shade_model ); - state->enable( GL_LIGHTING ); - state->enable ( GL_CULL_FACE ) ; - state->enable( GL_TEXTURE_2D ); - state->disable( GL_BLEND ); - state->disable( GL_ALPHA_TEST ); - - if ( !defer_tex_load ) { - SG_LOG(SG_INPUT, SG_INFO, " " << _status[i].texture_path ); - state->setTexture( (char *)_status[i].texture_path.c_str(), - wrapu, wrapv ); - _status[i].texture_loaded = true; - } else { - _status[i].texture_loaded = false; - } + map >::const_iterator it; + it = glyphs.find(name); + if (it == glyphs.end()) + return 0; - state->enable( GL_COLOR_MATERIAL ); - state->setMaterial ( GL_AMBIENT, - ambient[0], ambient[1], - ambient[2], ambient[3] ) ; - state->setMaterial ( GL_DIFFUSE, - diffuse[0], diffuse[1], - diffuse[2], diffuse[3] ) ; - state->setMaterial ( GL_SPECULAR, - specular[0], specular[1], - specular[2], specular[3] ) ; - state->setMaterial ( GL_EMISSION, - emission[0], emission[1], - emission[2], emission[3] ) ; - state->setShininess ( shininess ); - - _status[i].state = state; - } + return it->second; } + +//////////////////////////////////////////////////////////////////////// +// SGMaterialGlyph. +//////////////////////////////////////////////////////////////////////// -void SGMaterial::set_ssg_state( ssgSimpleState *s ) +SGMaterialGlyph::SGMaterialGlyph(SGPropertyNode *p) : + _left(p->getDoubleValue("left", 0.0)), + _right(p->getDoubleValue("right", 1.0)) { - _internal_state st = { s, "", true }; - st.state->ref(); - _status.push_back( st ); } -// end of mat.cxx +void +SGSetTextureFilter( int max) { + SGSceneFeatures::instance()->setTextureFilter( max); +} + +int +SGGetTextureFilter() { + return SGSceneFeatures::instance()->getTextureFilter(); +}