X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fscene%2Fmaterial%2Fmat.cxx;h=2d488f345eb7db8da34c8bbebbba5b3a9fcdd932;hb=373a0e4a7d59c3f8ed1d66ff6145de61ecd46279;hp=a0c4557d44650e0b1d8cd95e23e22a80e631ed56;hpb=d8a75897526f2ba2a030225a22dfbd93c7c39a7e;p=simgear.git diff --git a/simgear/scene/material/mat.cxx b/simgear/scene/material/mat.cxx index a0c4557d..2d488f34 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,225 +27,30 @@ #include +#include #include SG_USING_STD(map); -#include +#include #ifdef SG_MATH_EXCEPTION_CLASH # include #endif +#include +#include +#include +#include +#include +#include + #include -#include #include #include -#include - -#include "mat.hxx" - - -//////////////////////////////////////////////////////////////////////// -// Local static functions. -//////////////////////////////////////////////////////////////////////// - -/** - * Internal method to test whether a file exists. - * - * TODO: this should be moved to a SimGear library of local file - * functions. - */ -static inline bool -local_file_exists( const string& path ) { - sg_gzifstream in( path ); - if ( ! in.is_open() ) { - return false; - } else { - return true; - } -} - - - -//////////////////////////////////////////////////////////////////////// -// Implementation of SGMaterial::Object. -//////////////////////////////////////////////////////////////////////// - -SGMaterial::Object::Object (const SGPropertyNode * node, double range_m) - : _models_loaded(false), - _coverage_m2(node->getDoubleValue("coverage-m2", 1000000)), - _range_m(range_m) -{ - // Sanity check - if (_coverage_m2 < 1000) { - SG_LOG(SG_INPUT, SG_ALERT, "Random object coverage " << _coverage_m2 - << " is too small, forcing, to 1000"); - _coverage_m2 = 1000; - } - // Note all the model paths - vector path_nodes = node->getChildren("path"); - for (unsigned int i = 0; i < path_nodes.size(); i++) - _paths.push_back(path_nodes[i]->getStringValue()); - - // Note the heading type - string hdg = node->getStringValue("heading-type", "fixed"); - if (hdg == "fixed") { - _heading_type = HEADING_FIXED; - } else if (hdg == "billboard") { - _heading_type = HEADING_BILLBOARD; - } else if (hdg == "random") { - _heading_type = HEADING_RANDOM; - } else { - _heading_type = HEADING_FIXED; - SG_LOG(SG_INPUT, SG_ALERT, "Unknown heading type: " << hdg - << "; using 'fixed' instead."); - } - - // uncomment to preload models - // load_models(); -} - -SGMaterial::Object::~Object () -{ - for (unsigned int i = 0; i < _models.size(); i++) { - if (_models[i] != 0) { - _models[i]->deRef(); - _models[i] = 0; - } - } -} - -int -SGMaterial::Object::get_model_count( SGModelLoader *loader, - const string &fg_root, - SGPropertyNode *prop_root, - double sim_time_sec ) -{ - load_models( loader, fg_root, prop_root, sim_time_sec ); - return _models.size(); -} - -inline void -SGMaterial::Object::load_models ( SGModelLoader *loader, - const string &fg_root, - SGPropertyNode *prop_root, - double sim_time_sec ) -{ - // Load model only on demand - if (!_models_loaded) { - for (unsigned int i = 0; i < _paths.size(); i++) { - ssgEntity *entity = loader->load_model( fg_root, _paths[i], - prop_root, sim_time_sec ); - if (entity != 0) { - // FIXME: this stuff can be handled - // in the XML wrapper as well (at least, - // the billboarding should be handled - // there). - float ranges[] = {0, _range_m}; - ssgRangeSelector * lod = new ssgRangeSelector; - lod->ref(); - lod->setRanges(ranges, 2); - if (_heading_type == HEADING_BILLBOARD) { - ssgCutout * cutout = new ssgCutout(false); - cutout->addKid(entity); - lod->addKid(cutout); - } else { - lod->addKid(entity); - } - _models.push_back(lod); - } else { - SG_LOG(SG_INPUT, SG_ALERT, "Failed to load object " << _paths[i]); - } - } - } - _models_loaded = true; -} - -ssgEntity * -SGMaterial::Object::get_model( int index, - SGModelLoader *loader, - const string &fg_root, - SGPropertyNode *prop_root, - double sim_time_sec ) -{ - load_models( loader, fg_root, prop_root, sim_time_sec ); // comment this out if preloading models - return _models[index]; -} - -ssgEntity * -SGMaterial::Object::get_random_model( SGModelLoader *loader, - const string &fg_root, - SGPropertyNode *prop_root, - double sim_time_sec ) -{ - load_models( loader, fg_root, prop_root, sim_time_sec ); // comment this out if preloading models - int nModels = _models.size(); - int index = int(sg_random() * nModels); - if (index >= nModels) - index = 0; - return _models[index]; -} - -double -SGMaterial::Object::get_coverage_m2 () const -{ - return _coverage_m2; -} - -SGMaterial::Object::HeadingType -SGMaterial::Object::get_heading_type () const -{ - return _heading_type; -} - - - -//////////////////////////////////////////////////////////////////////// -// Implementation of SGMaterial::ObjectGroup. -//////////////////////////////////////////////////////////////////////// - -SGMaterial::ObjectGroup::ObjectGroup (SGPropertyNode * node) - : _range_m(node->getDoubleValue("range-m", 2000)) -{ - // Load the object subnodes - vector object_nodes = - ((SGPropertyNode *)node)->getChildren("object"); - for (unsigned int i = 0; i < object_nodes.size(); i++) { - const SGPropertyNode * object_node = object_nodes[i]; - if (object_node->hasChild("path")) - _objects.push_back(new Object(object_node, _range_m)); - else - SG_LOG(SG_INPUT, SG_ALERT, "No path supplied for object"); - } -} - -SGMaterial::ObjectGroup::~ObjectGroup () -{ - for (unsigned int i = 0; i < _objects.size(); i++) { - delete _objects[i]; - _objects[i] = 0; - } -} - -double -SGMaterial::ObjectGroup::get_range_m () const -{ - return _range_m; -} - -int -SGMaterial::ObjectGroup::get_object_count () const -{ - return _objects.size(); -} - -SGMaterial::Object * -SGMaterial::ObjectGroup::get_object (int index) const -{ - return _objects[index]; -} +#include +#include "mat.hxx" //////////////////////////////////////////////////////////////////////// @@ -253,39 +58,31 @@ SGMaterial::ObjectGroup::get_object (int index) const //////////////////////////////////////////////////////////////////////// -SGMaterial::SGMaterial( const string &fg_root, - const SGPropertyNode *props, - bool smooth_shading, - bool use_textures ) +SGMaterial::SGMaterial( const string &fg_root, const SGPropertyNode *props, const char *season ) { init(); - read_properties( fg_root, props ); - build_ssg_state( false, smooth_shading, use_textures ); + read_properties( fg_root, props, season ); + build_state( false ); } -SGMaterial::SGMaterial( const string &texpath, - bool smooth_shading, - bool use_textures ) +SGMaterial::SGMaterial( const string &texpath ) { init(); - texture_path = texpath; - build_ssg_state( true, smooth_shading, use_textures ); + + _internal_state st( NULL, texpath, false ); + _status.push_back( st ); + + build_state( true ); } -SGMaterial::SGMaterial( ssgSimpleState *s, - bool smooth_shading, - bool use_textures ) +SGMaterial::SGMaterial( osg::StateSet *s ) { init(); - set_ssg_state( s, smooth_shading, use_textures ); + set_state( s ); } SGMaterial::~SGMaterial (void) { - for (unsigned int i = 0; i < object_groups.size(); i++) { - delete object_groups[i]; - object_groups[i] = 0; - } } @@ -295,19 +92,43 @@ SGMaterial::~SGMaterial (void) //////////////////////////////////////////////////////////////////////// void -SGMaterial::read_properties( const string &fg_root, const SGPropertyNode * props ) +SGMaterial::read_properties( const string &fg_root, const SGPropertyNode * props, const char *season ) { - // Get the path to the texture - string tname = props->getStringValue("texture", "unknown.rgb"); - SGPath tpath( fg_root ); - tpath.append("Textures.high"); - tpath.append(tname); - if (!local_file_exists(tpath.str())) { - tpath = SGPath( fg_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(); + string otname = tname; + + if (tname == "") { + tname = "unknown.rgb"; + } + + SGPath tpath( fg_root ); + tpath.append("Textures.high"); + tpath.append(tname); + if ( !ulFileExists(tpath.c_str()) ) { + tpath = SGPath( fg_root ); + tpath.append("Textures"); + tpath.append(tname); + } + + if ( ulFileExists(tpath.c_str()) ) { + _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("Terrain"); tpath.append(tname); + _internal_state st( NULL, tpath.str(), true ); + _status.push_back( st ); } - texture_path = tpath.str(); xsize = props->getDoubleValue("xsize", 0.0); ysize = props->getDoubleValue("ysize", 0.0); @@ -315,33 +136,58 @@ 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); + 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); - ambient[0] = props->getDoubleValue("ambient/r", 0.0); - ambient[1] = props->getDoubleValue("ambient/g", 0.0); - ambient[2] = props->getDoubleValue("ambient/b", 0.0); - ambient[3] = props->getDoubleValue("ambient/a", 0.0); - - diffuse[0] = props->getDoubleValue("diffuse/r", 0.0); - diffuse[1] = props->getDoubleValue("diffuse/g", 0.0); - diffuse[2] = props->getDoubleValue("diffuse/b", 0.0); - diffuse[3] = props->getDoubleValue("diffuse/a", 0.0); + SGPath tpath( fg_root ); + tpath.append(props->getStringValue("tree-texture")); + tree_texture = tpath.str(); + + // 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", 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", 0.0); + emission[3] = props->getDoubleValue("emissive/a", 1.0); - shininess = props->getDoubleValue("shininess", 0.0); + shininess = props->getDoubleValue("shininess", 1.0); 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 ObjectGroup(object_group_nodes[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]); + } } @@ -353,175 +199,149 @@ SGMaterial::read_properties( const string &fg_root, const SGPropertyNode * props void SGMaterial::init () { - texture_path = ""; - state = 0; - textured = 0; - nontextured = 0; + _status.clear(); + _current_ptr = 0; xsize = 0; ysize = 0; wrapu = true; wrapv = true; + mipmap = true; light_coverage = 0.0; - texture_loaded = false; - refcount = 0; - shininess = 0.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] = diffuse[i] = specular[i] = emission[i] = 0.0; + ambient[i] = (i < 3) ? 0.2 : 1.0; + specular[i] = (i < 3) ? 0.0 : 1.0; + diffuse[i] = (i < 3) ? 0.8 : 1.0; + emission[i] = (i < 3) ? 0.0 : 1.0; } } -bool -SGMaterial::load_texture () +osg::StateSet * +SGMaterial::get_state (int n) { - if (texture_loaded) { - return false; - } else { - SG_LOG( SG_GENERAL, SG_INFO, "Loading deferred texture " - << texture_path ); - textured->setTexture( (char *)texture_path.c_str(), - wrapu, wrapv, mipmap ); - texture_loaded = true; - return true; + if (_status.size() == 0) { + SG_LOG( SG_GENERAL, SG_WARN, "No state available."); + return NULL; + } + + 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; } + osg::StateSet *st = _status[i].state.get(); + + _current_ptr += 1; + if (_current_ptr >= _status.size()) + _current_ptr = 0; + + return st; } void -SGMaterial::build_ssg_state( bool defer_tex_load, - bool smooth_shading, - bool use_textures ) +SGMaterial::build_state( bool defer_tex_load ) { - GLenum shade_model = ( smooth_shading ? GL_SMOOTH : GL_FLAT); - - state = new ssgStateSelector(2); - state->ref(); - - textured = new ssgSimpleState(); - textured->ref(); - - nontextured = new ssgSimpleState(); - nontextured->ref(); - - // Set up the textured state - textured->setShadeModel( shade_model ); - textured->enable( GL_LIGHTING ); - textured->enable ( GL_CULL_FACE ) ; - textured->enable( GL_TEXTURE_2D ); - textured->disable( GL_BLEND ); - textured->disable( GL_ALPHA_TEST ); - if ( !defer_tex_load ) { - SG_LOG(SG_INPUT, SG_INFO, " " << texture_path ); - textured->setTexture( (char *)texture_path.c_str(), wrapu, wrapv ); - texture_loaded = true; - } else { - texture_loaded = false; + for (unsigned int i = 0; i < _status.size(); i++) + { + osg::StateSet *stateSet = new osg::StateSet; + stateSet->setUserData(new SGMaterialUserData(this)); + + // Set up the textured state + osg::ShadeModel* shadeModel = new osg::ShadeModel; + shadeModel->setMode(osg::ShadeModel::SMOOTH); + stateSet->setAttribute(shadeModel); + + osg::CullFace* cullFace = new osg::CullFace; + cullFace->setMode(osg::CullFace::BACK); + stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::ON); + stateSet->setAttribute(cullFace); + + stateSet->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 ); + stateSet->setAttribute(material); + + if (ambient[3] < 1 || diffuse[3] < 1 || + specular[3] < 1 || emission[3] < 1) { + stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); + stateSet->setMode(GL_BLEND, osg::StateAttribute::ON); + stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON); + } else { + stateSet->setRenderingHint(osg::StateSet::OPAQUE_BIN); + stateSet->setMode(GL_BLEND, osg::StateAttribute::OFF); + stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::OFF); + } + + _status[i].state = stateSet; } - textured->enable( GL_COLOR_MATERIAL ); -#if 0 - textured->setColourMaterial( GL_AMBIENT_AND_DIFFUSE ); - textured->setMaterial( GL_EMISSION, 0, 0, 0, 1 ); - textured->setMaterial( GL_SPECULAR, 0, 0, 0, 1 ); -#else - textured->setMaterial ( GL_AMBIENT, - ambient[0], ambient[1], - ambient[2], ambient[3] ) ; - textured->setMaterial ( GL_DIFFUSE, - diffuse[0], diffuse[1], - diffuse[2], diffuse[3] ) ; - textured->setMaterial ( GL_SPECULAR, - specular[0], specular[1], - specular[2], specular[3] ) ; - textured->setMaterial ( GL_EMISSION, - emission[0], emission[1], - emission[2], emission[3] ) ; - textured->setShininess ( shininess ); -#endif +} - // Set up the coloured state - nontextured->enable( GL_LIGHTING ); - nontextured->setShadeModel( shade_model ); - nontextured->enable ( GL_CULL_FACE ) ; - nontextured->disable( GL_TEXTURE_2D ); - nontextured->disable( GL_BLEND ); - nontextured->disable( GL_ALPHA_TEST ); - nontextured->disable( GL_COLOR_MATERIAL ); - - nontextured->setMaterial ( GL_AMBIENT, - ambient[0], ambient[1], - ambient[2], ambient[3] ) ; - nontextured->setMaterial ( GL_DIFFUSE, - diffuse[0], diffuse[1], - diffuse[2], diffuse[3] ) ; - nontextured->setMaterial ( GL_SPECULAR, - specular[0], specular[1], - specular[2], specular[3] ) ; - nontextured->setMaterial ( GL_EMISSION, - emission[0], emission[1], - emission[2], emission[3] ) ; - nontextured->setShininess ( shininess ); - - state->setStep( 0, textured ); // textured - state->setStep( 1, nontextured ); // untextured - - // Choose the appropriate starting state. - if ( use_textures ) { - state->selectStep(0); - } else { - state->selectStep(1); - } + +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); + + osg::TexEnv* texEnv = new osg::TexEnv; + texEnv->setMode(osg::TexEnv::MODULATE); + state->setTextureAttributeAndModes(0, texEnv); +} -void SGMaterial::set_ssg_state( ssgSimpleState *s, - bool smooth_shading, bool use_textures ) +SGMaterialGlyph* SGMaterial::get_glyph (const string& name) const +{ + map >::const_iterator it; + it = glyphs.find(name); + if (it == glyphs.end()) + return 0; + + return it->second; +} + + +//////////////////////////////////////////////////////////////////////// +// SGMaterialGlyph. +//////////////////////////////////////////////////////////////////////// + +SGMaterialGlyph::SGMaterialGlyph(SGPropertyNode *p) : + _left(p->getDoubleValue("left", 0.0)), + _right(p->getDoubleValue("right", 1.0)) { - GLenum shade_model = ( smooth_shading ? GL_SMOOTH : GL_FLAT); - - state = new ssgStateSelector(2); - state->ref(); - - textured = s; - texture_loaded = true; - - nontextured = new ssgSimpleState(); - nontextured->ref(); - - // Set up the textured state - textured->setShadeModel( shade_model ); - - // Set up the coloured state - nontextured->enable( GL_LIGHTING ); - nontextured->setShadeModel( shade_model ); - nontextured->enable ( GL_CULL_FACE ) ; - nontextured->disable( GL_TEXTURE_2D ); - nontextured->disable( GL_BLEND ); - nontextured->disable( GL_ALPHA_TEST ); - nontextured->disable( GL_COLOR_MATERIAL ); - - nontextured->setMaterial ( GL_AMBIENT, - ambient[0], ambient[1], - ambient[2], ambient[3] ) ; - nontextured->setMaterial ( GL_DIFFUSE, - diffuse[0], diffuse[1], - diffuse[2], diffuse[3] ) ; - nontextured->setMaterial ( GL_SPECULAR, - specular[0], specular[1], - specular[2], specular[3] ) ; - nontextured->setMaterial ( GL_EMISSION, - emission[0], emission[1], - emission[2], emission[3] ) ; - nontextured->setShininess ( shininess ); - - state->setStep( 0, textured ); // textured - state->setStep( 1, nontextured ); // untextured - - // Choose the appropriate starting state. - if ( use_textures ) { - state->selectStep(0); - } else { - state->selectStep(1); - } } -// end of newmat.cxx +void +SGSetTextureFilter( int max) { + SGSceneFeatures::instance()->setTextureFilter( max); +} + +int +SGGetTextureFilter() { + return SGSceneFeatures::instance()->getTextureFilter(); +}