write shit
This commit is contained in:
@@ -26,7 +26,7 @@ option(BASALT_OBJ_OBJECT_LOADER "Build with Wavefront OBJ 3D object loader suppo
|
||||
option(BASALT_GLTF_OBJECT_LOADER "Build with glTF 3D object loader support." OFF)
|
||||
option(BASALT_ASSIMP_OBJECT_LOADER "Build with Assimp 3D object loader support." OFF)
|
||||
# Camera Motion Loaders
|
||||
option(BASALT_homemade_ANIME_LOADER "Build with homemade camera motion loader support." OFF)
|
||||
option(BASALT_CHICKENNUGGET_ANIME_LOADER "Build with chicken nugget camera motion loader support." OFF)
|
||||
|
||||
# Set C++ standards
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
if (BASALT_CHICKENNUGGET_ANIME_LOADER)
|
||||
add_subdirectory(ChickenNuggetAnimeLoader)
|
||||
endif ()
|
||||
@@ -0,0 +1,27 @@
|
||||
# Create shared library
|
||||
add_library(BasaltChickenNuggetAnimeLoader SHARED "")
|
||||
# Setup sources
|
||||
target_sources(BasaltChickenNuggetAnimeLoader
|
||||
PRIVATE
|
||||
main.cpp
|
||||
)
|
||||
# Setup header infomation
|
||||
target_include_directories(BasaltChickenNuggetAnimeLoader
|
||||
PRIVATE
|
||||
"${CMAKE_CURRENT_LIST_DIR}"
|
||||
)
|
||||
# Setup linked library infomation
|
||||
target_link_libraries(BasaltChickenNuggetAnimeLoader
|
||||
PRIVATE
|
||||
BasaltShared
|
||||
)
|
||||
# Enable export macro
|
||||
target_compile_definitions(BasaltChickenNuggetAnimeLoader
|
||||
PRIVATE
|
||||
BS_EXPORTING
|
||||
)
|
||||
|
||||
# Install BasaltChickenNuggetAnimeLoader only on Release mode
|
||||
install(TARGETS BasaltChickenNuggetAnimeLoader
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}/plugin/anime_loader"
|
||||
)
|
||||
@@ -0,0 +1,39 @@
|
||||
#include <basalt/export_macro.hpp>
|
||||
#include <basalt/anime_loader.hpp>
|
||||
#include <basalt/math.hpp>
|
||||
|
||||
namespace anime_loader = ::basalt::shared::anime_loader;
|
||||
using anime_loader::IAnimeLoader;
|
||||
using anime_loader::KeyFrame;
|
||||
|
||||
using ::basalt::shared::math::FloatPoint;
|
||||
#define F(x) (static_cast<FloatPoint>(x))
|
||||
|
||||
class ChickenNuggetAnimeLoader : public IAnimeLoader {
|
||||
public:
|
||||
ChickenNuggetAnimeLoader() {}
|
||||
virtual ~ChickenNuggetAnimeLoader() {}
|
||||
|
||||
protected:
|
||||
virtual void internal_load() override {
|
||||
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->frames.emplace(60 * 1,
|
||||
KeyFrame{.position = {F(-10), F(0), F(10)},
|
||||
.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->frames.emplace(60 * 3,
|
||||
KeyFrame{.position = {F(10), F(0), F(10)},
|
||||
.rotation = {F(-0.270598), F(-0.270598), F(-0.653282), F(-0.653282)}});
|
||||
this->frames.emplace(60 * 4,
|
||||
KeyFrame{.position = {F(0), F(-10), F(10)},
|
||||
.rotation = {F(0.382683), F(0), F(0), F(0.92388)}}); // Same as the first
|
||||
}
|
||||
};
|
||||
|
||||
BS_EXPORT void* BSCreateInstance() {
|
||||
return static_cast<IAnimeLoader*>(new ChickenNuggetAnimeLoader());
|
||||
}
|
||||
|
||||
BS_EXPORT void BSDestroyInstance(void* instance) {
|
||||
delete dynamic_cast<ChickenNuggetAnimeLoader*>(static_cast<IAnimeLoader*>(instance));
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
if (BASALT_OBJ_OBJECT_LOADER)
|
||||
add_subdirectory(ObjObjectLoader)
|
||||
endif ()
|
||||
# if (BASALT_GLTF_OBJECT_LOADER)
|
||||
# add_subdirectory(GltfObjectLoader)
|
||||
# endif ()
|
||||
# if (BASALT_ASSIMP_OBJECT_LOADER)
|
||||
# add_subdirectory(AssimpObjectLoader)
|
||||
# endif ()
|
||||
@@ -0,0 +1,27 @@
|
||||
# Create shared library
|
||||
add_library(BasaltObjObjectLoader SHARED "")
|
||||
# Setup sources
|
||||
target_sources(BasaltObjObjectLoader
|
||||
PRIVATE
|
||||
main.cpp
|
||||
)
|
||||
# Setup header infomation
|
||||
target_include_directories(BasaltObjObjectLoader
|
||||
PRIVATE
|
||||
"${CMAKE_CURRENT_LIST_DIR}"
|
||||
)
|
||||
# Setup linked library infomation
|
||||
target_link_libraries(BasaltObjObjectLoader
|
||||
PRIVATE
|
||||
BasaltShared
|
||||
)
|
||||
# Enable export macro
|
||||
target_compile_definitions(BasaltObjObjectLoader
|
||||
PRIVATE
|
||||
BS_EXPORTING
|
||||
)
|
||||
|
||||
# Install BasaltObjObjectLoader only on Release mode
|
||||
install(TARGETS BasaltObjObjectLoader
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}/plugin/object_loader"
|
||||
)
|
||||
@@ -0,0 +1,9 @@
|
||||
#include <basalt/export_macro.hpp>
|
||||
|
||||
BS_EXPORT void* BSCreateInstance() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BS_EXPORT void BSDestroyInstance(void* instance) {
|
||||
return;
|
||||
}
|
||||
@@ -1,13 +1,70 @@
|
||||
#include "anime_loader.hpp"
|
||||
|
||||
using ::basalt::shared::math::FloatPoint;
|
||||
|
||||
namespace basalt::shared::anime_loader {
|
||||
|
||||
IAnimeLoader::IAnimeLoader() {
|
||||
#pragma region Anime Loader
|
||||
|
||||
IAnimeLoader::IAnimeLoader() : status(AnimeLoaderStatus::Ready), time(0), last_index(0) {}
|
||||
|
||||
IAnimeLoader::~IAnimeLoader() {}
|
||||
|
||||
void IAnimeLoader::load() {
|
||||
if (this->status != AnimeLoaderStatus::Ready) throw std::runtime_error("unexpected anime loader status");
|
||||
|
||||
// load by user
|
||||
internal_load();
|
||||
|
||||
// check empty
|
||||
if (this->frames.empty()) throw std::runtime_error("no anime key frames.");
|
||||
// Get last frame index
|
||||
auto last_pair = this->frames.end();
|
||||
--last_pair;
|
||||
this->last_index = last_pair->first;
|
||||
|
||||
// change status
|
||||
this->status = AnimeLoaderStatus::Loaded;
|
||||
}
|
||||
|
||||
IAnimeLoader::~IAnimeLoader() {
|
||||
KeyFrameSpan IAnimeLoader::tick() {
|
||||
if (this->status != AnimeLoaderStatus::Loaded) throw std::runtime_error("unexpected anime loader status");
|
||||
|
||||
// Accumulate time
|
||||
++this->time;
|
||||
if (this->time > this->last_index) {
|
||||
this->time = 0;
|
||||
}
|
||||
|
||||
// 首先用lower_bound获取到不小于自身的项目(肯定能获取到)
|
||||
auto lower_bound = this->frames.lower_bound(this->time);
|
||||
// 获取下一帧,如果没有下一帧,就转换为自身
|
||||
auto upper_bound = lower_bound;
|
||||
++upper_bound;
|
||||
if (upper_bound == this->frames.end()) {
|
||||
upper_bound = lower_bound;
|
||||
}
|
||||
|
||||
// 计算归一化时间
|
||||
FloatPoint next_time = static_cast<FloatPoint>(this->time - lower_bound->first)
|
||||
/ static_cast<FloatPoint>(upper_bound->first - lower_bound->first + 1);
|
||||
FloatPoint prev_time = static_cast<FloatPoint>(1) - next_time;
|
||||
|
||||
// 返回结构
|
||||
return KeyFrameSpan{
|
||||
.prev_time = prev_time,
|
||||
.next_time = next_time,
|
||||
.prev_position = lower_bound->second.position,
|
||||
.next_position = upper_bound->second.position,
|
||||
.prev_rotation = lower_bound->second.rotation,
|
||||
.next_rotation = upper_bound->second.rotation,
|
||||
};
|
||||
}
|
||||
|
||||
void IAnimeLoader::internal_load() {
|
||||
throw std::logic_error("unimplemented function");
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
} // namespace basalt::shared::anime_loader
|
||||
|
||||
@@ -1,13 +1,60 @@
|
||||
#pragma once
|
||||
#include "math.hpp"
|
||||
#include <map>
|
||||
#include <functional>
|
||||
|
||||
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 {
|
||||
math::Vector3 position;
|
||||
math::Quaternion rotation;
|
||||
};
|
||||
|
||||
struct KeyFrameSpan {
|
||||
math::FloatPoint prev_time; ///< 归一化的到前一帧的时间,即两者加起来为1。
|
||||
math::FloatPoint next_time; ///< 归一化的到后一帧的时间,即两者加起来为1。
|
||||
math::Vector3 prev_position; ///< 前一帧的摄像机坐标。
|
||||
math::Vector3 next_position; ///< 后一帧的摄像机坐标。
|
||||
math::Quaternion prev_rotation; ///< 前一帧的摄像机旋转。
|
||||
math::Quaternion next_rotation; ///< 后一帧的摄像机旋转。
|
||||
};
|
||||
|
||||
enum class AnimeLoaderStatus {
|
||||
Ready,
|
||||
Loaded,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @details
|
||||
* \li 摄像机的transform基于Blender坐标系。
|
||||
* \li 摄像机的默认状态与Blender摄像机一致,即初始指向-Z,+Y Up。
|
||||
*/
|
||||
class IAnimeLoader {
|
||||
public:
|
||||
IAnimeLoader();
|
||||
virtual ~IAnimeLoader();
|
||||
|
||||
public:
|
||||
void load();
|
||||
KeyFrameSpan tick();
|
||||
|
||||
protected:
|
||||
virtual void internal_load();
|
||||
|
||||
protected:
|
||||
AnimeLoaderStatus status;
|
||||
math::Index time, last_index;
|
||||
std::map<math::Index, KeyFrame> frames;
|
||||
};
|
||||
|
||||
} // namespace basalt::shared::anime_loader
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
namespace basalt::shared::deliver {
|
||||
|
||||
IDeliver::IDeliver() {}
|
||||
IDeliver::IDeliver() : status(DeliverStatus::Ready) {}
|
||||
|
||||
IDeliver::~IDeliver() {
|
||||
if (this->status != DeliverStatus::Stop) {
|
||||
|
||||
@@ -1,7 +1,37 @@
|
||||
#include "math.hpp"
|
||||
#include <stdexcept> // Include for std::out_of_range
|
||||
|
||||
namespace Basalt::Shared::Math {
|
||||
namespace basalt::shared::math {
|
||||
|
||||
#pragma region Triangle
|
||||
|
||||
Index& Triangle::operator[](size_t index) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return i;
|
||||
case 1:
|
||||
return j;
|
||||
case 2:
|
||||
return k;
|
||||
default:
|
||||
throw std::out_of_range("Triangle index out of range");
|
||||
}
|
||||
}
|
||||
|
||||
const Index& Triangle::operator[](size_t index) const {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return i;
|
||||
case 1:
|
||||
return j;
|
||||
case 2:
|
||||
return k;
|
||||
default:
|
||||
throw std::out_of_range("Triangle index out of range");
|
||||
}
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Vector3
|
||||
|
||||
@@ -33,9 +63,9 @@ namespace Basalt::Shared::Math {
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Vector4
|
||||
#pragma region Quaternion
|
||||
|
||||
FloatPoint& Vector4::operator[](size_t index) {
|
||||
FloatPoint& Quaternion::operator[](size_t index) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return x;
|
||||
@@ -46,11 +76,11 @@ namespace Basalt::Shared::Math {
|
||||
case 3:
|
||||
return w;
|
||||
default:
|
||||
throw std::out_of_range("Vector4 index out of range");
|
||||
throw std::out_of_range("Quaternion index out of range");
|
||||
}
|
||||
}
|
||||
|
||||
const FloatPoint& Vector4::operator[](size_t index) const {
|
||||
const FloatPoint& Quaternion::operator[](size_t index) const {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return x;
|
||||
@@ -61,22 +91,56 @@ namespace Basalt::Shared::Math {
|
||||
case 3:
|
||||
return w;
|
||||
default:
|
||||
throw std::out_of_range("Vector4 index out of range");
|
||||
throw std::out_of_range("Quaternion index out of range");
|
||||
}
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
//
|
||||
//#pragma region Vector4
|
||||
//
|
||||
// FloatPoint& Vector4::operator[](size_t index) {
|
||||
// switch (index) {
|
||||
// case 0:
|
||||
// return x;
|
||||
// case 1:
|
||||
// return y;
|
||||
// case 2:
|
||||
// return z;
|
||||
// case 3:
|
||||
// return w;
|
||||
// default:
|
||||
// throw std::out_of_range("Vector4 index out of range");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// const FloatPoint& Vector4::operator[](size_t index) const {
|
||||
// switch (index) {
|
||||
// case 0:
|
||||
// return x;
|
||||
// case 1:
|
||||
// return y;
|
||||
// case 2:
|
||||
// return z;
|
||||
// case 3:
|
||||
// return w;
|
||||
// default:
|
||||
// throw std::out_of_range("Vector4 index out of range");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//#pragma endregion
|
||||
//
|
||||
//#pragma region Matrix4x4
|
||||
//
|
||||
// Vector4& Matrix4x4::operator[](size_t index) {
|
||||
// return data.at(index);
|
||||
// }
|
||||
//
|
||||
// const Vector4& Matrix4x4::operator[](size_t index) const {
|
||||
// return data.at(index);
|
||||
// }
|
||||
//
|
||||
//#pragma endregion
|
||||
|
||||
#pragma region Matrix4x4
|
||||
|
||||
Vector4& Matrix4x4::operator[](size_t index) {
|
||||
return data.at(index);
|
||||
}
|
||||
|
||||
const Vector4& Matrix4x4::operator[](size_t index) const {
|
||||
return data.at(index);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
} // namespace Basalt::Shared::Math
|
||||
} // namespace basalt::shared::math
|
||||
@@ -1,10 +1,19 @@
|
||||
#pragma once
|
||||
#include <stdexcept>
|
||||
#include <cinttypes>
|
||||
#include <array> // Include array for std::array::at
|
||||
|
||||
namespace Basalt::Shared::Math {
|
||||
namespace basalt::shared::math {
|
||||
|
||||
using FloatPoint = float;
|
||||
using Index = std::uint32_t;
|
||||
|
||||
struct Triangle {
|
||||
Index i, j, k;
|
||||
|
||||
Index& operator[](size_t index);
|
||||
const Index& operator[](size_t index) const;
|
||||
};
|
||||
|
||||
struct Vector3 {
|
||||
FloatPoint x, y, z;
|
||||
@@ -13,30 +22,37 @@ namespace Basalt::Shared::Math {
|
||||
const FloatPoint& operator[](size_t index) const;
|
||||
};
|
||||
|
||||
struct Vector4 {
|
||||
struct Quaternion {
|
||||
FloatPoint x, y, z, w;
|
||||
|
||||
FloatPoint& operator[](size_t index);
|
||||
const FloatPoint& operator[](size_t index) const;
|
||||
};
|
||||
|
||||
struct Matrix4x4 {
|
||||
private:
|
||||
std::array<Vector4, 4> data; // Use std::array instead of raw array for .at() method
|
||||
//struct Vector4 {
|
||||
// FloatPoint x, y, z, w;
|
||||
|
||||
public:
|
||||
Vector4& operator[](size_t index);
|
||||
const Vector4& operator[](size_t index) const;
|
||||
};
|
||||
// FloatPoint& operator[](size_t index);
|
||||
// const FloatPoint& operator[](size_t index) const;
|
||||
//};
|
||||
|
||||
#define NOT_IMPLEMENTED throw std::logic_error("not implemented function");
|
||||
//struct Matrix4x4 {
|
||||
//private:
|
||||
// std::array<Vector4, 4> data; // Use std::array instead of raw array for .at() method
|
||||
|
||||
template<typename TNum, typename TVec>
|
||||
struct Vector3Traits {};
|
||||
//public:
|
||||
// Vector4& operator[](size_t index);
|
||||
// const Vector4& operator[](size_t index) const;
|
||||
//};
|
||||
//
|
||||
//#define NOT_IMPLEMENTED throw std::logic_error("not implemented function");
|
||||
//
|
||||
// template<typename TNum, typename TVec>
|
||||
// struct Vector3Traits {};
|
||||
//
|
||||
// template<typename TNum, typename TMat>
|
||||
// struct Matrix4x4Traits {};
|
||||
//
|
||||
//#undef NOT_IMPLEMENTED
|
||||
|
||||
template<typename TNum, typename TMat>
|
||||
struct Matrix4x4Traits {};
|
||||
|
||||
#undef NOT_IMPLEMENTED
|
||||
|
||||
} // namespace Basalt::Shared::Math
|
||||
} // namespace basalt::shared::math
|
||||
@@ -1,13 +1,57 @@
|
||||
#include "object_loader.hpp"
|
||||
#include "anime_loader.hpp"
|
||||
|
||||
using ::basalt::shared::math::Triangle;
|
||||
using ::basalt::shared::math::Vector3;
|
||||
|
||||
namespace basalt::shared::object_loader {
|
||||
|
||||
IObjectLoader::IObjectLoader() {
|
||||
#pragma region Object
|
||||
|
||||
Object::Object(std::vector<Vector3>&& vertices, std::vector<Triangle>&& triangles) :
|
||||
vertices(std::move(vertices)), triangles(std::move(triangles)) {}
|
||||
|
||||
Object::~Object() {}
|
||||
|
||||
size_t Object::get_vertices_count() const {
|
||||
return this->vertices.size();
|
||||
}
|
||||
|
||||
IObjectLoader::~IObjectLoader() {
|
||||
|
||||
const math::Vector3* Object::get_vertices() const {
|
||||
return this->vertices.data();
|
||||
}
|
||||
|
||||
size_t Object::get_triangle_count() const {
|
||||
return this->triangles.size();
|
||||
}
|
||||
|
||||
const math::Triangle* Object::get_triangles() const {
|
||||
return this->triangles.data();
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Object Loader
|
||||
|
||||
IObjectLoader::IObjectLoader() : status(ObjectLoaderStatus::Ready) {}
|
||||
|
||||
IObjectLoader::~IObjectLoader() {}
|
||||
|
||||
void IObjectLoader::load() {
|
||||
if (this->status != ObjectLoaderStatus::Ready) throw std::runtime_error("unexpected object loader status");
|
||||
this->status = ObjectLoaderStatus::Loaded;
|
||||
}
|
||||
|
||||
const Object& IObjectLoader::get_object(size_t index) const {
|
||||
if (this->status != ObjectLoaderStatus::Loaded) throw std::runtime_error("unexpected object loader status");
|
||||
return this->objects.at(index);
|
||||
}
|
||||
|
||||
size_t IObjectLoader::get_object_count() const {
|
||||
if (this->status != ObjectLoaderStatus::Loaded) throw std::runtime_error("unexpected object loader status");
|
||||
return this->objects.size();
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
} // namespace basalt::shared::object_loader
|
||||
|
||||
@@ -1,13 +1,49 @@
|
||||
#pragma once
|
||||
#include "math.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace basalt::shared::object_loader {
|
||||
|
||||
class Object {
|
||||
public:
|
||||
Object(std::vector<math::Vector3>&& vertices, std::vector<math::Triangle>&& triangles);
|
||||
~Object();
|
||||
|
||||
public:
|
||||
size_t get_vertices_count() const;
|
||||
const math::Vector3* get_vertices() const;
|
||||
size_t get_triangle_count() const;
|
||||
const math::Triangle* get_triangles() const;
|
||||
|
||||
private:
|
||||
std::vector<math::Vector3> vertices;
|
||||
std::vector<math::Triangle> triangles;
|
||||
};
|
||||
|
||||
enum class ObjectLoaderStatus {
|
||||
Ready,
|
||||
Loaded,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @details
|
||||
* \li 加载的模型的坐标系与Blender一致。
|
||||
* \li 加载的模型的顶点顺序为CCW,即右手定则确认法线方向。
|
||||
*/
|
||||
class IObjectLoader {
|
||||
public:
|
||||
IObjectLoader();
|
||||
virtual ~IObjectLoader();
|
||||
|
||||
public:
|
||||
virtual void load();
|
||||
const Object& get_object(size_t index) const;
|
||||
size_t get_object_count() const;
|
||||
|
||||
protected:
|
||||
ObjectLoaderStatus status;
|
||||
std::vector<Object> objects;
|
||||
};
|
||||
|
||||
} // namespace basalt::shared::object_loader
|
||||
|
||||
Reference in New Issue
Block a user