Merge branch 'next' of gitorious.org:fg/flightgear into next
This commit is contained in:
commit
f2b354d9cb
10 changed files with 146 additions and 55 deletions
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue