1
0
Fork 0

Merge branch 'next' of gitorious.org:fg/flightgear into next

This commit is contained in:
Durk Talsma 2011-10-03 20:57:32 +02:00
commit f2b354d9cb
10 changed files with 146 additions and 55 deletions

View file

@ -179,6 +179,27 @@ void FGAIBase::update(double dt) {
ft_per_deg_lon = 365228.16 * cos(pos.getLatitudeRad());
}
/** update LOD properties of the model */
void FGAIBase::updateLOD()
{
double maxRangeDetail = fgGetDouble("/sim/rendering/static-lod/ai-detailed", 10000.0);
double maxRangeBare = fgGetDouble("/sim/rendering/static-lod/ai-bare", 20000.0);
if (_model.valid())
{
if( maxRangeDetail == 0.0 )
{
// disable LOD
_model->setRange(0, 0.0, FLT_MAX);
_model->setRange(1, FLT_MAX, FLT_MAX);
}
else
{
_model->setRange(0, 0.0, maxRangeDetail);
_model->setRange(1, maxRangeDetail,maxRangeBare);
}
}
}
void FGAIBase::Transform() {
if (!invisible) {
@ -226,23 +247,22 @@ bool FGAIBase::init(bool search_in_AI_path) {
_installed = true;
osg::Node * mdl = SGModelLib::loadPagedModel(f, props, new FGNasalModelData(props));
model = mdl;
double aiModelMaxRange = fgGetDouble("/sim/rendering/static-lod/ai", 0.0);
if( aiModelMaxRange > 0.0 ) {
osg::LOD * lod = new osg::LOD;
lod->setName("AI-model range animation node");
_model = new osg::LOD;
_model->setName("AI-model range animation node");
lod->addChild( mdl, 0, aiModelMaxRange );
lod->setCenterMode(osg::LOD::USE_BOUNDING_SPHERE_CENTER);
lod->setRangeMode(osg::LOD::DISTANCE_FROM_EYE_POINT);
model = lod;
}
_model->addChild( mdl, 0, FLT_MAX );
_model->setCenterMode(osg::LOD::USE_BOUNDING_SPHERE_CENTER);
_model->setRangeMode(osg::LOD::DISTANCE_FROM_EYE_POINT);
// We really need low-resolution versions of AI/MP aircraft.
// Or at least dummy "stubs" with some default silhouette.
// _model->addChild( SGModelLib::loadPagedModel(fgGetString("/sim/multiplay/default-model", default_model),
// props, new FGNasalModelData(props)), FLT_MAX, FLT_MAX);
updateLOD();
initModel(mdl);
if (model.valid() && _initialized == false) {
aip.init( model.get() );
if (_model.valid() && _initialized == false) {
aip.init( _model.get() );
aip.setVisible(true);
invisible = false;
globals->get_scenery()->get_scene_graph()->addChild(aip.getSceneGraph());
@ -260,7 +280,7 @@ bool FGAIBase::init(bool search_in_AI_path) {
void FGAIBase::initModel(osg::Node *node)
{
if (model.valid()) {
if (_model.valid()) {
if( _path != ""){
props->setStringValue("submodels/path", _path.c_str());
@ -523,7 +543,7 @@ SGVec3d FGAIBase::getCartPos() const {
bool FGAIBase::getGroundElevationM(const SGGeod& pos, double& elev,
const SGMaterial** material) const {
return globals->get_scenery()->get_elevation_m(pos, elev, material,
model.get());
_model.get());
}
double FGAIBase::_getCartPosX() const {

View file

@ -64,6 +64,7 @@ public:
virtual void unbind();
virtual void reinit() {}
void updateLOD();
void setManager(FGAIManager* mgr, SGPropertyNode* p);
void setPath( const char* model );
void setSMPath( const string& p );
@ -186,7 +187,6 @@ protected:
double ht_diff; // value used by radar display instrument
string model_path; //Path to the 3D model
osg::ref_ptr<osg::Node> model; //The 3D model object
SGModelPlacement aip;
bool delete_me;
@ -222,6 +222,7 @@ private:
int _refID;
object_type _otype;
bool _initialized;
osg::ref_ptr<osg::LOD> _model; //The 3D model LOD object
public:
object_type getType();

View file

@ -43,7 +43,12 @@
#include "AIGroundVehicle.hxx"
#include "AIEscort.hxx"
FGAIManager::FGAIManager() {
FGAIManager::FGAIManager() :
cb_ai_bare(SGPropertyChangeCallback<FGAIManager>(this,&FGAIManager::updateLOD,
fgGetNode("/sim/rendering/static-lod/ai-bare", true))),
cb_ai_detailed(SGPropertyChangeCallback<FGAIManager>(this,&FGAIManager::updateLOD,
fgGetNode("/sim/rendering/static-lod/ai-detailed", true)))
{
_dt = 0.0;
mNumAiModels = 0;
@ -181,6 +186,18 @@ FGAIManager::update(double dt) {
thermal_lift_node->setDoubleValue( strength ); // for thermals
}
/** update LOD settings of all AI/MP models */
void
FGAIManager::updateLOD(SGPropertyNode* node)
{
ai_list_iterator ai_list_itr = ai_list.begin();
while(ai_list_itr != ai_list.end())
{
(*ai_list_itr)->updateLOD();
++ai_list_itr;
}
}
void
FGAIManager::attach(FGAIBase *model)
{

View file

@ -27,6 +27,7 @@
#include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
#include <simgear/props/props_io.hxx>
#include <Main/fg_props.hxx>
@ -66,6 +67,7 @@ public:
void bind();
void unbind();
void update(double dt);
void updateLOD(SGPropertyNode* node);
void attach(FGAIBase *model);
void destroyObject( int ID );
@ -135,6 +137,8 @@ private:
double strength;
void processThermal( FGAIThermal* thermal );
SGPropertyChangeCallback<FGAIManager> cb_ai_bare;
SGPropertyChangeCallback<FGAIManager> cb_ai_detailed;
};
#endif // _FG_AIMANAGER_HXX

View file

@ -109,7 +109,7 @@ void FGATCManager::init() {
if (park_index < 0) {
SG_LOG( SG_GENERAL, SG_ALERT,
"Failed to find parking position " << parking <<
" at airport " << airport << "at " << SG_ORIGIN);
" at airport " << airport << " at " << SG_ORIGIN);
}
if (parking.empty() || (park_index < 0)) {
controller = apt->getDynamics()->getTowerController();

View file

@ -397,6 +397,7 @@ MapWidget::MapWidget(int x, int y, int maxX, int maxY) :
MapWidget::~MapWidget()
{
delete _magVar;
clearData();
}
void MapWidget::setProperty(SGPropertyNode_ptr prop)
@ -535,10 +536,14 @@ void MapWidget::draw(int dx, int dy)
{
_aircraft = SGGeod::fromDeg(fgGetDouble("/position/longitude-deg"),
fgGetDouble("/position/latitude-deg"));
_magneticHeadings = _root->getBoolValue("magnetic-headings");
if (_hasPanned)
{
bool mag = _root->getBoolValue("magnetic-headings");
if (mag != _magneticHeadings) {
clearData(); // flush cached data text, since it often includes heading
_magneticHeadings = mag;
}
if (_hasPanned) {
_root->setBoolValue("centre-on-aircraft", false);
_hasPanned = false;
}
@ -630,14 +635,9 @@ void MapWidget::paintRuler()
double dist, az, az2;
SGGeodesy::inverse(_aircraft, _clickGeod, az, az2, dist);
if (_magneticHeadings) {
az -= _magVar->get_magvar();
SG_NORMALIZE_RANGE(az, 0.0, 360.0);
}
char buffer[1024];
::snprintf(buffer, 1024, "%03d/%.1fnm",
SGMiscd::roundToInt(az), dist * SG_METER_TO_NM);
displayHeading(az), dist * SG_METER_TO_NM);
MapData* d = getOrCreateDataForKey((void*) RULER_LEGEND_KEY);
d->setLabel(buffer);
@ -1243,13 +1243,13 @@ void MapWidget::drawRunway(FGRunway* rwy)
setAnchorForKey(rwy, (p1 + p2) * 0.5);
return;
}
char buffer[1024];
::snprintf(buffer, 1024, "%s/%s\n%3.0f/%3.0f\n%.0f'",
::snprintf(buffer, 1024, "%s/%s\n%03d/%03d\n%.0f'",
rwy->ident().c_str(),
rwy->reciprocalRunway()->ident().c_str(),
rwy->headingDeg(),
rwy->reciprocalRunway()->headingDeg(),
displayHeading(rwy->headingDeg()),
displayHeading(rwy->reciprocalRunway()->headingDeg()),
rwy->lengthFt());
MapData* d = createDataForKey(rwy);
@ -1311,8 +1311,10 @@ void MapWidget::drawILS(bool tuned, FGRunway* rwy)
}
char buffer[1024];
::snprintf(buffer, 1024, "%s\n%s\n%3.2fMHz",
loc->name().c_str(), loc->ident().c_str(),loc->get_freq()/100.0);
::snprintf(buffer, 1024, "%s\n%s\n%03d - %3.2fMHz",
loc->ident().c_str(), loc->name().c_str(),
displayHeading(radial),
loc->get_freq()/100.0);
MapData* d = createDataForKey(loc);
d->setPriority(40);
@ -1680,3 +1682,23 @@ MapData* MapWidget::createDataForKey(void* key)
d->resetAge();
return d;
}
void MapWidget::clearData()
{
KeyDataMap::iterator it = _mapData.begin();
for (; it != _mapData.end(); ++it) {
delete it->second;
}
_mapData.clear();
}
int MapWidget::displayHeading(double h) const
{
if (_magneticHeadings) {
h -= _magVar->get_magvar() * SG_RADIANS_TO_DEGREES;
}
SG_NORMALIZE_RANGE(h, 0.0, 360.0);
return SGMiscd::roundToInt(h);
}

View file

@ -73,11 +73,14 @@ private:
MapData* getOrCreateDataForKey(void* key);
MapData* createDataForKey(void* key);
void setAnchorForKey(void* key, const SGVec2d& anchor);
void clearData();
SGVec2d project(const SGGeod& geod) const;
SGGeod unproject(const SGVec2d& p) const;
double currentScale() const;
int displayHeading(double trueHeading) const;
void circleAt(const SGVec2d& center, int nSides, double r);
void circleAtAlt(const SGVec2d& center, int nSides, double r, double r2);
void drawLine(const SGVec2d& p1, const SGVec2d& p2);

View file

@ -124,6 +124,7 @@ ADF::update (double delta_time_sec)
if (_electrical_node->getDoubleValue() < 8.0
|| !_serviceable_node->getBoolValue()
|| !_power_btn_node->getBoolValue() ) {
_in_range_node->setBoolValue(false);
_ident_node->setStringValue("");
return;
}
@ -131,6 +132,7 @@ ADF::update (double delta_time_sec)
string mode = _mode_node->getStringValue();
if (mode == "ant" || mode == "test") set_bearing(delta_time_sec, 90);
if (mode != "bfo" && mode != "adf") {
_in_range_node->setBoolValue(false);
_ident_node->setStringValue("");
return;
}
@ -155,6 +157,7 @@ ADF::update (double delta_time_sec)
search(frequency_khz, longitude_rad, latitude_rad, altitude_m);
if (!_transmitter_valid) {
_in_range_node->setBoolValue(false);
_ident_node->setStringValue("");
return;
}

View file

@ -638,7 +638,8 @@ FGMultiplayMgr::SendMyPosition(const FGExternalMotionData& motionInfo)
strncpy(PosMsg->Model, fgGetString("/sim/model/path"), MAX_MODEL_NAME_LEN);
PosMsg->Model[MAX_MODEL_NAME_LEN - 1] = '\0';
if (fgGetBool("/sim/freeze/replay-state", true))
if (fgGetBool("/sim/freeze/replay-state", true)&&
fgGetBool("/sim/multiplay/freeze-on-replay",true))
{
// do not send position updates during replay
for (unsigned i = 0 ; i < 3; ++i)

View file

@ -323,6 +323,34 @@ private:
ObjectClassConfigList _objectClassConfigList;
};
class PropertyReferenceSet : public SGReferenced {
public:
void insert(const std::string& relativePath, const SGSharedPtr<sg::HLAPropertyDataElement>& dataElement)
{
if (_rootNode.valid())
dataElement->setPropertyNode(_rootNode->getNode(relativePath, true));
_pathDataElementPairList.push_back(PathDataElementPair(relativePath, dataElement));
}
void setRootNode(SGPropertyNode* rootNode)
{
_rootNode = rootNode;
for (PathDataElementPairList::iterator i = _pathDataElementPairList.begin();
i != _pathDataElementPairList.end(); ++i) {
i->second->setPropertyNode(_rootNode->getNode(i->first, true));
}
}
SGPropertyNode* getRootNode()
{ return _rootNode.get(); }
private:
SGSharedPtr<SGPropertyNode> _rootNode;
typedef std::pair<std::string, SGSharedPtr<sg::HLAPropertyDataElement> > PathDataElementPair;
typedef std::list<PathDataElementPair> PathDataElementPairList;
PathDataElementPairList _pathDataElementPairList;
};
class AbstractSimTime : public SGReferenced {
public:
virtual ~AbstractSimTime() {}
@ -533,7 +561,7 @@ private:
// Factory class that is used to create an apternative data element for the multiplayer property attribute
class MPPropertyVariantDataElementFactory : public sg::HLAVariantArrayDataElement::AlternativeDataElementFactory {
public:
MPPropertyVariantDataElementFactory(sg::HLAPropertyReferenceSet* propertyReferenceSet) :
MPPropertyVariantDataElementFactory(PropertyReferenceSet* propertyReferenceSet) :
_propertyReferenceSet(propertyReferenceSet)
{ }
@ -551,19 +579,19 @@ public:
// The relative property path should be in the semantics field name
std::string relativePath = dataType->getAlternativeSemantics(index);
sg::HLAPropertyReference* propertyReference = new sg::HLAPropertyReference(relativePath);
_propertyReferenceSet->insert(propertyReference);
return new sg::HLAPropertyDataElement(alternativeDataType, propertyReference);
sg::HLAPropertyDataElement* dataElement = new sg::HLAPropertyDataElement(alternativeDataType, (SGPropertyNode*)0);
_propertyReferenceSet->insert(relativePath, dataElement);
return dataElement;
}
private:
SGSharedPtr<sg::HLAPropertyReferenceSet> _propertyReferenceSet;
SGSharedPtr<PropertyReferenceSet> _propertyReferenceSet;
};
class MPAttributeCallback : public sg::HLAObjectInstance::AttributeCallback {
public:
MPAttributeCallback() :
_propertyReferenceSet(new sg::HLAPropertyReferenceSet),
_propertyReferenceSet(new PropertyReferenceSet),
_mpProperties(new sg::HLAVariantArrayDataElement)
{
_mpProperties->setAlternativeDataElementFactory(new MPPropertyVariantDataElementFactory(_propertyReferenceSet.get()));
@ -595,7 +623,7 @@ public:
sg::HLAVariantArrayDataElement* getMPProperties() const
{ return _mpProperties.get(); }
SGSharedPtr<sg::HLAPropertyReferenceSet> _propertyReferenceSet;
SGSharedPtr<PropertyReferenceSet> _propertyReferenceSet;
protected:
SGSharedPtr<sg::HLAAbstractLocation> _location;
@ -792,7 +820,7 @@ private:
objectInstance.setAttributes(attributePathElementMap);
}
void attachPropertyDataElements(sg::HLAPropertyReferenceSet& propertyReferenceSet,
void attachPropertyDataElements(PropertyReferenceSet& propertyReferenceSet,
sg::HLAAttributePathElementMap& attributePathElementMap,
const AttributePathPropertyMap& attributePathPropertyMap)
{
@ -800,10 +828,9 @@ private:
i != attributePathPropertyMap.end(); ++i) {
for (PathPropertyMap::const_iterator j = i->second.begin();
j != i->second.end(); ++j) {
SGSharedPtr<sg::HLAPropertyReference> propertyReference;
propertyReference = new sg::HLAPropertyReference(j->second);
propertyReferenceSet.insert(propertyReference);
attributePathElementMap[i->first][j->first] = new sg::HLAPropertyDataElement(propertyReference);
sg::HLAPropertyDataElement* dataElement = new sg::HLAPropertyDataElement;
propertyReferenceSet.insert(j->second, dataElement);
attributePathElementMap[i->first][j->first] = dataElement;
}
}
}
@ -1240,14 +1267,7 @@ FGHLA::process()
// Then get news from others and process possible update requests
if (get_direction() & (SG_IO_IN|SG_IO_OUT)) {
// I hoped that the tick call itself would do that job with the timestamps, but this way it works
SGTimeStamp timestamp = SGTimeStamp::now();
timestamp += SGTimeStamp::fromSec(0.01);
do {
if (!_hlaFederate->tick(0.0, 0.0))
break;
} while (SGTimeStamp::now() <= timestamp);
_hlaFederate->processMessages();
}
return true;