Merge branch 'next' into durk-atc
This commit is contained in:
commit
de1564d83e
80 changed files with 2854 additions and 1040 deletions
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
1
projects/VC90/fgpanel/.gitignore
vendored
Executable file
|
@ -0,0 +1 @@
|
|||
*.user
|
262
projects/VC90/fgpanel/fgpanel.vcproj
Executable file
262
projects/VC90/fgpanel/fgpanel.vcproj
Executable 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>
|
|
@ -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,20 +750,24 @@ 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_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_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;
|
||||
|
@ -792,7 +791,7 @@ void FGAIBallistic::Run(double dt) {
|
|||
//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;
|
||||
_speed_north_fps = _speed_east_fps = 0;
|
||||
} else
|
||||
dynamic_friction_force_lbs = (static_friction_force_lbs * 0.95);
|
||||
|
||||
|
@ -805,6 +804,8 @@ void FGAIBallistic::Run(double dt) {
|
|||
|
||||
}
|
||||
|
||||
} //endif
|
||||
|
||||
//acceleration = (force(lbsf)/mass(slugs))
|
||||
v_force_acc_fpss = v_force_lbs/_mass;
|
||||
normal_force_fpss = normal_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
|
||||
//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();
|
||||
|
|
|
@ -96,7 +96,7 @@ 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 getRelBrgHitchToUser() const;
|
||||
|
|
|
@ -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") ) );
|
||||
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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -16,6 +16,7 @@ set(SOURCES
|
|||
ridge_lift.cxx
|
||||
terrainsampler.cxx
|
||||
presets.cxx
|
||||
gravity.cxx
|
||||
)
|
||||
|
||||
flightgear_component(Environment "${SOURCES}")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -31,8 +31,6 @@
|
|||
#include <cmath>
|
||||
#include <utility>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/**
|
||||
* Model the atmosphere in a way consistent with the laws
|
||||
* of physics.
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
89
src/Environment/gravity.cxx
Normal file
89
src/Environment/gravity.cxx
Normal 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
|
43
src/Environment/gravity.hxx
Normal file
43
src/Environment/gravity.hxx
Normal 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
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -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" );
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,7 +344,16 @@ 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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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")
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
#include <cstring>
|
||||
#include <simgear/math/SGMathFwd.hxx> // for SGVec3d
|
||||
#include <simgear/math/SGMisc.hxx>
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -85,6 +85,7 @@ private:
|
|||
double _drawRangeNm;
|
||||
double _upHeading; // true heading corresponding to +ve y-axis
|
||||
bool _magneticHeadings;
|
||||
bool _hasPanned;
|
||||
|
||||
SGGeod _projectionCenter;
|
||||
SGGeod _aircraft;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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")),
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,15 +378,22 @@ 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));
|
||||
|
||||
update_weather();
|
||||
|
||||
|
||||
osg::DrawArrays *quadPSet
|
||||
= static_cast<osg::DrawArrays*>(_geom->getPrimitiveSet(0));
|
||||
quadPSet->set(osg::PrimitiveSet::QUADS, 0, _vertices->size());
|
||||
quadPSet->dirty();
|
||||
|
||||
if (_display_mode == ARC) {
|
||||
// erase what is out of sight of antenna
|
||||
/*
|
||||
|\ /|
|
||||
|
@ -398,13 +404,6 @@ wxRadarBg::update (double delta_time_sec)
|
|||
| |
|
||||
---------
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
|
@ -418,6 +417,7 @@ wxRadarBg::update (double delta_time_sec)
|
|||
_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,
|
||||
|
@ -444,25 +444,33 @@ wxRadarBg::update (double delta_time_sec)
|
|||
for (int i = 0; i < 3 * 4; i++)
|
||||
_texCoords->push_back(whiteSpot);
|
||||
|
||||
trimaskPSet->set(osg::PrimitiveSet::TRIANGLES, firstQuadVert + 4, 3 * 4);
|
||||
trimaskPSet->set(osg::PrimitiveSet::TRIANGLES, firstQuadVert, 3 * 4);
|
||||
|
||||
} else {
|
||||
} else
|
||||
{
|
||||
maskPSet->set(osg::PrimitiveSet::QUADS, 0, 0);
|
||||
trimaskPSet->set(osg::PrimitiveSet::TRIANGLES, 0, 0);
|
||||
}
|
||||
|
||||
maskPSet->dirty();
|
||||
trimaskPSet->dirty();
|
||||
}
|
||||
#endif
|
||||
|
||||
// draw without mask
|
||||
_vertices->clear();
|
||||
_texCoords->clear();
|
||||
// remember index of next vertex
|
||||
int vIndex = _vertices->size();
|
||||
|
||||
update_weather();
|
||||
|
||||
osg::DrawArrays *quadPSet
|
||||
= static_cast<osg::DrawArrays*>(_geom->getPrimitiveSet(0));
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -91,12 +91,13 @@ WindowBuilder::makeDefaultTraits(bool stencil)
|
|||
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;
|
||||
|
|
|
@ -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;
|
||||
|
@ -1302,9 +1223,18 @@ do_load_xml_to_proptree(const SGPropertyNode * arg)
|
|||
if (file.extension() != "xml")
|
||||
file.concat(".xml");
|
||||
|
||||
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 "
|
||||
|
@ -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 },
|
||||
|
|
|
@ -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,6 +143,12 @@ FGIO::parse_port_config( const string& config )
|
|||
} else if ( protocol == "AV400Sim" ) {
|
||||
FGAV400Sim *av400sim = new FGAV400Sim;
|
||||
io = av400sim;
|
||||
} 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;
|
||||
|
@ -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 )
|
||||
{
|
||||
for (; i != end; ++i ) {
|
||||
p = parse_port_config( *i );
|
||||
if ( p != NULL ) {
|
||||
if (!p) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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." );
|
||||
}
|
||||
delete p;
|
||||
}
|
||||
|
||||
io_channels.push_back( p );
|
||||
} // of channel options iteration
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -306,6 +306,7 @@ void fgWarpMouse(int x, int y)
|
|||
|
||||
void fgOSInit(int* argc, char** argv)
|
||||
{
|
||||
globals->get_renderer()->init();
|
||||
WindowSystemAdapter::setWSA(new WindowSystemAdapter);
|
||||
}
|
||||
|
||||
|
|
|
@ -241,6 +241,7 @@ 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]);
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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,7 +384,6 @@ static void fgIdleFunction ( void ) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
fgInitCommands();
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Initialize the material manager
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
string_list *waypoints = globals->get_initial_waypoints();
|
||||
if (!waypoints) {
|
||||
waypoints = new string_list;
|
||||
globals->set_initial_waypoints(waypoints);
|
||||
}
|
||||
|
||||
static int
|
||||
fgOptFlightPlan( const char *arg )
|
||||
{
|
||||
parse_flightplan ( arg );
|
||||
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, ' ');
|
||||
|
||||
|
|
|
@ -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");
|
||||
osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
|
||||
if (!scenery_loaded) {
|
||||
fgSetDouble("/sim/startup/splash-alpha", 1.0);
|
||||
if (!(_scenery_loaded->getBoolValue() ||
|
||||
_scenery_override->getBoolValue()))
|
||||
{
|
||||
_splash_alpha->setDoubleValue(1.0);
|
||||
return;
|
||||
}
|
||||
osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
|
||||
|
||||
// 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);
|
||||
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);
|
||||
}
|
||||
|
||||
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,29 +772,33 @@ 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);
|
||||
viewmgr->get_view(i)->set_aspect_ratio(aspect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,17 +47,19 @@ 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,
|
||||
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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
fgSetBool("/sim/multiplay/online", false);
|
||||
|
||||
if (mSocket.get()) {
|
||||
mSocket->close();
|
||||
mSocket.reset();
|
||||
}
|
||||
|
||||
MultiPlayerMap::iterator it = mMultiPlayerMap.begin(),
|
||||
end = mMultiPlayerMap.end();
|
||||
for (; it != end; ++it) {
|
||||
it->second->setDie(true);
|
||||
}
|
||||
mMultiPlayerMap.clear();
|
||||
|
||||
if (mSocket) {
|
||||
mSocket->close();
|
||||
delete mSocket;
|
||||
mSocket = 0;
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
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
1046
src/Network/AV400WSim.cxx
Normal file
File diff suppressed because it is too large
Load diff
144
src/Network/AV400WSim.hxx
Normal file
144
src/Network/AV400WSim.hxx
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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();
|
||||
|
|
|
@ -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 ) ) {
|
||||
|
|
|
@ -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() );
|
||||
}
|
||||
|
|
|
@ -43,6 +43,8 @@ public:
|
|||
|
||||
// SGPropertyChangeListener overrides
|
||||
virtual void valueChanged(SGPropertyNode *);
|
||||
|
||||
void setTimeOffset(const std::string& offset_type, int offset);
|
||||
private:
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
4
utils/fgpanel/.cvsignore
Normal file
|
@ -0,0 +1,4 @@
|
|||
.deps
|
||||
Makefile
|
||||
Makefile.in
|
||||
fgpanel
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
@ -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.
|
||||
//
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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>
|
||||
|
|
2
version
2
version
|
@ -1 +1 @@
|
|||
2.2.0
|
||||
2.3.0
|
||||
|
|
Loading…
Reference in a new issue