Index: simworld.cc =================================================================== --- simworld.cc (revision 9140) +++ simworld.cc (working copy) @@ -211,7 +211,7 @@ world_thread_param[t].welt = this; world_thread_param[t].thread_num = t; - world_thread_param[t].x_step = min( 64, max_x / env_t::num_threads ); + world_thread_param[t].x_step = sync_x_steps ? min( 64, max_x / env_t::num_threads ) : max_x; world_thread_param[t].x_world_max = max_x; world_thread_param[t].y_min = (t * max_y) / env_t::num_threads; world_thread_param[t].y_max = ((t + 1) * max_y) / env_t::num_threads; @@ -356,7 +356,6 @@ for( int y = y_min; y < y_max; y++ ) { for( int x = x_min; x < x_max; x++ ) { planquadrat_t *pl = access_nocheck(x,y); - grund_t *gr = pl->get_kartenboden(); koord k(x,y); slope_t::type slope = calc_natural_slope(k); sint8 height = min_hgt_nocheck(k); @@ -371,17 +370,13 @@ slope = encode_corners(disp_hn_sw - height, disp_hn_se - height, disp_hn_ne - height, disp_hn_nw - height); } - gr->set_pos( koord3d( k, height) ); - if( gr->get_typ() != grund_t::wasser && max_hgt_nocheck(k) <= water_hgt ) { - // below water but ground => convert - pl->kartenboden_setzen( new wasser_t(gr->get_pos()), true /* do not calc_image for water tiles */ ); + if( max_hgt_nocheck(k) <= water_hgt ) { + // create water + pl->kartenboden_setzen( new wasser_t(koord3d( k, height)), true /* do not calc_image for water tiles */ ); } - else if( gr->get_typ() == grund_t::wasser && max_hgt_nocheck(k) > water_hgt ) { - // water above ground => to ground - pl->kartenboden_setzen( new boden_t(gr->get_pos(), slope ) ); - } else { - gr->set_grund_hang( slope ); + // create ground + pl->kartenboden_setzen( new boden_t(koord3d( k, height), slope ) ); } if( max_hgt_nocheck(k) > water_hgt ) { @@ -416,7 +411,8 @@ } if( xoff==0 && yoff==0 ) { - world_xy_loop(&karte_t::cleanup_grounds_loop, 0); + //world_xy_loop(&karte_t::cleanup_grounds_loop, 0); + cleanup_grounds_loop( 0, get_size().x, 0, get_size().y ); } else { cleanup_grounds_loop( 0, get_size().x, yoff, get_size().y ); @@ -1353,6 +1349,77 @@ * To start with every tile in the map is checked - but when we fail for * a tile then it is excluded from subsequent checks */ +sint8 *stage; +sint8 *new_stage; +sint8 *local_stage; +sint8 *max_water_hgt; +bool need_to_flood; +sint8 h; + +#define LAKE_SUCCESS 1 +#define LAKE_FAIL 0 +#define LAKE_SEAM -1 + +void karte_t::create_lakes_loop( sint16 x_min, sint16 x_max, sint16 y_min, sint16 y_max ) +{ + const sint8 max_lake_height = groundwater + 8; + const uint16 size_x = get_size().x; + const uint16 size_y = get_size().y; + + if( x_min < 1 ) x_min = 1; + //if( y_min < 1 ) y_min = 1; + y_min++; // first row is barrier even if not at world edge + if( x_max > size_x-1 ) x_max = size_x-1; + if( y_max > size_y-1 ) y_max = size_y-1; + + for( uint16 y = y_min; y < y_max; y++ ) { + for( uint16 x = x_min; x < x_max; x++ ) { + uint32 offset = array_koord(x,y); + if( max_water_hgt[offset]==1 && stage[offset]==-1 ) { + + sint8 hgt = lookup_hgt_nocheck( x, y ); + const sint8 water_hgt = water_hgts[offset]; // optimised <- get_water_hgt_nocheck(x, y); + const sint8 new_water_hgt = max(hgt, water_hgt); + if( new_water_hgt>max_lake_height ) { + max_water_hgt[offset] = 0; + } + else if( h>new_water_hgt ) { + koord k(x,y); + for( uint16 iy = y_min; iy -1 ) { + max_water_hgt[local_offset] = 0; + } + } + } + } + } + } + } + } +} + void karte_t::create_lakes( int xoff, int yoff ) { if( xoff > 0 || yoff > 0 ) { @@ -1364,54 +1431,46 @@ const uint16 size_x = get_size().x; const uint16 size_y = get_size().y; - sint8 *max_water_hgt = new sint8[size_x * size_y]; + max_water_hgt = new sint8[size_x * size_y]; memset( max_water_hgt, 1, sizeof(sint8) * size_x * size_y ); - sint8 *stage = new sint8[size_x * size_y]; - sint8 *new_stage = new sint8[size_x * size_y]; - sint8 *local_stage = new sint8[size_x * size_y]; + stage = new sint8[size_x * size_y]; + new_stage = new sint8[size_x * size_y]; + local_stage = new sint8[size_x * size_y]; - for( sint8 h = groundwater+1; hmax_lake_height ) { - max_water_hgt[offset] = 0; - } - else if( h>new_water_hgt ) { - koord k(x,y); - memcpy( new_stage, stage, sizeof(sint8) * size_x * size_y ); - if(can_flood_to_depth( k, h, new_stage, local_stage )) { - sint8 *tmp_stage = new_stage; - new_stage = stage; - stage = tmp_stage; - need_to_flood = true; - } - else { - for( uint16 iy = 1; iy -1 ) { - max_water_hgt[local_offset] = 0; - } - } - } - } - } - } +// set seams to invalid - if single thread then skipped + for( int t = 1; t < env_t::num_threads; t++ ) { + sint16 y_min = (t * size_y) / env_t::num_threads; + memset( stage + sizeof(sint8) * array_koord(0,y_min), -2, sizeof(sint8) * (size_x) ); + } + + world_xy_loop(&karte_t::create_lakes_loop, 0); + + bool threaded_need_to_flood = need_to_flood; + + if( env_t::num_threads > 1 ) { + if(need_to_flood) { + flood_to_depth( h, stage ); + need_to_flood = false; } + + memset( stage, -1, sizeof(sint8) * size_x * size_y ); + + for( int t = 1; t < env_t::num_threads - 1; t++ ) { + sint16 y_min = (t * size_y) / env_t::num_threads; + create_lakes_loop( 0, size_x, y_min, y_min + 1 ); + } } + if(need_to_flood) { flood_to_depth( h, stage ); } - else { + else if(!threaded_need_to_flood) { break; } } @@ -1426,10 +1485,9 @@ } } - -bool karte_t::can_flood_to_depth( koord k, sint8 new_water_height, sint8 *stage, sint8 *our_stage ) const +uint8 karte_t::can_flood_to_depth( koord k, sint8 new_water_height, sint8 *stage, sint8 *our_stage, sint16 x_min, sint16 x_max, sint16 y_min, sint16 y_max ) const { - bool succeeded = true; + uint8 succeeded = LAKE_SUCCESS; if( k == koord::invalid ) { return false; } @@ -1448,8 +1506,9 @@ our_stage = new sint8[get_size().x * get_size().y]; } - memset( from_dir, -1, sizeof(sint8) * get_size().x * get_size().y ); - memset( our_stage, -1, sizeof(sint8) * get_size().x * get_size().y ); + memset( from_dir + sizeof(sint8) * array_koord(0,y_min), -1, sizeof(sint8) * get_size().x * (y_max-y_min) ); + memset( our_stage + sizeof(sint8) * array_koord(0,y_min), -1, sizeof(sint8) * get_size().x * (y_max-y_min) ); + uint32 offset = array_koord(k.x,k.y); stage[offset]=0; our_stage[offset]=0; @@ -1456,12 +1515,17 @@ do { for( int i = our_stage[offset]; i < 8; i++ ) { koord k_neighbour = k + koord::neighbours[i]; - if( is_within_limits(k_neighbour) ) { + if( k_neighbour.x >= x_min && k_neighbour.x= y_min && k_neighbour.y -1) goto next_neighbour; + if(our_stage[neighbour_offset] == -2) { + succeeded = LAKE_SEAM; + goto next_neighbour; + } + // water height above if(water_hgts[neighbour_offset] >= new_water_height) goto next_neighbour; @@ -1484,7 +1548,7 @@ } else { // edge of map - we keep iterating so we can mark all connected tiles as failing - succeeded = false; + succeeded = LAKE_FAIL; } next_neighbour: //return back to previous tile @@ -1512,7 +1576,7 @@ uint32 offset_max = size_x*size_y; for( uint32 offset = 0; offset < offset_max; offset++ ) { - if( stage[offset] == -1 ) { + if( stage[offset] < 0 ) { continue; } water_hgts[offset] = new_water_height; @@ -1805,17 +1869,9 @@ } } - if ( old_x > 0 && old_y > 0 ) { - // create grounds on new part - for (sint16 iy = 0; iy=old_y)?0:old_x; ixkartenboden_setzen( new boden_t( koord3d( ix, iy, max( min_hgt_nocheck(k), get_water_hgt_nocheck(k) ) ), 0 ) ); - } - } - } - else { - world_xy_loop(&karte_t::create_grounds_loop, 0); + // smooth the new part, reassign slopes on new part + cleanup_karte( old_x, old_y ); + if ( old_x == 0 && old_y == 0 ) { ls.set_progress(10); } @@ -1833,12 +1889,6 @@ } if ( old_x == 0 && old_y == 0 ) { - ls.set_progress(11); - } - - // smooth the new part, reassign slopes on new part - cleanup_karte( old_x, old_y ); - if ( old_x == 0 && old_y == 0 ) { ls.set_progress(12); } @@ -6044,17 +6094,6 @@ } -void karte_t::create_grounds_loop( sint16 x_min, sint16 x_max, sint16 y_min, sint16 y_max ) -{ - for( int y = y_min; y < y_max; y++ ) { - for( int x = x_min; x < x_max; x++ ) { - koord k(x,y); - access_nocheck(k)->kartenboden_setzen( new boden_t( koord3d( x, y, max(min_hgt_nocheck(k),get_water_hgt_nocheck(k)) ), 0 ) ); - } - } -} - - uint8 karte_t::sp2num(player_t *player) { if( player==NULL ) { Index: simworld.h =================================================================== --- simworld.h (revision 9140) +++ simworld.h (working copy) @@ -649,6 +649,11 @@ void create_rivers(sint16 number); /** + * Will create lakes (multithreaded). + */ + void create_lakes_loop(sint16, sint16, sint16, sint16); + + /** * Will create lakes. */ void create_lakes( int xoff, int yoff ); @@ -1117,7 +1122,7 @@ * lakes are left where there is no drainage */ void drain_tile(koord k, sint8 water_height); - bool can_flood_to_depth(koord k, sint8 new_water_height, sint8 *stage, sint8 *our_stage) const; + uint8 can_flood_to_depth(koord k, sint8 new_water_height, sint8 *stage, sint8 *our_stage, sint16, sint16, sint16, sint16) const; public: void flood_to_depth(sint8 new_water_height, sint8 *stage); @@ -1632,11 +1637,6 @@ void recalc_transitions_loop(sint16, sint16, sint16, sint16); /** - * Loop creating grounds on all plans from height and water height - suitable for multithreading - */ - void create_grounds_loop(sint16, sint16, sint16, sint16); - - /** * Loop cleans grounds so that they have correct boden and slope - suitable for multithreading */ void cleanup_grounds_loop(sint16, sint16, sint16, sint16);