Skip to content

Commit

Permalink
LOS POC
Browse files Browse the repository at this point in the history
  • Loading branch information
jove-m committed Jun 10, 2022
1 parent 394e6ff commit de22376
Show file tree
Hide file tree
Showing 8 changed files with 255 additions and 70 deletions.
2 changes: 1 addition & 1 deletion src/explosion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ static std::map<const Creature *, int> shrapnel( const tripoint &src, const proj
const int offset_distance = 60 - 1 - fragment.range;
castLightAll<float, float, shrapnel_calc, shrapnel_check,
update_fragment_cloud, accumulate_fragment_cloud>
( visited_cache, obstacle_cache, src.xy(), offset_distance, fragment.range + 1.0f );
( visited_cache, obstacle_cache, g->m.access_cache(src.z).blocked_cache, src.xy(), offset_distance, fragment.range + 1.0f );

// Now visited_caches are populated with density and velocity of fragments.
for( const tripoint &target : area ) {
Expand Down
223 changes: 174 additions & 49 deletions src/lightmap.cpp

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8482,6 +8482,7 @@ level_cache::level_cache()
std::fill_n( &outside_cache[0][0], map_dimensions, false );
std::fill_n( &floor_cache[0][0], map_dimensions, false );
std::fill_n( &transparency_cache[0][0], map_dimensions, 0.0f );
std::fill_n( &blocked_cache[0][0][0], map_dimensions*2, false );
std::fill_n( &vision_transparency_cache[0][0], map_dimensions, 0.0f );
std::fill_n( &seen_cache[0][0], map_dimensions, 0.0f );
std::fill_n( &camera_cache[0][0], map_dimensions, 0.0f );
Expand Down
4 changes: 4 additions & 0 deletions src/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,10 @@ struct level_cache {
// units: "transparency" (see LIGHT_TRANSPARENCY_OPEN_AIR)
float transparency_cache[MAPSIZE_X][MAPSIZE_Y];

// true when light entering a tile diagonally is blocked by the walls of a turned vehicle. First bit represents nw direction, the second ne
// check the values of adjacent tiles to find sw and se directions
bool blocked_cache[MAPSIZE_X][MAPSIZE_Y][2];

// stores "adjusted transparency" of the tiles
// initial values derived from transparency_cache, uses same units
// examples of adjustment: changed transparency on player's tile and special case for crouching
Expand Down
2 changes: 2 additions & 0 deletions src/shadowcasting.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ template<typename T, typename Out, T( *calc )( const T &, const T &, const int &
T( *accumulate )( const T &, const T &, const int & )>
void castLightAll( Out( &output_cache )[MAPSIZE_X][MAPSIZE_Y],
const T( &input_array )[MAPSIZE_X][MAPSIZE_Y],
const bool( &blocked_array )[MAPSIZE_X][MAPSIZE_Y][2],
const point &offset, int offsetDistance = 0,
T numerator = 1.0 );

Expand All @@ -123,6 +124,7 @@ void cast_zlight(
const array_of_grids_of<T> &output_caches,
const array_of_grids_of<const T> &input_arrays,
const array_of_grids_of<const bool> &floor_caches,
const array_of_grids_of<const bool[2]> &blocked_caches,
const tripoint &origin, int offset_distance, T numerator );

#endif // CATA_SRC_SHADOWCASTING_H
59 changes: 46 additions & 13 deletions src/vehicle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2596,6 +2596,23 @@ int vehicle::obstacle_at_position(const point &pos) const
return i;
}

int vehicle::opaque_at_position(const point &pos) const
{
int i=part_with_feature(pos, "OPAQUE", true);

if(i==-1){
return -1;
}

auto ref=parts[i];

if( ref.info().has_flag( VPFLAG_OPENABLE ) && ref.open ) {
return -1;
}

return i;
}

std::vector<vehicle_part *> vehicle::get_parts_at( const tripoint &pos, const std::string &flag,
const part_status_flag condition )
{
Expand Down Expand Up @@ -3052,6 +3069,7 @@ void vehicle::coord_translate( tileray tdir, const point &pivot, const point &p,
q.x = tdir.dx() + tdir.ortho_dx( relative.y );
q.y = tdir.dy() + tdir.ortho_dy( relative.y );


coord_translate_cache[key].insert({ relative, q.xy() });
coord_translate_reverse[key].insert({q.xy(), relative});
}
Expand Down Expand Up @@ -3082,11 +3100,11 @@ point vehicle::tripoint_to_mount( const tripoint &p) const
}

int vehicle::angle_to_increment(units::angle dir) {
int increment=(std::lround( to_degrees( dir ))%360)/15;
if(increment<0){
increment+=360/15;
}
return increment;
int increment=(std::lround( to_degrees( dir ))%360)/15;
if(increment<0){
increment+=360/15;
}
return increment;
}

void vehicle::precalc_mounts( int idir, units::angle dir, const point &pivot )
Expand All @@ -3102,8 +3120,8 @@ void vehicle::precalc_mounts( int idir, units::angle dir, const point &pivot )
continue;
}

for(int xd=-2; xd<=2; xd++){//Calculate a small distance around the vehicle
for(int yd=-2; yd<=2; yd++){
for(int xd=-4; xd<=4; xd++){//Calculate a small distance around the vehicle
for(int yd=-4; yd<=4; yd++){

point mount=p.mount;
mount.x+=xd;
Expand All @@ -3118,7 +3136,8 @@ void vehicle::precalc_mounts( int idir, units::angle dir, const point &pivot )
coord_translate( tdir, pivot, mount, out );
}
if(xd==0 && yd==0){
p.precalc[idir] = out;
p.precalc[idir].x = out.x;
p.precalc[idir].y = out.y;
}
}
}
Expand All @@ -3127,7 +3146,7 @@ void vehicle::precalc_mounts( int idir, units::angle dir, const point &pivot )
pivot_rotation[idir] = dir;
}

bool vehicle::allowed_move( const point &from, const point &to) const
bool vehicle::check_rotated_intervening(const point &from, const point &to, bool( *check )( const vehicle * , const point & )) const
{
point delta=to-from;
if( abs(delta.x) <=1 && abs(delta.y) <=1 ) { //Just a normal move
Expand All @@ -3141,30 +3160,44 @@ bool vehicle::allowed_move( const point &from, const point &to) const

if( abs(delta.x)==2 ){//Mostly horizontal move
point t1={from.x+(delta.x/2), from.y+delta.y};
if(obstacle_at_position(t1)==-1){
if(check(this, t1)){
return true;
}

point t2={from.x+(delta.x/2), from.y};
if(obstacle_at_position(t2)==-1){
if(check(this, t2)){
return true;
}

}else{//Mostly vertical move
point t1={from.x+delta.x, from.y+(delta.y/2)};
if(obstacle_at_position(t1)==-1){
if(check(this, t1)){
return true;
}

point t2={from.x, from.y+(delta.y/2)};
if(obstacle_at_position(t2)==-1){
if(check(this, t2)){
return true;
}
}

return false;
}

bool vehicle::allowed_light( const point &from, const point &to) const
{
return check_rotated_intervening(from, to, [](const vehicle* veh, const point &p) {
return (veh->opaque_at_position(p)==-1);//TODO! actual light check
});
}

bool vehicle::allowed_move( const point &from, const point &to) const
{
return check_rotated_intervening(from, to, [](const vehicle* veh, const point &p) {
return (veh->obstacle_at_position(p)==-1);
});
}

std::vector<int> vehicle::boarded_parts() const
{
std::vector<int> res;
Expand Down
8 changes: 7 additions & 1 deletion src/vehicle.h
Original file line number Diff line number Diff line change
Expand Up @@ -1011,6 +1011,7 @@ class vehicle
int avail_part_with_feature( int p, vpart_bitflags f, bool unbroken ) const;

int obstacle_at_position(const point &pos) const;
int opaque_at_position(const point &pos) const;

/**
* Check if vehicle has at least one unbroken part with specified flag
Expand Down Expand Up @@ -1227,7 +1228,7 @@ class vehicle
* Mark mass caches and pivot cache as dirty
*/
void invalidate_mass();

//Converts angles into turning increments
static int angle_to_increment(units::angle dir);

Expand Down Expand Up @@ -1740,6 +1741,11 @@ class vehicle
//Check if a movement is blocked
bool allowed_move(const point &from, const point &to) const;

//Check if light is blocked
bool allowed_light(const point &from, const point &to) const;

bool check_rotated_intervening(const point &from, const point &to, bool( *check )( const vehicle *, const point & )) const;

std::string disp_name() const;

/** Required strength to be able to successfully lift the vehicle unaided by equipment */
Expand Down
26 changes: 20 additions & 6 deletions tests/shadowcasting_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,9 @@ static void shadowcasting_runoff( const int iterations, const bool test_bresenha
float seen_squares_control[MAPSIZE * SEEX][MAPSIZE * SEEY] = {{0}};
float seen_squares_experiment[MAPSIZE * SEEX][MAPSIZE * SEEY] = {{0}};
float transparency_cache[MAPSIZE * SEEX][MAPSIZE * SEEY] = {{0}};
bool blocked_cache[MAPSIZE * SEEX][MAPSIZE * SEEY][2] = {{{0}}};

std::uninitialized_fill_n(&blocked_cache[0][0][0], MAPSIZE*SEEX*MAPSIZE*SEEY*2, false);

randomly_fill_transparency( transparency_cache );

Expand Down Expand Up @@ -249,7 +252,7 @@ static void shadowcasting_runoff( const int iterations, const bool test_bresenha
for( int i = 0; i < iterations; i++ ) {
// Then the current algorithm.
castLightAll<float, float, sight_calc, sight_check, update_light, accumulate_transparency>(
seen_squares_experiment, transparency_cache, offset );
seen_squares_experiment, transparency_cache, blocked_cache, offset );
}
const auto end2 = std::chrono::high_resolution_clock::now();

Expand Down Expand Up @@ -290,6 +293,9 @@ static void shadowcasting_float_quad(
float lit_squares_float[MAPSIZE * SEEX][MAPSIZE * SEEY] = {{0}};
four_quadrants lit_squares_quad[MAPSIZE * SEEX][MAPSIZE * SEEY] = {{}};
float transparency_cache[MAPSIZE * SEEX][MAPSIZE * SEEY] = {{0}};
bool blocked_cache[MAPSIZE * SEEX][MAPSIZE * SEEY][2] = {{{0}}};

std::uninitialized_fill_n(&blocked_cache[0][0][0], MAPSIZE*SEEX*MAPSIZE*SEEY*2, false);

randomly_fill_transparency( transparency_cache, denominator );

Expand All @@ -301,7 +307,7 @@ static void shadowcasting_float_quad(
for( int i = 0; i < iterations; i++ ) {
castLightAll<float, four_quadrants, sight_calc, sight_check, update_light_quadrants,
accumulate_transparency>(
lit_squares_quad, transparency_cache, offset );
lit_squares_quad, transparency_cache, blocked_cache, offset );
}
const auto end1 = std::chrono::high_resolution_clock::now();

Expand All @@ -310,7 +316,7 @@ static void shadowcasting_float_quad(
// Then the current algorithm.
castLightAll<float, float, sight_calc, sight_check, update_light,
accumulate_transparency>(
lit_squares_float, transparency_cache, offset );
lit_squares_float, transparency_cache, blocked_cache, offset );
}
const auto end2 = std::chrono::high_resolution_clock::now();

Expand Down Expand Up @@ -343,6 +349,9 @@ static void shadowcasting_3d_2d( const int iterations )
float seen_squares_experiment[MAPSIZE * SEEX][MAPSIZE * SEEY] = {{0}};
float transparency_cache[MAPSIZE * SEEX][MAPSIZE * SEEY] = {{0}};
bool floor_cache[MAPSIZE * SEEX][MAPSIZE * SEEY] = {{false}};
bool blocked_cache[MAPSIZE_X][MAPSIZE_Y][2] = {{{0}}};

std::fill_n(&blocked_cache[0][0][0], MAPSIZE*SEEX*MAPSIZE*SEEY*2, false);

randomly_fill_transparency( transparency_cache );

Expand All @@ -354,26 +363,28 @@ static void shadowcasting_3d_2d( const int iterations )
for( int i = 0; i < iterations; i++ ) {
// First the control algorithm.
castLightAll<float, float, sight_calc, sight_check, update_light, accumulate_transparency>(
seen_squares_control, transparency_cache, offset.xy() );
seen_squares_control, transparency_cache, blocked_cache, offset.xy() );
}
const auto end1 = std::chrono::high_resolution_clock::now();

const tripoint origin( offset );
std::array<const float ( * )[MAPSIZE *SEEX][MAPSIZE *SEEY], OVERMAP_LAYERS> transparency_caches;
std::array<float ( * )[MAPSIZE *SEEX][MAPSIZE *SEEY], OVERMAP_LAYERS> seen_caches;
std::array<const bool ( * )[MAPSIZE *SEEX][MAPSIZE *SEEY], OVERMAP_LAYERS> floor_caches;
std::array<const bool ( * )[MAPSIZE_X][MAPSIZE_Y][2], OVERMAP_LAYERS> blocked_caches;
for( int z = -OVERMAP_DEPTH; z <= OVERMAP_HEIGHT; z++ ) {
// TODO: Give some more proper values here
transparency_caches[z + OVERMAP_DEPTH] = &transparency_cache;
seen_caches[z + OVERMAP_DEPTH] = &seen_squares_experiment;
floor_caches[z + OVERMAP_DEPTH] = &floor_cache;
blocked_caches[z + OVERMAP_DEPTH] = &blocked_cache;
}

const auto start2 = std::chrono::high_resolution_clock::now();
for( int i = 0; i < iterations; i++ ) {
// Then the newer algorithm.
cast_zlight<float, sight_calc, sight_check, accumulate_transparency>(
seen_caches, transparency_caches, floor_caches, origin, 0, 1.0 );
seen_caches, transparency_caches, floor_caches, blocked_caches, origin, 0, 1.0 );
}
const auto end2 = std::chrono::high_resolution_clock::now();

Expand Down Expand Up @@ -446,6 +457,9 @@ static void run_spot_check( const grid_overlay &test_case, const grid_overlay &e
{
float seen_squares[ MAPSIZE * SEEY ][ MAPSIZE * SEEX ] = {{ 0 }};
float transparency_cache[ MAPSIZE * SEEY ][ MAPSIZE * SEEX ] = {{ 0 }};
bool blocked_cache[MAPSIZE_X][MAPSIZE_Y][2] = {{{0}}};

std::fill_n(&blocked_cache[0][0][0], MAPSIZE_X*MAPSIZE_Y*2, false);

for( int y = 0; y < static_cast<int>( sizeof( transparency_cache ) /
sizeof( transparency_cache[0] ) ); ++y ) {
Expand All @@ -456,7 +470,7 @@ static void run_spot_check( const grid_overlay &test_case, const grid_overlay &e
}

castLightAll<float, float, sight_calc, sight_check, update_light, accumulate_transparency>(
seen_squares, transparency_cache, ORIGIN );
seen_squares, transparency_cache, blocked_cache, ORIGIN );

// Compares the whole grid, but out-of-bounds compares will de-facto pass.
for( int y = 0; y < expected_result.height(); ++y ) {
Expand Down

0 comments on commit de22376

Please sign in to comment.