diff --git a/src/FDM/groundcache.cxx b/src/FDM/groundcache.cxx index 2cedf7cc8..035302dac 100644 --- a/src/FDM/groundcache.cxx +++ b/src/FDM/groundcache.cxx @@ -194,11 +194,6 @@ public: FGGroundCache::GroundProperty& gp = mGroundProperty; // get some material information for use in the gear model - gp.material = globals->get_matlib()->findMaterial(&node); - if (gp.material) { - gp.type = gp.material->get_solid() ? FGInterface::Solid : FGInterface::Water; - return true; - } gp.type = FGInterface::Unknown; osg::Referenced* base = node.getUserData(); if (!base) @@ -235,6 +230,12 @@ public: bool oldBackfaceCulling = mBackfaceCulling; updateCullMode(drawable->getStateSet()); + FGGroundCache::GroundProperty& gp = mGroundProperty; + // get some material information for use in the gear model + gp.material = globals->get_matlib()->findMaterial(drawable->getStateSet()); + if (gp.material) + gp.type = gp.material->get_solid() ? FGInterface::Solid : FGInterface::Water; + drawable->accept(mTriangleFunctor); mBackfaceCulling = oldBackfaceCulling; diff --git a/src/Main/fg_commands.cxx b/src/Main/fg_commands.cxx index de4336833..bcde46e68 100644 --- a/src/Main/fg_commands.cxx +++ b/src/Main/fg_commands.cxx @@ -1240,7 +1240,7 @@ do_terrain_elevation (const SGPropertyNode * arg) double lon = arg->getDoubleValue("longitude-deg", 0.0); double lat = arg->getDoubleValue("latitude-deg", 0.0); double elev; - bool ret = globals->get_scenery()->get_elevation_m(lat, lon, 10000.0, elev, 0, false); + bool ret = globals->get_scenery()->get_elevation_m(lat, lon, 10000.0, elev, 0); const_cast(arg)->setDoubleValue("elevation-m", elev); return ret; } diff --git a/src/Main/main.cxx b/src/Main/main.cxx index 70a4e5966..94729fc73 100644 --- a/src/Main/main.cxx +++ b/src/Main/main.cxx @@ -514,8 +514,7 @@ static void fgMainLoop( void ) { double visibility_meters = fgGetDouble("/environment/visibility-m"); FGViewer *current_view = globals->get_current_view(); - globals->get_tile_mgr()->prep_ssg_nodes( current_view->getSGLocation(), - visibility_meters ); + globals->get_tile_mgr()->prep_ssg_nodes( visibility_meters ); // update tile manager for view... SGLocation *view_location = globals->get_current_view()->getSGLocation(); globals->get_tile_mgr()->update( view_location, visibility_meters ); diff --git a/src/Main/renderer.cxx b/src/Main/renderer.cxx index ad13865fc..755be7a6d 100644 --- a/src/Main/renderer.cxx +++ b/src/Main/renderer.cxx @@ -313,6 +313,20 @@ private: SGSharedPtr mFogEnabled; }; +class FGFogUpdateCallback : public osg::StateAttribute::Callback { +public: + virtual void operator () (osg::StateAttribute* sa, osg::NodeVisitor* nv) + { + assert(dynamic_cast(nv)); + assert(dynamic_cast(sa)); + SGUpdateVisitor* updateVisitor = static_cast(nv); + osg::Fog* fog = static_cast(sa); + fog->setMode(osg::Fog::EXP2); + fog->setColor(updateVisitor->getFogColor().osg()); + fog->setDensity(updateVisitor->getFogExp2Density()); + } +}; + // update callback for the switch node guarding that splash class FGScenerySwitchCallback : public osg::NodeCallback { public: @@ -330,16 +344,6 @@ public: } }; -// fog constants. I'm a little nervous about putting actual code out -// here but it seems to work (?) -static const double m_log01 = -log( 0.01 ); -static const double sqrt_m_log01 = sqrt( m_log01 ); -static GLfloat fog_exp_density; -static GLfloat fog_exp2_density; -static GLfloat rwy_exp2_punch_through; -static GLfloat taxi_exp2_punch_through; -static GLfloat ground_exp2_punch_through; - // Sky structures SGSky *thesky; @@ -354,11 +358,6 @@ static osg::ref_ptr mRoot = new osg::Group; static osg::ref_ptr mCameraView = new osg::CameraView; static osg::ref_ptr mBackGroundCamera = new osg::Camera; -static osg::ref_ptr mFog = new osg::Fog; -static osg::ref_ptr mRunwayLightingFog = new osg::Fog; -static osg::ref_ptr mTaxiLightingFog = new osg::Fog; -static osg::ref_ptr mGroundLightingFog = new osg::Fog; - FGRenderer::FGRenderer() { #ifdef FG_JPEG_SERVER @@ -412,10 +411,6 @@ FGRenderer::init( void ) { glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE); glHint(GL_POINT_SMOOTH_HINT, GL_DONT_CARE); - mFog->setMode(osg::Fog::EXP2); - mRunwayLightingFog->setMode(osg::Fog::EXP2); - mTaxiLightingFog->setMode(osg::Fog::EXP2); - mGroundLightingFog->setMode(osg::Fog::EXP2); sceneView->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR); sceneView->getCamera()->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR); @@ -502,7 +497,9 @@ FGRenderer::init( void ) { stateSet->setAttributeAndModes(polygonMode); // scene fog handling - stateSet->setAttributeAndModes(mFog.get()); + osg::Fog* fog = new osg::Fog; + fog->setUpdateCallback(new FGFogUpdateCallback); + stateSet->setAttributeAndModes(fog); stateSet->setUpdateCallback(new FGFogEnableUpdateCallback); // plug in the GUI @@ -520,28 +517,6 @@ FGRenderer::init( void ) { geode->addDrawable(new SGHUDAndPanelDrawable); guiCamera->addChild(geode); - // this one contains all lights, here we set the light states we did - // in the plib case with plain OpenGL - osg::Group* lightGroup = new osg::Group; - sceneGroup->addChild(lightGroup); - lightGroup->addChild(globals->get_scenery()->get_gnd_lights_root()); - lightGroup->addChild(globals->get_scenery()->get_vasi_lights_root()); - lightGroup->addChild(globals->get_scenery()->get_rwy_lights_root()); - lightGroup->addChild(globals->get_scenery()->get_taxi_lights_root()); - - stateSet = globals->get_scenery()->get_gnd_lights_root()->getOrCreateStateSet(); - stateSet->setAttributeAndModes(mFog.get()); - stateSet->setUpdateCallback(new FGFogEnableUpdateCallback); - stateSet = globals->get_scenery()->get_vasi_lights_root()->getOrCreateStateSet(); - stateSet->setAttributeAndModes(mRunwayLightingFog.get()); - stateSet->setUpdateCallback(new FGFogEnableUpdateCallback); - stateSet = globals->get_scenery()->get_rwy_lights_root()->getOrCreateStateSet(); - stateSet->setAttributeAndModes(mRunwayLightingFog.get()); - stateSet->setUpdateCallback(new FGFogEnableUpdateCallback); - stateSet = globals->get_scenery()->get_taxi_lights_root()->getOrCreateStateSet(); - stateSet->setAttributeAndModes(mTaxiLightingFog.get()); - stateSet->setUpdateCallback(new FGFogEnableUpdateCallback); - mCameraView->addChild(mRoot.get()); osg::Switch* sw = new osg::Switch; @@ -600,26 +575,6 @@ FGRenderer::update( bool refresh_camera_settings ) { actual_visibility = fgGetDouble("/environment/visibility-m"); } - static double last_visibility = -9999; - if ( actual_visibility != last_visibility ) { - last_visibility = actual_visibility; - - fog_exp_density = m_log01 / actual_visibility; - fog_exp2_density = sqrt_m_log01 / actual_visibility; - ground_exp2_punch_through = sqrt_m_log01 / (actual_visibility * 1.5); - if ( actual_visibility < 8000 ) { - rwy_exp2_punch_through = sqrt_m_log01 / (actual_visibility * 2.5); - taxi_exp2_punch_through = sqrt_m_log01 / (actual_visibility * 1.5); - } else { - rwy_exp2_punch_through = sqrt_m_log01 / ( 8000 * 2.5 ); - taxi_exp2_punch_through = sqrt_m_log01 / ( 8000 * 1.5 ); - } - mFog->setDensity(fog_exp2_density); - mRunwayLightingFog->setDensity(rwy_exp2_punch_through); - mTaxiLightingFog->setDensity(taxi_exp2_punch_through); - mGroundLightingFog->setDensity(ground_exp2_punch_through); - } - // idle_state is now 1000 meaning we've finished all our // initializations and are running the main loop, so this will // now work without seg faulting the system. @@ -758,15 +713,6 @@ FGRenderer::update( bool refresh_camera_settings ) { } - if ( strcmp(fgGetString("/sim/rendering/fog"), "disabled") ) { - SGVec4f color(l->adj_fog_color()); - mFog->setColor(color.osg()); - mRunwayLightingFog->setColor(color.osg()); - mTaxiLightingFog->setColor(color.osg()); - mGroundLightingFog->setColor(color.osg()); - } - - // sgEnviro.setLight(l->adj_fog_color()); // texture parameters @@ -822,10 +768,11 @@ FGRenderer::update( bool refresh_camera_settings ) { mFrameStamp->setCalendarTime(*globals->get_time_params()->getGmt()); mUpdateVisitor->setViewData(current__view->getViewPosition(), current__view->getViewOrientation()); - mUpdateVisitor->setSceneryCenter(SGVec3d(0, 0, 0)); SGVec3f direction(l->sun_vec()[0], l->sun_vec()[1], l->sun_vec()[2]); mUpdateVisitor->setLight(direction, l->scene_ambient(), - l->scene_diffuse(), l->scene_specular()); + l->scene_diffuse(), l->scene_specular(), + l->adj_fog_color(), + l->get_sun_angle()*SGD_RADIANS_TO_DEGREES); mUpdateVisitor->setVisibility(actual_visibility); if (fgGetBool("/sim/panel-hotspots")) diff --git a/src/Scenery/FGTileLoader.cxx b/src/Scenery/FGTileLoader.cxx index e8fee269a..3b6d3ce93 100644 --- a/src/Scenery/FGTileLoader.cxx +++ b/src/Scenery/FGTileLoader.cxx @@ -32,10 +32,6 @@ #include "tileentry.hxx" #include "tilemgr.hxx" -extern ssgBranch *terrain; -extern ssgBranch *ground; - - /** * */ diff --git a/src/Scenery/scenery.cxx b/src/Scenery/scenery.cxx index 26f49e4c9..b24131196 100644 --- a/src/Scenery/scenery.cxx +++ b/src/Scenery/scenery.cxx @@ -97,19 +97,6 @@ void FGScenery::init() { aircraft_branch->setName( "Aircraft" ); scene_graph->addChild( aircraft_branch.get() ); - // Lighting - gnd_lights_root = new osg::Group; - gnd_lights_root->setName( "Ground Lighting Root" ); - - vasi_lights_root = new osg::Group; - vasi_lights_root->setName( "VASI/PAPI Lighting Root" ); - - rwy_lights_root = new osg::Group; - rwy_lights_root->setName( "Runway Lighting Root" ); - - taxi_lights_root = new osg::Group; - taxi_lights_root->setName( "Taxi Lighting Root" ); - // Initials values needed by the draw-time object loader sgUserDataInit( globals->get_model_lib(), globals->get_fg_root(), globals->get_props(), globals->get_sim_time_sec() ); @@ -129,18 +116,16 @@ void FGScenery::unbind() { bool FGScenery::get_elevation_m(double lat, double lon, double max_alt, - double& alt, const SGMaterial** material, - bool exact) + double& alt, const SGMaterial** material) { SGGeod geod = SGGeod::fromDegM(lon, lat, max_alt); SGVec3d pos = SGVec3d::fromGeod(geod); - return get_cart_elevation_m(pos, 0, alt, material, exact); + return get_cart_elevation_m(pos, 0, alt, material); } bool FGScenery::get_cart_elevation_m(const SGVec3d& pos, double max_altoff, - double& alt, const SGMaterial** material, - bool exact) + double& alt, const SGMaterial** material) { if ( norm1(pos) < 1 ) return false; @@ -167,8 +152,10 @@ FGScenery::get_cart_elevation_m(const SGVec3d& pos, double max_altoff, double elevation = geod.getElevationM(); if (alt < elevation) { alt = elevation; - if (material) - *material = globals->get_matlib()->findMaterial(hit.getGeode()); + if (material) { + const osg::StateSet* stateSet = hit.getDrawable()->getStateSet(); + *material = globals->get_matlib()->findMaterial(stateSet); + } } } } @@ -178,7 +165,7 @@ FGScenery::get_cart_elevation_m(const SGVec3d& pos, double max_altoff, bool FGScenery::get_cart_ground_intersection(const SGVec3d& pos, const SGVec3d& dir, - SGVec3d& nearestHit, bool exact) + SGVec3d& nearestHit) { // We assume that starting positions in the center of the earth are invalid if ( norm1(pos) < 1 ) diff --git a/src/Scenery/scenery.hxx b/src/Scenery/scenery.hxx index 49b3dce4e..55dca7a90 100644 --- a/src/Scenery/scenery.hxx +++ b/src/Scenery/scenery.hxx @@ -29,35 +29,21 @@ # error This library requires C++ #endif -#include - #include #include #include +#include #include -#include -#include -#include - -SG_USING_STD(list); class SGMaterial; - // Define a structure containing global scenery parameters class FGScenery : public SGSubsystem { - // FIXME this should be a views property - // angle of sun relative to current local horizontal - double sun_angle; // scene graph osg::ref_ptr scene_graph; osg::ref_ptr terrain_branch; - osg::ref_ptr gnd_lights_root; - osg::ref_ptr vasi_lights_root; - osg::ref_ptr rwy_lights_root; - osg::ref_ptr taxi_lights_root; osg::ref_ptr models_branch; osg::ref_ptr aircraft_branch; @@ -83,8 +69,7 @@ public: /// value is undefined. /// All values are meant to be in meters or degrees. bool get_elevation_m(double lat, double lon, double max_alt, - double& alt, const SGMaterial** material, - bool exact = false); + double& alt, const SGMaterial** material); /// Compute the elevation of the scenery beow the cartesian point pos. /// you the returned scenery altitude is not higher than the position @@ -98,8 +83,7 @@ public: /// value is undefined. /// All values are meant to be in meters. bool get_cart_elevation_m(const SGVec3d& pos, double max_altoff, - double& radius, const SGMaterial** material, - bool exact = false); + double& radius, const SGMaterial** material); /// Compute the nearest intersection point of the line starting from /// start going in direction dir with the terrain. @@ -107,55 +91,12 @@ public: /// usual earth centered wgs84 coordiante system. Units are meters. /// On success, true is returned. bool get_cart_ground_intersection(const SGVec3d& start, const SGVec3d& dir, - SGVec3d& nearestHit, bool exact = false); + SGVec3d& nearestHit); osg::Group *get_scene_graph () const { return scene_graph.get(); } - inline void set_scene_graph (osg::Group * s) { scene_graph = s; } - osg::Group *get_terrain_branch () const { return terrain_branch.get(); } - inline void set_terrain_branch (osg::Group * t) { terrain_branch = t; } - - inline osg::Group *get_gnd_lights_root () const { - return gnd_lights_root.get(); - } - inline void set_gnd_lights_root (osg::Group *r) { - gnd_lights_root = r; - } - - inline osg::Group *get_vasi_lights_root () const { - return vasi_lights_root.get(); - } - inline void set_vasi_lights_root (osg::Group *r) { - vasi_lights_root = r; - } - - inline osg::Group *get_rwy_lights_root () const { - return rwy_lights_root.get(); - } - inline void set_rwy_lights_root (osg::Group *r) { - rwy_lights_root = r; - } - - inline osg::Group *get_taxi_lights_root () const { - return taxi_lights_root.get(); - } - inline void set_taxi_lights_root (osg::Group *r) { - taxi_lights_root = r; - } - - inline osg::Group *get_models_branch () const { - return models_branch.get(); - } - inline void set_models_branch (osg::Group *t) { - models_branch = t; - } - - inline osg::Group *get_aircraft_branch () const { - return aircraft_branch.get(); - } - inline void set_aircraft_branch (osg::Group *t) { - aircraft_branch = t; - } + osg::Group *get_models_branch () const { return models_branch.get(); } + osg::Group *get_aircraft_branch () const { return aircraft_branch.get(); } }; diff --git a/src/Scenery/tileentry.cxx b/src/Scenery/tileentry.cxx index 45c8bf440..1f2564597 100644 --- a/src/Scenery/tileentry.cxx +++ b/src/Scenery/tileentry.cxx @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -65,41 +66,42 @@ SG_USING_STD(string); +class FGTileUpdateCallback : public osg::NodeCallback { +public: + virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + { + assert(dynamic_cast(nv)); + SGUpdateVisitor* updateVisitor = static_cast(nv); + + osg::Vec3 center = node->getBound().center(); + double dist2 = distSqr(updateVisitor->getGlobalEyePos(), + SGVec3d(center[0], center[1], center[2])); + if (updateVisitor->getSqrVisibility() < dist2) + return; + + traverse(node, nv); + } +}; // Constructor FGTileEntry::FGTileEntry ( const SGBucket& b ) - : center( Point3D( 0.0 ) ), - tile_bucket( b ), - terra_transform( new SGPlacementTransform ), - vasi_lights_transform( new SGPlacementTransform ), - rwy_lights_transform( new SGPlacementTransform ), - taxi_lights_transform( new SGPlacementTransform ), + : tile_bucket( b ), + terra_transform( new osg::Group ), terra_range( new osg::LOD ), - vasi_lights_selector( new osg::Switch ), - rwy_lights_selector( new osg::Switch ), - taxi_lights_selector( new osg::Switch ), loaded(false), pending_models(0), is_inner_ring(false), free_tracker(0) { - // update the contents - // if ( vec3_ptrs.size() || vec2_ptrs.size() || index_ptrs.size() ) { - // SG_LOG( SG_TERRAIN, SG_ALERT, - // "Attempting to overwrite existing or" - // << " not properly freed leaf data." ); - // exit(-1); - // } + terra_transform->setUpdateCallback(new FGTileUpdateCallback); } // Destructor FGTileEntry::~FGTileEntry () { - // cout << "nodes = " << nodes.size() << endl;; - // delete[] nodes; } -static void WorldCoordinate( osg::Matrix& obj_pos, Point3D center, double lat, +static void WorldCoordinate( osg::Matrix& obj_pos, double lat, double lon, double elev, double hdg ) { double lon_rad = lon * SGD_DEGREES_TO_RADIANS; @@ -110,30 +112,30 @@ static void WorldCoordinate( osg::Matrix& obj_pos, Point3D center, double lat, Point3D geod( lon_rad, lat_rad, elev ); Point3D world_pos = sgGeodToCart( geod ); - Point3D offset = world_pos - center; + Point3D offset = world_pos; - sgMat4 mat; + sgdMat4 mat; - SGfloat sin_lat = (SGfloat)sin( lat_rad ); - SGfloat cos_lat = (SGfloat)cos( lat_rad ); - SGfloat cos_lon = (SGfloat)cos( lon_rad ); - SGfloat sin_lon = (SGfloat)sin( lon_rad ); - SGfloat sin_hdg = (SGfloat)sin( hdg_rad ) ; - SGfloat cos_hdg = (SGfloat)cos( hdg_rad ) ; + double sin_lat = sin( lat_rad ); + double cos_lat = cos( lat_rad ); + double cos_lon = cos( lon_rad ); + double sin_lon = sin( lon_rad ); + double sin_hdg = sin( hdg_rad ) ; + double cos_hdg = cos( hdg_rad ) ; - mat[0][0] = cos_hdg * (SGfloat)sin_lat * (SGfloat)cos_lon - sin_hdg * (SGfloat)sin_lon; - mat[0][1] = cos_hdg * (SGfloat)sin_lat * (SGfloat)sin_lon + sin_hdg * (SGfloat)cos_lon; - mat[0][2] = -cos_hdg * (SGfloat)cos_lat; + mat[0][0] = cos_hdg * sin_lat * cos_lon - sin_hdg * sin_lon; + mat[0][1] = cos_hdg * sin_lat * sin_lon + sin_hdg * cos_lon; + mat[0][2] = -cos_hdg * cos_lat; mat[0][3] = SG_ZERO; - mat[1][0] = -sin_hdg * (SGfloat)sin_lat * (SGfloat)cos_lon - cos_hdg * (SGfloat)sin_lon; - mat[1][1] = -sin_hdg * (SGfloat)sin_lat * (SGfloat)sin_lon + cos_hdg * (SGfloat)cos_lon; - mat[1][2] = sin_hdg * (SGfloat)cos_lat; + mat[1][0] = -sin_hdg * sin_lat * cos_lon - cos_hdg * sin_lon; + mat[1][1] = -sin_hdg * sin_lat * sin_lon + cos_hdg * cos_lon; + mat[1][2] = sin_hdg * cos_lat; mat[1][3] = SG_ZERO; - mat[2][0] = (SGfloat)cos_lat * (SGfloat)cos_lon; - mat[2][1] = (SGfloat)cos_lat * (SGfloat)sin_lon; - mat[2][2] = (SGfloat)sin_lat; + mat[2][0] = cos_lat * cos_lon; + mat[2][1] = cos_lat * sin_lon; + mat[2][2] = sin_lat; mat[2][3] = SG_ZERO; mat[3][0] = offset.x(); @@ -147,52 +149,15 @@ static void WorldCoordinate( osg::Matrix& obj_pos, Point3D center, double lat, } -// recurse an ssg tree and call removeChild() on every node from the -// bottom up. Leaves the original branch in existance, but empty so -// it can be removed by the calling routine. -// static void my_remove_branch( osg::Group * branch ) { -// branch->removeChildren(0, branch->getNumChildren()); -// } - - // Free "n" leaf elements of an ssg tree. returns the number of // elements freed. An empty branch node is considered a leaf. This // is intended to spread the load of freeing a complex tile out over // several frames. static int fgPartialFreeSSGtree( osg::Group *b, int n ) { - int num_deletes = 0; + int num_deletes = b->getNumChildren(); b->removeChildren(0, b->getNumChildren()); -// if ( n > 0 ) { -// // we still have some delete budget left -// // if ( b->getNumChilds() > 100 ) { -// // cout << "large family = " << b->getNumChilds() << endl; -// // } -// // deleting in reverse would help if my plib patch get's -// // applied, but for now it will make things slower. -// // for ( int i = b->getNumChilds() - 1; i >= 0 ; --i ) { -// for ( int i = 0; i < b->getNumChildren(); ++i ) { -// ssgEntity *kid = b->getChild(i); -// if ( kid->isAKindOf( ssgTypeBranch() ) && kid->getRef() <= 1 ) { -// int result = fgPartialFreeSSGtree( (osg::Group *)kid, n ); -// num_deletes += result; -// n -= result; -// if ( n < 0 ) { -// break; -// } -// } -// // remove the kid if (a) it is now empty -or- (b) it's ref -// // count is > zero at which point we don't care if it's -// // empty, we don't want to touch it's contents. -// if ( kid->getNumChildren() == 0 || kid->getRef() > 1 ) { -// b->removeChild( kid ); -// num_deletes++; -// n--; -// } -// } -// } - return num_deletes; } @@ -218,38 +183,6 @@ bool FGTileEntry::free_tile() { terra_transform = 0; free_tracker |= TERRA_NODE; } - } else if ( !(free_tracker & GROUND_LIGHTS) && gnd_lights_transform.get() ) { - // delete the terrain lighting branch (this should already have been - // disconnected from the scene graph) - SG_LOG( SG_TERRAIN, SG_DEBUG, "FREEING gnd_lights_transform" ); - if ( fgPartialFreeSSGtree( gnd_lights_transform.get(), delete_size ) == 0 ) { - gnd_lights_transform = 0; - free_tracker |= GROUND_LIGHTS; - } - } else if ( !(free_tracker & VASI_LIGHTS) && vasi_lights_selector.get() ) { - // delete the runway lighting branch (this should already have - // been disconnected from the scene graph) - SG_LOG( SG_TERRAIN, SG_DEBUG, "FREEING vasi_lights_selector" ); - if ( fgPartialFreeSSGtree( vasi_lights_selector.get(), delete_size ) == 0 ) { - vasi_lights_selector = 0; - free_tracker |= VASI_LIGHTS; - } - } else if ( !(free_tracker & RWY_LIGHTS) && rwy_lights_selector.get() ) { - // delete the runway lighting branch (this should already have - // been disconnected from the scene graph) - SG_LOG( SG_TERRAIN, SG_DEBUG, "FREEING rwy_lights_selector" ); - if ( fgPartialFreeSSGtree( rwy_lights_selector.get(), delete_size ) == 0 ) { - rwy_lights_selector = 0; - free_tracker |= RWY_LIGHTS; - } - } else if ( !(free_tracker & TAXI_LIGHTS) && taxi_lights_selector.get() ) { - // delete the taxi lighting branch (this should already have been - // disconnected from the scene graph) - SG_LOG( SG_TERRAIN, SG_DEBUG, "FREEING taxi_lights_selector" ); - if ( fgPartialFreeSSGtree( taxi_lights_selector.get(), delete_size ) == 0 ) { - taxi_lights_selector = 0; - free_tracker |= TAXI_LIGHTS; - } } else if ( !(free_tracker & LIGHTMAPS) ) { free_tracker |= LIGHTMAPS; } else { @@ -265,167 +198,27 @@ bool FGTileEntry::free_tile() { // Update the ssg transform node for this tile so it can be // properly drawn relative to our (0,0,0) point -void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) { +void FGTileEntry::prep_ssg_node(float vis) { if ( !loaded ) return; // visibility can change from frame to frame so we update the // range selector cutoff's each time. + float bounding_radius = terra_range->getChild(0)->getBound().radius(); terra_range->setRange( 0, 0, vis + bounding_radius ); - - if ( gnd_lights_range.get() ) { - gnd_lights_range->setRange( 0, 0, vis * 1.5 + bounding_radius ); - } - - SGVec3d lt_trans(center.x(), center.y(), center.z()); - - FGLight *l = (FGLight *)(globals->get_subsystem("lighting")); - if ( gnd_lights_transform.get() ) { - // we need to lift the lights above the terrain to avoid - // z-buffer fighting. We do this based on our altitude and - // the distance this tile is away from scenery center. - - // we expect 'up' to be a unit vector coming in, but since we - // modify the value of lift_vec, we need to create a local - // copy. - SGVec3f lift_vec(up); - - double agl; - agl = globals->get_current_view()->getAltitudeASL_ft()*SG_FEET_TO_METER - - globals->get_current_view()->getSGLocation()->get_cur_elev_m(); - - // Compute the distance of the scenery center from the view position. - double dist = center.distance3D(p); - - if ( general.get_glDepthBits() > 16 ) { - lift_vec *= 10.0 + agl / 100.0 + dist / 10000; - } else { - lift_vec *= 10.0 + agl / 20.0 + dist / 5000; - } - - gnd_lights_transform->setTransform( lt_trans + toVec3d(lift_vec) ); - - // select which set of lights based on sun angle - float sun_angle = l->get_sun_angle() * SGD_RADIANS_TO_DEGREES; - if ( sun_angle > 95 ) { - gnd_lights_brightness->setSingleChildOn(2); - } else if ( sun_angle > 92 ) { - gnd_lights_brightness->setSingleChildOn(1); - } else if ( sun_angle > 89 ) { - gnd_lights_brightness->setSingleChildOn(0); - } else { - gnd_lights_brightness->setAllChildrenOff(); - } - } - - if ( rwy_lights_transform.get() ) { - // turn runway lights on/off based on sun angle and visibility - float sun_angle = l->get_sun_angle() * SGD_RADIANS_TO_DEGREES; - if ( sun_angle > 85 || - (fgGetDouble("/environment/visibility-m") < 5000.0) ) { - rwy_lights_selector->setAllChildrenOn(); - } else { - rwy_lights_selector->setAllChildrenOff(); - } - } - - if ( taxi_lights_transform.get() ) { - // turn taxi lights on/off based on sun angle and visibility - float sun_angle = l->get_sun_angle() * SGD_RADIANS_TO_DEGREES; - if ( sun_angle > 85 || - (fgGetDouble("/environment/visibility-m") < 5000.0) ) { - taxi_lights_selector->setAllChildrenOn(); - } else { - taxi_lights_selector->setAllChildrenOff(); - } - } } - -osg::Node* -FGTileEntry::gen_lights( SGMaterialLib *matlib, osg::Vec3Array *lights, - int inc, float bright ) -{ - // generate a repeatable random seed - sg_srandom( (unsigned)(*lights)[0][0] ); - - // Allocate ssg structure - osg::Vec3Array *vl = new osg::Vec3Array; - osg::Vec4Array *cl = new osg::Vec4Array; - - for ( unsigned i = 0; i < lights->size(); ++i ) { - // this loop is slightly less efficient than it otherwise - // could be, but we want a red light to always be red, and a - // yellow light to always be yellow, etc. so we are trying to - // preserve the random sequence. - float zombie = sg_random(); - if ( i % inc == 0 ) { - vl->push_back( (*lights)[i] ); - - // factor = sg_random() ^ 2, range = 0 .. 1 concentrated towards 0 - float factor = sg_random(); - factor *= factor; - - osg::Vec4 color; - if ( zombie > 0.5 ) { - // 50% chance of yellowish - color = osg::Vec4( 0.9, 0.9, 0.3, bright - factor * 0.2 ); - } else if ( zombie > 0.15 ) { - // 35% chance of whitish - color = osg::Vec4( 0.9, 0.9, 0.8, bright - factor * 0.2 ); - } else if ( zombie > 0.05 ) { - // 10% chance of orangish - color = osg::Vec4( 0.9, 0.6, 0.2, bright - factor * 0.2 ); - } else { - // 5% chance of redish - color = osg::Vec4( 0.9, 0.2, 0.2, bright - factor * 0.2 ); - } - cl->push_back( color ); - } - } - - // create ssg leaf - osg::Geometry* geometry = new osg::Geometry; - geometry->setVertexArray(vl); - geometry->setColorArray(cl); - geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX); - geometry->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, 0, vl->size())); - osg::Geode* geode = new osg::Geode; - geode->addDrawable(geometry); - - // assign state - SGMaterial *mat = matlib->find( "GROUND_LIGHTS" ); - geode->setStateSet(mat->get_state()); - - return geode; -} - - bool FGTileEntry::obj_load( const string& path, - osg::Group *geometry, - osg::Group *vasi_lights, - osg::Group *rwy_lights, - osg::Group *taxi_lights, - osg::Vec3Array *ground_lights, bool is_base ) + osg::Group *geometry, bool is_base ) { - Point3D c; // returned center point - double br; // returned bounding radius - bool use_random_objects = fgGetBool("/sim/rendering/random-objects", true); // try loading binary format - if ( SGBinObjLoad( path, is_base, - &c, &br, globals->get_matlib(), use_random_objects, - geometry, vasi_lights, rwy_lights, taxi_lights, - ground_lights ) ) - { - if ( is_base ) { - center = c; - bounding_radius = br; - } - } + osg::Node* node = SGLoadBTG(path, globals->get_matlib(), is_base, use_random_objects); + if (node) + geometry->addChild(node); - return (geometry != NULL); + return node; } @@ -562,30 +355,17 @@ FGTileEntry::load( const string_list &path_list, bool is_base ) // obj_load() will generate ground lighting for us ... - osg::ref_ptr light_pts = new osg::Vec3Array; osg::Group* new_tile = new osg::Group; - if (found_tile_base) { // load tile if found ... - osg::ref_ptr geometry = new osg::Group; - if ( obj_load( object_base.str(), geometry.get(), - NULL, NULL, NULL, light_pts.get(), true ) ) { - new_tile -> addChild( geometry.get() ); - } + obj_load( object_base.str(), new_tile, true ); } else { // ... or generate an ocean tile on the fly SG_LOG(SG_TERRAIN, SG_INFO, " Generating ocean tile"); - osg::ref_ptr geometry = new osg::Group; - Point3D c; - double br; - if ( SGGenTile( path_list[0], tile_bucket, &c, &br, - globals->get_matlib(), geometry.get() ) ) { - center = c; - bounding_radius = br; - new_tile -> addChild( geometry.get() ); - } else { + if ( !SGGenTile( path_list[0], tile_bucket, + globals->get_matlib(), new_tile ) ) { SG_LOG( SG_TERRAIN, SG_ALERT, "Warning: failed to generate ocean tile!" ); } @@ -599,30 +379,7 @@ FGTileEntry::load( const string_list &path_list, bool is_base ) if (obj->type == OBJECT) { SGPath custom_path = obj->path; custom_path.append( obj->name ); - - osg::ref_ptr geometry = new osg::Group; - osg::ref_ptr vasi_lights = new osg::Group; - osg::ref_ptr rwy_lights = new osg::Group; - osg::ref_ptr taxi_lights = new osg::Group; - - if ( obj_load( custom_path.str(), - geometry.get(), vasi_lights.get(), rwy_lights.get(), - taxi_lights.get(), NULL, false ) ) { - - if ( geometry -> getNumChildren() > 0 ) { - new_tile -> addChild( geometry.get() ); - } - - if ( vasi_lights -> getNumChildren() > 0 ) - vasi_lights_transform -> addChild( vasi_lights.get() ); - - if ( rwy_lights -> getNumChildren() > 0 ) - rwy_lights_transform -> addChild( rwy_lights.get() ); - - if ( taxi_lights -> getNumChildren() > 0 ) - taxi_lights_transform -> addChild( taxi_lights.get() ); - } - + obj_load( custom_path.str(), new_tile, false ); } else if (obj->type == OBJECT_SHARED || obj->type == OBJECT_STATIC) { // object loading is deferred to main render thread, @@ -636,7 +393,7 @@ FGTileEntry::load( const string_list &path_list, bool is_base ) custom_path.append( obj->name ); osg::Matrix obj_pos; - WorldCoordinate( obj_pos, center, obj->lat, obj->lon, obj->elev, obj->hdg ); + WorldCoordinate( obj_pos, obj->lat, obj->lon, obj->elev, obj->hdg ); osg::MatrixTransform *obj_trans = new osg::MatrixTransform; obj_trans->setMatrix( obj_pos ); @@ -661,7 +418,7 @@ FGTileEntry::load( const string_list &path_list, bool is_base ) custom_path.append( obj->name ); osg::Matrix obj_pos; - WorldCoordinate( obj_pos, center, obj->lat, obj->lon, obj->elev, obj->hdg ); + WorldCoordinate( obj_pos, obj->lat, obj->lon, obj->elev, obj->hdg ); osg::MatrixTransform *obj_trans = new osg::MatrixTransform; obj_trans->setMatrix( obj_pos ); @@ -682,63 +439,12 @@ FGTileEntry::load( const string_list &path_list, bool is_base ) delete obj; } - - if ( new_tile != NULL ) { - terra_range->addChild( new_tile ); - } - + terra_range->addChild( new_tile ); terra_transform->addChild( terra_range.get() ); - - // calculate initial tile offset - SGVec3d sgdTrans(center.x(), center.y(), center.z()); - terra_transform->setTransform( sgdTrans ); - - // Add ground lights to scene graph if any exist - gnd_lights_transform = NULL; - gnd_lights_range = NULL; - if ( light_pts->size() ) { - SG_LOG( SG_TERRAIN, SG_DEBUG, "generating lights" ); - gnd_lights_transform = new SGPlacementTransform; - gnd_lights_range = new osg::LOD; - gnd_lights_brightness = new osg::Switch; - osg::Node *lights; - - lights = gen_lights( globals->get_matlib(), light_pts.get(), 4, 0.7 ); - gnd_lights_brightness->addChild( lights ); - - lights = gen_lights( globals->get_matlib(), light_pts.get(), 2, 0.85 ); - gnd_lights_brightness->addChild( lights ); - - lights = gen_lights( globals->get_matlib(), light_pts.get(), 1, 1.0 ); - gnd_lights_brightness->addChild( lights ); - - gnd_lights_range->addChild( gnd_lights_brightness.get() ); - gnd_lights_transform->addChild( gnd_lights_range.get() ); - gnd_lights_transform->setTransform( sgdTrans ); - } - - // Update vasi lights transform - if ( vasi_lights_transform->getNumChildren() > 0 ) { - vasi_lights_transform->setTransform( sgdTrans ); - } - - // Update runway lights transform - if ( rwy_lights_transform->getNumChildren() > 0 ) { - rwy_lights_transform->setTransform( sgdTrans ); - } - - // Update taxi lights transform - if ( taxi_lights_transform->getNumChildren() > 0 ) { - taxi_lights_transform->setTransform( sgdTrans ); - } } void -FGTileEntry::add_ssg_nodes( osg::Group *terrain_branch, - osg::Group *gnd_lights_branch, - osg::Group *vasi_lights_branch, - osg::Group *rwy_lights_branch, - osg::Group *taxi_lights_branch ) +FGTileEntry::add_ssg_nodes( osg::Group *terrain_branch ) { // bump up the ref count so we can remove this later without // having ssg try to free the memory. @@ -750,33 +456,6 @@ FGTileEntry::add_ssg_nodes( osg::Group *terrain_branch, SG_LOG( SG_TERRAIN, SG_DEBUG, "num parents now = " << terra_transform->getNumParents() ); - if ( gnd_lights_transform.get() != NULL ) { - // bump up the ref count so we can remove this later without - // having ssg try to free the memory. - gnd_lights_branch->addChild( gnd_lights_transform.get() ); - } - - if ( vasi_lights_transform.get() != NULL ) { - // bump up the ref count so we can remove this later without - // having ssg try to free the memory. - vasi_lights_selector->addChild( vasi_lights_transform.get() ); - vasi_lights_branch->addChild( vasi_lights_selector.get() ); - } - - if ( rwy_lights_transform.get() != NULL ) { - // bump up the ref count so we can remove this later without - // having ssg try to free the memory. - rwy_lights_selector->addChild( rwy_lights_transform.get() ); - rwy_lights_branch->addChild( rwy_lights_selector.get() ); - } - - if ( taxi_lights_transform.get() != NULL ) { - // bump up the ref count so we can remove this later without - // having ssg try to free the memory. - taxi_lights_selector->addChild( taxi_lights_transform.get() ); - taxi_lights_branch->addChild( taxi_lights_selector.get() ); - } - loaded = true; } @@ -811,92 +490,4 @@ FGTileEntry::disconnect_ssg_nodes() "Parent count is zero for an ssg tile! Dying" ); exit(-1); } - - // find the ground lighting branch - if ( gnd_lights_transform.get() ) { - pcount = gnd_lights_transform->getNumParents(); - if ( pcount > 0 ) { - // find the first parent (should only be one) - osg::Group *parent = gnd_lights_transform->getParent( 0 ) ; - if( parent ) { - // disconnect the light branch (we previously ref()'d - // it so it won't get freed now) - parent->removeChild( gnd_lights_transform.get() ); - } else { - SG_LOG( SG_TERRAIN, SG_ALERT, - "parent pointer is NULL! Dying" ); - exit(-1); - } - } else { - SG_LOG( SG_TERRAIN, SG_ALERT, - "Parent count is zero for an ssg light tile! Dying" ); - exit(-1); - } - } - - // find the vasi lighting branch - if ( vasi_lights_transform.get() ) { - pcount = vasi_lights_transform->getNumParents(); - if ( pcount > 0 ) { - // find the first parent (should only be one) - osg::Group *parent = vasi_lights_transform->getParent( 0 ) ; - if( parent ) { - // disconnect the light branch (we previously ref()'d - // it so it won't get freed now) - parent->removeChild( vasi_lights_transform.get() ); - } else { - SG_LOG( SG_TERRAIN, SG_ALERT, - "parent pointer is NULL! Dying" ); - exit(-1); - } - } else { - SG_LOG( SG_TERRAIN, SG_ALERT, - "Parent count is zero for an ssg light tile! Dying" ); - exit(-1); - } - } - - // find the runway lighting branch - if ( rwy_lights_transform.get() ) { - pcount = rwy_lights_transform->getNumParents(); - if ( pcount > 0 ) { - // find the first parent (should only be one) - osg::Group *parent = rwy_lights_transform->getParent( 0 ) ; - if( parent ) { - // disconnect the light branch (we previously ref()'d - // it so it won't get freed now) - parent->removeChild( rwy_lights_transform.get() ); - } else { - SG_LOG( SG_TERRAIN, SG_ALERT, - "parent pointer is NULL! Dying" ); - exit(-1); - } - } else { - SG_LOG( SG_TERRAIN, SG_ALERT, - "Parent count is zero for an ssg light tile! Dying" ); - exit(-1); - } - } - - // find the taxi lighting branch - if ( taxi_lights_transform.get() ) { - pcount = taxi_lights_transform->getNumParents(); - if ( pcount > 0 ) { - // find the first parent (should only be one) - osg::Group *parent = taxi_lights_transform->getParent( 0 ) ; - if( parent ) { - // disconnect the light branch (we previously ref()'d - // it so it won't get freed now) - parent->removeChild( taxi_lights_transform.get() ); - } else { - SG_LOG( SG_TERRAIN, SG_ALERT, - "parent pointer is NULL! Dying" ); - exit(-1); - } - } else { - SG_LOG( SG_TERRAIN, SG_ALERT, - "Parent count is zero for an ssg light tile! Dying" ); - exit(-1); - } - } } diff --git a/src/Scenery/tileentry.hxx b/src/Scenery/tileentry.hxx index a2f368224..a29626964 100644 --- a/src/Scenery/tileentry.hxx +++ b/src/Scenery/tileentry.hxx @@ -110,49 +110,16 @@ public: class FGTileEntry { public: - - // global tile culling data - Point3D center; - double bounding_radius; - // this tile's official location in the world SGBucket tile_bucket; private: - // ssg tree structure for this tile is as follows: - // osg::Group(scene) - // - osg::Group(terrain) - // - SGPlacementTransform(tile) - // - osg::LOD(tile) - // - ssgEntity(tile) - // - kid1(fan) - // - kid2(fan) - // ... - // - kidn(fan) - // pointer to ssg transform for this tile - osg::ref_ptr terra_transform; - osg::ref_ptr vasi_lights_transform; - osg::ref_ptr rwy_lights_transform; - osg::ref_ptr taxi_lights_transform; - osg::ref_ptr gnd_lights_transform; + osg::ref_ptr terra_transform; // pointer to ssg range selector for this tile osg::ref_ptr terra_range; - osg::ref_ptr gnd_lights_range; - - // we create several preset brightness and can choose which one we - // want based on lighting conditions. - osg::ref_ptr gnd_lights_brightness; - - // we need to be able to turn runway lights on or off (doing this - // via a call back would be nifty, but then the call back needs to - // know about the higher level application's global state which is - // a problem if we move the code into simgear.) - osg::ref_ptr vasi_lights_selector; - osg::ref_ptr rwy_lights_selector; - osg::ref_ptr taxi_lights_selector; /** * Indicates this tile has been loaded from a file and connected @@ -170,15 +137,8 @@ private: bool obj_load( const string& path, osg::Group* geometry, - osg::Group* vasi_lights, - osg::Group* rwy_lights, - osg::Group* taxi_lights, - osg::Vec3Array* gound_lights, bool is_base ); - osg::Node* gen_lights( SGMaterialLib *matlib, osg::Vec3Array *lights, - int inc, float bright ); - double timestamp; /** @@ -224,7 +184,7 @@ public: // Update the ssg transform node for this tile so it can be // properly drawn relative to our (0,0,0) point - void prep_ssg_node( const Point3D& p, sgVec3 up, float vis); + void prep_ssg_node(float vis); /** * Load tile data from a file. @@ -257,11 +217,7 @@ public: /** * Add terrain mesh and ground lighting to scene graph. */ - void add_ssg_nodes( osg::Group *terrain_branch, - osg::Group *gnd_lights_branch, - osg::Group *vasi_lights_branch, - osg::Group *rwy_lights_branch, - osg::Group *taxi_lights_branch ); + void add_ssg_nodes( osg::Group *terrain_branch); /** * disconnect terrain mesh and ground lighting nodes from scene @@ -273,7 +229,7 @@ public: /** * return the SSG Transform node for the terrain */ - inline SGPlacementTransform *get_terra_transform() const { return terra_transform.get(); } + osg::Group *get_terra_transform() const { return terra_transform.get(); } inline double get_timestamp() const { return timestamp; } inline void set_timestamp( double time_ms ) { timestamp = time_ms; } diff --git a/src/Scenery/tilemgr.cxx b/src/Scenery/tilemgr.cxx index baf830659..8fe1d760f 100644 --- a/src/Scenery/tilemgr.cxx +++ b/src/Scenery/tilemgr.cxx @@ -348,11 +348,7 @@ void FGTileMgr::update_queues() FGTileEntry* e = attach_queue.front(); attach_queue.pop(); #endif - e->add_ssg_nodes( globals->get_scenery()->get_terrain_branch(), - globals->get_scenery()->get_gnd_lights_root(), - globals->get_scenery()->get_vasi_lights_root(), - globals->get_scenery()->get_rwy_lights_root(), - globals->get_scenery()->get_taxi_lights_root() ); + e->add_ssg_nodes( globals->get_scenery()->get_terrain_branch() ); // cout << "Adding ssg nodes for " } @@ -457,22 +453,18 @@ void FGTileMgr::refresh_view_timestamps() { } } -void FGTileMgr::prep_ssg_nodes( SGLocation *location, float vis ) { +void FGTileMgr::prep_ssg_nodes(float vis) { // traverse the potentially viewable tile list and update range // selector and transform - float *up = location->get_world_up(); - FGTileEntry *e; tile_cache.reset_traversal(); - const double *vp = location->get_absolute_view_pos(); - Point3D viewpos(vp[0], vp[1], vp[2]); while ( ! tile_cache.at_end() ) { // cout << "processing a tile" << endl; if ( (e = tile_cache.get_current()) ) { - e->prep_ssg_node( viewpos, up, vis); + e->prep_ssg_node(vis); } else { SG_LOG(SG_INPUT, SG_ALERT, "warning ... empty tile in cache"); } @@ -486,11 +478,6 @@ bool FGTileMgr::set_tile_filter( bool f ) { return old; } -int FGTileMgr::tile_filter_cb( ssgEntity *, int ) -{ - return tile_filter ? 1 : 0; -} - bool FGTileMgr::scenery_available(double lat, double lon, double range_m) { // sanity check (unfortunately needed!) diff --git a/src/Scenery/tilemgr.hxx b/src/Scenery/tilemgr.hxx index a206d1cc3..31a8a443c 100644 --- a/src/Scenery/tilemgr.hxx +++ b/src/Scenery/tilemgr.hxx @@ -53,8 +53,6 @@ SG_USING_STD( queue ); // forward declaration -class ssgBranch; -class ssgEntity; class FGTileEntry; class FGDeferredModel; @@ -169,17 +167,15 @@ public: // tile, set the ssg transform and update it's range selector // based on current visibilty void prep_ssg_nodes( float // visibility_meters ); - void prep_ssg_nodes( SGLocation *location, float visibility_meters ); + void prep_ssg_nodes(float visibility_meters ); // Set flag with event manager so that non-moving view refreshes // tiles... void refresh_view_timestamps(); - inline const SGBucket& get_current_bucket () const { return current_bucket; } - inline const SGBucket& get_previous_bucket () const { return previous_bucket; } + const SGBucket& get_current_bucket () const { return current_bucket; } static bool set_tile_filter( bool f ); - static int tile_filter_cb( ssgEntity *, int ); /// Returns true if scenery is avaliable for the given lat, lon position /// within a range of range_m.