1
0
Fork 0

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

This commit is contained in:
Erik Hofman 2010-11-30 13:35:18 +01:00
commit 2a674c76fa
12 changed files with 691 additions and 284 deletions

View file

@ -133,6 +133,30 @@ window, camera, or gui tags.
This specifies an orthographic view. The parameters are the sames as This specifies an orthographic view. The parameters are the sames as
the frustum node's. the frustum node's.
texture
This tag indicates that the camera renders to a texture instead of the
framebuffer. For now the following tags are supported, but obviously
different texture formats should be specified too.
name - string
The name of the texture. This can be referred to by other cameras.
width, height - double
The dimensions of the texture
panoramic-distortion
This tag cause the camera to create distortion geometry that
corrects for projection onto a spherical screen. It is equivalent to
the --panoramic-sd option to osgviewer.
texture - string
The name of a texture, created by another camera, that will be
rendered on the distortion correction geometry.
radius - double
Radius of string
collar - double
size of screen collar.
gui gui
This is a special camera node that displays the 2D GUI. This is a special camera node that displays the 2D GUI.
@ -313,3 +337,61 @@ accounted for.
</rendering> </rendering>
</sim> </sim>
</PropertyList> </PropertyList>
This example renders the scene for projection onto a spherical screen.
<PropertyList>
<sim>
<rendering>
<camera-group>
<camera>
<window>
<name type="string">main</name>
<host-name type="string"></host-name>
<display>0</display>
<screen>0</screen>
<!-- <fullscreen type = "bool">true</fullscreen>-->
<width>1024</width>
<height>768</height>
</window>
<view>
<heading-deg type = "double">0</heading-deg>
</view>
<frustum>
<top>0.133</top>
<bottom>-0.133</bottom>
<left>-.1668</left>
<right>.1668</right>
<near>0.4</near>
<far>120000.0</far>
</frustum>
<texture>
<name>mainview</name>
<width>1024</width>
<height>768</height>
</texture>
</camera>
<camera>
<window><name>main</name></window>
<ortho>
<top>768</top>
<bottom>0</bottom>
<left>0</left>
<right>1024</right>
<near>-1.0</near>
<far>1.0</far>
</ortho>
<panoramic-spherical>
<texture>mainview</texture>
</panoramic-spherical>
</camera>
<gui>
<window>
<name type="string">main</name>
</window>
</gui>
</camera-group>
</rendering>
</sim>
</PropertyList>

View file

@ -152,11 +152,11 @@ bool FGAIBallistic::init(bool search_in_AI_path) {
props->setStringValue("contents/path", _contents_path.c_str()); props->setStringValue("contents/path", _contents_path.c_str());
} }
if(_parent != ""){ //if(_parent != ""){
setParentNode(); // setParentNode();
} //}
setParentNodes(_selected_ac); //setParentNodes(_selected_ac);
//props->setStringValue("vector/path", _vector_path.c_str()); //props->setStringValue("vector/path", _vector_path.c_str());
@ -168,7 +168,11 @@ bool FGAIBallistic::init(bool search_in_AI_path) {
Transform(); Transform();
//cout << _name << " speed init: " << speed << endl; if(_parent != ""){
setParentNode();
}
setParentNodes(_selected_ac);
return true; return true;
} }

View file

