Skip to content

Commit

Permalink
Make light serialization incremental.
Browse files Browse the repository at this point in the history
  • Loading branch information
0mdc committed Sep 16, 2022
1 parent 5933fbc commit a75daa4
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 54 deletions.
2 changes: 1 addition & 1 deletion src/esp/gfx/replay/Keyframe.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ struct Keyframe {
std::vector<std::pair<RenderAssetInstanceKey, RenderAssetInstanceState>>
stateUpdates;
std::unordered_map<std::string, Transform> userTransforms;
std::vector<LightInfo> lights;
Cr::Containers::Optional<std::vector<LightInfo>> lights;

ESP_SMART_POINTERS(Keyframe)
};
Expand Down
14 changes: 9 additions & 5 deletions src/esp/gfx/replay/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ Keyframe Player::keyframeFromString(const std::string& keyframe) {
return res;
}

Player::Player(const LoadAndCreateRenderAssetInstanceCallback& callback,
const SetLightsCallback& lightsCallback)
: loadAndCreateRenderAssetInstanceCallback(callback),
setLightsCallback(lightsCallback) {}
Player::Player(const LoadAndCreateRenderAssetInstanceCallback&
loadAndCreateRenderAssetInstanceCallback,
const ChangeLightSetupCallback& changeLightSetupCallback)
: loadAndCreateRenderAssetInstanceCallback(
loadAndCreateRenderAssetInstanceCallback),
changeLightSetupCallback(changeLightSetupCallback) {}

void Player::readKeyframesFromFile(const std::string& filepath) {
close();
Expand Down Expand Up @@ -169,7 +171,9 @@ void Player::applyKeyframe(const Keyframe& keyframe) {
setSemanticIdForSubtree(node, state.semanticId);
}

setLightsCallback(keyframe.lights);
if (keyframe.lights) {
changeLightSetupCallback(*keyframe.lights);
}
}

