1
0

write shit

This commit is contained in:
2026-01-09 16:40:30 +08:00
parent 55ed60c643
commit 06bfe69c0e
14 changed files with 424 additions and 46 deletions

View File

@@ -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_GLTF_OBJECT_LOADER "Build with glTF 3D object loader support." OFF)
option(BASALT_ASSIMP_OBJECT_LOADER "Build with Assimp 3D object loader support." OFF) option(BASALT_ASSIMP_OBJECT_LOADER "Build with Assimp 3D object loader support." OFF)
# Camera Motion Loaders # 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 C++ standards
set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD 23)

View File

@@ -0,0 +1,3 @@
if (BASALT_CHICKENNUGGET_ANIME_LOADER)
add_subdirectory(ChickenNuggetAnimeLoader)
endif ()

View File

@@ -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"
)

View File

@@ -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));
}

View File

@@ -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 ()

View File

@@ -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"
)

View File

@@ -0,0 +1,9 @@
#include <basalt/export_macro.hpp>
BS_EXPORT void* BSCreateInstance() {
return nullptr;
}
BS_EXPORT void BSDestroyInstance(void* instance) {
return;
}

View File

@@ -1,13 +1,70 @@
#include "anime_loader.hpp" #include "anime_loader.hpp"
using ::basalt::shared::math::FloatPoint;
namespace basalt::shared::anime_loader { 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

View File

@@ -1,13 +1,60 @@
#pragma once #pragma once
#include "math.hpp"
#include <map>
#include <functional>
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 {
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 { class IAnimeLoader {
public: public:
IAnimeLoader(); IAnimeLoader();
virtual ~IAnimeLoader(); virtual ~IAnimeLoader();
public:
void load();
KeyFrameSpan tick();
protected: protected:
virtual void internal_load();
protected:
AnimeLoaderStatus status;
math::Index time, last_index;
std::map<math::Index, KeyFrame> frames;
}; };
} // namespace basalt::shared::anime_loader } // namespace basalt::shared::anime_loader

View File

@@ -3,7 +3,7 @@
namespace basalt::shared::deliver { namespace basalt::shared::deliver {
IDeliver::IDeliver() {} IDeliver::IDeliver() : status(DeliverStatus::Ready) {}
IDeliver::~IDeliver() { IDeliver::~IDeliver() {
if (this->status != DeliverStatus::Stop) { if (this->status != DeliverStatus::Stop) {

View File

@@ -1,7 +1,37 @@
#include "math.hpp" #include "math.hpp"
#include <stdexcept> // Include for std::out_of_range #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 #pragma region Vector3
@@ -33,9 +63,9 @@ namespace Basalt::Shared::Math {
#pragma endregion #pragma endregion
#pragma region Vector4 #pragma region Quaternion
FloatPoint& Vector4::operator[](size_t index) { FloatPoint& Quaternion::operator[](size_t index) {
switch (index) { switch (index) {
case 0: case 0:
return x; return x;
@@ -46,11 +76,11 @@ namespace Basalt::Shared::Math {
case 3: case 3:
return w; return w;
default: 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) { switch (index) {
case 0: case 0:
return x; return x;
@@ -61,22 +91,56 @@ namespace Basalt::Shared::Math {
case 3: case 3:
return w; return w;
default: default:
throw std::out_of_range("Vector4 index out of range"); throw std::out_of_range("Quaternion index out of range");
} }
} }
#pragma endregion #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 } // namespace basalt::shared::math
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

View File

@@ -1,10 +1,19 @@
#pragma once #pragma once
#include <stdexcept> #include <stdexcept>
#include <cinttypes>
#include <array> // Include array for std::array::at #include <array> // Include array for std::array::at
namespace Basalt::Shared::Math { namespace basalt::shared::math {
using FloatPoint = float; 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 { struct Vector3 {
FloatPoint x, y, z; FloatPoint x, y, z;
@@ -13,30 +22,37 @@ namespace Basalt::Shared::Math {
const FloatPoint& operator[](size_t index) const; const FloatPoint& operator[](size_t index) const;
}; };
struct Vector4 { struct Quaternion {
FloatPoint x, y, z, w; FloatPoint x, y, z, w;
FloatPoint& operator[](size_t index); FloatPoint& operator[](size_t index);
const FloatPoint& operator[](size_t index) const; const FloatPoint& operator[](size_t index) const;
}; };
struct Matrix4x4 { //struct Vector4 {
private: // FloatPoint x, y, z, w;
std::array<Vector4, 4> data; // Use std::array instead of raw array for .at() method
public: // FloatPoint& operator[](size_t index);
Vector4& operator[](size_t index); // const FloatPoint& operator[](size_t index) const;
const Vector4& 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> //public:
struct Vector3Traits {}; // 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> } // namespace basalt::shared::math
struct Matrix4x4Traits {};
#undef NOT_IMPLEMENTED
} // namespace Basalt::Shared::Math

View File

@@ -1,13 +1,57 @@
#include "object_loader.hpp" #include "object_loader.hpp"
#include "anime_loader.hpp"
using ::basalt::shared::math::Triangle;
using ::basalt::shared::math::Vector3;
namespace basalt::shared::object_loader { 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

View File

@@ -1,13 +1,49 @@
#pragma once #pragma once
#include "math.hpp"
#include <vector>
namespace basalt::shared::object_loader { 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 { class IObjectLoader {
public: public:
IObjectLoader(); IObjectLoader();
virtual ~IObjectLoader(); virtual ~IObjectLoader();
public:
virtual void load();
const Object& get_object(size_t index) const;
size_t get_object_count() const;
protected: protected:
ObjectLoaderStatus status;
std::vector<Object> objects;
}; };
} // namespace basalt::shared::object_loader } // namespace basalt::shared::object_loader