diff --git a/engine/3rdparty/ylt/include/parray.h b/engine/3rdparty/ylt/include/parray.h new file mode 100644 index 0000000..df1a4fb --- /dev/null +++ b/engine/3rdparty/ylt/include/parray.h @@ -0,0 +1,59 @@ +#pragma once +#include +template + requires requires {typename P::UClass;} +class parray { + using UClass = P::UClass; +protected: + uint32_t t_size; + uint32_t m_size; + uint32_t m_head{ 0 }; + char* m_buf; + UClass* u_class; +public: + ~parray() { + if (m_buf) { + free(m_buf); + } + } + parray(uint32_t tsize, uint32_t size, UClass* uclass) + : t_size(tsize), m_buf((char*)malloc(tsize* size)), m_size(size),u_class(uclass) {} + parray(parray& other) noexcept { + m_size = other.m_size; + m_head = other.m_head; + m_buf = other.m_buf; + other.m_buf = nullptr; + } + void* data() { + return m_buf; + } + uint32_t size() { + return m_head; + } + uint32_t data_size() { + return t_size * m_head; + }; + P* at(int i){ + if (i >= m_head) { + return nullptr; + } + return (P*)(m_buf + i * t_size); + }; +}; +template + requires std::is_base_of::value && requires {typename P::UClass; } +class ptarray : public parray