@ -215,13 +215,14 @@ bool FGAIWingman::init(bool search_in_AI_path) {
roll = _rotation; roll = _rotation;
_ht_agl_ft = 1e10; _ht_agl_ft = 1e10;
props->setStringValue("submodels/path", _path.c_str());
if(_parent != ""){ if(_parent != ""){
setParentNode(); setParentNode();
} }
setParentNodes(_selected_ac); setParentNodes(_selected_ac);
props->setStringValue("submodels/path", _path.c_str());
user_WoW_node = fgGetNode("gear/gear[1]/wow", true);
return true; return true;
} }
@ -277,7 +278,7 @@ double FGAIWingman::calcAngle(double range, SGGeod pos1, SGGeod pos2){
void FGAIWingman::formateToAC(double dt){ void FGAIWingman::formateToAC(double dt){
double p_hdg, p_pch, p_rll, p_agl, p_ht = 0; double p_hdg, p_pch, p_rll, p_agl, p_ht, p_wow = 0;
setTgtOffsets(dt, 25); setTgtOffsets(dt, 25);
@ -312,8 +313,9 @@ void FGAIWingman::formateToAC(double dt){
double h_feet = 3 * factor; double h_feet = 3 * factor;
p_agl = manager->get_user_agl(); p_agl = manager->get_user_agl();
p_wow = user_WoW_node->getDoubleValue();
if(p_agl <= 10) { if(p_agl <= 10 || p_wow == 1) {
_height = p_ht; _height = p_ht;
//cout << "ht case1 " ; //cout << "ht case1 " ;
} else if (p_agl > 10 && p_agl <= 150 ) { } else if (p_agl > 10 && p_agl <= 150 ) {
@ -332,7 +334,8 @@ void FGAIWingman::formateToAC(double dt){
pos.setLongitudeDeg(_offsetpos.getLongitudeDeg()); pos.setLongitudeDeg(_offsetpos.getLongitudeDeg());
// these calculations are unreliable at slow speeds // these calculations are unreliable at slow speeds
if(speed >= 10) { // and we don't want random movement on the ground
if(speed >= 10 && p_wow != 1) {
setHdg(p_hdg + h_angle, dt, 0.9); setHdg(p_hdg + h_angle, dt, 0.9);
setPch(p_pch + p_angle + _pitch_offset, dt, 0.9); setPch(p_pch + p_angle + _pitch_offset, dt, 0.9);

View file

@ -67,7 +67,7 @@ private:
double _coeff_bnk; //dimensionless coefficient double _coeff_bnk; //dimensionless coefficient
double _coeff_spd; //dimensionless coefficient double _coeff_spd; //dimensionless coefficient
SGPropertyNode_ptr user_WoW_node;
inline void setFormate(bool f); inline void setFormate(bool f);
inline void setTgtHdg(double hdg); inline void setTgtHdg(double hdg);

View file

@ -7,6 +7,7 @@
// This file is in the Public Domain and comes with no warranty. // This file is in the Public Domain and comes with no warranty.
#include <simgear/compiler.h> #include <simgear/compiler.h>
#include <simgear/sg_inlines.h>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <sstream> #include <sstream>
@ -54,15 +55,26 @@ HeadingIndicatorDG::init ()
branch = "/instrumentation/" + name; branch = "/instrumentation/" + name;
_heading_in_node = fgGetNode("/orientation/heading-deg", true); _heading_in_node = fgGetNode("/orientation/heading-deg", true);
_yaw_rate_node = fgGetNode("/orientation/yaw-rate-degps", true);
_g_node = fgGetNode("/accelerations/pilot-g", true);
SGPropertyNode *node = fgGetNode(branch.c_str(), num, true ); SGPropertyNode *node = fgGetNode(branch.c_str(), num, true );
_offset_node = node->getChild("offset-deg", 0, true); _offset_node = node->getChild("offset-deg", 0, true);
_serviceable_node = node->getChild("serviceable", 0, true); _serviceable_node = node->getChild("serviceable", 0, true);
_error_node = node->getChild("heading-bug-error-deg", 0, true); _heading_bug_error_node = node->getChild("heading-bug-error-deg", 0, true);
_error_node = node->getChild("error-deg", 0, true);
_nav1_error_node = node->getChild("nav1-course-error-deg", 0, true); _nav1_error_node = node->getChild("nav1-course-error-deg", 0, true);
_heading_out_node = node->getChild("indicated-heading-deg", 0, true); _heading_out_node = node->getChild("indicated-heading-deg", 0, true);
_last_heading_deg = (_heading_in_node->getDoubleValue() + _align_node = node->getChild("align-deg", 0, true);
_offset_node->getDoubleValue());
_electrical_node = fgGetNode("/systems/electrical/outputs/DG", true); _electrical_node = fgGetNode("/systems/electrical/outputs/DG", true);
_align_node->setDoubleValue(0);
_error_node->setDoubleValue(0);
_last_heading_deg = (_heading_in_node->getDoubleValue() +
_offset_node->getDoubleValue() + _align_node->getDoubleValue());
} }
void void
@ -100,11 +112,30 @@ HeadingIndicatorDG::update (double dt)
_gyro.update(dt); _gyro.update(dt);
double spin = _gyro.get_spin_norm(); double spin = _gyro.get_spin_norm();
// No time-based precession for a flux gate compass // Next, calculate time-based precession
// No magvar double offset = _offset_node->getDoubleValue();
double offset = 0; offset -= dt * (0.25 / 60.0); // 360deg/day
SG_NORMALIZE_RANGE(offset, -360.0, 360.0);
_offset_node->setDoubleValue(offset);
// TODO: movement-induced error // No magvar - set the alignment manually
double align = _align_node->getDoubleValue();
// Movement-induced error
double yaw_rate = _yaw_rate_node->getDoubleValue();
double error = _error_node->getDoubleValue();
double g = _g_node->getDoubleValue();
int sign = 0;
if ( fabs ( yaw_rate ) > 5 ) {
error += 0.033 * -yaw_rate * dt ;
}
if ( g > 1.5 || g < -0.5){
error += 0.033 * g * dt;
}
_error_node->setDoubleValue(error);
// Next, calculate the indicated heading, // Next, calculate the indicated heading,
// introducing errors. // introducing errors.
@ -122,11 +153,8 @@ HeadingIndicatorDG::update (double dt)
heading = fgGetLowPass(_last_heading_deg, heading, dt * factor); heading = fgGetLowPass(_last_heading_deg, heading, dt * factor);
_last_heading_deg = heading; _last_heading_deg = heading;
heading += offset; heading += offset + align + error;
while (heading < 0) SG_NORMALIZE_RANGE(heading, 0.0, 360.0);
heading += 360;
while (heading > 360)
heading -= 360;
_heading_out_node->setDoubleValue(heading); _heading_out_node->setDoubleValue(heading);
@ -138,7 +166,7 @@ HeadingIndicatorDG::update (double dt)
double diff = bnode->getDoubleValue() - heading; double diff = bnode->getDoubleValue() - heading;
if ( diff < -180.0 ) { diff += 360.0; } if ( diff < -180.0 ) { diff += 360.0; }
if ( diff > 180.0 ) { diff -= 360.0; } if ( diff > 180.0 ) { diff -= 360.0; }
_error_node->setDoubleValue( diff ); _heading_bug_error_node->setDoubleValue( diff );
} }
// calculate the difference between the indicated heading // calculate the difference between the indicated heading
// and the selected nav1 radial for use with an autopilot // and the selected nav1 radial for use with an autopilot
@ -152,4 +180,4 @@ HeadingIndicatorDG::update (double dt)
} }
} }
// end of heading_indicator_fg.cxx // end of heading_indicator_dg.cxx

View file

@ -10,6 +10,7 @@
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
#include <simgear/structure/subsystem_mgr.hxx> #include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/math/sg_random.h>
#include "gyro.hxx" #include "gyro.hxx"
@ -59,6 +60,10 @@ private:
SGPropertyNode_ptr _electrical_node; SGPropertyNode_ptr _electrical_node;
SGPropertyNode_ptr _error_node; SGPropertyNode_ptr _error_node;
SGPropertyNode_ptr _nav1_error_node; SGPropertyNode_ptr _nav1_error_node;
SGPropertyNode_ptr _align_node;
SGPropertyNode_ptr _yaw_rate_node;
SGPropertyNode_ptr _heading_bug_error_node;
SGPropertyNode_ptr _g_node;
}; };
#endif // __INSTRUMENTS_HEADING_INDICATOR_ELEC_HXX #endif // __INSTRUMENTS_HEADING_INDICATOR_ELEC_HXX

