Move FGODGauge from FlightGear to SimGear.

This is a first step for moving the Canvas system to SimGear to
make it accessible to other applications (eg.FGRadar is going to
use it)
This commit is contained in:
Thomas Geymayer 2012-10-19 11:48:39 +02:00
parent e24e3c0612
commit f191b4f35c
4 changed files with 444 additions and 0 deletions

View File

@ -24,6 +24,7 @@ foreach( mylibfolder
endforeach( mylibfolder ) endforeach( mylibfolder )
if(NOT SIMGEAR_HEADLESS) if(NOT SIMGEAR_HEADLESS)
add_subdirectory(canvas)
add_subdirectory(environment) add_subdirectory(environment)
add_subdirectory(screen) add_subdirectory(screen)
add_subdirectory(scene) add_subdirectory(scene)

View File

@ -0,0 +1,11 @@
include (SimGearComponent)
set(HEADERS
ODGauge.hxx
)
set(SOURCES
ODGauge.cxx
)
simgear_scene_component(canvas canvas "${SOURCES}" "${HEADERS}")

276
simgear/canvas/ODGauge.cxx Normal file
View File

@ -0,0 +1,276 @@
// Owner Drawn Gauge helper class
//
// Written by Harald JOHNSEN, started May 2005.
//
// Copyright (C) 2005 Harald JOHNSEN
//
// Ported to OSG by Tim Moore - Jun 2007
//
// Heavily modified to be usable for the 2d Canvas by Thomas Geymayer - April 2012
// Supports now multisampling/mipmapping, usage of the stencil buffer and placing
// the texture in the scene by certain filter criteria
//
// 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 <simgear_config.h>
#endif
#include <osg/Texture2D>
#include <osg/AlphaFunc>
#include <osg/BlendFunc>
#include <osg/Camera>
#include <osg/Matrix>
#include <osg/PolygonMode>
#include <osg/ShadeModel>
#include <osg/StateSet>
#include <osg/FrameBufferObject> // for GL_DEPTH_STENCIL_EXT on Windows
#include <simgear/debug/logstream.hxx>
#include <simgear/scene/util/RenderConstants.hxx>
#include "ODGauge.hxx"
#include <cassert>
namespace simgear
{
//------------------------------------------------------------------------------
ODGauge::ODGauge( const CameraRegistrationCallback& cb_camera_add,
const CameraRegistrationCallback& cb_camera_remove ):
_size_x( -1 ),
_size_y( -1 ),
_view_width( -1 ),
_view_height( -1 ),
_use_image_coords( false ),
_use_stencil( false ),
_use_mipmapping( false ),
_coverage_samples( 0 ),
_color_samples( 0 ),
rtAvailable( false ),
_cb_cam_add( cb_camera_add ),
_cb_cam_remove( cb_camera_remove )
{
}
//------------------------------------------------------------------------------
ODGauge::~ODGauge()
{
if( camera.valid() )
_cb_cam_remove(camera.get());
}
//------------------------------------------------------------------------------
void ODGauge::setSize(int size_x, int size_y)
{
_size_x = size_x;
_size_y = size_y < 0 ? size_x : size_y;
if( texture.valid() )
texture->setTextureSize(_size_x, _size_x);
}
//----------------------------------------------------------------------------
void ODGauge::setViewSize(int width, int height)
{
_view_width = width;
_view_height = height < 0 ? width : height;
if( camera )
updateCoordinateFrame();
}
//------------------------------------------------------------------------------
void ODGauge::useImageCoords(bool use)
{
if( use == _use_image_coords )
return;
_use_image_coords = use;
if( texture )
updateCoordinateFrame();
}
//------------------------------------------------------------------------------
void ODGauge::useStencil(bool use)
{
if( use == _use_stencil )
return;
_use_stencil = use;
if( texture )
updateStencil();
}
//------------------------------------------------------------------------------
void ODGauge::setSampling( bool mipmapping,
int coverage_samples,
int color_samples )
{
if( _use_mipmapping == mipmapping
&& _coverage_samples == coverage_samples
&& _color_samples == color_samples )
return;
_use_mipmapping = mipmapping;
if( color_samples > coverage_samples )
{
SG_LOG
(
SG_GL,
SG_WARN,
"ODGauge::setSampling: color_samples > coverage_samples not allowed!"
);
color_samples = coverage_samples;
}
_coverage_samples = coverage_samples;
_color_samples = color_samples;
updateSampling();
}
//------------------------------------------------------------------------------
void ODGauge::setRender(bool render)
{
// Only the far camera should trigger this texture to be rendered.
camera->setNodeMask(render ? simgear::BACKGROUND_BIT : 0);
}
//------------------------------------------------------------------------------
bool ODGauge::serviceable(void)
{
return rtAvailable;
}
//------------------------------------------------------------------------------
void ODGauge::allocRT(osg::NodeCallback* camera_cull_callback)
{
camera = new osg::Camera;
camera->setDataVariance(osg::Object::DYNAMIC);
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
camera->setRenderOrder(osg::Camera::PRE_RENDER);
camera->setClearColor(osg::Vec4(0.0f, 0.0f, 0.0f , 0.0f));
camera->setClearStencil(0);
camera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT,
osg::Camera::FRAME_BUFFER );
if( camera_cull_callback )
camera->setCullCallback(camera_cull_callback);
setRender(true);
updateCoordinateFrame();
updateStencil();
osg::StateSet* stateSet = camera->getOrCreateStateSet();
stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
stateSet->setMode(GL_FOG, osg::StateAttribute::OFF);
stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
stateSet->setAttributeAndModes(new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK,
osg::PolygonMode::FILL),
osg::StateAttribute::ON);
stateSet->setAttributeAndModes(new osg::AlphaFunc(osg::AlphaFunc::GREATER,
0.0f),
osg::StateAttribute::ON);
stateSet->setAttribute(new osg::ShadeModel(osg::ShadeModel::FLAT));
stateSet->setAttributeAndModes(new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA,
osg::BlendFunc::ONE_MINUS_SRC_ALPHA),
osg::StateAttribute::ON);
if( !texture )
{
texture = new osg::Texture2D;
texture->setTextureSize(_size_x, _size_y);
texture->setInternalFormat(GL_RGBA);
}
updateSampling();
_cb_cam_add(camera.get());
rtAvailable = true;
}
//------------------------------------------------------------------------------
void ODGauge::updateCoordinateFrame()
{
assert( camera );
if( _view_width < 0 )
_view_width = _size_x;
if( _view_height < 0 )
_view_height = _size_y;
camera->setViewport(0, 0, _size_x, _size_y);
if( _use_image_coords )
camera->setProjectionMatrix(
osg::Matrix::ortho2D(0, _view_width, _view_height, 0)
);
else
camera->setProjectionMatrix(
osg::Matrix::ortho2D( -_view_width/2., _view_width/2.,
-_view_height/2., _view_height/2. )
);
}
//------------------------------------------------------------------------------
void ODGauge::updateStencil()
{
assert( camera );
GLbitfield mask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
if( _use_stencil)
{
camera->attach( osg::Camera::PACKED_DEPTH_STENCIL_BUFFER,
GL_DEPTH_STENCIL_EXT );
mask |= GL_STENCIL_BUFFER_BIT;
}
else
{
camera->detach(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER);
}
camera->setClearMask(mask);
}
//------------------------------------------------------------------------------
void ODGauge::updateSampling()
{
assert( camera );
assert( texture );
texture->setFilter(
osg::Texture2D::MIN_FILTER,
_use_mipmapping ? osg::Texture2D::LINEAR_MIPMAP_LINEAR
: osg::Texture2D::LINEAR
);
camera->attach(
osg::Camera::COLOR_BUFFER,
texture.get(),
0, 0,
_use_mipmapping,
_coverage_samples,
_color_samples
);
}
} // namespace simgear

156
simgear/canvas/ODGauge.hxx Normal file
View File

@ -0,0 +1,156 @@
// Owner Drawn Gauge helper class
//
// Written by Harald JOHNSEN, started May 2005.
//
// Copyright (C) 2005 Harald JOHNSEN - hjohnsen@evc.net
//
// Ported to OSG by Tim Moore - Jun 2007
//
// Heavily modified to be usable for the 2d Canvas by Thomas Geymayer - April 2012
// Supports now multisampling/mipmapping, usage of the stencil buffer and placing
// the texture in the scene by certain filter criteria
//
// 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 _SG_OD_GAUGE_HXX
#define _SG_OD_GAUGE_HXX
#include <osg/NodeCallback>
#include <osg/Group>
#include <boost/function.hpp>
namespace osg
{
class Camera;
class Texture2D;
}
namespace simgear
{
/**
* Owner Drawn Gauge (aka render-to-texture) helper class
*/
class ODGauge
{
public:
typedef boost::function<void(osg::Camera*)> CameraRegistrationCallback;
ODGauge( const CameraRegistrationCallback& cb_camera_add,
const CameraRegistrationCallback& cb_camera_remove );
virtual ~ODGauge();
/**
* Set the size of the render target.
*
* @param size_x X size
* @param size_y Y size. Defaults to size_x if not specified
*/
void setSize(int size_x, int size_y = -1);
/**
* Set the size of the viewport
*
* @param width
* @param height Defaults to width if not specified
*/
void setViewSize(int width, int height = -1);
/**
* DEPRECATED
*
* Get size of squared texture
*/
int size() const { return _size_x; }
/**
* Set whether to use image coordinates or not.
*
* Default: origin == center of texture
* Image Coords: origin == top left corner
*/
void useImageCoords(bool use = true);
/**
* Enable/Disable using a stencil buffer
*/
void useStencil(bool use = true);
/**
* Set sampling parameters for mipmapping and coverage sampling
* antialiasing.
*
* @note color_samples is not allowed to be higher than coverage_samples
*
*/
void setSampling( bool mipmapping,
int coverage_samples = 0,
int color_samples = 0 );
/**
* Enable/Disable updating the texture (If disabled the contents of the
* texture remains with the outcome of the last rendering pass)
*/
void setRender(bool render);
/**
* Say if we can render to a texture.
* @return true if rtt is available
*/
bool serviceable(void);
/**
* Get the OSG camera for drawing this gauge.
*/
osg::Camera* getCamera() const { return camera.get(); }
osg::Texture2D* getTexture() const { return texture.get(); }
// Real initialization function. Bad name.
void allocRT(osg::NodeCallback* camera_cull_callback = 0);
private:
int _size_x,
_size_y,
_view_width,
_view_height;
bool _use_image_coords,
_use_stencil,
_use_mipmapping;
// Multisampling parameters
int _coverage_samples,
_color_samples;
bool rtAvailable;
osg::ref_ptr<osg::Camera> camera;
osg::ref_ptr<osg::Texture2D> texture;
CameraRegistrationCallback _cb_cam_add,
_cb_cam_remove;
void updateCoordinateFrame();
void updateStencil();
void updateSampling();
};
} // namespace simgear
#endif // _SG_OD_GAUGE_HXX