add timeline for anime loader
This commit is contained in:
@@ -19,17 +19,18 @@ public:
|
|||||||
virtual void load(AnimeLoaderConfig&& config) override {
|
virtual void load(AnimeLoaderConfig&& config) override {
|
||||||
IAnimeLoader::load(std::move(config));
|
IAnimeLoader::load(std::move(config));
|
||||||
|
|
||||||
this->frames.emplace(60 * 0, KeyFrame{.position = {F(0), F(-10), F(10)}, .rotation = {F(0.382683), F(0), F(0), F(0.92388)}});
|
this->timeline.add_key_frame(60 * 0, KeyFrame{.position = {F(0), F(-10), F(10)}, .rotation = {F(0.382683), F(0), F(0), F(0.92388)}});
|
||||||
this->frames.emplace(60 * 1,
|
this->timeline.add_key_frame(60 * 1,
|
||||||
KeyFrame{.position = {F(-10), F(0), F(10)},
|
KeyFrame{.position = {F(-10), F(0), F(10)},
|
||||||
.rotation = {F(0.270598), F(-0.270598), F(-0.653282), F(0.653282)}});
|
.rotation = {F(0.270598), F(-0.270598), F(-0.653282), F(0.653282)}});
|
||||||
this->frames.emplace(60 * 2, KeyFrame{.position = {F(0), F(10), F(10)}, .rotation = {F(0), F(-0.382683), F(-0.92388), F(0)}});
|
this->timeline.add_key_frame(60 * 2,
|
||||||
this->frames.emplace(60 * 3,
|
KeyFrame{.position = {F(0), F(10), F(10)}, .rotation = {F(0), F(-0.382683), F(-0.92388), F(0)}});
|
||||||
KeyFrame{.position = {F(10), F(0), F(10)},
|
this->timeline.add_key_frame(60 * 3,
|
||||||
.rotation = {F(-0.270598), F(-0.270598), F(-0.653282), F(-0.653282)}});
|
KeyFrame{.position = {F(10), F(0), F(10)},
|
||||||
this->frames.emplace(60 * 4,
|
.rotation = {F(-0.270598), F(-0.270598), F(-0.653282), F(-0.653282)}});
|
||||||
KeyFrame{.position = {F(0), F(-10), F(10)},
|
this->timeline.add_key_frame(60 * 4,
|
||||||
.rotation = {F(0.382683), F(0), F(0), F(0.92388)}}); // Same as the first
|
KeyFrame{.position = {F(0), F(-10), F(10)},
|
||||||
|
.rotation = {F(0.382683), F(0), F(0), F(0.92388)}}); // Same as the first
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,42 +4,42 @@ using ::basalt::shared::math::FloatPoint;
|
|||||||
|
|
||||||
namespace basalt::shared::anime_loader {
|
namespace basalt::shared::anime_loader {
|
||||||
|
|
||||||
#pragma region Anime Loader
|
#pragma region Timeline
|
||||||
|
|
||||||
IAnimeLoader::IAnimeLoader() : status(AnimeLoaderStatus::Ready), time(0) {}
|
Timeline::Timeline() : keyframes(), max_frame_cache(0) {
|
||||||
|
// insert default frame for first index
|
||||||
IAnimeLoader::~IAnimeLoader() {}
|
this->keyframes[0] = KeyFrame{.position = {0, 0, 0}, .rotation = {0, 0, 0, 1}};
|
||||||
|
|
||||||
void IAnimeLoader::load(AnimeLoaderConfig&& config) {
|
|
||||||
if (this->status != AnimeLoaderStatus::Ready) throw std::runtime_error("unexpected anime loader status");
|
|
||||||
this->config = std::move(config);
|
|
||||||
this->status = AnimeLoaderStatus::Loaded;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyFrameSpan IAnimeLoader::tick() {
|
Timeline::~Timeline() {}
|
||||||
if (this->status != AnimeLoaderStatus::Loaded) throw std::runtime_error("unexpected anime loader status");
|
|
||||||
|
|
||||||
// Get last frame index
|
void Timeline::add_key_frame(math::Index frame_index, KeyFrame frame_data) {
|
||||||
auto last_pair = this->frames.end();
|
// insert data
|
||||||
--last_pair;
|
this->keyframes[frame_index] = frame_data;
|
||||||
auto last_index = last_pair->first;
|
// update max frame
|
||||||
// Accumulate time
|
this->max_frame_cache = keyframes.rbegin()->first;
|
||||||
++this->time;
|
}
|
||||||
if (this->time > last_index) {
|
|
||||||
this->time = 0;
|
math::Index Timeline::max_frame() const {
|
||||||
|
return this->max_frame_cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyFrameSpan Timeline::tick(math::Index frame_index) const {
|
||||||
|
if (this->keyframes.empty()) [[unlikely]] {
|
||||||
|
throw std::runtime_error("No key frames in timeline");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 首先用lower_bound获取到不小于自身的项目(肯定能获取到)
|
// 首先用lower_bound获取到不小于自身的项目(肯定能获取到)
|
||||||
auto lower_bound = this->frames.lower_bound(this->time);
|
auto lower_bound = this->keyframes.lower_bound(frame_index);
|
||||||
// 获取下一帧,如果没有下一帧,就转换为自身
|
// 获取下一帧,如果没有下一帧,就转换为自身
|
||||||
auto upper_bound = lower_bound;
|
auto upper_bound = lower_bound;
|
||||||
++upper_bound;
|
++upper_bound;
|
||||||
if (upper_bound == this->frames.end()) {
|
if (upper_bound == this->keyframes.end()) {
|
||||||
upper_bound = lower_bound;
|
upper_bound = lower_bound;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算归一化时间
|
// 计算归一化时间
|
||||||
FloatPoint next_time = static_cast<FloatPoint>(this->time - lower_bound->first)
|
FloatPoint next_time = static_cast<FloatPoint>(frame_index - lower_bound->first)
|
||||||
/ static_cast<FloatPoint>(upper_bound->first - lower_bound->first + 1);
|
/ static_cast<FloatPoint>(upper_bound->first - lower_bound->first + 1);
|
||||||
FloatPoint prev_time = static_cast<FloatPoint>(1) - next_time;
|
FloatPoint prev_time = static_cast<FloatPoint>(1) - next_time;
|
||||||
|
|
||||||
@@ -56,4 +56,30 @@ namespace basalt::shared::anime_loader {
|
|||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Anime Loader
|
||||||
|
|
||||||
|
IAnimeLoader::IAnimeLoader() : status(AnimeLoaderStatus::Ready), time(0), timeline() {}
|
||||||
|
|
||||||
|
IAnimeLoader::~IAnimeLoader() {}
|
||||||
|
|
||||||
|
void IAnimeLoader::load(AnimeLoaderConfig&& config) {
|
||||||
|
if (this->status != AnimeLoaderStatus::Ready) throw std::runtime_error("unexpected anime loader status");
|
||||||
|
this->config = std::move(config);
|
||||||
|
this->status = AnimeLoaderStatus::Loaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyFrameSpan IAnimeLoader::tick() {
|
||||||
|
if (this->status != AnimeLoaderStatus::Loaded) throw std::runtime_error("unexpected anime loader status");
|
||||||
|
|
||||||
|
// Accumulate time
|
||||||
|
++this->time;
|
||||||
|
if (this->time > this->timeline.max_frame()) {
|
||||||
|
this->time = 0;
|
||||||
|
}
|
||||||
|
// Return from timeline
|
||||||
|
return this->timeline.tick(this->time);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
} // namespace basalt::shared::anime_loader
|
} // namespace basalt::shared::anime_loader
|
||||||
|
|||||||
@@ -6,15 +6,6 @@
|
|||||||
|
|
||||||
namespace basalt::shared::anime_loader {
|
namespace basalt::shared::anime_loader {
|
||||||
|
|
||||||
//struct KeyFrame {
|
|
||||||
// math::Index frame_index;
|
|
||||||
// math::Matrix4x4 transform;
|
|
||||||
//};
|
|
||||||
|
|
||||||
//struct KeyFrameCompare {
|
|
||||||
// bool operator()(const KeyFrame& lhs, const KeyFrame& rhs) const { return lhs.time < rhs.time; }
|
|
||||||
//};
|
|
||||||
|
|
||||||
struct KeyFrame {
|
struct KeyFrame {
|
||||||
math::Vector3 position;
|
math::Vector3 position;
|
||||||
math::Quaternion rotation;
|
math::Quaternion rotation;
|
||||||
@@ -29,6 +20,21 @@ namespace basalt::shared::anime_loader {
|
|||||||
math::Quaternion next_rotation; ///< 后一帧的摄像机旋转。
|
math::Quaternion next_rotation; ///< 后一帧的摄像机旋转。
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Timeline {
|
||||||
|
public:
|
||||||
|
Timeline();
|
||||||
|
~Timeline();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void add_key_frame(math::Index frame_index, KeyFrame frame_data);
|
||||||
|
math::Index max_frame() const;
|
||||||
|
KeyFrameSpan tick(math::Index frame_index) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
math::Index max_frame_cache;
|
||||||
|
std::map<math::Index, KeyFrame> keyframes;
|
||||||
|
};
|
||||||
|
|
||||||
struct AnimeLoaderConfig {
|
struct AnimeLoaderConfig {
|
||||||
char_types::BSString filename; ///< The file to be loaded by loader.
|
char_types::BSString filename; ///< The file to be loaded by loader.
|
||||||
};
|
};
|
||||||
@@ -53,8 +59,8 @@ namespace basalt::shared::anime_loader {
|
|||||||
/**
|
/**
|
||||||
* @brief
|
* @brief
|
||||||
* @remarks
|
* @remarks
|
||||||
* \li 重写时只允许往frames里插入数据。
|
* \li 重写时只允许往timeline里插入数据。
|
||||||
* \li 重写时务必保证frames里插入的数据大于2个,且初始节点的Key总是0。动画帧个数必须大于4。
|
* \li 重写时务必保证timeline里插入的数据大于2个,且初始节点的Key总是0。动画帧个数必须大于4。
|
||||||
*/
|
*/
|
||||||
virtual void load(AnimeLoaderConfig&& config);
|
virtual void load(AnimeLoaderConfig&& config);
|
||||||
KeyFrameSpan tick();
|
KeyFrameSpan tick();
|
||||||
@@ -63,7 +69,7 @@ namespace basalt::shared::anime_loader {
|
|||||||
AnimeLoaderStatus status;
|
AnimeLoaderStatus status;
|
||||||
AnimeLoaderConfig config;
|
AnimeLoaderConfig config;
|
||||||
math::Index time;
|
math::Index time;
|
||||||
std::map<math::Index, KeyFrame> frames;
|
Timeline timeline;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace basalt::shared::anime_loader
|
} // namespace basalt::shared::anime_loader
|
||||||
|
|||||||
Reference in New Issue
Block a user