Advertisement
Guest User

Untitled

a guest
Apr 19th, 2015
202
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.53 KB | None | 0 0
  1. /*
  2. Fiddlings:
  3.  
  4. * Whitespace:
  5. - using 0, single or double spacing to make things easier to read, e.g.
  6. static constexpr unsigned int var = bytes_internal<N-1,T>::var + type_at<N-1>::dim * sizeof(typename type_at<N-1>::type);
  7.  
  8. - using 0, single or double vertical (linebreak) spacing, again to separate out things
  9. e.g. clumping a recursion template together with its terminator
  10.  
  11. - alignment
  12. - etc. I whitespace freestyle while I try to figure out code (whatever increases clarity), hope it isn't annoying..
  13.  
  14. * Removing redundant ( ) for integer template parameters
  15.  
  16. * Simplified a couple of recursion terminators (so they quit on -1 rather than 0, and are empty rather than copying the main template)
  17.  
  18. I wonder whether it may be simpler to allow:
  19. SetVertexAttribs< float, 4, int, 2, double, 3 >();
  20. rather than:
  21. SetVertexAttribs<Vec<float, 4>, Vec<int, 2>, vec<double, 3>>();
  22. π
  23. */
  24.  
  25. //Ok, here is my implementation.
  26. //
  27. //It's inline&template-only, so you should put it in a header.
  28. //
  29. //Keep in mind that it expects that locations of vertex attribs are specified in a shader with `layout(location = ..)` and start with 0 (then 1,2,3...).
  30. //
  31. //<hr>
  32. //Features:
  33. //
  34. //**Attribute setup:**
  35.  
  36. SetVertexAttribs<Vec<float, 4>, Vec<int, 2>, vec<double, 3>>();
  37.  
  38. // It enables attrib arrays (here: 0, 1 and 2), and then sets attrib pointers for them.
  39. // It also selects correct glVertexAttrib{|I|L}Pointer function depending on type of each parametr.
  40.  
  41. //**Class Vec:**
  42.  
  43. Vec<float, 4> a {1, 2, 3, 4}, b;
  44. // First parametr can be any type. Second parametr is
  45. // number of objects of that type in the vector.
  46. // First parametr can be any default scalar type.
  47. // Second parametr can only be 1, 2, 3 or 4.
  48. //
  49. // Warning: vectors can have padding, so don't use them for model storage. (Usually they don't have it, but it's better to be careful.)
  50.  
  51. a.x = 2; // you can use .x or .r - they have same meaning
  52. a.y = 3; // you can use .y or .g - they have same meaning
  53. a.z = 4; // you can use .z or .b - they have same meaning
  54. a.w = 4; // you can use .w or .a - they have same meaning
  55. a = a + a - a + -a; // Overloaded operators
  56. a = {1, 2, 3, 4}; b = a; // Overloaded assignment
  57. a += {0, 1, 2, 3}; b += a;
  58. a -= {0, 1, 0, 1}; b -= a;
  59.  
  60. Vec<float, 4>::type var; // here means `float var;`
  61. // Vec<...>::type means type of a single element
  62. std::cout << a.dim; // here prints 4 -- number of dimensions of a vector
  63.  
  64. //**Class AttribLayout:**
  65. //
  66. //Arrays of this type are useful for storing models.
  67.  
  68. AttribLayout<Vec<float, 4>, Vec<int, 2>, Vec<double, 3>>
  69. obj1, obj2({0,0,0,0},{1,2},{10,20,30}); // Constructors
  70. // This class uses trick with char array - don't worry about padding, it does not have it.
  71.  
  72. std::cout << obj1.elements; // Here prints 3 -- number of vectors in layout
  73. std::cout << obj1.byte_len; // Same as `sizeof obj1`
  74.  
  75. Vec<int, 2> var = obj1.get<1>(); // Returns vector with a specific number in a layout
  76. double dvar = obj2.get<2,1>; // Here dvar == 20. First parametr means number of vector in a layout, second parametr means number of element in a vector.
  77.  
  78. obj1.set<1>({1,2}); // Parametrs mean same things as in `get()`.
  79. obj1.set<2,0>(0.0); // I think you understood what `set()` does.
  80.  
  81. AttribLayout<Vec<float, 4>, Vec<int, 2>, vec<double, 3>>::type_at<1> var;
  82. // Here means `Vec<int, 2> var;`
  83.  
  84. //**Useful functions:**
  85.  
  86. type2glconst<int>::value // == GL_INT
  87. // I think you understand what it's for.
  88.  
  89. type2glattribfunc<float> // same as glVertexAttribPointer
  90. type2glattribfunc<double> // same as glVertexAttribLPointer
  91. type2glattribfunc</*any integer type*/> // same as glVertexAttribIPointer
  92.  
  93.  
  94.  
  95.  
  96. //Code:
  97.  
  98. template <typename T>
  99. struct type2glconst
  100. {
  101. static_assert( std::is_same<T, void>::value, "Invalid type!" );
  102. static constexpr GLenum value = 0;
  103. };
  104.  
  105. template <> struct type2glconst<unsigned char> {static constexpr GLenum value = GL_UNSIGNED_BYTE;};
  106. template <> struct type2glconst<signed char> {static constexpr GLenum value = GL_BYTE;};
  107. template <> struct type2glconst<char> {static constexpr GLenum value = Utils::is_char_signed ? GL_BYTE : GL_UNSIGNED_BYTE;};
  108. template <> struct type2glconst<unsigned short> {static constexpr GLenum value = GL_UNSIGNED_SHORT;};
  109. template <> struct type2glconst<signed short> {static constexpr GLenum value = GL_SHORT;};
  110. template <> struct type2glconst<unsigned int> {static constexpr GLenum value = GL_UNSIGNED_INT;};
  111. template <> struct type2glconst<signed int> {static constexpr GLenum value = GL_INT;};
  112. template <> struct type2glconst<float> {static constexpr GLenum value = GL_FLOAT;};
  113. template <> struct type2glconst<double> {static constexpr GLenum value = GL_DOUBLE;};
  114.  
  115.  
  116. template <typename T>
  117. inline void type2glattribfunc(GLuint index, GLint size, GLsizei stride, const GLvoid *pointer) {
  118. static_assert(type2glconst<T>::value, "Invalid type!");
  119. glVertexAttribIPointer( index, size, type2glconst<T>::value, stride, pointer );
  120. }
  121.  
  122. template <>
  123. inline void type2glattribfunc<float>(GLuint index, GLint size, GLsizei stride, const GLvoid *pointer) {
  124. glVertexAttribPointer( index, size, type2glconst<float>::value, GL_FALSE, stride, pointer );
  125. }
  126.  
  127. template <>
  128. inline void type2glattribfunc<double>(GLuint index, GLint size, GLsizei stride, const GLvoid *pointer) {
  129. glVertexAttribLPointer( index, size, type2glconst<double>::value, stride, pointer );
  130. }
  131.  
  132.  
  133. template <typename T, unsigned int D>
  134. struct Vec {
  135. static_assert( (std::is_void<T>::value || type2glconst<T>::value) && D <= 4, "Invalid dimension for vector!" );
  136. static constexpr int dim = 0;
  137. using type = void;
  138. };
  139.  
  140.  
  141. template <typename T>
  142. struct Vec<T, 1> {
  143. using type = T;
  144. static constexpr int dim = 1;
  145. T x;
  146. Vec<T, 1> operator- () const {return {-x};}
  147. Vec<T, 1> operator+ (const Vec<T, 1> &o) const {return {x + o.x};}
  148. Vec<T, 1> operator- (const Vec<T, 1> &o) const {return {x - o.x};}
  149. Vec<T, 1> &operator+=(const Vec<T, 1> &o) {x += o.x; return *this;}
  150. Vec<T, 1> &operator-=(const Vec<T, 1> &o) {x -= o.x; return *this;}
  151. };
  152.  
  153. template <typename T>
  154. struct Vec<T, 2> {
  155. using type = T;
  156. static constexpr int dim = 2;
  157. union {T x, u;};
  158. union {T y, v;};
  159. Vec<T, 2> operator- () const {return {-x, -y};}
  160. Vec<T, 2> operator+ (const Vec<T, 2> &o) const {return {x + o.x, y + o.y};}
  161. Vec<T, 2> operator- (const Vec<T, 2> &o) const {return {x - o.x, y - o.y};}
  162. Vec<T, 2> &operator+=(const Vec<T, 2> &o) {x += o.x; y += o.y; return *this;}
  163. Vec<T, 2> &operator-=(const Vec<T, 2> &o) {x -= o.x; y -= o.y; return *this;}
  164. };
  165.  
  166. template <typename T>
  167. struct Vec<T, 3> {
  168. using type = T;
  169. static constexpr int dim = 3;
  170. union {T x, r;};
  171. union {T y, g;};
  172. union {T z, b;};
  173. Vec<T, 3> operator- () const {return {-x, -y, -z};}
  174. Vec<T, 3> operator+ (const Vec<T, 3> &o) const {return {x + o.x, y + o.y, z + o.z};}
  175. Vec<T, 3> operator- (const Vec<T, 3> &o) const {return {x - o.x, y - o.y, z - o.z};}
  176. Vec<T, 3> operator* (const Vec<T, 3> &o) const {return {y * o.z - z * o.y, z * o.x - x * o.z, x * o.y - y * o.x};}
  177. Vec<T, 3> &operator+=(const Vec<T, 3> &o) {x += o.x; y += o.y; z += o.z; return *this;}
  178. Vec<T, 3> &operator-=(const Vec<T, 3> &o) {x -= o.x; y -= o.y; z -= o.z; return *this;}
  179. Vec<T, 3> &operator*=(const Vec<T, 3> &o) {*this = *this * o; return *this;}
  180. };
  181.  
  182. template <typename T>
  183. struct Vec<T, 4> {
  184. using type = T;
  185. static constexpr int dim = 4;
  186. union {T x, r;};
  187. union {T y, g;};
  188. union {T z, b;};
  189. union {T w, a;};
  190. Vec<T, 4> operator- () const {return {-x, -y, -z, -w};}
  191. Vec<T, 4> operator+ (const Vec<T, 4> &o) const {return {x + o.x, y + o.y, z + o.z, w + o.w};}
  192. Vec<T, 4> operator- (const Vec<T, 4> &o) const {return {x - o.x, y - o.y, z - o.z, w - o.w};}
  193. Vec<T, 4> &operator+=(const Vec<T, 4> &o) {x += o.x; y += o.y; z += o.z; w += o.w; return *this;}
  194. Vec<T, 4> &operator-=(const Vec<T, 4> &o) {x -= o.x; y -= o.y; z -= o.z; w -= o.w; return *this;}
  195. };
  196.  
  197.  
  198. template <typename T, typename ...P>
  199. struct AttribLayout_InternalValue {
  200. static_assert( ! std::is_same<T,void>::value, "Void vector is used in layout!" );
  201. using curtype = T;
  202. };
  203.  
  204. template <typename T, typename ...P>
  205. struct AttribLayout_InternalContainer {
  206. static_assert( ! std::is_same<T,void>::value, "Void vector is used in layout!" );
  207. using curtype = T;
  208. using nexttype = typename std::conditional<
  209. sizeof...(P) > 1,
  210. AttribLayout_InternalContainer<P...>,
  211. AttribLayout_InternalValue<P...>
  212. >::type;
  213. };
  214.  
  215.  
  216. template <typename ...P>
  217. class AttribLayout
  218. {
  219. protected:
  220. static_assert( sizeof...(P) > 0, "Zero-length attrib layout!" );
  221. using cont_type = typename std::conditional<
  222. sizeof...(P) > 1,
  223. AttribLayout_InternalContainer<P...>,
  224. AttribLayout_InternalValue<P...>
  225. >::type;
  226.  
  227. public:
  228. static constexpr int elements = sizeof...(P);
  229.  
  230. protected:
  231.  
  232. template <unsigned int N, typename T>
  233. struct type_at_internal {
  234. using type = typename type_at_internal< N-1, typename T::nexttype > :: type;
  235. };
  236.  
  237. template <typename T>
  238. struct type_at_internal<0, T> {
  239. using type = T;
  240. };
  241.  
  242.  
  243. template <unsigned int N>
  244. using cont_type_at = typename type_at_internal< N, cont_type >::type;
  245.  
  246. public:
  247. template <unsigned int N>
  248. using type_at = typename type_at_internal< N, cont_type >::type::curtype;
  249.  
  250.  
  251. template <unsigned int N, typename T>
  252. struct bytes_internal {
  253. static constexpr unsigned int var = bytes_internal<(N-1),T>::var + type_at<(N-1)>::dim * sizeof(typename type_at<(N-1)>::type);
  254. };
  255.  
  256. template <typename T>
  257. struct bytes_internal<0, T> {
  258. static constexpr unsigned int var = 0;
  259. };
  260.  
  261.  
  262. static constexpr unsigned int byte_len = bytes_internal<(sizeof...(P)), void>::var;
  263.  
  264. unsigned char bytearr[byte_len];
  265.  
  266. template <unsigned int N>
  267. type_at<N> get() {
  268. static_assert( N>=0 && N<sizeof...(P), "Element is out of range!" );
  269. type_at<N> ret;
  270. std::memcpy(
  271. &ret,
  272. bytearr + bytes_internal<N,void>::var,
  273. sizeof(type_at<N>)
  274. );
  275. return ret;
  276. }
  277.  
  278. template <unsigned int N>
  279. void set( const type_at<N>& ref ) {
  280. static_assert( N >= 0 && N < sizeof...(P), "Element is out of range!" );
  281. std::memcpy(
  282. bytearr + bytes_internal<N,void>::var,
  283. &ref,
  284. sizeof (type_at<N>)
  285. );
  286. }
  287.  
  288. template <unsigned int N, unsigned int X>
  289. typename type_at<N>::type get( )
  290. {
  291. static_assert( N >= 0 && N < sizeof...(P), "Element is out of range!" );
  292. static_assert( X > 0 && X <= type_at<N>::dim, "Vector element is out of range!" );
  293.  
  294. typename type_at<N>::type ret;
  295. std::memcpy(
  296. &ret,
  297. bytearr + bytes_internal<N,void>::var + sizeof(typename type_at<N>::type) * (X-1),
  298. sizeof (typename type_at<N>::type)
  299. );
  300. return ret;
  301. }
  302.  
  303. template <unsigned int N, unsigned int X>
  304. void set( typename type_at<N>::type obj )
  305. {
  306. static_assert( N >= 0 && N < sizeof...(P), "Element is out of range!" );
  307. static_assert( X > 0 && X <= type_at<N>::dim, "Vector element is out of range!" );
  308. std::memcpy(
  309. bytearr + bytes_internal<N,void>::var + sizeof(typename type_at<N>::type) * (X-1),
  310. &obj,
  311. sizeof (typename type_at<N>::type)
  312. );
  313. }
  314.  
  315.  
  316. protected: // private? everywhere...?
  317. template <unsigned int N, unsigned int M>
  318. struct ctor_internal
  319. {
  320. static void func(void **ptr, unsigned char *arr)
  321. {
  322. std::memcpy(
  323. arr + bytes_internal< M-N, void >::var,
  324. *ptr,
  325. sizeof( type_at< M-N > )
  326. );
  327.  
  328. ctor_internal< N-1, M >::func( ptr+1, arr );
  329. }
  330. };
  331.  
  332. template <unsigned int M>
  333. struct ctor_internal< -1, M >
  334. {
  335. static void func(void **ptr, unsigned char *arr) { }
  336. }
  337.  
  338. // template <unsigned int M>
  339. // struct ctor_internal<0, M>
  340. // {
  341. // static void func(void **ptr, unsigned char *arr)
  342. // {
  343. // std::memcpy(arr + bytes_internal<M, void>::var,
  344. // *ptr,
  345. // sizeof (type_at<M>)
  346. // );
  347. // }
  348. // };
  349.  
  350.  
  351. public:
  352.  
  353. AttribLayout()
  354. {
  355. static_assert( sizeof(decltype(*this)) == byte_len, "Crappy compiler have added padding to AttribLayout!" );
  356. static_assert( alignof(decltype(*this)) == 1 , "Crappy compiler have added alignment to AttribLayout!" );
  357. }
  358.  
  359. AttribLayout(P ...params)
  360. {
  361. static constexpr int n = sizeof...(P); // π
  362.  
  363. void *ptrs[n] { (void*)&params... };
  364. ctor_internal< n-1, n-1 >::func( ptrs, bytearr );
  365. }
  366. };
  367.  
  368.  
  369. namespace InternalStuff
  370. {
  371. template <class T, unsigned N>
  372. struct SetVertexAttribs_internal
  373. {
  374. static void func()
  375. {
  376. SetVertexAttribs_internal< T, (N-1) >::func();
  377.  
  378. glEnableVertexAttribArray(N);
  379.  
  380. type2glattribfunc< typename T::template type_at<N>::type >(
  381. N,
  382. T::template type_at<N>::dim,
  383. T::byte_len,
  384. (void *) T::template bytes_internal<N,void>::var
  385. );
  386. }
  387. };
  388.  
  389. template <class T>
  390. struct SetVertexAttribs_internal<T, -1>
  391. {
  392. static void func() { }
  393. }
  394.  
  395. //template <class T>
  396. //struct SetVertexAttribs_internal<T, 0>
  397. //{
  398. // static void func()
  399. // {
  400. // glEnableVertexAttribArray(0);
  401. // type2glattribfunc<typename T::template type_at<0>::type>(
  402. // 0,
  403. // T::template type_at<0>::dim,
  404. // T::byte_len,
  405. // (void *)T::template bytes_internal<0, void>::var
  406. // );
  407. // }
  408. //};
  409. }
  410.  
  411. template <class T>
  412. void SetVertexAttribs()
  413. {
  414. InternalStuff::SetVertexAttribs_internal< T, T::elements-1 >::func();
  415. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement