Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replay renderer partial deletion #2136

Merged
merged 9 commits into from
Jun 27, 2023
Merged
104 changes: 74 additions & 30 deletions src/esp/gfx/replay/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,10 @@

#include "Player.h"

#include <Corrade/Containers/StringStl.h>
#include <Corrade/Utility/Path.h>

#include "esp/assets/ResourceManager.h"
#include "esp/core/Esp.h"
#include "esp/gfx/replay/Keyframe.h"
#include "esp/io/Json.h"
#include "esp/io/JsonAllTypes.h"

#include <rapidjson/document.h>

namespace esp {
namespace gfx {
Expand Down Expand Up @@ -69,6 +64,17 @@ void AbstractSceneGraphPlayerImplementation::setNodeTransform(
.setRotation(rotation);
}

void AbstractSceneGraphPlayerImplementation::setNodeTransform(
const NodeHandle node,
const Mn::Matrix4& transform) {
(*reinterpret_cast<scene::SceneNode*>(node)).setTransformation(transform);
}

Mn::Matrix4 AbstractSceneGraphPlayerImplementation::hackGetNodeTransform(
const NodeHandle node) const {
return (*reinterpret_cast<scene::SceneNode*>(node)).transformation();
}

void AbstractSceneGraphPlayerImplementation::setNodeSemanticId(
const NodeHandle node,
const unsigned id) {
Expand Down Expand Up @@ -170,6 +176,7 @@ void Player::clearFrame() {
implementation_->deleteAssetInstances(createdInstances_);
createdInstances_.clear();
assetInfos_.clear();
creationInfos_.clear();
frameIndex_ = -1;
}

Expand All @@ -183,15 +190,6 @@ void Player::applyKeyframe(const Keyframe& keyframe) {
assetInfos_[assetInfo.filepath] = assetInfo;
}

// If all current instances are being deleted, clear the frame. This enables
// the implementation to clear its memory and optimize its internals.
bool frameCleared = keyframe.deletions.size() > 0 &&
createdInstances_.size() == keyframe.deletions.size();
if (frameCleared) {
implementation_->deleteAssetInstances(createdInstances_);
createdInstances_.clear();
}

for (const auto& pair : keyframe.creations) {
const auto& creation = pair.second;

Expand Down Expand Up @@ -223,27 +221,15 @@ void Player::applyKeyframe(const Keyframe& keyframe) {
const auto& instanceKey = pair.first;
CORRADE_INTERNAL_ASSERT(createdInstances_.count(instanceKey) == 0);
createdInstances_[instanceKey] = node;
creationInfos_[instanceKey] = adjustedCreation;
}

if (!frameCleared) {
for (const auto& deletionInstanceKey : keyframe.deletions) {
const auto& it = createdInstances_.find(deletionInstanceKey);
if (it == createdInstances_.end()) {
// missing instance for this key, probably due to a failed instance
// creation
continue;
}

implementation_->deleteAssetInstance(it->second);
createdInstances_.erase(deletionInstanceKey);
}
}
hackProcessDeletions(keyframe);

for (const auto& pair : keyframe.stateUpdates) {
const auto& it = createdInstances_.find(pair.first);
if (it == createdInstances_.end()) {
// missing instance for this key, probably due to a failed instance
// creation
// Missing instance for this key due to a failed instance creation
continue;
}
auto* node = it->second;
Expand All @@ -258,6 +244,64 @@ void Player::applyKeyframe(const Keyframe& keyframe) {
}
}

void Player::hackProcessDeletions(const Keyframe& keyframe) {
// HACK: Classic and batch renderers currently handle deletions differently.
// The batch renderer can only clear the scene entirely; it cannot delete
// individual objects. To process deletions, all instances are deleted,
// remaining instances are re-created and latest transform updates are
// re-applied.
bool isClassicReplayRenderer =
dynamic_cast<AbstractSceneGraphPlayerImplementation*>(
implementation_.get()) != nullptr;
if (isClassicReplayRenderer) {
for (const auto& deletionInstanceKey : keyframe.deletions) {
const auto& it = createdInstances_.find(deletionInstanceKey);
if (it == createdInstances_.end()) {
// Missing instance for this key due to a failed instance creation
continue;
}

implementation_->deleteAssetInstance(it->second);
createdInstances_.erase(deletionInstanceKey);
}
} else if (keyframe.deletions.size() > 0) {
// Cache latest transforms
latestTransformCache_.clear();
for (const auto& pair : this->createdInstances_) {
const RenderAssetInstanceKey key = pair.first;
latestTransformCache_[key] =
0mdc marked this conversation as resolved.
Show resolved Hide resolved
implementation_->hackGetNodeTransform(pair.second);
}

// Delete all instances
implementation_->deleteAssetInstances(createdInstances_);

// Remove deleted instances from records
for (const auto& deletion : keyframe.deletions) {
const auto& createInstanceIt = createdInstances_.find(deletion);
if (createInstanceIt == createdInstances_.end()) {
// Missing instance for this key due to a failed instance creation
continue;
}
createdInstances_.erase(createInstanceIt);
creationInfos_.erase(deletion);
}

for (const auto& pair : createdInstances_) {
const auto key = pair.first;
const auto& creationInfo = creationInfos_[key];
auto* instance = implementation_->loadAndCreateRenderAssetInstance(
assetInfos_[creationInfo.filepath], creationInfo);

// Replace dangling reference
createdInstances_[key] = instance;

// Re-apply latest transform updates
implementation_->setNodeTransform(instance, latestTransformCache_[key]);
}
}
}

void Player::appendKeyframe(Keyframe&& keyframe) {
keyframes_.emplace_back(std::move(keyframe));
}
Expand Down
29 changes: 28 additions & 1 deletion src/esp/gfx/replay/Player.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class AbstractPlayerImplementation {
instances) = 0;

/**
* @brief Set node transform
* @brief Set node transform from translation and rotation components.
*
* The @p handle is expected to be returned from an earlier call to
* @ref loadAndCreateRenderAssetInstance() on the same instance.
Expand All @@ -94,6 +94,23 @@ class AbstractPlayerImplementation {
const Magnum::Vector3& translation,
const Magnum::Quaternion& rotation) = 0;

/**
* @brief Set node transform.
*
* The @p handle is expected to be returned from an earlier call to
* @ref loadAndCreateRenderAssetInstance() on the same instance.
*/
virtual void setNodeTransform(NodeHandle node,
const Mn::Matrix4& transform) = 0;

/**
* @brief Get node transform.
*
* The @p handle is expected to be returned from an earlier call to
* @ref loadAndCreateRenderAssetInstance() on the same instance.
*/
virtual Mn::Matrix4 hackGetNodeTransform(NodeHandle node) const = 0;

/**
* @brief Set node semantic ID
*
Expand Down Expand Up @@ -131,6 +148,10 @@ class AbstractSceneGraphPlayerImplementation
const Magnum::Vector3& translation,
const Magnum::Quaternion& rotation) override;

void setNodeTransform(NodeHandle node, const Mn::Matrix4& transform) override;

Mn::Matrix4 hackGetNodeTransform(NodeHandle node) const override;

void setNodeSemanticId(NodeHandle node, unsigned id) override;
};

Expand Down Expand Up @@ -251,13 +272,19 @@ class Player {
void applyKeyframe(const Keyframe& keyframe);
void readKeyframesFromJsonDocument(const rapidjson::Document& d);
void clearFrame();
void hackProcessDeletions(const Keyframe& keyframe);

std::shared_ptr<AbstractPlayerImplementation> implementation_;

int frameIndex_ = -1;
std::vector<Keyframe> keyframes_;
std::unordered_map<std::string, esp::assets::AssetInfo> assetInfos_;
std::unordered_map<RenderAssetInstanceKey, NodeHandle> createdInstances_;
std::unordered_map<RenderAssetInstanceKey,
assets::RenderAssetInstanceCreationInfo>
creationInfos_;
std::unordered_map<RenderAssetInstanceKey, Mn::Matrix4>
latestTransformCache_{};
std::set<std::string> failedFilepaths_;

ESP_SMART_POINTERS(Player)
Expand Down
3 changes: 0 additions & 3 deletions src/esp/sim/AbstractReplayRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@

#include "AbstractReplayRenderer.h"

#include <Magnum/Math/Functions.h>
#include <Magnum/Math/Vector2.h>

#include "esp/gfx/replay/Player.h"

namespace esp {
Expand Down
7 changes: 0 additions & 7 deletions src/esp/sim/AbstractReplayRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,9 @@
#ifndef ESP_SIM_ABSTRACTREPLAYRENDERER_H_
#define ESP_SIM_ABSTRACTREPLAYRENDERER_H_

#include <Magnum/GL/GL.h>
#include <Magnum/Magnum.h>

#include "esp/core/Check.h"
#include "esp/core/Esp.h"
#include "esp/geo/Geo.h"
#include "esp/gfx/DebugLineRender.h"

#include <memory>

namespace esp {

namespace gfx {
Expand Down
Loading