View file

@ -20,6 +20,7 @@
#include "mrg.hxx" #include "mrg.hxx"
const double MasterReferenceGyro::gravity = -32.1740485564;
MasterReferenceGyro::MasterReferenceGyro ( SGPropertyNode *node ) : MasterReferenceGyro::MasterReferenceGyro ( SGPropertyNode *node ) :
_name(node->getStringValue("name", "master-reference-gyro")), _name(node->getStringValue("name", "master-reference-gyro")),
@ -43,7 +44,9 @@ MasterReferenceGyro::init ()
_indicated_hdg_rate = 0; _indicated_hdg_rate = 0;
_indicated_roll_rate = 0; _indicated_roll_rate = 0;
_indicated_pitch_rate = 0; _indicated_pitch_rate = 0;
_erect_time = 0; _erect_time = 180;
_last_g = 1;
_g_error = 10;
string branch; string branch;
branch = "/instrumentation/" + _name; branch = "/instrumentation/" + _name;
@ -55,6 +58,7 @@ MasterReferenceGyro::init ()
_pitch_rate_node = fgGetNode("/orientation/pitch-rate-degps", true); _pitch_rate_node = fgGetNode("/orientation/pitch-rate-degps", true);
_roll_rate_node = fgGetNode("/orientation/roll-rate-degps", true); _roll_rate_node = fgGetNode("/orientation/roll-rate-degps", true);
_yaw_rate_node = fgGetNode("/orientation/yaw-rate-degps", true); _yaw_rate_node = fgGetNode("/orientation/yaw-rate-degps", true);
//_g_in_node = fgGetNode("/accelerations/pilot/z-accel-fps_sec", true);
_g_in_node = fgGetNode("/accelerations/pilot-g", true); _g_in_node = fgGetNode("/accelerations/pilot-g", true);
_electrical_node = fgGetNode("/systems/electrical/outputs/MRG", true); _electrical_node = fgGetNode("/systems/electrical/outputs/MRG", true);
_hdg_mag_in_node = fgGetNode("/orientation/heading-magnetic-deg", true); _hdg_mag_in_node = fgGetNode("/orientation/heading-magnetic-deg", true);
@ -78,6 +82,7 @@ MasterReferenceGyro::init ()
_off_node->setBoolValue(false); _off_node->setBoolValue(false);
_hdg_input_source_node->setBoolValue(false); _hdg_input_source_node->setBoolValue(false);
_fast_erect_node->setBoolValue(false); _fast_erect_node->setBoolValue(false);
_g_in_node->setDoubleValue(1);
} }
void void
@ -109,12 +114,22 @@ MasterReferenceGyro::unbind ()
void void
MasterReferenceGyro::update (double dt) MasterReferenceGyro::update (double dt)
{ {
//sanity check
if (!fgGetBool("/sim/fdm-initialized", false)) {
return;
}
double indicated_roll = 0; double indicated_roll = 0;
double indicated_pitch = 0; double indicated_pitch = 0;
double indicated_hdg = 0; double indicated_hdg = 0;
double indicated_roll_rate = 0; double indicated_roll_rate = 0;
double indicated_pitch_rate = 0; double indicated_pitch_rate = 0;
double indicated_hdg_rate = 0; double indicated_hdg_rate = 0;
double hdg = 0;
double erect_time_factor = 1;
const double erect_time = 180;
const double max_g_error = 10.0;
//Get the spin from the gyro //Get the spin from the gyro
_gyro.set_power_norm( _electrical_node->getDoubleValue()/24 ); _gyro.set_power_norm( _electrical_node->getDoubleValue()/24 );
@ -130,18 +145,19 @@ MasterReferenceGyro::update (double dt)
} }
// Get the input values // Get the input values
double hdg = _hdg_mag_in_node->getDoubleValue(); if(_hdg_input_source_node->getBoolValue()){
if(_hdg_input_source_node->getBoolValue())
hdg = _hdg_in_node->getDoubleValue(); hdg = _hdg_in_node->getDoubleValue();
} else {
hdg = _hdg_mag_in_node->getDoubleValue();
}
double roll = _roll_in_node->getDoubleValue(); double roll = _roll_in_node->getDoubleValue();
double pitch = _pitch_in_node->getDoubleValue(); double pitch = _pitch_in_node->getDoubleValue();
double g = _g_in_node->getDoubleValue()/* / gravity*/;
double roll_rate = _yaw_rate_node->getDoubleValue(); double roll_rate = _yaw_rate_node->getDoubleValue();
double pitch_rate = _yaw_rate_node->getDoubleValue(); double pitch_rate = _pitch_rate_node->getDoubleValue();
double yaw_rate = _yaw_rate_node->getDoubleValue(); double yaw_rate = _yaw_rate_node->getDoubleValue();
double g = _g_in_node->getDoubleValue();
//modulate the input by the spin rate //modulate the input by the spin rate
double responsiveness = spin * spin * spin * spin * spin * spin; double responsiveness = spin * spin * spin * spin * spin * spin;
@ -158,7 +174,7 @@ MasterReferenceGyro::update (double dt)
//but we need to filter the hdg and yaw_rate as well - yuk! //but we need to filter the hdg and yaw_rate as well - yuk!
responsiveness = 0.1 / (spin * spin * spin * spin * spin * spin); responsiveness = 0.1 / (spin * spin * spin * spin * spin * spin);
yaw_rate = fgGetLowPass( _last_yaw_rate , yaw_rate, responsiveness ); yaw_rate = fgGetLowPass( _last_yaw_rate , yaw_rate, responsiveness );
g = fgGetLowPass( _last_g , g, 0.015 ); g = fgGetLowPass( _last_g , g, 1.5);
// store the new values // store the new values
@ -170,38 +186,38 @@ MasterReferenceGyro::update (double dt)
_last_yaw_rate = yaw_rate; _last_yaw_rate = yaw_rate;
_last_g = g; _last_g = g;
if (_erect_time > 0){ //the gyro only erects inside limits
if ( fabs ( yaw_rate ) <= 5
&& g <= 1.5 && g >= -0.5){
if ( !_fast_erect_node->getBoolValue() ) if ( !_fast_erect_node->getBoolValue() ){
_erect_time -= dt; erect_time_factor = 1;
else } else {
_erect_time -= 2 * dt; erect_time_factor = 2;
}
_g_error -= (max_g_error/(erect_time * 0.33)) * dt * erect_time_factor;
} else {
_g_error += (max_g_error /(erect_time * 0.33)) * dt * 2;
//SG_LOG(SG_GENERAL, SG_ALERT,_num <<
// " g input " << _g_in_node->getDoubleValue() * gravity
// <<" _erect_time " << _erect_time
// << " yaw " << yaw_rate
// << " pitch " << _pitch_rate_node->getDoubleValue()
// << " roll " << _roll_rate_node->getDoubleValue());
} }
//SG_LOG(SG_GENERAL, SG_ALERT, //cout << "_g_error "<< _g_error << endl;
// "g input " << g <<" _erect_time " << _erect_time << " spin " << spin); _g_error = SGMiscd::clip(_g_error, 0, 10);
// cout << "_g_error clip "<< _g_error << endl;
//the gyro only erects inside limits indicated_roll = _last_roll + _g_error;
if ( fabs ( yaw_rate ) <= 5 indicated_pitch = _last_pitch + _g_error;
&& ( g <= 1.5 || g >= -0.5) indicated_hdg = _last_hdg + _g_error;
&& _erect_time <=0 ) {
indicated_roll = _last_roll;
indicated_pitch = _last_pitch;
indicated_hdg = _last_hdg;
indicated_roll_rate = _last_roll_rate; indicated_roll_rate = _last_roll_rate;
indicated_pitch_rate = _last_pitch_rate; indicated_pitch_rate = _last_pitch_rate;
indicated_hdg_rate = _last_yaw_rate; indicated_hdg_rate = _last_yaw_rate;
} else {
indicated_roll_rate = 0;
indicated_pitch_rate = 0;
indicated_hdg_rate = 0;
if (_erect_time <= 0 )
_erect_time = 34;
}
// calculate the difference between the indicated heading // calculate the difference between the indicated heading
// and the selected heading for use with an autopilot // and the selected heading for use with an autopilot
static SGPropertyNode *bnode static SGPropertyNode *bnode

View file

@ -49,6 +49,8 @@ public:
private: private:
static const double gravity; //conversion factor
string _name; string _name;
int _num; int _num;
@ -66,6 +68,7 @@ private:
double _last_yaw_rate; double _last_yaw_rate;
double _last_g; double _last_g;
double _erect_time; double _erect_time;
double _g_error;
Gyro _gyro; Gyro _gyro;

View file

@ -35,10 +35,15 @@
#include <string> #include <string>
#include <osg/Camera> #include <osg/Camera>
#include <osg/Geometry>
#include <osg/GraphicsContext> #include <osg/GraphicsContext>
#include <osg/io_utils>
#include <osg/Math> #include <osg/Math>
#include <osg/Matrix> #include <osg/Matrix>
#include <osg/Notify>
#include <osg/Program>
#include <osg/Quat> #include <osg/Quat>
#include <osg/TexMat>
#include <osg/Vec3d> #include <osg/Vec3d>
#include <osg/Viewport> #include <osg/Viewport>
@ -148,7 +153,18 @@ CameraInfo* CameraGroup::addCamera(unsigned flags, Camera* camera,
// resized; if the the viewport isn't copied here, it gets updated // resized; if the the viewport isn't copied here, it gets updated
// twice and ends up with the wrong value. // twice and ends up with the wrong value.
farCamera->setViewport(simgear::clone(camera->getViewport())); farCamera->setViewport(simgear::clone(camera->getViewport()));
_viewer->addSlave(farCamera, view, projection, useMasterSceneData); farCamera->setDrawBuffer(camera->getDrawBuffer());
farCamera->setReadBuffer(camera->getReadBuffer());
farCamera->setRenderTargetImplementation(
camera->getRenderTargetImplementation());
const Camera::BufferAttachmentMap& bufferMap
= camera->getBufferAttachmentMap();
if (bufferMap.count(Camera::COLOR_BUFFER) != 0) {
farCamera->attach(
Camera::COLOR_BUFFER,
bufferMap.find(Camera::COLOR_BUFFER)->second._texture);
}
_viewer->addSlave(farCamera, projection, view, useMasterSceneData);
installCullVisitor(farCamera); installCullVisitor(farCamera);
info->farCamera = farCamera; info->farCamera = farCamera;
info->farSlaveIndex = _viewer->getNumSlaves() - 1; info->farSlaveIndex = _viewer->getNumSlaves() - 1;
@ -156,7 +172,7 @@ CameraInfo* CameraGroup::addCamera(unsigned flags, Camera* camera,
camera->setCullMask(camera->getCullMask() & ~simgear::BACKGROUND_BIT); camera->setCullMask(camera->getCullMask() & ~simgear::BACKGROUND_BIT);
camera->setClearMask(GL_DEPTH_BUFFER_BIT); camera->setClearMask(GL_DEPTH_BUFFER_BIT);
} }
_viewer->addSlave(camera, view, projection, useMasterSceneData); _viewer->addSlave(camera, projection, view, useMasterSceneData);
installCullVisitor(camera); installCullVisitor(camera);
info->camera = camera; info->camera = camera;
info->slaveIndex = _viewer->getNumSlaves() - 1; info->slaveIndex = _viewer->getNumSlaves() - 1;
@ -297,6 +313,199 @@ void buildViewport(flightgear::CameraInfo* info, SGPropertyNode* viewportNode,
namespace flightgear namespace flightgear
{ {
// Mostly copied from osg's osgViewer/View.cpp
static osg::Geometry* createParoramicSphericalDisplayDistortionMesh(
const Vec3& origin, const Vec3& widthVector, const Vec3& heightVector,
double sphere_radius, double collar_radius,
Image* intensityMap = 0, const Matrix& projectorMatrix = Matrix())
{
osg::Vec3d center(0.0,0.0,0.0);
osg::Vec3d eye(0.0,0.0,0.0);
double distance = sqrt(sphere_radius*sphere_radius - collar_radius*collar_radius);
bool flip = false;
bool texcoord_flip = false;
osg::Vec3d projector = eye - osg::Vec3d(0.0,0.0, distance);
#if 0
OSG_INFO<<"createParoramicSphericalDisplayDistortionMesh : Projector position = "<<projector<<std::endl;
OSG_INFO<<"createParoramicSphericalDisplayDistortionMesh : distance = "<<distance<<std::endl;
#endif
// create the quad to visualize.
osg::Geometry* geometry = new osg::Geometry();
geometry->setSupportsDisplayList(false);
osg::Vec3 xAxis(widthVector);
float width = widthVector.length();
xAxis /= width;
osg::Vec3 yAxis(heightVector);
float height = heightVector.length();
yAxis /= height;
int noSteps = 160;
osg::Vec3Array* vertices = new osg::Vec3Array;
osg::Vec2Array* texcoords0 = new osg::Vec2Array;
osg::Vec2Array* texcoords1 = intensityMap==0 ? new osg::Vec2Array : 0;
osg::Vec4Array* colors = new osg::Vec4Array;
osg::Vec3 bottom = origin;
osg::Vec3 dx = xAxis*(width/((float)(noSteps-2)));
osg::Vec3 dy = yAxis*(height/((float)(noSteps-1)));
osg::Vec3 top = origin + yAxis*height;
osg::Vec3 screenCenter = origin + widthVector*0.5f + heightVector*0.5f;
float screenRadius = heightVector.length() * 0.5f;
geometry->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED);
for(int i=0;i<noSteps;++i)
{
osg::Vec3 cursor = bottom+dy*(float)i;
for(int j=0;j<noSteps;++j)
{
osg::Vec2 texcoord(double(i)/double(noSteps-1), double(j)/double(noSteps-1));
double theta = texcoord.x() * 2.0 * osg::PI;
double phi = (1.0-texcoord.y()) * osg::PI;
if (texcoord_flip) texcoord.y() = 1.0f - texcoord.y();
osg::Vec3 pos(sin(phi)*sin(theta), sin(phi)*cos(theta), cos(phi));
pos = pos*projectorMatrix;
double alpha = atan2(pos.x(), pos.y());
if (alpha<0.0) alpha += 2.0*osg::PI;
double beta = atan2(sqrt(pos.x()*pos.x() + pos.y()*pos.y()), pos.z());
if (beta<0.0) beta += 2.0*osg::PI;
double gamma = atan2(sqrt(double(pos.x()*pos.x() + pos.y()*pos.y())), double(pos.z()+distance));
if (gamma<0.0) gamma += 2.0*osg::PI;
osg::Vec3 v = screenCenter + osg::Vec3(sin(alpha)*gamma*2.0/osg::PI, -cos(alpha)*gamma*2.0/osg::PI, 0.0f)*screenRadius;
if (flip)
vertices->push_back(osg::Vec3(v.x(), top.y()-(v.y()-origin.y()),v.z()));
else
vertices->push_back(v);
texcoords0->push_back( texcoord );
osg::Vec2 texcoord1(alpha/(2.0*osg::PI), 1.0f - beta/osg::PI);
if (intensityMap)
{
colors->push_back(intensityMap->getColor(texcoord1));
}
else
{
colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
if (texcoords1) texcoords1->push_back( texcoord1 );
}
}
}
// pass the created vertex array to the points geometry object.
geometry->setVertexArray(vertices);
geometry->setColorArray(colors);
geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
geometry->setTexCoordArray(0,texcoords0);
if (texcoords1) geometry->setTexCoordArray(1,texcoords1);
osg::DrawElementsUShort* elements = new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLES);
geometry->addPrimitiveSet(elements);
for(int i=0;i<noSteps-1;++i)
{
for(int j=0;j<noSteps-1;++j)
{
int i1 = j+(i+1)*noSteps;
int i2 = j+(i)*noSteps;
int i3 = j+1+(i)*noSteps;
int i4 = j+1+(i+1)*noSteps;
osg::Vec3& v1 = (*vertices)[i1];
osg::Vec3& v2 = (*vertices)[i2];
osg::Vec3& v3 = (*vertices)[i3];
osg::Vec3& v4 = (*vertices)[i4];
if ((v1-screenCenter).length()>screenRadius) continue;
if ((v2-screenCenter).length()>screenRadius) continue;
if ((v3-screenCenter).length()>screenRadius) continue;
if ((v4-screenCenter).length()>screenRadius) continue;
elements->push_back(i1);
elements->push_back(i2);
elements->push_back(i3);
elements->push_back(i1);
elements->push_back(i3);
elements->push_back(i4);
}
}
return geometry;
}
void CameraGroup::buildDistortionCamera(const SGPropertyNode* psNode,
Camera* camera)
{
const SGPropertyNode* texNode = psNode->getNode("texture");
if (!texNode) {
// error
return;
}
string texName = texNode->getStringValue();
TextureMap::iterator itr = _textureTargets.find(texName);
if (itr == _textureTargets.end()) {
// error
return;
}
Viewport* viewport = camera->getViewport();
float width = viewport->width();
float height = viewport->height();
TextureRectangle* texRect = itr->second.get();
double radius = psNode->getDoubleValue("radius", 1.0);
double collar = psNode->getDoubleValue("collar", 0.45);
Geode* geode = new Geode();
geode->addDrawable(createParoramicSphericalDisplayDistortionMesh(
Vec3(0.0f,0.0f,0.0f), Vec3(width,0.0f,0.0f),
Vec3(0.0f,height,0.0f), radius, collar));
// new we need to add the texture to the mesh, we do so by creating a
// StateSet to contain the Texture StateAttribute.
StateSet* stateset = geode->getOrCreateStateSet();
stateset->setTextureAttributeAndModes(0, texRect, StateAttribute::ON);
stateset->setMode(GL_LIGHTING, StateAttribute::OFF);
TexMat* texmat = new TexMat;
texmat->setScaleByTextureRectangleSize(true);
stateset->setTextureAttributeAndModes(0, texmat, osg::StateAttribute::ON);
#if 0
if (!applyIntensityMapAsColours && intensityMap)
{
stateset->setTextureAttributeAndModes(1, new osg::Texture2D(intensityMap), osg::StateAttribute::ON);
}
#endif
// add subgraph to render
camera->addChild(geode);
camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
camera->setClearColor(osg::Vec4(0.0, 0.0, 0.0, 1.0));
camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
camera->setCullingMode(osg::CullSettings::NO_CULLING);
camera->setName("DistortionCorrectionCamera");
}
CameraInfo* CameraGroup::buildCamera(SGPropertyNode* cameraNode) CameraInfo* CameraGroup::buildCamera(SGPropertyNode* cameraNode)
{ {
WindowBuilder *wBuild = WindowBuilder::getWindowBuilder(); WindowBuilder *wBuild = WindowBuilder::getWindowBuilder();
@ -390,13 +599,43 @@ CameraInfo* CameraGroup::buildCamera(SGPropertyNode* cameraNode)
double sheary = cameraNode->getDoubleValue("shear-y", 0); double sheary = cameraNode->getDoubleValue("shear-y", 0);
pOff.makeTranslate(-shearx, -sheary, 0); pOff.makeTranslate(-shearx, -sheary, 0);
} }
CameraInfo* info = addCamera(cameraFlags, camera, pOff, vOff); const SGPropertyNode* textureNode = cameraNode->getNode("texture");
if (textureNode) {
string texName = textureNode->getStringValue("name");
int tex_width = textureNode->getIntValue("width");
int tex_height = textureNode->getIntValue("height");
TextureRectangle* texture = new TextureRectangle;
texture->setTextureSize(tex_width, tex_height);
texture->setInternalFormat(GL_RGB);
texture->setFilter(Texture::MIN_FILTER, Texture::LINEAR);
texture->setFilter(Texture::MAG_FILTER, Texture::LINEAR);
texture->setWrap(Texture::WRAP_S, Texture::CLAMP_TO_EDGE);
texture->setWrap(Texture::WRAP_T, Texture::CLAMP_TO_EDGE);
camera->setDrawBuffer(GL_FRONT);
camera->setReadBuffer(GL_FRONT);
camera->setRenderTargetImplementation(Camera::FRAME_BUFFER_OBJECT);
camera->attach(Camera::COLOR_BUFFER, texture);
_textureTargets[texName] = texture;
} else {
camera->setDrawBuffer(GL_BACK);
camera->setReadBuffer(GL_BACK);
}
const SGPropertyNode* psNode = cameraNode->getNode("panoramic-spherical");
bool useMasterSceneGraph = !psNode;
CameraInfo* info = addCamera(cameraFlags, camera, vOff, pOff,
useMasterSceneGraph);
// If a viewport isn't set on the camera, then it's hard to dig it // If a viewport isn't set on the camera, then it's hard to dig it
// out of the SceneView objects in the viewer, and the coordinates // out of the SceneView objects in the viewer, and the coordinates
// of mouse events are somewhat bizzare. // of mouse events are somewhat bizzare.
SGPropertyNode* viewportNode = cameraNode->getNode("viewport", true); SGPropertyNode* viewportNode = cameraNode->getNode("viewport", true);
buildViewport(info, viewportNode, window->gc->getTraits()); buildViewport(info, viewportNode, window->gc->getTraits());
updateCameras(info); updateCameras(info);
// Distortion camera needs the viewport which is created by addCamera().
if (psNode) {
info->flags = info->flags | VIEW_ABSOLUTE;
buildDistortionCamera(psNode, camera);
}
return info; return info;
} }

