#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>
return _models.size();
}
-static void
-setAlphaClampToBranch( ssgBranch *b, float clamp )
-{
- int nb = b->getNumKids();
- for (int i = 0; i<nb; i++) {
- ssgEntity *e = b->getKid(i);
- if (e->isAKindOf(ssgTypeLeaf())) {
- ssgSimpleState*s = (ssgSimpleState*)((ssgLeaf*)e)->getState();
- s->enable( GL_ALPHA_TEST );
- s->setAlphaClamp( clamp );
- } else if (e->isAKindOf(ssgTypeBranch())) {
- setAlphaClampToBranch( (ssgBranch*)e, clamp );
- }
- }
-}
-
inline void
SGMatModel::load_models ( SGModelLib *modellib,
const string &fg_root,
// Load model only on demand
if (!_models_loaded) {
for (unsigned int i = 0; i < _paths.size(); i++) {
- ssgEntity *entity = modellib->load_model( fg_root, _paths[i],
+ 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->setRanges(ranges, 2);
- if (_heading_type == HEADING_BILLBOARD) {
+ // 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
- if ( entity->isAKindOf(ssgTypeBranch()) ) {
- ssgBranch *b = (ssgBranch *)entity;
- setAlphaClampToBranch( b, 0.01f );
- }
- ssgCutout * cutout = new ssgCutout(false);
- cutout->addKid(entity);
- lod->addKid(cutout);
- } else {
- lod->addKid(entity);
- }
- _models.push_back(lod);
+ 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 *modellib,
const string &fg_root,
double sim_time_sec )
{
load_models( modellib, fg_root, prop_root, sim_time_sec ); // comment this out if preloading models
- return _models[index];
+ return _models[index].get();
}
-ssgEntity *
+osg::Node*
SGMatModel::get_random_model( SGModelLib *modellib,
const string &fg_root,
SGPropertyNode *prop_root,
int index = int(sg_random() * nModels);
if (index >= nModels)
index = 0;
- return _models[index];
+ return _models[index].get();
}
double
}
+
+
// end of matmodel.cxx