MeshPrimitiveFunctions.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #ifndef GUL_MESH_PRIMITIVE_FUNCTIONS_H
  2. #define GUL_MESH_PRIMITIVE_FUNCTIONS_H
  3. #include "MeshPrimitive2.h"
  4. #include <glm/glm.hpp>
  5. namespace gul
  6. {
  7. /**
  8. * @brief convertAttribute_t
  9. * @param V
  10. * @param C
  11. *
  12. * Converts the data from inType to outType using the callable function C,
  13. *
  14. * This does not do any type checking, it simply byte copies the data
  15. * runs it through the callable, and byte-writes the new data.
  16. *
  17. * Note: inType and outType must be fundamental type or have inType::value_type as a fundamental type
  18. */
  19. template<typename inType, typename outType, typename Callable_t>
  20. inline bool convertAttribute_t(VertexAttribute & V, Callable_t && C)
  21. {
  22. // if the output type is going to be smaller
  23. // then the input type, then we can
  24. // forward iterate because we wont overwrite any
  25. // data that is currently being read
  26. if constexpr ( sizeof(outType) <= sizeof(inType))
  27. {
  28. auto attrCount = V.attributeCount();
  29. auto byteSizeIn = attrCount * V.getAttributeSize();
  30. auto byteSizeOut = attrCount * sizeof(outType);
  31. auto newSize = byteSizeIn / sizeof(outType);
  32. (void)byteSizeIn;
  33. (void)byteSizeOut;
  34. (void)newSize;
  35. for(uint32_t i=0;i<attrCount;i++)
  36. {
  37. auto v = C(V.get<inType>(i));
  38. V.set<outType>(i, v);
  39. }
  40. V.init( type_to_component<outType>(), type_to_type<outType>() );
  41. V.resize(attrCount);
  42. assert( V.attributeCount() == attrCount);
  43. }
  44. else
  45. {
  46. // if the output size is larger, we have to do the conversion starting
  47. // from the end and work backwards
  48. auto attrCount = V.attributeCount();
  49. auto attrSize = V.getAttributeSize();
  50. if(attrSize == 0)
  51. return false;
  52. auto byteSizeIn = attrCount * attrSize;
  53. auto byteSizeOut = attrCount * sizeof(outType);
  54. auto newSize = (byteSizeOut) / (attrSize);
  55. (void)byteSizeIn;
  56. (void)byteSizeOut;
  57. (void)newSize;
  58. if constexpr ( sizeof(outType) % sizeof(inType) != 0)
  59. {
  60. V.resize(newSize+1);
  61. }
  62. else
  63. {
  64. V.resize(newSize);
  65. }
  66. for(uint32_t i=0;i<attrCount;i++)
  67. {
  68. auto j = attrCount-i-1;
  69. auto v = C(V.get<inType>(j));
  70. V.set<outType>(j, v);
  71. }
  72. V.init( type_to_component<outType>(), type_to_type<outType>());
  73. V.resize(attrCount);
  74. }
  75. return true;
  76. }
  77. inline glm::uvec2 packHalf4x32(glm::vec4 const &v)
  78. {
  79. return { glm::packHalf2x16(glm::vec2(v[0],v[1]) ), glm::packHalf2x16(glm::vec2(v[2],v[3]) ) };
  80. }
  81. inline uint32_t packSnorm3x10(glm::vec3 const & n)
  82. {
  83. auto ot = glm::uvec3( glm::mix( glm::vec3(0.0f), glm::vec3(1023), (n+1.0f)*0.5f) ) << glm::uvec3(0,10,20);
  84. return ot.x | ot.y | ot.z;
  85. }
  86. inline glm::vec3 unpackSnorm3x10(uint32_t n)
  87. {
  88. return ( glm::vec3( (glm::uvec3(n) >> glm::uvec3(0,10,20) ) & glm::uvec3(1023) ) - 511.0f ) / 511.0f;
  89. }
  90. /**
  91. * @brief packMesh
  92. * @param M
  93. * @return
  94. *
  95. * Packs the mesh using some known schemes:
  96. *
  97. * Attribute Input Type Output Type GLSL Function to unpack
  98. * ---------------------------------------------------------------------------------------
  99. * POSITION vec3 vec3
  100. * NORMAL vec3 uint see function above: unpackSnorm3x10
  101. * TEXCOORD_N vec2 uint unpackHalf2x16(uint)
  102. * COLOR_N vec4 uint unpackUnorm4x8(uint)
  103. * JOINTS_0 uvec4
  104. * WEIGHTS_N vec4 2 x uint vec4( unpackHalf2x16(u[0]), unpackHalf2x16(u[1]) )
  105. *
  106. */
  107. inline uint64_t packMesh(MeshPrimitive & M)
  108. {
  109. if(M.NORMAL.getComponentType() == eComponentType::FLOAT && M.NORMAL.getType() == eType::VEC3)
  110. {
  111. convertAttribute_t<glm::vec3, uint32_t>(M.NORMAL, packSnorm3x10);
  112. M.NORMAL.setType(eType::SCALAR);
  113. M.NORMAL.setComponent(eComponentType::UNSIGNED_INT);
  114. }
  115. if(M.TEXCOORD_0.getComponentType() == eComponentType::FLOAT && M.TEXCOORD_0.getType() == eType::VEC2)
  116. {
  117. convertAttribute_t<glm::vec2, uint32_t>(M.TEXCOORD_0, glm::packHalf2x16);
  118. M.NORMAL.setType(eType::SCALAR);
  119. M.NORMAL.setComponent(eComponentType::UNSIGNED_INT);
  120. }
  121. if(M.TEXCOORD_1.getComponentType() == eComponentType::FLOAT && M.TEXCOORD_1.getType() == eType::VEC2)
  122. {
  123. convertAttribute_t<glm::vec2, uint32_t>(M.TEXCOORD_1, glm::packHalf2x16);
  124. M.NORMAL.setType(eType::SCALAR);
  125. M.NORMAL.setComponent(eComponentType::UNSIGNED_INT);
  126. }
  127. if(M.TANGENT.getComponentType() == eComponentType::FLOAT && M.TANGENT.getType() == eType::VEC4)
  128. {
  129. convertAttribute_t<glm::vec4, uint32_t>(M.TANGENT, glm::packSnorm4x8);
  130. M.TANGENT.setType(eType::SCALAR);
  131. M.TANGENT.setComponent(eComponentType::UNSIGNED_INT);
  132. }
  133. if(M.COLOR_0.getComponentType() == eComponentType::FLOAT && M.COLOR_0.getType() == eType::VEC4)
  134. {
  135. convertAttribute_t<glm::vec4, uint32_t>(M.COLOR_0, glm::packUnorm4x8);
  136. M.NORMAL.setType(eType::SCALAR);
  137. M.NORMAL.setComponent(eComponentType::UNSIGNED_INT);
  138. }
  139. if(M.WEIGHTS_0.getComponentType() == eComponentType::FLOAT && M.WEIGHTS_0.getType() == eType::VEC4)
  140. {
  141. convertAttribute_t<glm::vec4, glm::uvec2>(M.WEIGHTS_0, packHalf4x32);
  142. M.WEIGHTS_0.setType(eType::VEC2);
  143. M.NORMAL.setComponent(eComponentType::UNSIGNED_INT);
  144. }
  145. return M.calculateDeviceSize();
  146. }
  147. }
  148. #endif