void map::apply_light_arc(int x, int y, int angle, float luminance, int wideangle ) { if (luminance <= LIGHT_SOURCE_LOCAL) { return; } static bool lit[LIGHTMAP_CACHE_X][LIGHTMAP_CACHE_Y]; memset(lit, 0, sizeof(lit)); #define lum_mult 3.0 luminance = luminance * lum_mult; int range = LIGHT_RANGE(luminance); apply_light_source(x, y, LIGHT_SOURCE_LOCAL, trigdist); // Normalise (should work with negative values too) const double PI = 3.14159265358979f; const double HALFPI = 1.570796326794895f; const double wangle = wideangle / 2.0; int nangle = angle % 360; int endx, endy; double rad = PI * (double)nangle / 180; calc_ray_end(nangle, range, x, y, &endx, &endy); apply_light_ray(lit, x, y, endx, endy , luminance, trigdist); int testx, testy; calc_ray_end(wangle + nangle, range, x, y, &testx, &testy); double wdist = sqrt(double((endx - testx) * (endx - testx) + (endy - testy) * (endy - testy))); if(wdist > 0.5) { double wstep = ( wangle / ( wdist * 1.42 ) ); // attempt to determine beam density required to cover all squares for (double ao = wstep; ao <= wangle; ao += wstep) { if ( trigdist ) { double fdist = (ao * HALFPI) / wangle; double orad = ( PI * ao / 180.0 ); endx = int( x + ( (double)range - fdist * 2.0) * cos(rad + orad) ); endy = int( y + ( (double)range - fdist * 2.0) * sin(rad + orad) ); apply_light_ray(lit, x, y, endx, endy , luminance, true); endx = int( x + ( (double)range - fdist * 2.0) * cos(rad - orad) ); endy = int( y + ( (double)range - fdist * 2.0) * sin(rad - orad) ); apply_light_ray(lit, x, y, endx, endy , luminance, true); } else { calc_ray_end(nangle + ao, range, x, y, &endx, &endy); apply_light_ray(lit, x, y, endx, endy , luminance, false); calc_ray_end(nangle - ao, range, x, y, &endx, &endy); apply_light_ray(lit, x, y, endx, endy , luminance, false); } } } }
void map::apply_light_arc(int x, int y, int angle, float luminance, int wideangle ) { if (luminance <= LIGHT_SOURCE_LOCAL) { return; } bool lit[LIGHTMAP_CACHE_X][LIGHTMAP_CACHE_Y] {}; constexpr float lum_mult = 3.0f; luminance = luminance * lum_mult; int range = LIGHT_RANGE(luminance); apply_light_source(x, y, LIGHT_SOURCE_LOCAL, trigdist); // Normalise (should work with negative values too) const double wangle = wideangle / 2.0; int nangle = angle % 360; int endx, endy; double rad = PI * (double)nangle / 180; calc_ray_end(nangle, range, x, y, &endx, &endy); apply_light_ray(lit, x, y, endx, endy , luminance, trigdist); int testx, testy; calc_ray_end(wangle + nangle, range, x, y, &testx, &testy); const float wdist = hypot(endx - testx, endy - testy); if (wdist <= 0.5) { return; } // attempt to determine beam density required to cover all squares const double wstep = ( wangle / ( wdist * SQRT_2 ) ); for (double ao = wstep; ao <= wangle; ao += wstep) { if ( trigdist ) { double fdist = (ao * HALFPI) / wangle; double orad = ( PI * ao / 180.0 ); endx = int( x + ( (double)range - fdist * 2.0) * cos(rad + orad) ); endy = int( y + ( (double)range - fdist * 2.0) * sin(rad + orad) ); apply_light_ray(lit, x, y, endx, endy , luminance, true); endx = int( x + ( (double)range - fdist * 2.0) * cos(rad - orad) ); endy = int( y + ( (double)range - fdist * 2.0) * sin(rad - orad) ); apply_light_ray(lit, x, y, endx, endy , luminance, true); } else { calc_ray_end(nangle + ao, range, x, y, &endx, &endy); apply_light_ray(lit, x, y, endx, endy , luminance, false); calc_ray_end(nangle - ao, range, x, y, &endx, &endy); apply_light_ray(lit, x, y, endx, endy , luminance, false); } } }
void map::apply_light_source(int x, int y, float luminance, bool trig_brightcalc ) { bool lit[LIGHTMAP_CACHE_X][LIGHTMAP_CACHE_Y]; memset(lit, 0, sizeof(lit)); if (INBOUNDS(x, y)) { lit[x][y] = true; lm[x][y] += std::max(luminance, static_cast<float>(LL_LOW)); sm[x][y] += luminance; } if ( luminance <= 1 ) { return; } else if ( luminance <=2 ) { luminance = 1.49f; } /* If we're a 5 luminance fire , we skip casting rays into ey && sx if we have neighboring fires to the north and west that were applied via light_source_buffer If there's a 1 luminance candle east in buffer, we still cast rays into ex since it's smaller If there's a 100 luminance magnesium flare south added via apply_light_source instead od add_light_source, it's unbuffered so we'll still cast rays into sy. ey nnnNnnn w e w 5 +e sx W 5*1+E ex w ++++e w+++++e sssSsss sy */ const int peer_inbounds = LIGHTMAP_CACHE_X-1; bool north=(y != 0 && light_source_buffer[x][y-1] < luminance ); bool south=(y != peer_inbounds && light_source_buffer[x][y+1] < luminance ); bool east=(x != peer_inbounds && light_source_buffer[x+1][y] < luminance ); bool west=(x != 0 && light_source_buffer[x-1][y] < luminance ); if (luminance > LIGHT_SOURCE_LOCAL) { int range = LIGHT_RANGE(luminance); int sx = x - range; int ex = x + range; int sy = y - range; int ey = y + range; for(int off = sx; off <= ex; ++off) { if ( south ) apply_light_ray(lit, x, y, off, sy, luminance, trig_brightcalc); if ( north ) apply_light_ray(lit, x, y, off, ey, luminance, trig_brightcalc); } // Skip corners with + 1 and < as they were done for(int off = sy + 1; off < ey; ++off) { if ( west ) apply_light_ray(lit, x, y, sx, off, luminance, trig_brightcalc); if ( east ) apply_light_ray(lit, x, y, ex, off, luminance, trig_brightcalc); } } }
void map::apply_light_arc( const tripoint &p, int angle, float luminance, int wideangle ) { if (luminance <= LIGHT_SOURCE_LOCAL) { return; } bool lit[LIGHTMAP_CACHE_X][LIGHTMAP_CACHE_Y] {}; apply_light_source( p, LIGHT_SOURCE_LOCAL ); // Normalise (should work with negative values too) const double wangle = wideangle / 2.0; int nangle = angle % 360; tripoint end; double rad = PI * (double)nangle / 180; int range = LIGHT_RANGE(luminance); calc_ray_end( nangle, range, p, end ); apply_light_ray(lit, p, end , luminance); tripoint test; calc_ray_end(wangle + nangle, range, p, test ); const float wdist = hypot( end.x - test.x, end.y - test.y ); if (wdist <= 0.5) { return; } // attempt to determine beam density required to cover all squares const double wstep = ( wangle / ( wdist * SQRT_2 ) ); for( double ao = wstep; ao <= wangle; ao += wstep ) { if( trigdist ) { double fdist = (ao * HALFPI) / wangle; double orad = ( PI * ao / 180.0 ); end.x = int( p.x + ( (double)range - fdist * 2.0) * cos(rad + orad) ); end.y = int( p.y + ( (double)range - fdist * 2.0) * sin(rad + orad) ); apply_light_ray( lit, p, end, luminance ); end.x = int( p.x + ( (double)range - fdist * 2.0) * cos(rad - orad) ); end.y = int( p.y + ( (double)range - fdist * 2.0) * sin(rad - orad) ); apply_light_ray( lit, p, end, luminance ); } else { calc_ray_end( nangle + ao, range, p, end ); apply_light_ray( lit, p, end, luminance ); calc_ray_end( nangle - ao, range, p, end ); apply_light_ray( lit, p, end, luminance ); } } }