X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FScenery%2Ftilemgr.cxx;h=8cf2b6c98d3480b01a9e95f4a8d5cf249f25f20d;hb=da3271e1035d3223734f7836bae559c1281315c0;hp=f303f82189d833762cafb2c248e1e88fa93ce2bf;hpb=39b3602dce6856d97644c44b6f5e638a4245ac1e;p=flightgear.git diff --git a/src/Scenery/tilemgr.cxx b/src/Scenery/tilemgr.cxx index f303f8218..8cf2b6c98 100644 --- a/src/Scenery/tilemgr.cxx +++ b/src/Scenery/tilemgr.cxx @@ -46,7 +46,12 @@ #include #include #include -#include + +#ifdef FG_NEW_WEATHER +# include +#else +# include +#endif #include "scenery.hxx" #include "tilecache.hxx" @@ -61,6 +66,9 @@ #endif +extern ssgRoot *scene; + + // the tile manager FGTileMgr global_tile_mgr; @@ -86,6 +94,8 @@ int FGTileMgr::init( void ) { material_mgr.load_lib(); } + global_tile_cache.init(); + state = Inited; return 1; @@ -93,21 +103,40 @@ int FGTileMgr::init( void ) { // schedule a tile for loading -void FGTileMgr::sched_tile( const FGBucket& b, int *index ) { +static void disable_tile( int cache_index ) { // see if tile already exists in the cache - *index = global_tile_cache.exists( b ); - if ( *index < 0 ) { - // find the next availabel cache entry and mark it as scheduled - *index = global_tile_cache.next_avail(); - FGTileEntry *t = global_tile_cache.get_tile( *index ); - t->mark_scheduled(); + // cout << "DISABLING CACHE ENTRY = " << cache_index << endl; + FGTileEntry *t = global_tile_cache.get_tile( cache_index ); + t->ssg_disable(); +} + + +// schedule a tile for loading +int FGTileMgr::sched_tile( const FGBucket& b ) { + // see if tile already exists in the cache + int cache_index = global_tile_cache.exists( b ); + + if ( cache_index >= 0 ) { + // tile exists in cache, reenable it. + // cout << "REENABLING DISABLED TILE" << endl; + FGTileEntry *t = global_tile_cache.get_tile( cache_index ); + t->select_ptr->select( 1 ); + t->mark_loaded(); + } else { + // find the next available cache entry and mark it as + // scheduled + cache_index = global_tile_cache.next_avail(); + FGTileEntry *t = global_tile_cache.get_tile( cache_index ); + t->mark_scheduled_for_use(); // register a load request FGLoadRec request; request.b = b; - request.index = *index; + request.cache_index = cache_index; load_queue.push_back( request ); } + + return cache_index; } @@ -340,6 +369,40 @@ FGTileMgr::current_elev( double lon, double lat, const Point3D& abs_view_pos ) { } +// Determine scenery altitude via ssg. Normally this just happens +// when we render the scene, but we'd also like to be able to do this +// explicitely. lat & lon are in radians. view_pos in current world +// coordinate translated near (0,0,0) (in meters.) Returns result in +// meters. +double +FGTileMgr::current_elev_ssg( const Point3D& abs_view_pos, + const Point3D& view_pos ) +{ + ssgHit *results ; + + // cout << "view pos = " << view_pos << endl; + // cout << "abs view pos = " << abs_view_pos << endl; + + sgMat4 m; + sgMakeTransMat4( m, view_pos.x(), view_pos.y(), view_pos.z() ); + + sgVec3 s; + sgSetVec3(s, -abs_view_pos.x(), -abs_view_pos.y(), -abs_view_pos.z() ); + + int num_hits = ssgLOS ( scene, s, m, &results ) ; + + for ( int i = 0 ; i < num_hits ; i++ ) { + ssgHit *h = &(results [ i ]) ; + // cout << "got a hit!" << endl; + /* Do something with 'h' */ + } + + FG_LOG( FG_TERRAIN, FG_INFO, "(ssg) no terrain intersection found" ); + + return 0.0; +} + + // given the current lon/lat, fill in the array of local chunks. If // the chunk isn't already in the cache, then read it from disk. int FGTileMgr::update( void ) { @@ -368,7 +431,7 @@ int FGTileMgr::update( void ) { } else if ( (state == Start) || (state == Inited) ) { state = Running; - // First time through or we have teleporte, initialize the + // First time through or we have teleported, initialize the // system and load all relavant tiles FG_LOG( FG_TERRAIN, FG_INFO, "Updating Tile list for " << p1 ); @@ -389,7 +452,7 @@ int FGTileMgr::update( void ) { p2 = fgBucketOffset( f->get_Longitude() * RAD_TO_DEG, f->get_Latitude() * RAD_TO_DEG, 0, 0 ); - sched_tile( p2, &tiles[(dh*tile_diameter) + dw]); + sched_tile( p2 ); for ( i = 3; i <= tile_diameter; i = i + 2 ) { int span = i / 2; @@ -399,7 +462,7 @@ int FGTileMgr::update( void ) { p2 = fgBucketOffset( f->get_Longitude() * RAD_TO_DEG, f->get_Latitude() * RAD_TO_DEG, j, -span ); - sched_tile( p2, &tiles[((dh-span)*tile_diameter) + dw+j]); + sched_tile( p2 ); } // top row @@ -407,7 +470,7 @@ int FGTileMgr::update( void ) { p2 = fgBucketOffset( f->get_Longitude() * RAD_TO_DEG, f->get_Latitude() * RAD_TO_DEG, j, span ); - sched_tile( p2, &tiles[((dh+span)*tile_diameter) + dw+j]); + sched_tile( p2 ); } // middle rows @@ -415,11 +478,11 @@ int FGTileMgr::update( void ) { p2 = fgBucketOffset( f->get_Longitude() * RAD_TO_DEG, f->get_Latitude() * RAD_TO_DEG, -span, j ); - sched_tile( p2, &tiles[((dh+j)*tile_diameter) + dw-span]); + sched_tile( p2 ); p2 = fgBucketOffset( f->get_Longitude() * RAD_TO_DEG, f->get_Latitude() * RAD_TO_DEG, span, j ); - sched_tile( p2, &tiles[((dh+j)*tile_diameter) + dw+span]); + sched_tile( p2 ); } } @@ -430,7 +493,7 @@ int FGTileMgr::update( void ) { p2 = fgBucketOffset( f->get_Longitude() * RAD_TO_DEG, f->get_Latitude() * RAD_TO_DEG, i - dw, j -dh ); - sched_tile( p2, &tiles[(j*tile_diameter) + i]); + sched_tile( p2 ); } } */ @@ -438,12 +501,12 @@ int FGTileMgr::update( void ) { // have something to see in our first frame. for ( i = 0; i < 9; ++i ) { if ( load_queue.size() ) { - FG_LOG( FG_TERRAIN, FG_INFO, + FG_LOG( FG_TERRAIN, FG_DEBUG, "Load queue not empty, loading a tile" ); FGLoadRec pending = load_queue.front(); load_queue.pop_front(); - load_tile( pending.b, pending.index ); + load_tile( pending.b, pending.cache_index ); } } @@ -451,6 +514,18 @@ int FGTileMgr::update( void ) { // We've moved to a new bucket, we need to scroll our // structures, and load in the new tiles +#if 0 + // make sure load queue is flushed before doing shift + while ( load_queue.size() ) { + FG_LOG( FG_TERRAIN, FG_DEBUG, + "Load queue not empty, flushing queue before tile shift." ); + + FGLoadRec pending = load_queue.front(); + load_queue.pop_front(); + load_tile( pending.b, pending.index ); + } +#endif + // CURRENTLY THIS ASSUMES WE CAN ONLY MOVE TO ADJACENT TILES. // AT ULTRA HIGH SPEEDS THIS ASSUMPTION MAY NOT BE VALID IF // THE AIRCRAFT CAN SKIP A TILE IN A SINGLE ITERATION. @@ -458,78 +533,60 @@ int FGTileMgr::update( void ) { FG_LOG( FG_TERRAIN, FG_INFO, "Updating Tile list for " << p1 ); if ( (p1.get_lon() > p_last.get_lon()) || - ( (p1.get_lon() == p_last.get_lon()) && (p1.get_x() > p_last.get_x()) ) ) { + ( (p1.get_lon() == p_last.get_lon()) && + (p1.get_x() > p_last.get_x()) ) ) { FG_LOG( FG_TERRAIN, FG_INFO, - " Loading " << tile_diameter << "tiles" ); + " (East) Loading " << tile_diameter << " tiles" ); for ( j = 0; j < tile_diameter; j++ ) { // scrolling East - for ( i = 0; i < tile_diameter - 1; i++ ) { - tiles[(j*tile_diameter) + i] = - tiles[(j*tile_diameter) + i + 1]; - } - // load in new column - // fgBucketOffset(&p_last, &p2, dw + 1, j - dh); + // schedule new column p2 = fgBucketOffset( last_lon, last_lat, dw + 1, j - dh ); - sched_tile( p2, &tiles[(j*tile_diameter) + - tile_diameter - 1]); + sched_tile( p2 ); } } else if ( (p1.get_lon() < p_last.get_lon()) || - ( (p1.get_lon() == p_last.get_lon()) && (p1.get_x() < p_last.get_x()) ) ) { + ( (p1.get_lon() == p_last.get_lon()) && + (p1.get_x() < p_last.get_x()) ) ) { FG_LOG( FG_TERRAIN, FG_INFO, - " Loading " << tile_diameter << "tiles" ); + " (West) Loading " << tile_diameter << " tiles" ); for ( j = 0; j < tile_diameter; j++ ) { // scrolling West - for ( i = tile_diameter - 1; i > 0; i-- ) { - tiles[(j*tile_diameter) + i] = - tiles[(j*tile_diameter) + i - 1]; - } - // load in new column - // fgBucketOffset(&p_last, &p2, -dw - 1, j - dh); + // schedule new column p2 = fgBucketOffset( last_lon, last_lat, -dw - 1, j - dh ); - sched_tile( p2, &tiles[(j*tile_diameter) + 0]); + sched_tile( p2 ); } } if ( (p1.get_lat() > p_last.get_lat()) || - ( (p1.get_lat() == p_last.get_lat()) && (p1.get_y() > p_last.get_y()) ) ) { + ( (p1.get_lat() == p_last.get_lat()) && + (p1.get_y() > p_last.get_y()) ) ) { FG_LOG( FG_TERRAIN, FG_INFO, - " Loading " << tile_diameter << "tiles" ); + " (North) Loading " << tile_diameter << " tiles" ); for ( i = 0; i < tile_diameter; i++ ) { // scrolling North - for ( j = 0; j < tile_diameter - 1; j++ ) { - tiles[(j * tile_diameter) + i] = - tiles[((j+1) * tile_diameter) + i]; - } - // load in new column - // fgBucketOffset(&p_last, &p2, i - dw, dh + 1); + // schedule new row p2 = fgBucketOffset( last_lon, last_lat, i - dw, dh + 1); - sched_tile( p2, &tiles[((tile_diameter-1) * - tile_diameter) + i]); + sched_tile( p2 ); } } else if ( (p1.get_lat() < p_last.get_lat()) || - ( (p1.get_lat() == p_last.get_lat()) && (p1.get_y() < p_last.get_y()) ) ) { + ( (p1.get_lat() == p_last.get_lat()) && + (p1.get_y() < p_last.get_y()) ) ) { FG_LOG( FG_TERRAIN, FG_INFO, - " Loading " << tile_diameter << "tiles" ); + " (South) Loading " << tile_diameter << " tiles" ); for ( i = 0; i < tile_diameter; i++ ) { // scrolling South - for ( j = tile_diameter - 1; j > 0; j-- ) { - tiles[(j * tile_diameter) + i] = - tiles[((j-1) * tile_diameter) + i]; - } - // load in new column - // fgBucketOffset(&p_last, &p2, i - dw, -dh - 1); + // schedule new row p2 = fgBucketOffset( last_lon, last_lat, i - dw, -dh - 1); - sched_tile( p2, &tiles[0 + i]); + sched_tile( p2 ); } } } if ( load_queue.size() ) { - FG_LOG( FG_TERRAIN, FG_INFO, "Load queue not empty, loading a tile" ); + FG_LOG( FG_TERRAIN, FG_DEBUG, "Load queue not empty, loading a tile" ); FGLoadRec pending = load_queue.front(); load_queue.pop_front(); - load_tile( pending.b, pending.index ); + load_tile( pending.b, pending.cache_index ); } // find our current elevation (feed in the current bucket to save work) @@ -538,7 +595,11 @@ int FGTileMgr::update( void ) { scenery.cur_elev = current_elev( f->get_Longitude(), f->get_Latitude(), tmp_abs_view_pos ); - + // cout << "current elevation == " << scenery.cur_elev << endl; + // double junk = current_elev_ssg( current_view.abs_view_pos, + // current_view.view_pos ); + // cout << "current elevation (ssg) == " << + p_last = p1; last_lon = f->get_Longitude() * RAD_TO_DEG; last_lat = f->get_Latitude() * RAD_TO_DEG; @@ -547,123 +608,6 @@ int FGTileMgr::update( void ) { } -// Calculate if point/radius is inside view frustum -static int viewable( const Point3D& cp, double radius ) { - int viewable = 1; // start by assuming it's viewable - double x1, y1; - - /********************************/ -#if defined( USE_FAST_FOV_CLIP ) // views.hxx - /********************************/ - - MAT3vec eye; - double *mat; - double x, y, z; - - x = cp.x(); - y = cp.y(); - z = cp.z(); - - mat = (double *)(current_view.get_WORLD_TO_EYE()); - - eye[2] = x*mat[2] + y*mat[6] + z*mat[10] + mat[14]; - - // Check near and far clip plane - if( ( eye[2] > radius ) || - ( eye[2] + radius + current_weather.get_visibility() < 0) ) - { - return(0); - } - - eye[0] = (x*mat[0] + y*mat[4] + z*mat[8] + mat[12]) - * current_view.get_slope_x(); - - // check right and left clip plane (from eye perspective) - x1 = radius * current_view.get_fov_x_clip(); - if( (eye[2] > -(eye[0]+x1)) || (eye[2] > (eye[0]-x1)) ) - { - return(0); - } - - eye[1] = (x*mat[1] + y*mat[5] + z*mat[9] + mat[13]) - * current_view.get_slope_y(); - - // check bottom and top clip plane (from eye perspective) - y1 = radius * current_view.get_fov_y_clip(); - if( (eye[2] > -(eye[1]+y1)) || (eye[2] > (eye[1]-y1)) ) - { - return(0); - } - - /********************************/ -#else // DO NOT USE_FAST_FOV_CLIP - /********************************/ - - fgVIEW *v; - MAT3hvec world, eye; - double x0, slope; - - v = ¤t_view; - - MAT3_SET_HVEC(world, cp->x, cp->y, cp->z, 1.0); - // MAT3mult_vec(eye, world, v->WORLD_TO_EYE); - // printf( "\nworld -> eye = %.2f %.2f %.2f radius = %.2f\n", - // eye[0], eye[1], eye[2], radius); - - // Use lazy evaluation for calculating eye hvec. -#define vec world -#define mat v->WORLD_TO_EYE - eye[2] = vec[0]*mat[0][2]+vec[1]*mat[1][2]+vec[2]*mat[2][2]+mat[3][2]; - - // Check near clip plane - if ( eye[2] > radius ) { - return(0); - } - - // Check far clip plane - if ( eye[2] + radius < -current_weather.get_visibility() ) { - return(0); - } - - // check right clip plane (from eye perspective) - // y = m * (x - x0) = equation of a line intercepting X axis at x0 - x1 = v->cos_fov_x * radius; - y1 = v->sin_fov_x * radius; - slope = v->slope_x; - eye[0] = vec[0]*mat[0][0]+vec[1]*mat[1][0]+vec[2]*mat[2][0]+mat[3][0]; - - if ( eye[2] > ((slope * (eye[0] - x1)) + y1) ) { - return( false ); - } - - // check left clip plane (from eye perspective) - if ( eye[2] > -((slope * (eye[0] + x1)) - y1) ) { - return( false ); - } - - // check bottom clip plane (from eye perspective) - x1 = -(v->cos_fov_y) * radius; - y1 = v->sin_fov_y * radius; - slope = v->slope_y; - eye[1] = vec[0]*mat[0][1]+vec[1]*mat[1][1]+vec[2]*mat[2][1]+mat[3][1]; -#undef vec -#undef mat - - if ( eye[2] > ((slope * (eye[1] - x1)) + y1) ) { - return( false ); - } - - // check top clip plane (from eye perspective) - if ( eye[2] > -((slope * (eye[1] + x1)) - y1) ) { - return( false ); - } - -#endif // defined( USE_FAST_FOV_CLIP ) - - return(viewable); -} - - // NEW // inrange() IS THIS POINT WITHIN POSSIBLE VIEWING RANGE ? @@ -740,20 +684,23 @@ update_tile_geometry( FGTileEntry *t, GLdouble *MODEL_VIEW) void FGTileMgr::prep_ssg_nodes( void ) { FGTileEntry *t; - int tile_diameter = current_options.get_tile_diameter(); - float ranges[2]; ranges[0] = 0.0f; - ranges[1] = current_weather.get_visibility(); // traverse the potentially viewable tile list and update range // selector and transform - for ( int i = 0; i < (tile_diameter * tile_diameter); i++ ) { - int index = tiles[i]; - t = global_tile_cache.get_tile(index); + for ( int i = 0; i < (int)global_tile_cache.get_size(); i++ ) { + t = global_tile_cache.get_tile( i ); if ( t->is_loaded() ) { - // set range selector (LOD trick) + // set range selector (LOD trick) to be distance to center + // of tile + bounding radius +#ifdef FG_NEW_WEATHER + ranges[1] = WeatherDatabase->getWeatherVisibility() + + t->bounding_radius; +#else + ranges[1] = current_weather.get_visibility()+t->bounding_radius; +#endif t->range_ptr->setRanges( ranges, 2 ); // calculate tile offset @@ -764,124 +711,7 @@ void FGTileMgr::prep_ssg_nodes( void ) { sgSetCoord( &sgcoord, t->offset.x(), t->offset.y(), t->offset.z(), 0.0, 0.0, 0.0 ); - t->branch_ptr->setTransform( &sgcoord ); - } - } -} - - -// Render the local tiles -void FGTileMgr::render( void ) { - FGInterface *f; - FGTileCache *c; - FGTileEntry *t; - FGView *v; - Point3D frag_offset; - fgFRAGMENT *frag_ptr; - FGMaterialSlot *mtl_ptr; - int i; - int index; - int culled = 0; - int drawn = 0; - - c = &global_tile_cache; - f = current_aircraft.fdm_state; - v = ¤t_view; - - int tile_diameter = current_options.get_tile_diameter(); - - // moved to fgTileMgrUpdate, right after we check if we need to - // load additional tiles: - // scenery.cur_elev = fgTileMgrCurElev( FG_Longitude, FG_Latitude, - // v->abs_view_pos ); - - // initialize the transient per-material fragment lists - material_mgr.init_transient_material_lists(); - - // Pass 1 - // traverse the potentially viewable tile list - for ( i = 0; i < (tile_diameter * tile_diameter); i++ ) { - index = tiles[i]; - // fgPrintf( FG_TERRAIN, FG_DEBUG, "Index = %d\n", index); - t = c->get_tile(index); - - if ( t->is_loaded() ) { - - // calculate tile offset - t->SetOffset( scenery.center ); - - // Course (tile based) culling - if ( viewable(t->offset, t->bounding_radius) ) { - // at least a portion of this tile could be viewable - - // Calculate the model_view transformation matrix for this tile - // This is equivalent to doing a glTranslatef(x, y, z); - t->update_view_matrix( v->get_MODEL_VIEW() ); - - // xglPushMatrix(); - // xglTranslatef(t->offset.x, t->offset.y, t->offset.z); - - // traverse fragment list for tile - FGTileEntry::FragmentIterator current = t->begin(); - FGTileEntry::FragmentIterator last = t->end(); - - for ( ; current != last; ++current ) { - frag_ptr = &(*current); - - if ( frag_ptr->display_list >= 0 ) { - // Fine (fragment based) culling - frag_offset = frag_ptr->center - scenery.center; - - if ( viewable(frag_offset, - frag_ptr->bounding_radius*2) ) - { - // add to transient per-material property - // fragment list - - // frag_ptr->tile_offset.x = t->offset.x; - // frag_ptr->tile_offset.y = t->offset.y; - // frag_ptr->tile_offset.z = t->offset.z; - - mtl_ptr = frag_ptr->material_ptr; - // printf(" lookup = %s\n", mtl_ptr->texture_name); - if ( ! mtl_ptr->append_sort_list( frag_ptr ) ) { - FG_LOG( FG_TERRAIN, FG_ALERT, - "Overran material sorting array" ); - } - - // xglCallList(frag_ptr->display_list); - drawn++; - } else { - // printf("Culled a fragment %.2f %.2f %.2f %.2f\n", - // frag_ptr->center.x, frag_ptr->center.y, - // frag_ptr->center.z, - // frag_ptr->bounding_radius); - culled++; - } - } - } - - // xglPopMatrix(); - } else { - culled += t->fragment_list.size(); - } - } else { - FG_LOG( FG_TERRAIN, FG_DEBUG, "Skipping a not yet loaded tile" ); + t->transform_ptr->setTransform( &sgcoord ); } } - - if ( (drawn + culled) > 0 ) { - v->set_vfc_ratio( (double)culled / (double)(drawn + culled) ); - } else { - v->set_vfc_ratio( 0.0 ); - } - // printf("drawn = %d culled = %d saved = %.2f\n", drawn, culled, - // v->vfc_ratio); - - // Pass 2 - // traverse the transient per-material fragment lists and render - // out all fragments for each material property. - xglPushMatrix(); - material_mgr.render_fragments(); - xglPopMatrix(); }