💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

906 lines
43 KiB

  1. /*
  2. * Copyright (C) 2021 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "game/ant/morphogenesis.hpp"
  20. #include "render/material.hpp"
  21. #include "render/vertex-attribute.hpp"
  22. #include <unordered_set>
  23. #include <iostream>
  24. namespace game {
  25. namespace ant {
  26. static render::model* generate_queen(const ant::breed& breed);
  27. static render::model* generate_worker(const ant::breed& breed);
  28. static render::model* generate_soldier(const ant::breed& breed);
  29. static render::model* generate_male(const ant::breed& breed);
  30. static render::material* build_exoskeleton_material
  31. (
  32. const ant::trait::pigmentation& pigmentation,
  33. const ant::trait::sculpturing& sculpturing
  34. );
  35. static void reskin_vertices
  36. (
  37. std::uint8_t* vertex_data,
  38. std::size_t index_count,
  39. const gl::vertex_attribute& position_attribute,
  40. const gl::vertex_attribute& normal_attribute,
  41. const gl::vertex_attribute& tangent_attribute,
  42. const gl::vertex_attribute& bone_index_attribute,
  43. const std::unordered_set<std::uint16_t>& old_bone_indices,
  44. std::uint16_t new_bone_index,
  45. const math::transform<float>& transform
  46. );
  47. static geom::aabb<float> calculate_bounds(std::uint8_t* vertex_data, std::size_t index_count, const gl::vertex_attribute& position_attribute);
  48. static render::model* build_model
  49. (
  50. render::material* material,
  51. const render::model* antennae,
  52. const render::model* eyes,
  53. const render::model* forewings,
  54. const render::model* gaster,
  55. const render::model* head,
  56. const render::model* hindwings,
  57. const render::model* legs,
  58. const render::model* mandibles,
  59. const render::model* mesosoma,
  60. const render::model* lateral_ocelli,
  61. const render::model* median_ocellus,
  62. const render::model* sting,
  63. const render::model* waist
  64. );
  65. render::model* morphogenesis(const ant::breed& breed, ant::caste caste)
  66. {
  67. switch (caste)
  68. {
  69. case ant::caste::queen:
  70. return generate_queen(breed);
  71. case ant::caste::worker:
  72. return generate_worker(breed);
  73. case ant::caste::soldier:
  74. return generate_soldier(breed);
  75. case ant::caste::male:
  76. return generate_male(breed);
  77. }
  78. return nullptr;
  79. }
  80. render::model* generate_queen(const ant::breed& breed)
  81. {
  82. return nullptr;
  83. }
  84. render::model* generate_worker(const ant::breed& breed)
  85. {
  86. // Get material parameters
  87. // Build exoskeleton material
  88. render::material* exoskeleton_material = build_exoskeleton_material(*breed.pigmentation, *breed.sculpturing);
  89. // Get worker body part models
  90. render::model* antennae_model = breed.antennae->model;
  91. render::model* eyes_model = breed.eyes->model;
  92. render::model* gaster_model = breed.gaster->model;
  93. render::model* head_model = breed.head->model;
  94. render::model* legs_model = breed.legs->model;
  95. render::model* mandibles_model = breed.mandibles->model;
  96. render::model* mesosoma_model = breed.mesosoma->model;
  97. render::model* sting_model = breed.sting->model;
  98. render::model* waist_model = breed.waist->model;
  99. //render::model* lateral_ocelli_model = breed.ocelli->lateral_ocelli_model;
  100. //render::model* median_ocellus_model = breed.ocelli->median_ocellus_model;
  101. // Build worker model
  102. render::model* model = build_model
  103. (
  104. exoskeleton_material,
  105. antennae_model,
  106. eyes_model,
  107. nullptr, // forewings
  108. gaster_model,
  109. head_model,
  110. nullptr, // hindwings
  111. legs_model,
  112. mandibles_model,
  113. mesosoma_model,
  114. nullptr, // lateral ocelli
  115. nullptr, // median ocellus
  116. sting_model,
  117. waist_model
  118. );
  119. return model;
  120. }
  121. render::model* generate_soldier(const ant::breed& breed)
  122. {
  123. return nullptr;
  124. }
  125. render::model* generate_male(const ant::breed& breed)
  126. {
  127. return nullptr;
  128. }
  129. render::material* build_exoskeleton_material
  130. (
  131. const ant::trait::pigmentation& pigmentation,
  132. const ant::trait::sculpturing& sculpturing
  133. )
  134. {
  135. // Allocate copy of pigmentation material
  136. render::material* exoskeleton_material = new render::material(*pigmentation.material);
  137. // Adjust roughness parameter
  138. if (render::material_property_base* property = exoskeleton_material->get_property("roughness"); property != nullptr)
  139. {
  140. static_cast<render::material_property<float>*>(property)->set_value(sculpturing.roughness);
  141. }
  142. else
  143. {
  144. exoskeleton_material->add_property<float>("roughness")->set_value(sculpturing.roughness);
  145. }
  146. // Adjust normal map parameter
  147. if (render::material_property_base* property = exoskeleton_material->get_property("normal_map"); property != nullptr)
  148. {
  149. static_cast<render::material_property<const gl::texture_2d*>*>(property)->set_value(sculpturing.normal_map);
  150. }
  151. else
  152. {
  153. exoskeleton_material->add_property<const gl::texture_2d*>("normal_map")->set_value(sculpturing.normal_map);
  154. }
  155. return exoskeleton_material;
  156. }
  157. render::model* build_model
  158. (
  159. render::material* exoskeleton_material,
  160. const render::model* antennae,
  161. const render::model* eyes,
  162. const render::model* forewings,
  163. const render::model* gaster,
  164. const render::model* head,
  165. const render::model* hindwings,
  166. const render::model* legs,
  167. const render::model* mandibles,
  168. const render::model* mesosoma,
  169. const render::model* lateral_ocelli,
  170. const render::model* median_ocellus,
  171. const render::model* sting,
  172. const render::model* waist
  173. )
  174. {
  175. // Get vertex buffers of required body parts
  176. const gl::vertex_buffer* mesosoma_vbo = mesosoma->get_vertex_buffer();
  177. const gl::vertex_buffer* legs_vbo = legs->get_vertex_buffer();
  178. const gl::vertex_buffer* head_vbo = head->get_vertex_buffer();
  179. const gl::vertex_buffer* mandibles_vbo = mandibles->get_vertex_buffer();
  180. const gl::vertex_buffer* antennae_vbo = antennae->get_vertex_buffer();
  181. const gl::vertex_buffer* waist_vbo = waist->get_vertex_buffer();
  182. const gl::vertex_buffer* gaster_vbo = gaster->get_vertex_buffer();
  183. // Get vertex buffers of optional body parts
  184. const gl::vertex_buffer* sting_vbo = (sting) ? sting->get_vertex_buffer() : nullptr;
  185. const gl::vertex_buffer* eyes_vbo = (eyes) ? eyes->get_vertex_buffer() : nullptr;
  186. const gl::vertex_buffer* lateral_ocelli_vbo = (lateral_ocelli) ? lateral_ocelli->get_vertex_buffer() : nullptr;
  187. const gl::vertex_buffer* median_ocellus_vbo = (median_ocellus) ? median_ocellus->get_vertex_buffer() : nullptr;
  188. const gl::vertex_buffer* forewings_vbo = (forewings) ? forewings->get_vertex_buffer() : nullptr;
  189. const gl::vertex_buffer* hindwings_vbo = (hindwings) ? hindwings->get_vertex_buffer() : nullptr;
  190. // Determine combined size of vertex buffers and save offsets
  191. std::size_t vertex_buffer_size = 0;
  192. std::size_t mesosoma_vbo_offset = vertex_buffer_size;
  193. vertex_buffer_size += mesosoma_vbo->get_size();
  194. std::size_t legs_vbo_offset = vertex_buffer_size;
  195. vertex_buffer_size += legs_vbo->get_size();
  196. std::size_t head_vbo_offset = vertex_buffer_size;
  197. vertex_buffer_size += head_vbo->get_size();
  198. std::size_t mandibles_vbo_offset = vertex_buffer_size;
  199. vertex_buffer_size += mandibles_vbo->get_size();
  200. std::size_t antennae_vbo_offset = vertex_buffer_size;
  201. vertex_buffer_size += antennae_vbo->get_size();
  202. std::size_t waist_vbo_offset = vertex_buffer_size;
  203. vertex_buffer_size += waist_vbo->get_size();
  204. std::size_t gaster_vbo_offset = vertex_buffer_size;
  205. vertex_buffer_size += gaster_vbo->get_size();
  206. std::size_t sting_vbo_offset = vertex_buffer_size;
  207. if (sting)
  208. vertex_buffer_size += sting_vbo->get_size();
  209. std::size_t eyes_vbo_offset = vertex_buffer_size;
  210. if (eyes)
  211. vertex_buffer_size += eyes_vbo->get_size();
  212. std::size_t lateral_ocelli_vbo_offset = vertex_buffer_size;
  213. if (lateral_ocelli)
  214. vertex_buffer_size += lateral_ocelli_vbo->get_size();
  215. std::size_t median_ocellus_vbo_offset = vertex_buffer_size;
  216. if (median_ocellus)
  217. vertex_buffer_size += median_ocellus_vbo->get_size();
  218. std::size_t forewings_vbo_offset = vertex_buffer_size;
  219. if (forewings)
  220. vertex_buffer_size += forewings_vbo->get_size();
  221. std::size_t hindwings_vbo_offset = vertex_buffer_size;
  222. if (hindwings)
  223. vertex_buffer_size += hindwings_vbo->get_size();
  224. // Allocate combined vertex buffer data
  225. std::uint8_t* vertex_buffer_data = new std::uint8_t[vertex_buffer_size];
  226. // Read body part vertex buffer data into combined vertex buffer data
  227. mesosoma_vbo->read(0, mesosoma_vbo->get_size(), vertex_buffer_data + mesosoma_vbo_offset);
  228. legs_vbo->read(0, legs_vbo->get_size(), vertex_buffer_data + legs_vbo_offset);
  229. head_vbo->read(0, head_vbo->get_size(), vertex_buffer_data + head_vbo_offset);
  230. mandibles_vbo->read(0, mandibles_vbo->get_size(), vertex_buffer_data + mandibles_vbo_offset);
  231. antennae_vbo->read(0, antennae_vbo->get_size(), vertex_buffer_data + antennae_vbo_offset);
  232. waist_vbo->read(0, waist_vbo->get_size(), vertex_buffer_data + waist_vbo_offset);
  233. gaster_vbo->read(0, gaster_vbo->get_size(), vertex_buffer_data + gaster_vbo_offset);
  234. if (sting)
  235. sting_vbo->read(0, sting_vbo->get_size(), vertex_buffer_data + sting_vbo_offset);
  236. if (eyes)
  237. eyes_vbo->read(0, eyes_vbo->get_size(), vertex_buffer_data + eyes_vbo_offset);
  238. if (lateral_ocelli)
  239. lateral_ocelli_vbo->read(0, lateral_ocelli_vbo->get_size(), vertex_buffer_data + lateral_ocelli_vbo_offset);
  240. if (median_ocellus)
  241. median_ocellus_vbo->read(0, median_ocellus_vbo->get_size(), vertex_buffer_data + median_ocellus_vbo_offset);
  242. if (forewings)
  243. forewings_vbo->read(0, forewings_vbo->get_size(), vertex_buffer_data + forewings_vbo_offset);
  244. if (hindwings)
  245. hindwings_vbo->read(0, hindwings_vbo->get_size(), vertex_buffer_data + hindwings_vbo_offset);
  246. // Allocate model
  247. render::model* model = new render::model();
  248. // Setup model VAO
  249. gl::vertex_array* model_vao = model->get_vertex_array();
  250. for (auto [location, attribute]: mesosoma->get_vertex_array()->get_attributes())
  251. {
  252. attribute.buffer = model->get_vertex_buffer();
  253. model_vao->bind(location, attribute);
  254. }
  255. // Get vertex attributes
  256. const gl::vertex_attribute* position_attribute = nullptr;
  257. const gl::vertex_attribute* normal_attribute = nullptr;
  258. const gl::vertex_attribute* tangent_attribute = nullptr;
  259. const gl::vertex_attribute* bone_index_attribute = nullptr;
  260. const auto& vertex_attribute_map = model_vao->get_attributes();
  261. if (auto it = vertex_attribute_map.find(render::vertex_attribute::position); it != vertex_attribute_map.end())
  262. position_attribute = &it->second;
  263. if (auto it = vertex_attribute_map.find(render::vertex_attribute::normal); it != vertex_attribute_map.end())
  264. normal_attribute = &it->second;
  265. if (auto it = vertex_attribute_map.find(render::vertex_attribute::tangent); it != vertex_attribute_map.end())
  266. tangent_attribute = &it->second;
  267. if (auto it = vertex_attribute_map.find(render::vertex_attribute::bone_index); it != vertex_attribute_map.end())
  268. bone_index_attribute = &it->second;
  269. // Get body part skeletons
  270. const render::skeleton& mesosoma_skeleton = mesosoma->get_skeleton();
  271. const render::skeleton& legs_skeleton = legs->get_skeleton();
  272. const render::skeleton& head_skeleton = head->get_skeleton();
  273. const render::skeleton& mandibles_skeleton = mandibles->get_skeleton();
  274. const render::skeleton& antennae_skeleton = antennae->get_skeleton();
  275. const render::skeleton& waist_skeleton = waist->get_skeleton();
  276. const render::skeleton& gaster_skeleton = gaster->get_skeleton();
  277. const render::skeleton* sting_skeleton = (sting) ? &sting->get_skeleton() : nullptr;
  278. const render::skeleton* eyes_skeleton = (eyes) ? &eyes->get_skeleton() : nullptr;
  279. const render::skeleton* lateral_ocelli_skeleton = (lateral_ocelli) ? &lateral_ocelli->get_skeleton() : nullptr;
  280. const render::skeleton* median_ocellus_skeleton = (median_ocellus) ? &median_ocellus->get_skeleton() : nullptr;
  281. bool postpetiole = (waist_skeleton.bone_map.find("postpetiole") != waist_skeleton.bone_map.end());
  282. // Allocate skeleton bones
  283. render::skeleton& skeleton = model->get_skeleton();
  284. std::size_t bone_count = 34;
  285. if (postpetiole)
  286. bone_count += 1;
  287. if (sting)
  288. bone_count += 1;
  289. if (forewings)
  290. bone_count += 2;
  291. if (hindwings)
  292. bone_count += 2;
  293. skeleton.bones.resize(bone_count);
  294. // Assign bone indices
  295. std::uint16_t bone_index = 0;
  296. std::uint16_t mesosoma_bone_index = bone_index++;
  297. std::uint16_t foreleg_coxa_l_bone_index = bone_index++;
  298. std::uint16_t foreleg_coxa_r_bone_index = bone_index++;
  299. std::uint16_t foreleg_femur_l_bone_index = bone_index++;
  300. std::uint16_t foreleg_femur_r_bone_index = bone_index++;
  301. std::uint16_t foreleg_tibia_l_bone_index = bone_index++;
  302. std::uint16_t foreleg_tibia_r_bone_index = bone_index++;
  303. std::uint16_t foreleg_tarsus_l_bone_index = bone_index++;
  304. std::uint16_t foreleg_tarsus_r_bone_index = bone_index++;
  305. std::uint16_t midleg_coxa_l_bone_index = bone_index++;
  306. std::uint16_t midleg_coxa_r_bone_index = bone_index++;
  307. std::uint16_t midleg_femur_l_bone_index = bone_index++;
  308. std::uint16_t midleg_femur_r_bone_index = bone_index++;
  309. std::uint16_t midleg_tibia_l_bone_index = bone_index++;
  310. std::uint16_t midleg_tibia_r_bone_index = bone_index++;
  311. std::uint16_t midleg_tarsus_l_bone_index = bone_index++;
  312. std::uint16_t midleg_tarsus_r_bone_index = bone_index++;
  313. std::uint16_t hindleg_coxa_l_bone_index = bone_index++;
  314. std::uint16_t hindleg_coxa_r_bone_index = bone_index++;
  315. std::uint16_t hindleg_femur_l_bone_index = bone_index++;
  316. std::uint16_t hindleg_femur_r_bone_index = bone_index++;
  317. std::uint16_t hindleg_tibia_l_bone_index = bone_index++;
  318. std::uint16_t hindleg_tibia_r_bone_index = bone_index++;
  319. std::uint16_t hindleg_tarsus_l_bone_index = bone_index++;
  320. std::uint16_t hindleg_tarsus_r_bone_index = bone_index++;
  321. std::uint16_t head_bone_index = bone_index++;
  322. std::uint16_t mandible_l_bone_index = bone_index++;
  323. std::uint16_t mandible_r_bone_index = bone_index++;
  324. std::uint16_t scape_l_bone_index = bone_index++;
  325. std::uint16_t scape_r_bone_index = bone_index++;
  326. std::uint16_t pedicel_l_bone_index = bone_index++;
  327. std::uint16_t pedicel_r_bone_index = bone_index++;
  328. std::uint16_t petiole_bone_index = bone_index++;
  329. std::uint16_t postpetiole_bone_index = (postpetiole) ? bone_index++ : static_cast<std::uint16_t>(bone_count);
  330. std::uint16_t gaster_bone_index = bone_index++;
  331. std::uint16_t sting_bone_index = (sting) ? bone_index++ : static_cast<std::uint16_t>(bone_count);
  332. // Get references and pointers to bones
  333. render::bone& mesosoma_bone = skeleton.bones[mesosoma_bone_index];
  334. render::bone& foreleg_coxa_l_bone = skeleton.bones[foreleg_coxa_l_bone_index];
  335. render::bone& foreleg_coxa_r_bone = skeleton.bones[foreleg_coxa_r_bone_index];
  336. render::bone& foreleg_femur_l_bone = skeleton.bones[foreleg_femur_l_bone_index];
  337. render::bone& foreleg_femur_r_bone = skeleton.bones[foreleg_femur_r_bone_index];
  338. render::bone& foreleg_tibia_l_bone = skeleton.bones[foreleg_tibia_l_bone_index];
  339. render::bone& foreleg_tibia_r_bone = skeleton.bones[foreleg_tibia_r_bone_index];
  340. render::bone& foreleg_tarsus_l_bone = skeleton.bones[foreleg_tarsus_l_bone_index];
  341. render::bone& foreleg_tarsus_r_bone = skeleton.bones[foreleg_tarsus_r_bone_index];
  342. render::bone& midleg_coxa_l_bone = skeleton.bones[midleg_coxa_l_bone_index];
  343. render::bone& midleg_coxa_r_bone = skeleton.bones[midleg_coxa_r_bone_index];
  344. render::bone& midleg_femur_l_bone = skeleton.bones[midleg_femur_l_bone_index];
  345. render::bone& midleg_femur_r_bone = skeleton.bones[midleg_femur_r_bone_index];
  346. render::bone& midleg_tibia_l_bone = skeleton.bones[midleg_tibia_l_bone_index];
  347. render::bone& midleg_tibia_r_bone = skeleton.bones[midleg_tibia_r_bone_index];
  348. render::bone& midleg_tarsus_l_bone = skeleton.bones[midleg_tarsus_l_bone_index];
  349. render::bone& midleg_tarsus_r_bone = skeleton.bones[midleg_tarsus_r_bone_index];
  350. render::bone& hindleg_coxa_l_bone = skeleton.bones[hindleg_coxa_l_bone_index];
  351. render::bone& hindleg_coxa_r_bone = skeleton.bones[hindleg_coxa_r_bone_index];
  352. render::bone& hindleg_femur_l_bone = skeleton.bones[hindleg_femur_l_bone_index];
  353. render::bone& hindleg_femur_r_bone = skeleton.bones[hindleg_femur_r_bone_index];
  354. render::bone& hindleg_tibia_l_bone = skeleton.bones[hindleg_tibia_l_bone_index];
  355. render::bone& hindleg_tibia_r_bone = skeleton.bones[hindleg_tibia_r_bone_index];
  356. render::bone& hindleg_tarsus_l_bone = skeleton.bones[hindleg_tarsus_l_bone_index];
  357. render::bone& hindleg_tarsus_r_bone = skeleton.bones[hindleg_tarsus_r_bone_index];
  358. render::bone& head_bone = skeleton.bones[head_bone_index];
  359. render::bone& mandible_l_bone = skeleton.bones[mandible_l_bone_index];
  360. render::bone& mandible_r_bone = skeleton.bones[mandible_r_bone_index];
  361. render::bone& scape_l_bone = skeleton.bones[scape_l_bone_index];
  362. render::bone& scape_r_bone = skeleton.bones[scape_r_bone_index];
  363. render::bone& pedicel_l_bone = skeleton.bones[pedicel_l_bone_index];
  364. render::bone& pedicel_r_bone = skeleton.bones[pedicel_r_bone_index];
  365. render::bone& petiole_bone = skeleton.bones[petiole_bone_index];
  366. render::bone* postpetiole_bone = (postpetiole) ? &skeleton.bones[postpetiole_bone_index] : nullptr;
  367. render::bone& gaster_bone = skeleton.bones[gaster_bone_index];
  368. render::bone* sting_bone = (sting) ? &skeleton.bones[sting_bone_index] : nullptr;
  369. // Skeleton mesosoma
  370. if (auto it = mesosoma_skeleton.bone_map.find("mesosoma"); it != mesosoma_skeleton.bone_map.end())
  371. mesosoma_bone = mesosoma_skeleton.bones[it->second];
  372. mesosoma_bone.parent = nullptr;
  373. // Skeleton forelegs
  374. if (auto it = legs_skeleton.bone_map.find("foreleg_coxa_l"); it != legs_skeleton.bone_map.end())
  375. foreleg_coxa_l_bone = legs_skeleton.bones[it->second];
  376. foreleg_coxa_l_bone.parent = &mesosoma_bone;
  377. if (auto it = legs_skeleton.bone_map.find("foreleg_coxa_r"); it != legs_skeleton.bone_map.end())
  378. foreleg_coxa_r_bone = legs_skeleton.bones[it->second];
  379. foreleg_coxa_r_bone.parent = &mesosoma_bone;
  380. if (auto it = legs_skeleton.bone_map.find("foreleg_femur_l"); it != legs_skeleton.bone_map.end())
  381. foreleg_femur_l_bone = legs_skeleton.bones[it->second];
  382. foreleg_femur_l_bone.parent = &foreleg_coxa_l_bone;
  383. if (auto it = legs_skeleton.bone_map.find("foreleg_femur_r"); it != legs_skeleton.bone_map.end())
  384. foreleg_femur_r_bone = legs_skeleton.bones[it->second];
  385. foreleg_femur_r_bone.parent = &foreleg_coxa_r_bone;
  386. if (auto it = legs_skeleton.bone_map.find("foreleg_tibia_l"); it != legs_skeleton.bone_map.end())
  387. foreleg_tibia_l_bone = legs_skeleton.bones[it->second];
  388. foreleg_tibia_l_bone.parent = &foreleg_femur_l_bone;
  389. if (auto it = legs_skeleton.bone_map.find("foreleg_tibia_r"); it != legs_skeleton.bone_map.end())
  390. foreleg_tibia_r_bone = legs_skeleton.bones[it->second];
  391. foreleg_tibia_r_bone.parent = &foreleg_femur_r_bone;
  392. if (auto it = legs_skeleton.bone_map.find("foreleg_tarsus_l"); it != legs_skeleton.bone_map.end())
  393. foreleg_tarsus_l_bone = legs_skeleton.bones[it->second];
  394. foreleg_tarsus_l_bone.parent = &foreleg_tibia_l_bone;
  395. if (auto it = legs_skeleton.bone_map.find("foreleg_tarsus_r"); it != legs_skeleton.bone_map.end())
  396. foreleg_tarsus_r_bone = legs_skeleton.bones[it->second];
  397. foreleg_tarsus_r_bone.parent = &foreleg_tibia_r_bone;
  398. // Skeleton midlegs
  399. if (auto it = legs_skeleton.bone_map.find("midleg_coxa_l"); it != legs_skeleton.bone_map.end())
  400. midleg_coxa_l_bone = legs_skeleton.bones[it->second];
  401. midleg_coxa_l_bone.parent = &mesosoma_bone;
  402. if (auto it = legs_skeleton.bone_map.find("midleg_coxa_r"); it != legs_skeleton.bone_map.end())
  403. midleg_coxa_r_bone = legs_skeleton.bones[it->second];
  404. midleg_coxa_r_bone.parent = &mesosoma_bone;
  405. if (auto it = legs_skeleton.bone_map.find("midleg_femur_l"); it != legs_skeleton.bone_map.end())
  406. midleg_femur_l_bone = legs_skeleton.bones[it->second];
  407. midleg_femur_l_bone.parent = &midleg_coxa_l_bone;
  408. if (auto it = legs_skeleton.bone_map.find("midleg_femur_r"); it != legs_skeleton.bone_map.end())
  409. midleg_femur_r_bone = legs_skeleton.bones[it->second];
  410. midleg_femur_r_bone.parent = &midleg_coxa_r_bone;
  411. if (auto it = legs_skeleton.bone_map.find("midleg_tibia_l"); it != legs_skeleton.bone_map.end())
  412. midleg_tibia_l_bone = legs_skeleton.bones[it->second];
  413. midleg_tibia_l_bone.parent = &midleg_femur_l_bone;
  414. if (auto it = legs_skeleton.bone_map.find("midleg_tibia_r"); it != legs_skeleton.bone_map.end())
  415. midleg_tibia_r_bone = legs_skeleton.bones[it->second];
  416. midleg_tibia_r_bone.parent = &midleg_femur_r_bone;
  417. if (auto it = legs_skeleton.bone_map.find("midleg_tarsus_l"); it != legs_skeleton.bone_map.end())
  418. midleg_tarsus_l_bone = legs_skeleton.bones[it->second];
  419. midleg_tarsus_l_bone.parent = &midleg_tibia_l_bone;
  420. if (auto it = legs_skeleton.bone_map.find("midleg_tarsus_r"); it != legs_skeleton.bone_map.end())
  421. midleg_tarsus_r_bone = legs_skeleton.bones[it->second];
  422. midleg_tarsus_r_bone.parent = &midleg_tibia_r_bone;
  423. // Skeleton hindlegs
  424. if (auto it = legs_skeleton.bone_map.find("hindleg_coxa_l"); it != legs_skeleton.bone_map.end())
  425. hindleg_coxa_l_bone = legs_skeleton.bones[it->second];
  426. hindleg_coxa_l_bone.parent = &mesosoma_bone;
  427. if (auto it = legs_skeleton.bone_map.find("hindleg_coxa_r"); it != legs_skeleton.bone_map.end())
  428. hindleg_coxa_r_bone = legs_skeleton.bones[it->second];
  429. hindleg_coxa_r_bone.parent = &mesosoma_bone;
  430. if (auto it = legs_skeleton.bone_map.find("hindleg_femur_l"); it != legs_skeleton.bone_map.end())
  431. hindleg_femur_l_bone = legs_skeleton.bones[it->second];
  432. hindleg_femur_l_bone.parent = &hindleg_coxa_l_bone;
  433. if (auto it = legs_skeleton.bone_map.find("hindleg_femur_r"); it != legs_skeleton.bone_map.end())
  434. hindleg_femur_r_bone = legs_skeleton.bones[it->second];
  435. hindleg_femur_r_bone.parent = &hindleg_coxa_r_bone;
  436. if (auto it = legs_skeleton.bone_map.find("hindleg_tibia_l"); it != legs_skeleton.bone_map.end())
  437. hindleg_tibia_l_bone = legs_skeleton.bones[it->second];
  438. hindleg_tibia_l_bone.parent = &hindleg_femur_l_bone;
  439. if (auto it = legs_skeleton.bone_map.find("hindleg_tibia_r"); it != legs_skeleton.bone_map.end())
  440. hindleg_tibia_r_bone = legs_skeleton.bones[it->second];
  441. hindleg_tibia_r_bone.parent = &hindleg_femur_r_bone;
  442. if (auto it = legs_skeleton.bone_map.find("hindleg_tarsus_l"); it != legs_skeleton.bone_map.end())
  443. hindleg_tarsus_l_bone = legs_skeleton.bones[it->second];
  444. hindleg_tarsus_l_bone.parent = &hindleg_tibia_l_bone;
  445. if (auto it = legs_skeleton.bone_map.find("hindleg_tarsus_r"); it != legs_skeleton.bone_map.end())
  446. hindleg_tarsus_r_bone = legs_skeleton.bones[it->second];
  447. hindleg_tarsus_r_bone.parent = &hindleg_tibia_r_bone;
  448. // Skeleton head
  449. if (auto it = head_skeleton.bone_map.find("head"); it != head_skeleton.bone_map.end())
  450. head_bone = head_skeleton.bones[it->second];
  451. head_bone.parent = &mesosoma_bone;
  452. // Skeleton mandibles
  453. if (auto it = mandibles_skeleton.bone_map.find("mandible_l"); it != mandibles_skeleton.bone_map.end())
  454. mandible_l_bone = mandibles_skeleton.bones[it->second];
  455. mandible_l_bone.parent = &head_bone;
  456. if (auto it = mandibles_skeleton.bone_map.find("mandible_r"); it != mandibles_skeleton.bone_map.end())
  457. mandible_r_bone = mandibles_skeleton.bones[it->second];
  458. mandible_r_bone.parent = &head_bone;
  459. // Skeleton antennae
  460. if (auto it = antennae_skeleton.bone_map.find("scape_l"); it != antennae_skeleton.bone_map.end())
  461. scape_l_bone = antennae_skeleton.bones[it->second];
  462. scape_l_bone.parent = &head_bone;
  463. if (auto it = antennae_skeleton.bone_map.find("scape_r"); it != antennae_skeleton.bone_map.end())
  464. scape_r_bone = antennae_skeleton.bones[it->second];
  465. scape_r_bone.parent = &head_bone;
  466. if (auto it = antennae_skeleton.bone_map.find("pedicel_l"); it != antennae_skeleton.bone_map.end())
  467. pedicel_l_bone = antennae_skeleton.bones[it->second];
  468. pedicel_l_bone.parent = &scape_l_bone;
  469. if (auto it = antennae_skeleton.bone_map.find("pedicel_r"); it != antennae_skeleton.bone_map.end())
  470. pedicel_r_bone = antennae_skeleton.bones[it->second];
  471. pedicel_r_bone.parent = &scape_r_bone;
  472. // Skeleton waist
  473. if (auto it = waist_skeleton.bone_map.find("petiole"); it != waist_skeleton.bone_map.end())
  474. petiole_bone = waist_skeleton.bones[it->second];
  475. petiole_bone.parent = &mesosoma_bone;
  476. if (postpetiole)
  477. {
  478. if (auto it = waist_skeleton.bone_map.find("postpetiole"); it != waist_skeleton.bone_map.end())
  479. *postpetiole_bone = waist_skeleton.bones[it->second];
  480. postpetiole_bone->parent = &petiole_bone;
  481. }
  482. // Skeleton gaster
  483. if (auto it = gaster_skeleton.bone_map.find("gaster"); it != gaster_skeleton.bone_map.end())
  484. gaster_bone = gaster_skeleton.bones[it->second];
  485. gaster_bone.parent = (postpetiole) ? postpetiole_bone : &petiole_bone;
  486. // Skeleton sting
  487. if (sting)
  488. {
  489. if (auto it = sting_skeleton->bone_map.find("sting"); it != sting_skeleton->bone_map.end())
  490. *sting_bone = sting_skeleton->bones[it->second];
  491. sting_bone->parent = &gaster_bone;
  492. }
  493. // Get number of vertex indices for each body part
  494. std::size_t mesosoma_index_count = (*mesosoma->get_groups())[0]->get_index_count();
  495. std::size_t legs_index_count = (*legs->get_groups())[0]->get_index_count();
  496. std::size_t head_index_count = (*head->get_groups())[0]->get_index_count();
  497. std::size_t mandibles_index_count = (*mandibles->get_groups())[0]->get_index_count();
  498. std::size_t antennae_index_count = (*antennae->get_groups())[0]->get_index_count();
  499. std::size_t waist_index_count = (*waist->get_groups())[0]->get_index_count();
  500. std::size_t gaster_index_count = (*gaster->get_groups())[0]->get_index_count();
  501. std::size_t sting_index_count = (sting) ? (*sting->get_groups())[0]->get_index_count() : 0;
  502. std::size_t eyes_index_count = (eyes) ? (*eyes->get_groups())[0]->get_index_count() : 0;
  503. std::size_t lateral_ocelli_index_count = (lateral_ocelli) ? (*lateral_ocelli->get_groups())[0]->get_index_count() : 0;
  504. std::size_t median_ocellus_index_count = (median_ocellus) ? (*median_ocellus->get_groups())[0]->get_index_count() : 0;
  505. std::size_t forewings_index_count = (forewings) ? (*forewings->get_groups())[0]->get_index_count() : 0;
  506. std::size_t hindwings_index_count = (hindwings) ? (*hindwings->get_groups())[0]->get_index_count() : 0;
  507. std::size_t exoskeleton_index_count =
  508. mesosoma_index_count
  509. + legs_index_count
  510. + head_index_count
  511. + mandibles_index_count
  512. + antennae_index_count
  513. + waist_index_count
  514. + gaster_index_count
  515. + sting_index_count;
  516. // Calculate transform from head space to body space
  517. math::transform<float> head_to_body;
  518. if (auto it = mesosoma_skeleton.bone_map.find("head"); it != mesosoma_skeleton.bone_map.end())
  519. head_to_body = mesosoma_skeleton.concatenate(it->second);
  520. // Reskin head bone
  521. std::unordered_set<std::uint16_t> old_head_bone_indices;
  522. if (auto it = head_skeleton.bone_map.find("head"); it != head_skeleton.bone_map.end())
  523. old_head_bone_indices.emplace(it->second);
  524. reskin_vertices(vertex_buffer_data + head_vbo_offset, head_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_head_bone_indices, head_bone_index, head_to_body);
  525. // Calculate transforms from mandible space to body space
  526. math::transform<float> mandible_l_to_body;
  527. if (auto it = head_skeleton.bone_map.find("mandible_l"); it != head_skeleton.bone_map.end())
  528. mandible_l_to_body = head_to_body * head_skeleton.concatenate(it->second);
  529. math::transform<float> mandible_r_to_body;
  530. if (auto it = head_skeleton.bone_map.find("mandible_r"); it != head_skeleton.bone_map.end())
  531. mandible_r_to_body = head_to_body * head_skeleton.concatenate(it->second);
  532. // Reskin mandible bones
  533. std::unordered_set<std::uint16_t> old_head_mandible_l_bone_indices;
  534. if (auto it = mandibles_skeleton.bone_map.find("mandible_l"); it != mandibles_skeleton.bone_map.end())
  535. old_head_mandible_l_bone_indices.emplace(it->second);
  536. reskin_vertices(vertex_buffer_data + mandibles_vbo_offset, mandibles_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_head_mandible_l_bone_indices, mandible_l_bone_index, mandible_l_to_body);
  537. std::unordered_set<std::uint16_t> old_head_mandible_r_bone_indices;
  538. if (auto it = mandibles_skeleton.bone_map.find("mandible_r"); it != mandibles_skeleton.bone_map.end())
  539. old_head_mandible_r_bone_indices.emplace(it->second);
  540. reskin_vertices(vertex_buffer_data + mandibles_vbo_offset, mandibles_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_head_mandible_r_bone_indices, mandible_r_bone_index, mandible_r_to_body);
  541. // Calculate transforms from antennae space to body space
  542. math::transform<float> antenna_l_to_body;
  543. if (auto it = head_skeleton.bone_map.find("scape_l"); it != head_skeleton.bone_map.end())
  544. antenna_l_to_body = head_to_body * head_skeleton.concatenate(it->second);
  545. math::transform<float> antenna_r_to_body;
  546. if (auto it = head_skeleton.bone_map.find("scape_r"); it != head_skeleton.bone_map.end())
  547. antenna_r_to_body = head_to_body * head_skeleton.concatenate(it->second);
  548. // Reskin scape bones
  549. std::unordered_set<std::uint16_t> old_scape_l_indices;
  550. if (auto it = antennae_skeleton.bone_map.find("scape_l"); it != antennae_skeleton.bone_map.end())
  551. old_scape_l_indices.emplace(it->second);
  552. reskin_vertices(vertex_buffer_data + antennae_vbo_offset, antennae_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_scape_l_indices, scape_l_bone_index, antenna_l_to_body);
  553. std::unordered_set<std::uint16_t> old_scape_r_indices;
  554. if (auto it = antennae_skeleton.bone_map.find("scape_r"); it != antennae_skeleton.bone_map.end())
  555. old_scape_r_indices.emplace(it->second);
  556. reskin_vertices(vertex_buffer_data + antennae_vbo_offset, antennae_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_scape_r_indices, scape_r_bone_index, antenna_r_to_body);
  557. // Reskin pedicel bones
  558. const std::vector<std::string> pedicel_bone_names =
  559. {
  560. "pedicel",
  561. "flagellomere_1",
  562. "flagellomere_2",
  563. "flagellomere_3",
  564. "flagellomere_4",
  565. "flagellomere_5",
  566. "flagellomere_6",
  567. "flagellomere_7",
  568. "flagellomere_8",
  569. "flagellomere_9",
  570. "flagellomere_10",
  571. "flagellomere_11",
  572. "flagellomere_12"
  573. };
  574. std::unordered_set<std::uint16_t> old_pedicel_l_indices;
  575. for (const std::string& bone_name: pedicel_bone_names)
  576. if (auto it = antennae_skeleton.bone_map.find(bone_name + "_l"); it != antennae_skeleton.bone_map.end())
  577. old_pedicel_l_indices.emplace(it->second);
  578. reskin_vertices(vertex_buffer_data + antennae_vbo_offset, antennae_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_pedicel_l_indices, pedicel_l_bone_index, antenna_l_to_body);
  579. std::unordered_set<std::uint16_t> old_pedicel_r_indices;
  580. for (const std::string& bone_name: pedicel_bone_names)
  581. if (auto it = antennae_skeleton.bone_map.find(bone_name + "_r"); it != antennae_skeleton.bone_map.end())
  582. old_pedicel_r_indices.emplace(it->second);
  583. reskin_vertices(vertex_buffer_data + antennae_vbo_offset, antennae_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_pedicel_r_indices, pedicel_r_bone_index, antenna_r_to_body);
  584. // Calculate transform from waist space to body space
  585. math::transform<float> waist_to_body;
  586. if (auto it = mesosoma_skeleton.bone_map.find("petiole"); it != mesosoma_skeleton.bone_map.end())
  587. waist_to_body = mesosoma_skeleton.concatenate(it->second);
  588. // Reskin waist bones
  589. std::unordered_set<std::uint16_t> old_petiole_bone_indices;
  590. if (auto it = waist_skeleton.bone_map.find("petiole"); it != waist_skeleton.bone_map.end())
  591. old_petiole_bone_indices.emplace(it->second);
  592. reskin_vertices(vertex_buffer_data + waist_vbo_offset, waist_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_petiole_bone_indices, petiole_bone_index, waist_to_body);
  593. if (postpetiole)
  594. {
  595. std::unordered_set<std::uint16_t> old_postpetiole_bone_indices;
  596. if (auto it = waist_skeleton.bone_map.find("postpetiole"); it != waist_skeleton.bone_map.end())
  597. old_postpetiole_bone_indices.emplace(it->second);
  598. reskin_vertices(vertex_buffer_data + waist_vbo_offset, waist_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_postpetiole_bone_indices, postpetiole_bone_index, waist_to_body);
  599. }
  600. // Calculate transform from gaster space to body space
  601. math::transform<float> gaster_to_body;
  602. if (auto it = waist_skeleton.bone_map.find("gaster"); it != waist_skeleton.bone_map.end())
  603. gaster_to_body = waist_to_body * waist_skeleton.concatenate(it->second);
  604. // Reskin gaster bones
  605. std::unordered_set<std::uint16_t> old_gaster_bone_indices;
  606. if (auto it = gaster_skeleton.bone_map.find("gaster"); it != gaster_skeleton.bone_map.end())
  607. old_gaster_bone_indices.emplace(it->second);
  608. reskin_vertices(vertex_buffer_data + gaster_vbo_offset, gaster_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_gaster_bone_indices, gaster_bone_index, gaster_to_body);
  609. if (sting)
  610. {
  611. // Calculate transform from sting space to body space
  612. math::transform<float> sting_to_body;
  613. if (auto it = gaster_skeleton.bone_map.find("sting"); it != gaster_skeleton.bone_map.end())
  614. sting_to_body = gaster_to_body * gaster_skeleton.concatenate(it->second);
  615. // Reskin sting bones
  616. std::unordered_set<std::uint16_t> old_sting_bone_indices;
  617. if (auto it = sting_skeleton->bone_map.find("sting"); it != sting_skeleton->bone_map.end())
  618. old_sting_bone_indices.emplace(it->second);
  619. reskin_vertices(vertex_buffer_data + sting_vbo_offset, sting_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_sting_bone_indices, sting_bone_index, sting_to_body);
  620. }
  621. if (eyes)
  622. {
  623. // Calculate transforms from eyes space to body space
  624. math::transform<float> eye_l_to_body;
  625. if (auto it = head_skeleton.bone_map.find("eye_l"); it != head_skeleton.bone_map.end())
  626. eye_l_to_body = head_to_body * head_skeleton.concatenate(it->second);
  627. math::transform<float> eye_r_to_body;
  628. if (auto it = head_skeleton.bone_map.find("eye_r"); it != head_skeleton.bone_map.end())
  629. eye_r_to_body = head_to_body * head_skeleton.concatenate(it->second);
  630. // Reskin eye bones
  631. std::unordered_set<std::uint16_t> old_eye_l_bone_indices;
  632. if (auto it = eyes_skeleton->bone_map.find("eye_l"); it != eyes_skeleton->bone_map.end())
  633. old_eye_l_bone_indices.emplace(it->second);
  634. reskin_vertices(vertex_buffer_data + eyes_vbo_offset, eyes_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_eye_l_bone_indices, head_bone_index, eye_l_to_body);
  635. std::unordered_set<std::uint16_t> old_eye_r_bone_indices;
  636. if (auto it = eyes_skeleton->bone_map.find("eye_r"); it != eyes_skeleton->bone_map.end())
  637. old_eye_r_bone_indices.emplace(it->second);
  638. reskin_vertices(vertex_buffer_data + eyes_vbo_offset, eyes_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_eye_r_bone_indices, head_bone_index, eye_r_to_body);
  639. }
  640. if (lateral_ocelli)
  641. {
  642. // Calculate transforms from lateral ocelli space to body space
  643. math::transform<float> ocellus_l_to_body;
  644. if (auto it = head_skeleton.bone_map.find("ocellus_l"); it != head_skeleton.bone_map.end())
  645. ocellus_l_to_body = head_to_body * head_skeleton.concatenate(it->second);
  646. math::transform<float> ocellus_r_to_body;
  647. if (auto it = head_skeleton.bone_map.find("ocellus_r"); it != head_skeleton.bone_map.end())
  648. ocellus_r_to_body = head_to_body * head_skeleton.concatenate(it->second);
  649. // Reskin lateral ocelli bones
  650. std::unordered_set<std::uint16_t> old_ocellus_l_bone_indices;
  651. if (auto it = lateral_ocelli_skeleton->bone_map.find("ocellus_l"); it != lateral_ocelli_skeleton->bone_map.end())
  652. old_ocellus_l_bone_indices.emplace(it->second);
  653. reskin_vertices(vertex_buffer_data + lateral_ocelli_vbo_offset, lateral_ocelli_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_ocellus_l_bone_indices, head_bone_index, ocellus_l_to_body);
  654. std::unordered_set<std::uint16_t> old_ocellus_r_bone_indices;
  655. if (auto it = lateral_ocelli_skeleton->bone_map.find("ocellus_r"); it != lateral_ocelli_skeleton->bone_map.end())
  656. old_ocellus_r_bone_indices.emplace(it->second);
  657. reskin_vertices(vertex_buffer_data + lateral_ocelli_vbo_offset, lateral_ocelli_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_ocellus_r_bone_indices, head_bone_index, ocellus_r_to_body);
  658. }
  659. if (median_ocellus)
  660. {
  661. // Calculate transforms from lateral ocelli space to body space
  662. math::transform<float> ocellus_m_to_body;
  663. if (auto it = head_skeleton.bone_map.find("ocellus_m"); it != head_skeleton.bone_map.end())
  664. ocellus_m_to_body = head_to_body * head_skeleton.concatenate(it->second);
  665. // Reskin lateral ocelli bones
  666. std::unordered_set<std::uint16_t> old_ocellus_m_bone_indices;
  667. if (auto it = median_ocellus_skeleton->bone_map.find("ocellus_m"); it != median_ocellus_skeleton->bone_map.end())
  668. old_ocellus_m_bone_indices.emplace(it->second);
  669. reskin_vertices(vertex_buffer_data + median_ocellus_vbo_offset, median_ocellus_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_ocellus_m_bone_indices, head_bone_index, ocellus_m_to_body);
  670. }
  671. // Upload vertex buffer data to model VBO
  672. model->get_vertex_buffer()->repurpose(gl::buffer_usage::static_draw, vertex_buffer_size, vertex_buffer_data);
  673. // Construct exoskeleton model group
  674. render::model_group* exoskeleton_group = model->add_group("exoskeleton");
  675. exoskeleton_group->set_material(exoskeleton_material);
  676. exoskeleton_group->set_drawing_mode(gl::drawing_mode::triangles);
  677. exoskeleton_group->set_start_index(0);
  678. exoskeleton_group->set_index_count(exoskeleton_index_count);
  679. std::size_t index_offset = exoskeleton_index_count;
  680. if (eyes)
  681. {
  682. // Construct eyes model group
  683. render::model_group* eyes_group = model->add_group("eyes");
  684. eyes_group->set_material((*eyes->get_groups())[0]->get_material());
  685. eyes_group->set_drawing_mode(gl::drawing_mode::triangles);
  686. eyes_group->set_start_index(index_offset);
  687. eyes_group->set_index_count(eyes_index_count);
  688. index_offset += eyes_index_count;
  689. }
  690. if (lateral_ocelli || median_ocellus)
  691. {
  692. // Construct ocelli model group
  693. render::model_group* ocelli_group = model->add_group("ocelli");
  694. ocelli_group->set_drawing_mode(gl::drawing_mode::triangles);
  695. ocelli_group->set_start_index(index_offset);
  696. std::size_t index_count = 0;
  697. if (lateral_ocelli)
  698. {
  699. index_count += lateral_ocelli_index_count;
  700. index_offset += lateral_ocelli_index_count;
  701. ocelli_group->set_material((*lateral_ocelli->get_groups())[0]->get_material());
  702. }
  703. if (median_ocellus)
  704. {
  705. index_count += median_ocellus_index_count;
  706. index_offset += median_ocellus_index_count;
  707. if (!lateral_ocelli)
  708. ocelli_group->set_material((*median_ocellus->get_groups())[0]->get_material());
  709. }
  710. ocelli_group->set_index_count(index_count);
  711. }
  712. if (forewings)
  713. {
  714. // Construct forewings model group
  715. render::model_group* forewings_group = model->add_group("forewings");
  716. forewings_group->set_material((*forewings->get_groups())[0]->get_material());
  717. forewings_group->set_drawing_mode(gl::drawing_mode::triangles);
  718. forewings_group->set_start_index(index_offset);
  719. forewings_group->set_index_count(forewings_index_count);
  720. index_offset += forewings_index_count;
  721. }
  722. if (hindwings)
  723. {
  724. // Construct hindwings model group
  725. render::model_group* hindwings_group = model->add_group("hindwings");
  726. hindwings_group->set_material((*hindwings->get_groups())[0]->get_material());
  727. hindwings_group->set_drawing_mode(gl::drawing_mode::triangles);
  728. hindwings_group->set_start_index(index_offset);
  729. hindwings_group->set_index_count(hindwings_index_count);
  730. index_offset += hindwings_index_count;
  731. }
  732. // Calculate model bounding box
  733. geom::aabb<float> bounds = calculate_bounds(vertex_buffer_data, index_offset, *position_attribute);
  734. model->set_bounds(bounds);
  735. // Free vertex buffer data
  736. delete[] vertex_buffer_data;
  737. return model;
  738. }
  739. void reskin_vertices
  740. (
  741. std::uint8_t* vertex_data,
  742. std::size_t index_count,
  743. const gl::vertex_attribute& position_attribute,
  744. const gl::vertex_attribute& normal_attribute,
  745. const gl::vertex_attribute& tangent_attribute,
  746. const gl::vertex_attribute& bone_index_attribute,
  747. const std::unordered_set<std::uint16_t>& old_bone_indices,
  748. std::uint16_t new_bone_index,
  749. const math::transform<float>& transform
  750. )
  751. {
  752. std::uint8_t* position_data = vertex_data + position_attribute.offset;
  753. std::uint8_t* normal_data = vertex_data + normal_attribute.offset;
  754. std::uint8_t* tangent_data = vertex_data + tangent_attribute.offset;
  755. std::uint8_t* bone_index_data = vertex_data + bone_index_attribute.offset;
  756. for (std::size_t i = 0; i < index_count; ++i)
  757. {
  758. // Get bone index of current vertex
  759. float* bone_index = reinterpret_cast<float*>(bone_index_data + bone_index_attribute.stride * i);
  760. // Skip irrelevant bones
  761. if (!old_bone_indices.count(static_cast<std::uint16_t>(*bone_index + 0.5f)))
  762. continue;
  763. // Get vertex position
  764. float* x = reinterpret_cast<float*>(position_data + position_attribute.stride * i);
  765. float* y = x + 1;
  766. float* z = y + 1;
  767. // Get vertex normal
  768. float* nx = reinterpret_cast<float*>(normal_data + normal_attribute.stride * i);
  769. float* ny = nx + 1;
  770. float* nz = ny + 1;
  771. // Get vertex tangent
  772. float* tx = reinterpret_cast<float*>(tangent_data + tangent_attribute.stride * i);
  773. float* ty = tx + 1;
  774. float* tz = ty + 1;
  775. //float* bts = tz + 1;
  776. // Transform vertex attributes
  777. float3 position = transform * float3{*x, *y, *z};
  778. float3 normal = math::normalize(transform.rotation * float3{*nx, *ny, *nz});
  779. float3 tangent = transform.rotation * float3{*tx, *ty, *tz};
  780. // Update vertex data
  781. *x = position.x;
  782. *y = position.y;
  783. *z = position.z;
  784. *nx = normal.x;
  785. *ny = normal.y;
  786. *nz = normal.z;
  787. *tx = tangent.x;
  788. *ty = tangent.y;
  789. *tz = tangent.z;
  790. //*bts = ...
  791. *bone_index = static_cast<float>(new_bone_index);
  792. }
  793. }
  794. geom::aabb<float> calculate_bounds(std::uint8_t* vertex_data, std::size_t index_count, const gl::vertex_attribute& position_attribute)
  795. {
  796. std::uint8_t* position_data = vertex_data + position_attribute.offset;
  797. geom::aabb<float> bounds;
  798. bounds.min_point.x = std::numeric_limits<float>::infinity();
  799. bounds.min_point.y = std::numeric_limits<float>::infinity();
  800. bounds.min_point.z = std::numeric_limits<float>::infinity();
  801. bounds.max_point.x = -std::numeric_limits<float>::infinity();
  802. bounds.max_point.y = -std::numeric_limits<float>::infinity();
  803. bounds.max_point.z = -std::numeric_limits<float>::infinity();
  804. for (std::size_t i = 0; i < index_count; ++i)
  805. {
  806. // Get vertex position
  807. float* x = reinterpret_cast<float*>(position_data + position_attribute.stride * i);
  808. float* y = x + 1;
  809. float* z = y + 1;
  810. bounds.min_point.x = std::min<float>(*x, bounds.min_point.x);
  811. bounds.min_point.y = std::min<float>(*y, bounds.min_point.y);
  812. bounds.min_point.z = std::min<float>(*z, bounds.min_point.z);
  813. bounds.max_point.x = std::max<float>(*x, bounds.max_point.x);
  814. bounds.max_point.y = std::max<float>(*y, bounds.max_point.y);
  815. bounds.max_point.z = std::max<float>(*z, bounds.max_point.z);
  816. }
  817. return bounds;
  818. }
  819. } // namespace ant
  820. } // namespace game