mirror of
https://github.com/lighttransport/tinyusdz.git
synced 2026-01-18 01:11:17 +01:00
FlexibleReflection experiment.
This commit is contained in:
@@ -216,18 +216,18 @@ struct frame4d {
|
||||
};
|
||||
|
||||
struct quath {
|
||||
half3 imag;
|
||||
half real;
|
||||
half3 imag;
|
||||
};
|
||||
|
||||
struct quatf {
|
||||
float3 imag;
|
||||
float real;
|
||||
float3 imag;
|
||||
};
|
||||
|
||||
struct quatd {
|
||||
double3 imag;
|
||||
double real;
|
||||
double3 imag;
|
||||
};
|
||||
|
||||
struct vector3h {
|
||||
@@ -828,15 +828,75 @@ std::ostream &operator<<(std::ostream &os, const double2 &v);
|
||||
std::ostream &operator<<(std::ostream &os, const double3 &v);
|
||||
std::ostream &operator<<(std::ostream &os, const double4 &v);
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const normal3h &v);
|
||||
std::ostream &operator<<(std::ostream &os, const normal3f &v);
|
||||
std::ostream &operator<<(std::ostream &os, const normal3d &v);
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const vector3h &v);
|
||||
std::ostream &operator<<(std::ostream &os, const vector3f &v);
|
||||
std::ostream &operator<<(std::ostream &os, const vector3d &v);
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const point3h &v);
|
||||
std::ostream &operator<<(std::ostream &os, const point3f &v);
|
||||
std::ostream &operator<<(std::ostream &os, const point3d &v);
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const color3f &v);
|
||||
std::ostream &operator<<(std::ostream &os, const color3d &v);
|
||||
std::ostream &operator<<(std::ostream &os, const color4f &v);
|
||||
std::ostream &operator<<(std::ostream &os, const color4d &v);
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const texcoord2h &v);
|
||||
std::ostream &operator<<(std::ostream &os, const texcoord2f &v);
|
||||
std::ostream &operator<<(std::ostream &os, const texcoord2d &v);
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const texcoord3h &v);
|
||||
std::ostream &operator<<(std::ostream &os, const texcoord3f &v);
|
||||
std::ostream &operator<<(std::ostream &os, const texcoord3d &v);
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const quath &v);
|
||||
std::ostream &operator<<(std::ostream &os, const quatf &v);
|
||||
std::ostream &operator<<(std::ostream &os, const quatd &v);
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const dict &v);
|
||||
std::ostream &operator<<(std::ostream &os, const TimeSample &ts);
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const any_value &v);
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const matrix2d &v);
|
||||
std::ostream &operator<<(std::ostream &os, const matrix3d &v);
|
||||
std::ostream &operator<<(std::ostream &os, const matrix4d &v);
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const matrix2d &v) {
|
||||
os << "(";
|
||||
os << "(" << v.m[0][0] << ", " << v.m[0][1] << "), ";
|
||||
os << "(" << v.m[1][0] << ", " << v.m[1][1] << ")";
|
||||
os << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const matrix3d &v) {
|
||||
os << "(";
|
||||
os << "(" << v.m[0][0] << ", " << v.m[0][1] << ", " << v.m[0][2] << "), ";
|
||||
os << "(" << v.m[1][0] << ", " << v.m[1][1] << ", " << v.m[1][2] << ")";
|
||||
os << "(" << v.m[2][0] << ", " << v.m[2][1] << ", " << v.m[2][2] << ")";
|
||||
os << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const matrix4d &v) {
|
||||
os << "(";
|
||||
os << "(" << v.m[0][0] << ", " << v.m[0][1] << ", " << v.m[0][2] << ", "
|
||||
<< v.m[0][3] << "), ";
|
||||
os << "(" << v.m[1][0] << ", " << v.m[1][1] << ", " << v.m[1][2] << ", "
|
||||
<< v.m[1][3] << ")";
|
||||
os << "(" << v.m[2][0] << ", " << v.m[2][1] << ", " << v.m[2][2] << ", "
|
||||
<< v.m[2][3] << ")";
|
||||
os << "(" << v.m[3][0] << ", " << v.m[3][1] << ", " << v.m[3][2] << ", "
|
||||
<< v.m[3][3] << ")";
|
||||
os << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const int2 &v) {
|
||||
os << "(" << v[0] << ", " << v[1] << ")";
|
||||
return os;
|
||||
@@ -912,11 +972,89 @@ std::ostream &operator<<(std::ostream &os, const double4 &v) {
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const vector3h &v) {
|
||||
os << "(" << v.x << ", " << v.y << ", " << v.z << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const vector3f &v) {
|
||||
os << "(" << v.x << ", " << v.y << ", " << v.z << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const vector3d &v) {
|
||||
os << "(" << v.x << ", " << v.y << ", " << v.z << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const normal3h &v) {
|
||||
os << "(" << v.x << ", " << v.y << ", " << v.z << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const normal3f &v) {
|
||||
os << "(" << v.x << ", " << v.y << ", " << v.z << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const normal3d &v) {
|
||||
os << "(" << v.x << ", " << v.y << ", " << v.z << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const point3h &v) {
|
||||
os << "(" << v.x << ", " << v.y << ", " << v.z << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const point3f &v) {
|
||||
os << "(" << v.x << ", " << v.y << ", " << v.z << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const point3d &v) {
|
||||
os << "(" << v.x << ", " << v.y << ", " << v.z << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const color3f &v) {
|
||||
os << "(" << v.r << ", " << v.g << ", " << v.b << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const color3d &v) {
|
||||
os << "(" << v.r << ", " << v.g << ", " << v.b << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const color4f &v) {
|
||||
os << "(" << v.r << ", " << v.g << ", " << v.b << ", " << v.a << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const color4d &v) {
|
||||
os << "(" << v.r << ", " << v.g << ", " << v.b << ", " << v.a << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const quath &v) {
|
||||
os << "(" << v.real << ", " << v.imag[0] << ", " << v.imag[1] << ", "
|
||||
<< v.imag[2] << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const quatf &v) {
|
||||
os << "(" << v.real << ", " << v.imag[0] << ", " << v.imag[1] << ", "
|
||||
<< v.imag[2] << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const quatd &v) {
|
||||
os << "(" << v.real << ", " << v.imag[0] << ", " << v.imag[1] << ", "
|
||||
<< v.imag[2] << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
// Simple is_vector
|
||||
template <typename>
|
||||
struct is_vector : std::false_type {};
|
||||
@@ -989,55 +1127,76 @@ std::ostream &operator<<(std::ostream &os, const any_value &v) {
|
||||
// Simple brute-force way..
|
||||
// TODO: Use std::function or some template technique?
|
||||
|
||||
#define BASETYPE_CASE_EXPR(__tid, __ty) \
|
||||
case __tid: { \
|
||||
#define BASETYPE_CASE_EXPR(__ty) \
|
||||
case TypeTrait<__ty>::type_id: { \
|
||||
os << *reinterpret_cast<const __ty *>(v.value()); \
|
||||
break; \
|
||||
}
|
||||
|
||||
#define ARRAY1DTYPE_CASE_EXPR(__tid, __ty) \
|
||||
case __tid + TYPE_ID_1D_ARRAY_BIT: { \
|
||||
#define ARRAY1DTYPE_CASE_EXPR(__ty) \
|
||||
case TypeTrait<std::vector<__ty>>::type_id: { \
|
||||
os << *reinterpret_cast<const std::vector<__ty> *>(v.value()); \
|
||||
break; \
|
||||
}
|
||||
|
||||
#define ARRAY2DTYPE_CASE_EXPR(__tid, __ty) \
|
||||
case __tid + TYPE_ID_2D_ARRAY_BIT: { \
|
||||
#define ARRAY2DTYPE_CASE_EXPR(__ty) \
|
||||
case TypeTrait<std::vector<std::vector<__ty>>>::type_id: { \
|
||||
os << *reinterpret_cast<const std::vector<std::vector<__ty>> *>( \
|
||||
v.value()); \
|
||||
break; \
|
||||
}
|
||||
|
||||
#define CASE_EXR_LIST(__FUNC) \
|
||||
__FUNC(TYPE_ID_HALF, half) \
|
||||
__FUNC(TYPE_ID_HALF2, half2) \
|
||||
__FUNC(TYPE_ID_HALF3, half3) \
|
||||
__FUNC(TYPE_ID_HALF4, half4) \
|
||||
__FUNC(TYPE_ID_INT32, int32_t) \
|
||||
__FUNC(TYPE_ID_UINT32, uint32_t) \
|
||||
__FUNC(TYPE_ID_INT2, int2) \
|
||||
__FUNC(TYPE_ID_INT3, int3) \
|
||||
__FUNC(TYPE_ID_INT4, int4) \
|
||||
__FUNC(TYPE_ID_UINT2, uint2) \
|
||||
__FUNC(TYPE_ID_UINT3, uint3) \
|
||||
__FUNC(TYPE_ID_UINT4, uint4) \
|
||||
__FUNC(TYPE_ID_INT64, int64_t) \
|
||||
__FUNC(TYPE_ID_UINT64, uint64_t) \
|
||||
__FUNC(TYPE_ID_FLOAT, float) \
|
||||
__FUNC(TYPE_ID_FLOAT2, float2) \
|
||||
__FUNC(TYPE_ID_FLOAT3, float3) \
|
||||
__FUNC(TYPE_ID_FLOAT4, float4) \
|
||||
__FUNC(TYPE_ID_DOUBLE, double) \
|
||||
__FUNC(TYPE_ID_DOUBLE2, double2) \
|
||||
__FUNC(TYPE_ID_DOUBLE3, double3) \
|
||||
__FUNC(TYPE_ID_DOUBLE4, double4)
|
||||
#define CASE_EXR_LIST(__FUNC) \
|
||||
__FUNC(token) \
|
||||
__FUNC(std::string) \
|
||||
__FUNC(half) \
|
||||
__FUNC(half2) \
|
||||
__FUNC(half3) \
|
||||
__FUNC(half4) \
|
||||
__FUNC(int32_t) \
|
||||
__FUNC(uint32_t) \
|
||||
__FUNC(int2) \
|
||||
__FUNC(int3) \
|
||||
__FUNC(int4) \
|
||||
__FUNC(uint2) \
|
||||
__FUNC(uint3) \
|
||||
__FUNC(uint4) \
|
||||
__FUNC(int64_t) \
|
||||
__FUNC(uint64_t) \
|
||||
__FUNC(float) \
|
||||
__FUNC(float2) \
|
||||
__FUNC(float3) \
|
||||
__FUNC(float4) \
|
||||
__FUNC(double) \
|
||||
__FUNC(double2) \
|
||||
__FUNC(double3) \
|
||||
__FUNC(double4) \
|
||||
__FUNC(matrix2d) \
|
||||
__FUNC(matrix3d) \
|
||||
__FUNC(matrix4d) \
|
||||
__FUNC(quath) \
|
||||
__FUNC(quatf) \
|
||||
__FUNC(quatd) \
|
||||
__FUNC(normal3h) \
|
||||
__FUNC(normal3f) \
|
||||
__FUNC(normal3d) \
|
||||
__FUNC(vector3h) \
|
||||
__FUNC(vector3f) \
|
||||
__FUNC(vector3d) \
|
||||
__FUNC(point3h) \
|
||||
__FUNC(point3f) \
|
||||
__FUNC(point3d) \
|
||||
__FUNC(color3f) \
|
||||
__FUNC(color3d) \
|
||||
__FUNC(color4f) \
|
||||
__FUNC(color4d)
|
||||
|
||||
switch (v.type_id()) {
|
||||
// no `bool` type for 1D and 2D array
|
||||
BASETYPE_CASE_EXPR(TYPE_ID_BOOL, bool)
|
||||
BASETYPE_CASE_EXPR(bool)
|
||||
|
||||
// no std::vector<dict> and std::vector<std::vector<dict>>, ...
|
||||
BASETYPE_CASE_EXPR(TYPE_ID_DICT, dict)
|
||||
BASETYPE_CASE_EXPR(dict)
|
||||
|
||||
// base type
|
||||
CASE_EXR_LIST(BASETYPE_CASE_EXPR)
|
||||
@@ -1111,6 +1270,120 @@ static bool ReconstructVertrices(const any_value &v, Mesh &mesh) {
|
||||
|
||||
namespace staticstruct {
|
||||
|
||||
// -- 00conv
|
||||
|
||||
template <>
|
||||
struct Converter<quath> {
|
||||
typedef std::array<uint16_t, 4> shadow_type;
|
||||
|
||||
static std::unique_ptr<Error> from_shadow(const shadow_type &shadow,
|
||||
quath &value) {
|
||||
memcpy(&value.real, &shadow[0], sizeof(uint16_t) * 4);
|
||||
|
||||
return nullptr; // success
|
||||
}
|
||||
|
||||
static void to_shadow(const quath &value, shadow_type &shadow) {
|
||||
memcpy(&shadow[0], &value.real, sizeof(uint16_t) * 4);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<quatf> {
|
||||
typedef std::array<float, 4> shadow_type;
|
||||
|
||||
static std::unique_ptr<Error> from_shadow(const shadow_type &shadow,
|
||||
quatf &value) {
|
||||
memcpy(&value.real, &shadow[0], sizeof(float) * 4);
|
||||
|
||||
return nullptr; // success
|
||||
}
|
||||
|
||||
static void to_shadow(const quatf &value, shadow_type &shadow) {
|
||||
memcpy(&shadow[0], &value.real, sizeof(float) * 4);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<quatd> {
|
||||
typedef std::array<double, 4> shadow_type;
|
||||
|
||||
static std::unique_ptr<Error> from_shadow(const shadow_type &shadow,
|
||||
quatd &value) {
|
||||
memcpy(&value.real, &shadow[0], sizeof(double) * 4);
|
||||
|
||||
return nullptr; // success
|
||||
}
|
||||
|
||||
static void to_shadow(const quatd &value, shadow_type &shadow) {
|
||||
memcpy(&shadow[0], &value.real, sizeof(double) * 4);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<matrix2d> {
|
||||
typedef std::array<double, 4> shadow_type;
|
||||
|
||||
static std::unique_ptr<Error> from_shadow(const shadow_type &shadow,
|
||||
matrix2d &value) {
|
||||
memcpy(&value.m[0][0], &shadow[0], sizeof(double) * 4);
|
||||
|
||||
return nullptr; // success
|
||||
}
|
||||
|
||||
static void to_shadow(const matrix2d &value, shadow_type &shadow) {
|
||||
memcpy(&shadow[0], &value.m[0][0], sizeof(double) * 4);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<matrix3d> {
|
||||
typedef std::array<double, 9> shadow_type;
|
||||
|
||||
static std::unique_ptr<Error> from_shadow(const shadow_type &shadow,
|
||||
matrix3d &value) {
|
||||
memcpy(&value.m[0][0], &shadow[0], sizeof(double) * 9);
|
||||
|
||||
return nullptr; // success
|
||||
}
|
||||
|
||||
static void to_shadow(const matrix3d &value, shadow_type &shadow) {
|
||||
memcpy(&shadow[0], &value.m[0][0], sizeof(double) * 9);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<matrix4d> {
|
||||
typedef std::array<double, 16> shadow_type;
|
||||
|
||||
static std::unique_ptr<Error> from_shadow(const shadow_type &shadow,
|
||||
matrix4d &value) {
|
||||
memcpy(&value.m[0][0], &shadow[0], sizeof(double) * 16);
|
||||
|
||||
return nullptr; // success
|
||||
}
|
||||
|
||||
static void to_shadow(const matrix4d &value, shadow_type &shadow) {
|
||||
memcpy(&shadow[0], &value.m[0][0], sizeof(double) * 16);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<vector3h> {
|
||||
typedef std::array<uint16_t, 3> shadow_type;
|
||||
|
||||
static std::unique_ptr<Error> from_shadow(const shadow_type &shadow,
|
||||
vector3h &value) {
|
||||
memcpy(&value, &shadow[0], sizeof(uint16_t) * 3);
|
||||
|
||||
return nullptr; // success
|
||||
}
|
||||
|
||||
static void to_shadow(const vector3h &value, shadow_type &shadow) {
|
||||
memcpy(&shadow[0], &value, sizeof(uint16_t) * 3);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<vector3f> {
|
||||
typedef std::array<float, 3> shadow_type;
|
||||
@@ -1130,6 +1403,223 @@ struct Converter<vector3f> {
|
||||
shadow[2] = value.z;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<vector3d> {
|
||||
typedef std::array<double, 3> shadow_type;
|
||||
|
||||
static std::unique_ptr<Error> from_shadow(const shadow_type &shadow,
|
||||
vector3d &value) {
|
||||
value.x = shadow[0];
|
||||
value.y = shadow[1];
|
||||
value.z = shadow[2];
|
||||
|
||||
return nullptr; // success
|
||||
}
|
||||
|
||||
static void to_shadow(const vector3d &value, shadow_type &shadow) {
|
||||
shadow[0] = value.x;
|
||||
shadow[1] = value.y;
|
||||
shadow[2] = value.z;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<normal3h> {
|
||||
typedef std::array<uint16_t, 3> shadow_type;
|
||||
|
||||
static std::unique_ptr<Error> from_shadow(const shadow_type &shadow,
|
||||
normal3h &value) {
|
||||
memcpy(&value, &shadow[0], sizeof(uint16_t) * 3);
|
||||
|
||||
return nullptr; // success
|
||||
}
|
||||
|
||||
static void to_shadow(const normal3h &value, shadow_type &shadow) {
|
||||
memcpy(&shadow[0], &value, sizeof(uint16_t) * 3);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<normal3f> {
|
||||
typedef std::array<float, 3> shadow_type;
|
||||
|
||||
static std::unique_ptr<Error> from_shadow(const shadow_type &shadow,
|
||||
normal3f &value) {
|
||||
value.x = shadow[0];
|
||||
value.y = shadow[1];
|
||||
value.z = shadow[2];
|
||||
|
||||
return nullptr; // success
|
||||
}
|
||||
|
||||
static void to_shadow(const normal3f &value, shadow_type &shadow) {
|
||||
shadow[0] = value.x;
|
||||
shadow[1] = value.y;
|
||||
shadow[2] = value.z;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<normal3d> {
|
||||
typedef std::array<double, 3> shadow_type;
|
||||
|
||||
static std::unique_ptr<Error> from_shadow(const shadow_type &shadow,
|
||||
normal3d &value) {
|
||||
value.x = shadow[0];
|
||||
value.y = shadow[1];
|
||||
value.z = shadow[2];
|
||||
|
||||
return nullptr; // success
|
||||
}
|
||||
|
||||
static void to_shadow(const normal3d &value, shadow_type &shadow) {
|
||||
shadow[0] = value.x;
|
||||
shadow[1] = value.y;
|
||||
shadow[2] = value.z;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<point3h> {
|
||||
typedef std::array<uint16_t, 3> shadow_type;
|
||||
|
||||
static std::unique_ptr<Error> from_shadow(const shadow_type &shadow,
|
||||
point3h &value) {
|
||||
memcpy(&value, &shadow[0], sizeof(uint16_t) * 3);
|
||||
|
||||
return nullptr; // success
|
||||
}
|
||||
|
||||
static void to_shadow(const point3h &value, shadow_type &shadow) {
|
||||
memcpy(&shadow[0], &value, sizeof(uint16_t) * 3);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<point3f> {
|
||||
typedef std::array<float, 3> shadow_type;
|
||||
|
||||
static std::unique_ptr<Error> from_shadow(const shadow_type &shadow,
|
||||
point3f &value) {
|
||||
value.x = shadow[0];
|
||||
value.y = shadow[1];
|
||||
value.z = shadow[2];
|
||||
|
||||
return nullptr; // success
|
||||
}
|
||||
|
||||
static void to_shadow(const point3f &value, shadow_type &shadow) {
|
||||
shadow[0] = value.x;
|
||||
shadow[1] = value.y;
|
||||
shadow[2] = value.z;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<point3d> {
|
||||
typedef std::array<double, 3> shadow_type;
|
||||
|
||||
static std::unique_ptr<Error> from_shadow(const shadow_type &shadow,
|
||||
point3d &value) {
|
||||
value.x = shadow[0];
|
||||
value.y = shadow[1];
|
||||
value.z = shadow[2];
|
||||
|
||||
return nullptr; // success
|
||||
}
|
||||
|
||||
static void to_shadow(const point3d &value, shadow_type &shadow) {
|
||||
shadow[0] = value.x;
|
||||
shadow[1] = value.y;
|
||||
shadow[2] = value.z;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<color3f> {
|
||||
typedef std::array<float, 3> shadow_type;
|
||||
|
||||
static std::unique_ptr<Error> from_shadow(const shadow_type &shadow,
|
||||
color3f &value) {
|
||||
value.r = shadow[0];
|
||||
value.g = shadow[1];
|
||||
value.b = shadow[2];
|
||||
|
||||
return nullptr; // success
|
||||
}
|
||||
|
||||
static void to_shadow(const color3f &value, shadow_type &shadow) {
|
||||
shadow[0] = value.r;
|
||||
shadow[1] = value.g;
|
||||
shadow[2] = value.b;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<color3d> {
|
||||
typedef std::array<double, 3> shadow_type;
|
||||
|
||||
static std::unique_ptr<Error> from_shadow(const shadow_type &shadow,
|
||||
color3d &value) {
|
||||
value.r = shadow[0];
|
||||
value.g = shadow[1];
|
||||
value.b = shadow[2];
|
||||
|
||||
return nullptr; // success
|
||||
}
|
||||
|
||||
static void to_shadow(const color3d &value, shadow_type &shadow) {
|
||||
shadow[0] = value.r;
|
||||
shadow[1] = value.g;
|
||||
shadow[2] = value.b;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<color4f> {
|
||||
typedef std::array<float, 4> shadow_type;
|
||||
|
||||
static std::unique_ptr<Error> from_shadow(const shadow_type &shadow,
|
||||
color4f &value) {
|
||||
value.r = shadow[0];
|
||||
value.g = shadow[1];
|
||||
value.b = shadow[2];
|
||||
value.a = shadow[3];
|
||||
|
||||
return nullptr; // success
|
||||
}
|
||||
|
||||
static void to_shadow(const color4f &value, shadow_type &shadow) {
|
||||
shadow[0] = value.r;
|
||||
shadow[1] = value.g;
|
||||
shadow[2] = value.b;
|
||||
shadow[3] = value.a;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<color4d> {
|
||||
typedef std::array<double, 4> shadow_type;
|
||||
|
||||
static std::unique_ptr<Error> from_shadow(const shadow_type &shadow,
|
||||
color4d &value) {
|
||||
value.r = shadow[0];
|
||||
value.g = shadow[1];
|
||||
value.b = shadow[2];
|
||||
value.a = shadow[2];
|
||||
|
||||
return nullptr; // success
|
||||
}
|
||||
|
||||
static void to_shadow(const color4d &value, shadow_type &shadow) {
|
||||
shadow[0] = value.r;
|
||||
shadow[1] = value.g;
|
||||
shadow[2] = value.b;
|
||||
shadow[3] = value.a;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace staticstruct
|
||||
|
||||
struct AttribMap {
|
||||
@@ -1153,6 +1643,71 @@ class Register {
|
||||
|
||||
staticstruct::Reader r;
|
||||
|
||||
#define CONVERT_TYPE_SCALAR(__ty, __value) \
|
||||
case TypeTrait<__ty>::type_id: { \
|
||||
__ty *p = reinterpret_cast<__ty *>(__value); \
|
||||
staticstruct::Handler<__ty> _h(p); \
|
||||
return _h.write(&handler); \
|
||||
}
|
||||
|
||||
#define CONVERT_TYPE_1D(__ty, __value) \
|
||||
case (TypeTrait<__ty>::type_id | TYPE_ID_1D_ARRAY_BIT): { \
|
||||
std::vector<__ty> *p = reinterpret_cast<std::vector<__ty> *>(__value); \
|
||||
staticstruct::Handler<std::vector<__ty>> _h(p); \
|
||||
return _h.write(&handler); \
|
||||
}
|
||||
|
||||
#define CONVERT_TYPE_2D(__ty, __value) \
|
||||
case (TypeTrait<__ty>::type_id | TYPE_ID_2D_ARRAY_BIT): { \
|
||||
std::vector<std::vector<__ty>> *p = \
|
||||
reinterpret_cast<std::vector<std::vector<__ty>> *>(__value); \
|
||||
staticstruct::Handler<std::vector<std::vector<__ty>>> _h(p); \
|
||||
return _h.write(&handler); \
|
||||
}
|
||||
|
||||
#define CONVERT_TYPE_LIST(__FUNC) \
|
||||
__FUNC(half, v) \
|
||||
__FUNC(half2, v) \
|
||||
__FUNC(half3, v) \
|
||||
__FUNC(half4, v) \
|
||||
__FUNC(int32_t, v) \
|
||||
__FUNC(uint32_t, v) \
|
||||
__FUNC(int2, v) \
|
||||
__FUNC(int3, v) \
|
||||
__FUNC(int4, v) \
|
||||
__FUNC(uint2, v) \
|
||||
__FUNC(uint3, v) \
|
||||
__FUNC(uint4, v) \
|
||||
__FUNC(int64_t, v) \
|
||||
__FUNC(uint64_t, v) \
|
||||
__FUNC(float, v) \
|
||||
__FUNC(float2, v) \
|
||||
__FUNC(float3, v) \
|
||||
__FUNC(float4, v) \
|
||||
__FUNC(double, v) \
|
||||
__FUNC(double2, v) \
|
||||
__FUNC(double3, v) \
|
||||
__FUNC(double4, v) \
|
||||
__FUNC(quath, v) \
|
||||
__FUNC(quatf, v) \
|
||||
__FUNC(quatd, v) \
|
||||
__FUNC(vector3h, v) \
|
||||
__FUNC(vector3f, v) \
|
||||
__FUNC(vector3d, v) \
|
||||
__FUNC(normal3h, v) \
|
||||
__FUNC(normal3f, v) \
|
||||
__FUNC(normal3d, v) \
|
||||
__FUNC(point3h, v) \
|
||||
__FUNC(point3f, v) \
|
||||
__FUNC(point3d, v) \
|
||||
__FUNC(color3f, v) \
|
||||
__FUNC(color3d, v) \
|
||||
__FUNC(color4f, v) \
|
||||
__FUNC(color4d, v) \
|
||||
__FUNC(matrix2d, v) \
|
||||
__FUNC(matrix3d, v) \
|
||||
__FUNC(matrix4d, v)
|
||||
|
||||
bool ret = r.ParseStruct(
|
||||
&h,
|
||||
[&amap](std::string key, uint32_t flags, uint32_t user_type_id,
|
||||
@@ -1170,15 +1725,20 @@ class Register {
|
||||
|
||||
auto &value = amap.attribs[key];
|
||||
if (amap.attribs[key].type_id() == user_type_id) {
|
||||
if (user_type_id == (TYPE_ID_VECTOR3F | TYPE_ID_1D_ARRAY_BIT)) {
|
||||
std::vector<float3> *p =
|
||||
reinterpret_cast<std::vector<float3> *>(value.value());
|
||||
staticstruct::Handler<std::vector<float3>> _h(p);
|
||||
return _h.write(&handler);
|
||||
} else {
|
||||
std::cerr << "Unsupported type: " << GetTypeName(user_type_id)
|
||||
<< "\n";
|
||||
return false;
|
||||
void *v = value.value();
|
||||
|
||||
switch (user_type_id) {
|
||||
CONVERT_TYPE_SCALAR(bool, v)
|
||||
|
||||
CONVERT_TYPE_LIST(CONVERT_TYPE_SCALAR)
|
||||
CONVERT_TYPE_LIST(CONVERT_TYPE_1D)
|
||||
CONVERT_TYPE_LIST(CONVERT_TYPE_2D)
|
||||
|
||||
default: {
|
||||
std::cerr << "Unsupported type: " << GetTypeName(user_type_id)
|
||||
<< "\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::cerr << "type: " << amap.attribs[key].type_name() << "(a.k.a "
|
||||
@@ -1193,6 +1753,11 @@ class Register {
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef CONVERT_TYPE_SCALAR
|
||||
#undef CONVERT_TYPE_1D
|
||||
#undef CONVERT_TYPE_2D
|
||||
#undef CONVERT_TYPE_LIST
|
||||
|
||||
std::string get_error() const { return err_; }
|
||||
|
||||
private:
|
||||
|
||||
4
sandbox/reflection/CMakeLists.txt
Normal file
4
sandbox/reflection/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
project(FlexibleReflection)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
add_executable(FlexibleReflection main.cc Primitives.cpp Reflect.h)
|
||||
59
sandbox/reflection/Primitives.cpp
Normal file
59
sandbox/reflection/Primitives.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#include "Reflect.h"
|
||||
|
||||
namespace reflect {
|
||||
|
||||
//--------------------------------------------------------
|
||||
// A type descriptor for int
|
||||
//--------------------------------------------------------
|
||||
|
||||
struct TypeDescriptor_Int : TypeDescriptor {
|
||||
TypeDescriptor_Int() : TypeDescriptor{"int", sizeof(int)} {
|
||||
}
|
||||
virtual void dump(const void* obj, int /* unused */) const override {
|
||||
std::cout << "int{" << *(const int*) obj << "}";
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
TypeDescriptor* getPrimitiveDescriptor<int>() {
|
||||
static TypeDescriptor_Int typeDesc;
|
||||
return &typeDesc;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------
|
||||
// A type descriptor for float
|
||||
//--------------------------------------------------------
|
||||
|
||||
struct TypeDescriptor_Float : TypeDescriptor {
|
||||
TypeDescriptor_Float() : TypeDescriptor{"float", sizeof(float)} {
|
||||
}
|
||||
virtual void dump(const void* obj, int /* unused */) const override {
|
||||
std::cout << "float{" << *(const float*) obj << "}";
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
TypeDescriptor* getPrimitiveDescriptor<float>() {
|
||||
static TypeDescriptor_Float typeDesc;
|
||||
return &typeDesc;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------
|
||||
// A type descriptor for std::string
|
||||
//--------------------------------------------------------
|
||||
|
||||
struct TypeDescriptor_StdString : TypeDescriptor {
|
||||
TypeDescriptor_StdString() : TypeDescriptor{"std::string", sizeof(std::string)} {
|
||||
}
|
||||
virtual void dump(const void* obj, int /* unused */) const override {
|
||||
std::cout << "std::string{\"" << *(const std::string*) obj << "\"}";
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
TypeDescriptor* getPrimitiveDescriptor<std::string>() {
|
||||
static TypeDescriptor_StdString typeDesc;
|
||||
return &typeDesc;
|
||||
}
|
||||
|
||||
} // namespace reflect
|
||||
21
sandbox/reflection/Reflect.LICENSE
Normal file
21
sandbox/reflection/Reflect.LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Jeff Preshing
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
15
sandbox/reflection/Reflect.README.md
Normal file
15
sandbox/reflection/Reflect.README.md
Normal file
@@ -0,0 +1,15 @@
|
||||
This project presents a small, flexible runtime reflection system using C++11 language features.
|
||||
|
||||
For more information, see the blog series ["A Flexible Reflection System in C++"](http://preshing.com/20180116/a-primitive-reflection-system-in-cpp-part-1).
|
||||
|
||||
## Build Instructions
|
||||
|
||||
[CMake](https://cmake.org/) is required. Quick start:
|
||||
|
||||
$ git clone https://github.com/preshing/FlexibleReflection
|
||||
$ cd FlexibleReflection
|
||||
$ mkdir build
|
||||
$ cd build
|
||||
$ cmake ..
|
||||
|
||||
For detailed build instructions, see ["How to Build a CMake-Based Project"](http://preshing.com/20170511/how-to-build-a-cmake-based-project).
|
||||
161
sandbox/reflection/Reflect.h
Normal file
161
sandbox/reflection/Reflect.h
Normal file
@@ -0,0 +1,161 @@
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cstddef>
|
||||
|
||||
namespace reflect {
|
||||
|
||||
//--------------------------------------------------------
|
||||
// Base class of all type descriptors
|
||||
//--------------------------------------------------------
|
||||
|
||||
struct TypeDescriptor {
|
||||
const char* name;
|
||||
size_t size;
|
||||
|
||||
TypeDescriptor(const char* name, size_t size) : name{name}, size{size} {}
|
||||
virtual ~TypeDescriptor() {}
|
||||
virtual std::string getFullName() const { return name; }
|
||||
virtual void dump(const void* obj, int indentLevel = 0) const = 0;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------
|
||||
// Finding type descriptors
|
||||
//--------------------------------------------------------
|
||||
|
||||
// Declare the function template that handles primitive types such as int, std::string, etc.:
|
||||
template <typename T>
|
||||
TypeDescriptor* getPrimitiveDescriptor();
|
||||
|
||||
// A helper class to find TypeDescriptors in different ways:
|
||||
struct DefaultResolver {
|
||||
template <typename T> static char func(decltype(&T::Reflection));
|
||||
template <typename T> static int func(...);
|
||||
template <typename T>
|
||||
struct IsReflected {
|
||||
enum { value = (sizeof(func<T>(nullptr)) == sizeof(char)) };
|
||||
};
|
||||
|
||||
// This version is called if T has a static member named "Reflection":
|
||||
template <typename T, typename std::enable_if<IsReflected<T>::value, int>::type = 0>
|
||||
static TypeDescriptor* get() {
|
||||
return &T::Reflection;
|
||||
}
|
||||
|
||||
// This version is called otherwise:
|
||||
template <typename T, typename std::enable_if<!IsReflected<T>::value, int>::type = 0>
|
||||
static TypeDescriptor* get() {
|
||||
return getPrimitiveDescriptor<T>();
|
||||
}
|
||||
};
|
||||
|
||||
// This is the primary class template for finding all TypeDescriptors:
|
||||
template <typename T>
|
||||
struct TypeResolver {
|
||||
static TypeDescriptor* get() {
|
||||
return DefaultResolver::get<T>();
|
||||
}
|
||||
};
|
||||
|
||||
//--------------------------------------------------------
|
||||
// Type descriptors for user-defined structs/classes
|
||||
//--------------------------------------------------------
|
||||
|
||||
struct TypeDescriptor_Struct : TypeDescriptor {
|
||||
struct Member {
|
||||
const char* name;
|
||||
size_t offset;
|
||||
TypeDescriptor* type;
|
||||
};
|
||||
|
||||
std::vector<Member> members;
|
||||
|
||||
TypeDescriptor_Struct(void (*init)(TypeDescriptor_Struct*)) : TypeDescriptor{nullptr, 0} {
|
||||
init(this);
|
||||
}
|
||||
TypeDescriptor_Struct(const char* name, size_t size, const std::initializer_list<Member>& init) : TypeDescriptor{nullptr, 0}, members{init} {
|
||||
}
|
||||
virtual void dump(const void* obj, int indentLevel) const override {
|
||||
std::cout << name << " {" << std::endl;
|
||||
for (const Member& member : members) {
|
||||
std::cout << std::string(4 * (indentLevel + 1), ' ') << member.name << " = ";
|
||||
member.type->dump((char*) obj + member.offset, indentLevel + 1);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
std::cout << std::string(4 * indentLevel, ' ') << "}";
|
||||
}
|
||||
};
|
||||
|
||||
#define REFLECT() \
|
||||
friend struct reflect::DefaultResolver; \
|
||||
static reflect::TypeDescriptor_Struct Reflection; \
|
||||
static void initReflection(reflect::TypeDescriptor_Struct*);
|
||||
|
||||
#define REFLECT_STRUCT_BEGIN(type) \
|
||||
reflect::TypeDescriptor_Struct type::Reflection{type::initReflection}; \
|
||||
void type::initReflection(reflect::TypeDescriptor_Struct* typeDesc) { \
|
||||
using T = type; \
|
||||
typeDesc->name = #type; \
|
||||
typeDesc->size = sizeof(T); \
|
||||
typeDesc->members = {
|
||||
|
||||
#define REFLECT_STRUCT_MEMBER(name) \
|
||||
{#name, offsetof(T, name), reflect::TypeResolver<decltype(T::name)>::get()},
|
||||
|
||||
#define REFLECT_STRUCT_END() \
|
||||
}; \
|
||||
}
|
||||
|
||||
//--------------------------------------------------------
|
||||
// Type descriptors for std::vector
|
||||
//--------------------------------------------------------
|
||||
|
||||
struct TypeDescriptor_StdVector : TypeDescriptor {
|
||||
TypeDescriptor* itemType;
|
||||
size_t (*getSize)(const void*);
|
||||
const void* (*getItem)(const void*, size_t);
|
||||
|
||||
template <typename ItemType>
|
||||
TypeDescriptor_StdVector(ItemType*)
|
||||
: TypeDescriptor{"std::vector<>", sizeof(std::vector<ItemType>)},
|
||||
itemType{TypeResolver<ItemType>::get()} {
|
||||
getSize = [](const void* vecPtr) -> size_t {
|
||||
const auto& vec = *(const std::vector<ItemType>*) vecPtr;
|
||||
return vec.size();
|
||||
};
|
||||
getItem = [](const void* vecPtr, size_t index) -> const void* {
|
||||
const auto& vec = *(const std::vector<ItemType>*) vecPtr;
|
||||
return &vec[index];
|
||||
};
|
||||
}
|
||||
virtual std::string getFullName() const override {
|
||||
return std::string("std::vector<") + itemType->getFullName() + ">";
|
||||
}
|
||||
virtual void dump(const void* obj, int indentLevel) const override {
|
||||
size_t numItems = getSize(obj);
|
||||
std::cout << getFullName();
|
||||
if (numItems == 0) {
|
||||
std::cout << "{}";
|
||||
} else {
|
||||
std::cout << "{" << std::endl;
|
||||
for (size_t index = 0; index < numItems; index++) {
|
||||
std::cout << std::string(4 * (indentLevel + 1), ' ') << "[" << index << "] ";
|
||||
itemType->dump(getItem(obj, index), indentLevel + 1);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
std::cout << std::string(4 * indentLevel, ' ') << "}";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Partially specialize TypeResolver<> for std::vectors:
|
||||
template <typename T>
|
||||
class TypeResolver<std::vector<T>> {
|
||||
public:
|
||||
static TypeDescriptor* get() {
|
||||
static TypeDescriptor_StdVector typeDesc{(T*) nullptr};
|
||||
return &typeDesc;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace reflect
|
||||
32
sandbox/reflection/main.cc
Normal file
32
sandbox/reflection/main.cc
Normal file
@@ -0,0 +1,32 @@
|
||||
#include <vector>
|
||||
#include "Reflect.h"
|
||||
|
||||
struct Node {
|
||||
std::string key;
|
||||
int value;
|
||||
float fval;
|
||||
std::vector<Node> children;
|
||||
|
||||
REFLECT() // Enable reflection for this type
|
||||
};
|
||||
|
||||
int main() {
|
||||
// Create an object of type Node
|
||||
Node node = {"apple", 3, 1.0f, {{"banana", 7, 3.0f, {}}, {"cherry", 11, 4.2f, {}}}};
|
||||
|
||||
// Find Node's type descriptor
|
||||
reflect::TypeDescriptor* typeDesc = reflect::TypeResolver<Node>::get();
|
||||
|
||||
// Dump a description of the Node object to the console
|
||||
typeDesc->dump(&node);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Define Node's type descriptor
|
||||
REFLECT_STRUCT_BEGIN(Node)
|
||||
REFLECT_STRUCT_MEMBER(key)
|
||||
REFLECT_STRUCT_MEMBER(value)
|
||||
REFLECT_STRUCT_MEMBER(fval)
|
||||
REFLECT_STRUCT_MEMBER(children)
|
||||
REFLECT_STRUCT_END()
|
||||
Reference in New Issue
Block a user