Skip to content

Commit

Permalink
Optimize add_area_node_boxes in collision code (#15719)
Browse files Browse the repository at this point in the history
  • Loading branch information
sfan5 authored Feb 15, 2025
1 parent d027fc9 commit 75dcd94
Showing 1 changed file with 40 additions and 7 deletions.
47 changes: 40 additions & 7 deletions src/collision.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,16 +224,50 @@ static bool add_area_node_boxes(const v3s16 min, const v3s16 max, IGameDef *game
thread_local std::vector<aabb3f> nodeboxes;
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;
for (p.Z = min.Z; p.Z <= max.Z; p.Z++)
for (p.Y = min.Y; p.Y <= max.Y; p.Y++)
for (p.X = min.X; p.X <= max.X; p.X++) {
bool is_position_valid;
MapNode n = map->getNode(p, &is_position_valid);
v3s16 bp, relp;
getNodeBlockPosWithOffset(p, bp, relp);
if (bp != last_bp) {
last_block = map->getBlockNoCreateNoEx(bp);
last_bp = bp;
}
MapBlock *const block = last_block;

if (!block) {
// 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 (is_position_valid && n.getContent() != CONTENT_IGNORE) {
// Object collides into walkable nodes
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;
const ContentFeatures &f = nodedef->get(n);

Expand All @@ -248,20 +282,19 @@ static bool add_area_node_boxes(const v3s16 min, const v3s16 max, IGameDef *game
nodeboxes.clear();
n.getCollisionBoxes(nodedef, &nodeboxes, neighbors);

// Calculate float position only once
v3f posf = intToFloat(p, BS);
for (auto box : nodeboxes) {
box.MinEdge += posf;
box.MaxEdge += posf;
cinfo.emplace_back(false, n_bouncy_value, p, box);
}
} else {
// Collide with unloaded nodes (position invalid) and loaded
// CONTENT_IGNORE nodes (position valid)
// Collide with loaded CONTENT_IGNORE nodes
aabb3f box = getNodeBox(p, BS);
cinfo.emplace_back(true, 0, p, box);
}
}

return any_position_valid;
}

Expand Down

0 comments on commit 75dcd94

Please sign in to comment.