Merge branch 'next' of git://gitorious.org/fg/flightgear into next
This commit is contained in:
commit
2a674c76fa
12 changed files with 691 additions and 284 deletions
|
@ -133,6 +133,30 @@ window, camera, or gui tags.
|
|||
This specifies an orthographic view. The parameters are the sames as
|
||||
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
|
||||
This is a special camera node that displays the 2D GUI.
|
||||
|
||||
|
@ -313,3 +337,61 @@ accounted for.
|
|||
</rendering>
|
||||
</sim>
|
||||
</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>
|
||||
|
||||
|
|
|
@ -152,11 +152,11 @@ bool FGAIBallistic::init(bool search_in_AI_path) {
|
|||
props->setStringValue("contents/path", _contents_path.c_str());
|
||||
}
|
||||
|
||||
if(_parent != ""){
|
||||
setParentNode();
|
||||
}
|
||||
//if(_parent != ""){
|
||||
// setParentNode();
|
||||
//}
|
||||
|
||||
setParentNodes(_selected_ac);
|
||||
//setParentNodes(_selected_ac);
|
||||
|
||||
//props->setStringValue("vector/path", _vector_path.c_str());
|
||||
|
||||
|
@ -168,7 +168,11 @@ bool FGAIBallistic::init(bool search_in_AI_path) {
|
|||
|
||||
Transform();
|
||||
|
||||
//cout << _name << " speed init: " << speed << endl;
|
||||
if(_parent != ""){
|
||||
setParentNode();
|
||||
}
|
||||
|
||||
setParentNodes(_selected_ac);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -215,13 +215,14 @@ bool FGAIWingman::init(bool search_in_AI_path) {
|
|||
roll = _rotation;
|
||||
_ht_agl_ft = 1e10;
|
||||
|
||||
props->setStringValue("submodels/path", _path.c_str());
|
||||
|
||||
if(_parent != ""){
|
||||
setParentNode();
|
||||
}
|
||||
|
||||
setParentNodes(_selected_ac);
|
||||
|
||||
props->setStringValue("submodels/path", _path.c_str());
|
||||
user_WoW_node = fgGetNode("gear/gear[1]/wow", true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -277,7 +278,7 @@ double FGAIWingman::calcAngle(double range, SGGeod pos1, SGGeod pos2){
|
|||
|
||||
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);
|
||||
|
||||
|
@ -312,8 +313,9 @@ void FGAIWingman::formateToAC(double dt){
|
|||
double h_feet = 3 * factor;
|
||||
|
||||
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;
|
||||
//cout << "ht case1 " ;
|
||||
} else if (p_agl > 10 && p_agl <= 150 ) {
|
||||
|
@ -332,7 +334,8 @@ void FGAIWingman::formateToAC(double dt){
|
|||
pos.setLongitudeDeg(_offsetpos.getLongitudeDeg());
|
||||
|
||||
// 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);
|
||||
setPch(p_pch + p_angle + _pitch_offset, dt, 0.9);
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ private:
|
|||
double _coeff_bnk; //dimensionless coefficient
|
||||
double _coeff_spd; //dimensionless coefficient
|
||||
|
||||
|
||||
SGPropertyNode_ptr user_WoW_node;
|
||||
|
||||
inline void setFormate(bool f);
|
||||
inline void setTgtHdg(double hdg);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
// This file is in the Public Domain and comes with no warranty.
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/sg_inlines.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
@ -54,15 +55,26 @@ HeadingIndicatorDG::init ()
|
|||
branch = "/instrumentation/" + name;
|
||||
|
||||
_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 );
|
||||
_offset_node = node->getChild("offset-deg", 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);
|
||||
_heading_out_node = node->getChild("indicated-heading-deg", 0, true);
|
||||
_last_heading_deg = (_heading_in_node->getDoubleValue() +
|
||||
_offset_node->getDoubleValue());
|
||||
_align_node = node->getChild("align-deg", 0, 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
|
||||
|
@ -100,11 +112,30 @@ HeadingIndicatorDG::update (double dt)
|
|||
_gyro.update(dt);
|
||||
double spin = _gyro.get_spin_norm();
|
||||
|
||||
// No time-based precession for a flux gate compass
|
||||
// No magvar
|
||||
double offset = 0;
|
||||
// Next, calculate time-based precession
|
||||
double offset = _offset_node->getDoubleValue();
|
||||
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,
|
||||
// introducing errors.
|
||||
|
@ -122,11 +153,8 @@ HeadingIndicatorDG::update (double dt)
|
|||
heading = fgGetLowPass(_last_heading_deg, heading, dt * factor);
|
||||
_last_heading_deg = heading;
|
||||
|
||||
heading += offset;
|
||||
while (heading < 0)
|
||||
heading += 360;
|
||||
while (heading > 360)
|
||||
heading -= 360;
|
||||
heading += offset + align + error;
|
||||
SG_NORMALIZE_RANGE(heading, 0.0, 360.0);
|
||||
|
||||
_heading_out_node->setDoubleValue(heading);
|
||||
|
||||
|
@ -138,7 +166,7 @@ HeadingIndicatorDG::update (double dt)
|
|||
double diff = bnode->getDoubleValue() - heading;
|
||||
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
|
||||
// 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
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/math/sg_random.h>
|
||||
|
||||
#include "gyro.hxx"
|
||||
|
||||
|
@ -59,6 +60,10 @@ private:
|
|||
SGPropertyNode_ptr _electrical_node;
|
||||
SGPropertyNode_ptr _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
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "mrg.hxx"
|
||||
|
||||
const double MasterReferenceGyro::gravity = -32.1740485564;
|
||||
|
||||
MasterReferenceGyro::MasterReferenceGyro ( SGPropertyNode *node ) :
|
||||
_name(node->getStringValue("name", "master-reference-gyro")),
|
||||
|
@ -43,7 +44,9 @@ MasterReferenceGyro::init ()
|
|||
_indicated_hdg_rate = 0;
|
||||
_indicated_roll_rate = 0;
|
||||
_indicated_pitch_rate = 0;
|
||||
_erect_time = 0;
|
||||
_erect_time = 180;
|
||||
_last_g = 1;
|
||||
_g_error = 10;
|
||||
|
||||
string branch;
|
||||
branch = "/instrumentation/" + _name;
|
||||
|
@ -55,6 +58,7 @@ MasterReferenceGyro::init ()
|
|||
_pitch_rate_node = fgGetNode("/orientation/pitch-rate-degps", true);
|
||||
_roll_rate_node = fgGetNode("/orientation/roll-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);
|
||||
_electrical_node = fgGetNode("/systems/electrical/outputs/MRG", true);
|
||||
_hdg_mag_in_node = fgGetNode("/orientation/heading-magnetic-deg", true);
|
||||
|
@ -78,6 +82,7 @@ MasterReferenceGyro::init ()
|
|||
_off_node->setBoolValue(false);
|
||||
_hdg_input_source_node->setBoolValue(false);
|
||||
_fast_erect_node->setBoolValue(false);
|
||||
_g_in_node->setDoubleValue(1);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -109,12 +114,22 @@ MasterReferenceGyro::unbind ()
|
|||
void
|
||||
MasterReferenceGyro::update (double dt)
|
||||
{
|
||||
//sanity check
|
||||
if (!fgGetBool("/sim/fdm-initialized", false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
double indicated_roll = 0;
|
||||
double indicated_pitch = 0;
|
||||
double indicated_hdg = 0;
|
||||
double indicated_roll_rate = 0;
|
||||
double indicated_pitch_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
|
||||
_gyro.set_power_norm( _electrical_node->getDoubleValue()/24 );
|
||||
|
@ -130,18 +145,19 @@ MasterReferenceGyro::update (double dt)
|
|||
}
|
||||
|
||||
// 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();
|
||||
} else {
|
||||
hdg = _hdg_mag_in_node->getDoubleValue();
|
||||
}
|
||||
|
||||
double roll = _roll_in_node->getDoubleValue();
|
||||
double pitch = _pitch_in_node->getDoubleValue();
|
||||
double g = _g_in_node->getDoubleValue()/* / gravity*/;
|
||||
|
||||
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 g = _g_in_node->getDoubleValue();
|
||||
|
||||
//modulate the input by the spin rate
|
||||
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!
|
||||
responsiveness = 0.1 / (spin * spin * spin * spin * spin * spin);
|
||||
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
|
||||
|
@ -170,38 +186,38 @@ MasterReferenceGyro::update (double dt)
|
|||
_last_yaw_rate = yaw_rate;
|
||||
_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() )
|
||||
_erect_time -= dt;
|
||||
else
|
||||
_erect_time -= 2 * dt;
|
||||
if ( !_fast_erect_node->getBoolValue() ){
|
||||
erect_time_factor = 1;
|
||||
} else {
|
||||
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,
|
||||
// "g input " << g <<" _erect_time " << _erect_time << " spin " << spin);
|
||||
|
||||
//the gyro only erects inside limits
|
||||
if ( fabs ( yaw_rate ) <= 5
|
||||
&& ( g <= 1.5 || g >= -0.5)
|
||||
&& _erect_time <=0 ) {
|
||||
indicated_roll = _last_roll;
|
||||
indicated_pitch = _last_pitch;
|
||||
indicated_hdg = _last_hdg;
|
||||
//cout << "_g_error "<< _g_error << endl;
|
||||
_g_error = SGMiscd::clip(_g_error, 0, 10);
|
||||
// cout << "_g_error clip "<< _g_error << endl;
|
||||
indicated_roll = _last_roll + _g_error;
|
||||
indicated_pitch = _last_pitch + _g_error;
|
||||
indicated_hdg = _last_hdg + _g_error;
|
||||
indicated_roll_rate = _last_roll_rate;
|
||||
indicated_pitch_rate = _last_pitch_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
|
||||
// and the selected heading for use with an autopilot
|
||||
static SGPropertyNode *bnode
|
||||
|
|
|
@ -49,6 +49,8 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
static const double gravity; //conversion factor
|
||||
|
||||
string _name;
|
||||
int _num;
|
||||
|
||||
|
@ -66,6 +68,7 @@ private:
|
|||
double _last_yaw_rate;
|
||||
double _last_g;
|
||||
double _erect_time;
|
||||
double _g_error;
|
||||
|
||||
Gyro _gyro;
|
||||
|
||||
|
|
|
@ -35,10 +35,15 @@
|
|||
#include <string>
|
||||
|
||||
#include <osg/Camera>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/GraphicsContext>
|
||||
#include <osg/io_utils>
|
||||
#include <osg/Math>
|
||||
#include <osg/Matrix>
|
||||
#include <osg/Notify>
|
||||
#include <osg/Program>
|
||||
#include <osg/Quat>
|
||||
#include <osg/TexMat>
|
||||
#include <osg/Vec3d>
|
||||
#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
|
||||
// twice and ends up with the wrong value.
|
||||
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);
|
||||
info->farCamera = farCamera;
|
||||
info->farSlaveIndex = _viewer->getNumSlaves() - 1;
|
||||
|
@ -156,7 +172,7 @@ CameraInfo* CameraGroup::addCamera(unsigned flags, Camera* camera,
|
|||
camera->setCullMask(camera->getCullMask() & ~simgear::BACKGROUND_BIT);
|
||||
camera->setClearMask(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
_viewer->addSlave(camera, view, projection, useMasterSceneData);
|
||||
_viewer->addSlave(camera, projection, view, useMasterSceneData);
|
||||
installCullVisitor(camera);
|
||||
info->camera = camera;
|
||||
info->slaveIndex = _viewer->getNumSlaves() - 1;
|
||||
|
@ -297,6 +313,199 @@ void buildViewport(flightgear::CameraInfo* info, SGPropertyNode* viewportNode,
|
|||
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)
|
||||
{
|
||||
WindowBuilder *wBuild = WindowBuilder::getWindowBuilder();
|
||||
|
@ -390,13 +599,43 @@ CameraInfo* CameraGroup::buildCamera(SGPropertyNode* cameraNode)
|
|||
double sheary = cameraNode->getDoubleValue("shear-y", 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
|
||||
// out of the SceneView objects in the viewer, and the coordinates
|
||||
// of mouse events are somewhat bizzare.
|
||||
SGPropertyNode* viewportNode = cameraNode->getNode("viewport", true);
|
||||
buildViewport(info, viewportNode, window->gc->getTraits());
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#ifndef CAMERAGROUP_HXX
|
||||
#define CAMERAGROUP_HXX 1
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
@ -24,6 +25,7 @@
|
|||
#include <osg/ref_ptr>
|
||||
#include <osg/Referenced>
|
||||
#include <osg/Node>
|
||||
#include <osg/TextureRectangle>
|
||||
|
||||
// For osgUtil::LineSegmentIntersector::Intersections, which is a typedef.
|
||||
#include <osgUtil/LineSegmentIntersector>
|
||||
|
@ -178,6 +180,9 @@ public:
|
|||
/** Update camera properties after a resize event.
|
||||
*/
|
||||
void resized();
|
||||
|
||||
void buildDistortionCamera(const SGPropertyNode* psNode,
|
||||
osg::Camera* camera);
|
||||
protected:
|
||||
CameraList _cameras;
|
||||
osg::ref_ptr<osgViewer::Viewer> _viewer;
|
||||
|
@ -186,6 +191,8 @@ protected:
|
|||
float _zNear;
|
||||
float _zFar;
|
||||
float _nearField;
|
||||
typedef std::map<std::string, osg::ref_ptr<osg::TextureRectangle> > TextureMap;
|
||||
TextureMap _textureTargets;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -601,6 +601,9 @@ public:
|
|||
SGPropertyNode *n = _cache->getNode("fg-root", true);
|
||||
n->setStringValue(globals->get_fg_root().c_str());
|
||||
n->setAttribute(SGPropertyNode::USERARCHIVE, true);
|
||||
n = _cache->getNode("fg-aircraft", true);
|
||||
n->setStringValue(getAircraftPaths().c_str());
|
||||
n->setAttribute(SGPropertyNode::USERARCHIVE, true);
|
||||
_cache->removeChildren("aircraft");
|
||||
|
||||
fgFindAircraft(this, &FindAndCacheAircraft::checkAircraft);
|
||||
|
@ -629,12 +632,30 @@ public:
|
|||
}
|
||||
|
||||
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()
|
||||
{
|
||||
if (globals->get_fg_root() != _cache->getStringValue("fg-root", "")) {
|
||||
return false; // cache mismatch
|
||||
}
|
||||
|
||||
if (getAircraftPaths().str() != _cache->getStringValue("fg-aircraft", "")) {
|
||||
return false; // cache mismatch
|
||||
}
|
||||
|
||||
vector<SGPropertyNode_ptr> cache = _cache->getChildren("aircraft");
|
||||
for (unsigned int i = 0; i < cache.size(); i++) {
|
||||
const char *name = cache[i]->getStringValue("file", "");
|
||||
|
|
|
@ -33,7 +33,6 @@ SceneryPager::SceneryPager()
|
|||
{
|
||||
_pagerRequests.reserve(48);
|
||||
_deleteRequests.reserve(16);
|
||||
setExpiryDelay(120.0);
|
||||
}
|
||||
|
||||
SceneryPager::SceneryPager(const SceneryPager& rhs) :
|
||||
|
|
Loading…
Reference in a new issue