mirror of
https://github.com/minetest/minetest.git
synced 2025-03-06 20:48:40 +01:00
Optimize add_area_node_boxes in collision code (#15719)
This commit is contained in:
parent
d027fc9a88
commit
75dcd94b90
1 changed files with 40 additions and 7 deletions
|
@ -224,16 +224,50 @@ static bool add_area_node_boxes(const v3s16 min, const v3s16 max, IGameDef *game
|
||||||
thread_local std::vector<aabb3f> nodeboxes;
|
thread_local std::vector<aabb3f> nodeboxes;
|
||||||
Map *map = &env->getMap();
|
Map *map = &env->getMap();
|
||||||
|
|
||||||
|
const bool air_walkable = nodedef->get(CONTENT_AIR).walkable;
|
||||||
|
|
||||||
|
v3s16 last_bp(S16_MAX);
|
||||||
|
MapBlock *last_block = nullptr;
|
||||||
|
|
||||||
|
// Note: as the area used here is usually small, iterating entire blocks
|
||||||
|
// would actually be slower by factor of 10.
|
||||||
|
|
||||||
v3s16 p;
|
v3s16 p;
|
||||||
for (p.Z = min.Z; p.Z <= max.Z; p.Z++)
|
for (p.Z = min.Z; p.Z <= max.Z; p.Z++)
|
||||||
for (p.Y = min.Y; p.Y <= max.Y; p.Y++)
|
for (p.Y = min.Y; p.Y <= max.Y; p.Y++)
|
||||||
for (p.X = min.X; p.X <= max.X; p.X++) {
|
for (p.X = min.X; p.X <= max.X; p.X++) {
|
||||||
bool is_position_valid;
|
v3s16 bp, relp;
|
||||||
MapNode n = map->getNode(p, &is_position_valid);
|
getNodeBlockPosWithOffset(p, bp, relp);
|
||||||
|
if (bp != last_bp) {
|
||||||
|
last_block = map->getBlockNoCreateNoEx(bp);
|
||||||
|
last_bp = bp;
|
||||||
|
}
|
||||||
|
MapBlock *const block = last_block;
|
||||||
|
|
||||||
if (is_position_valid && n.getContent() != CONTENT_IGNORE) {
|
if (!block) {
|
||||||
// Object collides into walkable nodes
|
// Since we iterate with node precision we can only safely skip
|
||||||
|
// ahead in the "innermost" axis of the MapBlock (X).
|
||||||
|
// This still worth it as it reduces the number of nodes to look at
|
||||||
|
// and entries in `cinfo`.
|
||||||
|
v3s16 rowend(bp.X * MAP_BLOCKSIZE + MAP_BLOCKSIZE - 1, p.Y, p.Z);
|
||||||
|
aabb3f box = getNodeBox(p, BS);
|
||||||
|
box.addInternalBox(getNodeBox(rowend, BS));
|
||||||
|
// Collide with unloaded block
|
||||||
|
cinfo.emplace_back(true, 0, p, box);
|
||||||
|
p.X = rowend.X;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!air_walkable && block->isAir()) {
|
||||||
|
// Skip ahead if air, like above
|
||||||
|
any_position_valid = true;
|
||||||
|
p.X = bp.X * MAP_BLOCKSIZE + MAP_BLOCKSIZE - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MapNode n = block->getNodeNoCheck(relp);
|
||||||
|
|
||||||
|
if (n.getContent() != CONTENT_IGNORE) {
|
||||||
any_position_valid = true;
|
any_position_valid = true;
|
||||||
const ContentFeatures &f = nodedef->get(n);
|
const ContentFeatures &f = nodedef->get(n);
|
||||||
|
|
||||||
|
@ -248,7 +282,6 @@ static bool add_area_node_boxes(const v3s16 min, const v3s16 max, IGameDef *game
|
||||||
nodeboxes.clear();
|
nodeboxes.clear();
|
||||||
n.getCollisionBoxes(nodedef, &nodeboxes, neighbors);
|
n.getCollisionBoxes(nodedef, &nodeboxes, neighbors);
|
||||||
|
|
||||||
// Calculate float position only once
|
|
||||||
v3f posf = intToFloat(p, BS);
|
v3f posf = intToFloat(p, BS);
|
||||||
for (auto box : nodeboxes) {
|
for (auto box : nodeboxes) {
|
||||||
box.MinEdge += posf;
|
box.MinEdge += posf;
|
||||||
|
@ -256,12 +289,12 @@ static bool add_area_node_boxes(const v3s16 min, const v3s16 max, IGameDef *game
|
||||||
cinfo.emplace_back(false, n_bouncy_value, p, box);
|
cinfo.emplace_back(false, n_bouncy_value, p, box);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Collide with unloaded nodes (position invalid) and loaded
|
// Collide with loaded CONTENT_IGNORE nodes
|
||||||
// CONTENT_IGNORE nodes (position valid)
|
|
||||||
aabb3f box = getNodeBox(p, BS);
|
aabb3f box = getNodeBox(p, BS);
|
||||||
cinfo.emplace_back(true, 0, p, box);
|
cinfo.emplace_back(true, 0, p, box);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return any_position_valid;
|
return any_position_valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue