AnimEngine
MaterialAttribute.hpp
1 #pragma once
2 #ifndef KJY_OBJECT_ORIENTED_OPENGL_MATERIAL_ATTRIBUTE_HPP_
3 #define KJY_OBJECT_ORIENTED_OPENGL_MATERIAL_ATTRIBUTE_HPP_
4 
5 #include <glm/glm.hpp>
6 #include <glm/gtc/type_ptr.hpp>
7 #include <glad/glad.h>
8 #include <cstdint>
9 #include <cassert>
10 #include <vector>
11 #include <cstdio>
12 #include <stdexcept>
13 #include "../GLobjects/Texture.hpp"
14 
15 /* Check if given template parameter is a glm vector type using SFINAE. See docs for std::void_t and SFINAE.*/
16 template<typename, typename = std::void_t<>, typename = std::void_t<>>
17 struct is_glm_vector : std::false_type{};
18 
19 /* Check if given template parameter is a glm matrix type using SFINAE. See docs for std::void_t and SFINAE.*/
20 template<typename T>
21 struct is_glm_vector<T, std::void_t<typename T::value_type>, std::void_t<typename T::length_type>> : std::true_type{};
22 
23 /* Check if given template parameter is a glm vector type using SFINAE. See docs for std::void_t and SFINAE.*/
24 template<typename, typename = std::void_t<>, typename = std::void_t<>>
25 struct is_glm_matrix : std::false_type{};
26 
27 /* Check if given template parameter is a glm matrix type using SFINAE. See docs for std::void_t and SFINAE.*/
28 template<typename T>
29 struct is_glm_matrix<T, std::void_t<typename T::col_type>, std::void_t<typename T::row_type>> : std::true_type{};
30 
31 namespace OOOGL{
32 
33 /* 0 0000 000
34  * (1)^ (2)^ (3)^
35  *
36  * 1: Unused
37  * 2: Dimension Type (e.g scalar vs vec3 vs mat4...)
38  * 3: Component Type (e.g float vs bool, vs double...)
39  */
41  const unsigned char dim_shift = 4;
42  const unsigned char component_type_mask = 0x03;
43  const unsigned char dimension_type_mask = 0xF << dim_shift;
44 
45  const unsigned char a_floating = 0x00;
46  const unsigned char a_integral = 0x01;
47  const unsigned char a_boolean = 0x02;
48  const unsigned char a_double = 0x03;
49  const unsigned char a_unsigned = 0x04;
50  const unsigned char a_opaque = 0x08;
51 
52  const unsigned char a_scalar = 0x01 << dim_shift;
53  const unsigned char a_vec2 = 0x02 << dim_shift;
54  const unsigned char a_vec3 = 0x03 << dim_shift;
55  const unsigned char a_vec4 = 0x04 << dim_shift;
56 
57  const unsigned char a_mat2 = 0x05 << dim_shift;
58  const unsigned char a_mat3 = 0x06 << dim_shift;
59  const unsigned char a_mat4 = 0x07 << dim_shift;
60  const unsigned char a_tex = 0x08 << dim_shift;
61 
62 };
63 const static _MatAttribType MatAttribType;
64 
65 
66 
68  public:
69 
70  MaterialAttribute(bool value) : MaterialAttribute((GLboolean) value) {}
71  MaterialAttribute(GLint value) : _attrib_type(MatAttribType.a_integral | MatAttribType.a_scalar) {memcpy(&_scalar, &value, sizeof(uint64_t));}
72  MaterialAttribute(GLdouble value) : _attrib_type(MatAttribType.a_double | MatAttribType.a_scalar) {memcpy(&_scalar, &value, sizeof(uint64_t));}
73  explicit MaterialAttribute(GLuint value) : _attrib_type(MatAttribType.a_integral | MatAttribType.a_unsigned | MatAttribType.a_scalar) {memcpy(&_scalar, &value, sizeof(uint64_t));}
74  explicit MaterialAttribute(GLfloat value) : _attrib_type(MatAttribType.a_floating | MatAttribType.a_scalar) {memcpy(&_scalar, &value, sizeof(uint64_t));}
75  explicit MaterialAttribute(GLboolean value) : _attrib_type(MatAttribType.a_boolean | MatAttribType.a_scalar) {memcpy(&_scalar, &value, sizeof(uint64_t));}
76  explicit MaterialAttribute(SimpleTexture2D tex) : _attrib_type(MatAttribType.a_tex | MatAttribType.a_opaque), _tex(tex) {}
77  explicit MaterialAttribute(const OptionalSimpleTexture2D& tex) : _attrib_type(MatAttribType.a_tex | MatAttribType.a_opaque), _tex(tex) {}
78 
79 
80  template<typename GenericT>
81  explicit MaterialAttribute(const GenericT& value){
82  using value_type = typename GenericT::value_type;
83  unsigned char component_type = ~0;
84  static_assert(std::is_fundamental<value_type>::value);
85  if constexpr(std::is_same<value_type, bool>::value){
86  component_type = MatAttribType.a_boolean;
87  }else if constexpr(std::is_integral<value_type>::value){
88  component_type = MatAttribType.a_integral | ((std::is_unsigned<value_type>::value && std::is_same<value_type, bool>::value) ? MatAttribType.a_unsigned : 0);
89  }else if constexpr(std::is_same<value_type, glm::f64>::value){
90  component_type = MatAttribType.a_double;
91  }else if constexpr(std::is_same<value_type, glm::f32>::value){
92  component_type = MatAttribType.a_floating;
93  }else{
94  fprintf(stderr, "Error: Generic type given for MaterialArgument has an unexpected value_type");
95  assert(false);
96  }
97 
98  if constexpr(is_glm_vector<GenericT>::value){
99  unsigned char dimension_type = ((MatAttribType.a_scalar >> MatAttribType.dim_shift) + GenericT::length()-1) << MatAttribType.dim_shift;
100  _attrib_type = component_type | dimension_type;
101  }else if constexpr(is_glm_matrix<GenericT>::value){
102  static_assert(std::is_same<GenericT, typename GenericT::transpose_type>::value); // Assert that this matrix is square
103  unsigned char dimension_type = ((MatAttribType.a_mat2 >> MatAttribType.dim_shift) + GenericT::length()-2) << MatAttribType.dim_shift;
104  _attrib_type = component_type | dimension_type;
105  }else{
106  fprintf(stderr, "Error: Generic type given for Material attribute must be a glm 'vec' or 'mat'");
107  assert(false);
108  }
109 
110  _data.resize(sizeof(GenericT));
111  memcpy(_data.data(), glm::value_ptr(value), sizeof(GenericT));
112  }
113 
114 
115  template<typename GenericT>
116  GenericT getValue() const{
117  GenericT value;
118  getValue<GenericT>(value);
119  return(value);
120  }
121 
122  template<typename GenericT>
123  void getValue(GenericT& value_out) const{
124  if constexpr(is_glm_vector<GenericT>::value){
125  memcpy(&value_out[0], _data.data(), sizeof(GenericT));
126  return;
127  }else if constexpr(is_glm_matrix<GenericT>::value){
128  memcpy(&value_out[0][0], _data.data(), sizeof(GenericT));
129  return;
130  }else{
131  // Specialization is not working for some reason, so we have to hail mary here.
132  _getScalarValue(value_out);
133  return;
134  }
135  throw std::runtime_error("MaterialAttribute getValue<" + std::string(typeid(GenericT).name()) + ">() executed unusually and reached a point which should be unreachable");
136  }
137 
138  OptionalSimpleTexture2D getTexture() const {return(_tex);}
139 
140  bool typeEquals(const MaterialAttribute& other) const {return(this->_attrib_type == other._attrib_type);}
141 
142  bool isUnsigned() const {return((_attrib_type & MatAttribType.a_unsigned) == MatAttribType.a_unsigned);}
143  bool isBoolean() const {return((_attrib_type & MatAttribType.component_type_mask) == MatAttribType.a_boolean);}
144  bool isIntegral() const {return((_attrib_type & MatAttribType.component_type_mask) == MatAttribType.a_integral);}
145  bool isFloat32() const {return((_attrib_type & MatAttribType.component_type_mask) == MatAttribType.a_floating && ((_attrib_type & MatAttribType.a_opaque) == 0));}
146  bool isFloat64() const {return((_attrib_type & MatAttribType.component_type_mask) == MatAttribType.a_double);}
147  bool isOpaque() const {return((_attrib_type & MatAttribType.a_opaque) == MatAttribType.a_opaque);}
148  bool isScalar() const {return((_attrib_type & MatAttribType.dimension_type_mask) == MatAttribType.a_scalar);}
149  bool isVec2() const {return((_attrib_type & MatAttribType.dimension_type_mask) == MatAttribType.a_vec2);}
150  bool isVec3() const {return((_attrib_type & MatAttribType.dimension_type_mask) == MatAttribType.a_vec3);}
151  bool isVec4() const {return((_attrib_type & MatAttribType.dimension_type_mask) == MatAttribType.a_vec4);}
152  bool isMat2() const {return((_attrib_type & MatAttribType.dimension_type_mask) == MatAttribType.a_mat2);}
153  bool isMat3() const {return((_attrib_type & MatAttribType.dimension_type_mask) == MatAttribType.a_mat3);}
154  bool isMat4() const {return((_attrib_type & MatAttribType.dimension_type_mask) == MatAttribType.a_mat4);}
155  bool isTex() const {return((_attrib_type & MatAttribType.dimension_type_mask) == MatAttribType.a_tex);}
156 
157  private:
158 
159  template<typename GenericT>
160  void _getScalarValue(GenericT& value_out) const{
161  memcpy(&value_out, &_scalar, sizeof(GenericT));
162  }
163 
164  uint64_t _scalar;
165  std::vector<uint8_t> _data;
167 
168  unsigned char _attrib_type;
169 };
170 
171 
172 }
173 
174 #endif
Definition: Texture.hpp:60
Definition: MaterialAttribute.hpp:40
Definition: MaterialAttribute.hpp:17
Definition: MaterialAttribute.hpp:67
Definition: Core_Utilities.cpp:3
Definition: MaterialAttribute.hpp:25