configure.ac simgear/environment/visual_enviro.cxx simgear/ephemeris/ephemeris.cxx simgear/ephemeris/ephemeris.hxx simgear/ephemeris/stardata.cxx simgear/ephemeris/stardata.hxx simgear/math/SGMatrix.hxx simgear/math/SGQuat.hxx simgear/math/SGVec3.hxx simgear/math/SGVec4.hxx simgear/scene/Makefile.am simgear/scene/material/mat.cxx simgear/scene/material/mat.hxx simgear/scene/material/matlib.cxx simgear/scene/material/matlib.hxx simgear/scene/material/matmodel.cxx simgear/scene/material/matmodel.hxx simgear/scene/model/Makefile.am simgear/scene/model/animation.cxx simgear/scene/model/animation.hxx simgear/scene/model/custtrans.hxx simgear/scene/model/model.cxx simgear/scene/model/model.hxx simgear/scene/model/modellib.cxx simgear/scene/model/modellib.hxx simgear/scene/model/personality.cxx simgear/scene/model/personality.hxx simgear/scene/model/placement.cxx simgear/scene/model/placement.hxx simgear/scene/model/placementtrans.cxx simgear/scene/model/placementtrans.hxx simgear/scene/model/shadanim.cxx simgear/scene/model/shadowvolume.hxx simgear/scene/sky/cloud.cxx simgear/scene/sky/cloud.hxx simgear/scene/sky/cloudfield.cxx simgear/scene/sky/dome.cxx simgear/scene/sky/dome.hxx simgear/scene/sky/moon.cxx simgear/scene/sky/moon.hxx simgear/scene/sky/newcloud.cxx simgear/scene/sky/oursun.cxx simgear/scene/sky/oursun.hxx simgear/scene/sky/sky.cxx simgear/scene/sky/sky.hxx simgear/scene/sky/sphere.cxx simgear/scene/sky/sphere.hxx simgear/scene/sky/stars.cxx simgear/scene/sky/stars.hxx simgear/scene/tgdb/apt_signs.cxx simgear/scene/tgdb/apt_signs.hxx simgear/scene/tgdb/leaf.cxx simgear/scene/tgdb/leaf.hxx simgear/scene/tgdb/obj.cxx simgear/scene/tgdb/obj.hxx simgear/scene/tgdb/pt_lights.cxx simgear/scene/tgdb/pt_lights.hxx simgear/scene/tgdb/userdata.cxx simgear/scene/tgdb/userdata.hxx simgear/scene/tgdb/vasi.hxx simgear/screen/jpgfactory.cxx simgear/screen/tr.cxx simgear/structure/Makefile.am simgear/threads/SGThread.hxx Added Files: simgear/scene/util/Makefile.am simgear/scene/util/SGDebugDrawCallback.hxx simgear/scene/util/SGNodeMasks.hxx simgear/scene/util/SGStateAttributeVisitor.hxx simgear/scene/util/SGTextureStateAttributeVisitor.hxx simgear/scene/util/SGUpdateVisitor.hxx Removed Files: simgear/screen/ssgEntityArray.cxx simgear/screen/ssgEntityArray.hxx simgear/structure/ssgSharedPtr.hxx Big BLOB on the way to OSG.
259 lines
7.5 KiB
C++
259 lines
7.5 KiB
C++
// matmodel.cxx -- class to handle models tied to a material property
|
|
//
|
|
// Written by David Megginson, started May 1998.
|
|
//
|
|
// 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
|
|
// published by the Free Software Foundation; either version 2 of the
|
|
// License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful, but
|
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
// General Public License for more details.
|
|
//
|
|
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
//
|
|
// $Id$
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <simgear_config.h>
|
|
#endif
|
|
|
|
#include <simgear/compiler.h>
|
|
|
|
#include <map>
|
|
SG_USING_STD(map);
|
|
|
|
#include <osg/AlphaFunc>
|
|
#include <osg/Group>
|
|
#include <osg/LOD>
|
|
#include <osg/StateSet>
|
|
#include <osg/Transform>
|
|
|
|
#ifdef SG_MATH_EXCEPTION_CLASH
|
|
# include <math.h>
|
|
#endif
|
|
|
|
#include <simgear/debug/logstream.hxx>
|
|
#include <simgear/math/sg_random.h>
|
|
#include <simgear/misc/sg_path.hxx>
|
|
#include <simgear/misc/sgstream.hxx>
|
|
#include <simgear/scene/model/modellib.hxx>
|
|
|
|
#include "matmodel.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 SGMatModel.
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
SGMatModel::SGMatModel (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 <SGPropertyNode_ptr> 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();
|
|
}
|
|
|
|
SGMatModel::~SGMatModel ()
|
|
{
|
|
}
|
|
|
|
int
|
|
SGMatModel::get_model_count( SGModelLib *modellib,
|
|
const string &fg_root,
|
|
SGPropertyNode *prop_root,
|
|
double sim_time_sec )
|
|
{
|
|
load_models( modellib, fg_root, prop_root, sim_time_sec );
|
|
return _models.size();
|
|
}
|
|
|
|
inline void
|
|
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++) {
|
|
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).
|
|
osg::LOD * lod = new osg::LOD;
|
|
lod->setName("Model LOD");
|
|
lod->setRangeMode(osg::LOD::DISTANCE_FROM_EYE_POINT);
|
|
lod->setRange(0, 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);
|
|
|
|
osg::Transform* transform = new osg::Transform;
|
|
transform->setName("Model Billboard Transform");
|
|
transform->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
|
|
transform->addChild(entity);
|
|
lod->addChild(transform);
|
|
} else {
|
|
lod->addChild(entity);
|
|
}
|
|
_models.push_back(lod);
|
|
} else {
|
|
SG_LOG(SG_INPUT, SG_ALERT, "Failed to load object " << _paths[i]);
|
|
}
|
|
}
|
|
}
|
|
_models_loaded = true;
|
|
}
|
|
|
|
osg::Node*
|
|
SGMatModel::get_model( int index,
|
|
SGModelLib *modellib,
|
|
const string &fg_root,
|
|
SGPropertyNode *prop_root,
|
|
double sim_time_sec )
|
|
{
|
|
load_models( modellib, fg_root, prop_root, sim_time_sec ); // comment this out if preloading models
|
|
return _models[index].get();
|
|
}
|
|
|
|
osg::Node*
|
|
SGMatModel::get_random_model( SGModelLib *modellib,
|
|
const string &fg_root,
|
|
SGPropertyNode *prop_root,
|
|
double sim_time_sec )
|
|
{
|
|
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].get();
|
|
}
|
|
|
|
double
|
|
SGMatModel::get_coverage_m2 () const
|
|
{
|
|
return _coverage_m2;
|
|
}
|
|
|
|
SGMatModel::HeadingType
|
|
SGMatModel::get_heading_type () const
|
|
{
|
|
return _heading_type;
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// Implementation of SGMatModelGroup.
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
SGMatModelGroup::SGMatModelGroup (SGPropertyNode * node)
|
|
: _range_m(node->getDoubleValue("range-m", 2000))
|
|
{
|
|
// Load the object subnodes
|
|
vector<SGPropertyNode_ptr> 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 SGMatModel(object_node, _range_m));
|
|
else
|
|
SG_LOG(SG_INPUT, SG_ALERT, "No path supplied for object");
|
|
}
|
|
}
|
|
|
|
SGMatModelGroup::~SGMatModelGroup ()
|
|
{
|
|
}
|
|
|
|
double
|
|
SGMatModelGroup::get_range_m () const
|
|
{
|
|
return _range_m;
|
|
}
|
|
|
|
int
|
|
SGMatModelGroup::get_object_count () const
|
|
{
|
|
return _objects.size();
|
|
}
|
|
|
|
SGMatModel *
|
|
SGMatModelGroup::get_object (int index) const
|
|
{
|
|
return _objects[index];
|
|
}
|
|
|
|
|
|
// end of matmodel.cxx
|