{ + using parray

::m_head; + using parray

::m_size; + using parray

::m_buf; + using parray

::t_size; +public: + ptarray(uint32_t size = 1) : parray

(sizeof(T), size, new T::UClass()) {} + void push_back(T& t) { + if (m_head >= m_size) { + return; + } + *(T*)(m_buf + m_head * t_size) = t; + m_head++; + }; +}; \ No newline at end of file diff --git a/engine/3rdparty/ylt/include/struct_member.h b/engine/3rdparty/ylt/include/struct_member.h new file mode 100644 index 0000000..e69de29 diff --git a/engine/3rdparty/ylt/include/template.h b/engine/3rdparty/ylt/include/template.h new file mode 100644 index 0000000..367acac --- /dev/null +++ b/engine/3rdparty/ylt/include/template.h @@ -0,0 +1,80 @@ +#include +#include +using namespace std; +using namespace struct_pack; +using UniversalVectorType = detail::UniversalVectorType; +using UniversalType = detail::UniversalType; +using UniversalOptionalType = detail::UniversalOptionalType; +using UniversalIntegralType = detail::UniversalIntegralType; +using UniversalNullptrType = detail::UniversalNullptrType; +using UniversalCompatibleType = detail::UniversalCompatibleType; + +/* +获取对象成员数量 +*/ +template +struct is_constructable_impl : std::false_type {}; + +template +struct is_constructable_impl < T, construct_param_t, + std::void_t< + decltype(T{ {Args{}}..., {construct_param_t{}} }) > , Args... > + : std::true_type {}; + +template +constexpr bool is_constructable = is_constructable_impl::value; + +template +constexpr std::size_t members_count_impl() { + if constexpr (is_constructable) { + return members_count_impl(); + } + else if constexpr (is_constructable) { + cout << "is_constructable UniversalType \n"; + return members_count_impl(); + } + return sizeof...(Args); +} +/* + 获取成员类型 +*/ +template +concept type_string = requires(Type container) { + requires detail::is_char_t::value_type>; +container.length(); +container.data(); +}; + +template +concept type_struct = requires(Type container) { + requires std::is_class_v; +}; + +template +concept type_u32 = requires(Type container) { + requires sizeof(Type) == 4; +}; +/* +获取成员信息 +*/ +template +constexpr void visit_one_member_info(T& item) { + constexpr auto id = detail::get_type_id(); + cout << "visit_one_member_info::" << (int)id << "=" << item << "\n"; +} +template +void visit_member_info(Args&...args) { + cout << "visit_member_info::" << sizeof...(args) << "\n"; + (visit_one_member_info(args), ...); +} +template +void visit_struct_info(T& item) { + int count = members_count_impl(); + auto visitor = [](auto&&... items) { + visit_member_info<>(items...); + }; + if (count == 4) { + auto&& [a1, a2, a3, a4] = item; + visitor(a1, a2, a3, a4); + } +} \ No newline at end of file diff --git a/engine/3rdparty/ylt/include/vertex.h b/engine/3rdparty/ylt/include/vertex.h new file mode 100644 index 0000000..8f82162 --- /dev/null +++ b/engine/3rdparty/ylt/include/vertex.h @@ -0,0 +1,52 @@ +#pragma once +#include +#include +#include +using namespace std; +#define sizeof_field(_struct, _field) sizeof(((_struct*)0)->_field) +// 顶点最多关联4个骨骼 +#define MAX_NUM_BONES_PER_VERTEX 4 +struct Vector2 { + float x; + float y; +}; +struct Vector3 { + float x; + float y; + float z; +}; +struct Vertex { + struct UClass { + virtual void BindLayout() = 0; + }; +}; +struct PosVertex : public Vertex { + Vector3 Position = {}; + struct UClass : public Vertex::UClass{ + int MemCount = 1; + tuple Position{sizeof_field(PosVertex, Position), offsetof(PosVertex, Position)}; + + virtual void BindLayout() {}; + }; +}; + +struct TexVertex : public Vertex { + Vector3 Position = {}; + Vector3 Normal = {}; + Vector2 TexCoords = {}; +}; +struct BoneVertex : public Vertex +{ + Vector3 Position = {}; + Vector2 TexCoords = {}; + Vector3 Normal = {}; + Vector3 Tangent = {}; + // 骨骼蒙皮数据 + float Weights[MAX_NUM_BONES_PER_VERTEX] = {}; + uint32_t BoneIDs[MAX_NUM_BONES_PER_VERTEX] = {}; + + void AddBoneData(uint32_t boneID, float weight) {}; +}; + + + diff --git a/engine/3rdparty/ylt/test/struct_pack.cpp b/engine/3rdparty/ylt/test/struct_pack.cpp index 5a120e6..6264def 100644 --- a/engine/3rdparty/ylt/test/struct_pack.cpp +++ b/engine/3rdparty/ylt/test/struct_pack.cpp @@ -1,58 +1,85 @@ #include -#include -using namespace std; -using namespace struct_pack; -using UniversalVectorType = detail::UniversalVectorType; -using UniversalType = detail::UniversalType; -using UniversalOptionalType = detail::UniversalOptionalType; -using UniversalIntegralType = detail::UniversalIntegralType; -using UniversalNullptrType = detail::UniversalNullptrType; -using UniversalCompatibleType = detail::UniversalCompatibleType; +#include "template.h" struct person { int64_t id; std::string name; int age; double salary; }; -template -struct is_constructable_impl : std::false_type {}; - -template -struct is_constructable_impl < T, construct_param_t, - std::void_t< - decltype(T{ {Args{}}..., {construct_param_t{}} }) > , Args... > - : std::true_type {}; - -template -bool is_constructable = is_constructable_impl::value; - -template -std::size_t members_count_impl() { - if (is_constructable) { - cout << "is_constructable UniversalVectorType \n"; - //return members_count_impl(); - } - else if (is_constructable) { - cout << "is_constructable UniversalType \n"; - //return members_count_impl(); +//STRUCT_PACK_REFL(person, ID, name, age); +inline person& STRUCT_PACK_REFL_FLAG(person& t) { + return t; +} +template constexpr std::size_t STRUCT_PACK_FIELD_COUNT_IMPL(); +template<> constexpr std::size_t STRUCT_PACK_FIELD_COUNT_IMPL() { + return 3; +} +inline decltype(auto) STRUCT_PACK_FIELD_COUNT(const person&) { + return std::integral_constant{}; +} +template auto& STRUCT_PACK_GET(person& c) { + if constexpr (0 == I) { + return c.age; + } if constexpr (1 == I) { + return c.name; + } if constexpr (2 == I) { + return c.ID; } else { - return sizeof...(Args); + static_assert(I < STRUCT_PACK_FIELD_COUNT_IMPL()); } - return sizeof...(Args); -} +} +template const auto& STRUCT_PACK_GET(const person& c) { + if constexpr (0 == I) { + return c.age; + } if constexpr (1 == I) { + return c.name; + } if constexpr (2 == I) { + return c.ID; + } + else { + static_assert(I < STRUCT_PACK_FIELD_COUNT_IMPL()); + } +} +inline auto& STRUCT_PACK_GET_0(person& c) { + return STRUCT_PACK_GET() - 1 - 0>(c); +} +inline auto& STRUCT_PACK_GET_1(person& c) { + return STRUCT_PACK_GET() - 1 - 1>(c); +} +inline auto& STRUCT_PACK_GET_2(person& c) { + return STRUCT_PACK_GET() - 1 - 2>(c); +} +inline const auto& STRUCT_PACK_GET_0(const person& c) { + return STRUCT_PACK_GET() - 1 - 0>(c); +} +inline const auto& STRUCT_PACK_GET_1(const person& c) { + return STRUCT_PACK_GET() - 1 - 1>(c); +} +inline const auto& STRUCT_PACK_GET_2(const person& c) { + return STRUCT_PACK_GET() - 1 - 2>(c); +}; int main() { person person1{ .id = 1, .name = "hello struct pack", .age = 20, .salary = 1024.42 }; using type = remove_cvref_t; - using type2 = remove_cvref_t; - auto Count = members_count; - int isc = members_count_impl(); - int c2 = detail::members_count(); - // 1дл + auto c1 = members_count; + int c2 = members_count_impl(); + int c3 = detail::members_count(); + + auto id = detail::get_type_id(); + auto t1 = type_struct; + auto t2 = type_string; + auto t3 = type_u32; + + visit_struct_info(person1); + visit_member_info<>(person1.name, person1.age); + + auto sz_info = detail::calculate_payload_size(person1); + // 1行代码序列化 vector buffer = serialize(person1); - // ֻлpersonĵ2ֶ + // 只反序列化person的第2个字段 auto name = get_field(buffer.data(), buffer.size()); - cout << "hello " << name.value() << "Count == " << Count << c2; + cout << "hello " << name.value() << "Count == " << c1; } \ No newline at end of file diff --git a/engine/3rdparty/ylt/test/vertex_wrap.cpp b/engine/3rdparty/ylt/test/vertex_wrap.cpp new file mode 100644 index 0000000..60f9fb1 --- /dev/null +++ b/engine/3rdparty/ylt/test/vertex_wrap.cpp @@ -0,0 +1,35 @@ +#include +#include +#include +#include "vertex.h" +#include "parray.h" + +//方案一,使用静态变量存储数据 +//方案二,模板元编程,传递数据 +int main() { + cout << "std::is_aggregate_v = "<< is_aggregate_v << endl; + cout << "std::is_aggregate_v = "<< is_aggregate_v << endl; + cout << "std::is_aggregate_v = "<< is_aggregate_v << endl; + float x1 = 1.0, x2 = 2.0, x3 = 3.0; + PosVertex p; + TexVertex t; + BoneVertex b; + ptarray vertices(10); + //ptarray vertices2(10); + vertices.push_back(p); + parray pv = vertices; + + auto Position = make_tuple(1, 2, 3); + + auto pv0 = *(PosVertex*)pv.at(0); + //vertices.push_back(t); + cout<< "sizeof " << sizeof(p) << "," << sizeof(t) << "," << sizeof(b)<<"\n"; + //auto r1 = b.BindLayout(); + //auto r2 = t.BindLayout(); + //auto r3 = p.BindLayout(); + //cout << "vector " << get<0>(r1[0]) << "," << get<0>(r2[0]) << "," << get<0>(r3[0]) << "\n"; +} + + + + diff --git a/engine/3rdparty/ylt/xmake.lua b/engine/3rdparty/ylt/xmake.lua index 4e74fe9..7708444 100644 --- a/engine/3rdparty/ylt/xmake.lua +++ b/engine/3rdparty/ylt/xmake.lua @@ -5,8 +5,16 @@ package("ylt") on_install(function (package) os.cp("include", package:installdir()) end) +-- target("ylt_struct_pack") +-- set_kind("binary") +-- add_packages("ylt") +-- add_includedirs("include") +-- add_headerfiles("include/*.h") +-- add_files("test/struct_pack.cpp") -target("ylt_struct_pack") +target("ylt_vertex_wrap") set_kind("binary") add_packages("ylt") - add_files("test/struct_pack.cpp") \ No newline at end of file + add_includedirs("include") + add_headerfiles("include/*.h") + add_files("test/vertex_wrap.cpp") \ No newline at end of file