// matmodel.cxx -- class to handle models tied to a material property
//
-// Written by Curtis Olson, started May 1998.
+// Written by David Megginson, started May 1998.
//
-// Copyright (C) 1998 - 2003 Curtis L. Olson - curt@flightgear.org
+// Copyright (C) 1998 - 2003 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
//
// 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$
#include <map>
SG_USING_STD(map);
-#include <simgear/compiler.h>
+#include <osg/AlphaFunc>
+#include <osg/Group>
+#include <osg/LOD>
+#include <osg/StateSet>
+#include <osg/Transform>
#ifdef SG_MATH_EXCEPTION_CLASH
# include <math.h>
SGMatModel::~SGMatModel ()
{
- for (unsigned int i = 0; i < _models.size(); i++) {
- if (_models[i] != 0) {
- _models[i]->deRef();
- _models[i] = 0;
- }
- }
}
int
-SGMatModel::get_model_count( SGModelLib *loader,
- const string &fg_root,
- SGPropertyNode *prop_root,
- double sim_time_sec )
+SGMatModel::get_model_count( SGModelLib *modellib,
+ const string &fg_root,
+ SGPropertyNode *prop_root,
+ double sim_time_sec )
{
- load_models( loader, fg_root, prop_root, sim_time_sec );
+ load_models( modellib, fg_root, prop_root, sim_time_sec );
return _models.size();
}
inline void
-SGMatModel::load_models ( SGModelLib *loader,
- const string &fg_root,
- SGPropertyNode *prop_root,
- double sim_time_sec )
+SGMatModel::load_models ( SGModelLib *modellib,
+ 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 );
+ osg::Node *entity = modellib->load_model( fg_root, _paths[i],
+ prop_root, sim_time_sec,
+ /*cache_object*/ true );
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);
+ // FIXME: this stuff can be handled
+ // in the XML wrapper as well (at least,
+ // the billboarding should be handled
+ // there).
+
+ // Create multiple LoD nodes so instead of all objects
+ // of the same type appearing at once, some appear further
+ // away.
+ //
+ // Very basic hardcoded distribution:
+ // 4 at normal range
+ // 2 at 1.5 times normal range
+ // 1 at 2 time normal range.
+ //
+ // We achieve this by creating the three different LoD
+ // nodes and adding them to the _models list multiple times.
+
+ osg::LOD * lod1 = new osg::LOD;
+ lod1->setName("Model LOD");
+ lod1->setRangeMode(osg::LOD::DISTANCE_FROM_EYE_POINT);
+ lod1->setRange(0, 0, _range_m);
+
+ osg::LOD * lod15 = new osg::LOD;
+ lod15->setName("Model LOD - 1.5");
+ lod15->setRangeMode(osg::LOD::DISTANCE_FROM_EYE_POINT);
+ lod15->setRange(0, 0, 1.5 * _range_m);
+
+ osg::LOD * lod2 = new osg::LOD;
+ lod2->setName("Model LOD - 2.0");
+ lod2->setRangeMode(osg::LOD::DISTANCE_FROM_EYE_POINT);
+ lod2->setRange(0, 0, 2.0 * _range_m);
+
+ if (_heading_type == HEADING_BILLBOARD) {
+ // if the model is a billboard, it is likely :
+ // 1. a branch with only leaves,
+ // 2. a tree or a non rectangular shape faked by transparency
+ // We add alpha clamp then
+ osg::StateSet* stateSet = entity->getOrCreateStateSet();
+ osg::AlphaFunc* alphaFunc =
+ new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0.01f);
+ stateSet->setAttributeAndModes(alphaFunc,
+ osg::StateAttribute::OVERRIDE);
+ stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
+
+ lod1->addChild(entity);
+ lod15->addChild(entity);
+ lod2->addChild(entity);
+ } else {
+ lod1->addChild(entity);
+ lod15->addChild(entity);
+ lod2->addChild(entity);
+ }
+
+ // Vary the distribution of LoDs by adding multiple times.
+ _models.push_back(lod1);
+ _models.push_back(lod1);
+ _models.push_back(lod1);
+ _models.push_back(lod1);
+
+ _models.push_back(lod15);
+ _models.push_back(lod15);
+
+ _models.push_back(lod2);
+
} else {
- SG_LOG(SG_INPUT, SG_ALERT, "Failed to load object " << _paths[i]);
+ SG_LOG(SG_INPUT, SG_ALERT, "Failed to load object " << _paths[i]);
}
}
}
_models_loaded = true;
}
-ssgEntity *
+osg::Node*
SGMatModel::get_model( int index,
- SGModelLib *loader,
- const string &fg_root,
- SGPropertyNode *prop_root,
- double sim_time_sec )
+ SGModelLib *modellib,
+ 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];
+ load_models( modellib, fg_root, prop_root, sim_time_sec ); // comment this out if preloading models
+ return _models[index].get();
}
-ssgEntity *
-SGMatModel::get_random_model( SGModelLib *loader,
- const string &fg_root,
- SGPropertyNode *prop_root,
- double sim_time_sec )
+osg::Node*
+SGMatModel::get_random_model( SGModelLib *modellib,
+ 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
+ load_models( modellib, 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];
+ return _models[index].get();
}
double
SGMatModelGroup::~SGMatModelGroup ()
{
- for (unsigned int i = 0; i < _objects.size(); i++) {
- delete _objects[i];
- _objects[i] = 0;
- }
}
double
}
+
+
// end of matmodel.cxx