1
0
Fork 0

Merge branch 'next' into durk-atc

This commit is contained in:
Durk Talsma 2011-05-31 20:38:42 +02:00
commit de1564d83e
80 changed files with 2854 additions and 1040 deletions

View file

@ -583,7 +583,7 @@ if test "x$ac_cv_header_simgear_version_h" != "xyes"; then
exit
fi
AC_MSG_CHECKING([for SimGear 2.2.0 or newer])
AC_MSG_CHECKING([for SimGear 2.3.0 or newer])
AC_TRY_RUN([
#include <stdio.h>
@ -593,7 +593,7 @@ AC_TRY_RUN([
#define XSTRINGIFY(X) #X
#define MIN_MAJOR 2
#define MIN_MINOR 2
#define MIN_MINOR 3
#define MIN_MICRO 0
int main() {

View file

@ -1,7 +1,7 @@
#!/bin/sh
SDK_PATH="/Developer/SDKs/MacOSX10.5.sdk"
OSX_TARGET="10.5"
SDK_PATH="/Developer/SDKs/MacOSX10.6.sdk"
OSX_TARGET="10.6"
svn co https://macflightgear.svn.sourceforge.net/svnroot/macflightgear/trunk/FlightGearOSX macflightgear

View file

@ -54,6 +54,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "yasim", "yasim\yasim.vcproj
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimGear", "..\..\..\Simgear\projects\VC90\SimGear.vcproj", "{22540CD3-D3CA-4C86-A773-80AEEE3ACDED}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fgpanel", "fgpanel\fgpanel.vcproj", "{FA27B353-179C-4DE8-B3AC-E260F8F790DD}"
ProjectSection(ProjectDependencies) = postProject
{22540CD3-D3CA-4C86-A773-80AEEE3ACDED} = {22540CD3-D3CA-4C86-A773-80AEEE3ACDED}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@ -156,6 +161,12 @@ Global
{22540CD3-D3CA-4C86-A773-80AEEE3ACDED}.Release|Win32.Build.0 = Release|Win32
{22540CD3-D3CA-4C86-A773-80AEEE3ACDED}.Release|x64.ActiveCfg = Release|x64
{22540CD3-D3CA-4C86-A773-80AEEE3ACDED}.Release|x64.Build.0 = Release|x64
{FA27B353-179C-4DE8-B3AC-E260F8F790DD}.Debug|Win32.ActiveCfg = Debug|Win32
{FA27B353-179C-4DE8-B3AC-E260F8F790DD}.Debug|Win32.Build.0 = Debug|Win32
{FA27B353-179C-4DE8-B3AC-E260F8F790DD}.Debug|x64.ActiveCfg = Debug|Win32
{FA27B353-179C-4DE8-B3AC-E260F8F790DD}.Release|Win32.ActiveCfg = Release|Win32
{FA27B353-179C-4DE8-B3AC-E260F8F790DD}.Release|Win32.Build.0 = Release|Win32
{FA27B353-179C-4DE8-B3AC-E260F8F790DD}.Release|x64.ActiveCfg = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View file

@ -2977,6 +2977,14 @@
RelativePath="..\..\..\src\Network\AV400Sim.hxx"
>
</File>
<File
RelativePath="..\..\..\src\Network\AV400WSim.cxx"
>
</File>
<File
RelativePath="..\..\..\src\Network\AV400WSim.hxx"
>
</File>
<File
RelativePath="..\..\..\src\Network\garmin.cxx"
>
@ -3025,14 +3033,6 @@
RelativePath="..\..\..\src\Network\jsclient.hxx"
>
</File>
<File
RelativePath="..\..\..\src\Network\multiplay.cxx"
>
</File>
<File
RelativePath="..\..\..\src\Network\multiplay.hxx"
>
</File>
<File
RelativePath="..\..\..\src\Network\native.cxx"
>
@ -3437,6 +3437,14 @@
RelativePath="..\..\..\src\Environment\presets.hxx"
>
</File>
<File
RelativePath="..\..\..\src\Environment\gravity.cxx"
>
</File>
<File
RelativePath="..\..\..\src\Environment\gravity.hxx"
>
</File>
</Filter>
<Filter
Name="Lib_Model"

1
projects/VC90/fgpanel/.gitignore vendored Executable file
View file

@ -0,0 +1 @@
*.user

View file

@ -0,0 +1,262 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
Name="fgpanel"
ProjectGUID="{FA27B353-179C-4DE8-B3AC-E260F8F790DD}"
RootNamespace="fgpanel"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\..\SimGear;..\..\..\..\boost_1_44_0;..\..\..\..\install\msvc90\OpenSceneGraph\include;..\..\..\..\3rdParty\include;..\..\..\src\include"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;HAVE_CONFIG_H"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="wsock32.lib zlibd.lib libpngd.lib fnt_d.lib ul_d.lib sg_d.lib pui_d.lib"
LinkIncremental="2"
AdditionalLibraryDirectories="..\..\..\..\install\msvc90\OpenSceneGraph\lib;..\..\..\..\3rdParty\lib"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\..\..\src;..\..\..\src\include;..\..\..\src\FDM\JSBSim;..\..\..\..\SimGear;..\..\..\..\install\msvc90\OpenSceneGraph\include;..\..\..\..\3rdParty\include;..\..\..\..\boost_1_44_0"
PreprocessorDefinitions="NDEBUG;WIN32;_CONSOLE;HAVE_CONFIG_H;FGFS;ENABLE_AUDIO_SUPPORT;_FG_NDEBUG;ENABLE_THREADS=1;FG_ENABLE_MULTIPASS_CLOUDS;ENABLE_SP_FMDS;_USE_MATH_DEFINES;FG_JPEG_SERVER;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;HAVE_VERSION_H=$(HAVE_VERSION_H)0"
StringPooling="true"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="wsock32.lib net.lib sg.lib pui.lib fnt.lib ul.lib libpng.lib zlib.lib "
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\..\..\install\msvc90\OpenSceneGraph\lib;..\..\..\..\3rdParty\lib"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="0"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\..\..\utils\fgpanel\ApplicationProperties.hxx"
>
</File>
<File
RelativePath="..\..\..\utils\fgpanel\FGFontCache.cxx"
>
</File>
<File
RelativePath="..\..\..\utils\fgpanel\FGFontCache.hxx"
>
</File>
<File
RelativePath="..\..\..\utils\fgpanel\FGGLApplication.cxx"
>
</File>
<File
RelativePath="..\..\..\utils\fgpanel\FGGLApplication.hxx"
>
</File>
<File
RelativePath="..\..\..\utils\fgpanel\FGPanelApplication.cxx"
>
</File>
<File
RelativePath="..\..\..\utils\fgpanel\FGPanelApplication.hxx"
>
</File>
<File
RelativePath="..\..\..\utils\fgpanel\FGPanelProtocol.cxx"
>
</File>
<File
RelativePath="..\..\..\utils\fgpanel\FGPanelProtocol.hxx"
>
</File>
<File
RelativePath="..\..\..\utils\fgpanel\FGPNGTextureLoader.cxx"
>
</File>
<File
RelativePath="..\..\..\utils\fgpanel\FGPNGTextureLoader.hxx"
>
</File>
<File
RelativePath="..\..\..\utils\fgpanel\FGRGBTextureLoader.cxx"
>
</File>
<File
RelativePath="..\..\..\utils\fgpanel\FGRGBTextureLoader.hxx"
>
</File>
<File
RelativePath="..\..\..\utils\fgpanel\FGTextureLoaderInterface.hxx"
>
</File>
<File
RelativePath="..\..\..\utils\fgpanel\main.cxx"
>
</File>
<File
RelativePath="..\..\..\utils\fgpanel\panel.cxx"
>
</File>
<File
RelativePath="..\..\..\utils\fgpanel\panel.hxx"
>
</File>
<File
RelativePath="..\..\..\utils\fgpanel\panel_io.cxx"
>
</File>
<File
RelativePath="..\..\..\utils\fgpanel\panel_io.hxx"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View file

@ -182,7 +182,7 @@ void FGAIBallistic::bind() {
props->tie("sim/time/elapsed-sec",
SGRawValueMethods<FGAIBallistic,double>(*this,
&FGAIBallistic::_getTime));
&FGAIBallistic::_getTime, &FGAIBallistic::setTime));
//props->tie("mass-slug",
// SGRawValueMethods<FGAIBallistic,double>(*this,
// &FGAIBallistic::getMass));
@ -586,6 +586,7 @@ void FGAIBallistic::setHt(double h, double dt, double coeff){
int FGAIBallistic::setHdg(double tgt_hdg, double dt, double coeff){
double recip = getRecip(hdg);
double c = dt / (coeff + dt);
//cout << "set heading " << tgt_hdg << endl;
//we need to ensure that we turn the short way to the new hdg
if (tgt_hdg < recip && tgt_hdg < hdg && hdg > 180) {
hdg = ((tgt_hdg + 360) * c) + (hdg * (1 - c));
@ -626,6 +627,9 @@ void FGAIBallistic::setTgtZOffset(double z){
void FGAIBallistic::slaveToAC(double dt){
if (invisible)
return;
double hdg, pch, rll, agl = 0;
if (_pnode != 0) {
@ -652,6 +656,7 @@ void FGAIBallistic::slaveToAC(double dt){
setPitch(pch + _pitch_offset);
setBank(rll + _roll_offset);
setOffsetVelocity(dt, pos);
setTime(0);
//update the mass (slugs)
_mass = (_weight_lb + getContents()) / slugs_to_lbs;
@ -710,23 +715,13 @@ void FGAIBallistic::Run(double dt) {
speed = 0.0;
double speed_fps = speed * SG_KT_TO_FPS;
//double hs;
// calculate vertical and horizontal speed components
if (speed == 0.0) {
hs = vs = 0.0;
} else {
vs = sin( _elevation * SG_DEGREES_TO_RADIANS ) * speed_fps;
hs = cos( _elevation * SG_DEGREES_TO_RADIANS ) * speed_fps;
}
calcVSHS();
//resolve horizontal speed into north and east components:
double speed_north_fps = cos(_azimuth / SG_RADIANS_TO_DEGREES) * hs;
double speed_east_fps = sin(_azimuth / SG_RADIANS_TO_DEGREES) * hs;
// convert horizontal speed (fps) to degrees per second
double speed_north_deg_sec = speed_north_fps / ft_per_deg_lat;
double speed_east_deg_sec = speed_east_fps / ft_per_deg_lon;
//and convert horizontal speed (fps) to degrees per second
calcNE();
// if wind not required, set to zero
if (!_wind) {
@ -755,55 +750,61 @@ void FGAIBallistic::Run(double dt) {
double friction_force_speed_north_deg_sec = 0;
double friction_force_speed_east_deg_sec = 0;
double force_elevation_deg = 0;
double force_azimuth_deg = 0;
double force_lbs = 0;
if (_external_force) {
//cout << _name << " external force" << endl;
//cout << _name << " external force " << hdg << " az " << _azimuth << endl;
SGPropertyNode *n = fgGetNode(_force_path.c_str(), true);
double force_lbs = n->getChild("force-lb", 0, true)->getDoubleValue();
force_elevation_deg = n->getChild("force-elevation-deg", 0, true)->getDoubleValue();
double force_azimuth_deg = n->getChild("force-azimuth-deg", 0, true)->getDoubleValue();
force_lbs = n->getChild("force-lb", 0, true)->getDoubleValue();
force_elevation_deg = n->getChild("force-elevation-deg", 0, true)->getDoubleValue();
force_azimuth_deg = n->getChild("force-azimuth-deg", 0, true)->getDoubleValue();
//resolve force into vertical and horizontal components:
double v_force_lbs = force_lbs * sin( force_elevation_deg * SG_DEGREES_TO_RADIANS );
h_force_lbs = force_lbs * cos( force_elevation_deg * SG_DEGREES_TO_RADIANS );
//ground interaction
//we don't do this if impacts are calculated
if(!_report_impact){
if (getHtAGL(10000)){
double deadzone = 0.1;
if (getHtAGL(10000)){
double deadzone = 0.1;
if (_ht_agl_ft <= (0 + _ground_offset + deadzone) && _solid){
normal_force_lbs = (_mass * slugs_to_lbs) - v_force_lbs;
if (_ht_agl_ft <= (0 + _ground_offset + deadzone) && _solid){
normal_force_lbs = (_mass * slugs_to_lbs) - v_force_lbs;
if ( normal_force_lbs < 0 )
normal_force_lbs = 0;
if ( normal_force_lbs < 0 )
normal_force_lbs = 0;
pos.setElevationFt(0 + _ground_offset);
if (vs < 0)
vs = -vs * 0.5;
pos.setElevationFt(0 + _ground_offset);
if (vs < 0)
vs = -vs * 0.5;
// calculate friction
// we assume a static Coefficient of Friction (mu) of 0.62 (wood on concrete)
double mu = 0.62;
// calculate friction
// we assume a static Coefficient of Friction (mu) of 0.62 (wood on concrete)
double mu = 0.62;
static_friction_force_lbs = mu * normal_force_lbs * _frictionFactor;
static_friction_force_lbs = mu * normal_force_lbs * _frictionFactor;
//adjust horizontal force. We assume that a speed of <= 5 fps is static
if (h_force_lbs <= static_friction_force_lbs && hs <= 5){
h_force_lbs = hs = 0;
speed_north_fps = speed_east_fps = 0;
} else
dynamic_friction_force_lbs = (static_friction_force_lbs * 0.95);
//adjust horizontal force. We assume that a speed of <= 5 fps is static
if (h_force_lbs <= static_friction_force_lbs && hs <= 5){
h_force_lbs = hs = 0;
_speed_north_fps = _speed_east_fps = 0;
} else
dynamic_friction_force_lbs = (static_friction_force_lbs * 0.95);
//ignore wind when on the ground for now
//TODO fix this
_wind_from_north = 0;
_wind_from_east = 0;
//ignore wind when on the ground for now
//TODO fix this
_wind_from_north = 0;
_wind_from_east = 0;
}
}
}
} //endif
//acceleration = (force(lbsf)/mass(slugs))
v_force_acc_fpss = v_force_lbs/_mass;
@ -835,10 +836,10 @@ void FGAIBallistic::Run(double dt) {
double wind_speed_from_east_deg_sec = _wind_from_east / ft_per_deg_lon;
//recombine the horizontal velocity components
hs = sqrt(((speed_north_fps + force_speed_north_fps + friction_force_speed_north_fps)
* (speed_north_fps + force_speed_north_fps + friction_force_speed_north_fps))
+ ((speed_east_fps + force_speed_east_fps + friction_force_speed_east_fps)
* (speed_east_fps + force_speed_east_fps + friction_force_speed_east_fps)));
hs = sqrt(((_speed_north_fps + force_speed_north_fps + friction_force_speed_north_fps)
* (_speed_north_fps + force_speed_north_fps + friction_force_speed_north_fps))
+ ((_speed_east_fps + force_speed_east_fps + friction_force_speed_east_fps)
* (_speed_east_fps + force_speed_east_fps + friction_force_speed_east_fps)));
if (hs <= 0.00001)
hs = 0;
@ -890,8 +891,8 @@ void FGAIBallistic::Run(double dt) {
// recalculate elevation and azimuth (velocity vectors)
_elevation = atan2( vs, hs ) * SG_RADIANS_TO_DEGREES;
_azimuth = atan2((speed_east_fps + force_speed_east_fps + friction_force_speed_east_fps),
(speed_north_fps + force_speed_north_fps + friction_force_speed_north_fps))
_azimuth = atan2((_speed_east_fps + force_speed_east_fps + friction_force_speed_east_fps),
(_speed_north_fps + force_speed_north_fps + friction_force_speed_north_fps))
* SG_RADIANS_TO_DEGREES;
// rationalise azimuth
@ -899,7 +900,7 @@ void FGAIBallistic::Run(double dt) {
_azimuth += 360;
if (_aero_stabilised) { // we simulate rotational moment of inertia by using a filter
//cout<< "_aero_stabilised "<< endl;
//cout<< "_aero_stabilised " << hdg << " az " << _azimuth << endl;
const double coeff = 0.9;
// we assume a symetrical MI about the pitch and yaw axis
@ -941,16 +942,20 @@ double FGAIBallistic::_getTime() const {
return _life_timer;
}
void FGAIBallistic::setTime(double s){
_life_timer = s;
}
void FGAIBallistic::handle_impact() {
// try terrain intersection
double start = pos.getElevationM() + 10;
double start = pos.getElevationM() + 100;
if(!getHtAGL(start))
return;
if (_ht_agl_ft <= 0) {
SG_LOG(SG_GENERAL, SG_DEBUG, "AIBallistic: terrain impact");
SG_LOG(SG_GENERAL, SG_DEBUG, "AIBallistic: terrain impact material" << _mat_name);
report_impact(_elevation_m);
_impact_reported = true;
@ -1004,7 +1009,8 @@ void FGAIBallistic::report_impact(double elevation, const FGAIBase *object)
else
n->setStringValue("type", "terrain");
SG_LOG(SG_GENERAL, SG_DEBUG, "AIBallistic: object impact" << _name << " lon " <<_impact_lon);
SG_LOG(SG_GENERAL, SG_DEBUG, "AIBallistic: object impact " << _name
<< " lon " <<_impact_lon << " lat " <<_impact_lat);
n->setDoubleValue("longitude-deg", _impact_lon);
n->setDoubleValue("latitude-deg", _impact_lat);
@ -1239,9 +1245,17 @@ void FGAIBallistic::setOffsetVelocity(double dt, SGGeod offsetpos) {
calcVSHS();
//calculate the bearing of the new offset position from the old
double az1, az2, dist;
geo_inverse_wgs_84(_oldoffsetpos, offsetpos, &az1, &az2, &dist);
_azimuth = az1;
//don't do this if speed is low
//cout << "speed " << speed << endl;
if (speed > 0.1){
double az1, az2, dist;
geo_inverse_wgs_84(_oldoffsetpos, offsetpos, &az1, &az2, &dist);
_azimuth = az1;
//cout << "offset az " << _azimuth << endl;
} else {
_azimuth = hdg;
//cout << " slow offset az " << _azimuth << endl;
}
//resolve horizontal speed into north and east components:
calcNE();

View file

@ -96,9 +96,9 @@ public:
void setParentPos();
void setOffsetPos(SGGeod pos, double heading, double pitch, double roll);
void setOffsetVelocity(double dt, SGGeod pos);
void setTime(double sec);
double _getTime() const;
double _getTime()const;
double getRelBrgHitchToUser() const;
double getElevHitchToUser() const;
double getLoadOffset() const;

View file

@ -100,6 +100,7 @@ void FGReplay::init()
disable_replay = fgGetNode( "/sim/replay/disable", true );
replay_master = fgGetNode( "/sim/freeze/replay-state", true );
replay_time = fgGetNode( "/sim/replay/time", true);
replay_looped = fgGetNode( "/sim/replay/looped", true);
reinit();
}
@ -194,10 +195,28 @@ void FGReplay::update( double dt )
// replay inactive, keep recording
break;
case 1:
// replay active
replay( replay_time->getDoubleValue() );
replay_time->setDoubleValue( replay_time->getDoubleValue()
+ ( dt * fgGetInt("/sim/speed-up") ) );
{
// replay active
double current_time = replay_time->getDoubleValue();
if (current_time<0.0)
{
// initialize start time
fgSetDouble( "/sim/replay/start-time", get_start_time() );
fgSetDouble( "/sim/replay/end-time", get_end_time() );
double duration = fgGetDouble( "/sim/replay/duration" );
if( duration && duration < (get_end_time() - get_start_time()) ) {
current_time = get_end_time() - duration;
} else {
current_time = get_start_time();
}
}
bool IsFinished = replay( replay_time->getDoubleValue() );
if ((IsFinished)&&(replay_looped->getBoolValue()))
current_time = -1;
else
current_time += dt * fgGetInt("/sim/speed-up");
replay_time->setDoubleValue(current_time);
}
return; // don't record the replay session
case 2:
// replay paused, no-op
@ -279,7 +298,7 @@ void FGReplay::update( double dt )
FGReplayData *lt_front = long_term.front();
if ( sim_time - lt_front->sim_time > lt_list_time ) {
//stamp("point_10");
//stamp("point_10");
while ( sim_time - lt_front->sim_time > lt_list_time ) {
lt_front = long_term.front();
recycler.push_back(lt_front);
@ -558,9 +577,10 @@ static void interpolate( double time, const replay_list_type &list ) {
/**
* Replay a saved frame based on time, interpolate from the two
* nearest saved frames.
* Returns true when replay sequence has finished, false otherwise.
*/
void FGReplay::replay( double time ) {
bool FGReplay::replay( double time ) {
// cout << "replay: " << time << " ";
// find the two frames to interpolate between
double t1, t2;
@ -571,6 +591,8 @@ void FGReplay::replay( double time ) {
if ( time > t1 ) {
// replay the most recent frame
update_fdm( (*short_term.back()) );
// replay is finished now
return true;
// cout << "first frame" << endl;
} else if ( time <= t1 && time >= t2 ) {
interpolate( time, short_term );
@ -624,7 +646,9 @@ void FGReplay::replay( double time ) {
}
} else {
// nothing to replay
return true;
}
return false;
}

View file

@ -74,7 +74,7 @@ public:
virtual void unbind();
virtual void update( double dt );
void replay( double time );
bool replay( double time );
double get_start_time();
double get_end_time();
@ -101,6 +101,7 @@ private:
SGPropertyNode_ptr disable_replay;
SGPropertyNode_ptr replay_master;
SGPropertyNode_ptr replay_time;
SGPropertyNode_ptr replay_looped;
};

View file

@ -14,8 +14,8 @@
//
#include <simgear/misc/sg_path.hxx>
#include <simgear/xml/easyxml.hxx>
#include <simgear/misc/strutils.hxx>
#include <Main/globals.hxx>
#include <Main/fg_props.hxx>
@ -84,11 +84,16 @@ void XMLLoader::load(FGSidStar* p) {
bool XMLLoader::findAirportData(const std::string& aICAO,
const std::string& aFileName, SGPath& aPath)
{
string fileName(aFileName);
if (!simgear::strutils::ends_with(aFileName, ".xml")) {
fileName.append(".xml");
}
string_list sc = globals->get_fg_scenery();
char buffer[128];
::snprintf(buffer, 128, "%c/%c/%c/%s.%s.xml",
::snprintf(buffer, 128, "%c/%c/%c/%s.%s",
aICAO[0], aICAO[1], aICAO[2],
aICAO.c_str(), aFileName.c_str());
aICAO.c_str(), fileName.c_str());
for (string_list_iterator it = sc.begin(); it != sc.end(); ++it) {
SGPath path(*it);

View file

@ -224,6 +224,15 @@ void FGRouteMgr::init() {
void FGRouteMgr::postinit()
{
SGPath path(_pathNode->getStringValue());
if (path.exists()) {
SG_LOG(SG_AUTOPILOT, SG_INFO, "loading flight-plan from:" << path.str());
loadRoute();
}
// this code only matters for the --wp option now - perhaps the option
// should be deprecated in favour of an explicit flight-plan file?
// then the global initial waypoint list could die.
string_list *waypoints = globals->get_initial_waypoints();
if (waypoints) {
string_list::iterator it;

View file

@ -16,6 +16,7 @@ set(SOURCES
ridge_lift.cxx
terrainsampler.cxx
presets.cxx
gravity.cxx
)
flightgear_component(Environment "${SOURCES}")

View file

@ -17,6 +17,7 @@ libEnvironment_a_SOURCES = \
ridge_lift.cxx ridge_lift.hxx \
ephemeris.cxx ephemeris.hxx \
terrainsampler.cxx terrainsampler.cxx \
presets.cxx presets.hxx
presets.cxx presets.hxx \
gravity.cxx gravity.hxx
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src

View file

@ -31,8 +31,6 @@
#include <cmath>
#include <utility>
using namespace std;
/**
* Model the atmosphere in a way consistent with the laws
* of physics.

View file

@ -27,7 +27,6 @@
#include <simgear/constants.h>
#include <simgear/debug/logstream.hxx>
#include <simgear/scene/sky/sky.hxx>
#include <simgear/environment/visual_enviro.hxx>
#include <simgear/scene/model/particles.hxx>
#include <Main/main.hxx>
@ -43,6 +42,7 @@
#include "ridge_lift.hxx"
#include "terrainsampler.hxx"
#include "Airports/simple.hxx"
#include "gravity.hxx"
class SGSky;
extern SGSky *thesky;
@ -51,7 +51,7 @@ FGEnvironmentMgr::FGEnvironmentMgr () :
_environment(new FGEnvironment()),
fgClouds(new FGClouds()),
_cloudLayersDirty(true),
_altitudeNode(fgGetNode("/position/altitude-ft", true)),
_altitude_n(fgGetNode("/position/altitude-ft", true)),
_longitude_n(fgGetNode( "/position/longitude-deg", true )),
_latitude_n( fgGetNode( "/position/latitude-deg", true )),
_positionTimeToLive(0.0)
@ -98,6 +98,14 @@ FGEnvironmentMgr::init ()
SG_LOG( SG_GENERAL, SG_INFO, "Initializing environment subsystem");
SGSubsystemGroup::init();
fgClouds->Init();
// FIXME: is this really part of the environment_mgr?
// Initialize the longitude, latitude and altitude to the initial position
// of the aircraft so that the atmospheric properties (pressure, temperature
// and density) can be initialized accordingly.
_altitude_n->setDoubleValue(fgGetDouble("/sim/presets/altitude-ft"));
_longitude_n->setDoubleValue(fgGetDouble("/sim/presets/longitude-deg"));
_latitude_n->setDoubleValue(fgGetDouble("/sim/presets/latitude-deg"));
}
void
@ -122,9 +130,9 @@ FGEnvironmentMgr::bind ()
&FGClouds::get_update_event,
&FGClouds::set_update_event);
_tiedProperties.Tie("turbulence/use-cloud-turbulence", &sgEnviro,
&SGEnviro::get_turbulence_enable_state,
&SGEnviro::set_turbulence_enable_state);
// _tiedProperties.Tie("turbulence/use-cloud-turbulence", &sgEnviro,
// &SGEnviro::get_turbulence_enable_state,
// &SGEnviro::set_turbulence_enable_state);
for (int i = 0; i < MAX_CLOUD_LAYERS; i++) {
SGPropertyNode_ptr layerNode = fgGetNode("/environment/clouds",true)->getChild("layer", i, true );
@ -176,15 +184,10 @@ FGEnvironmentMgr::bind ()
&SGSky::get_3dCloudVisRange,
&SGSky::set_3dCloudVisRange);
_tiedProperties.Tie("precipitation-enable", &sgEnviro,
&SGEnviro::get_precipitation_enable_state,
&SGEnviro::set_precipitation_enable_state);
// _tiedProperties.Tie("lightning-enable", &sgEnviro,
// &SGEnviro::get_lightning_enable_state,
// &SGEnviro::set_lightning_enable_state);
_tiedProperties.Tie("lightning-enable", &sgEnviro,
&SGEnviro::get_lightning_enable_state,
&SGEnviro::set_lightning_enable_state);
sgEnviro.config(fgGetNode("/sim/rendering/precipitation"));
}
void
@ -200,7 +203,7 @@ FGEnvironmentMgr::update (double dt)
{
SGSubsystemGroup::update(dt);
_environment->set_elevation_ft( _altitudeNode->getDoubleValue() );
_environment->set_elevation_ft( _altitude_n->getDoubleValue() );
simgear::Particles::setWindFrom( _environment->get_wind_from_heading_deg(),
_environment->get_wind_speed_kt() );
@ -209,6 +212,14 @@ FGEnvironmentMgr::update (double dt)
fgClouds->set_update_event( fgClouds->get_update_event()+1 );
}
fgSetDouble( "/environment/gravitational-acceleration-mps2",
Environment::Gravity::instance()->getGravity(SGGeod::fromDegFt(
_longitude_n->getDoubleValue(),
_latitude_n->getDoubleValue(),
_altitude_n->getDoubleValue()
)));
_positionTimeToLive -= dt;
if( _positionTimeToLive <= 0.0 )
{

View file

@ -95,7 +95,7 @@ private:
FGEnvironment * _environment; // always the same, for now
FGClouds *fgClouds;
bool _cloudLayersDirty;
SGPropertyNode_ptr _altitudeNode;
SGPropertyNode_ptr _altitude_n;
SGPropertyNode_ptr _longitude_n;
SGPropertyNode_ptr _latitude_n;
double _positionTimeToLive;

View file

@ -30,7 +30,7 @@
#include <simgear/constants.h>
#include <simgear/sound/soundmgr_openal.hxx>
#include <simgear/scene/sky/sky.hxx>
#include <simgear/environment/visual_enviro.hxx>
//#include <simgear/environment/visual_enviro.hxx>
#include <simgear/scene/sky/cloudfield.hxx>
#include <simgear/scene/sky/newcloud.hxx>
#include <simgear/structure/commands.hxx>
@ -45,9 +45,14 @@
extern SGSky *thesky;
static bool do_delete_3Dcloud (const SGPropertyNode *arg);
static bool do_move_3Dcloud (const SGPropertyNode *arg);
static bool do_add_3Dcloud (const SGPropertyNode *arg);
FGClouds::FGClouds() :
#if 0
snd_lightning(0),
#endif
clouds_3d_enabled(false),
index(0)
{
@ -68,6 +73,7 @@ void FGClouds::set_update_event(int count) {
}
void FGClouds::Init(void) {
#if 0
if( snd_lightning == NULL ) {
snd_lightning = new SGSoundSample("Sounds/thunder.wav", SGPath());
snd_lightning->set_max_dist(7000.0f);
@ -75,8 +81,8 @@ void FGClouds::Init(void) {
SGSoundMgr *smgr = globals->get_soundmgr();
SGSampleGroup *sgr = smgr->find("weather", true);
sgr->add( snd_lightning, "thunder" );
sgEnviro.set_sampleGroup( sgr );
}
#endif
globals->get_commands()->addCommand("add-cloud", do_add_3Dcloud);
globals->get_commands()->addCommand("del-cloud", do_delete_3Dcloud);

View file

@ -45,7 +45,9 @@ private:
void buildCloudLayers(void);
int update_event;
#if 0
SGSoundSample *snd_lightning;
#endif
bool clouds_3d_enabled;
int index;
@ -62,9 +64,5 @@ public:
};
static bool do_delete_3Dcloud (const SGPropertyNode *arg);
static bool do_move_3Dcloud (const SGPropertyNode *arg);
static bool do_add_3Dcloud (const SGPropertyNode *arg);
#endif // _FGCLOUDS_HXX

View file

@ -0,0 +1,89 @@
// gravity.cxx -- interface for earth gravitational model
//
// Written by Torsten Dreyer, June 2011
//
// Copyright (C) 2011 Torsten Dreyer - torsten (at) t3r _dot_ de
//
// 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.
//
#include "gravity.hxx"
#include <simgear/structure/exception.hxx>
namespace Environment {
/*
http://de.wikipedia.org/wiki/Normalschwereformel
*/
class Somigliana : public Gravity {
public:
Somigliana();
virtual ~Somigliana();
virtual double getGravity( const SGGeod & position ) const;
};
Somigliana::Somigliana()
{
}
Somigliana::~Somigliana()
{
}
#include <stdio.h>
double Somigliana::getGravity( const SGGeod & position ) const
{
// Geodetic Reference System 1980 parameter
#define A 6378137.0 // equatorial radius of earth
#define B 6356752.3141 // semiminor axis
#define AGA (A*9.7803267715) // A times normal gravity at equator
#define BGB (B*9.8321863685) // B times normal gravity at pole
// forumla of Somigliana
double cosphi = ::cos(position.getLatitudeRad());
double cos2phi = cosphi*cosphi;
double sinphi = ::sin(position.getLatitudeRad());
double sin2phi = sinphi*sinphi;
double g0 = (AGA * cos2phi + BGB * sin2phi) / sqrt( A*A*cos2phi+B*B*sin2phi );
static const double k1 = 3.15704e-7;
static const double k2 = 2.10269e-9;
static const double k3 = 7.37452e-14;
double h = position.getElevationM();
return g0*(1-(k1-k2*sin2phi)*h+k3*h*h);
}
static Somigliana _somigliana;
/* --------------------- Gravity implementation --------------------- */
Gravity * Gravity::_instance = NULL;
Gravity::~Gravity()
{
}
//double Gravity::getGravity( const SGGeoc & position ) = 0;
const Gravity * Gravity::instance()
{
if( _instance == NULL )
_instance = &_somigliana;
return _instance;
}
} // namespace

View file

@ -0,0 +1,43 @@
// gravity.hxx -- interface for earth gravitational model
//
// Written by Torsten Dreyer, June 2011
//
// Copyright (C) 2011 Torsten Dreyer - torsten (at) t3r _dot_ de
//
// 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.
//
#ifndef __GRAVITY_HXX
#define __GRAVITY_HXX
#include <simgear/math/SGMath.hxx>
namespace Environment {
class Gravity
{
public:
virtual ~Gravity();
virtual double getGravity( const SGGeod & position ) const = 0;
const static Gravity * instance();
private:
static Gravity * _instance;
};
} // namespace
#endif // __GRAVITY_HXX

View file

@ -36,7 +36,6 @@
#include <simgear/math/SGMath.hxx>
#include <simgear/scene/sky/sky.hxx>
#include <simgear/scene/sky/cloud.hxx>
#include <simgear/environment/visual_enviro.hxx>
#include <Main/fg_props.hxx>
#include <Main/globals.hxx>
@ -93,6 +92,19 @@ void FGPrecipitationMgr::init()
fgGetNode("environment/params/precipitation-level-ft", true);
}
void FGPrecipitationMgr::bind ()
{
_tiedProperties.setRoot( fgGetNode("/sim/rendering", true ) );
_tiedProperties.Tie("precipitation-enable", precipitation.get(),
&SGPrecipitation::getEnabled,
&SGPrecipitation::setEnabled);
}
void FGPrecipitationMgr::unbind ()
{
_tiedProperties.Untie();
}
void FGPrecipitationMgr::setPrecipitationLevel(double a)
{
fgSetDouble("environment/params/precipitation-level-ft",a);
@ -206,7 +218,7 @@ void FGPrecipitationMgr::update(double dt)
setPrecipitationLevel(altitudeCloudLayer);
// Does the user enable the precipitation ?
if (!sgEnviro.get_precipitation_enable_state()) {
if (!precipitation->getEnabled() ) {
// Disable precipitations
precipitation->setRainIntensity(0);
precipitation->setSnowIntensity(0);

View file

@ -31,7 +31,7 @@
#include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/environment/precipitation.hxx>
#include <simgear/props/tiedpropertylist.hxx>
class FGPrecipitationMgr : public SGSubsystem
{
@ -40,12 +40,15 @@ private:
osg::ref_ptr<osg::MatrixTransform> transform;
osg::ref_ptr<SGPrecipitation> precipitation;
float getPrecipitationAtAltitudeMax(void);
simgear::TiedPropertyList _tiedProperties;
public:
FGPrecipitationMgr();
virtual ~FGPrecipitationMgr();
// SGSubsystem methods
virtual void bind ();
virtual void unbind ();
virtual void init ();
virtual void update (double dt);

View file

@ -114,12 +114,38 @@ private:
FGJSBsim* mInterface;
};
// FG uses a squared normalized magnitude for turbulence
// this lookup table maps fg's severity levels
// none(0), light(1/3), moderate(2/3) and severe(3/3)
// to the POE table indexes 0, 3, 4 and 7
class FGTurbulenceSeverityTable : public FGTable {
public:
FGTurbulenceSeverityTable() : FGTable(4) {
*this << (0.0/9.0) << 0.0;
*this << (1.0/9.0) << 3.0;
*this << (4.0/9.0) << 4.0;
*this << (9.0/9.0) << 7.0;
}
};
/******************************************************************************/
std::map<std::string,int> FGJSBsim::TURBULENCE_TYPE_NAMES;
static FGTurbulenceSeverityTable TurbulenceSeverityTable;
FGJSBsim::FGJSBsim( double dt )
: FGInterface(dt), got_wire(false)
{
bool result;
if( TURBULENCE_TYPE_NAMES.empty() ) {
TURBULENCE_TYPE_NAMES["ttNone"] = FGAtmosphere::ttNone;
TURBULENCE_TYPE_NAMES["ttStandard"] = FGAtmosphere::ttStandard;
TURBULENCE_TYPE_NAMES["ttBerndt"] = FGAtmosphere::ttBerndt;
TURBULENCE_TYPE_NAMES["ttCulp"] = FGAtmosphere::ttCulp;
TURBULENCE_TYPE_NAMES["ttMilspec"] = FGAtmosphere::ttMilspec;
TURBULENCE_TYPE_NAMES["ttTustin"] = FGAtmosphere::ttTustin;
}
// Set up the debugging level
// FIXME: this will not respond to
// runtime changes
@ -155,7 +181,7 @@ FGJSBsim::FGJSBsim( double dt )
MassBalance = fdmex->GetMassBalance();
Propulsion = fdmex->GetPropulsion();
Aircraft = fdmex->GetAircraft();
Propagate = fdmex->GetPropagate();
Propagate = fdmex->GetPropagate();
Auxiliary = fdmex->GetAuxiliary();
Inertial = fdmex->GetInertial();
Aerodynamics = fdmex->GetAerodynamics();
@ -282,8 +308,10 @@ FGJSBsim::FGJSBsim( double dt )
temperature = fgGetNode("/environment/temperature-degc",true);
pressure = fgGetNode("/environment/pressure-inhg",true);
density = fgGetNode("/environment/density-slugft3",true);
ground_wind = fgGetNode("/environment/config/boundary/entry[0]/wind-speed-kt",true);
turbulence_gain = fgGetNode("/environment/turbulence/magnitude-norm",true);
turbulence_rate = fgGetNode("/environment/turbulence/rate-hz",true);
turbulence_model = fgGetNode("/environment/params/jsbsim-turbulence-model",true);
wind_from_north= fgGetNode("/environment/wind-from-north-fps",true);
wind_from_east = fgGetNode("/environment/wind-from-east-fps" ,true);
@ -331,17 +359,19 @@ void FGJSBsim::init()
9.0/5.0*(temperature->getDoubleValue()+273.15) );
Atmosphere->SetExPressure(pressure->getDoubleValue()*70.726566);
Atmosphere->SetExDensity(density->getDoubleValue());
Atmosphere->SetTurbType(FGAtmosphere::ttCulp);
Atmosphere->SetTurbGain(turbulence_gain->getDoubleValue());
Atmosphere->SetTurbRate(turbulence_rate->getDoubleValue());
// initialize to no turbulence, these values get set in the update loop
Atmosphere->SetTurbType(FGAtmosphere::ttNone);
Atmosphere->SetTurbGain(0.0);
Atmosphere->SetTurbRate(0.0);
Atmosphere->SetWindspeed20ft(0.0);
Atmosphere->SetProbabilityOfExceedence(0.0);
} else {
Atmosphere->UseInternal();
}
fgic->SetVNorthFpsIC( -wind_from_north->getDoubleValue() );
fgic->SetVEastFpsIC( -wind_from_east->getDoubleValue() );
fgic->SetVDownFpsIC( -wind_from_down->getDoubleValue() );
fgic->SetWindNEDFpsIC( -wind_from_north->getDoubleValue(),
-wind_from_east->getDoubleValue(),
-wind_from_down->getDoubleValue() );
//Atmosphere->SetExTemperature(get_Static_temperature());
//Atmosphere->SetExPressure(get_Static_pressure());
@ -351,34 +381,32 @@ void FGJSBsim::init()
<< ", " << fdmex->GetAtmosphere()->GetDensity() );
// deprecate egt_degf for egt-degf to have consistent naming
// TODO: raise log-level to ALERT in summer 2010,
// remove alias in fall 2010,
// remove this code in winter 2010
// TODO: remove this by end of 2011
for (unsigned int i=0; i < Propulsion->GetNumEngines(); i++) {
SGPropertyNode * node = fgGetNode("engines/engine", i, true);
SGPropertyNode * egtn = node->getNode( "egt_degf" );
if( egtn != NULL ) {
SG_LOG(SG_FLIGHT,SG_WARN,
SG_LOG(SG_FLIGHT,SG_ALERT,
"Aircraft uses deprecated node egt_degf. Please upgrade to egt-degf");
node->getNode("egt-degf", true)->alias( egtn );
}
}
// end of egt_degf deprecation patch
if (fgGetBool("/sim/presets/running")) {
for (unsigned int i=0; i < Propulsion->GetNumEngines(); i++) {
SGPropertyNode * node = fgGetNode("engines/engine", i, true);
node->setBoolValue("running", true);
Propulsion->GetEngine(i)->SetRunning(true);
}
}
FCS->SetDfPos( ofNorm, globals->get_controls()->get_flaps() );
common_init();
copy_to_JSBsim();
fdmex->RunIC(); //loop JSBSim once w/o integrating
if (fgGetBool("/sim/presets/running")) {
Propulsion->InitRunning(-1);
for (unsigned int i = 0; i < Propulsion->GetNumEngines(); i++) {
FGPiston* eng = (FGPiston*)Propulsion->GetEngine(i);
globals->get_controls()->set_magnetos(i, eng->GetMagnetos());
globals->get_controls()->set_mixture(i, FCS->GetMixtureCmd(i));
}
}
copy_from_JSBsim(); //update the bus
SG_LOG( SG_FLIGHT, SG_INFO, " Initialized JSBSim with:" );
@ -590,7 +618,6 @@ void FGJSBsim::resume()
bool FGJSBsim::copy_to_JSBsim()
{
double tmp;
unsigned int i;
// copy control positions into the JSBsim structure
@ -686,11 +713,31 @@ bool FGJSBsim::copy_to_JSBsim()
Atmosphere->SetExPressure(pressure->getDoubleValue()*70.726566);
Atmosphere->SetExDensity(density->getDoubleValue());
tmp = turbulence_gain->getDoubleValue();
//Atmosphere->SetTurbGain(tmp * tmp * 100.0);
Atmosphere->SetTurbType((FGAtmosphere::tType)TURBULENCE_TYPE_NAMES[turbulence_model->getStringValue()]);
switch( Atmosphere->GetTurbType() ) {
case FGAtmosphere::ttStandard:
case FGAtmosphere::ttCulp:
case FGAtmosphere::ttBerndt: {
double tmp = turbulence_gain->getDoubleValue();
Atmosphere->SetTurbGain(tmp * tmp * 100.0);
Atmosphere->SetTurbRate(turbulence_rate->getDoubleValue());
break;
}
case FGAtmosphere::ttMilspec:
case FGAtmosphere::ttTustin: {
// milspec turbulence: 3=light, 4=moderate, 6=severe turbulence
// turbulence_gain normalized: 0: none, 1/3: light, 2/3: moderate, 3/3: severe
double tmp = turbulence_gain->getDoubleValue();
Atmosphere->SetProbabilityOfExceedence(
SGMiscd::roundToInt(TurbulenceSeverityTable.GetValue( tmp ) )
);
Atmosphere->SetWindspeed20ft(ground_wind->getDoubleValue());
break;
}
tmp = turbulence_rate->getDoubleValue();
//Atmosphere->SetTurbRate(tmp);
default:
break;
}
Atmosphere->SetWindNED( -wind_from_north->getDoubleValue(),
-wind_from_east->getDoubleValue(),
@ -1235,7 +1282,7 @@ void FGJSBsim::do_trim(void)
{
fgtrim = new FGTrim(fdmex,tGround);
} else {
fgtrim = new FGTrim(fdmex,tLongitudinal);
fgtrim = new FGTrim(fdmex,tFull);
}
if ( !fgtrim->DoTrim() ) {
@ -1249,7 +1296,7 @@ void FGJSBsim::do_trim(void)
pitch_trim->setDoubleValue( FCS->GetPitchTrimCmd() );
throttle_trim->setDoubleValue( FCS->GetThrottleCmd(0) );
aileron_trim->setDoubleValue( FCS->GetDaCmd() );
rudder_trim->setDoubleValue( FCS->GetDrCmd() );
rudder_trim->setDoubleValue( -FCS->GetDrCmd() );
globals->get_controls()->set_elevator_trim(FCS->GetPitchTrimCmd());
globals->get_controls()->set_elevator(FCS->GetDeCmd());
@ -1257,7 +1304,7 @@ void FGJSBsim::do_trim(void)
globals->get_controls()->set_throttle(i, FCS->GetThrottleCmd(i));
globals->get_controls()->set_aileron(FCS->GetDaCmd());
globals->get_controls()->set_rudder( FCS->GetDrCmd());
globals->get_controls()->set_rudder( -FCS->GetDrCmd());
SG_LOG( SG_FLIGHT, SG_INFO, " Trim complete" );
}

View file

@ -271,8 +271,10 @@ private:
SGPropertyNode_ptr temperature;
SGPropertyNode_ptr pressure;
SGPropertyNode_ptr density;
SGPropertyNode_ptr ground_wind;
SGPropertyNode_ptr turbulence_gain;
SGPropertyNode_ptr turbulence_rate;
SGPropertyNode_ptr turbulence_model;
SGPropertyNode_ptr wind_from_north;
SGPropertyNode_ptr wind_from_east;
@ -280,6 +282,8 @@ private:
SGPropertyNode_ptr slaved;
static std::map<std::string,int> TURBULENCE_TYPE_NAMES;
double last_hook_tip[3];
double last_hook_root[3];
JSBSim::FGColumnVector3 hook_root_struct;

View file

@ -61,7 +61,7 @@ using namespace std;
namespace JSBSim {
static const char *IdSrc = "$Id: FGInitialCondition.cpp,v 1.59 2011/04/03 13:18:51 bcoconni Exp $";
static const char *IdSrc = "$Id: FGInitialCondition.cpp,v 1.61 2011/05/20 00:47:03 bcoconni Exp $";
static const char *IdHdr = ID_INITIALCONDITION;
//******************************************************************************
@ -112,7 +112,7 @@ void FGInitialCondition::ResetIC(double u0, double v0, double w0,
FGQuaternion Quat(phi, theta, psi);
Quat.Normalize();
Tl2b = Quat.GetT();
Tb2l = Quat.GetTInv();
Tb2l = Tl2b.Transposed();
vUVW_NED = Tb2l * FGColumnVector3(u0, v0, w0);
vt = vUVW_NED.Magnitude();
@ -322,20 +322,18 @@ void FGInitialCondition::SetClimbRateFpsIC(double hdot)
FGColumnVector3 _vt_NED = Tb2l * Tw2b * FGColumnVector3(vt, 0., 0.);
FGColumnVector3 _WIND_NED = _vt_NED - vUVW_NED;
double hdot0 = _vt_NED(eW);
double hdot0 = -_vt_NED(eW);
if (fabs(hdot0) < vt) {
double scale = sqrt((vt*vt-hdot*hdot)/(vt*vt-hdot0*hdot0));
_vt_NED(eU) *= scale;
_vt_NED(eV) *= scale;
}
_vt_NED(eW) = hdot;
_vt_NED(eW) = -hdot;
vUVW_NED = _vt_NED - _WIND_NED;
// The AoA is not modified here but the function SetAlphaRadIC is updating the
// same angles than SetClimbRateFpsIC needs to update.
// TODO : create a subroutine that only shares the relevant code.
SetAlphaRadIC(alpha);
// Updating the angles theta and beta to keep the true airspeed amplitude
calcThetaBeta(alpha, _vt_NED);
}
//******************************************************************************
@ -346,13 +344,22 @@ void FGInitialCondition::SetClimbRateFpsIC(double hdot)
void FGInitialCondition::SetAlphaRadIC(double alfa)
{
FGColumnVector3 _vt_NED = Tb2l * Tw2b * FGColumnVector3(vt, 0., 0.);
calcThetaBeta(alfa, _vt_NED);
}
//******************************************************************************
// When the AoA is modified, we need to update the angles theta and beta to
// keep the true airspeed amplitude, the climb rate and the heading unchanged.
// Beta will be modified if the aircraft roll angle is not null.
void FGInitialCondition::calcThetaBeta(double alfa, const FGColumnVector3& _vt_NED)
{
double calpha = cos(alfa), salpha = sin(alfa);
double cpsi = cos(psi), spsi = sin(psi);
double cphi = cos(phi), sphi = sin(phi);
FGMatrix33 Tpsi( cpsi, spsi, 0.,
-spsi, cpsi, 0.,
0., 0., 1.);
-spsi, cpsi, 0.,
0., 0., 1.);
FGMatrix33 Tphi(1., 0., 0.,
0., cphi, sphi,
0.,-sphi, cphi);
@ -398,11 +405,11 @@ void FGInitialCondition::SetAlphaRadIC(double alfa)
Tl2b = Quat.GetT();
Tb2l = Quat.GetTInv();
FGColumnVector3 v2 = Talpha * Quat.GetT() * _vt_NED;
FGColumnVector3 v2 = Talpha * Tl2b * _vt_NED;
alpha = alfa;
beta = atan2(v2(eV), v2(eU));
double cbeta=0.0, sbeta=0.0;
double cbeta=1.0, sbeta=0.0;
if (vt != 0.0) {
cbeta = v2(eU) / vt;
sbeta = v2(eV) / vt;
@ -687,6 +694,8 @@ void FGInitialCondition::SetAltitudeASLFtIC(double alt)
double ve0 = vt * sqrt(rho/rhoSL);
altitudeASL=alt;
position.SetRadius(alt + sea_level_radius);
temperature = fdmex->GetAtmosphere()->GetTemperature(altitudeASL);
soundSpeed = sqrt(SHRatio*Reng*temperature);
rho = fdmex->GetAtmosphere()->GetDensity(altitudeASL);
@ -703,8 +712,6 @@ void FGInitialCondition::SetAltitudeASLFtIC(double alt)
default: // Make the compiler stop complaining about missing enums
break;
}
position.SetRadius(alt + sea_level_radius);
}
//******************************************************************************

View file

@ -54,7 +54,7 @@ INCLUDES
DEFINITIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#define ID_INITIALCONDITION "$Id: FGInitialCondition.h,v 1.26 2011/01/16 16:10:59 bcoconni Exp $"
#define ID_INITIALCONDITION "$Id: FGInitialCondition.h,v 1.27 2011/05/20 00:47:03 bcoconni Exp $"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -213,7 +213,7 @@ CLASS DOCUMENTATION
@property ic/r-rad_sec (read/write) Yaw rate initial condition in radians/second
@author Tony Peden
@version "$Id: FGInitialCondition.h,v 1.26 2011/01/16 16:10:59 bcoconni Exp $"
@version "$Id: FGInitialCondition.h,v 1.27 2011/05/20 00:47:03 bcoconni Exp $"
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -666,6 +666,7 @@ private:
double getMachFromVcas(double vcas);
double calcVcas(double Mach) const;
void calcAeroAngles(const FGColumnVector3& _vt_BODY);
void calcThetaBeta(double alfa, const FGColumnVector3& _vt_NED);
void bind(void);
void Debug(int from);

View file

@ -179,6 +179,15 @@ FGInterface::common_init ()
double slr = SGGeodesy::SGGeodToSeaLevelRadius(geodetic_position_v);
_set_Sea_level_radius( slr * SG_METER_TO_FEET );
// Set initial Euler angles
SG_LOG( SG_FLIGHT, SG_INFO, "...initializing Euler angles..." );
set_Euler_Angles( fgGetDouble("/sim/presets/roll-deg")
* SGD_DEGREES_TO_RADIANS,
fgGetDouble("/sim/presets/pitch-deg")
* SGD_DEGREES_TO_RADIANS,
fgGetDouble("/sim/presets/heading-deg")
* SGD_DEGREES_TO_RADIANS );
// Set initial velocities
SG_LOG( SG_FLIGHT, SG_INFO, "...initializing velocities..." );
if ( !fgHasNode("/sim/presets/speed-set") ) {
@ -207,14 +216,11 @@ FGInterface::common_init ()
}
}
// Set initial Euler angles
SG_LOG( SG_FLIGHT, SG_INFO, "...initializing Euler angles..." );
set_Euler_Angles( fgGetDouble("/sim/presets/roll-deg")
* SGD_DEGREES_TO_RADIANS,
fgGetDouble("/sim/presets/pitch-deg")
* SGD_DEGREES_TO_RADIANS,
fgGetDouble("/sim/presets/heading-deg")
* SGD_DEGREES_TO_RADIANS );
if ( fgHasNode("/sim/presets/glideslope-deg") )
set_Gamma_vert_rad( fgGetDouble("/sim/presets/glideslope-deg")
* SGD_DEGREES_TO_RADIANS );
else if ( fgHasNode( "/velocities/vertical-speed-fps") )
set_Climb_Rate( fgGetDouble("/velocities/vertical-speed-fps") );
SG_LOG( SG_FLIGHT, SG_INFO, "End common FDM init" );
}
@ -251,7 +257,7 @@ FGInterface::bind ()
false);
fgSetArchivable("/position/altitude-ft");
fgTie("/position/altitude-agl-ft", this,
&FGInterface::get_Altitude_AGL, &FGInterface::set_AltitudeAGL);
&FGInterface::get_Altitude_AGL, &FGInterface::set_AltitudeAGL, false);
fgSetArchivable("/position/ground-elev-ft");
fgTie("/position/ground-elev-ft", this,
&FGInterface::get_Runway_altitude); // read-only
@ -263,7 +269,7 @@ FGInterface::bind ()
fgSetArchivable("/position/sea-level-radius-ft");
fgTie("/position/sea-level-radius-ft", this,
&FGInterface::get_Sea_level_radius,
&FGInterface::_set_Sea_level_radius);
&FGInterface::_set_Sea_level_radius, false);
// Orientation
fgTie("/orientation/roll-deg", this,
@ -279,24 +285,27 @@ FGInterface::bind ()
&FGInterface::set_Psi_deg, false);
fgSetArchivable("/orientation/heading-deg");
fgTie("/orientation/track-deg", this,
&FGInterface::get_Track);
&FGInterface::get_Track); // read-only
// Body-axis "euler rates" (rotation speed, but in a funny
// representation).
fgTie("/orientation/roll-rate-degps", this,
&FGInterface::get_Phi_dot_degps, &FGInterface::set_Phi_dot_degps);
&FGInterface::get_Phi_dot_degps,
&FGInterface::set_Phi_dot_degps, false);
fgTie("/orientation/pitch-rate-degps", this,
&FGInterface::get_Theta_dot_degps, &FGInterface::set_Theta_dot_degps);
&FGInterface::get_Theta_dot_degps,
&FGInterface::set_Theta_dot_degps, false);
fgTie("/orientation/yaw-rate-degps", this,
&FGInterface::get_Psi_dot_degps, &FGInterface::set_Psi_dot_degps);
&FGInterface::get_Psi_dot_degps,
&FGInterface::set_Psi_dot_degps, false);
fgTie("/orientation/p-body", this, &FGInterface::get_P_body);
fgTie("/orientation/q-body", this, &FGInterface::get_Q_body);
fgTie("/orientation/r-body", this, &FGInterface::get_R_body);
fgTie("/orientation/p-body", this, &FGInterface::get_P_body); // read-only
fgTie("/orientation/q-body", this, &FGInterface::get_Q_body); // read-only
fgTie("/orientation/r-body", this, &FGInterface::get_R_body); // read-only
// Ground speed knots
fgTie("/velocities/groundspeed-kt", this,
&FGInterface::get_V_ground_speed_kt);
&FGInterface::get_V_ground_speed_kt); // read-only
// Calibrated airspeed
fgTie("/velocities/airspeed-kt", this,
@ -305,7 +314,7 @@ FGInterface::bind ()
false);
fgTie("/velocities/equivalent-kt", this,
&FGInterface::get_V_equiv_kts);
&FGInterface::get_V_equiv_kts); // read-only
// Mach number
fgTie("/velocities/mach", this,
@ -338,11 +347,11 @@ FGInterface::bind ()
&FGInterface::get_V_down, &FGInterface::set_V_down, false);
fgTie("/velocities/north-relground-fps", this,
&FGInterface::get_V_north_rel_ground);
&FGInterface::get_V_north_rel_ground); // read-only
fgTie("/velocities/east-relground-fps", this,
&FGInterface::get_V_east_rel_ground);
&FGInterface::get_V_east_rel_ground); // read-only
fgTie("/velocities/down-relground-fps", this,
&FGInterface::get_V_down_rel_ground);
&FGInterface::get_V_down_rel_ground); // read-only
// Relative wind
@ -367,36 +376,37 @@ FGInterface::bind ()
// Climb and slip (read-only)
fgTie("/velocities/vertical-speed-fps", this,
&FGInterface::get_Climb_Rate,
&FGInterface::set_Climb_Rate );
&FGInterface::set_Climb_Rate, false );
fgTie("/velocities/glideslope", this,
&FGInterface::get_Gamma_vert_rad,
&FGInterface::set_Gamma_vert_rad );
&FGInterface::set_Gamma_vert_rad, false );
fgTie("/orientation/side-slip-rad", this,
&FGInterface::get_Beta, &FGInterface::_set_Beta);
&FGInterface::get_Beta, &FGInterface::_set_Beta, false);
fgTie("/orientation/side-slip-deg", this,
&FGInterface::get_Beta_deg); // read-only
fgTie("/orientation/alpha-deg", this,
&FGInterface::get_Alpha_deg, &FGInterface::set_Alpha_deg); // read-only
&FGInterface::get_Alpha_deg, &FGInterface::set_Alpha_deg, false);
fgTie("/accelerations/nlf", this,
&FGInterface::get_Nlf); // read-only
// NED accelerations
fgTie("/accelerations/ned/north-accel-fps_sec",
this, &FGInterface::get_V_dot_north);
this, &FGInterface::get_V_dot_north); // read-only
fgTie("/accelerations/ned/east-accel-fps_sec",
this, &FGInterface::get_V_dot_east);
this, &FGInterface::get_V_dot_east); // read-only
fgTie("/accelerations/ned/down-accel-fps_sec",
this, &FGInterface::get_V_dot_down);
this, &FGInterface::get_V_dot_down); // read-only
// Pilot accelerations
fgTie("/accelerations/pilot/x-accel-fps_sec",
this, &FGInterface::get_A_X_pilot, &FGInterface::set_A_X_pilot);
this, &FGInterface::get_A_X_pilot, &FGInterface::set_A_X_pilot, false);
fgTie("/accelerations/pilot/y-accel-fps_sec",
this, &FGInterface::get_A_Y_pilot, &FGInterface::set_A_Y_pilot);
this, &FGInterface::get_A_Y_pilot, &FGInterface::set_A_Y_pilot, false);
fgTie("/accelerations/pilot/z-accel-fps_sec",
this, &FGInterface::get_A_Z_pilot, &FGInterface::set_A_Z_pilot);
this, &FGInterface::get_A_Z_pilot, &FGInterface::set_A_Z_pilot, false);
fgTie("/accelerations/n-z-cg-fps_sec", this, &FGInterface::get_N_Z_cg);
fgTie("/accelerations/n-z-cg-fps_sec",
this, &FGInterface::get_N_Z_cg); // read-only
}

View file

@ -27,7 +27,7 @@
# include <config.h>
#endif
#include <memory>
#include <cstring>
#include <simgear/math/SGMathFwd.hxx> // for SGVec3d
#include <simgear/math/SGMisc.hxx>

View file

@ -386,6 +386,7 @@ MapWidget::MapWidget(int x, int y, int maxX, int maxY) :
_zoom = 6;
_width = maxX - x;
_height = maxY - y;
_hasPanned = false;
MapData::setFont(legendFont);
MapData::setPalette(colour);
@ -496,6 +497,7 @@ int MapWidget::checkKey (int key, int updown )
void MapWidget::pan(const SGVec2d& delta)
{
_hasPanned = true;
_projectionCenter = unproject(-delta);
}
@ -525,6 +527,12 @@ void MapWidget::draw(int dx, int dy)
fgGetDouble("/position/latitude-deg"));
_magneticHeadings = _root->getBoolValue("magnetic-headings");
if (_hasPanned)
{
_root->setBoolValue("centre-on-aircraft", false);
_hasPanned = false;
}
else
if (_root->getBoolValue("centre-on-aircraft")) {
_projectionCenter = _aircraft;
}

View file

@ -85,6 +85,7 @@ private:
double _drawRangeNm;
double _upHeading; // true heading corresponding to +ve y-axis
bool _magneticHeadings;
bool _hasPanned;
SGGeod _projectionCenter;
SGGeod _aircraft;

View file

@ -42,6 +42,7 @@
#include <simgear/debug/logstream.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/screen/screen-dump.hxx>
#include <simgear/structure/event_mgr.hxx>
#include <Cockpit/panel.hxx>
#include <Main/globals.hxx>
@ -49,8 +50,11 @@
#include <Main/fg_os.hxx>
#include <Main/renderer.hxx>
#include <Main/viewmgr.hxx>
#include <Main/WindowSystemAdapter.hxx>
#include <Main/CameraGroup.hxx>
#include <GUI/new_gui.hxx>
#ifdef _WIN32
# include <shellapi.h>
#endif
@ -406,9 +410,134 @@ void fgHiResDumpWrapper () {
fgHiResDump();
}
namespace
{
using namespace flightgear;
class GUISnapShotOperation :
public GraphicsContextOperation
{
public:
// start new snap shot
static bool start()
{
// allow only one snapshot at a time
if (_snapShotOp.valid())
return false;
_snapShotOp = new GUISnapShotOperation();
/* register with graphics context so actual snap shot is done
* in the graphics context (thread) */
osg::Camera* guiCamera = getGUICamera(CameraGroup::getDefault());
WindowSystemAdapter* wsa = WindowSystemAdapter::getWSA();
osg::GraphicsContext* gc = 0;
if (guiCamera)
gc = guiCamera->getGraphicsContext();
if (gc) {
gc->add(_snapShotOp.get());
} else {
wsa->windows[0]->gc->add(_snapShotOp.get());
}
return true;
}
private:
// constructor to be executed in main loop's thread
GUISnapShotOperation() :
flightgear::GraphicsContextOperation(std::string("GUI snap shot")),
_master_freeze(fgGetNode("/sim/freeze/master", true)),
_freeze(_master_freeze->getBoolValue()),
_result(false),
_mouse(fgGetMouseCursor())
{
if (!_freeze)
_master_freeze->setBoolValue(true);
fgSetMouseCursor(MOUSE_CURSOR_NONE);
string dir = fgGetString("/sim/paths/screenshot-dir");
if (dir.empty())
dir = fgGetString("/sim/fg-current");
_path.set(dir + '/');
if (_path.create_dir( 0755 )) {
SG_LOG(SG_GENERAL, SG_ALERT, "Cannot create screenshot directory '"
<< dir << "'. Trying home directory.");
dir = fgGetString("/sim/fg-home");
}
char filename[24];
static int count = 1;
while (count < 1000) {
snprintf(filename, 24, "fgfs-screen-%03d.png", count++);
SGPath p(dir);
p.append(filename);
if (!p.exists()) {
_path.set(p.str());
break;
}
}
_xsize = fgGetInt("/sim/startup/xsize");
_ysize = fgGetInt("/sim/startup/ysize");
FGRenderer *renderer = globals->get_renderer();
renderer->resize(_xsize, _ysize);
globals->get_event_mgr()->addTask("SnapShotTimer",
this, &GUISnapShotOperation::timerExpired,
0.1, false);
}
// to be executed in graphics context (maybe separate thread)
void run(osg::GraphicsContext* gc)
{
_result = sg_glDumpWindow(_path.c_str(),
_xsize,
_ysize);
}
// timer method, to be executed in main loop's thread
virtual void timerExpired()
{
if (isFinished())
{
globals->get_event_mgr()->removeTask("SnapShotTimer");
fgSetString("/sim/paths/screenshot-last", _path.c_str());
fgSetBool("/sim/signals/screenshot", _result);
fgSetMouseCursor(_mouse);
if ( !_freeze )
_master_freeze->setBoolValue(false);
_snapShotOp = 0;
}
}
static osg::ref_ptr<GUISnapShotOperation> _snapShotOp;
SGPropertyNode_ptr _master_freeze;
bool _freeze;
bool _result;
int _mouse;
int _xsize, _ysize;
SGPath _path;
};
}
osg::ref_ptr<GUISnapShotOperation> GUISnapShotOperation::_snapShotOp;
// do a screen snap shot
bool fgDumpSnapShot () {
bool fgDumpSnapShot ()
{
#if 1
// start snap shot operation, while needs to be executed in
// graphics context
return GUISnapShotOperation::start();
#else
// obsolete code => remove when new code is stable
static SGConstPropertyNode_ptr master_freeze = fgGetNode("/sim/freeze/master");
bool freeze = master_freeze->getBoolValue();
@ -455,7 +584,7 @@ bool fgDumpSnapShot () {
}
}
int result = sg_glDumpWindow(path.c_str(),
bool result = sg_glDumpWindow(path.c_str(),
fgGetInt("/sim/startup/xsize"),
fgGetInt("/sim/startup/ysize"));
@ -467,7 +596,8 @@ bool fgDumpSnapShot () {
if ( !freeze ) {
fgSetBool("/sim/freeze/master", false);
}
return result != 0;
return result;
#endif
}
// do an entire scenegraph dump

View file

@ -49,7 +49,8 @@ FGJoystickInput::joystick::joystick ()
naxes(0),
nbuttons(0),
axes(0),
buttons(0)
buttons(0),
predefined(true)
{
}
@ -73,15 +74,18 @@ FGJoystickInput::FGJoystickInput()
FGJoystickInput::~FGJoystickInput()
{
_remove();
_remove(true);
}
void FGJoystickInput::_remove()
void FGJoystickInput::_remove(bool all)
{
SGPropertyNode * js_nodes = fgGetNode("/input/joysticks", true);
js_nodes->removeChildren("js", false);
for (int i = 0; i < MAX_JOYSTICKS; i++)
{
// do not remove predefined joysticks info on reinit
if ((all)||(!bindings[i].predefined))
js_nodes->removeChild("js", i, false);
if (bindings[i].js)
delete bindings[i].js;
bindings[i].js = NULL;
@ -92,7 +96,7 @@ void FGJoystickInput::init()
{
jsInit();
SG_LOG(SG_INPUT, SG_DEBUG, "Initializing joystick bindings");
SGPropertyNode * js_nodes = fgGetNode("/input/joysticks", true);
SGPropertyNode_ptr js_nodes = fgGetNode("/input/joysticks", true);
FGDeviceConfigurationMap configMap("Input/Joysticks", js_nodes, "js-named");
@ -112,6 +116,7 @@ void FGJoystickInput::init()
SG_LOG(SG_INPUT, SG_INFO, "Using existing bindings for joystick " << i);
} else {
bindings[i].predefined = false;
SG_LOG(SG_INPUT, SG_INFO, "Looking for bindings for joystick \"" << name << '"');
SGPropertyNode_ptr named;
@ -137,7 +142,7 @@ void FGJoystickInput::init()
void FGJoystickInput::reinit() {
SG_LOG(SG_INPUT, SG_DEBUG, "Re-Initializing joystick bindings");
_remove();
_remove(false);
FGJoystickInput::init();
FGJoystickInput::postinit();
}

View file

@ -25,7 +25,7 @@
#ifndef _FGJOYSTICKINPUT_HXX
#define _FGJOYSTICKINPUT_HXX
#ifndef __cplusplus
#ifndef __cplusplus
# error This library requires C++
#endif
@ -52,7 +52,7 @@ public:
static const int MAX_JOYSTICK_BUTTONS = 32;
private:
void _remove();
void _remove(bool all);
/**
* Settings for a single joystick axis.
@ -83,6 +83,7 @@ private:
int nbuttons;
axis * axes;
FGButton * buttons;
bool predefined;
};
joystick bindings[MAX_JOYSTICKS];

View file

@ -23,8 +23,8 @@
// $Id$
#include "FGMouseInput.hxx"
#include "Main/globals.hxx"
void ActivePickCallbacks::init( int b, const osgGA::GUIEventAdapter* ea )
{
// Get the list of hit callbacks. Take the first callback that
@ -33,7 +33,7 @@ void ActivePickCallbacks::init( int b, const osgGA::GUIEventAdapter* ea )
// The nearest one is the first one and the deepest
// (the most specialized one in the scenegraph) is the first.
std::vector<SGSceneryPick> pickList;
if (FGRenderer::pick(pickList, ea)) {
if (globals->get_renderer()->pick(pickList, ea)) {
std::vector<SGSceneryPick>::const_iterator i;
for (i = pickList.begin(); i != pickList.end(); ++i) {
if (i->callback->buttonPressed(b, i->info)) {

View file

@ -269,7 +269,7 @@ public:
_offset = n->getFloatValue("offset", offset);
_min = n->getFloatValue("min", min);
_max = n->getFloatValue("max", max);
_coeff = 1.0 - 1.0 / powf(10, fabsf(n->getFloatValue("damp", 0.0)));
_coeff = 1.0 - 1.0 / powf(10, fabs(n->getFloatValue("damp", 0.0)));
SGPropertyNode *p = ((SGPropertyNode *)n)->getNode("property", false);
if (p) {
const char *path = p->getStringValue();

View file

@ -89,7 +89,7 @@ void HUD::Label::draw(void)
l = _center_x - pw;
r = _center_x + pw;
bool draw_parallel = fabsf(_pointer_width - _w) > 2.0; // draw lines left and right of arrow?
bool draw_parallel = fabs(_pointer_width - _w) > 2.0; // draw lines left and right of arrow?
if (option_bottom()) {
if (draw_parallel) {
@ -115,7 +115,7 @@ void HUD::Label::draw(void)
l = _center_y - pw;
r = _center_y + pw;
draw_parallel = fabsf(_pointer_width - _h) > 2.0;
draw_parallel = fabs(_pointer_width - _h) > 2.0;
if (option_left()) {
if (draw_parallel) {

View file

@ -48,7 +48,7 @@ HUD::Ladder::Ladder(HUD *hud, const SGPropertyNode *n, float x, float y) :
_roll(n->getNode("roll-input", false)),
_width_units(int(n->getFloatValue("display-span"))),
_div_units(int(fabs(n->getFloatValue("divisions")))),
_scr_hole(fabsf(n->getFloatValue("screen-hole")) * 0.5f),
_scr_hole(fabs(n->getFloatValue("screen-hole")) * 0.5f),
_zero_bar_overlength(n->getFloatValue("zero-bar-overlength", 10)),
_dive_bar_angle(n->getBoolValue("enable-dive-bar-angle")),
_tick_length(n->getFloatValue("tick-length")),

View file

@ -534,7 +534,7 @@ void HUD::Tape::draw_horizontal(float value)
char *HUD::Tape::format_value(float v)
{
if (fabsf(v) < 1e-8) // avoid -0.0
if (fabs(v) < 1e-8) // avoid -0.0
v = 0.0f;
if (_label_fmt == INT)

View file

@ -129,12 +129,12 @@ void HUD::TurnBankIndicator::draw_scale()
int dir = bank > 0 ? 1 : -1;
if (fabsf(bank) > 25) {
if (fabs(bank) > 25) {
draw_tick(45, r, minor, dir);
draw_tick(60, r, major, dir);
}
if (fabsf(bank) > 55) {
if (fabs(bank) > 55) {
draw_tick(90, r, major, dir);
draw_tick(135, r, major, dir);
}

View file

@ -38,7 +38,6 @@
#include <simgear/constants.h>
#include <simgear/misc/sg_path.hxx>
#include <simgear/environment/visual_enviro.hxx>
#include <simgear/scene/model/model.hxx>
#include <simgear/structure/exception.hxx>
#include <simgear/misc/sg_path.hxx>
@ -137,7 +136,7 @@ wxRadarBg::init ()
SGPath tpath = globals->resolve_aircraft_path(path);
// no mipmap or else alpha will mix with pixels on the border of shapes, ruining the effect
_wxEcho = SGLoadTexture2D(tpath, false, false);
_wxEcho = SGLoadTexture2D(tpath, NULL, false, false);
_Instrument->setFloatValue("trk", 0.0);
@ -379,90 +378,99 @@ wxRadarBg::update (double delta_time_sec)
_texCoords->clear();
_textGeode->removeDrawables(0, _textGeode->getNumDrawables());
#if 0
//TODO FIXME Mask below (only used for ARC mode) isn't properly aligned, i.e.
// it assumes the a/c position at the center of the display - though it's somewhere at
// bottom part for ARC mode.
// The mask hadn't worked at all for a while (probably since the OSG port) due to
// another bug (which is fixed now). Now, the mask is disabled completely until s.o.
// adapted the coordinates below. And the mask is only really useful to limit displayed
// weather blobs (not support yet).
// Aircraft echos are already limited properly through wxradar's "limit-deg" property.
{
osg::DrawArrays *maskPSet
= static_cast<osg::DrawArrays*>(_geom->getPrimitiveSet(1));
osg::DrawArrays *trimaskPSet
= static_cast<osg::DrawArrays*>(_geom->getPrimitiveSet(2));
if (_display_mode == ARC) {
// erase what is out of sight of antenna
/*
|\ /|
| \ / |
| \ / |
---------
| |
| |
---------
*/
float xOffset = 256.0f;
float yOffset = 200.0f;
int firstQuadVert = _vertices->size();
_texCoords->push_back(osg::Vec2f(0.5f, 0.25f));
_vertices->push_back(osg::Vec2f(-xOffset, 0.0 + yOffset));
_texCoords->push_back(osg::Vec2f(1.0f, 0.25f));
_vertices->push_back(osg::Vec2f(xOffset, 0.0 + yOffset));
_texCoords->push_back(osg::Vec2f(1.0f, 0.5f));
_vertices->push_back(osg::Vec2f(xOffset, 256.0 + yOffset));
_texCoords->push_back(osg::Vec2f(0.5f, 0.5f));
_vertices->push_back(osg::Vec2f(-xOffset, 256.0 + yOffset));
maskPSet->set(osg::PrimitiveSet::QUADS, firstQuadVert, 4);
firstQuadVert += 4;
// The triangles aren't supposed to be textured, but there's
// no need to set up a different Geometry, switch modes,
// etc. I happen to know that there's a white pixel in the
// texture at 1.0, 0.0 :)
float centerY = tan(30 * SG_DEGREES_TO_RADIANS);
_vertices->push_back(osg::Vec2f(0.0, 0.0));
_vertices->push_back(osg::Vec2f(-256.0, 0.0));
_vertices->push_back(osg::Vec2f(-256.0, 256.0 * centerY));
_vertices->push_back(osg::Vec2f(0.0, 0.0));
_vertices->push_back(osg::Vec2f(256.0, 0.0));
_vertices->push_back(osg::Vec2f(256.0, 256.0 * centerY));
_vertices->push_back(osg::Vec2f(-256, 0.0));
_vertices->push_back(osg::Vec2f(256.0, 0.0));
_vertices->push_back(osg::Vec2f(-256.0, -256.0));
_vertices->push_back(osg::Vec2f(256, 0.0));
_vertices->push_back(osg::Vec2f(256.0, -256.0));
_vertices->push_back(osg::Vec2f(-256.0, -256.0));
const osg::Vec2f whiteSpot(1.0f, 0.0f);
for (int i = 0; i < 3 * 4; i++)
_texCoords->push_back(whiteSpot);
trimaskPSet->set(osg::PrimitiveSet::TRIANGLES, firstQuadVert, 3 * 4);
} else
{
maskPSet->set(osg::PrimitiveSet::QUADS, 0, 0);
trimaskPSet->set(osg::PrimitiveSet::TRIANGLES, 0, 0);
}
maskPSet->dirty();
trimaskPSet->dirty();
}
#endif
// remember index of next vertex
int vIndex = _vertices->size();
update_weather();
osg::DrawArrays *quadPSet
= static_cast<osg::DrawArrays*>(_geom->getPrimitiveSet(0));
quadPSet->set(osg::PrimitiveSet::QUADS, 0, _vertices->size());
quadPSet->dirty();
// erase what is out of sight of antenna
/*
|\ /|
| \ / |
| \ / |
---------
| |
| |
---------
*/
osg::DrawArrays *maskPSet
= static_cast<osg::DrawArrays*>(_geom->getPrimitiveSet(1));
osg::DrawArrays *trimaskPSet
= static_cast<osg::DrawArrays*>(_geom->getPrimitiveSet(2));
if (_display_mode == ARC) {
float xOffset = 256.0f;
float yOffset = 200.0f;
int firstQuadVert = _vertices->size();
_texCoords->push_back(osg::Vec2f(0.5f, 0.25f));
_vertices->push_back(osg::Vec2f(-xOffset, 0.0 + yOffset));
_texCoords->push_back(osg::Vec2f(1.0f, 0.25f));
_vertices->push_back(osg::Vec2f(xOffset, 0.0 + yOffset));
_texCoords->push_back(osg::Vec2f(1.0f, 0.5f));
_vertices->push_back(osg::Vec2f(xOffset, 256.0 + yOffset));
_texCoords->push_back(osg::Vec2f(0.5f, 0.5f));
_vertices->push_back(osg::Vec2f(-xOffset, 256.0 + yOffset));
maskPSet->set(osg::PrimitiveSet::QUADS, firstQuadVert, 4);
// The triangles aren't supposed to be textured, but there's
// no need to set up a different Geometry, switch modes,
// etc. I happen to know that there's a white pixel in the
// texture at 1.0, 0.0 :)
float centerY = tan(30 * SG_DEGREES_TO_RADIANS);
_vertices->push_back(osg::Vec2f(0.0, 0.0));
_vertices->push_back(osg::Vec2f(-256.0, 0.0));
_vertices->push_back(osg::Vec2f(-256.0, 256.0 * centerY));
_vertices->push_back(osg::Vec2f(0.0, 0.0));
_vertices->push_back(osg::Vec2f(256.0, 0.0));
_vertices->push_back(osg::Vec2f(256.0, 256.0 * centerY));
_vertices->push_back(osg::Vec2f(-256, 0.0));
_vertices->push_back(osg::Vec2f(256.0, 0.0));
_vertices->push_back(osg::Vec2f(-256.0, -256.0));
_vertices->push_back(osg::Vec2f(256, 0.0));
_vertices->push_back(osg::Vec2f(256.0, -256.0));
_vertices->push_back(osg::Vec2f(-256.0, -256.0));
const osg::Vec2f whiteSpot(1.0f, 0.0f);
for (int i = 0; i < 3 * 4; i++)
_texCoords->push_back(whiteSpot);
trimaskPSet->set(osg::PrimitiveSet::TRIANGLES, firstQuadVert + 4, 3 * 4);
} else {
maskPSet->set(osg::PrimitiveSet::QUADS, 0, 0);
trimaskPSet->set(osg::PrimitiveSet::TRIANGLES, 0, 0);
}
maskPSet->dirty();
trimaskPSet->dirty();
// draw without mask
_vertices->clear();
_texCoords->clear();
update_aircraft();
update_tacan();
update_heading_marker();
quadPSet->set(osg::PrimitiveSet::QUADS, 0, _vertices->size());
// draw all new vertices are quads
quadPSet->set(osg::PrimitiveSet::QUADS, vIndex, _vertices->size()-vIndex);
quadPSet->dirty();
}
}
@ -472,13 +480,16 @@ void
wxRadarBg::update_weather()
{
string modeButton = _Instrument->getStringValue("mode", "WX");
_radarEchoBuffer = *sgEnviro.get_radar_echo();
// FIXME: implementation of radar echoes missing
// _radarEchoBuffer = *sgEnviro.get_radar_echo();
// pretend we have a scan angle bigger then the FOV
// TODO:check real fov, enlarge if < nn, and do clipping if > mm
// const float fovFactor = 1.45f;
_Instrument->setStringValue("status", modeButton.c_str());
// FIXME: implementation of radar echoes missing
#if 0
list_of_SGWxRadarEcho *radarEcho = &_radarEchoBuffer;
list_of_SGWxRadarEcho::iterator iradarEcho, end = radarEcho->end();
const float LWClevel[] = { 0.1f, 0.5f, 2.1f };
@ -558,6 +569,7 @@ wxRadarBg::update_weather()
addQuad(_vertices, _texCoords, m, texBase);
}
}
#endif
}

View file

@ -30,7 +30,6 @@
#include <simgear/props/props.hxx>
#include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/environment/visual_enviro.hxx>
#include <vector>
#include <string>
@ -148,7 +147,8 @@ private:
float _font_size;
float _font_spacing;
list_of_SGWxRadarEcho _radarEchoBuffer;
// FIXME: implementation of radar echoes missing
// list_of_SGWxRadarEcho _radarEchoBuffer;
void update_weather();
void update_aircraft();

View file

@ -69,9 +69,9 @@ WindowBuilder::makeDefaultTraits(bool stencil)
traits->red = traits->green = traits->blue = cbits;
traits->depth = zbits;
if (alpha)
traits->alpha = 8;
traits->alpha = 8;
if (stencil)
traits->stencil = 8;
traits->stencil = 8;
traits->doubleBuffer = true;
traits->mipMapGeneration = true;
traits->windowName = "FlightGear";
@ -83,20 +83,21 @@ WindowBuilder::makeDefaultTraits(bool stencil)
unsigned width = 0;
unsigned height = 0;
wsi->getScreenResolution(*traits, width, height);
traits->windowDecoration = false;
traits->windowDecoration = false;
traits->width = width;
traits->height = height;
traits->supportsResize = false;
} else {
traits->windowDecoration = true;
traits->windowDecoration = true;
traits->width = w;
traits->height = h;
#if defined(WIN32) || defined(__APPLE__)
unsigned screenwidth = 0;
unsigned screenheight = 0;
wsi->getScreenResolution(*traits, screenwidth, screenheight);
// Ugly Hack, why does CW_USEDEFAULT works like phase of the moon?
// Mac also needs this to show window frame, menubar and Docks
traits->x = 100;
traits->y = 100;
#endif
traits->x = (w>screenwidth) ? 0 : (screenwidth-w)/3;
traits->y = (h>screenheight) ? 0 : (screenheight-h)/3;
traits->supportsResize = true;
}
return traits;

View file

@ -33,7 +33,7 @@
#include <Scenery/scenery.hxx>
#include <Scripting/NasalSys.hxx>
#include <Sound/sample_queue.hxx>
#include <Time/sunsolver.hxx>
#include <Airports/xmlloader.hxx>
#include "fg_init.hxx"
#include "fg_io.hxx"
@ -314,6 +314,16 @@ do_resume (const SGPropertyNode * arg)
#endif
static bool
do_pause (const SGPropertyNode * arg)
{
bool paused = fgGetBool("/sim/freeze/master",true) || fgGetBool("/sim/freeze/clock",true);
fgSetBool("/sim/freeze/master",!paused);
fgSetBool("/sim/freeze/clock",!paused);
if (fgGetBool("/sim/freeze/replay-state",false))
fgSetBool("/sim/replay/disable",true);
return true;
}
/**
* Built-in command: load flight.
@ -688,85 +698,6 @@ do_set_dewpoint_degc (const SGPropertyNode * arg)
return do_set_dewpoint_sea_level_degc(dummy.get_dewpoint_sea_level_degc());
}
#endif
/**
* Update the lighting manually.
*/
static bool
do_timeofday (const SGPropertyNode * arg)
{
const string &offset_type = arg->getStringValue("timeofday", "noon");
static const SGPropertyNode *longitude
= fgGetNode("/position/longitude-deg");
static const SGPropertyNode *latitude
= fgGetNode("/position/latitude-deg");
int orig_warp = globals->get_warp();
SGTime *t = globals->get_time_params();
time_t cur_time = t->get_cur_time();
// cout << "cur_time = " << cur_time << endl;
// cout << "orig_warp = " << orig_warp << endl;
int warp = 0;
if ( offset_type == "real" ) {
warp = -orig_warp;
} else if ( offset_type == "dawn" ) {
warp = fgTimeSecondsUntilSunAngle( cur_time,
longitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
latitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
90.0, true );
} else if ( offset_type == "morning" ) {
warp = fgTimeSecondsUntilSunAngle( cur_time,
longitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
latitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
75.0, true );
} else if ( offset_type == "noon" ) {
warp = fgTimeSecondsUntilSunAngle( cur_time,
longitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
latitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
0.0, true );
} else if ( offset_type == "afternoon" ) {
warp = fgTimeSecondsUntilSunAngle( cur_time,
longitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
latitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
60.0, false );
} else if ( offset_type == "dusk" ) {
warp = fgTimeSecondsUntilSunAngle( cur_time,
longitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
latitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
90.0, false );
} else if ( offset_type == "evening" ) {
warp = fgTimeSecondsUntilSunAngle( cur_time,
longitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
latitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
100.0, false );
} else if ( offset_type == "midnight" ) {
warp = fgTimeSecondsUntilSunAngle( cur_time,
longitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
latitude->getDoubleValue()
* SGD_DEGREES_TO_RADIANS,
180.0, false );
}
fgSetInt("/sim/time/warp", orig_warp + warp);
return true;
}
/**
* Built-in command: toggle a bool property value.
@ -1247,17 +1178,7 @@ do_replay (const SGPropertyNode * arg)
fgSetInt( "/sim/freeze/replay-state", 1 );
fgSetBool("/sim/freeze/master", 0 );
fgSetBool("/sim/freeze/clock", 0 );
FGReplay *r = (FGReplay *)(globals->get_subsystem( "replay" ));
fgSetDouble( "/sim/replay/start-time", r->get_start_time() );
fgSetDouble( "/sim/replay/end-time", r->get_end_time() );
double duration = fgGetDouble( "/sim/replay/duration" );
if( duration && duration < (r->get_end_time() - r->get_start_time()) ) {
fgSetDouble( "/sim/replay/time", r->get_end_time() - duration );
} else {
fgSetDouble( "/sim/replay/time", r->get_start_time() );
}
fgSetDouble( "/sim/replay/time", -1 );
// cout << "start = " << r->get_start_time()
// << " end = " << r->get_end_time() << endl;
@ -1301,11 +1222,20 @@ do_load_xml_to_proptree(const SGPropertyNode * arg)
if (file.extension() != "xml")
file.concat(".xml");
if (file.isRelative()) {
file = globals->resolve_maybe_aircraft_path(file.str());
std::string icao = arg->getStringValue("icao");
if (icao.empty()) {
if (file.isRelative()) {
file = globals->resolve_maybe_aircraft_path(file.str());
}
} else {
if (!XMLLoader::findAirportData(icao, file.str(), file)) {
SG_LOG(SG_IO, SG_INFO, "loadxml: failed to find airport data for "
<< file.str() << " at ICAO:" << icao);
return false;
}
}
if (!fgValidatePath(file.c_str(), false)) {
SG_LOG(SG_IO, SG_ALERT, "loadxml: reading '" << file.str() << "' denied "
"(unauthorized access)");
@ -1442,6 +1372,7 @@ static struct {
{ "reinit", do_reinit },
{ "suspend", do_reinit },
{ "resume", do_reinit },
{ "pause", do_pause },
{ "load", do_load },
{ "save", do_save },
{ "panel-load", do_panel_load },
@ -1457,7 +1388,6 @@ static struct {
{ "set-dewpoint-sea-level-air-temp-degc", do_set_dewpoint_sea_level_degc },
{ "set-dewpoint-temp-degc", do_set_dewpoint_degc },
*/
{ "timeofday", do_timeofday },
{ "property-toggle", do_property_toggle },
{ "property-assign", do_property_assign },
{ "property-adjust", do_property_adjust },

View file

@ -46,6 +46,7 @@
#include <Network/atlas.hxx>
#include <Network/AV400.hxx>
#include <Network/AV400Sim.hxx>
#include <Network/AV400WSim.hxx>
#include <Network/garmin.hxx>
#include <Network/httpd.hxx>
#ifdef FG_JPEG_SERVER
@ -64,7 +65,7 @@
#include <Network/ray.hxx>
#include <Network/rul.hxx>
#include <Network/generic.hxx>
#include <Network/multiplay.hxx>
#ifdef FG_HAVE_HLA
#include <Network/HLA/hla.hxx>
#endif
@ -142,7 +143,13 @@ FGIO::parse_port_config( const string& config )
} else if ( protocol == "AV400Sim" ) {
FGAV400Sim *av400sim = new FGAV400Sim;
io = av400sim;
} else if ( protocol == "garmin" ) {
} else if ( protocol == "AV400WSimA" ) {
FGAV400WSimA *av400wsima = new FGAV400WSimA;
io = av400wsima;
} else if ( protocol == "AV400WSimB" ) {
FGAV400WSimB *av400wsimb = new FGAV400WSimB;
io = av400wsimb;
} else if ( protocol == "garmin" ) {
FGGarmin *garmin = new FGGarmin;
io = garmin;
} else if ( protocol == "httpd" ) {
@ -212,10 +219,23 @@ FGIO::parse_port_config( const string& config )
return NULL;
}
string dir = tokens[1];
string rate = tokens[2];
int rate = atoi(tokens[2].c_str());
string host = tokens[3];
string port = tokens[4];
return new FGMultiplay(dir, atoi(rate.c_str()), host, atoi(port.c_str()));
short port = atoi(tokens[4].c_str());
// multiplay used to be handled by an FGProtocol, but no longer. This code
// retains compatability with existing command-line syntax
fgSetInt("/sim/multiplay/tx-rate-hz", rate);
if (dir == "in") {
fgSetInt("/sim/multiplay/rxport", port);
fgSetString("/sim/multiplay/rxhost", host.c_str());
} else if (dir == "out") {
fgSetInt("/sim/multiplay/txport", port);
fgSetString("/sim/multiplay/txhost", host.c_str());
}
return NULL;
#ifdef FG_HAVE_HLA
} else if ( protocol == "hla" ) {
return new FGHLA(tokens);
@ -263,6 +283,17 @@ FGIO::parse_port_config( const string& config )
SGSerial *ch = new SGSerial( device, baud );
io->set_io_channel( ch );
if ( protocol == "AV400WSimB" ) {
if ( tokens.size() < 7 ) {
SG_LOG( SG_IO, SG_ALERT, "Missing second hz for AV400WSimB.");
return NULL;
}
FGAV400WSimB *fgavb = static_cast<FGAV400WSimB*>(io);
string hz2_str = tokens[6];
double hz2 = atof(hz2_str.c_str());
fgavb->set_hz2(hz2);
}
} else if ( medium == "file" ) {
// file name
if ( tokens.size() < 4) {
@ -325,20 +356,20 @@ FGIO::init()
// appropriate FGIOChannel structures
string_list::iterator i = globals->get_channel_options_list()->begin();
string_list::iterator end = globals->get_channel_options_list()->end();
for (; i != end; ++i )
{
p = parse_port_config( *i );
if ( p != NULL ) {
p->open();
io_channels.push_back( p );
if ( !p->is_enabled() ) {
SG_LOG( SG_IO, SG_ALERT, "I/O Channel config failed." );
exit(-1);
}
} else {
SG_LOG( SG_IO, SG_INFO, "I/O Channel parse failed." );
}
}
for (; i != end; ++i ) {
p = parse_port_config( *i );
if (!p) {
continue;
}
p->open();
if ( !p->is_enabled() ) {
SG_LOG( SG_IO, SG_ALERT, "I/O Channel config failed." );
delete p;
}
io_channels.push_back( p );
} // of channel options iteration
}
void

View file

@ -306,6 +306,7 @@ void fgWarpMouse(int x, int y)
void fgOSInit(int* argc, char** argv)
{
globals->get_renderer()->init();
WindowSystemAdapter::setWSA(new WindowSystemAdapter);
}

View file

@ -241,7 +241,8 @@ void FGGlobals::set_fg_scenery (const string &scenery)
string_list path_list = sgPathSplit( s.str() );
fg_scenery.clear();
SGPropertyNode* sim = fgGetNode("/sim", true);
for (unsigned i = 0; i < path_list.size(); i++) {
SGPath path(path_list[i]);
if (!path.exists()) {
@ -271,6 +272,12 @@ void FGGlobals::set_fg_scenery (const string &scenery)
// FG_SCENERY=A:B becomes list ["A/Terrain", "A/Objects", "",
// "B/Terrain", "B/Objects", ""]
fg_scenery.push_back("");
// make scenery dirs available to Nasal
sim->removeChild("fg-scenery", i, false);
SGPropertyNode* n = sim->getChild("fg-scenery", i, true);
n->setStringValue(path.str());
n->setAttribute(SGPropertyNode::WRITE, false);
} // of path list iteration
}

View file

@ -203,6 +203,7 @@ static void fgMainLoop( void ) {
if (globals->get_tile_mgr()->isSceneryLoaded()
&& fgGetBool("sim/fdm-initialized")) {
fgSetBool("sim/sceneryloaded",true);
fgSplashProgress("");
if (fgGetBool("/sim/sound/working")) {
globals->get_soundmgr()->activate();
}
@ -211,6 +212,7 @@ static void fgMainLoop( void ) {
}
else
{
fgSplashProgress("loading scenery");
// be nice to loader threads while waiting for initial scenery, reduce to 2fps
simgear::sleepForMSec(500);
}
@ -313,7 +315,7 @@ SGPath resolve_path(const std::string& s)
}
// This is the top level master main function that is registered as
// our idle funciton
// our idle function
// The first few passes take care of initialization things (a couple
// per pass) and once everything has been initialized fgMainLoop from
@ -347,20 +349,17 @@ static void fgIdleFunction ( void ) {
if (!guiFinishInit())
return;
idle_state++;
fgSplashProgress("reading aircraft list");
fgSplashProgress("loading aircraft list");
} else if ( idle_state == 2 ) {
idle_state++;
fgSplashProgress("reading airport & navigation data");
fgSplashProgress("loading navigation data");
} else if ( idle_state == 3 ) {
idle_state++;
fgInitNav();
fgSplashProgress("setting up scenery");
fgSplashProgress("initializing scenery system");
} else if ( idle_state == 4 ) {
idle_state++;
@ -385,14 +384,13 @@ static void fgIdleFunction ( void ) {
////////////////////////////////////////////////////////////////////
fgInitCommands();
////////////////////////////////////////////////////////////////////
// Initialize the material manager
////////////////////////////////////////////////////////////////////
globals->set_matlib( new SGMaterialLib );
simgear::SGModelLib::init(globals->get_fg_root(), globals->get_props());
simgear::SGModelLib::setPanelFunc(load_panel);
////////////////////////////////////////////////////////////////////
// Initialize the TG scenery subsystem.
////////////////////////////////////////////////////////////////////
@ -401,15 +399,12 @@ static void fgIdleFunction ( void ) {
globals->get_scenery()->bind();
globals->set_tile_mgr( new FGTileMgr );
fgSplashProgress("loading aircraft");
} else if ( idle_state == 5 ) {
idle_state++;
fgSplashProgress("generating sky elements");
fgSplashProgress("initializing sky elements");
} else if ( idle_state == 6 ) {
idle_state++;
@ -470,10 +465,8 @@ static void fgIdleFunction ( void ) {
// airport->setName( "Airport Lighting" );
// lighting->addKid( airport );
// build our custom render states
fgSplashProgress("initializing subsystems");
} else if ( idle_state == 7 ) {
idle_state++;
// Initialize audio support
@ -530,18 +523,18 @@ static void fgIdleFunction ( void ) {
fgSetPosFromAirportIDandHdg( apt, hdg );
}
}
fgSplashProgress("setting up time & renderer");
fgSplashProgress("initializing graphics engine");
} else if ( idle_state == 8 ) {
idle_state = 1000;
// setup OpenGL view parameters
globals->get_renderer()->init();
globals->get_renderer()->setupView();
globals->get_renderer()->resize( fgGetInt("/sim/startup/xsize"),
fgGetInt("/sim/startup/ysize") );
fgSplashProgress("loading scenery objects");
int session = fgGetInt("/sim/session",0);
session++;
fgSetInt("/sim/session",session);
@ -555,6 +548,10 @@ static void fgIdleFunction ( void ) {
}
}
static void fgWinResizeFunction(int width, int height)
{
globals->get_renderer()->resize(width, height);
}
static void upper_case_property(const char *name)
{
@ -644,7 +641,7 @@ int fgMainInit( int argc, char **argv ) {
fgOSInit(&argc, argv);
_bootstrap_OSInit++;
fgRegisterWindowResizeHandler( &FGRenderer::resize );
fgRegisterWindowResizeHandler( &fgWinResizeFunction );
fgRegisterIdleHandler( &fgIdleFunction );
fgRegisterDrawHandler( &FGRenderer::update );
@ -668,5 +665,3 @@ int fgMainInit( int argc, char **argv ) {
return result;
}

View file

@ -555,54 +555,6 @@ add_channel( const string& type, const string& channel_str ) {
return true;
}
// The parse wp and parse flight-plan options don't work anymore, because
// the route manager and the airport subsystems have not yet been initialized
// at this stage.
// Parse --wp=ID[@alt]
static void
parse_wp( const string& arg ) {
string_list *waypoints = globals->get_initial_waypoints();
if (!waypoints) {
waypoints = new string_list;
globals->set_initial_waypoints(waypoints);
}
waypoints->push_back(arg);
}
// Parse --flight-plan=[file]
static bool
parse_flightplan(const string& arg)
{
string_list *waypoints = globals->get_initial_waypoints();
if (!waypoints) {
waypoints = new string_list;
globals->set_initial_waypoints(waypoints);
}
sg_gzifstream in(arg.c_str());
if ( !in.is_open() )
return false;
while ( true ) {
string line;
getline( in, line, '\n' );
// catch extraneous (DOS) line ending character
if ( line[line.length() - 1] < 32 )
line = line.substr( 0, line.length()-1 );
if ( in.eof() )
break;
waypoints->push_back(line);
}
return true;
}
static int
fgOptLanguage( const char *arg )
{
@ -1067,14 +1019,12 @@ fgOptCeiling( const char *arg )
static int
fgOptWp( const char *arg )
{
parse_wp( arg );
return FG_OPTIONS_OK;
}
static int
fgOptFlightPlan( const char *arg )
{
parse_flightplan ( arg );
string_list *waypoints = globals->get_initial_waypoints();
if (!waypoints) {
waypoints = new string_list;
globals->set_initial_waypoints(waypoints);
}
waypoints->push_back(arg);
return FG_OPTIONS_OK;
}
@ -1467,6 +1417,8 @@ struct OptionDesc {
{"opengc", true, OPTION_CHANNEL, "", false, "", 0 },
{"AV400", true, OPTION_CHANNEL, "", false, "", 0 },
{"AV400Sim", true, OPTION_CHANNEL, "", false, "", 0 },
{"AV400WSimA", true, OPTION_CHANNEL, "", false, "", 0 },
{"AV400WSimB", true, OPTION_CHANNEL, "", false, "", 0 },
{"garmin", true, OPTION_CHANNEL, "", false, "", 0 },
{"nmea", true, OPTION_CHANNEL, "", false, "", 0 },
{"generic", true, OPTION_CHANNEL, "", false, "", 0 },
@ -1494,7 +1446,7 @@ struct OptionDesc {
{"turbulence", true, OPTION_FUNC, "", false, "", fgOptTurbulence },
{"ceiling", true, OPTION_FUNC, "", false, "", fgOptCeiling },
{"wp", true, OPTION_FUNC, "", false, "", fgOptWp },
{"flight-plan", true, OPTION_FUNC, "", false, "", fgOptFlightPlan },
{"flight-plan", true, OPTION_STRING, "/autopilot/route-manager/file-path", false, "", NULL },
{"config", true, OPTION_FUNC, "", false, "", fgOptConfig },
{"aircraft", true, OPTION_STRING, "/sim/aircraft", false, "", 0 },
{"vehicle", true, OPTION_STRING, "/sim/aircraft", false, "", 0 },
@ -1886,7 +1838,7 @@ fgUsage (bool verbose)
while ( t_str.size() > 47 ) {
unsigned int m = t_str.rfind(' ', 47);
string::size_type m = t_str.rfind(' ', 47);
msg += t_str.substr(0, m) + '\n';
msg.append( 32, ' ');

View file

@ -82,8 +82,6 @@
#include <simgear/screen/jpgfactory.hxx>
#endif
#include <simgear/environment/visual_enviro.hxx>
#include <Time/light.hxx>
#include <Time/light.hxx>
#include <Cockpit/panel.hxx>
@ -130,7 +128,7 @@ public:
hint->setMode(GL_DONT_CARE);
}
private:
SGSharedPtr<SGPropertyNode> mConfigNode;
SGPropertyNode_ptr mConfigNode;
};
@ -274,7 +272,7 @@ private:
class FGWireFrameModeUpdateCallback : public osg::StateAttribute::Callback {
public:
FGWireFrameModeUpdateCallback() :
mWireframe(fgGetNode("/sim/rendering/wireframe"))
mWireframe(fgGetNode("/sim/rendering/wireframe", true))
{ }
virtual void operator()(osg::StateAttribute* stateAttribute,
osg::NodeVisitor*)
@ -291,13 +289,13 @@ public:
osg::PolygonMode::FILL);
}
private:
SGSharedPtr<SGPropertyNode> mWireframe;
SGPropertyNode_ptr mWireframe;
};
class FGLightModelUpdateCallback : public osg::StateAttribute::Callback {
public:
FGLightModelUpdateCallback() :
mHighlights(fgGetNode("/sim/rendering/specular-highlight"))
mHighlights(fgGetNode("/sim/rendering/specular-highlight", true))
{ }
virtual void operator()(osg::StateAttribute* stateAttribute,
osg::NodeVisitor*)
@ -322,13 +320,13 @@ public:
}
}
private:
SGSharedPtr<SGPropertyNode> mHighlights;
SGPropertyNode_ptr mHighlights;
};
class FGFogEnableUpdateCallback : public osg::StateSet::Callback {
public:
FGFogEnableUpdateCallback() :
mFogEnabled(fgGetNode("/sim/rendering/fog"))
mFogEnabled(fgGetNode("/sim/rendering/fog", true))
{ }
virtual void operator()(osg::StateSet* stateSet, osg::NodeVisitor*)
{
@ -339,7 +337,7 @@ public:
}
}
private:
SGSharedPtr<SGPropertyNode> mFogEnabled;
SGPropertyNode_ptr mFogEnabled;
};
class FGFogUpdateCallback : public osg::StateAttribute::Callback {
@ -364,15 +362,18 @@ public:
assert(dynamic_cast<osg::Switch*>(node));
osg::Switch* sw = static_cast<osg::Switch*>(node);
double t = globals->get_sim_time_sec();
bool enabled = 0 < t;
bool enabled = scenery_enabled;
sw->setValue(0, enabled);
if (!enabled)
return;
traverse(node, nv);
}
static bool scenery_enabled;
};
bool FGScenerySwitchCallback::scenery_enabled = false;
// Sky structures
SGSky *thesky;
@ -411,10 +412,38 @@ FGRenderer::splashinit( void ) {
// visitor automatically.
mUpdateVisitor->setFrameStamp(mFrameStamp.get());
viewer->setUpdateVisitor(mUpdateVisitor.get());
fgSetDouble("/sim/startup/splash-alpha", 1.0);
}
void
FGRenderer::init( void )
{
_scenery_loaded = fgGetNode("/sim/sceneryloaded", true);
_scenery_override = fgGetNode("/sim/sceneryloaded-override", true);
_panel_hotspots = fgGetNode("/sim/panel-hotspots", true);
_virtual_cockpit = fgGetNode("/sim/virtual-cockpit", true);
_sim_delta_sec = fgGetNode("/sim/time/delta-sec", true);
_xsize = fgGetNode("/sim/startup/xsize", true);
_ysize = fgGetNode("/sim/startup/ysize", true);
_splash_alpha = fgGetNode("/sim/startup/splash-alpha", true);
_skyblend = fgGetNode("/sim/rendering/skyblend", true);
_point_sprites = fgGetNode("/sim/rendering/point-sprites", true);
_enhanced_lighting = fgGetNode("/sim/rendering/enhanced-lighting", true);
_distance_attenuation = fgGetNode("/sim/rendering/distance-attenuation", true);
_horizon_effect = fgGetNode("/sim/rendering/horizon-effect", true);
_textures = fgGetNode("/sim/rendering/textures", true);
_altitude_ft = fgGetNode("/position/altitude-ft", true);
_cloud_status = fgGetNode("/environment/clouds/status", true);
_visibility_m = fgGetNode("/environment/visibility-m", true);
}
void
FGRenderer::setupView( void )
{
osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
osg::initNotifyLevel();
@ -559,27 +588,42 @@ FGRenderer::init( void )
stateSet->setAttributeAndModes(new osg::Program, osg::StateAttribute::ON);
}
void
FGRenderer::update()
{
globals->get_renderer()->update(true);
}
// Update all Visuals (redraws anything graphics related)
void
FGRenderer::update( bool refresh_camera_settings ) {
bool scenery_loaded = fgGetBool("sim/sceneryloaded", false)
|| fgGetBool("sim/sceneryloaded-override");
if (!(_scenery_loaded->getBoolValue() ||
_scenery_override->getBoolValue()))
{
_splash_alpha->setDoubleValue(1.0);
return;
}
osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
if (!scenery_loaded) {
fgSetDouble("/sim/startup/splash-alpha", 1.0);
return;
if (_splash_alpha->getDoubleValue()>0.0)
{
// Fade out the splash screen
const double fade_time = 0.8;
const double fade_steps_per_sec = 20;
double delay_time = SGMiscd::min(fade_time/fade_steps_per_sec,
(SGTimeStamp::now() - _splash_time).toSecs());
_splash_time = SGTimeStamp::now();
double sAlpha = _splash_alpha->getDoubleValue();
sAlpha -= SGMiscd::max(0.0,delay_time/fade_time);
FGScenerySwitchCallback::scenery_enabled = (sAlpha<1.0);
_splash_alpha->setDoubleValue(sAlpha);
}
// Fade out the splash screen over the first three seconds.
double sAlpha = SGMiscd::max(0, (2.5 - globals->get_sim_time_sec()) / 2.5);
fgSetDouble("/sim/startup/splash-alpha", sAlpha);
bool skyblend = _skyblend->getBoolValue();
bool use_point_sprites = _point_sprites->getBoolValue();
bool enhanced_lighting = _enhanced_lighting->getBoolValue();
bool distance_attenuation = _distance_attenuation->getBoolValue();
bool skyblend = fgGetBool("/sim/rendering/skyblend");
bool use_point_sprites = fgGetBool("/sim/rendering/point-sprites");
bool enhanced_lighting = fgGetBool("/sim/rendering/enhanced-lighting");
bool distance_attenuation
= fgGetBool("/sim/rendering/distance-attenuation");
// OSGFIXME
SGConfigureDirectionalLights( use_point_sprites, enhanced_lighting,
distance_attenuation );
@ -588,10 +632,10 @@ FGRenderer::update( bool refresh_camera_settings ) {
// update fog params
double actual_visibility;
if (fgGetBool("/environment/clouds/status")) {
if (_cloud_status->getBoolValue()) {
actual_visibility = thesky->get_visibility();
} else {
actual_visibility = fgGetDouble("/environment/visibility-m");
actual_visibility = _visibility_m->getDoubleValue();
}
// idle_state is now 1000 meaning we've finished all our
@ -604,27 +648,27 @@ FGRenderer::update( bool refresh_camera_settings ) {
if ( refresh_camera_settings ) {
// update view port
resize( fgGetInt("/sim/startup/xsize"),
fgGetInt("/sim/startup/ysize") );
resize( _xsize->getIntValue(),
_ysize->getIntValue() );
}
osg::Camera *camera = viewer->getCamera();
if ( skyblend ) {
if ( fgGetBool("/sim/rendering/textures") ) {
if ( _textures->getBoolValue() ) {
SGVec4f clearColor(l->adj_fog_color());
camera->setClearColor(osg::Vec4(0.0, 0.0, 0.0, 1.0));
camera->setClearColor(toOsg(clearColor));
}
} else {
SGVec4f clearColor(l->sky_color());
camera->setClearColor(osg::Vec4(0.0, 0.0, 0.0, 1.0));
camera->setClearColor(toOsg(clearColor));
}
// update fog params if visibility has changed
double visibility_meters = fgGetDouble("/environment/visibility-m");
double visibility_meters = _visibility_m->getDoubleValue();
thesky->set_visibility(visibility_meters);
double altitude_m = fgGetDouble("/position/altitude-ft") * SG_FEET_TO_METER;
double altitude_m = _altitude_ft->getDoubleValue() * SG_FEET_TO_METER;
thesky->modify_vis( altitude_m, 0.0 /* time factor, now unused */);
// update the sky dome
@ -637,7 +681,7 @@ FGRenderer::update( bool refresh_camera_settings ) {
// Sun distance: 150,000,000 kilometers
double sun_horiz_eff, moon_horiz_eff;
if (fgGetBool("/sim/rendering/horizon-effect")) {
if (_horizon_effect->getBoolValue()) {
sun_horiz_eff
= 0.67 + pow(osg::clampAbove(0.5 + cos(l->get_sun_angle()),
0.0),
@ -668,7 +712,7 @@ FGRenderer::update( bool refresh_camera_settings ) {
scolor.sun_angle = l->get_sun_angle();
scolor.moon_angle = l->get_moon_angle();
double delta_time_sec = fgGetDouble("/sim/time/delta-sec");
double delta_time_sec = _sim_delta_sec->getDoubleValue();
thesky->reposition( sstate, *globals->get_ephem(), delta_time_sec );
thesky->repaint( scolor, *globals->get_ephem() );
@ -714,11 +758,10 @@ FGRenderer::update( bool refresh_camera_settings ) {
l->get_sun_angle()*SGD_RADIANS_TO_DEGREES);
mUpdateVisitor->setVisibility(actual_visibility);
simgear::GroundLightManager::instance()->update(mUpdateVisitor.get());
bool hotspots = fgGetBool("/sim/panel-hotspots");
osg::Node::NodeMask cullMask = ~simgear::LIGHTS_BITS & ~simgear::PICK_BIT;
cullMask |= simgear::GroundLightManager::instance()
->getLightNodeMask(mUpdateVisitor.get());
if (hotspots)
if (_panel_hotspots->getBoolValue())
cullMask |= simgear::PICK_BIT;
CameraGroup::getDefault()->setCameraCullMasks(cullMask);
}
@ -729,30 +772,34 @@ FGRenderer::update( bool refresh_camera_settings ) {
// Handle new window size or exposure
void
FGRenderer::resize( int width, int height ) {
int view_h;
if ( (!fgGetBool("/sim/virtual-cockpit"))
&& fgPanelVisible() && idle_state == 1000 ) {
view_h = (int)(height * (globals->get_current_panel()->getViewHeight() -
globals->get_current_panel()->getYOffset()) / 768.0);
} else {
view_h = height;
// the following breaks aspect-ratio of the main 3D scenery window when 2D panels are moved
// in y direction - causing issues for aircraft with 2D panels (/sim/virtual_cockpit=false).
// Disabling for now. Seems this useful for the pre-OSG time only.
// if ( (!_virtual_cockpit->getBoolValue())
// && fgPanelVisible() && idle_state == 1000 ) {
// view_h = (int)(height * (globals->get_current_panel()->getViewHeight() -
// globals->get_current_panel()->getYOffset()) / 768.0);
// }
int curWidth = _xsize->getIntValue(),
curHeight = _ysize->getIntValue();
if ((curHeight != height) || (curWidth != width)) {
// must guard setting these, or PLIB-PUI fails with too many live interfaces
_xsize->setIntValue(width);
_ysize->setIntValue(height);
}
static int lastwidth = 0;
static int lastheight = 0;
if (width != lastwidth)
fgSetInt("/sim/startup/xsize", lastwidth = width);
if (height != lastheight)
fgSetInt("/sim/startup/ysize", lastheight = height);
// must set view aspect ratio each frame, or initial values are wrong.
// should probably be fixed 'smarter' during view setup.
double aspect = height / (double) width;
// for all views
FGViewMgr *viewmgr = globals->get_viewmgr();
if (viewmgr) {
for ( int i = 0; i < viewmgr->size(); ++i ) {
viewmgr->get_view(i)->
set_aspect_ratio((float)view_h / (float)width);
}
for ( int i = 0; i < viewmgr->size(); ++i ) {
viewmgr->get_view(i)->set_aspect_ratio(aspect);
}
}
}

View file

@ -3,6 +3,8 @@
#define __FG_RENDERER_HXX 1
#include <simgear/scene/util/SGPickCallback.hxx>
#include <simgear/props/props.hxx>
#include <simgear/timing/timestamp.hxx>
#include <osg/ref_ptr>
@ -45,18 +47,20 @@ public:
void splashinit();
void init();
static void resize(int width, int height );
void setupView();
void resize(int width, int height );
// calling update( refresh_camera_settings = false ) will not
// touch window or camera settings. This is useful for the tiled
// renderer which needs to set the view frustum itself.
static void update( bool refresh_camera_settings );
inline static void update() { update( true ); }
void update( bool refresh_camera_settings);
static void update();
/** Just pick into the scene and return the pick callbacks on the way ...
*/
static bool pick( std::vector<SGSceneryPick>& pickList,
const osgGA::GUIEventAdapter* ea );
bool pick( std::vector<SGSceneryPick>& pickList,
const osgGA::GUIEventAdapter* ea );
/** Get and set the OSG Viewer object, if any.
*/
@ -76,6 +80,15 @@ public:
protected:
osg::ref_ptr<osgViewer::Viewer> viewer;
osg::ref_ptr<flightgear::FGEventHandler> eventHandler;
SGPropertyNode_ptr _scenery_loaded,_scenery_override;
SGPropertyNode_ptr _skyblend, _splash_alpha;
SGPropertyNode_ptr _point_sprites, _enhanced_lighting, _distance_attenuation;
SGPropertyNode_ptr _textures;
SGPropertyNode_ptr _cloud_status, _visibility_m;
SGPropertyNode_ptr _xsize, _ysize;
SGPropertyNode_ptr _panel_hotspots, _sim_delta_sec, _horizon_effect, _altitude_ft;
SGPropertyNode_ptr _virtual_cockpit;
SGTimeStamp _splash_time;
};
bool fgDumpSceneGraphToFile(const char* filename);

View file

@ -295,6 +295,7 @@ static osg::Node* fgCreateSplashCamera()
text->setPosition(osg::Vec3(0, -0.92, 0));
text->setAlignment(osgText::Text::CENTER_CENTER);
SGPropertyNode* prop = fgGetNode("/sim/startup/splash-progress-text", true);
prop->setStringValue("initializing");
text->setUpdateCallback(new FGSplashTextUpdateCallback(prop));
geode->addDrawable(text);

View file

@ -356,7 +356,7 @@ FGViewMgr::update (double dt)
abs_viewer_position = loop_view->getViewPosition();
// update audio listener values
// set the viewer posotion in Cartesian coordinates in meters
// set the viewer position in Cartesian coordinates in meters
smgr->set_position( abs_viewer_position, loop_view->getPosition() );
smgr->set_orientation( current_view_orientation );

View file

@ -164,7 +164,7 @@ struct FGExternalMotionData {
// the earth centered frame
SGVec3f angularAccel;
// The set of properties recieved for this timeslot
// The set of properties received for this timeslot
std::vector<FGPropertyData*> properties;
~FGExternalMotionData()

View file

@ -42,9 +42,11 @@
#include <simgear/props/props.hxx>
#include <AIModel/AIManager.hxx>
#include <AIModel/AIMultiplayer.hxx>
#include <Main/fg_props.hxx>
#include "multiplaymgr.hxx"
#include "mpmessages.hxx"
#include <FDM/flightProperties.hxx>
using namespace std;
@ -56,11 +58,18 @@ using namespace std;
const char sMULTIPLAYMGR_BID[] = "$Id$";
const char sMULTIPLAYMGR_HID[] = MULTIPLAYTXMGR_HID;
struct IdPropertyList {
unsigned id;
const char* name;
simgear::props::Type type;
};
static const IdPropertyList* findProperty(unsigned id);
// A static map of protocol property id values to property paths,
// This should be extendable dynamically for every specific aircraft ...
// For now only that static list
const FGMultiplayMgr::IdPropertyList
FGMultiplayMgr::sIdPropertyList[] = {
static const IdPropertyList sIdPropertyList[] = {
{100, "surface-positions/left-aileron-pos-norm", simgear::props::FLOAT},
{101, "surface-positions/right-aileron-pos-norm", simgear::props::FLOAT},
{102, "surface-positions/elevator-pos-norm", simgear::props::FLOAT},
@ -229,34 +238,33 @@ FGMultiplayMgr::sIdPropertyList[] = {
{10319, "sim/multiplay/generic/int[19]", simgear::props::INT}
};
const unsigned
FGMultiplayMgr::numProperties = (sizeof(FGMultiplayMgr::sIdPropertyList)
/ sizeof(FGMultiplayMgr::sIdPropertyList[0]));
const unsigned int numProperties = (sizeof(sIdPropertyList)
/ sizeof(sIdPropertyList[0]));
// Look up a property ID using binary search.
namespace
{
struct ComparePropertyId
{
bool operator()(const FGMultiplayMgr::IdPropertyList& lhs,
const FGMultiplayMgr::IdPropertyList& rhs)
bool operator()(const IdPropertyList& lhs,
const IdPropertyList& rhs)
{
return lhs.id < rhs.id;
}
bool operator()(const FGMultiplayMgr::IdPropertyList& lhs,
bool operator()(const IdPropertyList& lhs,
unsigned id)
{
return lhs.id < id;
}
bool operator()(unsigned id,
const FGMultiplayMgr::IdPropertyList& rhs)
const IdPropertyList& rhs)
{
return id < rhs.id;
}
};
};
}
const FGMultiplayMgr::IdPropertyList* FGMultiplayMgr::findProperty(unsigned id)
const IdPropertyList* findProperty(unsigned id)
{
std::pair<const IdPropertyList*, const IdPropertyList*> result
= std::equal_range(sIdPropertyList, sIdPropertyList + numProperties, id,
@ -276,8 +284,7 @@ namespace
const xdr_data_t* xdr = data;
while (xdr < end) {
unsigned id = XDR_decode_uint32(*xdr);
const FGMultiplayMgr::IdPropertyList* plist
= FGMultiplayMgr::findProperty(id);
const IdPropertyList* plist = findProperty(id);
if (plist) {
xdr++;
@ -336,6 +343,24 @@ namespace
return true;
}
}
class MPPropertyListener : public SGPropertyChangeListener
{
public:
MPPropertyListener(FGMultiplayMgr* mp) :
_multiplay(mp)
{
}
virtual void childAdded(SGPropertyNode*, SGPropertyNode*)
{
_multiplay->setPropertiesChanged();
}
private:
FGMultiplayMgr* _multiplay;
};
//////////////////////////////////////////////////////////////////////
//
// MultiplayMgr constructor
@ -343,9 +368,9 @@ namespace
//////////////////////////////////////////////////////////////////////
FGMultiplayMgr::FGMultiplayMgr()
{
mSocket = 0;
mInitialised = false;
mHaveServer = false;
mListener = NULL;
} // FGMultiplayMgr::FGMultiplayMgr()
//////////////////////////////////////////////////////////////////////
@ -356,7 +381,7 @@ FGMultiplayMgr::FGMultiplayMgr()
//////////////////////////////////////////////////////////////////////
FGMultiplayMgr::~FGMultiplayMgr()
{
Close();
} // FGMultiplayMgr::~FGMultiplayMgr()
//////////////////////////////////////////////////////////////////////
@ -375,22 +400,36 @@ FGMultiplayMgr::init (void)
SG_LOG(SG_NETWORK, SG_WARN, "FGMultiplayMgr::init - already initialised");
return;
}
fgSetBool("/sim/multiplay/online", false);
//////////////////////////////////////////////////
// Set members from property values
//////////////////////////////////////////////////
short rxPort = fgGetInt("/sim/multiplay/rxport");
string rxAddress = fgGetString("/sim/multiplay/rxhost");
short txPort = fgGetInt("/sim/multiplay/txport");
short txPort = fgGetInt("/sim/multiplay/txport", 5000);
string txAddress = fgGetString("/sim/multiplay/txhost");
int hz = fgGetInt("/sim/multiplay/tx-rate-hz", 10);
if (hz < 1) {
hz = 10;
}
mDt = 1.0 / hz;
mTimeUntilSend = 0.0;
mCallsign = fgGetString("/sim/multiplay/callsign");
if (txPort > 0 && !txAddress.empty()) {
if (!txAddress.empty()) {
mServer.set(txAddress.c_str(), txPort);
if (strncmp (mServer.getHost(), "0.0.0.0", 8) == 0) {
mHaveServer = false;
SG_LOG(SG_NETWORK, SG_DEBUG,
SG_LOG(SG_NETWORK, SG_WARN,
"FGMultiplayMgr - could not resolve '"
<< txAddress << "', Multiplayermode disabled");
return;
} else {
SG_LOG(SG_NETWORK, SG_INFO, "have server");
mHaveServer = true;
}
if (rxPort <= 0)
@ -408,11 +447,10 @@ FGMultiplayMgr::init (void)
SG_LOG(SG_NETWORK,SG_INFO,"FGMultiplayMgr::init-rxaddress="<<rxAddress );
SG_LOG(SG_NETWORK,SG_INFO,"FGMultiplayMgr::init-rxport= "<<rxPort);
SG_LOG(SG_NETWORK,SG_INFO,"FGMultiplayMgr::init-callsign= "<<mCallsign);
Close(); // Should Init be called twice, close Socket first
// A memory leak was reported here by valgrind
mSocket = new simgear::Socket();
mSocket.reset(new simgear::Socket());
if (!mSocket->open(false)) {
SG_LOG( SG_NETWORK, SG_DEBUG,
SG_LOG( SG_NETWORK, SG_WARN,
"FGMultiplayMgr::init - Failed to create data socket" );
return;
}
@ -424,6 +462,11 @@ FGMultiplayMgr::init (void)
return;
}
mPropertiesChanged = true;
mListener = new MPPropertyListener(this);
globals->get_props()->addChangeListener(mListener, false);
fgSetBool("/sim/multiplay/online", true);
mInitialised = true;
} // FGMultiplayMgr::init()
//////////////////////////////////////////////////////////////////////
@ -435,19 +478,39 @@ FGMultiplayMgr::init (void)
//
//////////////////////////////////////////////////////////////////////
void
FGMultiplayMgr::Close (void)
FGMultiplayMgr::shutdown (void)
{
mMultiPlayerMap.clear();
if (mSocket) {
fgSetBool("/sim/multiplay/online", false);
if (mSocket.get()) {
mSocket->close();
delete mSocket;
mSocket = 0;
mSocket.reset();
}
MultiPlayerMap::iterator it = mMultiPlayerMap.begin(),
end = mMultiPlayerMap.end();
for (; it != end; ++it) {
it->second->setDie(true);
}
mMultiPlayerMap.clear();
if (mListener) {
globals->get_props()->removeChangeListener(mListener);
delete mListener;
mListener = NULL;
}
mInitialised = false;
} // FGMultiplayMgr::Close(void)
//////////////////////////////////////////////////////////////////////
void
FGMultiplayMgr::reinit()
{
shutdown();
init();
}
//////////////////////////////////////////////////////////////////////
//
// Description: Sends the position data for the local position.
@ -757,7 +820,7 @@ FGMultiplayMgr::SendTextMessage(const string &MsgText)
//
//////////////////////////////////////////////////////////////////////
void
FGMultiplayMgr::update(double)
FGMultiplayMgr::update(double dt)
{
if (!mInitialised)
return;
@ -765,6 +828,14 @@ FGMultiplayMgr::update(double)
/// Just for expiry
long stamp = SGTimeStamp::now().getSeconds();
//////////////////////////////////////////////////
// Send if required
//////////////////////////////////////////////////
mTimeUntilSend -= dt;
if (mTimeUntilSend <= 0.0) {
Send();
}
//////////////////////////////////////////////////
// Read the receive socket and process any data
//////////////////////////////////////////////////
@ -813,7 +884,7 @@ FGMultiplayMgr::update(double)
<< "message has invalid protocol number!" );
break;
}
if (MsgHdr->MsgLen != bytes) {
if (static_cast<ssize_t>(MsgHdr->MsgLen) != bytes) {
SG_LOG(SG_NETWORK, SG_DEBUG, "FGMultiplayMgr::MP_ProcessData - "
<< "message from " << MsgHdr->Callsign << " has invalid length!");
break;
@ -854,6 +925,140 @@ FGMultiplayMgr::update(double)
} // FGMultiplayMgr::ProcessData(void)
//////////////////////////////////////////////////////////////////////
void
FGMultiplayMgr::Send()
{
using namespace simgear;
findProperties();
// smooth the send rate, by adjusting based on the 'remainder' time, which
// is how -ve mTimeUntilSend is. Watch for large values and ignore them,
// however.
if ((mTimeUntilSend < 0.0) && (fabs(mTimeUntilSend) < mDt)) {
mTimeUntilSend = mDt + mTimeUntilSend;
} else {
mTimeUntilSend = mDt;
}
double sim_time = globals->get_sim_time_sec();
static double lastTime = 0.0;
// SG_LOG(SG_GENERAL, SG_INFO, "actual dt=" << sim_time - lastTime);
lastTime = sim_time;
FlightProperties ifce;
// put together a motion info struct, you will get that later
// from FGInterface directly ...
FGExternalMotionData motionInfo;
// The current simulation time we need to update for,
// note that the simulation time is updated before calling all the
// update methods. Thus it contains the time intervals *end* time.
// The FDM is already run, so the states belong to that time.
motionInfo.time = sim_time;
motionInfo.lag = mDt;
// These are for now converted from lat/lon/alt and euler angles.
// But this should change in FGInterface ...
double lon = ifce.get_Longitude();
double lat = ifce.get_Latitude();
// first the aprioriate structure for the geodetic one
SGGeod geod = SGGeod::fromRadFt(lon, lat, ifce.get_Altitude());
// Convert to cartesion coordinate
motionInfo.position = SGVec3d::fromGeod(geod);
// The quaternion rotating from the earth centered frame to the
// horizontal local frame
SGQuatf qEc2Hl = SGQuatf::fromLonLatRad((float)lon, (float)lat);
// The orientation wrt the horizontal local frame
float heading = ifce.get_Psi();
float pitch = ifce.get_Theta();
float roll = ifce.get_Phi();
SGQuatf hlOr = SGQuatf::fromYawPitchRoll(heading, pitch, roll);
// The orientation of the vehicle wrt the earth centered frame
motionInfo.orientation = qEc2Hl*hlOr;
if (!globals->get_subsystem("flight")->is_suspended()) {
// velocities
motionInfo.linearVel = SG_FEET_TO_METER*SGVec3f(ifce.get_uBody(),
ifce.get_vBody(),
ifce.get_wBody());
motionInfo.angularVel = SGVec3f(ifce.get_P_body(),
ifce.get_Q_body(),
ifce.get_R_body());
// accels, set that to zero for now.
// Angular accelerations are missing from the interface anyway,
// linear accelerations are screwed up at least for JSBSim.
// motionInfo.linearAccel = SG_FEET_TO_METER*SGVec3f(ifce.get_U_dot_body(),
// ifce.get_V_dot_body(),
// ifce.get_W_dot_body());
motionInfo.linearAccel = SGVec3f::zeros();
motionInfo.angularAccel = SGVec3f::zeros();
} else {
// if the interface is suspendend, prevent the client from
// wild extrapolations
motionInfo.linearVel = SGVec3f::zeros();
motionInfo.angularVel = SGVec3f::zeros();
motionInfo.linearAccel = SGVec3f::zeros();
motionInfo.angularAccel = SGVec3f::zeros();
}
// now send the properties
PropertyMap::iterator it;
for (it = mPropertyMap.begin(); it != mPropertyMap.end(); ++it) {
FGPropertyData* pData = new FGPropertyData;
pData->id = it->first;
pData->type = it->second->getType();
switch (pData->type) {
case props::INT:
case props::LONG:
case props::BOOL:
pData->int_value = it->second->getIntValue();
break;
case props::FLOAT:
case props::DOUBLE:
pData->float_value = it->second->getFloatValue();
break;
case props::STRING:
case props::UNSPECIFIED:
{
// FIXME: We assume unspecified are strings for the moment.
const char* cstr = it->second->getStringValue();
int len = strlen(cstr);
if (len > 0)
{
pData->string_value = new char[len + 1];
strcpy(pData->string_value, cstr);
}
else
{
// Size 0 - ignore
pData->string_value = 0;
}
//cout << " Sending property " << pData->id << " " << pData->type << " " << pData->string_value << "\n";
break;
}
default:
// FIXME Currently default to a float.
//cout << "Unknown type when iterating through props: " << pData->type << "\n";
pData->float_value = it->second->getFloatValue();
break;
}
motionInfo.properties.push_back(pData);
}
SendMyPosition(motionInfo);
}
//////////////////////////////////////////////////////////////////////
//
// handle a position message
@ -1101,3 +1306,29 @@ FGMultiplayMgr::getMultiplayer(const std::string& callsign)
else
return 0;
}
void
FGMultiplayMgr::findProperties()
{
if (!mPropertiesChanged) {
return;
}
mPropertiesChanged = false;
for (unsigned i = 0; i < numProperties; ++i) {
const char* name = sIdPropertyList[i].name;
SGPropertyNode* pNode = globals->get_props()->getNode(name);
if (!pNode) {
continue;
}
int id = sIdPropertyList[i].id;
if (mPropertyMap.find(id) != mPropertyMap.end()) {
continue; // already activated
}
mPropertyMap[id] = pNode;
SG_LOG(SG_NETWORK, SG_DEBUG, "activating MP property:" << pNode->getPath());
}
}

View file

@ -31,48 +31,51 @@
#define MULTIPLAYTXMGR_HID "$Id$"
#include "mpmessages.hxx"
#include <string>
#include <vector>
#include <memory>
#include <simgear/compiler.h>
#include <simgear/props/props.hxx>
#include <Main/globals.hxx>
#include <simgear/io/raw_socket.hxx>
#include <simgear/structure/subsystem_mgr.hxx>
#include <AIModel/AIMultiplayer.hxx>
struct FGExternalMotionInfo;
struct FGExternalMotionData;
class MPPropertyListener;
struct T_MsgHdr;
class FGAIMultiplayer;
class FGMultiplayMgr : public SGSubsystem
{
public:
struct IdPropertyList {
unsigned id;
const char* name;
simgear::props::Type type;
};
static const IdPropertyList sIdPropertyList[];
static const unsigned numProperties;
static const IdPropertyList* findProperty(unsigned id);
public:
FGMultiplayMgr();
~FGMultiplayMgr();
virtual void init(void);
virtual void update(double dt);
void Close(void);
virtual void shutdown(void);
virtual void reinit();
// transmitter
void SendMyPosition(const FGExternalMotionData& motionInfo);
void SendTextMessage(const string &sMsgText);
// receiver
private:
friend class MPPropertyListener;
void setPropertiesChanged()
{
mPropertiesChanged = true;
}
void findProperties();
void Send();
void SendMyPosition(const FGExternalMotionData& motionInfo);
union MsgBuf;
FGAIMultiplayer* addMultiplayer(const std::string& callsign,
const std::string& modelName);
@ -87,11 +90,22 @@ private:
typedef std::map<std::string, SGSharedPtr<FGAIMultiplayer> > MultiPlayerMap;
MultiPlayerMap mMultiPlayerMap;
simgear::Socket* mSocket;
std::auto_ptr<simgear::Socket> mSocket;
simgear::IPAddress mServer;
bool mHaveServer;
bool mInitialised;
std::string mCallsign;
// Map between the property id's from the multiplayers network packets
// and the property nodes
typedef std::map<unsigned int, SGSharedPtr<SGPropertyNode> > PropertyMap;
PropertyMap mPropertyMap;
bool mPropertiesChanged;
MPPropertyListener* mListener;
double mDt; // reciprocal of /sim/multiplay/tx-rate-hz
double mTimeUntilSend;
};
#endif

1046
src/Network/AV400WSim.cxx Normal file

File diff suppressed because it is too large Load diff

144
src/Network/AV400WSim.hxx Normal file
View file

@ -0,0 +1,144 @@
// AV400Sim.hxx -- Garmin 400 series protocal class. This AV400Sim
// protocol generates the set of "simulator" commands a garmin 400
// series gps would expect as input in simulator mode. The AV400
// protocol generates the set of commands that a garmin 400 series gps
// would emit.
//
// Written by Curtis Olson, started Januar 2009.
//
// Copyright (C) 2009 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$
#ifndef _FG_AV400WSIM_HXX
#define _FG_AV400WSIM_HXX
#include <simgear/compiler.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include "protocol.hxx"
using std::string;
class FlightProperties;
//////////////////////////////////////////////////////////////////////////////
// Class FGAV400WSimA handles the input/output over the first serial port.
// This is very similar to the way previous Garmin non-WAAS models communicated
// but some items have been stripped out and just a minimal amount of
// info is necessary to be transmitted over this port.
class FGAV400WSimA : public FGProtocol {
char buf[ FG_MAX_MSG_SIZE ];
int length;
public:
FGAV400WSimA();
~FGAV400WSimA();
bool gen_message();
bool parse_message();
// open hailing frequencies
bool open();
// process work for this port
bool process();
// close the channel
bool close();
};
//////////////////////////////////////////////////////////////////////////////
// Class FGAV400WSimB handles the input/output over the second serial port
// which Garmin refers to as the "GPS Port". Some messages are handled on
// fixed cycle (usually 1 and 5 Hz) and some immediate responses are needed
// to certain messages upon requet by the GPS unit
class FGAV400WSimB : public FGProtocol {
char buf[ FG_MAX_MSG_SIZE ];
int length;
double hz2;
int hz2count;
int hz2cycles;
char flight_phase;
string hal;
string val;
string sbas_sel;
bool req_hostid;
bool req_raimap;
bool req_sbas;
int outputctr;
FlightProperties* fdm;
static const int SOM_SIZE = 2;
static const int DEG_TO_MILLIARCSECS = ( 60.0 * 60.0 * 1000 );
// Flight Phases
static const int PHASE_OCEANIC = 4;
static const int PHASE_ENROUTE = 5;
static const int PHASE_TERM = 6;
static const int PHASE_NONPREC = 7;
static const int PHASE_LNAVVNAV = 8;
static const int PHASE_LPVLP = 9;
public:
FGAV400WSimB();
~FGAV400WSimB();
bool gen_hostid_message();
bool gen_sbas_message();
bool gen_Wh_message();
bool gen_Wx_message();
bool gen_Wt_message();
bool gen_Wm_message();
bool gen_Wv_message();
bool verify_checksum( string message, int datachars );
string asciitize_message( string message );
string buffer_to_string();
bool parse_message();
// open hailing frequencies
bool open();
// process work for this port
bool process();
// close the channel
bool close();
inline double get_hz2() const { return hz2; }
inline void set_hz2( double t ) { hz2 = t, hz2cycles = get_hz() / hz2; }
};
#endif // _FG_AV400WSIM_HXX

View file

@ -6,6 +6,7 @@ set(SOURCES
ATC-Outputs.cxx
AV400.cxx
AV400Sim.cxx
AV400WSim.cxx
atlas.cxx
garmin.cxx
generic.cxx
@ -14,7 +15,6 @@ set(SOURCES
jpg-httpd.cxx
jsclient.cxx
lfsglass.cxx
multiplay.cxx
native.cxx
native_ctrls.cxx
native_fdm.cxx

View file

@ -9,8 +9,6 @@ else
JPEG_SERVER =
endif
MPLAYER_AS = multiplay.cxx multiplay.hxx
libNetwork_a_SOURCES = \
protocol.cxx protocol.hxx \
ATC-Main.cxx ATC-Main.hxx \
@ -19,6 +17,7 @@ libNetwork_a_SOURCES = \
atlas.cxx atlas.hxx \
AV400.cxx AV400.hxx \
AV400Sim.cxx AV400Sim.hxx \
AV400WSim.cxx AV400WSim.hxx \
garmin.cxx garmin.hxx \
lfsglass.cxx lfsglass.hxx lfsglass_data.hxx \
httpd.cxx httpd.hxx \
@ -32,7 +31,6 @@ libNetwork_a_SOURCES = \
net_ctrls.hxx net_fdm.hxx net_fdm_mini.hxx net_gui.hxx \
nmea.cxx nmea.hxx \
opengc.cxx opengc.hxx opengc_data.hxx \
$(MPLAYER_AS) \
props.cxx props.hxx \
pve.cxx pve.hxx \
ray.cxx ray.hxx \
@ -43,4 +41,4 @@ INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
if WITH_HLA
SUBDIRS = HLA
endif
endif

View file

@ -1,319 +0,0 @@
// multiplay.cxx -- protocol object for multiplay in Flightgear
//
// Written by Diarmuid Tyson, started February 2003.
// diarmuid.tyson@airservicesaustralia.com
//
// With addtions by Vivian Meazza, January 2006
//
// Copyright (C) 2003 Airservices Australia
//
// 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.
//
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <simgear/compiler.h>
#include <cstring>
#include <iostream>
#include <map>
#include <string>
#include <simgear/debug/logstream.hxx>
#include <simgear/math/SGMath.hxx>
#include <FDM/flightProperties.hxx>
#include <MultiPlayer/mpmessages.hxx>
#include "multiplay.hxx"
using std::string;
// These constants are provided so that the ident command can list file versions.
const char sFG_MULTIPLAY_BID[] = "$Id$";
const char sFG_MULTIPLAY_HID[] = FG_MULTIPLAY_HID;
typedef std::set<std::string> string_set;
class MPPropertyListener : public SGPropertyChangeListener
{
public:
MPPropertyListener(FGMultiplay* mp) :
_multiplay(mp)
{
}
virtual void childAdded(SGPropertyNode*, SGPropertyNode*)
{
_multiplay->setPropertiesChanged();
}
private:
FGMultiplay* _multiplay;
};
/******************************************************************
* Name: FGMultiplay
* Description: Constructor. Initialises the protocol and stores
* host and port information.
******************************************************************/
FGMultiplay::FGMultiplay (const string &dir, const int rate, const string &host, const int port) {
set_hz(rate);
set_direction(dir);
if (get_direction() == SG_IO_IN) {
fgSetInt("/sim/multiplay/rxport", port);
fgSetString("/sim/multiplay/rxhost", host.c_str());
} else if (get_direction() == SG_IO_OUT) {
fgSetInt("/sim/multiplay/txport", port);
fgSetString("/sim/multiplay/txhost", host.c_str());
}
mPropertiesChanged = true;
}
/******************************************************************
* Name: ~FGMultiplay
* Description: Destructor.
******************************************************************/
FGMultiplay::~FGMultiplay () {
}
/******************************************************************
* Name: open
* Description: Enables the protocol.
******************************************************************/
bool FGMultiplay::open() {
if ( is_enabled() ) {
SG_LOG( SG_IO, SG_ALERT, "This shouldn't happen, but the channel "
<< "is already in use, ignoring" );
return false;
}
set_enabled(true);
mPropertiesChanged = true;
MPPropertyListener* pl = new MPPropertyListener(this);
globals->get_props()->addChangeListener(pl, false);
return is_enabled();
}
void FGMultiplay::findProperties()
{
if (!mPropertiesChanged) {
return;
}
mPropertiesChanged = false;
for (unsigned i = 0; i < FGMultiplayMgr::numProperties; ++i) {
const char* name = FGMultiplayMgr::sIdPropertyList[i].name;
SGPropertyNode* pNode = globals->get_props()->getNode(name);
if (!pNode) {
continue;
}
int id = FGMultiplayMgr::sIdPropertyList[i].id;
if (mPropertyMap.find(id) != mPropertyMap.end()) {
continue; // already activated
}
mPropertyMap[id] = pNode;
SG_LOG(SG_NETWORK, SG_INFO, "activating MP property:" << pNode->getPath());
}
}
/******************************************************************
* Name: process
* Description: Prompts the multiplayer mgr to either send
* or receive data over the network
******************************************************************/
bool FGMultiplay::process() {
using namespace simgear;
if (get_direction() == SG_IO_OUT) {
findProperties();
// check if we have left initialization phase. That will not provide
// interresting data, also the freeze in simulation time hurts the
// multiplayer clients
double sim_time = globals->get_sim_time_sec();
// if (sim_time < 20)
// return true;
FlightProperties ifce;
// put together a motion info struct, you will get that later
// from FGInterface directly ...
FGExternalMotionData motionInfo;
// The current simulation time we need to update for,
// note that the simulation time is updated before calling all the
// update methods. Thus it contains the time intervals *end* time.
// The FDM is already run, so the states belong to that time.
motionInfo.time = sim_time;
// The typical lag will be the reciprocal of the output frequency
double hz = get_hz();
if (hz != 0) // I guess we can test a double for exact zero in this case
motionInfo.lag = 1/get_hz();
else
motionInfo.lag = 0.1; //??
// These are for now converted from lat/lon/alt and euler angles.
// But this should change in FGInterface ...
double lon = ifce.get_Longitude();
double lat = ifce.get_Latitude();
// first the aprioriate structure for the geodetic one
SGGeod geod = SGGeod::fromRadFt(lon, lat, ifce.get_Altitude());
// Convert to cartesion coordinate
motionInfo.position = SGVec3d::fromGeod(geod);
// The quaternion rotating from the earth centered frame to the
// horizontal local frame
SGQuatf qEc2Hl = SGQuatf::fromLonLatRad((float)lon, (float)lat);
// The orientation wrt the horizontal local frame
float heading = ifce.get_Psi();
float pitch = ifce.get_Theta();
float roll = ifce.get_Phi();
SGQuatf hlOr = SGQuatf::fromYawPitchRoll(heading, pitch, roll);
// The orientation of the vehicle wrt the earth centered frame
motionInfo.orientation = qEc2Hl*hlOr;
if (!globals->get_subsystem("flight")->is_suspended()) {
// velocities
motionInfo.linearVel = SG_FEET_TO_METER*SGVec3f(ifce.get_uBody(),
ifce.get_vBody(),
ifce.get_wBody());
motionInfo.angularVel = SGVec3f(ifce.get_P_body(),
ifce.get_Q_body(),
ifce.get_R_body());
// accels, set that to zero for now.
// Angular accelerations are missing from the interface anyway,
// linear accelerations are screwed up at least for JSBSim.
// motionInfo.linearAccel = SG_FEET_TO_METER*SGVec3f(ifce.get_U_dot_body(),
// ifce.get_V_dot_body(),
// ifce.get_W_dot_body());
motionInfo.linearAccel = SGVec3f::zeros();
motionInfo.angularAccel = SGVec3f::zeros();
} else {
// if the interface is suspendend, prevent the client from
// wild extrapolations
motionInfo.linearVel = SGVec3f::zeros();
motionInfo.angularVel = SGVec3f::zeros();
motionInfo.linearAccel = SGVec3f::zeros();
motionInfo.angularAccel = SGVec3f::zeros();
}
// now send the properties
PropertyMap::iterator it;
for (it = mPropertyMap.begin(); it != mPropertyMap.end(); ++it) {
FGPropertyData* pData = new FGPropertyData;
pData->id = it->first;
pData->type = it->second->getType();
switch (pData->type) {
case props::INT:
case props::LONG:
case props::BOOL:
pData->int_value = it->second->getIntValue();
break;
case props::FLOAT:
case props::DOUBLE:
pData->float_value = it->second->getFloatValue();
break;
case props::STRING:
case props::UNSPECIFIED:
{
// FIXME: We assume unspecified are strings for the moment.
const char* cstr = it->second->getStringValue();
int len = strlen(cstr);
if (len > 0)
{
pData->string_value = new char[len + 1];
strcpy(pData->string_value, cstr);
}
else
{
// Size 0 - ignore
pData->string_value = 0;
}
//cout << " Sending property " << pData->id << " " << pData->type << " " << pData->string_value << "\n";
break;
}
default:
// FIXME Currently default to a float.
//cout << "Unknown type when iterating through props: " << pData->type << "\n";
pData->float_value = it->second->getFloatValue();
break;
}
motionInfo.properties.push_back(pData);
}
FGMultiplayMgr* mpmgr = (FGMultiplayMgr*) globals->get_subsystem("mp");
mpmgr->SendMyPosition(motionInfo);
}
return true;
}
/******************************************************************
* Name: close
* Description: Closes the multiplayer mgrs to stop any further
* network processing
******************************************************************/
bool FGMultiplay::close()
{
mPropertyMap.clear();
FGMultiplayMgr* mgr = (FGMultiplayMgr*) globals->get_subsystem("mp");
if (mgr == 0) {
return false;
}
if (get_direction() == SG_IO_IN) {
mgr->Close();
} else if (get_direction() == SG_IO_OUT) {
mgr->Close();
}
return true;
}

View file

@ -1,97 +0,0 @@
// multiplay.hxx -- protocol object for multiplay in Flightgear
//
// Written by Diarmuid Tyson, started February 2003.
// diarmuid.tyson@airservicesaustralia.com
//
// With additions by Vivian Meazza, January 2006
//
// Copyright (C) 2003 Airservices Australia
//
// 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.
//
#ifndef _FG_MULTIPLAY_HXX
#define _FG_MULTIPLAY_HXX
#define FG_MULTIPLAY_HID "$Id$"
#include <simgear/compiler.h>
#include <string>
#include <simgear/props/props.hxx>
#include <Main/globals.hxx>
#include <Main/fg_props.hxx>
#include <Model/acmodel.hxx>
#include <MultiPlayer/multiplaymgr.hxx>
#include "protocol.hxx"
using std::string;
/****************************************************************
* @version $Id$
*
* Description: FGMultiplay is an FGProtocol object used as the basic
* interface for the multiplayer code into FlightGears generic IO
* subsystem. It only implements the basic FGProtocol methods: open(),
* process() and close(). It does not use Sim Gear's IO channels, as
* the MultiplayMgrs creates their own sockets through plib.
*
* It will set up it's direction and rate protocol properties when
* created. Subsequent calls to process will prompt the
* MultiplayMgr to either send or receive data over the network.
*
******************************************************************/
class FGMultiplay : public FGProtocol {
public:
/** Constructor */
FGMultiplay (const string &dir, const int rate, const string &host, const int port);
/** Destructor. */
~FGMultiplay ();
/** Enables the FGMultiplay object. */
bool open();
/** Tells the multiplayer_mgr to send/receive data.
*/
bool process();
/** Closes the multiplayer_mgr.
*/
bool close();
void setPropertiesChanged()
{
mPropertiesChanged = true;
}
private:
bool mPropertiesChanged;
void findProperties();
// Map between the property id's from the multiplayers network packets
// and the property nodes
typedef std::map<unsigned, SGSharedPtr<SGPropertyNode> > PropertyMap;
PropertyMap mPropertyMap;
};
#endif // _FG_MULTIPLAY_HXX

View file

@ -805,10 +805,19 @@ void FGNasalSys::update(double)
_context = naNewContext();
}
bool pathSortPredicate(const SGPath& p1, const SGPath& p2)
{
return p1.file() < p2.file();
}
// Loads all scripts in given directory
void FGNasalSys::loadScriptDirectory(simgear::Dir nasalDir)
{
simgear::PathList scripts = nasalDir.children(simgear::Dir::TYPE_FILE, ".nas");
// sort scripts, avoid loading sequence effects due to file system's
// random directory order
std::sort(scripts.begin(), scripts.end(), pathSortPredicate);
for (unsigned int i=0; i<scripts.size(); ++i) {
SGPath fullpath(scripts[i]);
SGPath file = fullpath.file();

View file

@ -80,7 +80,7 @@ FGSampleQueue::update (double dt)
last_volume = volume;
}
// process mesage queue
// process message queue
const string msgid = "Sequential Audio Message";
bool now_playing = false;
if ( exists( msgid ) ) {

View file

@ -35,16 +35,32 @@
#include <simgear/structure/event_mgr.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/timing/lowleveltime.h>
#include <simgear/structure/commands.hxx>
#include <Main/fg_props.hxx>
#include <Main/globals.hxx>
#include <Time/sunsolver.hxx>
static bool do_timeofday (const SGPropertyNode * arg)
{
const string &offset_type = arg->getStringValue("timeofday", "noon");
int offset = arg->getIntValue("offset", 0);
TimeManager* self = (TimeManager*) globals->get_subsystem("time");
if (offset_type == "real") {
// without this, setting 'real' time is a no-op, since the current
// wrap value (orig_warp) is retained in setTimeOffset. Ick.
fgSetInt("/sim/time/warp", 0);
}
self->setTimeOffset(offset_type, offset);
return true;
}
TimeManager::TimeManager() :
_inited(false),
_impl(NULL)
{
SGCommandMgr::instance()->addCommand("timeofday", do_timeofday);
}
void TimeManager::init()
@ -345,6 +361,14 @@ void TimeManager::updateLocalTime()
}
void TimeManager::initTimeOffset()
{
int offset = fgGetInt("/sim/startup/time-offset");
string offset_type = fgGetString("/sim/startup/time-offset-type");
setTimeOffset(offset_type, offset);
}
void TimeManager::setTimeOffset(const std::string& offset_type, int offset)
{
// Handle potential user specified time offsets
int orig_warp = _warp->getIntValue();
@ -355,8 +379,6 @@ void TimeManager::initTimeOffset()
sgTimeGetGMT( fgLocaltime(&cur_time, _impl->get_zonename() ) );
// Okay, we now have several possible scenarios
int offset = fgGetInt("/sim/startup/time-offset");
string offset_type = fgGetString("/sim/startup/time-offset-type");
double lon = _longitudeDeg->getDoubleValue() * SG_DEGREES_TO_RADIANS;
double lat = _latitudeDeg->getDoubleValue() * SG_DEGREES_TO_RADIANS;
int warp = 0;
@ -394,12 +416,12 @@ void TimeManager::initTimeOffset()
warp = offset - (aircraftLocalTime - currGMT)- cur_time;
} else {
SG_LOG( SG_GENERAL, SG_ALERT,
"TimeManager::initTimeOffset: unsupported offset: " << offset_type );
"TimeManager::setTimeOffset: unsupported offset: " << offset_type );
warp = 0;
}
_warp->setIntValue( orig_warp + warp );
SG_LOG( SG_GENERAL, SG_INFO, "After fgInitTimeOffset(): warp = "
SG_LOG( SG_GENERAL, SG_INFO, "After TimeManager::setTimeOffset(): warp = "
<< _warp->getIntValue() );
}

View file

@ -43,6 +43,8 @@ public:
// SGPropertyChangeListener overrides
virtual void valueChanged(SGPropertyNode *);
void setTimeOffset(const std::string& offset_type, int offset);
private:
/**

View file

@ -345,7 +345,7 @@ void FGLight::update_adj_fog_color () {
else
hor_rotation = fmod(hor_rotation, SGD_2PI);
// revert to unmodified values before usign them.
// revert to unmodified values before using them.
//
SGVec4f color = thesky->get_scene_color();
@ -359,7 +359,7 @@ void FGLight::update_adj_fog_color () {
float s_green = color[1]*color[1]*color[1];
float s_blue = color[2]*color[2];
// interpolate beween the sunrise/sunset color and the color
// interpolate between the sunrise/sunset color and the color
// at the opposite direction of this effect. Take in account
// the current visibility.
//

4
utils/fgpanel/.cvsignore Normal file
View file

@ -0,0 +1,4 @@
.deps
Makefile
Makefile.in
fgpanel

View file

@ -17,7 +17,12 @@
# include <config.h>
#endif
using namespace std;
#include "FGGLApplication.hxx"
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif
#include <map>
#include <algorithm>
#include "ApplicationProperties.hxx"
@ -93,7 +98,7 @@ inline bool FGFontCache::FntParamsLess::operator()(const FntParams& f1,
struct FGFontCache::fnt *
FGFontCache::getfnt(const char *name, float size, float slant)
{
string fontName(name);
std::string fontName(name);
FntParams fntParams(fontName, size, slant);
PuFontMap::iterator i = _puFonts.find(fntParams);
if (i != _puFonts.end())
@ -183,7 +188,7 @@ FGFontCache::getfntpath(const char *name)
bool FGFontCache::initializeFonts()
{
static string fontext("txf");
static std::string fontext("txf");
init();
ulDir* fontdir = ulOpenDir(_path.c_str());
if (!fontdir)
@ -195,7 +200,7 @@ bool FGFontCache::initializeFonts()
if (path.extension() == fontext) {
fntTexFont* f = new fntTexFont;
if (f->load((char *)path.c_str()))
_texFonts[string(dirEntry->d_name)] = f;
_texFonts[std::string(dirEntry->d_name)] = f;
else
delete f;
}

View file

@ -14,6 +14,7 @@
//
#ifndef __FGFONTCACHE_HXX
#define __FGFONTCACHE_HXX
#include <simgear/math/SGMath.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/props/props.hxx>
#include <plib/pu.h>
@ -55,8 +56,8 @@ private:
// Path to the font directory
SGPath _path;
typedef map<const string, fntTexFont*> TexFontMap;
typedef map<const FntParams, fnt*, FntParamsLess> PuFontMap;
typedef std::map<const std::string, fntTexFont*> TexFontMap;
typedef std::map<const FntParams, fnt*, FntParamsLess> PuFontMap;
TexFontMap _texFonts;
PuFontMap _puFonts;

View file

@ -15,9 +15,18 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "FGGLApplication.hxx"
#include "GL/gl.h"
#include "GL/glut.h"
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#define snprintf sprintf_s
#endif
#include <GL/gl.h>
#include <GL/glut.h>
#include <iostream>
#include <exception>

View file

@ -13,6 +13,13 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif
#include "FGPNGTextureLoader.hxx"
#include <GL/glu.h>

View file

@ -15,6 +15,16 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif
#include "FGGLApplication.hxx"
#include "FGPanelApplication.hxx"
#include <GL/gl.h>
#include <GL/glut.h>
@ -131,7 +141,7 @@ void FGPanelApplication::Init()
{
glAlphaFunc(GL_GREATER, 0.1);
glutSetCursor( GLUT_CURSOR_NONE );
ApplicationProperties::fontCache.initializeFonts();
ApplicationProperties::fontCache.initializeFonts();
}
void FGPanelApplication::Reshape( int width, int height )
@ -172,8 +182,7 @@ void FGPanelApplication::Key( unsigned char key, int x, int y )
{
switch( key ) {
case 0x1b:
if( gameMode ) glutLeaveGameMode();
else glutDestroyWindow( windowId );
exit(0);
break;
}
}
@ -226,7 +235,11 @@ double FGPanelApplication::Sleep()
double elapsed_us = (current_time_stamp - last_time_stamp).toUSecs();
if ( elapsed_us < frame_us ) {
double requested_us = frame_us - elapsed_us;
#ifdef _WIN32
::Sleep ((int)(requested_us / 1000.0)) ;
#else
usleep ( (useconds_t)(requested_us ) ) ;
#endif
}
// busy wait timing loop.
//

View file

@ -21,6 +21,7 @@
#include "FGGLApplication.hxx"
#include "FGPanelProtocol.hxx"
#include <simgear/math/SGMath.hxx>
#include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/props/props.hxx>

View file

@ -15,6 +15,18 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif
#ifdef WIN32
#define strtof strtod
#endif
#include "FGPanelProtocol.hxx"
#include "ApplicationProperties.hxx"
#include <simgear/io/sg_socket.hxx>

View file

@ -17,6 +17,7 @@
//
#ifndef __FGPANELPROTOCOL_HXX
#define __FGPANELPROTOCOL_HXX
#include <simgear/math/SGMath.hxx>
#include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/props/props.hxx>
#include <simgear/io/iochannel.hxx>

View file

@ -17,6 +17,14 @@
// Reader for sgi's .rgb format.
// specification can be found at http://local.wasp.uwa.edu.au/~pbourke/dataformats/sgirgb/sgiversion.html
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif
#include "FGRGBTextureLoader.hxx"
#include <GL/gl.h>
#include <GL/glu.h>

View file

@ -36,6 +36,7 @@
#include <plib/fnt.h>
#include <simgear/debug/logstream.hxx>
#include <simgear/math/SGMath.hxx>
#include <simgear/misc/sg_path.hxx>
#include "panel.hxx"

View file

@ -29,6 +29,7 @@
#include <string.h> // for strcmp()
#include <simgear/compiler.h>
#include <simgear/math/SGMath.hxx>
#include <simgear/structure/exception.hxx>
#include <simgear/debug/logstream.hxx>
#include <simgear/misc/sg_path.hxx>

View file

@ -1 +1 @@
2.2.0
2.3.0