Cleaning up a bit, before full integration

This commit is contained in:
ExeVirus 2024-05-11 16:07:09 -04:00
parent 5f262780f2
commit 2d4f9dd789
6 changed files with 53 additions and 140 deletions

View File

@ -74,38 +74,22 @@ void benchGetObjectsInArea(Catch::Benchmark::Chronometer &meter)
{
server::ActiveObjectMgr mgr;
size_t x;
std::vector<ServerActiveObject*> result, result2;
std::vector<ServerActiveObject*> result;
auto cb = [&x] (ServerActiveObject *obj) -> bool {
x += obj->m_static_exists ? 0 : 1;
return false;
};
fill(mgr, N);
mgr.m_spatial_map.cacheUpdate([&mgr](u16 id)
{
auto obj = mgr.getActiveObject(id);
if(obj != nullptr) {
return obj->getBasePosition();
} else {
mgr.m_spatial_map.remove(id);
return v3f();
}
});
v3f pos, off;
meter.measure([&] {
x = 0;
pos = randpos();
off = v3f(50, 50, 50);
v3f pos = randpos();
v3f off(50, 50, 50);
off[myrand_range(0, 2)] = 10;
mgr.getObjectsInArea({pos, pos + off}, result, cb);
return x;
});
REQUIRE(result.empty());
mgr.getObjectsInAreaDumb({v3f(0,-20,-2000), v3f(2000,60,2000)}, result2, [](ServerActiveObject *obj) { return true; });
//mgr.getObjectsInArea({v3f(0,-20,-2000), v3f(2000,60,2000)}, result, [](ServerActiveObject *obj) { return true; });
std::cout << "numberSmart:" << result.size() << std::endl;
std::cout << "numberDumb:" << result2.size() << std::endl;
mgr.clear(); // implementation expects this
}

View File

@ -17,7 +17,6 @@ You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <algorithm>
#include "mg_biome.h"
#include "mg_decoration.h"

View File

