#include <simgear/compiler.h>
+#include <algorithm>
+#include <iostream>
+#include <map>
+#include <vector>
+#include <typeinfo>
+
#include <osg/ref_ptr>
#include <osg/AlphaFunc>
#include <osg/BlendFunc>
#include <osg/Camera>
#include <osg/CullFace>
+#include <osg/CullStack>
#include <osg/Depth>
#include <osg/Fog>
#include <osg/Group>
#include <simgear/screen/jpgfactory.hxx>
#endif
-#include <simgear/environment/visual_enviro.hxx>
-
#include <Time/light.hxx>
#include <Time/light.hxx>
#include <Cockpit/panel.hxx>
-#include <Cockpit/cockpit.hxx>
-#include <Cockpit/hud.hxx>
#include <Model/panelnode.hxx>
#include <Model/modelmgr.hxx>
#include <Model/acmodel.hxx>
#include <Scenery/scenery.hxx>
#include <Scenery/redout.hxx>
-#include <Scenery/tilemgr.hxx>
#include <GUI/new_gui.hxx>
-#include <Instrumentation/instrument_mgr.hxx>
#include <Instrumentation/HUD/HUD.hxx>
#include <Environment/precipitation_mgr.hxx>
+#include <Environment/environment_mgr.hxx>
-#include <Include/general.hxx>
#include "splash.hxx"
#include "renderer.hxx"
#include "main.hxx"
#include "CameraGroup.hxx"
#include "FGEventHandler.hxx"
#include <Main/viewer.hxx>
+#include <Main/viewmgr.hxx>
using namespace osg;
using namespace simgear;
hint->setMode(GL_DONT_CARE);
}
private:
- SGSharedPtr<SGPropertyNode> mConfigNode;
+ SGPropertyNode_ptr mConfigNode;
};
glPushAttrib(GL_ALL_ATTRIB_BITS);
glPushClientAttrib(~0u);
- fgCockpitUpdate(&state);
-
- FGInstrumentMgr *instr = static_cast<FGInstrumentMgr*>(globals->get_subsystem("instrumentation"));
- HUD *hud = static_cast<HUD*>(instr->get_subsystem("hud"));
+ HUD *hud = static_cast<HUD*>(globals->get_subsystem("hud"));
hud->draw(state);
// update the panel subsystem
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*)
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*)
}
}
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*)
{
}
}
private:
- SGSharedPtr<SGPropertyNode> mFogEnabled;
+ SGPropertyNode_ptr mFogEnabled;
};
class FGFogUpdateCallback : public osg::StateAttribute::Callback {
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;
};
-// Sky structures
-SGSky *thesky;
+bool FGScenerySwitchCallback::scenery_enabled = false;
static osg::ref_ptr<osg::FrameStamp> mFrameStamp = new osg::FrameStamp;
static osg::ref_ptr<SGUpdateVisitor> mUpdateVisitor= new SGUpdateVisitor;
static osg::ref_ptr<osg::Group> mRoot = new osg::Group;
-FGRenderer::FGRenderer()
+#ifdef FG_JPEG_SERVER
+static void updateRenderer()
+{
+ globals->get_renderer()->update();
+}
+#endif
+
+FGRenderer::FGRenderer() :
+ _sky(NULL)
{
#ifdef FG_JPEG_SERVER
- jpgRenderFrame = FGRenderer::update;
+ jpgRenderFrame = updateRenderer;
#endif
eventHandler = new FGEventHandler;
}
#ifdef FG_JPEG_SERVER
jpgRenderFrame = NULL;
#endif
+ delete _sky;
}
// Initialize various GL/view parameters
// critical parts of the scene graph in addition to the splash screen.
void
FGRenderer::splashinit( void ) {
- osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
+ osgViewer::Viewer* viewer = getViewer();
mRealRoot = dynamic_cast<osg::Group*>(viewer->getSceneData());
mRealRoot->addChild(fgCreateSplashNode());
mFrameStamp = viewer->getFrameStamp();
// 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);
+
+ bool use_point_sprites = _point_sprites->getBoolValue();
+ bool enhanced_lighting = _enhanced_lighting->getBoolValue();
+ bool distance_attenuation = _distance_attenuation->getBoolValue();
+
+ SGConfigureDirectionalLights( use_point_sprites, enhanced_lighting,
+ distance_attenuation );
+
+// create sky, but can't build until setupView, since we depend
+// on other subsystems to be inited, eg Ephemeris
+ _sky = new SGSky;
+
+ SGPath texture_path(globals->get_fg_root());
+ texture_path.append("Textures");
+ texture_path.append("Sky");
+ for (int i = 0; i < FGEnvironmentMgr::MAX_CLOUD_LAYERS; i++) {
+ SGCloudLayer * layer = new SGCloudLayer(texture_path.str());
+ _sky->add_cloud_layer(layer);
+ }
+
+ _sky->texture_path( texture_path.str() );
+}
+
+void
+FGRenderer::setupView( void )
{
osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
osg::initNotifyLevel();
if ( fgGetBool("/sim/startup/fullscreen") )
fgOSFullScreen();
+// build the sky
+ // The sun and moon diameters are scaled down numbers of the
+ // actual diameters. This was needed to fit both the sun and the
+ // moon within the distance to the far clip plane.
+ // Moon diameter: 3,476 kilometers
+ // Sun diameter: 1,390,000 kilometers
+ _sky->build( 80000.0, 80000.0,
+ 463.3, 361.8,
+ *globals->get_ephem(),
+ fgGetNode("/environment", true));
+
viewer->getCamera()
->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
sunLight->setUpdateCallback(new FGLightSourceUpdateCallback(true));
sunLight->setReferenceFrame(osg::LightSource::RELATIVE_RF);
sunLight->setLocalStateSetModes(osg::StateAttribute::ON);
+
// Hang a StateSet above the sky subgraph in order to turn off
// light 0
Group* skyGroup = new Group;
StateSet* skySS = skyGroup->getOrCreateStateSet();
skySS->setMode(GL_LIGHT0, StateAttribute::OFF);
- skyGroup->addChild(thesky->getPreRoot());
+ skyGroup->addChild(_sky->getPreRoot());
sunLight->addChild(skyGroup);
mRoot->addChild(sceneGroup);
mRoot->addChild(sunLight);
+
// Clouds are added to the scene graph later
stateSet = globals->get_scenery()->get_scene_graph()->getOrCreateStateSet();
stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
// The clouds are attached directly to the scene graph root
// because, in theory, they don't want the same default state set
// as the rest of the scene. This may not be true in practice.
- mRealRoot->addChild(thesky->getCloudRoot());
+ mRealRoot->addChild(_sky->getCloudRoot());
mRealRoot->addChild(FGCreateRedoutNode());
// Attach empty program to the scene root so that shader programs
// don't leak into state sets (effects) that shouldn't have one.
stateSet->setAttributeAndModes(new osg::Program, osg::StateAttribute::ON);
}
-
// 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);
- return;
+FGRenderer::update( ) {
+ 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 = 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 );
+#if 0 // OSGFIXME
+ // OSGFIXME: features no longer available or no longer run-time configurable
+ {
+ bool use_point_sprites = _point_sprites->getBoolValue();
+ bool enhanced_lighting = _enhanced_lighting->getBoolValue();
+ bool distance_attenuation = _distance_attenuation->getBoolValue();
+
+ SGConfigureDirectionalLights( use_point_sprites, enhanced_lighting,
+ distance_attenuation );
+ }
+#endif
FGLight *l = static_cast<FGLight*>(globals->get_subsystem("lighting"));
// update fog params
double actual_visibility;
- if (fgGetBool("/environment/clouds/status")) {
- actual_visibility = thesky->get_visibility();
+ if (_cloud_status->getBoolValue()) {
+ actual_visibility = _sky->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
FGViewer *current__view = globals->get_current_view();
// Force update of center dependent values ...
current__view->set_dirty();
-
- if ( refresh_camera_settings ) {
- // update view port
- resize( fgGetInt("/sim/startup/xsize"),
- fgGetInt("/sim/startup/ysize") );
- }
+
osg::Camera *camera = viewer->getCamera();
+ bool skyblend = _skyblend->getBoolValue();
if ( skyblend ) {
- if ( fgGetBool("/sim/rendering/textures") ) {
+ if ( _textures->getBoolValue() ) {
SGVec4f clearColor(l->adj_fog_color());
camera->setClearColor(toOsg(clearColor));
}
}
// update fog params if visibility has changed
- double visibility_meters = fgGetDouble("/environment/visibility-m");
- thesky->set_visibility(visibility_meters);
+ double visibility_meters = _visibility_m->getDoubleValue();
+ _sky->set_visibility(visibility_meters);
- double altitude_m = fgGetDouble("/position/altitude-ft") * SG_FEET_TO_METER;
- thesky->modify_vis( altitude_m, 0.0 /* time factor, now unused */);
+ double altitude_m = _altitude_ft->getDoubleValue() * SG_FEET_TO_METER;
+ _sky->modify_vis( altitude_m, 0.0 /* time factor, now unused */);
// update the sky dome
if ( skyblend ) {
// 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),
scolor.sun_angle = l->get_sun_angle();
scolor.moon_angle = l->get_moon_angle();
- double delta_time_sec = fgGetDouble("/sim/time/delta-sec");
- thesky->reposition( sstate, *globals->get_ephem(), delta_time_sec );
- thesky->repaint( scolor, *globals->get_ephem() );
+ double delta_time_sec = _sim_delta_sec->getDoubleValue();
+ _sky->reposition( sstate, *globals->get_ephem(), delta_time_sec );
+ _sky->repaint( scolor, *globals->get_ephem() );
//OSGFIXME
// shadows->setupShadows(
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);
}
-
-
-// options.cxx needs to see this for toggle_panel()
-// 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;
- }
-
- 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);
-
- // 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);
- }
+FGRenderer::resize( int width, int height )
+{
+ int curWidth = _xsize->getIntValue(),
+ curHeight = _ysize->getIntValue();
+ SG_LOG(SG_VIEW, SG_DEBUG, "FGRenderer::resize: new size " << width << " x " << height);
+ if ((curHeight != height) || (curWidth != width)) {
+ // must guard setting these, or PLIB-PUI fails with too many live interfaces
+ _xsize->setIntValue(width);
+ _ysize->setIntValue(height);
}
}
{
return osgDB::writeNodeFile(*node, filename);
}
+
+namespace flightgear
+{
+using namespace osg;
+
+class VisibleSceneInfoVistor : public NodeVisitor, CullStack
+{
+public:
+ VisibleSceneInfoVistor()
+ : NodeVisitor(CULL_VISITOR, TRAVERSE_ACTIVE_CHILDREN)
+ {
+ setCullingMode(CullSettings::SMALL_FEATURE_CULLING
+ | CullSettings::VIEW_FRUSTUM_CULLING);
+ setComputeNearFarMode(CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
+ }
+
+ VisibleSceneInfoVistor(const VisibleSceneInfoVistor& rhs)
+ {
+ }
+
+ META_NodeVisitor("flightgear","VisibleSceneInfoVistor")
+
+ typedef std::map<const std::string,int> InfoMap;
+
+ void getNodeInfo(Node* node)
+ {
+ const char* typeName = typeid(*node).name();
+ classInfo[typeName]++;
+ const std::string& nodeName = node->getName();
+ if (!nodeName.empty())
+ nodeInfo[nodeName]++;
+ }
+
+ void dumpInfo()
+ {
+ using namespace std;
+ typedef vector<InfoMap::iterator> FreqVector;
+ cout << "class info:\n";
+ FreqVector classes;
+ for (InfoMap::iterator itr = classInfo.begin(), end = classInfo.end();
+ itr != end;
+ ++itr)
+ classes.push_back(itr);
+ sort(classes.begin(), classes.end(), freqComp);
+ for (FreqVector::iterator itr = classes.begin(), end = classes.end();
+ itr != end;
+ ++itr) {
+ cout << (*itr)->first << " " << (*itr)->second << "\n";
+ }
+ cout << "\nnode info:\n";
+ FreqVector nodes;
+ for (InfoMap::iterator itr = nodeInfo.begin(), end = nodeInfo.end();
+ itr != end;
+ ++itr)
+ nodes.push_back(itr);
+
+ sort (nodes.begin(), nodes.end(), freqComp);
+ for (FreqVector::iterator itr = nodes.begin(), end = nodes.end();
+ itr != end;
+ ++itr) {
+ cout << (*itr)->first << " " << (*itr)->second << "\n";
+ }
+ cout << endl;
+ }
+
+ void doTraversal(Camera* camera, Node* root, Viewport* viewport)
+ {
+ ref_ptr<RefMatrix> projection
+ = createOrReuseMatrix(camera->getProjectionMatrix());
+ ref_ptr<RefMatrix> mv = createOrReuseMatrix(camera->getViewMatrix());
+ if (!viewport)
+ viewport = camera->getViewport();
+ if (viewport)
+ pushViewport(viewport);
+ pushProjectionMatrix(projection.get());
+ pushModelViewMatrix(mv.get(), Transform::ABSOLUTE_RF);
+ root->accept(*this);
+ popModelViewMatrix();
+ popProjectionMatrix();
+ if (viewport)
+ popViewport();
+ dumpInfo();
+ }
+
+ void apply(Node& node)
+ {
+ if (isCulled(node))
+ return;
+ pushCurrentMask();
+ getNodeInfo(&node);
+ traverse(node);
+ popCurrentMask();
+ }
+ void apply(Group& node)
+ {
+ if (isCulled(node))
+ return;
+ pushCurrentMask();
+ getNodeInfo(&node);
+ traverse(node);
+ popCurrentMask();
+ }
+
+ void apply(Transform& node)
+ {
+ if (isCulled(node))
+ return;
+ pushCurrentMask();
+ ref_ptr<RefMatrix> matrix = createOrReuseMatrix(*getModelViewMatrix());
+ node.computeLocalToWorldMatrix(*matrix,this);
+ pushModelViewMatrix(matrix.get(), node.getReferenceFrame());
+ getNodeInfo(&node);
+ traverse(node);
+ popModelViewMatrix();
+ popCurrentMask();
+ }
+
+ void apply(Camera& camera)
+ {
+ // Save current cull settings
+ CullSettings saved_cull_settings(*this);
+
+ // set cull settings from this Camera
+ setCullSettings(camera);
+ // inherit the settings from above
+ inheritCullSettings(saved_cull_settings, camera.getInheritanceMask());
+
+ // set the cull mask.
+ unsigned int savedTraversalMask = getTraversalMask();
+ bool mustSetCullMask = (camera.getInheritanceMask()
+ & osg::CullSettings::CULL_MASK) == 0;
+ if (mustSetCullMask)
+ setTraversalMask(camera.getCullMask());
+
+ osg::RefMatrix* projection = 0;
+ osg::RefMatrix* modelview = 0;
+
+ if (camera.getReferenceFrame()==osg::Transform::RELATIVE_RF) {
+ if (camera.getTransformOrder()==osg::Camera::POST_MULTIPLY) {
+ projection = createOrReuseMatrix(*getProjectionMatrix()
+ *camera.getProjectionMatrix());
+ modelview = createOrReuseMatrix(*getModelViewMatrix()
+ * camera.getViewMatrix());
+ }
+ else { // pre multiply
+ projection = createOrReuseMatrix(camera.getProjectionMatrix()
+ * (*getProjectionMatrix()));
+ modelview = createOrReuseMatrix(camera.getViewMatrix()
+ * (*getModelViewMatrix()));
+ }
+ } else {
+ // an absolute reference frame
+ projection = createOrReuseMatrix(camera.getProjectionMatrix());
+ modelview = createOrReuseMatrix(camera.getViewMatrix());
+ }
+ if (camera.getViewport())
+ pushViewport(camera.getViewport());
+
+ pushProjectionMatrix(projection);
+ pushModelViewMatrix(modelview, camera.getReferenceFrame());
+
+ traverse(camera);
+
+ // restore the previous model view matrix.
+ popModelViewMatrix();
+
+ // restore the previous model view matrix.
+ popProjectionMatrix();
+
+ if (camera.getViewport()) popViewport();
+
+ // restore the previous traversal mask settings
+ if (mustSetCullMask)
+ setTraversalMask(savedTraversalMask);
+
+ // restore the previous cull settings
+ setCullSettings(saved_cull_settings);
+ }
+
+protected:
+ // sort in reverse
+ static bool freqComp(const InfoMap::iterator& lhs, const InfoMap::iterator& rhs)
+ {
+ return lhs->second > rhs->second;
+ }
+ InfoMap classInfo;
+ InfoMap nodeInfo;
+};
+
+bool printVisibleSceneInfo(FGRenderer* renderer)
+{
+ osgViewer::Viewer* viewer = renderer->getViewer();
+ VisibleSceneInfoVistor vsv;
+ Viewport* vp = 0;
+ if (!viewer->getCamera()->getViewport() && viewer->getNumSlaves() > 0) {
+ const View::Slave& slave = viewer->getSlave(0);
+ vp = slave._camera->getViewport();
+ }
+ vsv.doTraversal(viewer->getCamera(), viewer->getSceneData(), vp);
+ return true;
+}
+}
// end of renderer.cxx