void Player::appendKeyframe(Keyframe&& keyframe) {
Expand Down
10 changes: 6 additions & 4 deletions src/esp/gfx/replay/Player.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,16 @@ class Player {
std::function<esp::scene::SceneNode*(
const esp::assets::AssetInfo&,
const esp::assets::RenderAssetInstanceCreationInfo&)>;
using SetLightsCallback = std::function<void(const gfx::LightSetup& lights)>;
using ChangeLightSetupCallback =
std::function<void(const gfx::LightSetup& lights)>;

/**
* @brief Construct a Player.
* @param callback A function to load and create a render asset instance.
*/
explicit Player(const LoadAndCreateRenderAssetInstanceCallback& callback,
const SetLightsCallback& lightsCallback);
explicit Player(const LoadAndCreateRenderAssetInstanceCallback&
loadAndCreateRenderAssetInstanceCallback,
const ChangeLightSetupCallback& lightSetupCallback);

~Player();

Expand Down Expand Up @@ -128,7 +130,7 @@ class Player {

LoadAndCreateRenderAssetInstanceCallback
loadAndCreateRenderAssetInstanceCallback;
SetLightsCallback setLightsCallback;
ChangeLightSetupCallback changeLightSetupCallback;

int frameIndex_ = -1;
std::vector<Keyframe> keyframes_;
Expand Down
10 changes: 6 additions & 4 deletions src/esp/gfx/replay/Recorder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,15 @@ void Recorder::addUserTransformToKeyframe(const std::string& name,
}

void Recorder::addLightToKeyframe(const LightInfo& lightInfo) {
getKeyframe().lights.emplace_back(lightInfo);
auto& lights = getKeyframe().lights;
if (!lights) {
lights = std::vector<LightInfo>();
}
getKeyframe().lights->emplace_back(lightInfo);
}

void Recorder::clearLightsFromKeyframe() {
getKeyframe().lights.clear();
getKeyframe().lights = Cr::Containers::NullOpt;
}

void Recorder::addLoadsCreationsDeletions(KeyframeIterator begin,
Expand Down Expand Up @@ -188,8 +192,6 @@ void Recorder::updateInstanceStates() {
void Recorder::advanceKeyframe() {
savedKeyframes_.emplace_back(std::move(currKeyframe_));
currKeyframe_ = Keyframe{};
// TODO: record light deltas rather than absolute states
currKeyframe_.lights = savedKeyframes_.back().lights;
}

void Recorder::writeSavedKeyframesToFile(const std::string& filepath,
Expand Down
8 changes: 4 additions & 4 deletions src/esp/gfx/replay/ReplayManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ namespace replay {

std::shared_ptr<Player> ReplayManager::readKeyframesFromFile(
const std::string& filepath) {
auto player =
std::make_shared<Player>(playerCallback_, playerLightsCallback_);
auto player = std::make_shared<Player>(
loadAndCreateRenderAssetInstanceCallback_, changeLightSetupCallback_);
player->readKeyframesFromFile(filepath);
if (player->getNumKeyframes() == 0) {
ESP_ERROR(Mn::Debug::Flag::NoSpace)
Expand All @@ -22,8 +22,8 @@ std::shared_ptr<Player> ReplayManager::readKeyframesFromFile(
}

std::shared_ptr<Player> ReplayManager::createEmptyPlayer() {
auto player =
std::make_shared<Player>(playerCallback_, playerLightsCallback_);
auto player = std::make_shared<Player>(
loadAndCreateRenderAssetInstanceCallback_, changeLightSetupCallback_);
return player;
}

Expand Down
26 changes: 12 additions & 14 deletions src/esp/gfx/replay/ReplayManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,16 @@ class ReplayManager {
std::shared_ptr<Recorder> getRecorder() const { return recorder_; }

/**
* @brief Set a Player callback; this is needed to construct Player instances.
* @brief Set callbacks that are invoked when simulation state changes upon
* playing a new keyframe. This is required to construct Player instances.
*/
void setPlayerCallback(
const Player::LoadAndCreateRenderAssetInstanceCallback& callback) {
playerCallback_ = callback;
}

/**
* @brief Set a Player light creation callback; this is needed to construct
* Player instances.
*/
void setPlayerLightsCallback(const Player::SetLightsCallback& callback) {
playerLightsCallback_ = callback;
void setPlayerCallbacks(
const Player::LoadAndCreateRenderAssetInstanceCallback&
loadAndCreateRenderAssetInstanceCallback,
const Player::ChangeLightSetupCallback& changeLightSetupCallback) {
loadAndCreateRenderAssetInstanceCallback_ =
loadAndCreateRenderAssetInstanceCallback;
changeLightSetupCallback_ = changeLightSetupCallback;
}

/**
Expand All @@ -63,8 +60,9 @@ class ReplayManager {

private:
std::shared_ptr<Recorder> recorder_;
Player::LoadAndCreateRenderAssetInstanceCallback playerCallback_;
Player::SetLightsCallback playerLightsCallback_;
Player::LoadAndCreateRenderAssetInstanceCallback
loadAndCreateRenderAssetInstanceCallback_;
Player::ChangeLightSetupCallback changeLightSetupCallback_;

ESP_SMART_POINTERS(ReplayManager)
};
Expand Down
7 changes: 4 additions & 3 deletions src/esp/io/JsonEspTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ JsonGenericValue toJsonValue(const gfx::replay::Keyframe& keyframe,
io::addMember(obj, "userTransforms", userTransformsArray, allocator);
}

if (!keyframe.lights.empty()) {
if (keyframe.lights && !keyframe.lights->empty()) {
JsonGenericValue lightsArray(rapidjson::kArrayType);
for (const auto& light : keyframe.lights) {
for (const auto& light : *keyframe.lights) {
JsonGenericValue lightObj(rapidjson::kObjectType);
io::addMember(lightObj, "light", light, allocator);
lightsArray.PushBack(lightObj, allocator);
Expand Down Expand Up @@ -110,11 +110,12 @@ bool fromJsonValue(const JsonGenericValue& obj,

itr = obj.FindMember("lights");
if (itr != obj.MemberEnd()) {
keyframe.lights = std::vector<gfx::LightInfo>();
const JsonGenericValue& lightsArray = itr->value;
for (const auto& lightObj : lightsArray.GetArray()) {
gfx::LightInfo light;
io::readMember(lightObj, "light", light);
keyframe.lights.emplace_back(std::move(light));
keyframe.lights->emplace_back(light);
}
}

Expand Down
8 changes: 3 additions & 5 deletions src/esp/sim/Simulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -626,15 +626,13 @@ void Simulator::reconfigureReplayManager(bool enableGfxReplaySave) {
CORRADE_INTERNAL_ASSERT(resourceManager_);
resourceManager_->setRecorder(gfxReplayMgr_->getRecorder());

// provide Player callback to replay manager
gfxReplayMgr_->setPlayerCallback(
// provide Player callbacks to replay manager
gfxReplayMgr_->setPlayerCallbacks(
[this](const assets::AssetInfo& assetInfo,
const assets::RenderAssetInstanceCreationInfo& creation)
-> scene::SceneNode* {
return loadAndCreateRenderAssetInstance(assetInfo, creation);
});
// provide Player light creation callback
gfxReplayMgr_->setPlayerLightsCallback(
},
[this](const gfx::LightSetup& lights) -> void {
this->setLightSetup(lights);
});
Expand Down
36 changes: 22 additions & 14 deletions src/tests/GfxReplayTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,15 +206,15 @@ void GfxReplayTest::testPlayer() {

// Construct Player. Hook up ResourceManager::loadAndCreateRenderAssetInstance
// to Player via callback.
auto callback =
auto assetsCallback =
[&](const esp::assets::AssetInfo& assetInfo,
const esp::assets::RenderAssetInstanceCreationInfo& creation) {
std::vector<int> tempIDs{sceneID, esp::ID_UNDEFINED};
return resourceManager.loadAndCreateRenderAssetInstance(
assetInfo, creation, &sceneManager_, tempIDs);
};
auto dummyLightsCallback = [&](const esp::gfx::LightSetup& lights) -> void {};
esp::gfx::replay::Player player(callback, dummyLightsCallback);
esp::gfx::replay::Player player(assetsCallback, dummyLightsCallback);

std::vector<esp::gfx::replay::Keyframe> keyframes;

Expand All @@ -239,6 +239,7 @@ void GfxReplayTest::testPlayer() {
std::vector<std::pair<RenderAssetInstanceKey, RenderAssetInstanceState>>
stateUpdates;
std::unordered_map<std::string, Transform> userTransforms;
Cr::Containers::Optional<std::vector<LightInfo>> lights;
};
*/

Expand Down Expand Up @@ -342,13 +343,13 @@ void GfxReplayTest::testPlayer() {
}

void GfxReplayTest::testPlayerReadMissingFile() {
auto dummyCallback =
auto dummyAssetsCallback =
[&](const esp::assets::AssetInfo& assetInfo,
const esp::assets::RenderAssetInstanceCreationInfo& creation) {
return nullptr;
};
auto dummyLightsCallback = [&](const esp::gfx::LightSetup& lights) -> void {};
esp::gfx::replay::Player player(dummyCallback, dummyLightsCallback);
esp::gfx::replay::Player player(dummyAssetsCallback, dummyLightsCallback);

player.readKeyframesFromFile("file_that_does_not_exist.json");
CORRADE_COMPARE(player.getNumKeyframes(), 0);
Expand All @@ -363,13 +364,13 @@ void GfxReplayTest::testPlayerReadInvalidFile() {
out << "{invalid json";
out.close();

auto dummyCallback =
auto dummyAssetsCallback =
[&](const esp::assets::AssetInfo& assetInfo,
const esp::assets::RenderAssetInstanceCreationInfo& creation) {
return nullptr;
};
auto dummyLightsCallback = [&](const esp::gfx::LightSetup& lights) -> void {};
esp::gfx::replay::Player player(dummyCallback, dummyLightsCallback);
esp::gfx::replay::Player player(dummyAssetsCallback, dummyLightsCallback);

player.readKeyframesFromFile(testFilepath);
CORRADE_COMPARE(player.getNumKeyframes(), 0);
Expand Down Expand Up @@ -494,16 +495,16 @@ void GfxReplayTest::testLightIntegration() {
LightPositionModel::Global};
const LightInfo pointLight1{Magnum::Vector4{-10.0f, 4.25f, 10.0f, 1.0f},
{5.0, 5.0, 0.0},
LightPositionModel::Global};
LightPositionModel::Camera};
const LightInfo pointLight2{Magnum::Vector4{0.0f, 1.2f, -4.0f, 1.0f},
{4.0, 4.0, 4.0},
LightPositionModel::Global};
const LightInfo pointLight3{Magnum::Vector4{0.1f, 0.2f, -0.3f, 1.0f},
{0.0, 0.0, 1.0},
LightPositionModel::Global};
LightPositionModel::Object};
const LightInfo dirLight{Magnum::Vector4{0.1f, 0.2f, -0.3f, 0.0f},
{0.0, 0.0, 1.0},
LightPositionModel::Global};
const LightSetup lightSetup0{pointLight0, pointLight1};
const LightSetup lightSetup1{pointLight2};
const LightSetup lightSetup2{pointLight3};
const LightSetup lightSetup2{dirLight};

// record a playback file
{
Expand All @@ -521,8 +522,9 @@ void GfxReplayTest::testLightIntegration() {
recorder->saveKeyframe();
sim->setLightSetup(lightSetup1);
recorder->saveKeyframe();
recorder->saveKeyframe();
sim->setLightSetup(lightSetup2);
recorder->saveKeyframe(); // no change
sim->setLightSetup(lightSetup0);
sim->setLightSetup(lightSetup2); // overwrite previous light setup
recorder->saveKeyframe();

recorder->writeSavedKeyframesToFile(testFilepath);
Expand All @@ -541,23 +543,29 @@ void GfxReplayTest::testLightIntegration() {
sim->getGfxReplayManager()->readKeyframesFromFile(testFilepath);
CORRADE_VERIFY(player);
CORRADE_COMPARE(player->getNumKeyframes(), 4);
const auto& keyframes = player->debugGetKeyframes();
CORRADE_COMPARE(keyframes.size(), player->getNumKeyframes());

CORRADE_COMPARE(sim->getLightSetup().size(), 5); // 5 default lights

player->setKeyframeIndex(0);
CORRADE_COMPARE(sim->getLightSetup().size(), lightSetup0.size());
CORRADE_COMPARE(keyframes[0].lights->size(), lightSetup0.size());
compareLightSetups(sim->getLightSetup(), lightSetup0);

player->setKeyframeIndex(1);
CORRADE_COMPARE(sim->getLightSetup().size(), lightSetup1.size());
CORRADE_COMPARE(keyframes[1].lights->size(), lightSetup1.size());
compareLightSetups(sim->getLightSetup(), lightSetup1);

player->setKeyframeIndex(2);
CORRADE_COMPARE(sim->getLightSetup().size(), lightSetup1.size());
CORRADE_VERIFY(!keyframes[2].lights);
compareLightSetups(sim->getLightSetup(), lightSetup1);

player->setKeyframeIndex(3);
CORRADE_COMPARE(sim->getLightSetup().size(), lightSetup2.size());
CORRADE_COMPARE(keyframes[3].lights->size(), lightSetup2.size());
compareLightSetups(sim->getLightSetup(), lightSetup2);
}

Expand Down

0 comments on commit a75daa4

Please sign in to comment.