MeshPrimitive2.h 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247
  1. #ifndef GUL_MESH_PRIMITIVE_2_H
  2. #define GUL_MESH_PRIMITIVE_2_H
  3. #include <cmath>
  4. #include <vector>
  5. #include <array>
  6. #include <cstring>
  7. #include <tuple>
  8. #include <string>
  9. #include <fstream>
  10. #include <sstream>
  11. #include <cassert>
  12. #include <map>
  13. namespace gul
  14. {
  15. enum class eComponentType : uint32_t
  16. {
  17. UNKNOWN = 0,
  18. BYTE = 5120,
  19. UNSIGNED_BYTE = 5121,
  20. SHORT = 5122,
  21. UNSIGNED_SHORT = 5123,
  22. INT = 5124,
  23. UNSIGNED_INT = 5125,
  24. FLOAT = 5126,
  25. DOUBLE = 5130
  26. };
  27. enum class eType : uint32_t
  28. {
  29. // rows columns
  30. UNKNOWN = 0x00000000 | 0x00000000,
  31. SCALAR = 0x00000100 | 0x00000001,
  32. VEC2 = 0x00000100 | 0x00000002,
  33. VEC3 = 0x00000100 | 0x00000003,
  34. VEC4 = 0x00000100 | 0x00000004,
  35. MAT2 = 0x00000200 | 0x00000002,
  36. MAT3 = 0x00000300 | 0x00000003,
  37. MAT4 = 0x00000400 | 0x00000004
  38. };
  39. constexpr const char* to_string(eComponentType t)
  40. {
  41. switch(t)
  42. {
  43. default:
  44. case eComponentType::UNKNOWN : return "UNKNOWN";
  45. case eComponentType::BYTE : return "BYTE";
  46. case eComponentType::UNSIGNED_BYTE : return "UNSIGNED_BYTE";
  47. case eComponentType::SHORT : return "SHORT";
  48. case eComponentType::UNSIGNED_SHORT: return "UNSIGNED_SHORT";
  49. case eComponentType::INT : return "INT";
  50. case eComponentType::UNSIGNED_INT : return "UNSIGNED_INT";
  51. case eComponentType::FLOAT : return "FLOAT";
  52. case eComponentType::DOUBLE : return "DOUBLE";
  53. }
  54. }
  55. constexpr const char* to_string(eType t)
  56. {
  57. switch(t)
  58. {
  59. default:
  60. case eType::UNKNOWN: return "UNKNOWN";
  61. case eType::SCALAR : return "SCALAR";
  62. case eType::VEC2 : return "VEC2";
  63. case eType::VEC3 : return "VEC3";
  64. case eType::VEC4 : return "VEC4";
  65. case eType::MAT2 : return "MAT2";
  66. case eType::MAT3 : return "MAT3";
  67. case eType::MAT4 : return "MAT4";
  68. }
  69. }
  70. /**
  71. * @brief row_type
  72. * @param c
  73. * @return
  74. *
  75. * Returns the row type
  76. */
  77. constexpr eType row_type(eType c)
  78. {
  79. switch ( c )
  80. {
  81. case eType::UNKNOWN: return eType::UNKNOWN;
  82. case eType::SCALAR : return eType::UNKNOWN;
  83. case eType::VEC2 : return eType::SCALAR;
  84. case eType::VEC3 : return eType::SCALAR;
  85. case eType::VEC4 : return eType::SCALAR;
  86. case eType::MAT2 : return eType::VEC2;
  87. case eType::MAT3 : return eType::VEC3;
  88. case eType::MAT4 : return eType::VEC4;
  89. }
  90. return eType::UNKNOWN;
  91. }
  92. constexpr uint32_t component_row_count(eType c)
  93. {
  94. return (static_cast<uint32_t>(c) & 0x000000FF);
  95. }
  96. constexpr uint32_t component_column_count(eType c)
  97. {
  98. return ( (static_cast<uint32_t>(c) >> 8) & 0x000000FF);
  99. }
  100. constexpr uint32_t component_count(eType c)
  101. {
  102. return component_row_count(c) * component_column_count(c);
  103. }
  104. constexpr uint32_t component_size(eComponentType c)
  105. {
  106. switch(c)
  107. {
  108. case gul::eComponentType::BYTE:
  109. case gul::eComponentType::UNSIGNED_BYTE: return 1;
  110. case gul::eComponentType::SHORT:
  111. case gul::eComponentType::UNSIGNED_SHORT: return 2;
  112. case gul::eComponentType::INT:
  113. case gul::eComponentType::UNSIGNED_INT:
  114. case gul::eComponentType::FLOAT: return 4;
  115. case gul::eComponentType::DOUBLE: return 8;
  116. default:
  117. return 0;
  118. }
  119. }
  120. template<typename T>
  121. constexpr eComponentType type_to_component()
  122. {
  123. if constexpr ( std::is_arithmetic_v<T> )
  124. {
  125. if constexpr (std::is_same_v<T, int8_t>) return eComponentType::BYTE;
  126. else if constexpr (std::is_same_v<T, uint8_t>) return eComponentType::UNSIGNED_BYTE;
  127. else if constexpr (std::is_same_v<T, int16_t>) return eComponentType::SHORT;
  128. else if constexpr (std::is_same_v<T, uint16_t>) return eComponentType::UNSIGNED_SHORT;
  129. else if constexpr (std::is_same_v<T, int32_t>) return eComponentType::INT;
  130. else if constexpr (std::is_same_v<T, uint32_t>) return eComponentType::UNSIGNED_INT;
  131. else if constexpr (std::is_same_v<T, float>) return eComponentType::FLOAT;
  132. else if constexpr (std::is_same_v<T, double>) return eComponentType::DOUBLE;
  133. else
  134. {
  135. return eComponentType::UNKNOWN;
  136. }
  137. }
  138. else
  139. {
  140. return type_to_component<typename T::value_type>();
  141. }
  142. }
  143. template<typename T>
  144. constexpr eType type_to_type()
  145. {
  146. if constexpr ( std::is_arithmetic_v<T>)
  147. {
  148. return eType::SCALAR;
  149. }
  150. else
  151. {
  152. constexpr auto component = type_to_component<T>();
  153. constexpr auto size = component_size(component);
  154. // either a vec4 or a mat2
  155. if constexpr ( sizeof(T) / size == 4 )
  156. {
  157. struct S
  158. {
  159. auto operator()()
  160. {
  161. return T()[0];
  162. }
  163. };
  164. //std::invoke_result
  165. if constexpr( std::is_arithmetic_v< typename std::invoke_result<S>::type> )
  166. {
  167. return eType::VEC4;
  168. }
  169. else
  170. {
  171. return eType::MAT2;
  172. }
  173. }
  174. else
  175. {
  176. switch ( sizeof(T) / size)
  177. {
  178. case 1:
  179. return eType::SCALAR;
  180. case 2:
  181. return eType::VEC2;
  182. case 3:
  183. return eType::VEC3;
  184. case 4:
  185. return eType::VEC4;
  186. case 9:
  187. return eType::MAT3;
  188. case 16:
  189. return eType::MAT4;
  190. default:
  191. return eType::UNKNOWN;
  192. }
  193. }
  194. }
  195. }
  196. /**
  197. * @brief The VertexAttribute struct
  198. *
  199. * The vertex attribute class is essentially a vector of data
  200. * for a single attribute. This is NOT meant for compound vertices: eg
  201. * struct Vertex
  202. * {
  203. * vec3 position;
  204. * vec2 uv;
  205. * }
  206. *
  207. *
  208. */
  209. struct VertexAttribute
  210. {
  211. VertexAttribute()
  212. {
  213. }
  214. VertexAttribute(eComponentType c, eType t)
  215. {
  216. m_componentType = c;
  217. m_type = t;
  218. }
  219. template<typename T>
  220. VertexAttribute( std::vector<T> const & V)
  221. {
  222. using container_type = std::decay_t<decltype(V) >;
  223. using attribute_type = typename container_type::value_type;
  224. m_componentType = type_to_component<attribute_type>();
  225. m_type = type_to_type<attribute_type>();
  226. m_data.resize( getAttributeSize() * V.size() );
  227. std::memcpy(m_data.data(), V.data(), m_data.size());
  228. }
  229. void dump(std::ostream & out, std::string name)
  230. {
  231. out.write(name.data(), static_cast<std::streamsize>(name.size()));
  232. out.write(reinterpret_cast<const char*>(&m_componentType), sizeof(m_componentType));
  233. out.write(reinterpret_cast<const char*>(&m_type), sizeof(m_type));
  234. out.write(reinterpret_cast<const char*>(m_data.data()), static_cast<std::streamsize>(m_data.size()));
  235. }
  236. /**
  237. * @brief init
  238. * @param c
  239. * @param t
  240. *
  241. * Initialize the vertex attribute based on its base component type and
  242. * its attribute type
  243. */
  244. void init(eComponentType c, eType t)
  245. {
  246. m_componentType = c;
  247. m_type = t;
  248. }
  249. template<typename T>
  250. VertexAttribute& operator=(std::vector<T> const & V)
  251. {
  252. using container_type = std::decay_t<decltype(V) >;
  253. using attribute_type = typename container_type::value_type;
  254. m_componentType = type_to_component<attribute_type>();
  255. m_type = type_to_type<attribute_type>();
  256. m_data.resize( getAttributeSize() * V.size() );
  257. std::memcpy(m_data.data(), V.data(), m_data.size());
  258. return *this;
  259. }
  260. template<typename T>
  261. std::vector<T> toVector() const
  262. {
  263. std::vector<T> data( m_data.size() / sizeof(T));
  264. std::memcpy(data.data(), m_data.data(), sizeof(T)*data.size());
  265. return data;
  266. }
  267. /**
  268. * @brief at
  269. * @param i
  270. * @return
  271. *
  272. * Returns the value of a component
  273. */
  274. template<typename T>
  275. T at(size_t index, size_t componentIndex=0) const
  276. {
  277. T v;
  278. std::memcpy(&v, m_data.data() + index * getAttributeSize() + componentIndex * component_size(m_componentType), sizeof(T));
  279. return v;
  280. }
  281. /**
  282. * @brief get
  283. * @param index
  284. * @return
  285. *
  286. * Treats the VertexAttribute as a vector<T> and returns
  287. * the index into that vector
  288. */
  289. template<typename T>
  290. T get(size_t index) const
  291. {
  292. T v;
  293. std::memcpy(&v, m_data.data() + index * sizeof(T), sizeof(T));
  294. return v;
  295. }
  296. /**
  297. * @brief getAttributeAs
  298. * @param index
  299. * @return
  300. *
  301. * different from get(), return's the attribute specified by index,
  302. * the a
  303. */
  304. template<typename T>
  305. T getAttributeAs(size_t index) const
  306. {
  307. T v;
  308. std::memcpy(&v, m_data.data() + index * getAttributeSize(), sizeof(T));
  309. return v;
  310. }
  311. /**
  312. * @brief set
  313. * @param index
  314. * @param v
  315. *
  316. * Treats the VertexAttribute as a vector<T> and sets
  317. * vertexAttribute[index] = v
  318. */
  319. template<typename T>
  320. void set(size_t index, T const &v)
  321. {
  322. std::memcpy(m_data.data() + index*sizeof(T), &v, sizeof(T));
  323. }
  324. /**
  325. * @brief size
  326. * @return
  327. *
  328. * Returns the total number of components in the attribute array.
  329. *
  330. * If ther are 4 vertices and each vertex has xyz components, the
  331. * return value will be 12
  332. */
  333. size_t size() const
  334. {
  335. return attributeCount() * getNumComponents();
  336. }
  337. /**
  338. * @brief push_back
  339. * @param v
  340. *
  341. * Pushes data to the end of the vector
  342. */
  343. template<typename T>
  344. void push_back(T const & v)
  345. {
  346. auto m = m_data.size();
  347. m_data.resize( m + sizeof(v));
  348. std::memcpy( &m_data[m], &v, sizeof(v));
  349. }
  350. bool empty() const
  351. {
  352. return m_data.empty();
  353. }
  354. /**
  355. * @brief getType
  356. * @return
  357. *
  358. */
  359. eType getType() const
  360. {
  361. return m_type;
  362. }
  363. eComponentType getComponentType() const
  364. {
  365. return m_componentType;
  366. }
  367. uint32_t getNumComponents() const
  368. {
  369. return component_count(m_type);
  370. }
  371. std::array<uint32_t,2> getShape() const
  372. {
  373. return { static_cast<uint32_t>(attributeCount()), getNumComponents()};
  374. }
  375. /**
  376. * @brief convertTo32BitInteger
  377. *
  378. * Used only for uint and ints. Converts a lower
  379. * bit value into the 32 bit equivelant
  380. */
  381. bool convertTo32BitInteger()
  382. {
  383. auto totalComponents = attributeCount() * getNumComponents();
  384. if(getComponentType() == eComponentType::UNSIGNED_BYTE)
  385. {
  386. VertexAttribute newData(eComponentType::UNSIGNED_INT, getType());
  387. for(uint32_t i=0;i<totalComponents;i++)
  388. {
  389. newData.push_back<uint32_t>(get<uint8_t>(i));
  390. }
  391. *this = std::move(newData);
  392. return true;
  393. }
  394. if(getComponentType() == eComponentType::UNSIGNED_SHORT)
  395. {
  396. VertexAttribute newData(eComponentType::UNSIGNED_INT, getType());
  397. for(uint32_t i=0;i<totalComponents;i++)
  398. {
  399. newData.push_back<uint32_t>(get<uint16_t>(i));
  400. }
  401. *this = std::move(newData);
  402. return true;
  403. }
  404. if(getComponentType() == eComponentType::BYTE)
  405. {
  406. VertexAttribute newData(eComponentType::INT, getType());
  407. for(uint32_t i=0;i<totalComponents;i++)
  408. {
  409. newData.push_back<int32_t>(get<int8_t>(i));
  410. }
  411. *this = std::move(newData);
  412. return true;
  413. }
  414. if(getComponentType() == eComponentType::SHORT)
  415. {
  416. VertexAttribute newData(eComponentType::INT, getType());
  417. for(uint32_t i=0;i<totalComponents;i++)
  418. {
  419. newData.push_back<int32_t>(get<int16_t>(i));
  420. }
  421. *this = std::move(newData);
  422. return true;
  423. }
  424. return false;
  425. }
  426. void* data()
  427. {
  428. return m_data.data();
  429. }
  430. /**
  431. * @brief getAttributeSize
  432. * @return
  433. *
  434. * Returns the size of the attribute. If it returns 0 it means that
  435. * the attribute type has not been set
  436. */
  437. uint32_t getAttributeSize() const
  438. {
  439. return component_size(m_componentType) * component_count(m_type);
  440. }
  441. uint64_t getByteSize() const
  442. {
  443. return m_data.size();
  444. }
  445. /**
  446. * @brief attributeCount
  447. * @return
  448. *
  449. * Returns the total number of attributes in the buffer.
  450. */
  451. uint64_t attributeCount() const
  452. {
  453. auto s = getAttributeSize();
  454. return s == 0 ? 0 : m_data.size() / s;
  455. }
  456. /**
  457. * @brief resize
  458. * @param attrCount
  459. *
  460. * Resize the attribute vector to be able to hold attrCount attributes
  461. */
  462. void resize(size_t attrCount)
  463. {
  464. m_data.resize( attrCount * getAttributeSize() );
  465. }
  466. /**
  467. * @brief canMerge
  468. * @param B
  469. * @return
  470. *
  471. * Returns wither you can merge this vertex attribute with another.
  472. * You can only merge the two if the componentType and the Type are the same
  473. */
  474. bool canMerge(VertexAttribute const & B) const
  475. {
  476. return m_componentType == B.m_componentType && m_type == B.m_type;
  477. }
  478. /**
  479. * @brief merge
  480. * @param B
  481. * @return
  482. *
  483. * Merge B to the end of the attribute vector and return the byte offset
  484. * at which the data was merged.
  485. */
  486. uint64_t merge(VertexAttribute const& B)
  487. {
  488. auto s = m_data.size();
  489. m_data.insert(m_data.end(), B.m_data.begin(), B.m_data.end());
  490. return s;
  491. }
  492. /**
  493. * @brief strideCopy
  494. * @param data
  495. * @param stride
  496. *
  497. * Copy the vertex attribute data into the memory location.
  498. *
  499. * if V = [p0,p1,p2,p3]
  500. *
  501. * Then a stride copy of strideCopy(data, 2*sizeof(p0)) will copy data as follows
  502. *
  503. * data = [p0| |p1| |p2| |p3]
  504. *
  505. * This is used to interleave multiple attribute. eg:
  506. *
  507. * positionAttribute.strideCopy(data, sizeof(vec3) )
  508. * uvAttribute.strideCopy( data+sizeof(vec3), sizeof(vec2) )
  509. */
  510. void strideCopy(void * data, uint64_t stride) const
  511. {
  512. auto c = attributeCount();
  513. auto s = getAttributeSize();
  514. auto d_in = static_cast<uint8_t const*>(m_data.data());
  515. auto d_out = static_cast<uint8_t*>(data);
  516. for(uint64_t i=0;i<c;i++)
  517. {
  518. std::memcpy(d_out, d_in, s);
  519. d_out += stride;
  520. d_in += s;
  521. }
  522. }
  523. /**
  524. * @brief strideCopyOffset
  525. * @param dstData - the start of the destination to copy to
  526. * @param dstByteStride - how many bytes to skip after copying each attribute
  527. * @param dstByteOffset - the offset from the start of dstData to start copying to
  528. *
  529. * @param srcStartAttributeIndex - which index in the source attribute to start copying from
  530. * @param attributeCountToCopy - number of attributes to copy
  531. * @return
  532. *
  533. * Copies the attribute data to dstData+dstByteOffset
  534. */
  535. uint64_t strideCopyOffset(void * dstData,
  536. uint64_t dstByteStride,
  537. uint64_t dstByteOffset,
  538. uint64_t srcStartAttributeIndex,
  539. uint64_t attributeCountToCopy = std::numeric_limits<uint64_t>::max()) const
  540. {
  541. auto c = std::min(attributeCount(), attributeCountToCopy);
  542. auto srcAttrSize = getAttributeSize();
  543. auto d_in = static_cast<uint8_t const*>(m_data.data()) + srcStartAttributeIndex * srcAttrSize;
  544. auto d_in_end = std::min(d_in + srcAttrSize * attributeCountToCopy, &m_data.back()+1);
  545. auto d_out = static_cast<uint8_t*>(dstData) + dstByteOffset;
  546. while(d_in < d_in_end)
  547. {
  548. std::memcpy(d_out, d_in, srcAttrSize);
  549. d_out += dstByteStride;
  550. d_in += srcAttrSize;
  551. }
  552. return c;
  553. }
  554. /**
  555. * @brief strideCopy
  556. * @param data
  557. * @param n
  558. * @param offset
  559. * @param stride
  560. * @param num
  561. *
  562. * Copies num attributes into memory starting at data+offset with a specific stride.
  563. *
  564. * For example
  565. *
  566. * <-offset-> <--stride-->
  567. * [ | A1 | | A2 | | A3 | ]
  568. * ^--data
  569. */
  570. [[deprecated]] uint64_t strideCopy(void * data, uint64_t stride, uint64_t offset, uint64_t num = std::numeric_limits<uint64_t>::max()) const
  571. {
  572. auto c = std::min(attributeCount(), num);
  573. auto s = getAttributeSize();
  574. auto d_in = static_cast<uint8_t const*>(m_data.data());
  575. auto d_out = static_cast<uint8_t*>(data)+offset;
  576. for(uint64_t i=0;i<c;i++)
  577. {
  578. std::memcpy(d_out, d_in, s);
  579. d_out += stride;
  580. d_in += s;
  581. }
  582. return c;
  583. }
  584. void clear()
  585. {
  586. m_data.clear();
  587. }
  588. void setType(eType t)
  589. {
  590. m_type = t;
  591. }
  592. void setComponent(eComponentType c)
  593. {
  594. m_componentType = c;
  595. }
  596. /**
  597. * @brief getMinMax
  598. * @return
  599. *
  600. * Returns the min and max values for each component.
  601. */
  602. template<typename T>
  603. std::pair< std::vector<T>, std::vector<T>> getMinMax() const
  604. {
  605. auto & V = *this;
  606. static_assert( std::is_arithmetic_v<T>, "T must be an arithmetic type");
  607. using value_type = T;
  608. std::vector<value_type> _min(component_count(V.getType()), std::numeric_limits<value_type>::max() );
  609. std::vector<value_type> _max(component_count(V.getType()), std::numeric_limits<value_type>::lowest() );
  610. auto attrCount = attributeCount();
  611. for(uint32_t j=0;j<attrCount;j++)
  612. {
  613. for(size_t i=0;i<_min.size();i++)
  614. {
  615. _min[i] = std::min( V.at<value_type>(j, i), _min[i] );
  616. _max[i] = std::max( V.at<value_type>(j, i), _max[i] );
  617. }
  618. }
  619. return {_min, _max};
  620. }
  621. protected:
  622. friend struct MeshPrimitive;
  623. std::vector<uint8_t> m_data;
  624. eComponentType m_componentType = eComponentType::UNKNOWN;
  625. eType m_type = eType::UNKNOWN;
  626. };
  627. //===========================================================================================================
  628. /**
  629. * @brief calculateInterleavedStride
  630. * @param attrs
  631. * @return
  632. *
  633. * Calculates the sum of each attr[i].attributeSize() skipping any attributes that dont have
  634. * items
  635. */
  636. inline uint64_t calculateInterleavedStride(std::vector<VertexAttribute const*> const &attrs)
  637. {
  638. uint64_t stride=0;
  639. for(auto * v : attrs)
  640. {
  641. if(v->size() > 0)
  642. stride += v->getAttributeSize();
  643. }
  644. return stride;
  645. }
  646. /**
  647. * @brief calculateInterleavedBytes
  648. * @param attrs
  649. * @return
  650. *
  651. * Returns the total number of bytes required to store all attributes in
  652. * interleaved format, attributes with zero attributeCount() are not included
  653. */
  654. inline uint64_t calculateInterleavedBytes(std::vector<VertexAttribute const*> const &attrs)
  655. {
  656. auto stride = calculateInterleavedStride(attrs);
  657. uint64_t vCount = 9999999999999;
  658. for(auto * v : attrs)
  659. {
  660. if(v->size() > 0)
  661. vCount = std::min(vCount,v->attributeCount());
  662. }
  663. return stride*vCount;
  664. }
  665. //===========================================================================================================
  666. enum class Topology
  667. {
  668. POINT_LIST = 0,
  669. LINE_LIST = 1,
  670. LINE_STRIP = 2,
  671. TRIANGLE_LIST = 3,
  672. TRIANGLE_STRIP = 4,
  673. TRIANGLE_FAN = 5,
  674. LINE_LIST_WITH_ADJACENCY = 6,
  675. LINE_STRIP_WITH_ADJACENCY = 7,
  676. TRIANGLE_LIST_WITH_ADJACENCY = 8,
  677. TRIANGLE_STRIP_WITH_ADJACENCY = 9,
  678. PATCH_LIST = 10,
  679. };
  680. struct DrawCall
  681. {
  682. uint32_t indexCount = 0;
  683. uint32_t vertexCount = 0;
  684. int32_t vertexOffset = 0;
  685. int32_t indexOffset = 0;
  686. Topology topology = Topology::TRIANGLE_LIST;
  687. };
  688. using Primitive = DrawCall;
  689. /**
  690. * @brief forEachVertexIndex
  691. * @param _INDEX
  692. * @param p
  693. * @param C
  694. *
  695. * Given an index buffer and a primitive, call the callable, C for each VertexIndex in the primitive.
  696. *
  697. */
  698. template<typename Callable_t>
  699. inline void forEachVertexIndex(VertexAttribute const & _INDEX, Primitive const & p, Callable_t && C)
  700. {
  701. if( _INDEX.getComponentType() == eComponentType::UNSIGNED_INT)
  702. {
  703. uint32_t vertexOffset = static_cast<uint32_t>(p.vertexOffset);
  704. using IndexComponentType = uint32_t;
  705. for(uint32_t i=0;i < p.indexCount ; i++)
  706. {
  707. uint32_t vertexIndex = _INDEX.at<IndexComponentType>(i + static_cast<uint32_t>(p.indexOffset))
  708. + vertexOffset;
  709. C(vertexIndex);
  710. }
  711. }
  712. }
  713. /**
  714. * @brief The MeshPrimitive struct
  715. *
  716. * A Mesh Primitive is a class which allows
  717. * you to represent a triangular mesh
  718. *
  719. */
  720. struct MeshPrimitive
  721. {
  722. using attribute_type = VertexAttribute;
  723. // list of common attributes in the order specified by the GLTF specification
  724. // initialized using the most common types
  725. attribute_type POSITION = attribute_type(eComponentType::FLOAT, eType::VEC3);
  726. attribute_type NORMAL = attribute_type(eComponentType::FLOAT, eType::VEC3);
  727. attribute_type TANGENT = attribute_type(eComponentType::FLOAT, eType::VEC4);
  728. attribute_type TEXCOORD_0 = attribute_type(eComponentType::FLOAT, eType::VEC2);
  729. attribute_type TEXCOORD_1 = attribute_type(eComponentType::FLOAT, eType::VEC2);
  730. attribute_type COLOR_0 = attribute_type(eComponentType::UNSIGNED_BYTE, eType::VEC4);
  731. attribute_type JOINTS_0 = attribute_type(eComponentType::UNSIGNED_SHORT, eType::VEC4);
  732. attribute_type WEIGHTS_0 = attribute_type(eComponentType::FLOAT, eType::VEC4);
  733. // The index buffer
  734. attribute_type INDEX = attribute_type(eComponentType::UNSIGNED_INT, eType::SCALAR);
  735. Topology topology = Topology::TRIANGLE_LIST;
  736. // a vector of primitives
  737. // each primitive is a sub component of the mesh and
  738. // contains the draw call to draw it
  739. std::vector<Primitive> primitives;
  740. void clear()
  741. {
  742. for(auto * attr : {&POSITION ,
  743. &NORMAL ,
  744. &TANGENT ,
  745. &TEXCOORD_0,
  746. &TEXCOORD_1,
  747. &COLOR_0 ,
  748. &JOINTS_0 ,
  749. &WEIGHTS_0 ,
  750. &INDEX})
  751. {
  752. attr->clear();
  753. }
  754. }
  755. /**
  756. * @brief dump
  757. * @param out
  758. *
  759. * [experimental]
  760. * Dump the entire mesh to a simple binary file
  761. */
  762. void dump(std::ostream & out)
  763. {
  764. auto attrs = {&POSITION ,
  765. &NORMAL ,
  766. &TANGENT ,
  767. &TEXCOORD_0,
  768. &TEXCOORD_1,
  769. &COLOR_0 ,
  770. &JOINTS_0 ,
  771. &WEIGHTS_0 ,
  772. &INDEX};
  773. struct header_t
  774. {
  775. uint64_t magic = 5496876546618;
  776. uint32_t byteSize=0;
  777. uint32_t numAttributes=0;
  778. };
  779. header_t h;
  780. h.byteSize = 0;
  781. for(auto * attr : attrs)
  782. {
  783. if(attr->size())
  784. {
  785. h.numAttributes++;
  786. }
  787. }
  788. #define DUMP_ATTR(NAME ) if(NAME.size() > 0) NAME.dump(out, #NAME)
  789. out.write(reinterpret_cast<char const *>(&h), sizeof(h));
  790. DUMP_ATTR(NORMAL );
  791. DUMP_ATTR(TANGENT );
  792. DUMP_ATTR(TEXCOORD_0);
  793. DUMP_ATTR(TEXCOORD_1);
  794. DUMP_ATTR(COLOR_0 );
  795. DUMP_ATTR(JOINTS_0 );
  796. DUMP_ATTR(WEIGHTS_0 );
  797. DUMP_ATTR(INDEX );
  798. }
  799. /**
  800. * @brief calculateDeviceSize
  801. * @return
  802. *
  803. * Calculate the amount of bytes this mesh takes on the
  804. * the GPU if all vertices were placed one after the
  805. * other.
  806. *
  807. * This also includes the index size!
  808. */
  809. uint64_t calculateDeviceSize() const
  810. {
  811. uint64_t size = 0;
  812. size += POSITION .getByteSize();
  813. size += NORMAL .getByteSize();
  814. size += TANGENT .getByteSize();
  815. size += TEXCOORD_0.getByteSize();
  816. size += TEXCOORD_1.getByteSize();
  817. size += COLOR_0 .getByteSize();
  818. size += JOINTS_0 .getByteSize();
  819. size += WEIGHTS_0 .getByteSize();
  820. size += INDEX.getByteSize();
  821. return size;
  822. }
  823. /**
  824. * @brief isSimilar
  825. * @param P
  826. * @return
  827. *
  828. * Returns true if two mesh primitives are similar.
  829. * Two mesh primitives are similar if they have the same attributes
  830. * and their attribute have the same type
  831. */
  832. bool isSimilar( MeshPrimitive const & P) const
  833. {
  834. return
  835. POSITION .canMerge(P.POSITION ) &&
  836. NORMAL .canMerge(P.NORMAL ) &&
  837. TANGENT .canMerge(P.TANGENT ) &&
  838. TEXCOORD_0.canMerge(P.TEXCOORD_0 ) &&
  839. TEXCOORD_1.canMerge(P.TEXCOORD_1 ) &&
  840. COLOR_0 .canMerge(P.COLOR_0 ) &&
  841. JOINTS_0 .canMerge(P.JOINTS_0 ) &&
  842. WEIGHTS_0 .canMerge(P.WEIGHTS_0 ) &&
  843. INDEX .canMerge(P.INDEX );
  844. }
  845. /**
  846. * @brief indexCount
  847. * @return
  848. *
  849. * Returns the total number of indices in the mesh
  850. */
  851. size_t indexCount() const
  852. {
  853. return INDEX.attributeCount();
  854. }
  855. /**
  856. * @brief vertexCount
  857. * @return
  858. *
  859. * Returns number of vertices in the mesh. The number of vertices
  860. * is the minimum (non-zero) attribute count of
  861. */
  862. size_t vertexCount() const
  863. {
  864. size_t count=std::numeric_limits<size_t>::max();
  865. for(auto * v : { &POSITION,
  866. &NORMAL,
  867. &TANGENT,
  868. &TEXCOORD_0,
  869. &TEXCOORD_1,
  870. &COLOR_0,
  871. &JOINTS_0,
  872. &WEIGHTS_0})
  873. {
  874. auto sh = v->attributeCount();
  875. if( sh != 0)
  876. count = std::min<size_t>(count, sh);
  877. }
  878. return count;
  879. }
  880. /**
  881. * @brief getVertexFlags
  882. * @return
  883. *
  884. * Return a the vertex flag mask where each bit
  885. * represents whether the given attribute is available.
  886. */
  887. uint32_t getVertexFlags() const
  888. {
  889. uint32_t f = 0;
  890. f |= POSITION .size() == 0 ? 0 : (1u << 0);
  891. f |= NORMAL .size() == 0 ? 0 : (1u << 1);
  892. f |= TANGENT .size() == 0 ? 0 : (1u << 2);
  893. f |= TEXCOORD_0 .size() == 0 ? 0 : (1u << 3);
  894. f |= TEXCOORD_1 .size() == 0 ? 0 : (1u << 4);
  895. f |= COLOR_0 .size() == 0 ? 0 : (1u << 5);
  896. f |= JOINTS_0 .size() == 0 ? 0 : (1u << 6);
  897. f |= WEIGHTS_0 .size() == 0 ? 0 : (1u << 7);
  898. return f;
  899. }
  900. /**
  901. * @brief getDrawCall
  902. * @return
  903. *
  904. * Returns the drawcall for the entire mesh. This can be used
  905. * if there are no primitives listed
  906. */
  907. Primitive getDrawCall() const
  908. {
  909. DrawCall dc;
  910. dc.indexOffset = static_cast<int32_t>(0);
  911. dc.vertexOffset = static_cast<int32_t>(0);
  912. dc.vertexCount = static_cast<uint32_t>(vertexCount());
  913. dc.indexCount = static_cast<uint32_t>(indexCount());
  914. dc.topology = topology;
  915. return dc;
  916. }
  917. /**
  918. * @brief merge
  919. * @param P
  920. * @param renumberIndices
  921. * @return
  922. *
  923. * Merges mesh P into the current mesh and returns the full primitive drawcall.
  924. *
  925. * The meshes can be merged only if they are similar (ie: they have the same attributes)
  926. */
  927. Primitive merge(MeshPrimitive const & P, bool renumberIndices = false)
  928. {
  929. DrawCall dc;
  930. uint32_t currentVertexCount = static_cast<uint32_t>(this->vertexCount());
  931. uint32_t currentIndexCount = static_cast<uint32_t>(this->INDEX.size());
  932. auto origIndexCount = indexCount();
  933. auto origVertexCount = vertexCount();
  934. dc.indexOffset = static_cast<int32_t>(indexCount() );
  935. dc.vertexOffset = static_cast<int32_t>(vertexCount());
  936. dc.vertexCount = static_cast<uint32_t>(P.vertexCount());
  937. dc.indexCount = static_cast<uint32_t>(P.indexCount() );
  938. if( isSimilar(P) )
  939. {
  940. POSITION .merge(P.POSITION );
  941. NORMAL .merge(P.NORMAL );
  942. TANGENT .merge(P.TANGENT );
  943. TEXCOORD_0.merge(P.TEXCOORD_0);
  944. TEXCOORD_1.merge(P.TEXCOORD_1);
  945. COLOR_0 .merge(P.COLOR_0 );
  946. JOINTS_0 .merge(P.JOINTS_0 );
  947. WEIGHTS_0 .merge(P.WEIGHTS_0 );
  948. INDEX .merge(P.INDEX );
  949. if(renumberIndices)
  950. {
  951. auto C = INDEX.size();
  952. for(uint32_t i=currentIndexCount; i<C; i++)
  953. {
  954. uint32_t v = INDEX.get<uint32_t>(i) + currentVertexCount;
  955. INDEX.set(i, v);
  956. assert( v == INDEX.get<uint32_t>(i) );
  957. }
  958. dc.vertexOffset = 0;
  959. }
  960. for(auto & c : P.primitives)
  961. {
  962. auto & b = primitives.emplace_back(c);
  963. b.indexOffset += static_cast<int32_t>(origIndexCount);
  964. b.vertexOffset = renumberIndices ? 0 : static_cast<int>(origVertexCount);
  965. }
  966. return dc;
  967. }
  968. throw std::runtime_error("MeshPrimitives are not similar");
  969. }
  970. /**
  971. * @brief calculateInterleavedStride
  972. * @return
  973. *
  974. * Returns the number of bytes required to copy all the attributes
  975. * in an interleaved layout: eg:
  976. *
  977. * [p0,n0,t0,p1,n1,t1...]
  978. *
  979. * The index buffer is not taken into account in the calculation
  980. */
  981. uint64_t calculateInterleavedStride() const
  982. {
  983. uint64_t stride=0;
  984. for(auto * v : { &POSITION,
  985. &NORMAL,
  986. &TANGENT,
  987. &TEXCOORD_0,
  988. &TEXCOORD_1,
  989. &COLOR_0,
  990. &JOINTS_0,
  991. &WEIGHTS_0})
  992. {
  993. if(v->attributeCount() > 0)
  994. stride += v->getAttributeSize();
  995. }
  996. return stride;
  997. }
  998. /**
  999. * @brief calculateBoundingSphereRadius
  1000. * @param p
  1001. * @return
  1002. *
  1003. * Calculate the bounding sphere of a specific primitive.
  1004. * The center of the sphere is positioned at the origin. If the primitive
  1005. * is fully in some quadrant, then the center of the sphere is still at the origin
  1006. */
  1007. template<typename PositionType=std::array<float,3>, typename IndexComponentType=uint32_t>
  1008. float calculateBoundingSphereRadius(Primitive const & p) const
  1009. {
  1010. float _Max=0.0f;
  1011. forEachVertexIndex(INDEX, p, [&_Max, this](IndexComponentType i)
  1012. {
  1013. auto r = POSITION.at< PositionType >(i);
  1014. auto R2 = r[0]*r[0] + r[1]*r[1] + r[2]*r[2];
  1015. _Max = std::max( _Max, R2 );
  1016. });
  1017. return std::sqrt(_Max);
  1018. }
  1019. template<typename PositionType=std::array<float,3>, typename IndexComponentType=uint32_t>
  1020. float calculateBoundingSphereRadius() const
  1021. {
  1022. auto P = getDrawCall();
  1023. return calculateBoundingSphereRadius(P);
  1024. }
  1025. /**
  1026. * @brief copySequential
  1027. * @param data
  1028. * @return
  1029. *
  1030. * Copies all the vertex attributes sequentually into the provided buffer
  1031. * and returns the total number of vertices copied.
  1032. *
  1033. *
  1034. * [p0,n0,t0,p1,n1,t1...]
  1035. *
  1036. *
  1037. */
  1038. inline uint64_t copyVertexAttributesInterleaved(void * data, uint64_t offset=0) const
  1039. {
  1040. return copyVertexAttributesInterleaved(static_cast<uint8_t*>(data)+offset,
  1041. { &POSITION,
  1042. &NORMAL,
  1043. &TANGENT,
  1044. &TEXCOORD_0,
  1045. &TEXCOORD_1,
  1046. &COLOR_0,
  1047. &JOINTS_0,
  1048. &WEIGHTS_0});
  1049. }
  1050. /**
  1051. * @brief copyVertexAttributesInterleaved
  1052. * @param data
  1053. * @param attrs
  1054. * @return
  1055. *
  1056. * Given a list of VertexAttribute pointers, copy them interleaved into data_write_ptr
  1057. * Eg:
  1058. * copyVertexAttributeInterleaved(buffer, (&M.POSITION, &M.NORMAL, &M.TEXCOORD_0});
  1059. *
  1060. * will write the following information to buffer
  1061. *
  1062. * buffer [p0,n0,t0,p1,n1,t1,p2,n2,t2...]
  1063. *
  1064. * Returns the total number of vertices written.
  1065. *
  1066. * Requires: * All attributes must have the same number of vertices
  1067. * * data_write_ptr must have enough sequental data to write all attribute data
  1068. *
  1069. */
  1070. template<typename T>
  1071. static uint64_t copyVertexAttributesInterleaved(T * data_write_ptr, std::vector<VertexAttribute const*> const &attrs)
  1072. {
  1073. auto stride = gul::calculateInterleavedStride(attrs);
  1074. uint64_t vCount = attrs.front()->attributeCount();
  1075. uint64_t offset = 0;
  1076. for(auto * v : attrs)
  1077. {
  1078. if(v->size() == 0)
  1079. continue;
  1080. v->strideCopyOffset(
  1081. data_write_ptr,
  1082. stride,
  1083. offset,
  1084. 0,
  1085. vCount
  1086. );
  1087. offset += v->getAttributeSize();
  1088. }
  1089. return vCount;
  1090. }
  1091. template<typename T>
  1092. static uint64_t copyVertexAttributesInterleaved(std::vector<T> & dataVec, std::vector<VertexAttribute const*> const &attrs)
  1093. {
  1094. uint64_t vertexStride = 0;
  1095. uint64_t vertexCount = attrs.front()->attributeCount();
  1096. for(auto * v : attrs)
  1097. {
  1098. vertexStride += v->getAttributeSize();
  1099. }
  1100. auto totalBytes = vertexCount * vertexStride;
  1101. dataVec.resize( totalBytes / sizeof(T) );
  1102. copyVertexAttributesInterleaved(dataVec.data(), attrs);
  1103. return vertexCount*vertexStride;
  1104. }
  1105. /**
  1106. * @brief copyVertexAttributesSquential
  1107. * @param data
  1108. * @return
  1109. *
  1110. * Copies the data in sequential layout and retuns the offsets for each
  1111. * attribute.
  1112. *
  1113. * eg:
  1114. *
  1115. * p0,p1,p2,n0,n1,n2,t0,t1,t2...
  1116. *
  1117. * The index buffer is always placed at the end
  1118. */
  1119. std::vector<uint64_t> copyVertexAttributesSquential(void * data) const
  1120. {
  1121. //auto vertexCount = getVertexCount();
  1122. std::vector<uint64_t> offsets;
  1123. uint64_t offset=0;
  1124. for(auto * v : { &POSITION,
  1125. &NORMAL,
  1126. &TANGENT,
  1127. &TEXCOORD_0,
  1128. &TEXCOORD_1,
  1129. &COLOR_0,
  1130. &JOINTS_0,
  1131. &WEIGHTS_0,
  1132. &INDEX})
  1133. {
  1134. if(!v->empty())
  1135. {
  1136. offsets.push_back(offset);
  1137. //auto attrSize = v->getAttributeSize();
  1138. auto count = v->attributeCount();
  1139. assert( count * v->getAttributeSize() <= v->m_data.size());
  1140. std::memcpy( static_cast<uint8_t*>(data)+offset, v->m_data.data(), count * v->getAttributeSize());
  1141. offset += count * v->getAttributeSize();
  1142. }
  1143. else
  1144. {
  1145. offsets.push_back(0);
  1146. }
  1147. }
  1148. return offsets;
  1149. }
  1150. /**
  1151. * @brief copyIndex
  1152. * @param data
  1153. * @return
  1154. *
  1155. * Copy the index buffer
  1156. */
  1157. uint64_t copyIndex(void * data) const
  1158. {
  1159. std::memcpy(data, INDEX.m_data.data(), INDEX.m_data.size());
  1160. return INDEX.m_data.size();
  1161. }
  1162. /**
  1163. * @brief getVertexByteSize
  1164. * @return
  1165. *
  1166. * Returns the size in byte of the vertrex in bytes if all the
  1167. * attributes were interleaved
  1168. */
  1169. uint64_t getVertexByteSize() const
  1170. {
  1171. return calculateInterleavedStride();
  1172. }
  1173. inline uint64_t calculateInterleavedBufferSize() const
  1174. {
  1175. return getVertexByteSize() * vertexCount();
  1176. }
  1177. /**
  1178. * @brief fuseVertices
  1179. *
  1180. * Fuse near by vertices. This may not be accurate
  1181. */
  1182. void fuseVertices()
  1183. {
  1184. using _vec2 = std::array<float,2>;
  1185. using _vec3 = std::array<float,3>;
  1186. using _ivec3 = std::array<int32_t,3>;
  1187. std::map< std::tuple<int32_t, int32_t, int32_t>, uint32_t> posToIndex;
  1188. auto & _POS = POSITION;
  1189. auto & _NOR = NORMAL;
  1190. auto & _UV = TEXCOORD_0;
  1191. auto & _INDEX = INDEX;
  1192. std::vector<_vec3> NEW_POS;
  1193. std::vector<_vec3> NEW_NOR;
  1194. std::vector<_vec2> NEW_UV;
  1195. uint32_t index = 0;
  1196. //uint32_t j = 0;
  1197. auto vCount = vertexCount();
  1198. for(uint32_t j=0;j<vCount;j++)
  1199. {
  1200. auto p = _POS.at<_vec3>(j);
  1201. _ivec3 P{ int32_t(p[0]*100.0f) , int32_t(p[1]*100.0f) , int32_t(p[2]*100.0f) };
  1202. if( posToIndex.insert( { {P[0], P[1], P[2]}, index }).second)
  1203. {
  1204. NEW_POS.push_back(p);
  1205. if(!_NOR.empty())
  1206. NEW_NOR.push_back(_NOR.at<_vec3>(j));
  1207. if(!_UV.empty())
  1208. NEW_UV.push_back(_UV.at<_vec2>(j));
  1209. index++;
  1210. }
  1211. }
  1212. std::vector<uint32_t> newINDEX;
  1213. for(uint32_t j=0;j<_INDEX.attributeCount();j++)
  1214. {
  1215. auto i = _INDEX.at<uint32_t>(j);
  1216. auto p = _POS.at<_vec3>(i);
  1217. _ivec3 P{ int32_t(p[0]*100.0f) , int32_t(p[1]*100.0f) , int32_t(p[2]*100.0f) };
  1218. newINDEX.push_back( posToIndex.at({P[0],P[1],P[2]}) );
  1219. }
  1220. INDEX = newINDEX;
  1221. POSITION = NEW_POS;
  1222. NORMAL = NEW_NOR;
  1223. TEXCOORD_0 = NEW_UV;
  1224. }
  1225. /**
  1226. * @brief rebuildNormals
  1227. *
  1228. * Recalculate the normals for each vertex. Normals are calculated as the average
  1229. * of the face normals attached to the vertex
  1230. */
  1231. void rebuildNormals()
  1232. {
  1233. //using _vec2 = std::array<float,2>;
  1234. using _vec3 = std::array<float,3>;
  1235. {
  1236. auto & I = INDEX;
  1237. auto & P = POSITION;
  1238. std::vector< _vec3 > normals(P.attributeCount(), _vec3({0,0,0}));
  1239. auto iC = I.attributeCount();
  1240. for(size_t j=0; j< iC; j+=3)
  1241. {
  1242. auto i0 = I.at<uint32_t>(j);
  1243. auto i1 = I.at<uint32_t>(j+1);
  1244. auto i2 = I.at<uint32_t>(j+2);
  1245. assert(i0 < vertexCount());
  1246. assert(i1 < vertexCount());
  1247. assert(i2 < vertexCount());
  1248. auto p0 = P.at<_vec3>(i0);
  1249. auto p1 = P.at<_vec3>(i1);
  1250. auto p2 = P.at<_vec3>(i2);
  1251. decltype(p0) v1, v2;
  1252. v1[0] = p1[0] - p0[0];
  1253. v1[1] = p1[1] - p0[1];
  1254. v1[2] = p1[2] - p0[2];
  1255. v2[0] = p2[0] - p0[0];
  1256. v2[1] = p2[1] - p0[1];
  1257. v2[2] = p2[2] - p0[2];
  1258. auto & x = v1;
  1259. auto & y = v2;
  1260. _vec3 n = {
  1261. x[1] * y[2] - y[1] * x[2],
  1262. x[2] * y[0] - y[2] * x[0],
  1263. x[0] * y[1] - y[0] * x[1] };
  1264. normals[i0][0] += n[0];
  1265. normals[i1][0] += n[0];
  1266. normals[i2][0] += n[0];
  1267. normals[i0][1] += n[1];
  1268. normals[i1][1] += n[1];
  1269. normals[i2][1] += n[1];
  1270. normals[i0][2] += n[2];
  1271. normals[i1][2] += n[2];
  1272. normals[i2][2] += n[2];
  1273. }
  1274. for(auto & n : normals)
  1275. {
  1276. auto L = 1.0f / std::sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
  1277. n[0] *= L;
  1278. n[1] *= L;
  1279. n[2] *= L;
  1280. }
  1281. NORMAL = normals;
  1282. }
  1283. }
  1284. };
  1285. /**
  1286. * @brief translateMesh
  1287. * @param M
  1288. * @param x
  1289. * @param y
  1290. * @param z
  1291. *
  1292. * Adds {x,y,z} to each position value
  1293. */
  1294. inline void translateMesh(MeshPrimitive & M, float x, float y, float z)
  1295. {
  1296. auto & pos = M.POSITION;
  1297. auto totalCount = pos.size();
  1298. auto numComp = pos.getNumComponents();
  1299. switch(numComp)
  1300. {
  1301. case 1:
  1302. for(uint32_t i=0;i<totalCount;i++)
  1303. {
  1304. pos.set<float>(i, pos.get<float>(i)+x);
  1305. }
  1306. break;
  1307. case 2:
  1308. for(uint32_t i=0;i<totalCount;i+=2)
  1309. {
  1310. pos.set<float>(i, pos.get<float>(i)+x);
  1311. pos.set<float>(i+1, pos.get<float>(i+1)+y);
  1312. }
  1313. break;
  1314. case 3:
  1315. for(uint32_t i=0;i<totalCount;i+=3)
  1316. {
  1317. pos.set<float>(i, pos.get<float>(i)+x);
  1318. pos.set<float>(i+1, pos.get<float>(i+1)+y);
  1319. pos.set<float>(i+2, pos.get<float>(i+2)+z);
  1320. }
  1321. break;
  1322. }
  1323. }
  1324. /**
  1325. * @brief Box
  1326. * @param dx
  1327. * @param dy
  1328. * @param dz
  1329. * @return
  1330. *
  1331. * Create a box mesh with side lengths (dx,dy,dz)
  1332. */
  1333. inline MeshPrimitive Box(float dx , float dy , float dz )
  1334. {
  1335. using _vec2 = std::array<float,2>;
  1336. using _vec3 = std::array<float,3>;
  1337. MeshPrimitive M;
  1338. auto & P = M.POSITION;
  1339. auto & N = M.NORMAL;
  1340. auto & U = M.TEXCOORD_0;
  1341. auto & I = M.INDEX;
  1342. // | Position | UV | Normal |
  1343. P.push_back( _vec3{0.0f - 0.5f*dx ,0.0f - 0.5f*dy ,dz -0.5f*dz} ) ; U.push_back( _vec2{0.0f,0.0f}) ; N.push_back( _vec3{0.0f, 0.0f, 1.0f}) ;
  1344. P.push_back( _vec3{dx - 0.5f*dx ,0.0f - 0.5f*dy ,dz -0.5f*dz} ) ; U.push_back( _vec2{1.0f,0.0f}) ; N.push_back( _vec3{0.0f, 0.0f, 1.0f}) ;
  1345. P.push_back( _vec3{dx - 0.5f*dx ,dy - 0.5f*dy ,dz -0.5f*dz} ) ; U.push_back( _vec2{1.0f,1.0f}) ; N.push_back( _vec3{0.0f, 0.0f, 1.0f}) ;
  1346. P.push_back( _vec3{0.0f - 0.5f*dx ,0.0f - 0.5f*dy ,dz -0.5f*dz} ) ; U.push_back( _vec2{0.0f,0.0f}) ; N.push_back( _vec3{0.0f, 0.0f, 1.0f}) ;
  1347. P.push_back( _vec3{dx - 0.5f*dx ,dy - 0.5f*dy ,dz -0.5f*dz} ) ; U.push_back( _vec2{1.0f,1.0f}) ; N.push_back( _vec3{0.0f, 0.0f, 1.0f}) ;
  1348. P.push_back( _vec3{0.0f - 0.5f*dx ,dy - 0.5f*dy ,dz -0.5f*dz} ) ; U.push_back( _vec2{0.0f,1.0f}) ; N.push_back( _vec3{0.0f, 0.0f, 1.0f}) ;
  1349. P.push_back( _vec3{0.0f - 0.5f*dx ,dy - 0.5f*dy ,0.0f -0.5f*dz} ) ; U.push_back( _vec2{0.0f,1.0f}) ; N.push_back( _vec3{0.0f, 0.0f, -1.0f}) ;
  1350. P.push_back( _vec3{dx - 0.5f*dx ,dy - 0.5f*dy ,0.0f -0.5f*dz} ) ; U.push_back( _vec2{1.0f,1.0f}) ; N.push_back( _vec3{0.0f, 0.0f, -1.0f}) ;
  1351. P.push_back( _vec3{dx - 0.5f*dx ,0.0f - 0.5f*dy ,0.0f -0.5f*dz} ) ; U.push_back( _vec2{1.0f,0.0f}) ; N.push_back( _vec3{0.0f, 0.0f, -1.0f}) ;
  1352. P.push_back( _vec3{0.0f - 0.5f*dx ,dy - 0.5f*dy ,0.0f -0.5f*dz} ) ; U.push_back( _vec2{0.0f,1.0f}) ; N.push_back( _vec3{0.0f, 0.0f, -1.0f}) ;
  1353. P.push_back( _vec3{dx - 0.5f*dx ,0.0f - 0.5f*dy ,0.0f -0.5f*dz} ) ; U.push_back( _vec2{1.0f,0.0f}) ; N.push_back( _vec3{0.0f, 0.0f, -1.0f}) ;
  1354. P.push_back( _vec3{0.0f - 0.5f*dx ,0.0f - 0.5f*dy ,0.0f -0.5f*dz} ) ; U.push_back( _vec2{0.0f,0.0f}) ; N.push_back( _vec3{0.0f, 0.0f, -1.0f}) ;
  1355. P.push_back( _vec3{0.0f - 0.5f*dx ,0.0f - 0.5f*dy ,0.0f -0.5f*dz} ) ; U.push_back( _vec2{0.0f,0.0f}) ; N.push_back( _vec3{-1.0f, 0.0f, 0.0f }) ;
  1356. P.push_back( _vec3{0.0f - 0.5f*dx ,0.0f - 0.5f*dy ,dz -0.5f*dz} ) ; U.push_back( _vec2{1.0f,0.0f}) ; N.push_back( _vec3{-1.0f, 0.0f, 0.0f }) ;
  1357. P.push_back( _vec3{0.0f - 0.5f*dx ,dy - 0.5f*dy ,dz -0.5f*dz} ) ; U.push_back( _vec2{1.0f,1.0f}) ; N.push_back( _vec3{-1.0f, 0.0f, 0.0f }) ;
  1358. P.push_back( _vec3{0.0f - 0.5f*dx ,0.0f - 0.5f*dy ,0.0f -0.5f*dz} ) ; U.push_back( _vec2{0.0f,0.0f}) ; N.push_back( _vec3{-1.0f, 0.0f, 0.0f }) ;
  1359. P.push_back( _vec3{0.0f - 0.5f*dx ,dy - 0.5f*dy ,dz -0.5f*dz} ) ; U.push_back( _vec2{1.0f,1.0f}) ; N.push_back( _vec3{-1.0f, 0.0f, 0.0f }) ;
  1360. P.push_back( _vec3{0.0f - 0.5f*dx ,dy - 0.5f*dy ,0.0f -0.5f*dz} ) ; U.push_back( _vec2{0.0f,1.0f}) ; N.push_back( _vec3{-1.0f, 0.0f, 0.0f }) ;
  1361. P.push_back( _vec3{dx - 0.5f*dx ,dy - 0.5f*dy ,0.0f -0.5f*dz} ) ; U.push_back( _vec2{0.0f,1.0f}) ; N.push_back( _vec3{1.0f, 0.0f, 0.0f }) ;
  1362. P.push_back( _vec3{dx - 0.5f*dx ,dy - 0.5f*dy ,dz -0.5f*dz} ) ; U.push_back( _vec2{1.0f,1.0f}) ; N.push_back( _vec3{1.0f, 0.0f, 0.0f }) ;
  1363. P.push_back( _vec3{dx - 0.5f*dx ,0.0f - 0.5f*dy ,dz -0.5f*dz} ) ; U.push_back( _vec2{1.0f,0.0f}) ; N.push_back( _vec3{1.0f, 0.0f, 0.0f }) ;
  1364. P.push_back( _vec3{dx - 0.5f*dx ,dy - 0.5f*dy ,0.0f -0.5f*dz} ) ; U.push_back( _vec2{0.0f,1.0f}) ; N.push_back( _vec3{1.0f, 0.0f, 0.0f }) ;
  1365. P.push_back( _vec3{dx - 0.5f*dx ,0.0f - 0.5f*dy ,dz -0.5f*dz} ) ; U.push_back( _vec2{1.0f,0.0f}) ; N.push_back( _vec3{1.0f, 0.0f, 0.0f }) ;
  1366. P.push_back( _vec3{dx - 0.5f*dx ,0.0f - 0.5f*dy ,0.0f -0.5f*dz} ) ; U.push_back( _vec2{0.0f,0.0f}) ; N.push_back( _vec3{1.0f, 0.0f, 0.0f }) ;
  1367. P.push_back( _vec3{0.0f - 0.5f*dx ,0.0f - 0.5f*dy ,0.0f -0.5f*dz} ) ; U.push_back( _vec2{0.0f,0.0f}) ; N.push_back( _vec3{0.0f,-1.0f, 0.0f }) ;
  1368. P.push_back( _vec3{dx - 0.5f*dx ,0.0f - 0.5f*dy ,0.0f -0.5f*dz} ) ; U.push_back( _vec2{1.0f,0.0f}) ; N.push_back( _vec3{0.0f,-1.0f, 0.0f }) ;
  1369. P.push_back( _vec3{dx - 0.5f*dx ,0.0f - 0.5f*dy ,dz -0.5f*dz} ) ; U.push_back( _vec2{1.0f,1.0f}) ; N.push_back( _vec3{0.0f,-1.0f, 0.0f }) ;
  1370. P.push_back( _vec3{0.0f - 0.5f*dx ,0.0f - 0.5f*dy ,0.0f -0.5f*dz} ) ; U.push_back( _vec2{0.0f,0.0f}) ; N.push_back( _vec3{0.0f,-1.0f, 0.0f }) ;
  1371. P.push_back( _vec3{dx - 0.5f*dx ,0.0f - 0.5f*dy ,dz -0.5f*dz} ) ; U.push_back( _vec2{1.0f,1.0f}) ; N.push_back( _vec3{0.0f,-1.0f, 0.0f }) ;
  1372. P.push_back( _vec3{0.0f - 0.5f*dx ,0.0f - 0.5f*dy ,dz -0.5f*dz} ) ; U.push_back( _vec2{0.0f,1.0f}) ; N.push_back( _vec3{0.0f,-1.0f, 0.0f }) ;
  1373. P.push_back( _vec3{0.0f - 0.5f*dx ,dy - 0.5f*dy ,dz -0.5f*dz} ) ; U.push_back( _vec2{0.0f,1.0f}) ; N.push_back( _vec3{0.0f, 1.0f, 0.0f }) ;
  1374. P.push_back( _vec3{dx - 0.5f*dx ,dy - 0.5f*dy ,dz -0.5f*dz} ) ; U.push_back( _vec2{1.0f,1.0f}) ; N.push_back( _vec3{0.0f, 1.0f, 0.0f }) ;
  1375. P.push_back( _vec3{dx - 0.5f*dx ,dy - 0.5f*dy ,0.0f -0.5f*dz} ) ; U.push_back( _vec2{1.0f,0.0f}) ; N.push_back( _vec3{0.0f, 1.0f, 0.0f }) ;
  1376. P.push_back( _vec3{0.0f - 0.5f*dx ,dy - 0.5f*dy ,dz -0.5f*dz} ) ; U.push_back( _vec2{0.0f,1.0f}) ; N.push_back( _vec3{0.0f, 1.0f, 0.0f }) ;
  1377. P.push_back( _vec3{dx - 0.5f*dx ,dy - 0.5f*dy ,0.0f -0.5f*dz} ) ; U.push_back( _vec2{1.0f,0.0f}) ; N.push_back( _vec3{0.0f, 1.0f, 0.0f }) ;
  1378. P.push_back( _vec3{0.0f - 0.5f*dx ,dy - 0.5f*dy ,0.0f -0.5f*dz} ) ; U.push_back( _vec2{0.0f,0.0f}) ; N.push_back( _vec3{0.0f, 1.0f, 0.0f }) ;
  1379. //=========================
  1380. // Edges of the triangle : postion delta
  1381. //=========================
  1382. I.init(eComponentType::UNSIGNED_INT, eType::SCALAR);
  1383. for( uint32_t j=0;j<36;j++)
  1384. I.push_back( j );
  1385. {
  1386. auto & dc = M.primitives.emplace_back();
  1387. dc.indexOffset = static_cast<int32_t>(0);
  1388. dc.vertexOffset = static_cast<int32_t>(0);
  1389. dc.vertexCount = static_cast<uint32_t>(M.vertexCount());
  1390. dc.indexCount = static_cast<uint32_t>(M.indexCount());
  1391. dc.topology = gul::Topology::TRIANGLE_LIST;
  1392. }
  1393. return M;
  1394. }
  1395. inline MeshPrimitive Box(float dx )
  1396. {
  1397. return Box(dx,dx,dx);
  1398. }
  1399. /**
  1400. * @brief Grid
  1401. * @param length - length of the grid
  1402. * @param width - width of the grid
  1403. * @param dl - grid line spacing in the length dimension
  1404. * @param dw - grid line spacing in the width dimension
  1405. * @param majorL -
  1406. * @param majorW
  1407. * @param lscale
  1408. * @param wscale
  1409. * @return
  1410. *
  1411. * Return a grid mesh. Attributes: POSITION, COLOR
  1412. */
  1413. inline MeshPrimitive Grid(int length, int width, int dl=1, int dw=1, int majorL=5, int majorW=5, float lscale=1.0f, float wscale=1.0f)
  1414. {
  1415. using _vec3 = std::array<float,3>;
  1416. using _uvec4 = std::array<uint8_t,4>;
  1417. MeshPrimitive M;
  1418. M.topology = Topology::LINE_LIST;
  1419. auto & P = M.POSITION;
  1420. auto & C = M.COLOR_0;
  1421. //_uvec4 xColor{1,1,1,255};
  1422. _uvec4 xColor{80,80,80,255};
  1423. _uvec4 majorColor{128,128,128,255};
  1424. // _uvec4 minorColor{255,0,0,255};
  1425. _uvec4 borderColor{255,255,255,255};
  1426. for(int x=-length;x<=length;x+=dl)
  1427. {
  1428. _vec3 p0{ static_cast<float>(x)*lscale, 0.0f, static_cast<float>(-width)*wscale };
  1429. _vec3 p1{ static_cast<float>(x)*lscale, 0.0f, static_cast<float>( width)*wscale };
  1430. P.push_back(p0);
  1431. P.push_back(p1);
  1432. if( x == -length || x==length)
  1433. {
  1434. C.push_back(borderColor);
  1435. C.push_back(borderColor);
  1436. }
  1437. else if( x % majorL==0)
  1438. {
  1439. C.push_back(majorColor);
  1440. C.push_back(majorColor);
  1441. }
  1442. else
  1443. {
  1444. C.push_back(xColor);
  1445. C.push_back(xColor);
  1446. }
  1447. }
  1448. for(int x=-width;x<=width;x+=dw)
  1449. {
  1450. _vec3 p0{ static_cast<float>( length)*lscale, 0.0, static_cast<float>(x)*wscale };
  1451. _vec3 p1{ static_cast<float>(-length)*lscale, 0.0, static_cast<float>(x)*wscale };
  1452. P.push_back(p0);
  1453. P.push_back(p1);
  1454. if( x == -length || x==length)
  1455. {
  1456. C.push_back(borderColor);
  1457. C.push_back(borderColor);
  1458. }
  1459. else if( x % majorW==0)
  1460. {
  1461. C.push_back(majorColor);
  1462. C.push_back(majorColor);
  1463. }
  1464. else
  1465. {
  1466. C.push_back(xColor);
  1467. C.push_back(xColor);
  1468. }
  1469. }
  1470. {
  1471. auto & dc = M.primitives.emplace_back();
  1472. dc.indexOffset = static_cast<int32_t>(0);
  1473. dc.vertexOffset = static_cast<int32_t>(0);
  1474. dc.vertexCount = static_cast<uint32_t>(M.vertexCount());
  1475. dc.indexCount = static_cast<uint32_t>(M.indexCount());
  1476. dc.topology = gul::Topology::TRIANGLE_LIST;
  1477. }
  1478. return M;
  1479. }
  1480. /**
  1481. * @brief Sphere
  1482. * @param radius
  1483. * @param rings
  1484. * @param sectors
  1485. * @return
  1486. *
  1487. * Return a sphere mesh
  1488. */
  1489. inline MeshPrimitive Sphere(float radius , uint32_t rings=20, uint32_t sectors=20)
  1490. {
  1491. using _vec2 = std::array<float,2>;
  1492. using _vec3 = std::array<float,3>;
  1493. MeshPrimitive M;
  1494. auto & P = M.POSITION;
  1495. auto & N = M.NORMAL;
  1496. auto & U = M.TEXCOORD_0;
  1497. auto & I = M.INDEX;
  1498. float const R = 1.0f / static_cast<float>(rings-1);
  1499. float const S = 1.0f / static_cast<float>(sectors-1);
  1500. unsigned int r, s;
  1501. for(r = 0; r < rings; r++)
  1502. {
  1503. auto rf = static_cast<float>(r);
  1504. for(s = 0; s < sectors; s++)
  1505. {
  1506. auto sf = static_cast<float>(s);
  1507. float const y = std::sin( -3.141592653589f*0.5f + 3.141592653589f * rf * R );
  1508. float const x = std::cos(2*3.141592653589f * sf * S) * std::sin( 3.141592653589f * rf * R );
  1509. float const z = std::sin(2*3.141592653589f * sf * S) * std::sin( 3.141592653589f * rf * R );
  1510. P.push_back( _vec3{ radius*x ,radius*y ,radius*z} );
  1511. U.push_back( _vec2{sf*S, rf*R} );
  1512. N.push_back( _vec3{x,y,z} );
  1513. }
  1514. }
  1515. I.init(eComponentType::UNSIGNED_INT, eType::SCALAR);
  1516. for(r = 0 ; r < rings - 1 ; r++)
  1517. {
  1518. for(s = 0 ; s < sectors - 1 ; s++)
  1519. {
  1520. I.push_back( static_cast<uint32_t>( (r+1) * sectors + s) ); //0
  1521. I.push_back( static_cast<uint32_t>( (r+1) * sectors + (s+1) ) ); //1
  1522. I.push_back( static_cast<uint32_t>( r * sectors + (s+1) )); //2
  1523. I.push_back( static_cast<uint32_t>( (r+1) * sectors + s )); //0
  1524. I.push_back( static_cast<uint32_t>( r * sectors + (s+1) )); //2
  1525. I.push_back( static_cast<uint32_t>( r * sectors + s )); //3
  1526. }
  1527. }
  1528. {
  1529. auto & dc = M.primitives.emplace_back();
  1530. dc.indexOffset = static_cast<int32_t>(0);
  1531. dc.vertexOffset = static_cast<int32_t>(0);
  1532. dc.vertexCount = static_cast<uint32_t>(M.vertexCount());
  1533. dc.indexCount = static_cast<uint32_t>(M.indexCount());
  1534. dc.topology = gul::Topology::TRIANGLE_LIST;
  1535. }
  1536. return M;
  1537. }
  1538. /**
  1539. * @brief Cylinder
  1540. * @param R
  1541. * @param H
  1542. * @param rSegments
  1543. * @return
  1544. *
  1545. * Return a cylinder mesh
  1546. */
  1547. inline MeshPrimitive Cylinder(float R=1.0f, float H=3.0f, uint32_t rSegments=16)
  1548. {
  1549. using _vec2 = std::array<float,2>;
  1550. using _vec3 = std::array<float,3>;
  1551. MeshPrimitive M;
  1552. std::vector<_vec3> P;// = M.POSITION; //[ vka2::PrimitiveAttribute::POSITION ];
  1553. std::vector<_vec3> N;// = M.NORMAL; //[ vka2::PrimitiveAttribute::NORMAL ];
  1554. std::vector<_vec2> U;// = M.TEXCOORD_0;//[ vka2::PrimitiveAttribute::TEXCOORD_0 ];
  1555. std::vector<uint32_t> I;// = M.INDEX;
  1556. float dt = 2.0f * 3.141592653589f / static_cast<float>(rSegments);
  1557. float t = 0;
  1558. if(1)
  1559. {
  1560. for(uint32_t r=0 ; r<rSegments; r++)
  1561. {
  1562. _vec3 p{ R*std::cos(t) , R * std::sin(t), 0 };
  1563. t += dt;
  1564. P.push_back(p);
  1565. N.push_back( _vec3{ std::cos(t), std::sin(t), 0.f } );
  1566. U.push_back( _vec2{ t, 0} );
  1567. }
  1568. for(uint32_t r=0 ; r<rSegments; r++)
  1569. {
  1570. _vec3 p{ R*std::cos(t) , R * std::sin(t), H };
  1571. t += dt;
  1572. P.push_back(p);
  1573. N.push_back( _vec3{ std::cos(t), std::sin(t), 0.f } );
  1574. U.push_back( _vec2{ t, 1} );
  1575. }
  1576. for(uint32_t i=0 ; i < rSegments; ++i)
  1577. {
  1578. const uint32_t a = (i + 0) % rSegments;
  1579. const uint32_t b = (i + 1) % rSegments;
  1580. const uint32_t c = b + rSegments;
  1581. const uint32_t d = a + rSegments;
  1582. I.push_back( static_cast<uint32_t>(a) );
  1583. I.push_back( static_cast<uint32_t>(b) );
  1584. I.push_back( static_cast<uint32_t>(c) );
  1585. I.push_back( static_cast<uint32_t>(a) );
  1586. I.push_back( static_cast<uint32_t>(c) );
  1587. I.push_back( static_cast<uint32_t>(d) );
  1588. }
  1589. M.INDEX = I;
  1590. M.POSITION = P;
  1591. M.NORMAL = N;
  1592. M.TEXCOORD_0 = U;
  1593. }
  1594. if(1)
  1595. { // top cap
  1596. MeshPrimitive M2;
  1597. std::vector<_vec3> P2;// = M2.POSITION; //[ vka2::PrimitiveAttribute::POSITION ];
  1598. std::vector<_vec3> N2;// = M2.NORMAL; //[ vka2::PrimitiveAttribute::NORMAL ];
  1599. std::vector<_vec2> U2;// = M2.TEXCOORD_0;//[ vka2::PrimitiveAttribute::TEXCOORD_0 ];
  1600. std::vector<std::array<uint32_t,3> > I2;// = M2.INDEX;
  1601. t = 0;
  1602. P2.push_back( _vec3{ 0.f, 0.f, H});
  1603. N2.push_back( _vec3{ 0.f, 0.f, 1.f } );
  1604. U2.push_back( _vec2{ 0.5f, 0.5f } );
  1605. for(uint32_t r=0 ; r < rSegments; r++)
  1606. {
  1607. _vec3 p{ R * std::cos(t) , R * std::sin(t), H };
  1608. t += dt;
  1609. P2.push_back(p);
  1610. N2.push_back( _vec3{ 0.f, 0.f, 1.f } );
  1611. U2.push_back( _vec2{ 0.5f+std::cos(t), 0.5f+std::sin(t)} );
  1612. const uint32_t A = 0;
  1613. const uint32_t B = static_cast<uint32_t>(r+1);
  1614. const uint32_t C = static_cast<uint32_t>( (r+1)%rSegments+1 );
  1615. I2.push_back( std::array<uint32_t,3>({A,B,C}));
  1616. }
  1617. M2.POSITION = P2;
  1618. M2.NORMAL = N2;
  1619. M2.TEXCOORD_0 = U2;
  1620. M2.INDEX = I2;
  1621. M.merge(M2, true);
  1622. // bottom cap.
  1623. if(1)
  1624. {
  1625. for(auto & p : P2)
  1626. p[2] = 0.0f;
  1627. for(auto & p : N2) // flip normals
  1628. {
  1629. p[0] *= -1.f;
  1630. p[1] *= -1.f;
  1631. p[2] *= -1.f;
  1632. }
  1633. for(auto & p : I2) // reverse winding order
  1634. {
  1635. std::swap(p[0], p[2]);
  1636. }
  1637. M2.INDEX = I2;
  1638. M2.POSITION = P2;
  1639. M2.NORMAL = N2;
  1640. M2.TEXCOORD_0 = U2;
  1641. M.merge(M2, true);
  1642. }
  1643. }
  1644. {
  1645. auto & dc = M.primitives.emplace_back();
  1646. dc.indexOffset = static_cast<int32_t>(0);
  1647. dc.vertexOffset = static_cast<int32_t>(0);
  1648. dc.vertexCount = static_cast<uint32_t>(M.vertexCount());
  1649. dc.indexCount = static_cast<uint32_t>(M.indexCount());
  1650. dc.topology = gul::Topology::TRIANGLE_LIST;
  1651. }
  1652. return M;
  1653. }
  1654. /**
  1655. * @brief Imposter
  1656. * @return
  1657. *
  1658. * An imposter is a simple quad in the XY plane with normal in the +Z direction
  1659. */
  1660. inline MeshPrimitive Imposter(float sideLength=1.0f)
  1661. {
  1662. MeshPrimitive M;
  1663. using _vec2 = std::array<float,2>;
  1664. using _vec3 = std::array<float,3>;
  1665. auto & P = M.POSITION;
  1666. auto & N = M.NORMAL;
  1667. auto & I = M.INDEX;
  1668. auto & U = M.TEXCOORD_0;
  1669. P.push_back( _vec3{-sideLength,-sideLength,0});
  1670. P.push_back( _vec3{ sideLength,-sideLength,0});
  1671. P.push_back( _vec3{ sideLength, sideLength,0});
  1672. P.push_back( _vec3{-sideLength, sideLength,0});
  1673. U.push_back( _vec2{0.0f, 1.0f});
  1674. U.push_back( _vec2{1.0f, 1.0f});
  1675. U.push_back( _vec2{1.0f, 0.0f});
  1676. U.push_back( _vec2{0.0f, 0.0f});
  1677. N.push_back(_vec3{0,0,1});
  1678. N.push_back(_vec3{0,0,1});
  1679. N.push_back(_vec3{0,0,1});
  1680. N.push_back(_vec3{0,0,1});
  1681. I = std::vector<uint32_t>{0,1,2,0,2,3};
  1682. {
  1683. auto & dc = M.primitives.emplace_back();
  1684. dc.indexOffset = static_cast<int32_t>(0);
  1685. dc.vertexOffset = static_cast<int32_t>(0);
  1686. dc.vertexCount = static_cast<uint32_t>(M.vertexCount());
  1687. dc.indexCount = static_cast<uint32_t>(M.indexCount());
  1688. dc.topology = gul::Topology::TRIANGLE_LIST;
  1689. }
  1690. return M;
  1691. }
  1692. /**
  1693. * @brief revolve
  1694. * @param XYpoints - pointer to numPoints*2 float values
  1695. * @param numPoints - total number of points
  1696. * @return
  1697. *
  1698. * Given a set of points in the XY plane, revolve the curve around
  1699. * the Z-axis
  1700. */
  1701. inline MeshPrimitive revolve(float const * XYpoints, size_t numPoints, size_t segments=10)
  1702. {
  1703. using _vec2 = std::array<float,2>;
  1704. using _vec3 = std::array<float,3>;
  1705. MeshPrimitive M;
  1706. std::vector< _vec3 > position;
  1707. std::vector< _vec3 > normal;
  1708. std::vector< _vec2 > uv;
  1709. std::vector<uint32_t> indices;
  1710. for(size_t k=0;k<segments+1;k++)
  1711. {
  1712. float t = ( float(k) / float(segments-1) );
  1713. float th = ( float(k) / float(segments) ) * 2.0f * 3.141592653589f;
  1714. for(size_t i=0;i<numPoints;i++)
  1715. {
  1716. if(k < segments)
  1717. {
  1718. float s = ( float(i) / float(numPoints-1) );
  1719. float R = XYpoints[2*i+1];
  1720. float xp = XYpoints[2*i];
  1721. float yp = R * std::cos(th);
  1722. float zp = R * std::sin(th);
  1723. position.push_back( _vec3{{ xp,yp,zp}} );
  1724. uv.push_back({s,t});
  1725. }
  1726. }
  1727. }
  1728. assert( position.size() == numPoints*segments);
  1729. auto totalPoints = position.size();
  1730. for(uint32_t k=0;k<segments;k++)
  1731. {
  1732. for(uint32_t i=0;i<numPoints-1;i++)
  1733. {
  1734. auto a = k * numPoints + i;
  1735. auto b = k * numPoints + i+1;
  1736. auto c = ( (k+1) * numPoints + i ) % totalPoints;
  1737. auto d = ( (k+1) * numPoints + i+1) % totalPoints;
  1738. indices.push_back(uint32_t(b));
  1739. indices.push_back(uint32_t(a));
  1740. indices.push_back(uint32_t(c));
  1741. indices.push_back(uint32_t(c));
  1742. indices.push_back(uint32_t(d));
  1743. indices.push_back(uint32_t(b));
  1744. }
  1745. }
  1746. M.POSITION = position;
  1747. M.INDEX = indices;
  1748. M.TEXCOORD_0 = uv;
  1749. M.rebuildNormals();
  1750. {
  1751. auto & dc = M.primitives.emplace_back();
  1752. dc.indexOffset = static_cast<int32_t>(0);
  1753. dc.vertexOffset = static_cast<int32_t>(0);
  1754. dc.vertexCount = static_cast<uint32_t>(M.vertexCount());
  1755. dc.indexCount = static_cast<uint32_t>(M.indexCount());
  1756. dc.topology = gul::Topology::TRIANGLE_LIST;
  1757. }
  1758. return M;
  1759. }
  1760. inline MeshPrimitive Arrow(float bodyLength, float bodyRadius, float headLength, float headRadius)
  1761. {
  1762. auto bl = bodyLength;
  1763. auto br = bodyRadius;
  1764. auto hl = headLength;
  1765. auto hr = headRadius;
  1766. std::vector<float> points;
  1767. points.push_back( 0 );
  1768. points.push_back( 0 );
  1769. points.push_back( 0 );
  1770. points.push_back( br );
  1771. points.push_back( 0 );
  1772. points.push_back( br );
  1773. points.push_back( bl );
  1774. points.push_back( br );
  1775. points.push_back( bl );
  1776. points.push_back( br );
  1777. points.push_back( bl );
  1778. points.push_back( hr );
  1779. points.push_back( bl );
  1780. points.push_back( hr );
  1781. points.push_back( hl+bl );
  1782. points.push_back( 0 );
  1783. return revolve(points.data(), points.size()/2, 10 );
  1784. }
  1785. inline MeshPrimitive ReadOBJ(std::ifstream & in)
  1786. {
  1787. using _vec2 = std::array<float,2>;
  1788. using _vec3 = std::array<float,3>;
  1789. std::vector< _vec3 > position;
  1790. std::vector< _vec3 > normal;
  1791. std::vector< _vec2 > uv;
  1792. struct faceIndex
  1793. {
  1794. uint32_t p=0;
  1795. uint32_t t=0;
  1796. uint32_t n=0;
  1797. };
  1798. std::vector< faceIndex > quads;
  1799. std::vector< faceIndex > tris;
  1800. auto split = [](std::string s, std::string delimiter)
  1801. {
  1802. using namespace std;
  1803. size_t pos_start = 0, pos_end, delim_len = delimiter.length();
  1804. string token;
  1805. vector<string> res;
  1806. while ((pos_end = s.find (delimiter, pos_start)) != string::npos) {
  1807. token = s.substr (pos_start, pos_end - pos_start);
  1808. pos_start = pos_end + delim_len;
  1809. res.push_back (token);
  1810. }
  1811. res.push_back (s.substr (pos_start));
  1812. return res;
  1813. };
  1814. auto getFace = [&](std::string s) -> faceIndex
  1815. {
  1816. faceIndex F;
  1817. auto S = split(s, "/");
  1818. if(S.size() == 3)
  1819. {
  1820. F.p = static_cast<uint32_t>(std::stoi( S[0] ));
  1821. if( S[1].size() != 0)
  1822. F.t = static_cast<uint32_t>(std::stoi(S[1]));
  1823. if( S[2].size() != 0)
  1824. F.n = static_cast<uint32_t>(std::stoi(S[2]));
  1825. return F;
  1826. }
  1827. else if(S.size() == 1)
  1828. {
  1829. F.p = static_cast<uint32_t>(std::stoi( S[0] ));
  1830. }
  1831. return F;
  1832. };
  1833. while(!in.eof())
  1834. {
  1835. std::string line;
  1836. std::string fullLine;
  1837. std::getline(in, fullLine);
  1838. std::istringstream ins(fullLine);
  1839. ins >> line;
  1840. if(line == "v")
  1841. {
  1842. _vec3 p;
  1843. ins >> p[0];
  1844. ins >> p[1];
  1845. ins >> p[2];
  1846. position.push_back(p);
  1847. }
  1848. else if(line == "vn")
  1849. {
  1850. _vec3 p;
  1851. ins >> p[0];
  1852. ins >> p[1];
  1853. ins >> p[2];
  1854. normal.push_back(p);
  1855. }
  1856. else if(line == "vt")
  1857. {
  1858. _vec2 p;
  1859. ins >> p[0];
  1860. ins >> p[1];
  1861. uv.push_back(p);
  1862. }
  1863. else if(line == "f")
  1864. {
  1865. std::string faceLine;
  1866. if(fullLine.front() == 'f')
  1867. {
  1868. faceLine = fullLine.substr(2);
  1869. }
  1870. auto sp = split(faceLine, " ");
  1871. if(sp.size() == 4)
  1872. {
  1873. for(auto & v : sp)
  1874. {
  1875. faceIndex Fa = getFace(v);
  1876. quads.push_back(Fa);
  1877. }
  1878. }
  1879. if(sp.size() == 3)
  1880. {
  1881. for(auto & v : sp)
  1882. {
  1883. faceIndex Fa = getFace(v);
  1884. tris.push_back(Fa);
  1885. }
  1886. }
  1887. //std::cout << faceLine << std::endl;
  1888. }
  1889. else
  1890. {
  1891. //std::string bah;
  1892. //std::getline(in, bah);
  1893. // std::cout << line << std::endl;
  1894. }
  1895. }
  1896. gul::MeshPrimitive M;
  1897. std::vector<_vec3> POSITION;
  1898. std::vector<_vec2> TEXCOORD;
  1899. std::vector<_vec3> NORMAL;
  1900. std::vector<uint32_t> INDEX;
  1901. for(size_t i=0;i<tris.size(); i+= 3)
  1902. {
  1903. auto & I1 = tris[i];
  1904. auto & I2 = tris[i+1];
  1905. auto & I3 = tris[i+2];
  1906. POSITION.push_back(position[I1.p-1]);
  1907. POSITION.push_back(position[I2.p-1]);
  1908. POSITION.push_back(position[I3.p-1]);
  1909. if(I1.n*I2.n*I3.n > 0 )
  1910. {
  1911. NORMAL.push_back(normal[I1.n-1]);
  1912. NORMAL.push_back(normal[I2.n-1]);
  1913. NORMAL.push_back(normal[I3.n-1]);
  1914. }
  1915. if(I1.t*I2.t*I3.t > 0 )
  1916. {
  1917. TEXCOORD.push_back(uv[I1.t-1]);
  1918. TEXCOORD.push_back(uv[I2.t-1]);
  1919. TEXCOORD.push_back(uv[I3.t-1]);
  1920. }
  1921. }
  1922. for(size_t i=0;i<quads.size(); i+= 4)
  1923. {
  1924. auto & I1 = quads[i];
  1925. auto & I2 = quads[i+1];
  1926. auto & I3 = quads[i+2];
  1927. auto & I4 = quads[i+3];
  1928. POSITION.push_back(position[I1.p - 1]);
  1929. POSITION.push_back(position[I2.p - 1]);
  1930. POSITION.push_back(position[I3.p - 1]);
  1931. POSITION.push_back(position[I1.p - 1]);
  1932. POSITION.push_back(position[I3.p - 1]);
  1933. POSITION.push_back(position[I4.p - 1]);
  1934. NORMAL.push_back(normal[I1.n - 1] );
  1935. NORMAL.push_back(normal[I2.n - 1] );
  1936. NORMAL.push_back(normal[I3.n - 1] );
  1937. NORMAL.push_back(normal[I1.n - 1] );
  1938. NORMAL.push_back(normal[I3.n - 1] );
  1939. NORMAL.push_back(normal[I4.n - 1] );
  1940. TEXCOORD.push_back(uv[I1.t - 1] );
  1941. TEXCOORD.push_back(uv[I2.t - 1] );
  1942. TEXCOORD.push_back(uv[I3.t - 1] );
  1943. TEXCOORD.push_back(uv[I1.t - 1] );
  1944. TEXCOORD.push_back(uv[I3.t - 1] );
  1945. TEXCOORD.push_back(uv[I4.t - 1] );
  1946. }
  1947. uint32_t i=0;
  1948. for(auto & x : POSITION)
  1949. {
  1950. (void)x;
  1951. INDEX.push_back(i++);
  1952. }
  1953. M.POSITION = std::move(POSITION);
  1954. M.INDEX = std::move(INDEX);
  1955. if(NORMAL.size() == 0)
  1956. {
  1957. M.rebuildNormals();
  1958. }
  1959. else
  1960. {
  1961. M.NORMAL = std::move(NORMAL);
  1962. }
  1963. M.TEXCOORD_0 = std::move(TEXCOORD);
  1964. return M;
  1965. }
  1966. }
  1967. #endif