View file

@ -17,6 +17,7 @@
#ifndef CAMERAGROUP_HXX #ifndef CAMERAGROUP_HXX
#define CAMERAGROUP_HXX 1 #define CAMERAGROUP_HXX 1
#include <map>
#include <string> #include <string>
#include <vector> #include <vector>
@ -24,6 +25,7 @@
#include <osg/ref_ptr> #include <osg/ref_ptr>
#include <osg/Referenced> #include <osg/Referenced>
#include <osg/Node> #include <osg/Node>
#include <osg/TextureRectangle>
// For osgUtil::LineSegmentIntersector::Intersections, which is a typedef. // For osgUtil::LineSegmentIntersector::Intersections, which is a typedef.
#include <osgUtil/LineSegmentIntersector> #include <osgUtil/LineSegmentIntersector>
@ -178,6 +180,9 @@ public:
/** Update camera properties after a resize event. /** Update camera properties after a resize event.
*/ */
void resized(); void resized();
void buildDistortionCamera(const SGPropertyNode* psNode,
osg::Camera* camera);
protected: protected:
CameraList _cameras; CameraList _cameras;
osg::ref_ptr<osgViewer::Viewer> _viewer; osg::ref_ptr<osgViewer::Viewer> _viewer;
@ -186,6 +191,8 @@ protected:
float _zNear; float _zNear;
float _zFar; float _zFar;
float _nearField; float _nearField;
typedef std::map<std::string, osg::ref_ptr<osg::TextureRectangle> > TextureMap;
TextureMap _textureTargets;
}; };
} }