@ -46,11 +46,6 @@ void ActiveObjectMgr::clearIf(const std::function<bool(ServerActiveObject *, u16
}
}
void ActiveObjectMgr::updateCachedObjectID(u16 id, v3f &last_position, v3f &new_position)
{
m_spatial_map.updatePosition(id, last_position, new_position);
}
void ActiveObjectMgr::step(
float dtime, const std::function<void(ServerActiveObject *)> &f)
{
@ -62,16 +57,6 @@ void ActiveObjectMgr::step(
count++;
f(ao_it.second.get());
}
m_spatial_map.cacheUpdate([this](u16 id)
{
auto obj = getActiveObject(id);
if(obj != nullptr) {
return obj->getBasePosition();
} else {
this->m_spatial_map.remove(id);
return v3f();
}
});
g_profiler->avg("ActiveObjectMgr: SAO count [#]", count);
}
@ -108,7 +93,7 @@ bool ActiveObjectMgr::registerObject(std::unique_ptr<ServerActiveObject> obj)
auto obj_id = obj->getId();
m_active_objects.put(obj_id, std::move(obj));
m_spatial_map.insert(obj_id);
m_spatial_map.insert(obj_id, obj->getBasePosition());
auto new_size = m_active_objects.size();
verbosestream << "Server::ActiveObjectMgr::addActiveObjectRaw(): "
@ -141,34 +126,22 @@ void ActiveObjectMgr::getObjectsInsideRadius(const v3f &pos, float radius,
std::function<bool(ServerActiveObject *obj)> include_obj_cb)
{
float r2 = radius * radius;
for (auto &activeObject : m_active_objects.iter()) {
ServerActiveObject *obj = activeObject.second.get();
if (!obj)
continue;
aabb3f bounds(pos.X-radius, pos.Y-radius, pos.Z-radius,
pos.X+radius, pos.Y+radius, pos.Z+radius);
m_spatial_map.getRelevantObjectIds(bounds, [&](u16 id) {
auto obj = m_active_objects.get(id).get();
if (!obj) { // should never be hit
m_spatial_map.remove(id);
return;
}
const v3f &objectpos = obj->getBasePosition();
if (objectpos.getDistanceFromSQ(pos) > r2)
continue;
if (!include_obj_cb || include_obj_cb(obj))
result.push_back(obj);
}
}
void ActiveObjectMgr::getObjectsInAreaDumb(const aabb3f &box,
std::vector<ServerActiveObject *> &result,
std::function<bool(ServerActiveObject *obj)> include_obj_cb)
{
for (auto &activeObject : m_active_objects.iter()) {
ServerActiveObject *obj = activeObject.second.get();
if (!obj)
return;
const v3f &objectpos = obj->getBasePosition();
if (!box.isPointInside(objectpos))
return;
if (!include_obj_cb || include_obj_cb(obj))
result.push_back(obj);
};
});
}
void ActiveObjectMgr::getObjectsInArea(const aabb3f &box,
@ -177,8 +150,11 @@ void ActiveObjectMgr::getObjectsInArea(const aabb3f &box,
{
m_spatial_map.getRelevantObjectIds(box,[&](u16 id) {
auto obj = m_active_objects.get(id).get();
if (!obj)
if (!obj) { // should never be hit
m_spatial_map.remove(id);
return;
}
const v3f &objectpos = obj->getBasePosition();
if (!box.isPointInside(objectpos))
return;
@ -199,32 +175,35 @@ void ActiveObjectMgr::getAddedActiveObjectsAroundPos(v3f player_pos, f32 radius,
- discard objects that are found in current_objects.
- add remaining objects to added_objects
*/
for (auto &ao_it : m_active_objects.iter()) {
u16 id = ao_it.first;
// Get object
ServerActiveObject *object = ao_it.second.get();
if (!object)
continue;
if (object->isGone())
continue;
f32 distance_f = object->getBasePosition().getDistanceFrom(player_pos);
if (object->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
float r2 = radius * radius;
aabb3f bounds(player_pos.X-radius, player_pos.Y-radius, player_pos.Z-radius,
player_pos.X+radius, player_pos.Y+radius, player_pos.Z+radius);
m_spatial_map.getRelevantObjectIds(bounds, [&](u16 id) {
auto obj = m_active_objects.get(id).get();
if (!obj) { // should never be hit
m_spatial_map.remove(id);
return;
}
if (obj->isGone()) {
return;
}
f32 distance_f = obj->getBasePosition().getDistanceFrom(player_pos);
if (obj->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
// Discard if too far
if (distance_f > player_radius && player_radius != 0)
continue;
return;
} else if (distance_f > radius)
continue;
return;
// Discard if already on current_objects
auto n = current_objects.find(id);
if (n != current_objects.end())
continue;
return;
// Add to added_objects
added_objects.push_back(id);
}
});
}
} // namespace server

View File

@ -38,14 +38,10 @@ public:
const std::function<void(ServerActiveObject *)> &f) override;
bool registerObject(std::unique_ptr<ServerActiveObject> obj) override;
void removeObject(u16 id) override;
void updateCachedObjectID(u16 id, v3f &last_position, v3f &new_position);
void getObjectsInsideRadius(const v3f &pos, float radius,
std::vector<ServerActiveObject *> &result,
std::function<bool(ServerActiveObject *obj)> include_obj_cb);
void getObjectsInAreaDumb(const aabb3f &box,
std::vector<ServerActiveObject *> &result,
std::function<bool(ServerActiveObject *obj)> include_obj_cb);
void getObjectsInArea(const aabb3f &box,
std::vector<ServerActiveObject *> &result,
std::function<bool(ServerActiveObject *obj)> include_obj_cb);
@ -53,7 +49,7 @@ public:
void getAddedActiveObjectsAroundPos(v3f player_pos, f32 radius,
f32 player_radius, const std::set<u16> &current_objects,
std::vector<u16> &added_objects);
protected:
SpatialMap m_spatial_map;
};
} // namespace server

View File

@ -24,9 +24,9 @@ namespace server
{
// all inserted entires go into the uncached vector
void SpatialMap::insert(u16 id)
void SpatialMap::insert(u16 id, v3f pos)
{
m_uncached.push_back(id);
m_cached.insert({SpatialKey(pos), id});
}
// Invalidates upon position update
@ -40,41 +40,19 @@ void SpatialMap::updatePosition(u16 id, v3f &oldPos, v3f& newPos)
}
}
// remove from cache, if present
bool found = false;
// remove from old cache position
range = m_cached.equal_range(SpatialKey(oldPos));
for (auto it = range.first; it != range.second; ++it) {
if (it->second == id) {
m_cached.erase(it);
found = true;
break; // Erase and leave early
}
}
if(!found) {
m_uncached.erase(std::find(m_uncached.begin(), m_uncached.end(), id));
}
// place back in uncached
// place in new bucket
m_cached.insert(std::pair<SpatialKey,u16>(newPos, id));
}
void SpatialMap::remove(u16 id)
{
auto found = std::find(m_uncached.begin(), m_uncached.end(), id);
if (found != m_uncached.end()) {
m_uncached.erase(found);
return;
}
for (auto it = m_cached.begin(); it != m_cached.end();++it) {
if(it->second == id) {
m_cached.erase(it);
break;
}
}
// Error, this shouldn't ever be hit.
}
void SpatialMap::remove(u16 id, v3f pos)
{
SpatialKey key(pos);
@ -86,25 +64,17 @@ void SpatialMap::remove(u16 id, v3f pos)
return; // Erase and leave early
}
}
};
auto it = std::find(m_uncached.begin(), m_uncached.end(), id);
if (it != m_uncached.end()) {
m_uncached.erase(it);
return;
} else {
// Error, this shouldn't ever be hit.
}
remove(id); // should never be hit
}
// Only when at least 64 uncached objects or 10% uncached overall
void SpatialMap::cacheUpdate(const std::function<v3f(u16)> &getPos)
void SpatialMap::remove(u16 id)
{
if(m_uncached.size() >= 64 || (m_uncached.size() >= 64 && m_uncached.size() * 10 > m_cached.size())) {
for(u16& entry : m_uncached) {
m_cached.insert(std::pair<SpatialKey,u16>(getPos(entry), entry));
for (auto it = m_cached.begin(); it != m_cached.end(); ++it) {
if (it->second == id) {
m_cached.erase(it);
return; // Erase and leave early
}
m_uncached.clear();
}
}
@ -137,11 +107,6 @@ void SpatialMap::getRelevantObjectIds(const aabb3f &box, const std::function<voi
}
}
}
// add the the rest, uncached objectIDs
for (auto id : m_uncached) {
callback(id);
}
}
} // namespace server

View File

@ -28,22 +28,13 @@ namespace server
class SpatialMap
{
public:
// all inserted entires go into the uncached vector
void insert(u16 id);
void updatePosition(u16 id, v3f &oldPos, v3f& newPos);
// On active_object removal, remove.
void insert(u16 id, v3f pos);
void remove(u16 id, v3f pos);
void remove(u16 id);
// Only when at least 64 uncached objects or 10% uncached overall
void cacheUpdate(const std::function<v3f(u16)> &getPos);
// Use the same basic algorithm for both area and radius lookups
void remove(u16 id)
void updatePosition(u16 id, v3f &oldPos, v3f& newPos);
void getRelevantObjectIds(const aabb3f &box, const std::function<void(u16 id)> &callback);
//protected:
protected:
typedef struct SpatialKey{
u16 padding{0};
s16 x;
@ -75,6 +66,5 @@ public:
};
std::unordered_multimap<SpatialKey, u16, SpatialKeyHash> m_cached;
std::vector<u16> m_uncached;
};
} // namespace server