mirror of
https://github.com/minetest/minetest.git
synced 2024-08-19 21:14:15 +02:00
Optimize lighting calculation (#12797)
This commit is contained in:
parent
440d966b93
commit
9676364c1f
@ -527,8 +527,8 @@ static bool getVisibleBrightness(Map *map, const v3f &p0, v3f dir, float step,
|
|||||||
{
|
{
|
||||||
v3s16 p = floatToInt(p0 /*+ dir * 3*BS*/, BS);
|
v3s16 p = floatToInt(p0 /*+ dir * 3*BS*/, BS);
|
||||||
MapNode n = map->getNode(p);
|
MapNode n = map->getNode(p);
|
||||||
if(ndef->get(n).param_type == CPT_LIGHT &&
|
if(ndef->getLightingFlags(n).has_light &&
|
||||||
!ndef->get(n).sunlight_propagates)
|
!ndef->getLightingFlags(n).sunlight_propagates)
|
||||||
allow_allowing_non_sunlight_propagates = true;
|
allow_allowing_non_sunlight_propagates = true;
|
||||||
}
|
}
|
||||||
// If would start at CONTENT_IGNORE, start closer
|
// If would start at CONTENT_IGNORE, start closer
|
||||||
@ -549,15 +549,13 @@ static bool getVisibleBrightness(Map *map, const v3f &p0, v3f dir, float step,
|
|||||||
|
|
||||||
v3s16 p = floatToInt(pf, BS);
|
v3s16 p = floatToInt(pf, BS);
|
||||||
MapNode n = map->getNode(p);
|
MapNode n = map->getNode(p);
|
||||||
|
ContentLightingFlags f = ndef->getLightingFlags(n);
|
||||||
if (allow_allowing_non_sunlight_propagates && i == 0 &&
|
if (allow_allowing_non_sunlight_propagates && i == 0 &&
|
||||||
ndef->get(n).param_type == CPT_LIGHT &&
|
f.has_light && !f.sunlight_propagates) {
|
||||||
!ndef->get(n).sunlight_propagates) {
|
|
||||||
allow_non_sunlight_propagates = true;
|
allow_non_sunlight_propagates = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ndef->get(n).param_type != CPT_LIGHT ||
|
if (!f.has_light || (!f.sunlight_propagates && !allow_non_sunlight_propagates)){
|
||||||
(!ndef->get(n).sunlight_propagates &&
|
|
||||||
!allow_non_sunlight_propagates)){
|
|
||||||
nonlight_seen = true;
|
nonlight_seen = true;
|
||||||
noncount++;
|
noncount++;
|
||||||
if(noncount >= 4)
|
if(noncount >= 4)
|
||||||
@ -566,10 +564,10 @@ static bool getVisibleBrightness(Map *map, const v3f &p0, v3f dir, float step,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (distance >= sunlight_min_d && !*sunlight_seen && !nonlight_seen)
|
if (distance >= sunlight_min_d && !*sunlight_seen && !nonlight_seen)
|
||||||
if (n.getLight(LIGHTBANK_DAY, ndef) == LIGHT_SUN)
|
if (n.getLight(LIGHTBANK_DAY, f) == LIGHT_SUN)
|
||||||
*sunlight_seen = true;
|
*sunlight_seen = true;
|
||||||
noncount = 0;
|
noncount = 0;
|
||||||
brightness_sum += decode_light(n.getLightBlend(daylight_factor, ndef));
|
brightness_sum += decode_light(n.getLightBlend(daylight_factor, f));
|
||||||
brightness_count++;
|
brightness_count++;
|
||||||
}
|
}
|
||||||
*result = 0;
|
*result = 0;
|
||||||
@ -653,8 +651,9 @@ int ClientMap::getBackgroundBrightness(float max_d, u32 daylight_factor,
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
if(brightness_count == 0){
|
if(brightness_count == 0){
|
||||||
MapNode n = getNode(floatToInt(m_camera_position, BS));
|
MapNode n = getNode(floatToInt(m_camera_position, BS));
|
||||||
if(m_nodedef->get(n).param_type == CPT_LIGHT){
|
ContentLightingFlags f = m_nodedef->getLightingFlags(n);
|
||||||
ret = decode_light(n.getLightBlend(daylight_factor, m_nodedef));
|
if(f.has_light){
|
||||||
|
ret = decode_light(n.getLightBlend(daylight_factor, f));
|
||||||
} else {
|
} else {
|
||||||
ret = oldvalue;
|
ret = oldvalue;
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "clientenvironment.h"
|
#include "clientenvironment.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
|
#include "nodedef.h"
|
||||||
|
|
||||||
class SmokePuffCSO: public ClientSimpleObject
|
class SmokePuffCSO: public ClientSimpleObject
|
||||||
{
|
{
|
||||||
@ -50,7 +51,7 @@ public:
|
|||||||
bool pos_ok;
|
bool pos_ok;
|
||||||
MapNode n = env->getMap().getNode(floatToInt(pos, BS), &pos_ok);
|
MapNode n = env->getMap().getNode(floatToInt(pos, BS), &pos_ok);
|
||||||
light = pos_ok ? decode_light(n.getLightBlend(env->getDayNightRatio(),
|
light = pos_ok ? decode_light(n.getLightBlend(env->getDayNightRatio(),
|
||||||
env->getGameDef()->ndef()))
|
env->getGameDef()->ndef()->getLightingFlags(n)))
|
||||||
: 64;
|
: 64;
|
||||||
video::SColor color(255,light,light,light);
|
video::SColor color(255,light,light,light);
|
||||||
m_spritenode->setColor(color);
|
m_spritenode->setColor(color);
|
||||||
|
@ -472,7 +472,7 @@ void MapblockMeshGenerator::prepareLiquidNodeDrawing()
|
|||||||
// it at what it emits, for an increased effect
|
// it at what it emits, for an increased effect
|
||||||
u8 e = decode_light(f->light_source);
|
u8 e = decode_light(f->light_source);
|
||||||
light = LightPair(std::max(e, light.lightDay), std::max(e, light.lightNight));
|
light = LightPair(std::max(e, light.lightDay), std::max(e, light.lightNight));
|
||||||
} else if (nodedef->get(ntop).param_type == CPT_LIGHT) {
|
} else if (nodedef->getLightingFlags(ntop).has_light) {
|
||||||
// Otherwise, use the light of the node on top if possible
|
// Otherwise, use the light of the node on top if possible
|
||||||
light = LightPair(getInteriorLight(ntop, 0, nodedef));
|
light = LightPair(getInteriorLight(ntop, 0, nodedef));
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,7 @@ void MeshMakeData::setSmoothLighting(bool smooth_lighting)
|
|||||||
static u8 getInteriorLight(enum LightBank bank, MapNode n, s32 increment,
|
static u8 getInteriorLight(enum LightBank bank, MapNode n, s32 increment,
|
||||||
const NodeDefManager *ndef)
|
const NodeDefManager *ndef)
|
||||||
{
|
{
|
||||||
u8 light = n.getLight(bank, ndef);
|
u8 light = n.getLight(bank, ndef->getLightingFlags(n));
|
||||||
if (light > 0)
|
if (light > 0)
|
||||||
light = rangelim(light + increment, 0, LIGHT_SUN);
|
light = rangelim(light + increment, 0, LIGHT_SUN);
|
||||||
return decode_light(light);
|
return decode_light(light);
|
||||||
@ -126,17 +126,19 @@ u16 getInteriorLight(MapNode n, s32 increment, const NodeDefManager *ndef)
|
|||||||
static u8 getFaceLight(enum LightBank bank, MapNode n, MapNode n2,
|
static u8 getFaceLight(enum LightBank bank, MapNode n, MapNode n2,
|
||||||
v3s16 face_dir, const NodeDefManager *ndef)
|
v3s16 face_dir, const NodeDefManager *ndef)
|
||||||
{
|
{
|
||||||
|
ContentLightingFlags f1 = ndef->getLightingFlags(n);
|
||||||
|
ContentLightingFlags f2 = ndef->getLightingFlags(n2);
|
||||||
|
|
||||||
u8 light;
|
u8 light;
|
||||||
u8 l1 = n.getLight(bank, ndef);
|
u8 l1 = n.getLight(bank, f1);
|
||||||
u8 l2 = n2.getLight(bank, ndef);
|
u8 l2 = n2.getLight(bank, f2);
|
||||||
if(l1 > l2)
|
if(l1 > l2)
|
||||||
light = l1;
|
light = l1;
|
||||||
else
|
else
|
||||||
light = l2;
|
light = l2;
|
||||||
|
|
||||||
// Boost light level for light sources
|
// Boost light level for light sources
|
||||||
u8 light_source = MYMAX(ndef->get(n).light_source,
|
u8 light_source = MYMAX(f1.light_source, f2.light_source);
|
||||||
ndef->get(n2).light_source);
|
|
||||||
if(light_source > light)
|
if(light_source > light)
|
||||||
light = light_source;
|
light = light_source;
|
||||||
|
|
||||||
@ -184,8 +186,8 @@ static u16 getSmoothLightCombined(const v3s16 &p,
|
|||||||
light_source_max = f.light_source;
|
light_source_max = f.light_source;
|
||||||
// Check f.solidness because fast-style leaves look better this way
|
// Check f.solidness because fast-style leaves look better this way
|
||||||
if (f.param_type == CPT_LIGHT && f.solidness != 2) {
|
if (f.param_type == CPT_LIGHT && f.solidness != 2) {
|
||||||
u8 light_level_day = n.getLightNoChecks(LIGHTBANK_DAY, &f);
|
u8 light_level_day = n.getLight(LIGHTBANK_DAY, f.getLightingFlags());
|
||||||
u8 light_level_night = n.getLightNoChecks(LIGHTBANK_NIGHT, &f);
|
u8 light_level_night = n.getLight(LIGHTBANK_NIGHT, f.getLightingFlags());
|
||||||
if (light_level_day == LIGHT_SUN)
|
if (light_level_day == LIGHT_SUN)
|
||||||
direct_sunlight = true;
|
direct_sunlight = true;
|
||||||
light_day += decode_light(light_level_day);
|
light_day += decode_light(light_level_day);
|
||||||
|
@ -265,7 +265,8 @@ void Particle::updateLight()
|
|||||||
);
|
);
|
||||||
MapNode n = m_env->getClientMap().getNode(p, &pos_ok);
|
MapNode n = m_env->getClientMap().getNode(p, &pos_ok);
|
||||||
if (pos_ok)
|
if (pos_ok)
|
||||||
light = n.getLightBlend(m_env->getDayNightRatio(), m_gamedef->ndef());
|
light = n.getLightBlend(m_env->getDayNightRatio(),
|
||||||
|
m_gamedef->ndef()->getLightingFlags(n));
|
||||||
else
|
else
|
||||||
light = blend_light(m_env->getDayNightRatio(), LIGHT_SUN, 0);
|
light = blend_light(m_env->getDayNightRatio(), LIGHT_SUN, 0);
|
||||||
|
|
||||||
|
21
src/map.cpp
21
src/map.cpp
@ -213,19 +213,19 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set the node on the map
|
// Set the node on the map
|
||||||
const ContentFeatures &cf = m_nodedef->get(n);
|
ContentLightingFlags f = m_nodedef->getLightingFlags(n);
|
||||||
const ContentFeatures &oldcf = m_nodedef->get(oldnode);
|
ContentLightingFlags oldf = m_nodedef->getLightingFlags(oldnode);
|
||||||
if (cf.lightingEquivalent(oldcf)) {
|
if (f == oldf) {
|
||||||
// No light update needed, just copy over the old light.
|
// No light update needed, just copy over the old light.
|
||||||
n.setLight(LIGHTBANK_DAY, oldnode.getLightRaw(LIGHTBANK_DAY, oldcf), cf);
|
n.setLight(LIGHTBANK_DAY, oldnode.getLightRaw(LIGHTBANK_DAY, oldf), f);
|
||||||
n.setLight(LIGHTBANK_NIGHT, oldnode.getLightRaw(LIGHTBANK_NIGHT, oldcf), cf);
|
n.setLight(LIGHTBANK_NIGHT, oldnode.getLightRaw(LIGHTBANK_NIGHT, oldf), f);
|
||||||
set_node_in_block(block, relpos, n);
|
set_node_in_block(block, relpos, n);
|
||||||
|
|
||||||
modified_blocks[blockpos] = block;
|
modified_blocks[blockpos] = block;
|
||||||
} else {
|
} else {
|
||||||
// Ignore light (because calling voxalgo::update_lighting_nodes)
|
// Ignore light (because calling voxalgo::update_lighting_nodes)
|
||||||
n.setLight(LIGHTBANK_DAY, 0, cf);
|
n.setLight(LIGHTBANK_DAY, 0, f);
|
||||||
n.setLight(LIGHTBANK_NIGHT, 0, cf);
|
n.setLight(LIGHTBANK_NIGHT, 0, f);
|
||||||
set_node_in_block(block, relpos, n);
|
set_node_in_block(block, relpos, n);
|
||||||
|
|
||||||
// Update lighting
|
// Update lighting
|
||||||
@ -780,8 +780,9 @@ void ServerMap::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ignore light (because calling voxalgo::update_lighting_nodes)
|
// Ignore light (because calling voxalgo::update_lighting_nodes)
|
||||||
n0.setLight(LIGHTBANK_DAY, 0, m_nodedef);
|
ContentLightingFlags f0 = m_nodedef->getLightingFlags(n0);
|
||||||
n0.setLight(LIGHTBANK_NIGHT, 0, m_nodedef);
|
n0.setLight(LIGHTBANK_DAY, 0, f0);
|
||||||
|
n0.setLight(LIGHTBANK_NIGHT, 0, f0);
|
||||||
|
|
||||||
// Find out whether there is a suspect for this action
|
// Find out whether there is a suspect for this action
|
||||||
std::string suspect;
|
std::string suspect;
|
||||||
@ -1122,7 +1123,7 @@ bool Map::isOccluded(const v3s16 &pos_camera, const v3s16 &pos_target,
|
|||||||
MapNode node = getNode(pos_node, &is_valid_position);
|
MapNode node = getNode(pos_node, &is_valid_position);
|
||||||
|
|
||||||
if (is_valid_position &&
|
if (is_valid_position &&
|
||||||
!m_nodedef->get(node).light_propagates) {
|
!m_nodedef->getLightingFlags(node).light_propagates) {
|
||||||
// Cannot see through light-blocking nodes --> occluded
|
// Cannot see through light-blocking nodes --> occluded
|
||||||
count++;
|
count++;
|
||||||
if (count >= needed_count)
|
if (count >= needed_count)
|
||||||
|
@ -180,7 +180,7 @@ void MapBlock::actuallyUpdateDayNightDiff()
|
|||||||
if (n == previous_n)
|
if (n == previous_n)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
differs = !n.isLightDayNightEq(nodemgr);
|
differs = !n.isLightDayNightEq(nodemgr->getLightingFlags(n));
|
||||||
if (differs)
|
if (differs)
|
||||||
break;
|
break;
|
||||||
previous_n = n;
|
previous_n = n;
|
||||||
|
@ -450,7 +450,7 @@ void Mapgen::lightSpread(VoxelArea &a, std::queue<std::pair<v3s16, u8>> &queue,
|
|||||||
// we hit a solid block that light cannot pass through.
|
// we hit a solid block that light cannot pass through.
|
||||||
if ((light_day <= (n.param1 & 0x0F) &&
|
if ((light_day <= (n.param1 & 0x0F) &&
|
||||||
light_night <= (n.param1 & 0xF0)) ||
|
light_night <= (n.param1 & 0xF0)) ||
|
||||||
!ndef->get(n).light_propagates)
|
!ndef->getLightingFlags(n).light_propagates)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// MYMAX still needed here because we only exit early if both banks have
|
// MYMAX still needed here because we only exit early if both banks have
|
||||||
@ -500,7 +500,7 @@ void Mapgen::propagateSunlight(v3s16 nmin, v3s16 nmax, bool propagate_shadow)
|
|||||||
|
|
||||||
for (int y = a.MaxEdge.Y; y >= a.MinEdge.Y; y--) {
|
for (int y = a.MaxEdge.Y; y >= a.MinEdge.Y; y--) {
|
||||||
MapNode &n = vm->m_data[i];
|
MapNode &n = vm->m_data[i];
|
||||||
if (!ndef->get(n).sunlight_propagates)
|
if (!ndef->getLightingFlags(n).sunlight_propagates)
|
||||||
break;
|
break;
|
||||||
n.param1 = LIGHT_SUN;
|
n.param1 = LIGHT_SUN;
|
||||||
VoxelArea::add_y(em, i, -1);
|
VoxelArea::add_y(em, i, -1);
|
||||||
@ -525,7 +525,7 @@ void Mapgen::spreadLight(const v3s16 &nmin, const v3s16 &nmax)
|
|||||||
if (n.getContent() == CONTENT_IGNORE)
|
if (n.getContent() == CONTENT_IGNORE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const ContentFeatures &cf = ndef->get(n);
|
ContentLightingFlags cf = ndef->getLightingFlags(n);
|
||||||
if (!cf.light_propagates)
|
if (!cf.light_propagates)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ MapgenSinglenode::MapgenSinglenode(MapgenParams *params, EmergeParams *emerge)
|
|||||||
c_node = CONTENT_AIR;
|
c_node = CONTENT_AIR;
|
||||||
|
|
||||||
MapNode n_node(c_node);
|
MapNode n_node(c_node);
|
||||||
set_light = (ndef->get(n_node).sunlight_propagates) ? LIGHT_SUN : 0x00;
|
set_light = (ndef->getLightingFlags(n_node).sunlight_propagates) ? LIGHT_SUN : 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,95 +53,6 @@ void MapNode::getColor(const ContentFeatures &f, video::SColor *color) const
|
|||||||
*color = f.color;
|
*color = f.color;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapNode::setLight(LightBank bank, u8 a_light, const ContentFeatures &f) noexcept
|
|
||||||
{
|
|
||||||
// If node doesn't contain light data, ignore this
|
|
||||||
if(f.param_type != CPT_LIGHT)
|
|
||||||
return;
|
|
||||||
if(bank == LIGHTBANK_DAY)
|
|
||||||
{
|
|
||||||
param1 &= 0xf0;
|
|
||||||
param1 |= a_light & 0x0f;
|
|
||||||
}
|
|
||||||
else if(bank == LIGHTBANK_NIGHT)
|
|
||||||
{
|
|
||||||
param1 &= 0x0f;
|
|
||||||
param1 |= (a_light & 0x0f)<<4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
assert("Invalid light bank" == NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MapNode::setLight(LightBank bank, u8 a_light, const NodeDefManager *nodemgr)
|
|
||||||
{
|
|
||||||
setLight(bank, a_light, nodemgr->get(*this));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MapNode::isLightDayNightEq(const NodeDefManager *nodemgr) const
|
|
||||||
{
|
|
||||||
const ContentFeatures &f = nodemgr->get(*this);
|
|
||||||
bool isEqual;
|
|
||||||
|
|
||||||
if (f.param_type == CPT_LIGHT) {
|
|
||||||
u8 day = MYMAX(f.light_source, param1 & 0x0f);
|
|
||||||
u8 night = MYMAX(f.light_source, (param1 >> 4) & 0x0f);
|
|
||||||
isEqual = day == night;
|
|
||||||
} else {
|
|
||||||
isEqual = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return isEqual;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 MapNode::getLight(LightBank bank, const NodeDefManager *nodemgr) const
|
|
||||||
{
|
|
||||||
// Select the brightest of [light source, propagated light]
|
|
||||||
const ContentFeatures &f = nodemgr->get(*this);
|
|
||||||
|
|
||||||
u8 light;
|
|
||||||
if(f.param_type == CPT_LIGHT)
|
|
||||||
light = bank == LIGHTBANK_DAY ? param1 & 0x0f : (param1 >> 4) & 0x0f;
|
|
||||||
else
|
|
||||||
light = 0;
|
|
||||||
|
|
||||||
return MYMAX(f.light_source, light);
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 MapNode::getLightRaw(LightBank bank, const ContentFeatures &f) const noexcept
|
|
||||||
{
|
|
||||||
if(f.param_type == CPT_LIGHT)
|
|
||||||
return bank == LIGHTBANK_DAY ? param1 & 0x0f : (param1 >> 4) & 0x0f;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 MapNode::getLightNoChecks(LightBank bank, const ContentFeatures *f) const noexcept
|
|
||||||
{
|
|
||||||
return MYMAX(f->light_source,
|
|
||||||
bank == LIGHTBANK_DAY ? param1 & 0x0f : (param1 >> 4) & 0x0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MapNode::getLightBanks(u8 &lightday, u8 &lightnight,
|
|
||||||
const NodeDefManager *nodemgr) const
|
|
||||||
{
|
|
||||||
// Select the brightest of [light source, propagated light]
|
|
||||||
const ContentFeatures &f = nodemgr->get(*this);
|
|
||||||
if(f.param_type == CPT_LIGHT)
|
|
||||||
{
|
|
||||||
lightday = param1 & 0x0f;
|
|
||||||
lightnight = (param1>>4)&0x0f;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lightday = 0;
|
|
||||||
lightnight = 0;
|
|
||||||
}
|
|
||||||
if(f.light_source > lightday)
|
|
||||||
lightday = f.light_source;
|
|
||||||
if(f.light_source > lightnight)
|
|
||||||
lightnight = f.light_source;
|
|
||||||
return f.param_type == CPT_LIGHT || f.light_source != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 MapNode::getFaceDir(const NodeDefManager *nodemgr,
|
u8 MapNode::getFaceDir(const NodeDefManager *nodemgr,
|
||||||
bool allow_wallmounted) const
|
bool allow_wallmounted) const
|
||||||
{
|
{
|
||||||
|
@ -35,6 +35,7 @@ class Map;
|
|||||||
- Tile = TileSpec at some side of a node of some content type
|
- Tile = TileSpec at some side of a node of some content type
|
||||||
*/
|
*/
|
||||||
typedef u16 content_t;
|
typedef u16 content_t;
|
||||||
|
#define CONTENT_MAX UINT16_MAX
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The maximum node ID that can be registered by mods. This must
|
The maximum node ID that can be registered by mods. This must
|
||||||
@ -71,6 +72,25 @@ typedef u16 content_t;
|
|||||||
*/
|
*/
|
||||||
#define CONTENT_IGNORE 127
|
#define CONTENT_IGNORE 127
|
||||||
|
|
||||||
|
/*
|
||||||
|
Content lighting information that fits into a single byte.
|
||||||
|
*/
|
||||||
|
struct ContentLightingFlags {
|
||||||
|
u8 light_source : 4;
|
||||||
|
bool has_light : 1;
|
||||||
|
bool light_propagates : 1;
|
||||||
|
bool sunlight_propagates : 1;
|
||||||
|
|
||||||
|
bool operator==(const ContentLightingFlags &other) const
|
||||||
|
{
|
||||||
|
return has_light == other.has_light && light_propagates == other.light_propagates &&
|
||||||
|
sunlight_propagates == other.sunlight_propagates &&
|
||||||
|
light_source == other.light_source;
|
||||||
|
}
|
||||||
|
bool operator!=(const ContentLightingFlags &other) const { return !(*this == other); }
|
||||||
|
};
|
||||||
|
static_assert(sizeof(ContentLightingFlags) == 1, "Unexpected ContentLightingFlags size");
|
||||||
|
|
||||||
enum LightBank
|
enum LightBank
|
||||||
{
|
{
|
||||||
LIGHTBANK_DAY,
|
LIGHTBANK_DAY,
|
||||||
@ -187,53 +207,55 @@ struct MapNode
|
|||||||
*/
|
*/
|
||||||
void getColor(const ContentFeatures &f, video::SColor *color) const;
|
void getColor(const ContentFeatures &f, video::SColor *color) const;
|
||||||
|
|
||||||
void setLight(LightBank bank, u8 a_light, const ContentFeatures &f) noexcept;
|
inline void setLight(LightBank bank, u8 a_light, ContentLightingFlags f) noexcept
|
||||||
|
{
|
||||||
void setLight(LightBank bank, u8 a_light, const NodeDefManager *nodemgr);
|
// If node doesn't contain light data, ignore this
|
||||||
|
if (!f.has_light)
|
||||||
|
return;
|
||||||
|
if (bank == LIGHTBANK_DAY) {
|
||||||
|
param1 &= 0xf0;
|
||||||
|
param1 |= a_light & 0x0f;
|
||||||
|
} else {
|
||||||
|
assert(bank == LIGHTBANK_NIGHT);
|
||||||
|
param1 &= 0x0f;
|
||||||
|
param1 |= (a_light & 0x0f)<<4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the light value for night differs from the light value for day.
|
* Check if the light value for night differs from the light value for day.
|
||||||
*
|
*
|
||||||
* @return If the light values are equal, returns true; otherwise false
|
* @return If the light values are equal, returns true; otherwise false
|
||||||
*/
|
*/
|
||||||
bool isLightDayNightEq(const NodeDefManager *nodemgr) const;
|
inline bool isLightDayNightEq(ContentLightingFlags f) const noexcept
|
||||||
|
{
|
||||||
|
return !f.has_light || getLight(LIGHTBANK_DAY, f) == getLight(LIGHTBANK_NIGHT, f);
|
||||||
|
}
|
||||||
|
|
||||||
u8 getLight(LightBank bank, const NodeDefManager *nodemgr) const;
|
inline u8 getLight(LightBank bank, ContentLightingFlags f) const noexcept
|
||||||
|
{
|
||||||
|
u8 raw_light = getLightRaw(bank, f);
|
||||||
|
return MYMAX(f.light_source, raw_light);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the node's light level from param1.
|
* Returns the node's light level from param1.
|
||||||
* If the node emits light, it is ignored.
|
* If the node emits light, it is ignored.
|
||||||
* \param f the ContentFeatures of this node.
|
* \param f the ContentLightingFlags of this node.
|
||||||
*/
|
*/
|
||||||
u8 getLightRaw(LightBank bank, const ContentFeatures &f) const noexcept;
|
inline u8 getLightRaw(LightBank bank, ContentLightingFlags f) const noexcept
|
||||||
|
{
|
||||||
/**
|
if(f.has_light)
|
||||||
* This function differs from getLight(LightBank bank, NodeDefManager *nodemgr)
|
return bank == LIGHTBANK_DAY ? param1 & 0x0f : (param1 >> 4) & 0x0f;
|
||||||
* in that the ContentFeatures of the node in question are not retrieved by
|
return 0;
|
||||||
* the function itself. Thus, if you have already called nodemgr->get() to
|
}
|
||||||
* get the ContentFeatures you pass it to this function instead of the
|
|
||||||
* function getting ContentFeatures itself. Since NodeDefManager::get()
|
|
||||||
* is relatively expensive this can lead to significant performance
|
|
||||||
* improvements in some situations. Call this function if (and only if)
|
|
||||||
* you have already retrieved the ContentFeatures by calling
|
|
||||||
* NodeDefManager::get() for the node you're working with and the
|
|
||||||
* pre-conditions listed are true.
|
|
||||||
*
|
|
||||||
* @pre f != NULL
|
|
||||||
* @pre f->param_type == CPT_LIGHT
|
|
||||||
*/
|
|
||||||
u8 getLightNoChecks(LightBank bank, const ContentFeatures *f) const noexcept;
|
|
||||||
|
|
||||||
bool getLightBanks(u8 &lightday, u8 &lightnight,
|
|
||||||
const NodeDefManager *nodemgr) const;
|
|
||||||
|
|
||||||
// 0 <= daylight_factor <= 1000
|
// 0 <= daylight_factor <= 1000
|
||||||
// 0 <= return value <= LIGHT_SUN
|
// 0 <= return value <= LIGHT_SUN
|
||||||
u8 getLightBlend(u32 daylight_factor, const NodeDefManager *nodemgr) const
|
u8 getLightBlend(u32 daylight_factor, ContentLightingFlags f) const
|
||||||
{
|
{
|
||||||
u8 lightday = 0;
|
u8 lightday = getLight(LIGHTBANK_DAY, f);
|
||||||
u8 lightnight = 0;
|
u8 lightnight = getLight(LIGHTBANK_NIGHT, f);
|
||||||
getLightBanks(lightday, lightnight, nodemgr);
|
|
||||||
return blend_light(daylight_factor, lightday, lightnight);
|
return blend_light(daylight_factor, lightday, lightnight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1098,6 +1098,8 @@ void NodeDefManager::clear()
|
|||||||
// Insert directly into containers
|
// Insert directly into containers
|
||||||
content_t c = CONTENT_UNKNOWN;
|
content_t c = CONTENT_UNKNOWN;
|
||||||
m_content_features[c] = f;
|
m_content_features[c] = f;
|
||||||
|
for (u32 ci = 0; ci <= CONTENT_MAX; ci++)
|
||||||
|
m_content_lighting_flag_cache[ci] = f.getLightingFlags();
|
||||||
addNameIdMapping(c, f.name);
|
addNameIdMapping(c, f.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1118,6 +1120,7 @@ void NodeDefManager::clear()
|
|||||||
// Insert directly into containers
|
// Insert directly into containers
|
||||||
content_t c = CONTENT_AIR;
|
content_t c = CONTENT_AIR;
|
||||||
m_content_features[c] = f;
|
m_content_features[c] = f;
|
||||||
|
m_content_lighting_flag_cache[c] = f.getLightingFlags();
|
||||||
addNameIdMapping(c, f.name);
|
addNameIdMapping(c, f.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1137,6 +1140,7 @@ void NodeDefManager::clear()
|
|||||||
// Insert directly into containers
|
// Insert directly into containers
|
||||||
content_t c = CONTENT_IGNORE;
|
content_t c = CONTENT_IGNORE;
|
||||||
m_content_features[c] = f;
|
m_content_features[c] = f;
|
||||||
|
m_content_lighting_flag_cache[c] = f.getLightingFlags();
|
||||||
addNameIdMapping(c, f.name);
|
addNameIdMapping(c, f.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1389,6 +1393,7 @@ content_t NodeDefManager::set(const std::string &name, const ContentFeatures &de
|
|||||||
eraseIdFromGroups(id);
|
eraseIdFromGroups(id);
|
||||||
|
|
||||||
m_content_features[id] = def;
|
m_content_features[id] = def;
|
||||||
|
m_content_lighting_flag_cache[id] = def.getLightingFlags();
|
||||||
verbosestream << "NodeDefManager: registering content id \"" << id
|
verbosestream << "NodeDefManager: registering content id \"" << id
|
||||||
<< "\": name=\"" << def.name << "\""<<std::endl;
|
<< "\": name=\"" << def.name << "\""<<std::endl;
|
||||||
|
|
||||||
@ -1601,6 +1606,7 @@ void NodeDefManager::deSerialize(std::istream &is, u16 protocol_version)
|
|||||||
if (i >= m_content_features.size())
|
if (i >= m_content_features.size())
|
||||||
m_content_features.resize((u32)(i) + 1);
|
m_content_features.resize((u32)(i) + 1);
|
||||||
m_content_features[i] = f;
|
m_content_features[i] = f;
|
||||||
|
m_content_lighting_flag_cache[i] = f.getLightingFlags();
|
||||||
addNameIdMapping(i, f.name);
|
addNameIdMapping(i, f.name);
|
||||||
TRACESTREAM(<< "NodeDef: deserialized " << f.name << std::endl);
|
TRACESTREAM(<< "NodeDef: deserialized " << f.name << std::endl);
|
||||||
|
|
||||||
|
@ -505,10 +505,13 @@ struct ContentFeatures
|
|||||||
liquid_alternative_source_id == f.liquid_alternative_source_id;
|
liquid_alternative_source_id == f.liquid_alternative_source_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lightingEquivalent(const ContentFeatures &other) const {
|
ContentLightingFlags getLightingFlags() const {
|
||||||
return light_propagates == other.light_propagates
|
ContentLightingFlags flags;
|
||||||
&& sunlight_propagates == other.sunlight_propagates
|
flags.has_light = param_type == CPT_LIGHT;
|
||||||
&& light_source == other.light_source;
|
flags.light_propagates = light_propagates;
|
||||||
|
flags.sunlight_propagates = sunlight_propagates;
|
||||||
|
flags.light_source = light_source;
|
||||||
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getGroup(const std::string &group) const
|
int getGroup(const std::string &group) const
|
||||||
@ -580,6 +583,15 @@ public:
|
|||||||
return get(n.getContent());
|
return get(n.getContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline ContentLightingFlags getLightingFlags(content_t c) const {
|
||||||
|
// No bound check is necessary, since the array's length is CONTENT_MAX + 1.
|
||||||
|
return m_content_lighting_flag_cache[c];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ContentLightingFlags getLightingFlags(const MapNode &n) const {
|
||||||
|
return getLightingFlags(n.getContent());
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the node properties for a node name.
|
* Returns the node properties for a node name.
|
||||||
* @param name name of a node
|
* @param name name of a node
|
||||||
@ -826,6 +838,11 @@ private:
|
|||||||
* Even constant NodeDefManager instances can register listeners.
|
* Even constant NodeDefManager instances can register listeners.
|
||||||
*/
|
*/
|
||||||
mutable std::vector<NodeResolver *> m_pending_resolve_callbacks;
|
mutable std::vector<NodeResolver *> m_pending_resolve_callbacks;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Fast cache of content lighting flags.
|
||||||
|
*/
|
||||||
|
ContentLightingFlags m_content_lighting_flag_cache[CONTENT_MAX + 1L];
|
||||||
};
|
};
|
||||||
|
|
||||||
NodeDefManager *createNodeDefManager();
|
NodeDefManager *createNodeDefManager();
|
||||||
|
@ -379,7 +379,7 @@ int ModApiEnvMod::l_get_node_light(lua_State *L)
|
|||||||
MapNode n = env->getMap().getNode(pos, &is_position_ok);
|
MapNode n = env->getMap().getNode(pos, &is_position_ok);
|
||||||
if (is_position_ok) {
|
if (is_position_ok) {
|
||||||
const NodeDefManager *ndef = env->getGameDef()->ndef();
|
const NodeDefManager *ndef = env->getGameDef()->ndef();
|
||||||
lua_pushinteger(L, n.getLightBlend(dnr, ndef));
|
lua_pushinteger(L, n.getLightBlend(dnr, ndef->getLightingFlags(n)));
|
||||||
} else {
|
} else {
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
}
|
}
|
||||||
|
@ -47,9 +47,10 @@ void TestMapNode::testNodeProperties(const NodeDefManager *nodedef)
|
|||||||
{
|
{
|
||||||
MapNode n(CONTENT_AIR);
|
MapNode n(CONTENT_AIR);
|
||||||
|
|
||||||
|
ContentLightingFlags f = nodedef->getLightingFlags(n);
|
||||||
UASSERT(n.getContent() == CONTENT_AIR);
|
UASSERT(n.getContent() == CONTENT_AIR);
|
||||||
UASSERT(n.getLight(LIGHTBANK_DAY, nodedef) == 0);
|
UASSERT(n.getLight(LIGHTBANK_DAY, f) == 0);
|
||||||
UASSERT(n.getLight(LIGHTBANK_NIGHT, nodedef) == 0);
|
UASSERT(n.getLight(LIGHTBANK_NIGHT, f) == 0);
|
||||||
|
|
||||||
// Transparency
|
// Transparency
|
||||||
n.setContent(CONTENT_AIR);
|
n.setContent(CONTENT_AIR);
|
||||||
|
@ -138,27 +138,27 @@ void TestVoxelAlgorithms::testLighting(IGameDef *gamedef)
|
|||||||
const NodeDefManager *ndef = gamedef->ndef();
|
const NodeDefManager *ndef = gamedef->ndef();
|
||||||
{
|
{
|
||||||
MapNode n = map.getNode(v3s16(9, 9, -9));
|
MapNode n = map.getNode(v3s16(9, 9, -9));
|
||||||
UASSERTEQ(int, n.getLight(LIGHTBANK_NIGHT, ndef), 0);
|
UASSERTEQ(int, n.getLight(LIGHTBANK_NIGHT, ndef->getLightingFlags(n)), 0);
|
||||||
UASSERTEQ(int, n.getLight(LIGHTBANK_DAY, ndef), 13);
|
UASSERTEQ(int, n.getLight(LIGHTBANK_DAY, ndef->getLightingFlags(n)), 13);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
MapNode n = map.getNode(v3s16(0, 1, 0));
|
MapNode n = map.getNode(v3s16(0, 1, 0));
|
||||||
UASSERTEQ(int, n.getLight(LIGHTBANK_NIGHT, ndef), 12);
|
UASSERTEQ(int, n.getLight(LIGHTBANK_NIGHT, ndef->getLightingFlags(n)), 12);
|
||||||
UASSERTEQ(int, n.getLight(LIGHTBANK_DAY, ndef), 12);
|
UASSERTEQ(int, n.getLight(LIGHTBANK_DAY, ndef->getLightingFlags(n)), 12);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
MapNode n = map.getNode(v3s16(-9, -1, 0));
|
MapNode n = map.getNode(v3s16(-9, -1, 0));
|
||||||
UASSERTEQ(int, n.getLight(LIGHTBANK_NIGHT, ndef), 3);
|
UASSERTEQ(int, n.getLight(LIGHTBANK_NIGHT, ndef->getLightingFlags(n)), 3);
|
||||||
UASSERTEQ(int, n.getLight(LIGHTBANK_DAY, ndef), 12);
|
UASSERTEQ(int, n.getLight(LIGHTBANK_DAY, ndef->getLightingFlags(n)), 12);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
MapNode n = map.getNode(v3s16(-10, 0, 0));
|
MapNode n = map.getNode(v3s16(-10, 0, 0));
|
||||||
UASSERTEQ(int, n.getLight(LIGHTBANK_NIGHT, ndef), 3);
|
UASSERTEQ(int, n.getLight(LIGHTBANK_NIGHT, ndef->getLightingFlags(n)), 3);
|
||||||
UASSERTEQ(int, n.getLight(LIGHTBANK_DAY, ndef), 14);
|
UASSERTEQ(int, n.getLight(LIGHTBANK_DAY, ndef->getLightingFlags(n)), 14);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
MapNode n = map.getNode(v3s16(-11, 0, 0));
|
MapNode n = map.getNode(v3s16(-11, 0, 0));
|
||||||
UASSERTEQ(int, n.getLight(LIGHTBANK_NIGHT, ndef), 2);
|
UASSERTEQ(int, n.getLight(LIGHTBANK_NIGHT, ndef->getLightingFlags(n)), 2);
|
||||||
UASSERTEQ(int, n.getLight(LIGHTBANK_DAY, ndef), 15);
|
UASSERTEQ(int, n.getLight(LIGHTBANK_DAY, ndef->getLightingFlags(n)), 15);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ void VoxelManipulator::print(std::ostream &o, const NodeDefManager *ndef,
|
|||||||
c = 'X';
|
c = 'X';
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
u8 light = n.getLight(LIGHTBANK_DAY, ndef);
|
u8 light = n.getLight(LIGHTBANK_DAY, ndef->getLightingFlags(n));
|
||||||
if(light < 10)
|
if(light < 10)
|
||||||
c = '0' + light;
|
c = '0' + light;
|
||||||
else
|
else
|
||||||
|
@ -268,7 +268,7 @@ void unspread_light(Map *map, const NodeDefManager *nodemgr, LightBank bank,
|
|||||||
// The current node
|
// The current node
|
||||||
const MapNode &node = current.block->getNodeNoCheck(
|
const MapNode &node = current.block->getNodeNoCheck(
|
||||||
current.rel_position, &is_valid_position);
|
current.rel_position, &is_valid_position);
|
||||||
const ContentFeatures &f = nodemgr->get(node);
|
ContentLightingFlags f = nodemgr->getLightingFlags(node);
|
||||||
// If the node emits light, it behaves like it had a
|
// If the node emits light, it behaves like it had a
|
||||||
// brighter neighbor.
|
// brighter neighbor.
|
||||||
u8 brightest_neighbor_light = f.light_source + 1;
|
u8 brightest_neighbor_light = f.light_source + 1;
|
||||||
@ -296,7 +296,7 @@ void unspread_light(Map *map, const NodeDefManager *nodemgr, LightBank bank,
|
|||||||
// Get the neighbor itself
|
// Get the neighbor itself
|
||||||
MapNode neighbor = neighbor_block->getNodeNoCheck(neighbor_rel_pos,
|
MapNode neighbor = neighbor_block->getNodeNoCheck(neighbor_rel_pos,
|
||||||
&is_valid_position);
|
&is_valid_position);
|
||||||
const ContentFeatures &neighbor_f = nodemgr->get(
|
ContentLightingFlags neighbor_f = nodemgr->getLightingFlags(
|
||||||
neighbor.getContent());
|
neighbor.getContent());
|
||||||
u8 neighbor_light = neighbor.getLightRaw(bank, neighbor_f);
|
u8 neighbor_light = neighbor.getLightRaw(bank, neighbor_f);
|
||||||
// If the neighbor has at least as much light as this node, then
|
// If the neighbor has at least as much light as this node, then
|
||||||
@ -386,7 +386,7 @@ void spread_light(Map *map, const NodeDefManager *nodemgr, LightBank bank,
|
|||||||
// Get the neighbor itself
|
// Get the neighbor itself
|
||||||
MapNode neighbor = neighbor_block->getNodeNoCheck(neighbor_rel_pos,
|
MapNode neighbor = neighbor_block->getNodeNoCheck(neighbor_rel_pos,
|
||||||
&is_valid_position);
|
&is_valid_position);
|
||||||
const ContentFeatures &f = nodemgr->get(neighbor.getContent());
|
ContentLightingFlags f = nodemgr->getLightingFlags(neighbor);
|
||||||
if (f.light_propagates) {
|
if (f.light_propagates) {
|
||||||
// Light up the neighbor, if it has less light than it should.
|
// Light up the neighbor, if it has less light than it should.
|
||||||
u8 neighbor_light = neighbor.getLightRaw(bank, f);
|
u8 neighbor_light = neighbor.getLightRaw(bank, f);
|
||||||
@ -454,10 +454,13 @@ bool is_sunlight_above(Map *map, v3s16 pos, const NodeDefManager *ndef)
|
|||||||
if (source_block->getIsUnderground()) {
|
if (source_block->getIsUnderground()) {
|
||||||
sunlight = false;
|
sunlight = false;
|
||||||
}
|
}
|
||||||
} else if (above.getLight(LIGHTBANK_DAY, ndef) != LIGHT_SUN) {
|
} else {
|
||||||
// If the node above doesn't have sunlight, this
|
ContentLightingFlags above_f = ndef->getLightingFlags(above);
|
||||||
// node is in shadow.
|
if (above.getLight(LIGHTBANK_DAY, above_f) != LIGHT_SUN) {
|
||||||
sunlight = false;
|
// If the node above doesn't have sunlight, this
|
||||||
|
// node is in shadow.
|
||||||
|
sunlight = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -483,7 +486,7 @@ void update_lighting_nodes(Map *map,
|
|||||||
// modified node.
|
// modified node.
|
||||||
u8 min_safe_light = 0;
|
u8 min_safe_light = 0;
|
||||||
for (auto it = oldnodes.cbegin(); it < oldnodes.cend(); ++it) {
|
for (auto it = oldnodes.cbegin(); it < oldnodes.cend(); ++it) {
|
||||||
u8 old_light = it->second.getLight(bank, ndef);
|
u8 old_light = it->second.getLight(bank, ndef->getLightingFlags(it->second));
|
||||||
if (old_light > min_safe_light) {
|
if (old_light > min_safe_light) {
|
||||||
min_safe_light = old_light;
|
min_safe_light = old_light;
|
||||||
}
|
}
|
||||||
@ -511,25 +514,26 @@ void update_lighting_nodes(Map *map,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Light of the old node
|
// Light of the old node
|
||||||
u8 old_light = it->second.getLight(bank, ndef);
|
u8 old_light = it->second.getLight(bank, ndef->getLightingFlags(it->second));
|
||||||
|
|
||||||
// Add the block of the added node to modified_blocks
|
// Add the block of the added node to modified_blocks
|
||||||
modified_blocks[block_pos] = block;
|
modified_blocks[block_pos] = block;
|
||||||
|
|
||||||
// Get new light level of the node
|
// Get new light level of the node
|
||||||
u8 new_light = 0;
|
u8 new_light = 0;
|
||||||
if (ndef->get(n).light_propagates) {
|
ContentLightingFlags f = ndef->getLightingFlags(n);
|
||||||
if (bank == LIGHTBANK_DAY && ndef->get(n).sunlight_propagates
|
if (f.light_propagates) {
|
||||||
|
if (bank == LIGHTBANK_DAY && f.sunlight_propagates
|
||||||
&& is_sunlight_above(map, p, ndef)) {
|
&& is_sunlight_above(map, p, ndef)) {
|
||||||
new_light = LIGHT_SUN;
|
new_light = LIGHT_SUN;
|
||||||
} else {
|
} else {
|
||||||
new_light = ndef->get(n).light_source;
|
new_light = f.light_source;
|
||||||
for (const v3s16 &neighbor_dir : neighbor_dirs) {
|
for (const v3s16 &neighbor_dir : neighbor_dirs) {
|
||||||
v3s16 p2 = p + neighbor_dir;
|
v3s16 p2 = p + neighbor_dir;
|
||||||
bool is_valid;
|
bool is_valid;
|
||||||
MapNode n2 = map->getNode(p2, &is_valid);
|
MapNode n2 = map->getNode(p2, &is_valid);
|
||||||
if (is_valid) {
|
if (is_valid) {
|
||||||
u8 spread = n2.getLight(bank, ndef);
|
u8 spread = n2.getLight(bank, ndef->getLightingFlags(n2));
|
||||||
// If it is sure that the neighbor won't be
|
// If it is sure that the neighbor won't be
|
||||||
// unlighted, its light can spread to this node.
|
// unlighted, its light can spread to this node.
|
||||||
if (spread > new_light && spread >= min_safe_light) {
|
if (spread > new_light && spread >= min_safe_light) {
|
||||||
@ -540,7 +544,7 @@ void update_lighting_nodes(Map *map,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If this is an opaque node, it still can emit light.
|
// If this is an opaque node, it still can emit light.
|
||||||
new_light = ndef->get(n).light_source;
|
new_light = f.light_source;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_light > 0) {
|
if (new_light > 0) {
|
||||||
@ -552,7 +556,7 @@ void update_lighting_nodes(Map *map,
|
|||||||
// light as the previous one, so it must be unlighted.
|
// light as the previous one, so it must be unlighted.
|
||||||
|
|
||||||
// Add to unlight queue
|
// Add to unlight queue
|
||||||
n.setLight(bank, 0, ndef);
|
n.setLight(bank, 0, f);
|
||||||
block->setNodeNoCheck(rel_pos, n);
|
block->setNodeNoCheck(rel_pos, n);
|
||||||
disappearing_lights.push(old_light, rel_pos, block_pos, block,
|
disappearing_lights.push(old_light, rel_pos, block_pos, block,
|
||||||
6);
|
6);
|
||||||
@ -570,11 +574,12 @@ void update_lighting_nodes(Map *map,
|
|||||||
|
|
||||||
// If this node doesn't have sunlight, the nodes below
|
// If this node doesn't have sunlight, the nodes below
|
||||||
// it don't have too.
|
// it don't have too.
|
||||||
if (n2.getLight(LIGHTBANK_DAY, ndef) != LIGHT_SUN) {
|
ContentLightingFlags f2 = ndef->getLightingFlags(n2);
|
||||||
|
if (n2.getLight(LIGHTBANK_DAY, f2) != LIGHT_SUN) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Remove sunlight and add to unlight queue.
|
// Remove sunlight and add to unlight queue.
|
||||||
n2.setLight(LIGHTBANK_DAY, 0, ndef);
|
n2.setLight(LIGHTBANK_DAY, 0, f2);
|
||||||
map->setNode(n2pos, n2);
|
map->setNode(n2pos, n2);
|
||||||
relative_v3 rel_pos2;
|
relative_v3 rel_pos2;
|
||||||
mapblock_v3 block_pos2;
|
mapblock_v3 block_pos2;
|
||||||
@ -602,11 +607,12 @@ void update_lighting_nodes(Map *map,
|
|||||||
|
|
||||||
// This should not happen, but if the node has sunlight
|
// This should not happen, but if the node has sunlight
|
||||||
// then the iteration should stop.
|
// then the iteration should stop.
|
||||||
if (n2.getLight(LIGHTBANK_DAY, ndef) == LIGHT_SUN) {
|
ContentLightingFlags f2 = ndef->getLightingFlags(n2);
|
||||||
|
if (n2.getLight(LIGHTBANK_DAY, f2) == LIGHT_SUN) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// If the node terminates sunlight, stop.
|
// If the node terminates sunlight, stop.
|
||||||
if (!ndef->get(n2).sunlight_propagates) {
|
if (!f2.sunlight_propagates) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
relative_v3 rel_pos2;
|
relative_v3 rel_pos2;
|
||||||
@ -632,7 +638,7 @@ void update_lighting_nodes(Map *map,
|
|||||||
it < lights.end(); ++it) {
|
it < lights.end(); ++it) {
|
||||||
MapNode n = it->block->getNodeNoCheck(it->rel_position,
|
MapNode n = it->block->getNodeNoCheck(it->rel_position,
|
||||||
&is_valid_position);
|
&is_valid_position);
|
||||||
n.setLight(bank, i, ndef);
|
n.setLight(bank, i, ndef->getLightingFlags(n));
|
||||||
it->block->setNodeNoCheck(it->rel_position, n);
|
it->block->setNodeNoCheck(it->rel_position, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -667,17 +673,17 @@ bool is_light_locally_correct(Map *map, const NodeDefManager *ndef,
|
|||||||
{
|
{
|
||||||
bool is_valid_position;
|
bool is_valid_position;
|
||||||
MapNode n = map->getNode(pos, &is_valid_position);
|
MapNode n = map->getNode(pos, &is_valid_position);
|
||||||
const ContentFeatures &f = ndef->get(n);
|
ContentLightingFlags f = ndef->getLightingFlags(n);
|
||||||
if (f.param_type != CPT_LIGHT) {
|
if (!f.has_light) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
u8 light = n.getLightNoChecks(bank, &f);
|
u8 light = n.getLight(bank, f);
|
||||||
assert(f.light_source <= LIGHT_MAX);
|
assert(f.light_source <= LIGHT_MAX);
|
||||||
u8 brightest_neighbor = f.light_source + 1;
|
u8 brightest_neighbor = f.light_source + 1;
|
||||||
for (const v3s16 &neighbor_dir : neighbor_dirs) {
|
for (const v3s16 &neighbor_dir : neighbor_dirs) {
|
||||||
MapNode n2 = map->getNode(pos + neighbor_dir,
|
MapNode n2 = map->getNode(pos + neighbor_dir,
|
||||||
&is_valid_position);
|
&is_valid_position);
|
||||||
u8 light2 = n2.getLight(bank, ndef);
|
u8 light2 = n2.getLight(bank, ndef->getLightingFlags(n2));
|
||||||
if (brightest_neighbor < light2) {
|
if (brightest_neighbor < light2) {
|
||||||
brightest_neighbor = light2;
|
brightest_neighbor = light2;
|
||||||
}
|
}
|
||||||
@ -725,14 +731,15 @@ void update_block_border_lighting(Map *map, MapBlock *block,
|
|||||||
for (s32 y = a.MinEdge.Y; y <= a.MaxEdge.Y; y++) {
|
for (s32 y = a.MinEdge.Y; y <= a.MaxEdge.Y; y++) {
|
||||||
MapNode n = b->getNodeNoCheck(x, y, z,
|
MapNode n = b->getNodeNoCheck(x, y, z,
|
||||||
&is_valid_position);
|
&is_valid_position);
|
||||||
u8 light = n.getLight(bank, ndef);
|
ContentLightingFlags f = ndef->getLightingFlags(n);
|
||||||
|
u8 light = n.getLight(bank, f);
|
||||||
// Sunlight is fixed
|
// Sunlight is fixed
|
||||||
if (light < LIGHT_SUN) {
|
if (light < LIGHT_SUN) {
|
||||||
// Unlight if not correct
|
// Unlight if not correct
|
||||||
if (!is_light_locally_correct(map, ndef, bank,
|
if (!is_light_locally_correct(map, ndef, bank,
|
||||||
v3s16(x, y, z) + b->getPosRelative())) {
|
v3s16(x, y, z) + b->getPosRelative())) {
|
||||||
// Initialize for unlighting
|
// Initialize for unlighting
|
||||||
n.setLight(bank, 0, ndef);
|
n.setLight(bank, 0, ndef->getLightingFlags(n));
|
||||||
b->setNodeNoCheck(x, y, z, n);
|
b->setNodeNoCheck(x, y, z, n);
|
||||||
modified_blocks[b->getPos()]=b;
|
modified_blocks[b->getPos()]=b;
|
||||||
disappearing_lights.push(light,
|
disappearing_lights.push(light,
|
||||||
@ -753,7 +760,7 @@ void update_block_border_lighting(Map *map, MapBlock *block,
|
|||||||
it < lights.end(); ++it) {
|
it < lights.end(); ++it) {
|
||||||
MapNode n = it->block->getNodeNoCheck(it->rel_position,
|
MapNode n = it->block->getNodeNoCheck(it->rel_position,
|
||||||
&is_valid_position);
|
&is_valid_position);
|
||||||
n.setLight(bank, i, ndef);
|
n.setLight(bank, i, ndef->getLightingFlags(n));
|
||||||
it->block->setNodeNoCheck(it->rel_position, n);
|
it->block->setNodeNoCheck(it->rel_position, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -804,7 +811,7 @@ void fill_with_sunlight(MMVManip *vm, const NodeDefManager *ndef, v2s16 offset,
|
|||||||
// Ignore IGNORE nodes, these are not generated yet.
|
// Ignore IGNORE nodes, these are not generated yet.
|
||||||
if(n->getContent() == CONTENT_IGNORE)
|
if(n->getContent() == CONTENT_IGNORE)
|
||||||
continue;
|
continue;
|
||||||
const ContentFeatures &f = ndef->get(n->getContent());
|
ContentLightingFlags f = ndef->getLightingFlags(*n);
|
||||||
if (lig && !f.sunlight_propagates)
|
if (lig && !f.sunlight_propagates)
|
||||||
// Sunlight is stopped.
|
// Sunlight is stopped.
|
||||||
lig = false;
|
lig = false;
|
||||||
@ -857,7 +864,8 @@ void is_sunlight_above_block(Map *map, mapblock_v3 pos,
|
|||||||
// Get the bottom block.
|
// Get the bottom block.
|
||||||
MapNode above = source_block->getNodeNoCheck(x, 0, z,
|
MapNode above = source_block->getNodeNoCheck(x, 0, z,
|
||||||
&is_valid_position);
|
&is_valid_position);
|
||||||
light[z][x] = above.getLight(LIGHTBANK_DAY, ndef) == LIGHT_SUN;
|
ContentLightingFlags above_f = ndef->getLightingFlags(above);
|
||||||
|
light[z][x] = above.getLight(LIGHTBANK_DAY, above_f) == LIGHT_SUN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -897,7 +905,7 @@ bool propagate_block_sunlight(Map *map, const NodeDefManager *ndef,
|
|||||||
// For each node downwards:
|
// For each node downwards:
|
||||||
for (; current_pos.Y >= 0; current_pos.Y--) {
|
for (; current_pos.Y >= 0; current_pos.Y--) {
|
||||||
MapNode n = block->getNodeNoCheck(current_pos, &is_valid);
|
MapNode n = block->getNodeNoCheck(current_pos, &is_valid);
|
||||||
const ContentFeatures &f = ndef->get(n);
|
ContentLightingFlags f = ndef->getLightingFlags(n);
|
||||||
if (n.getLightRaw(LIGHTBANK_DAY, f) < LIGHT_SUN
|
if (n.getLightRaw(LIGHTBANK_DAY, f) < LIGHT_SUN
|
||||||
&& f.sunlight_propagates) {
|
&& f.sunlight_propagates) {
|
||||||
// This node gets sunlight.
|
// This node gets sunlight.
|
||||||
@ -916,7 +924,7 @@ bool propagate_block_sunlight(Map *map, const NodeDefManager *ndef,
|
|||||||
// For each node downwards:
|
// For each node downwards:
|
||||||
for (; current_pos.Y >= 0; current_pos.Y--) {
|
for (; current_pos.Y >= 0; current_pos.Y--) {
|
||||||
MapNode n = block->getNodeNoCheck(current_pos, &is_valid);
|
MapNode n = block->getNodeNoCheck(current_pos, &is_valid);
|
||||||
const ContentFeatures &f = ndef->get(n);
|
ContentLightingFlags f = ndef->getLightingFlags(n);
|
||||||
if (n.getLightRaw(LIGHTBANK_DAY, f) == LIGHT_SUN) {
|
if (n.getLightRaw(LIGHTBANK_DAY, f) == LIGHT_SUN) {
|
||||||
// The sunlight is no longer valid.
|
// The sunlight is no longer valid.
|
||||||
n.setLight(LIGHTBANK_DAY, 0, f);
|
n.setLight(LIGHTBANK_DAY, 0, f);
|
||||||
@ -1007,13 +1015,13 @@ void finish_bulk_light_update(Map *map, mapblock_v3 minblock,
|
|||||||
for (relpos.Z = 0; relpos.Z < MAP_BLOCKSIZE; relpos.Z++)
|
for (relpos.Z = 0; relpos.Z < MAP_BLOCKSIZE; relpos.Z++)
|
||||||
for (relpos.Y = 0; relpos.Y < MAP_BLOCKSIZE; relpos.Y++) {
|
for (relpos.Y = 0; relpos.Y < MAP_BLOCKSIZE; relpos.Y++) {
|
||||||
MapNode node = block->getNodeNoCheck(relpos.X, relpos.Y, relpos.Z, &is_valid);
|
MapNode node = block->getNodeNoCheck(relpos.X, relpos.Y, relpos.Z, &is_valid);
|
||||||
const ContentFeatures &f = ndef->get(node);
|
ContentLightingFlags f = ndef->getLightingFlags(node);
|
||||||
|
|
||||||
// For each light bank
|
// For each light bank
|
||||||
for (size_t b = 0; b < 2; b++) {
|
for (size_t b = 0; b < 2; b++) {
|
||||||
LightBank bank = banks[b];
|
LightBank bank = banks[b];
|
||||||
u8 light = f.param_type == CPT_LIGHT ?
|
u8 light = f.has_light ?
|
||||||
node.getLightNoChecks(bank, &f):
|
node.getLight(bank, f):
|
||||||
f.light_source;
|
f.light_source;
|
||||||
if (light > 1)
|
if (light > 1)
|
||||||
relight[b].push(light, relpos, blockpos, block, 6);
|
relight[b].push(light, relpos, blockpos, block, 6);
|
||||||
@ -1035,7 +1043,7 @@ void finish_bulk_light_update(Map *map, mapblock_v3 minblock,
|
|||||||
it < lights.end(); ++it) {
|
it < lights.end(); ++it) {
|
||||||
MapNode n = it->block->getNodeNoCheck(it->rel_position,
|
MapNode n = it->block->getNodeNoCheck(it->rel_position,
|
||||||
&is_valid);
|
&is_valid);
|
||||||
n.setLight(bank, i, ndef);
|
n.setLight(bank, i, ndef->getLightingFlags(n));
|
||||||
it->block->setNodeNoCheck(it->rel_position, n);
|
it->block->setNodeNoCheck(it->rel_position, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1110,19 +1118,18 @@ void blit_back_with_light(Map *map, MMVManip *vm,
|
|||||||
|
|
||||||
// Get old and new node
|
// Get old and new node
|
||||||
MapNode oldnode = block->getNodeNoCheck(relpos, &is_valid);
|
MapNode oldnode = block->getNodeNoCheck(relpos, &is_valid);
|
||||||
const ContentFeatures &oldf = ndef->get(oldnode);
|
ContentLightingFlags oldf = ndef->getLightingFlags(oldnode);
|
||||||
MapNode newnode = vm->getNodeNoExNoEmerge(relpos + offset);
|
MapNode newnode = vm->getNodeNoExNoEmerge(relpos + offset);
|
||||||
const ContentFeatures &newf = oldnode == newnode ? oldf :
|
ContentLightingFlags newf = ndef->getLightingFlags(newnode);
|
||||||
ndef->get(newnode);
|
|
||||||
|
|
||||||
// For each light bank
|
// For each light bank
|
||||||
for (size_t b = 0; b < 2; b++) {
|
for (size_t b = 0; b < 2; b++) {
|
||||||
LightBank bank = banks[b];
|
LightBank bank = banks[b];
|
||||||
u8 oldlight = oldf.param_type == CPT_LIGHT ?
|
u8 oldlight = oldf.has_light ?
|
||||||
oldnode.getLightNoChecks(bank, &oldf):
|
oldnode.getLight(bank, oldf):
|
||||||
LIGHT_SUN; // no light information, force unlighting
|
LIGHT_SUN; // no light information, force unlighting
|
||||||
u8 newlight = newf.param_type == CPT_LIGHT ?
|
u8 newlight = newf.has_light ?
|
||||||
newnode.getLightNoChecks(bank, &newf):
|
newnode.getLight(bank, newf):
|
||||||
newf.light_source;
|
newf.light_source;
|
||||||
// If the new node is dimmer, unlight.
|
// If the new node is dimmer, unlight.
|
||||||
if (oldlight > newlight) {
|
if (oldlight > newlight) {
|
||||||
@ -1172,7 +1179,7 @@ void fill_with_sunlight(MapBlock *block, const NodeDefManager *ndef,
|
|||||||
// Ignore IGNORE nodes, these are not generated yet.
|
// Ignore IGNORE nodes, these are not generated yet.
|
||||||
if (n.getContent() == CONTENT_IGNORE)
|
if (n.getContent() == CONTENT_IGNORE)
|
||||||
continue;
|
continue;
|
||||||
const ContentFeatures &f = ndef->get(n.getContent());
|
ContentLightingFlags f = ndef->getLightingFlags(n);
|
||||||
if (lig && !f.sunlight_propagates) {
|
if (lig && !f.sunlight_propagates) {
|
||||||
// Sunlight is stopped.
|
// Sunlight is stopped.
|
||||||
lig = false;
|
lig = false;
|
||||||
@ -1239,12 +1246,12 @@ void repair_block_light(Map *map, MapBlock *block,
|
|||||||
|
|
||||||
// Get node
|
// Get node
|
||||||
MapNode node = block->getNodeNoCheck(relpos, &is_valid);
|
MapNode node = block->getNodeNoCheck(relpos, &is_valid);
|
||||||
const ContentFeatures &f = ndef->get(node);
|
ContentLightingFlags f = ndef->getLightingFlags(node);
|
||||||
// For each light bank
|
// For each light bank
|
||||||
for (size_t b = 0; b < 2; b++) {
|
for (size_t b = 0; b < 2; b++) {
|
||||||
LightBank bank = banks[b];
|
LightBank bank = banks[b];
|
||||||
u8 light = f.param_type == CPT_LIGHT ?
|
u8 light = f.has_light ?
|
||||||
node.getLightNoChecks(bank, &f):
|
node.getLight(bank, f):
|
||||||
f.light_source;
|
f.light_source;
|
||||||
// If the new node is dimmer than sunlight, unlight.
|
// If the new node is dimmer than sunlight, unlight.
|
||||||
// (if it has maximal light, it is pointless to remove
|
// (if it has maximal light, it is pointless to remove
|
||||||
|
Loading…
Reference in New Issue
Block a user