View file

@ -601,6 +601,9 @@ public:
SGPropertyNode *n = _cache->getNode("fg-root", true); SGPropertyNode *n = _cache->getNode("fg-root", true);
n->setStringValue(globals->get_fg_root().c_str()); n->setStringValue(globals->get_fg_root().c_str());
n->setAttribute(SGPropertyNode::USERARCHIVE, true); n->setAttribute(SGPropertyNode::USERARCHIVE, true);
n = _cache->getNode("fg-aircraft", true);
n->setStringValue(getAircraftPaths().c_str());
n->setAttribute(SGPropertyNode::USERARCHIVE, true);
_cache->removeChildren("aircraft"); _cache->removeChildren("aircraft");
fgFindAircraft(this, &FindAndCacheAircraft::checkAircraft); fgFindAircraft(this, &FindAndCacheAircraft::checkAircraft);
@ -629,12 +632,30 @@ public:
} }
private: private:
SGPath getAircraftPaths() {
string_list pathList = globals->get_aircraft_paths();
SGPath aircraftPaths;
string_list::const_iterator it = pathList.begin();
if (it != pathList.end()) {
aircraftPaths.set(*it);
it++;
}
for (; it != pathList.end(); ++it) {
aircraftPaths.add(*it);
}
return aircraftPaths;
}
bool checkCache() bool checkCache()
{ {
if (globals->get_fg_root() != _cache->getStringValue("fg-root", "")) { if (globals->get_fg_root() != _cache->getStringValue("fg-root", "")) {
return false; // cache mismatch return false; // cache mismatch
} }
if (getAircraftPaths().str() != _cache->getStringValue("fg-aircraft", "")) {
return false; // cache mismatch
}
vector<SGPropertyNode_ptr> cache = _cache->getChildren("aircraft"); vector<SGPropertyNode_ptr> cache = _cache->getChildren("aircraft");
for (unsigned int i = 0; i < cache.size(); i++) { for (unsigned int i = 0; i < cache.size(); i++) {
const char *name = cache[i]->getStringValue("file", ""); const char *name = cache[i]->getStringValue("file", "");

View file

@ -33,7 +33,6 @@ SceneryPager::SceneryPager()
{ {
_pagerRequests.reserve(48); _pagerRequests.reserve(48);
_deleteRequests.reserve(16); _deleteRequests.reserve(16);
setExpiryDelay(120.0);
} }
SceneryPager::SceneryPager(const SceneryPager& rhs) : SceneryPager::SceneryPager(const SceneryPager& rhs) :