💿🐜 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.

977 lines
56 KiB

  1. /*
  2. * Copyright (C) 2023 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 "math/transform-operators.hpp"
  23. #include "math/quaternion.hpp"
  24. #include <unordered_set>
  25. namespace game {
  26. namespace ant {
  27. static render::material* build_exoskeleton_material
  28. (
  29. const phene::pigmentation& pigmentation,
  30. const phene::sculpturing& sculpturing
  31. );
  32. static void reskin_vertices
  33. (
  34. std::uint8_t* vertex_data,
  35. std::size_t index_count,
  36. const gl::vertex_attribute& position_attribute,
  37. const gl::vertex_attribute& normal_attribute,
  38. const gl::vertex_attribute& tangent_attribute,
  39. const gl::vertex_attribute& bone_index_attribute,
  40. const std::unordered_set<std::uint8_t>& old_bone_indices,
  41. std::uint8_t new_bone_index,
  42. const math::transform<float>& transform
  43. );
  44. static geom::aabb<float> calculate_bounds(std::uint8_t* vertex_data, std::size_t index_count, const gl::vertex_attribute& position_attribute);
  45. static render::model* build_model
  46. (
  47. render::material* material,
  48. const render::model* antennae,
  49. const render::model* eyes,
  50. const render::model* forewings,
  51. const render::model* gaster,
  52. const render::model* head,
  53. const render::model* hindwings,
  54. const render::model* legs,
  55. const render::model* mandibles,
  56. const render::model* mesosoma,
  57. const render::model* lateral_ocelli,
  58. const render::model* median_ocellus,
  59. const render::model* sting,
  60. const render::model* waist
  61. );
  62. render::material* build_exoskeleton_material
  63. (
  64. const phene::pigmentation& pigmentation,
  65. const phene::sculpturing& sculpturing
  66. )
  67. {
  68. // Allocate copy of pigmentation material
  69. render::material* exoskeleton_material = new render::material(*pigmentation.material);
  70. // Adjust roughness parameter
  71. if (render::material_property_base* property = exoskeleton_material->get_property("roughness"); property != nullptr)
  72. {
  73. static_cast<render::material_property<float>*>(property)->set_value(sculpturing.roughness);
  74. }
  75. else
  76. {
  77. exoskeleton_material->add_property<float>("roughness")->set_value(sculpturing.roughness);
  78. }
  79. // Adjust normal map parameter
  80. if (render::material_property_base* property = exoskeleton_material->get_property("normal_map"); property != nullptr)
  81. {
  82. static_cast<render::material_property<const gl::texture_2d*>*>(property)->set_value(sculpturing.normal_map);
  83. }
  84. else
  85. {
  86. exoskeleton_material->add_property<const gl::texture_2d*>("normal_map")->set_value(sculpturing.normal_map);
  87. }
  88. return exoskeleton_material;
  89. }
  90. render::model* morphogenesis(const phenome& phenome)
  91. {
  92. // Build exoskeleton material
  93. render::material* exoskeleton_material = build_exoskeleton_material(*phenome.pigmentation, *phenome.sculpturing);
  94. // Determine presence of optional parts
  95. bool eyes_present = phenome.eyes->present;
  96. bool lateral_ocelli_present = phenome.ocelli->lateral_ocelli_present;
  97. bool median_ocellus_present = phenome.ocelli->median_ocellus_present;
  98. bool petiole_present = phenome.waist->petiole_present;
  99. bool postpetiole_present = phenome.waist->postpetiole_present;
  100. bool sting_present = phenome.sting->present;
  101. bool wings_present = phenome.wings->present;
  102. // Get body part models
  103. render::model* antennae_model = phenome.antennae->model;
  104. render::model* eyes_model = phenome.eyes->model;
  105. render::model* forewings_model = phenome.wings->forewings_model;
  106. render::model* gaster_model = phenome.gaster->model;
  107. render::model* head_model = phenome.head->model;
  108. render::model* hindwings_model = phenome.wings->hindwings_model;
  109. render::model* lateral_ocelli_model = phenome.ocelli->lateral_ocelli_model;
  110. render::model* legs_model = phenome.legs->model;
  111. render::model* mandibles_model = phenome.mandibles->model;
  112. render::model* median_ocellus_model = phenome.ocelli->median_ocellus_model;
  113. render::model* mesosoma_model = phenome.mesosoma->model;
  114. render::model* sting_model = phenome.sting->model;
  115. render::model* waist_model = phenome.waist->model;
  116. // Get body part vertex buffers
  117. const gl::vertex_buffer* antennae_vbo = antennae_model->get_vertex_buffer();
  118. const gl::vertex_buffer* eyes_vbo = (eyes_present) ? eyes_model->get_vertex_buffer() : nullptr;
  119. const gl::vertex_buffer* forewings_vbo = (wings_present) ? forewings_model->get_vertex_buffer() : nullptr;
  120. const gl::vertex_buffer* gaster_vbo = gaster_model->get_vertex_buffer();
  121. const gl::vertex_buffer* head_vbo = head_model->get_vertex_buffer();
  122. const gl::vertex_buffer* hindwings_vbo = (wings_present) ? hindwings_model->get_vertex_buffer() : nullptr;
  123. const gl::vertex_buffer* lateral_ocelli_vbo = (lateral_ocelli_model) ? lateral_ocelli_model->get_vertex_buffer() : nullptr;
  124. const gl::vertex_buffer* legs_vbo = legs_model->get_vertex_buffer();
  125. const gl::vertex_buffer* mandibles_vbo = mandibles_model->get_vertex_buffer();
  126. const gl::vertex_buffer* median_ocellus_vbo = (median_ocellus_model) ? median_ocellus_model->get_vertex_buffer() : nullptr;
  127. const gl::vertex_buffer* mesosoma_vbo = mesosoma_model->get_vertex_buffer();
  128. const gl::vertex_buffer* sting_vbo = (sting_present) ? sting_model->get_vertex_buffer() : nullptr;
  129. const gl::vertex_buffer* waist_vbo = waist_model->get_vertex_buffer();
  130. // Determine combined size of vertex buffers and save offsets
  131. std::size_t vertex_buffer_size = 0;
  132. std::size_t mesosoma_vbo_offset = vertex_buffer_size;
  133. vertex_buffer_size += mesosoma_vbo->get_size();
  134. std::size_t legs_vbo_offset = vertex_buffer_size;
  135. vertex_buffer_size += legs_vbo->get_size();
  136. std::size_t head_vbo_offset = vertex_buffer_size;
  137. vertex_buffer_size += head_vbo->get_size();
  138. std::size_t mandibles_vbo_offset = vertex_buffer_size;
  139. vertex_buffer_size += mandibles_vbo->get_size();
  140. std::size_t antennae_vbo_offset = vertex_buffer_size;
  141. vertex_buffer_size += antennae_vbo->get_size();
  142. std::size_t waist_vbo_offset = vertex_buffer_size;
  143. vertex_buffer_size += waist_vbo->get_size();
  144. std::size_t gaster_vbo_offset = vertex_buffer_size;
  145. vertex_buffer_size += gaster_vbo->get_size();
  146. std::size_t sting_vbo_offset = vertex_buffer_size;
  147. if (sting_present)
  148. vertex_buffer_size += sting_vbo->get_size();
  149. std::size_t eyes_vbo_offset = vertex_buffer_size;
  150. if (eyes_present)
  151. vertex_buffer_size += eyes_vbo->get_size();
  152. std::size_t lateral_ocelli_vbo_offset = vertex_buffer_size;
  153. if (lateral_ocelli_present)
  154. vertex_buffer_size += lateral_ocelli_vbo->get_size();
  155. std::size_t median_ocellus_vbo_offset = vertex_buffer_size;
  156. if (median_ocellus_present)
  157. vertex_buffer_size += median_ocellus_vbo->get_size();
  158. std::size_t forewings_vbo_offset = vertex_buffer_size;
  159. if (wings_present)
  160. vertex_buffer_size += forewings_vbo->get_size();
  161. std::size_t hindwings_vbo_offset = vertex_buffer_size;
  162. if (wings_present)
  163. vertex_buffer_size += hindwings_vbo->get_size();
  164. // Allocate combined vertex buffer data
  165. std::uint8_t* vertex_buffer_data = new std::uint8_t[vertex_buffer_size];
  166. // Read body part vertex buffer data into combined vertex buffer data
  167. mesosoma_vbo->read(0, mesosoma_vbo->get_size(), vertex_buffer_data + mesosoma_vbo_offset);
  168. legs_vbo->read(0, legs_vbo->get_size(), vertex_buffer_data + legs_vbo_offset);
  169. head_vbo->read(0, head_vbo->get_size(), vertex_buffer_data + head_vbo_offset);
  170. mandibles_vbo->read(0, mandibles_vbo->get_size(), vertex_buffer_data + mandibles_vbo_offset);
  171. antennae_vbo->read(0, antennae_vbo->get_size(), vertex_buffer_data + antennae_vbo_offset);
  172. waist_vbo->read(0, waist_vbo->get_size(), vertex_buffer_data + waist_vbo_offset);
  173. gaster_vbo->read(0, gaster_vbo->get_size(), vertex_buffer_data + gaster_vbo_offset);
  174. if (sting_present)
  175. sting_vbo->read(0, sting_vbo->get_size(), vertex_buffer_data + sting_vbo_offset);
  176. if (eyes_present)
  177. eyes_vbo->read(0, eyes_vbo->get_size(), vertex_buffer_data + eyes_vbo_offset);
  178. if (lateral_ocelli_present)
  179. lateral_ocelli_vbo->read(0, lateral_ocelli_vbo->get_size(), vertex_buffer_data + lateral_ocelli_vbo_offset);
  180. if (median_ocellus_present)
  181. median_ocellus_vbo->read(0, median_ocellus_vbo->get_size(), vertex_buffer_data + median_ocellus_vbo_offset);
  182. if (wings_present)
  183. {
  184. forewings_vbo->read(0, forewings_vbo->get_size(), vertex_buffer_data + forewings_vbo_offset);
  185. hindwings_vbo->read(0, hindwings_vbo->get_size(), vertex_buffer_data + hindwings_vbo_offset);
  186. }
  187. // Allocate model
  188. render::model* model = new render::model();
  189. // Setup model VAO
  190. gl::vertex_array* model_vao = model->get_vertex_array();
  191. for (auto [location, attribute]: mesosoma_model->get_vertex_array()->get_attributes())
  192. {
  193. attribute.buffer = model->get_vertex_buffer();
  194. model_vao->bind(location, attribute);
  195. }
  196. // Get vertex attributes
  197. const gl::vertex_attribute* position_attribute = nullptr;
  198. const gl::vertex_attribute* normal_attribute = nullptr;
  199. const gl::vertex_attribute* tangent_attribute = nullptr;
  200. const gl::vertex_attribute* bone_index_attribute = nullptr;
  201. const auto& vertex_attribute_map = model_vao->get_attributes();
  202. if (auto it = vertex_attribute_map.find(render::vertex_attribute::position); it != vertex_attribute_map.end())
  203. position_attribute = &it->second;
  204. if (auto it = vertex_attribute_map.find(render::vertex_attribute::normal); it != vertex_attribute_map.end())
  205. normal_attribute = &it->second;
  206. if (auto it = vertex_attribute_map.find(render::vertex_attribute::tangent); it != vertex_attribute_map.end())
  207. tangent_attribute = &it->second;
  208. if (auto it = vertex_attribute_map.find(render::vertex_attribute::bone_index); it != vertex_attribute_map.end())
  209. bone_index_attribute = &it->second;
  210. // Get body part skeletons
  211. const ::skeleton& mesosoma_skeleton = mesosoma_model->get_skeleton();
  212. const ::skeleton& legs_skeleton = legs_model->get_skeleton();
  213. const ::skeleton& head_skeleton = head_model->get_skeleton();
  214. const ::skeleton& mandibles_skeleton = mandibles_model->get_skeleton();
  215. const ::skeleton& antennae_skeleton = antennae_model->get_skeleton();
  216. const ::skeleton& waist_skeleton = waist_model->get_skeleton();
  217. const ::skeleton& gaster_skeleton = gaster_model->get_skeleton();
  218. const ::skeleton* sting_skeleton = (sting_present) ? &sting_model->get_skeleton() : nullptr;
  219. const ::skeleton* eyes_skeleton = (eyes_present) ? &eyes_model->get_skeleton() : nullptr;
  220. const ::skeleton* lateral_ocelli_skeleton = (lateral_ocelli_present) ? &lateral_ocelli_model->get_skeleton() : nullptr;
  221. const ::skeleton* median_ocellus_skeleton = (median_ocellus_present) ? &median_ocellus_model->get_skeleton() : nullptr;
  222. // Allocate skeleton bones
  223. ::skeleton& skeleton = model->get_skeleton();
  224. std::size_t bone_count = 33;
  225. if (petiole_present)
  226. bone_count += 1;
  227. if (postpetiole_present)
  228. bone_count += 1;
  229. if (sting_present)
  230. bone_count += 1;
  231. if (wings_present)
  232. bone_count += 4;
  233. // Assign bone indices
  234. std::uint8_t bone_index = 0;
  235. std::uint8_t mesosoma_bone_index = bone_index++;
  236. std::uint8_t procoxa_l_bone_index = bone_index++;
  237. std::uint8_t procoxa_r_bone_index = bone_index++;
  238. std::uint8_t profemur_l_bone_index = bone_index++;
  239. std::uint8_t profemur_r_bone_index = bone_index++;
  240. std::uint8_t protibia_l_bone_index = bone_index++;
  241. std::uint8_t protibia_r_bone_index = bone_index++;
  242. std::uint8_t protarsus_l_bone_index = bone_index++;
  243. std::uint8_t protarsus_r_bone_index = bone_index++;
  244. std::uint8_t mesocoxa_l_bone_index = bone_index++;
  245. std::uint8_t mesocoxa_r_bone_index = bone_index++;
  246. std::uint8_t mesofemur_l_bone_index = bone_index++;
  247. std::uint8_t mesofemur_r_bone_index = bone_index++;
  248. std::uint8_t mesotibia_l_bone_index = bone_index++;
  249. std::uint8_t mesotibia_r_bone_index = bone_index++;
  250. std::uint8_t mesotarsus_l_bone_index = bone_index++;
  251. std::uint8_t mesotarsus_r_bone_index = bone_index++;
  252. std::uint8_t metacoxa_l_bone_index = bone_index++;
  253. std::uint8_t metacoxa_r_bone_index = bone_index++;
  254. std::uint8_t metafemur_l_bone_index = bone_index++;
  255. std::uint8_t metafemur_r_bone_index = bone_index++;
  256. std::uint8_t metatibia_l_bone_index = bone_index++;
  257. std::uint8_t metatibia_r_bone_index = bone_index++;
  258. std::uint8_t metatarsus_l_bone_index = bone_index++;
  259. std::uint8_t metatarsus_r_bone_index = bone_index++;
  260. std::uint8_t head_bone_index = bone_index++;
  261. std::uint8_t mandible_l_bone_index = bone_index++;
  262. std::uint8_t mandible_r_bone_index = bone_index++;
  263. std::uint8_t antennomere1_l_bone_index = bone_index++;
  264. std::uint8_t antennomere1_r_bone_index = bone_index++;
  265. std::uint8_t antennomere2_l_bone_index = bone_index++;
  266. std::uint8_t antennomere2_r_bone_index = bone_index++;
  267. std::uint8_t petiole_bone_index =(petiole_present) ? bone_index++ : static_cast<std::uint8_t>(bone_count);
  268. std::uint8_t postpetiole_bone_index = (postpetiole_present) ? bone_index++ : static_cast<std::uint8_t>(bone_count);
  269. std::uint8_t gaster_bone_index = bone_index++;
  270. std::uint8_t sting_bone_index = (sting_present) ? bone_index++ : static_cast<std::uint8_t>(bone_count);
  271. // Construct bone identifiers
  272. ::bone mesosoma_bone = make_bone(mesosoma_bone_index);
  273. ::bone procoxa_l_bone = make_bone(procoxa_l_bone_index, mesosoma_bone_index);
  274. ::bone procoxa_r_bone = make_bone(procoxa_r_bone_index, mesosoma_bone_index);
  275. ::bone profemur_l_bone = make_bone(profemur_l_bone_index, procoxa_l_bone_index);
  276. ::bone profemur_r_bone = make_bone(profemur_r_bone_index, procoxa_r_bone_index);
  277. ::bone protibia_l_bone = make_bone(protibia_l_bone_index, profemur_l_bone_index);
  278. ::bone protibia_r_bone = make_bone(protibia_r_bone_index, profemur_r_bone_index);
  279. ::bone protarsus_l_bone = make_bone(protarsus_l_bone_index, protibia_l_bone_index);
  280. ::bone protarsus_r_bone = make_bone(protarsus_r_bone_index, protibia_r_bone_index);
  281. ::bone mesocoxa_l_bone = make_bone(mesocoxa_l_bone_index, mesosoma_bone_index);
  282. ::bone mesocoxa_r_bone = make_bone(mesocoxa_r_bone_index, mesosoma_bone_index);
  283. ::bone mesofemur_l_bone = make_bone(mesofemur_l_bone_index, mesocoxa_l_bone_index);
  284. ::bone mesofemur_r_bone = make_bone(mesofemur_r_bone_index, mesocoxa_r_bone_index);
  285. ::bone mesotibia_l_bone = make_bone(mesotibia_l_bone_index, mesofemur_l_bone_index);
  286. ::bone mesotibia_r_bone = make_bone(mesotibia_r_bone_index, mesofemur_r_bone_index);
  287. ::bone mesotarsus_l_bone = make_bone(mesotarsus_l_bone_index, mesotibia_l_bone_index);
  288. ::bone mesotarsus_r_bone = make_bone(mesotarsus_r_bone_index, mesotibia_r_bone_index);
  289. ::bone metacoxa_l_bone = make_bone(metacoxa_l_bone_index, mesosoma_bone_index);
  290. ::bone metacoxa_r_bone = make_bone(metacoxa_r_bone_index, mesosoma_bone_index);
  291. ::bone metafemur_l_bone = make_bone(metafemur_l_bone_index, metacoxa_l_bone_index);
  292. ::bone metafemur_r_bone = make_bone(metafemur_r_bone_index, metacoxa_r_bone_index);
  293. ::bone metatibia_l_bone = make_bone(metatibia_l_bone_index, metafemur_l_bone_index);
  294. ::bone metatibia_r_bone = make_bone(metatibia_r_bone_index, metafemur_r_bone_index);
  295. ::bone metatarsus_l_bone = make_bone(metatarsus_l_bone_index, metatibia_l_bone_index);
  296. ::bone metatarsus_r_bone = make_bone(metatarsus_r_bone_index, metatibia_r_bone_index);
  297. ::bone head_bone = make_bone(head_bone_index, mesosoma_bone_index);
  298. ::bone mandible_l_bone = make_bone(mandible_l_bone_index, head_bone_index);
  299. ::bone mandible_r_bone = make_bone(mandible_r_bone_index, head_bone_index);
  300. ::bone antennomere1_l_bone = make_bone(antennomere1_l_bone_index, head_bone_index);
  301. ::bone antennomere1_r_bone = make_bone(antennomere1_r_bone_index, head_bone_index);
  302. ::bone antennomere2_l_bone = make_bone(antennomere2_l_bone_index, antennomere1_l_bone_index);
  303. ::bone antennomere2_r_bone = make_bone(antennomere2_r_bone_index, antennomere1_r_bone_index);
  304. ::bone petiole_bone = make_bone(petiole_bone_index, mesosoma_bone_index);
  305. ::bone postpetiole_bone = make_bone(postpetiole_bone_index, petiole_bone_index);
  306. ::bone gaster_bone = make_bone(gaster_bone_index, (postpetiole_present) ? postpetiole_bone_index : petiole_bone_index);
  307. ::bone sting_bone = make_bone(sting_bone_index, gaster_bone_index);
  308. // Map bone names to bones
  309. skeleton.bone_map["mesosoma"] = mesosoma_bone;
  310. skeleton.bone_map["procoxa_l"] = procoxa_l_bone;
  311. skeleton.bone_map["procoxa_r"] = procoxa_r_bone;
  312. skeleton.bone_map["profemur_l"] = profemur_l_bone;
  313. skeleton.bone_map["profemur_r"] = profemur_r_bone;
  314. skeleton.bone_map["protibia_l"] = protibia_l_bone;
  315. skeleton.bone_map["protibia_r"] = protibia_r_bone;
  316. skeleton.bone_map["protarsus_l"] = protarsus_l_bone;
  317. skeleton.bone_map["protarsus_r"] = protarsus_r_bone;
  318. skeleton.bone_map["mesocoxa_l"] = mesocoxa_l_bone;
  319. skeleton.bone_map["mesocoxa_r"] = mesocoxa_r_bone;
  320. skeleton.bone_map["mesofemur_l"] = mesofemur_l_bone;
  321. skeleton.bone_map["mesofemur_r"] = mesofemur_r_bone;
  322. skeleton.bone_map["mesotibia_l"] = mesotibia_l_bone;
  323. skeleton.bone_map["mesotibia_r"] = mesotibia_r_bone;
  324. skeleton.bone_map["mesotarsus_l"] = mesotarsus_l_bone;
  325. skeleton.bone_map["mesotarsus_r"] = mesotarsus_r_bone;
  326. skeleton.bone_map["metacoxa_l"] = metacoxa_l_bone;
  327. skeleton.bone_map["metacoxa_r"] = metacoxa_r_bone;
  328. skeleton.bone_map["metafemur_l"] = metafemur_l_bone;
  329. skeleton.bone_map["metafemur_r"] = metafemur_r_bone;
  330. skeleton.bone_map["metatibia_l"] = metatibia_l_bone;
  331. skeleton.bone_map["metatibia_r"] = metatibia_r_bone;
  332. skeleton.bone_map["metatarsus_l"] = metatarsus_l_bone;
  333. skeleton.bone_map["metatarsus_r"] = metatarsus_r_bone;
  334. skeleton.bone_map["head"] = head_bone;
  335. skeleton.bone_map["mandible_l"] = mandible_l_bone;
  336. skeleton.bone_map["mandible_r"] = mandible_r_bone;
  337. skeleton.bone_map["antennomere1_l"] = antennomere1_l_bone;
  338. skeleton.bone_map["antennomere1_r"] = antennomere1_r_bone;
  339. skeleton.bone_map["antennomere2_l"] = antennomere2_l_bone;
  340. skeleton.bone_map["antennomere2_r"] = antennomere2_r_bone;
  341. if (petiole_present)
  342. skeleton.bone_map["petiole"] = petiole_bone;
  343. if (postpetiole_present)
  344. skeleton.bone_map["postpetiole"] = postpetiole_bone;
  345. skeleton.bone_map["gaster"] = gaster_bone;
  346. if (sting_present)
  347. skeleton.bone_map["sting"] = sting_bone;
  348. // Get reference to skeleton bind pose
  349. pose& bind_pose = skeleton.bind_pose;
  350. // Skeleton mesosoma pose
  351. if (auto it = mesosoma_skeleton.bone_map.find("mesosoma"); it != mesosoma_skeleton.bone_map.end())
  352. bind_pose[mesosoma_bone] = mesosoma_skeleton.bind_pose.at(it->second);
  353. // Skeleton forelegs pose
  354. if (auto it = legs_skeleton.bone_map.find("procoxa_l"); it != legs_skeleton.bone_map.end())
  355. bind_pose[procoxa_l_bone] = legs_skeleton.bind_pose.at(it->second);
  356. if (auto it = legs_skeleton.bone_map.find("procoxa_r"); it != legs_skeleton.bone_map.end())
  357. bind_pose[procoxa_r_bone] = legs_skeleton.bind_pose.at(it->second);
  358. if (auto it = legs_skeleton.bone_map.find("profemur_l"); it != legs_skeleton.bone_map.end())
  359. bind_pose[profemur_l_bone] = legs_skeleton.bind_pose.at(it->second);
  360. if (auto it = legs_skeleton.bone_map.find("profemur_r"); it != legs_skeleton.bone_map.end())
  361. bind_pose[profemur_r_bone] = legs_skeleton.bind_pose.at(it->second);
  362. if (auto it = legs_skeleton.bone_map.find("protibia_l"); it != legs_skeleton.bone_map.end())
  363. bind_pose[protibia_l_bone] = legs_skeleton.bind_pose.at(it->second);
  364. if (auto it = legs_skeleton.bone_map.find("protibia_r"); it != legs_skeleton.bone_map.end())
  365. bind_pose[protibia_r_bone] = legs_skeleton.bind_pose.at(it->second);
  366. if (auto it = legs_skeleton.bone_map.find("protarsus1_l"); it != legs_skeleton.bone_map.end())
  367. bind_pose[protarsus_l_bone] = legs_skeleton.bind_pose.at(it->second);
  368. if (auto it = legs_skeleton.bone_map.find("protarsus1_r"); it != legs_skeleton.bone_map.end())
  369. bind_pose[protarsus_r_bone] = legs_skeleton.bind_pose.at(it->second);
  370. // Skeleton midlegs pose
  371. if (auto it = legs_skeleton.bone_map.find("mesocoxa_l"); it != legs_skeleton.bone_map.end())
  372. bind_pose[mesocoxa_l_bone] = legs_skeleton.bind_pose.at(it->second);
  373. if (auto it = legs_skeleton.bone_map.find("mesocoxa_r"); it != legs_skeleton.bone_map.end())
  374. bind_pose[mesocoxa_r_bone] = legs_skeleton.bind_pose.at(it->second);
  375. if (auto it = legs_skeleton.bone_map.find("mesofemur_l"); it != legs_skeleton.bone_map.end())
  376. bind_pose[mesofemur_l_bone] = legs_skeleton.bind_pose.at(it->second);
  377. if (auto it = legs_skeleton.bone_map.find("mesofemur_r"); it != legs_skeleton.bone_map.end())
  378. bind_pose[mesofemur_r_bone] = legs_skeleton.bind_pose.at(it->second);
  379. if (auto it = legs_skeleton.bone_map.find("mesotibia_l"); it != legs_skeleton.bone_map.end())
  380. bind_pose[mesotibia_l_bone] = legs_skeleton.bind_pose.at(it->second);
  381. if (auto it = legs_skeleton.bone_map.find("mesotibia_r"); it != legs_skeleton.bone_map.end())
  382. bind_pose[mesotibia_r_bone] = legs_skeleton.bind_pose.at(it->second);
  383. if (auto it = legs_skeleton.bone_map.find("mesotarsus1_l"); it != legs_skeleton.bone_map.end())
  384. bind_pose[mesotarsus_l_bone] = legs_skeleton.bind_pose.at(it->second);
  385. if (auto it = legs_skeleton.bone_map.find("mesotarsus1_r"); it != legs_skeleton.bone_map.end())
  386. bind_pose[mesotarsus_r_bone] = legs_skeleton.bind_pose.at(it->second);
  387. // Skeleton hindlegs pose
  388. if (auto it = legs_skeleton.bone_map.find("metacoxa_l"); it != legs_skeleton.bone_map.end())
  389. bind_pose[metacoxa_l_bone] = legs_skeleton.bind_pose.at(it->second);
  390. if (auto it = legs_skeleton.bone_map.find("metacoxa_r"); it != legs_skeleton.bone_map.end())
  391. bind_pose[metacoxa_r_bone] = legs_skeleton.bind_pose.at(it->second);
  392. if (auto it = legs_skeleton.bone_map.find("metafemur_l"); it != legs_skeleton.bone_map.end())
  393. bind_pose[metafemur_l_bone] = legs_skeleton.bind_pose.at(it->second);
  394. if (auto it = legs_skeleton.bone_map.find("metafemur_r"); it != legs_skeleton.bone_map.end())
  395. bind_pose[metafemur_r_bone] = legs_skeleton.bind_pose.at(it->second);
  396. if (auto it = legs_skeleton.bone_map.find("metatibia_l"); it != legs_skeleton.bone_map.end())
  397. bind_pose[metatibia_l_bone] = legs_skeleton.bind_pose.at(it->second);
  398. if (auto it = legs_skeleton.bone_map.find("metatibia_r"); it != legs_skeleton.bone_map.end())
  399. bind_pose[metatibia_r_bone] = legs_skeleton.bind_pose.at(it->second);
  400. if (auto it = legs_skeleton.bone_map.find("metatarsus1_l"); it != legs_skeleton.bone_map.end())
  401. bind_pose[metatarsus_l_bone] = legs_skeleton.bind_pose.at(it->second);
  402. if (auto it = legs_skeleton.bone_map.find("metatarsus1_r"); it != legs_skeleton.bone_map.end())
  403. bind_pose[metatarsus_r_bone] = legs_skeleton.bind_pose.at(it->second);
  404. // Skeleton head pose
  405. bind_pose[head_bone] = mesosoma_skeleton.bind_pose.at(mesosoma_skeleton.bone_map.at("head")) * head_skeleton.bind_pose.at(head_skeleton.bone_map.at("head"));
  406. // Skeleton mandibles pose
  407. bind_pose[mandible_l_bone] = head_skeleton.bind_pose.at(head_skeleton.bone_map.at("mandible_l")) * mandibles_skeleton.bind_pose.at(mandibles_skeleton.bone_map.at("mandible_l"));
  408. bind_pose[mandible_r_bone] = head_skeleton.bind_pose.at(head_skeleton.bone_map.at("mandible_r")) * mandibles_skeleton.bind_pose.at(mandibles_skeleton.bone_map.at("mandible_r"));
  409. // Skeleton antennae pose
  410. bind_pose[antennomere1_l_bone] = head_skeleton.bind_pose.at(head_skeleton.bone_map.at("antenna_l")) * antennae_skeleton.bind_pose.at(antennae_skeleton.bone_map.at("antennomere1_l"));
  411. bind_pose[antennomere1_r_bone] = head_skeleton.bind_pose.at(head_skeleton.bone_map.at("antenna_r")) * antennae_skeleton.bind_pose.at(antennae_skeleton.bone_map.at("antennomere1_r"));
  412. bind_pose[antennomere2_l_bone] = antennae_skeleton.bind_pose.at(antennae_skeleton.bone_map.at("antennomere2_l"));
  413. bind_pose[antennomere2_r_bone] = antennae_skeleton.bind_pose.at(antennae_skeleton.bone_map.at("antennomere2_r"));
  414. // Skeleton waist pose
  415. if (petiole_present)
  416. {
  417. bind_pose[petiole_bone] = mesosoma_skeleton.bind_pose.at(mesosoma_skeleton.bone_map.at("petiole")) * waist_skeleton.bind_pose.at(waist_skeleton.bone_map.at("petiole"));
  418. }
  419. if (postpetiole_present)
  420. {
  421. bind_pose[postpetiole_bone] = waist_skeleton.bind_pose.at(waist_skeleton.bone_map.at("postpetiole"));
  422. }
  423. // Skeleton gaster pose
  424. if (postpetiole_present)
  425. {
  426. bind_pose[gaster_bone] = waist_skeleton.bind_pose.at(waist_skeleton.bone_map.at("postpetiole")) * gaster_skeleton.bind_pose.at(gaster_skeleton.bone_map.at("gaster"));
  427. }
  428. else if (petiole_present)
  429. {
  430. bind_pose[gaster_bone] = waist_skeleton.bind_pose.at(waist_skeleton.bone_map.at("petiole")) * gaster_skeleton.bind_pose.at(gaster_skeleton.bone_map.at("gaster"));
  431. }
  432. else
  433. {
  434. bind_pose[gaster_bone] = mesosoma_skeleton.bind_pose.at(mesosoma_skeleton.bone_map.at("petiole")) * gaster_skeleton.bind_pose.at(gaster_skeleton.bone_map.at("gaster"));
  435. }
  436. // Skeleton sting pose
  437. if (sting_present)
  438. {
  439. bind_pose[sting_bone] = gaster_skeleton.bind_pose.at(gaster_skeleton.bone_map.at("sting")) * sting_skeleton->bind_pose.at(sting_skeleton->bone_map.at("sting"));
  440. }
  441. // Calculate the skeleton-space bind pose
  442. pose bind_pose_ss;
  443. ::concatenate(bind_pose, bind_pose_ss);
  444. // Calculate inverse skeleton-space bind pose
  445. ::inverse(bind_pose_ss, skeleton.inverse_bind_pose);
  446. // Get number of vertex indices for each body part
  447. std::size_t mesosoma_index_count = (*mesosoma_model->get_groups())[0]->get_index_count();
  448. std::size_t legs_index_count = (*legs_model->get_groups())[0]->get_index_count();
  449. std::size_t head_index_count = (*head_model->get_groups())[0]->get_index_count();
  450. std::size_t mandibles_index_count = (*mandibles_model->get_groups())[0]->get_index_count();
  451. std::size_t antennae_index_count = (*antennae_model->get_groups())[0]->get_index_count();
  452. std::size_t waist_index_count = (*waist_model->get_groups())[0]->get_index_count();
  453. std::size_t gaster_index_count = (*gaster_model->get_groups())[0]->get_index_count();
  454. std::size_t sting_index_count = (sting_present) ? (*sting_model->get_groups())[0]->get_index_count() : 0;
  455. std::size_t eyes_index_count = (eyes_present) ? (*eyes_model->get_groups())[0]->get_index_count() : 0;
  456. std::size_t lateral_ocelli_index_count = (lateral_ocelli_present) ? (*lateral_ocelli_model->get_groups())[0]->get_index_count() : 0;
  457. std::size_t median_ocellus_index_count = (median_ocellus_present) ? (*median_ocellus_model->get_groups())[0]->get_index_count() : 0;
  458. std::size_t forewings_index_count = (wings_present) ? (*forewings_model->get_groups())[0]->get_index_count() : 0;
  459. std::size_t hindwings_index_count = (wings_present) ? (*hindwings_model->get_groups())[0]->get_index_count() : 0;
  460. std::size_t exoskeleton_index_count =
  461. mesosoma_index_count
  462. + legs_index_count
  463. + head_index_count
  464. + mandibles_index_count
  465. + antennae_index_count
  466. + waist_index_count
  467. + gaster_index_count
  468. + sting_index_count;
  469. // Calculate transform from legs space to body space
  470. const math::transform<float>& legs_to_body = math::transform<float>::identity;
  471. // Reskin leg bones
  472. std::unordered_set<std::uint8_t> old_procoxa_l_indices;
  473. if (auto it = legs_skeleton.bone_map.find("procoxa_l"); it != legs_skeleton.bone_map.end())
  474. old_procoxa_l_indices.emplace(it->second);
  475. reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_procoxa_l_indices, procoxa_l_bone_index, legs_to_body);
  476. std::unordered_set<std::uint8_t> old_profemur_l_indices;
  477. if (auto it = legs_skeleton.bone_map.find("profemur_l"); it != legs_skeleton.bone_map.end())
  478. old_profemur_l_indices.emplace(it->second);
  479. reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_profemur_l_indices, profemur_l_bone_index, legs_to_body);
  480. std::unordered_set<std::uint8_t> old_protibia_l_indices;
  481. if (auto it = legs_skeleton.bone_map.find("protibia_l"); it != legs_skeleton.bone_map.end())
  482. old_protibia_l_indices.emplace(it->second);
  483. reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_protibia_l_indices, protibia_l_bone_index, legs_to_body);
  484. std::unordered_set<std::uint8_t> old_protarsus_l_indices;
  485. if (auto it = legs_skeleton.bone_map.find("protarsus1_l"); it != legs_skeleton.bone_map.end())
  486. old_protarsus_l_indices.emplace(it->second);
  487. if (auto it = legs_skeleton.bone_map.find("protarsus2_l"); it != legs_skeleton.bone_map.end())
  488. old_protarsus_l_indices.emplace(it->second);
  489. if (auto it = legs_skeleton.bone_map.find("protarsus3_l"); it != legs_skeleton.bone_map.end())
  490. old_protarsus_l_indices.emplace(it->second);
  491. if (auto it = legs_skeleton.bone_map.find("protarsus4_l"); it != legs_skeleton.bone_map.end())
  492. old_protarsus_l_indices.emplace(it->second);
  493. if (auto it = legs_skeleton.bone_map.find("protarsus5_l"); it != legs_skeleton.bone_map.end())
  494. old_protarsus_l_indices.emplace(it->second);
  495. reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_protarsus_l_indices, protarsus_l_bone_index, legs_to_body);
  496. std::unordered_set<std::uint8_t> old_procoxa_r_indices;
  497. if (auto it = legs_skeleton.bone_map.find("procoxa_r"); it != legs_skeleton.bone_map.end())
  498. old_procoxa_r_indices.emplace(it->second);
  499. reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_procoxa_r_indices, procoxa_r_bone_index, legs_to_body);
  500. std::unordered_set<std::uint8_t> old_profemur_r_indices;
  501. if (auto it = legs_skeleton.bone_map.find("profemur_r"); it != legs_skeleton.bone_map.end())
  502. old_profemur_r_indices.emplace(it->second);
  503. reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_profemur_r_indices, profemur_r_bone_index, legs_to_body);
  504. std::unordered_set<std::uint8_t> old_protibia_r_indices;
  505. if (auto it = legs_skeleton.bone_map.find("protibia_r"); it != legs_skeleton.bone_map.end())
  506. old_protibia_r_indices.emplace(it->second);
  507. reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_protibia_r_indices, protibia_r_bone_index, legs_to_body);
  508. std::unordered_set<std::uint8_t> old_protarsus_r_indices;
  509. if (auto it = legs_skeleton.bone_map.find("protarsus1_r"); it != legs_skeleton.bone_map.end())
  510. old_protarsus_r_indices.emplace(it->second);
  511. if (auto it = legs_skeleton.bone_map.find("protarsus2_r"); it != legs_skeleton.bone_map.end())
  512. old_protarsus_r_indices.emplace(it->second);
  513. if (auto it = legs_skeleton.bone_map.find("protarsus3_r"); it != legs_skeleton.bone_map.end())
  514. old_protarsus_r_indices.emplace(it->second);
  515. if (auto it = legs_skeleton.bone_map.find("protarsus4_r"); it != legs_skeleton.bone_map.end())
  516. old_protarsus_r_indices.emplace(it->second);
  517. if (auto it = legs_skeleton.bone_map.find("protarsus5_r"); it != legs_skeleton.bone_map.end())
  518. old_protarsus_r_indices.emplace(it->second);
  519. reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_protarsus_r_indices, protarsus_r_bone_index, legs_to_body);
  520. std::unordered_set<std::uint8_t> old_mesocoxa_l_indices;
  521. if (auto it = legs_skeleton.bone_map.find("mesocoxa_l"); it != legs_skeleton.bone_map.end())
  522. old_mesocoxa_l_indices.emplace(it->second);
  523. reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_mesocoxa_l_indices, mesocoxa_l_bone_index, legs_to_body);
  524. std::unordered_set<std::uint8_t> old_mesofemur_l_indices;
  525. if (auto it = legs_skeleton.bone_map.find("mesofemur_l"); it != legs_skeleton.bone_map.end())
  526. old_mesofemur_l_indices.emplace(it->second);
  527. reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_mesofemur_l_indices, mesofemur_l_bone_index, legs_to_body);
  528. std::unordered_set<std::uint8_t> old_mesotibia_l_indices;
  529. if (auto it = legs_skeleton.bone_map.find("mesotibia_l"); it != legs_skeleton.bone_map.end())
  530. old_mesotibia_l_indices.emplace(it->second);
  531. reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_mesotibia_l_indices, mesotibia_l_bone_index, legs_to_body);
  532. std::unordered_set<std::uint8_t> old_mesotarsus_l_indices;
  533. if (auto it = legs_skeleton.bone_map.find("mesotarsus1_l"); it != legs_skeleton.bone_map.end())
  534. old_mesotarsus_l_indices.emplace(it->second);
  535. if (auto it = legs_skeleton.bone_map.find("mesotarsus2_l"); it != legs_skeleton.bone_map.end())
  536. old_mesotarsus_l_indices.emplace(it->second);
  537. if (auto it = legs_skeleton.bone_map.find("mesotarsus3_l"); it != legs_skeleton.bone_map.end())
  538. old_mesotarsus_l_indices.emplace(it->second);
  539. if (auto it = legs_skeleton.bone_map.find("mesotarsus4_l"); it != legs_skeleton.bone_map.end())
  540. old_mesotarsus_l_indices.emplace(it->second);
  541. if (auto it = legs_skeleton.bone_map.find("mesotarsus5_l"); it != legs_skeleton.bone_map.end())
  542. old_mesotarsus_l_indices.emplace(it->second);
  543. reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_mesotarsus_l_indices, mesotarsus_l_bone_index, legs_to_body);
  544. std::unordered_set<std::uint8_t> old_mesocoxa_r_indices;
  545. if (auto it = legs_skeleton.bone_map.find("mesocoxa_r"); it != legs_skeleton.bone_map.end())
  546. old_mesocoxa_r_indices.emplace(it->second);
  547. reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_mesocoxa_r_indices, mesocoxa_r_bone_index, legs_to_body);
  548. std::unordered_set<std::uint8_t> old_mesofemur_r_indices;
  549. if (auto it = legs_skeleton.bone_map.find("mesofemur_r"); it != legs_skeleton.bone_map.end())
  550. old_mesofemur_r_indices.emplace(it->second);
  551. reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_mesofemur_r_indices, mesofemur_r_bone_index, legs_to_body);
  552. std::unordered_set<std::uint8_t> old_mesotibia_r_indices;
  553. if (auto it = legs_skeleton.bone_map.find("mesotibia_r"); it != legs_skeleton.bone_map.end())
  554. old_mesotibia_r_indices.emplace(it->second);
  555. reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_mesotibia_r_indices, mesotibia_r_bone_index, legs_to_body);
  556. std::unordered_set<std::uint8_t> old_mesotarsus_r_indices;
  557. if (auto it = legs_skeleton.bone_map.find("mesotarsus1_r"); it != legs_skeleton.bone_map.end())
  558. old_mesotarsus_r_indices.emplace(it->second);
  559. if (auto it = legs_skeleton.bone_map.find("mesotarsus2_r"); it != legs_skeleton.bone_map.end())
  560. old_mesotarsus_r_indices.emplace(it->second);
  561. if (auto it = legs_skeleton.bone_map.find("mesotarsus3_r"); it != legs_skeleton.bone_map.end())
  562. old_mesotarsus_r_indices.emplace(it->second);
  563. if (auto it = legs_skeleton.bone_map.find("mesotarsus4_r"); it != legs_skeleton.bone_map.end())
  564. old_mesotarsus_r_indices.emplace(it->second);
  565. if (auto it = legs_skeleton.bone_map.find("mesotarsus5_r"); it != legs_skeleton.bone_map.end())
  566. old_mesotarsus_r_indices.emplace(it->second);
  567. reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_mesotarsus_r_indices, mesotarsus_r_bone_index, legs_to_body);
  568. std::unordered_set<std::uint8_t> old_metacoxa_l_indices;
  569. if (auto it = legs_skeleton.bone_map.find("metacoxa_l"); it != legs_skeleton.bone_map.end())
  570. old_metacoxa_l_indices.emplace(it->second);
  571. reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_metacoxa_l_indices, metacoxa_l_bone_index, legs_to_body);
  572. std::unordered_set<std::uint8_t> old_metafemur_l_indices;
  573. if (auto it = legs_skeleton.bone_map.find("metafemur_l"); it != legs_skeleton.bone_map.end())
  574. old_metafemur_l_indices.emplace(it->second);
  575. reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_metafemur_l_indices, metafemur_l_bone_index, legs_to_body);
  576. std::unordered_set<std::uint8_t> old_metatibia_l_indices;
  577. if (auto it = legs_skeleton.bone_map.find("metatibia_l"); it != legs_skeleton.bone_map.end())
  578. old_metatibia_l_indices.emplace(it->second);
  579. reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_metatibia_l_indices, metatibia_l_bone_index, legs_to_body);
  580. std::unordered_set<std::uint8_t> old_metatarsus_l_indices;
  581. if (auto it = legs_skeleton.bone_map.find("metatarsus1_l"); it != legs_skeleton.bone_map.end())
  582. old_metatarsus_l_indices.emplace(it->second);
  583. if (auto it = legs_skeleton.bone_map.find("metatarsus2_l"); it != legs_skeleton.bone_map.end())
  584. old_metatarsus_l_indices.emplace(it->second);
  585. if (auto it = legs_skeleton.bone_map.find("metatarsus3_l"); it != legs_skeleton.bone_map.end())
  586. old_metatarsus_l_indices.emplace(it->second);
  587. if (auto it = legs_skeleton.bone_map.find("metatarsus4_l"); it != legs_skeleton.bone_map.end())
  588. old_metatarsus_l_indices.emplace(it->second);
  589. if (auto it = legs_skeleton.bone_map.find("metatarsus5_l"); it != legs_skeleton.bone_map.end())
  590. old_metatarsus_l_indices.emplace(it->second);
  591. reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_metatarsus_l_indices, metatarsus_l_bone_index, legs_to_body);
  592. std::unordered_set<std::uint8_t> old_metacoxa_r_indices;
  593. if (auto it = legs_skeleton.bone_map.find("metacoxa_r"); it != legs_skeleton.bone_map.end())
  594. old_metacoxa_r_indices.emplace(it->second);
  595. reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_metacoxa_r_indices, metacoxa_r_bone_index, legs_to_body);
  596. std::unordered_set<std::uint8_t> old_metafemur_r_indices;
  597. if (auto it = legs_skeleton.bone_map.find("metafemur_r"); it != legs_skeleton.bone_map.end())
  598. old_metafemur_r_indices.emplace(it->second);
  599. reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_metafemur_r_indices, metafemur_r_bone_index, legs_to_body);
  600. std::unordered_set<std::uint8_t> old_metatibia_r_indices;
  601. if (auto it = legs_skeleton.bone_map.find("metatibia_r"); it != legs_skeleton.bone_map.end())
  602. old_metatibia_r_indices.emplace(it->second);
  603. reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_metatibia_r_indices, metatibia_r_bone_index, legs_to_body);
  604. std::unordered_set<std::uint8_t> old_metatarsus_r_indices;
  605. if (auto it = legs_skeleton.bone_map.find("metatarsus1_r"); it != legs_skeleton.bone_map.end())
  606. old_metatarsus_r_indices.emplace(it->second);
  607. if (auto it = legs_skeleton.bone_map.find("metatarsus2_r"); it != legs_skeleton.bone_map.end())
  608. old_metatarsus_r_indices.emplace(it->second);
  609. if (auto it = legs_skeleton.bone_map.find("metatarsus3_r"); it != legs_skeleton.bone_map.end())
  610. old_metatarsus_r_indices.emplace(it->second);
  611. if (auto it = legs_skeleton.bone_map.find("metatarsus4_r"); it != legs_skeleton.bone_map.end())
  612. old_metatarsus_r_indices.emplace(it->second);
  613. if (auto it = legs_skeleton.bone_map.find("metatarsus5_r"); it != legs_skeleton.bone_map.end())
  614. old_metatarsus_r_indices.emplace(it->second);
  615. reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_metatarsus_r_indices, metatarsus_r_bone_index, legs_to_body);
  616. // Calculate transform from head space to body space
  617. math::transform<float> head_to_body = bind_pose_ss.at(mesosoma_bone) * mesosoma_skeleton.bind_pose.at(mesosoma_skeleton.bone_map.at("head"));
  618. // Reskin head bone
  619. std::unordered_set<std::uint8_t> old_head_bone_indices;
  620. if (auto it = head_skeleton.bone_map.find("head"); it != head_skeleton.bone_map.end())
  621. old_head_bone_indices.emplace(it->second);
  622. 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);
  623. // Calculate transforms from mandibles space to body space
  624. math::transform<float> mandible_l_to_body = bind_pose_ss.at(head_bone) * head_skeleton.bind_pose.at(head_skeleton.bone_map.at("mandible_l"));
  625. math::transform<float> mandible_r_to_body = bind_pose_ss.at(head_bone) * head_skeleton.bind_pose.at(head_skeleton.bone_map.at("mandible_r"));
  626. // Reskin mandible bones
  627. std::unordered_set<std::uint8_t> old_head_mandible_l_bone_indices;
  628. if (auto it = mandibles_skeleton.bone_map.find("mandible_l"); it != mandibles_skeleton.bone_map.end())
  629. old_head_mandible_l_bone_indices.emplace(it->second);
  630. 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);
  631. std::unordered_set<std::uint8_t> old_head_mandible_r_bone_indices;
  632. if (auto it = mandibles_skeleton.bone_map.find("mandible_r"); it != mandibles_skeleton.bone_map.end())
  633. old_head_mandible_r_bone_indices.emplace(it->second);
  634. 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);
  635. // Calculate transforms from antennae space to body space
  636. math::transform<float> antenna_l_to_body = bind_pose_ss.at(head_bone) * head_skeleton.bind_pose.at(head_skeleton.bone_map.at("antenna_l"));
  637. math::transform<float> antenna_r_to_body = bind_pose_ss.at(head_bone) * head_skeleton.bind_pose.at(head_skeleton.bone_map.at("antenna_r"));
  638. // Reskin antennomere1 bones
  639. std::unordered_set<std::uint8_t> old_antennomere1_l_indices;
  640. if (auto it = antennae_skeleton.bone_map.find("antennomere1_l"); it != antennae_skeleton.bone_map.end())
  641. old_antennomere1_l_indices.emplace(it->second);
  642. reskin_vertices(vertex_buffer_data + antennae_vbo_offset, antennae_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_antennomere1_l_indices, antennomere1_l_bone_index, antenna_l_to_body);
  643. std::unordered_set<std::uint8_t> old_antennomere1_r_indices;
  644. if (auto it = antennae_skeleton.bone_map.find("antennomere1_r"); it != antennae_skeleton.bone_map.end())
  645. old_antennomere1_r_indices.emplace(it->second);
  646. reskin_vertices(vertex_buffer_data + antennae_vbo_offset, antennae_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_antennomere1_r_indices, antennomere1_r_bone_index, antenna_r_to_body);
  647. // Reskin antennomere2+ bones
  648. const std::vector<std::string> antennomere_bone_names =
  649. {
  650. "antennomere2",
  651. "antennomere3",
  652. "antennomere4",
  653. "antennomere5",
  654. "antennomere6",
  655. "antennomere7",
  656. "antennomere8",
  657. "antennomere9",
  658. "antennomere10",
  659. "antennomere11",
  660. "antennomere12",
  661. "antennomere13"
  662. };
  663. std::unordered_set<std::uint8_t> old_antennomere_l_indices;
  664. for (const std::string& bone_name: antennomere_bone_names)
  665. if (auto it = antennae_skeleton.bone_map.find(bone_name + "_l"); it != antennae_skeleton.bone_map.end())
  666. old_antennomere_l_indices.emplace(it->second);
  667. reskin_vertices(vertex_buffer_data + antennae_vbo_offset, antennae_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_antennomere_l_indices, antennomere2_l_bone_index, antenna_l_to_body);
  668. std::unordered_set<std::uint8_t> old_antennomere_r_indices;
  669. for (const std::string& bone_name: antennomere_bone_names)
  670. if (auto it = antennae_skeleton.bone_map.find(bone_name + "_r"); it != antennae_skeleton.bone_map.end())
  671. old_antennomere_r_indices.emplace(it->second);
  672. reskin_vertices(vertex_buffer_data + antennae_vbo_offset, antennae_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_antennomere_r_indices, antennomere2_r_bone_index, antenna_r_to_body);
  673. // Calculate transform from waist space to body space
  674. math::transform<float> waist_to_body = bind_pose_ss.at(mesosoma_bone) * mesosoma_skeleton.bind_pose.at(mesosoma_skeleton.bone_map.at("petiole"));
  675. // Reskin waist bones
  676. std::unordered_set<std::uint8_t> old_petiole_bone_indices;
  677. if (auto it = waist_skeleton.bone_map.find("petiole"); it != waist_skeleton.bone_map.end())
  678. old_petiole_bone_indices.emplace(it->second);
  679. 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);
  680. if (postpetiole_present)
  681. {
  682. std::unordered_set<std::uint8_t> old_postpetiole_bone_indices;
  683. if (auto it = waist_skeleton.bone_map.find("postpetiole"); it != waist_skeleton.bone_map.end())
  684. old_postpetiole_bone_indices.emplace(it->second);
  685. 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);
  686. }
  687. // Calculate transform from gaster space to body space
  688. math::transform<float> gaster_to_body = bind_pose_ss.at(bone_parent_index(gaster_bone)) * waist_skeleton.bind_pose.at(waist_skeleton.bone_map.at("gaster"));
  689. // Reskin gaster bones
  690. std::unordered_set<std::uint8_t> old_gaster_bone_indices;
  691. if (auto it = gaster_skeleton.bone_map.find("gaster"); it != gaster_skeleton.bone_map.end())
  692. old_gaster_bone_indices.emplace(it->second);
  693. 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);
  694. if (sting_present)
  695. {
  696. // Calculate transform from sting space to body space
  697. math::transform<float> sting_to_body = gaster_to_body * gaster_skeleton.bind_pose.at(gaster_skeleton.bone_map.at("sting"));
  698. // Reskin sting bones
  699. std::unordered_set<std::uint8_t> old_sting_bone_indices;
  700. if (auto it = sting_skeleton->bone_map.find("sting"); it != sting_skeleton->bone_map.end())
  701. old_sting_bone_indices.emplace(it->second);
  702. 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);
  703. }
  704. if (eyes_present)
  705. {
  706. // Calculate transforms from eyes space to body space
  707. math::transform<float> eye_l_to_body = bind_pose_ss.at(head_bone) * head_skeleton.bind_pose.at(head_skeleton.bone_map.at("eye_l"));
  708. math::transform<float> eye_r_to_body = bind_pose_ss.at(head_bone) * head_skeleton.bind_pose.at(head_skeleton.bone_map.at("eye_r"));
  709. // Reskin eye bones
  710. std::unordered_set<std::uint8_t> old_eye_l_bone_indices;
  711. if (auto it = eyes_skeleton->bone_map.find("eye_l"); it != eyes_skeleton->bone_map.end())
  712. old_eye_l_bone_indices.emplace(it->second);
  713. 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);
  714. std::unordered_set<std::uint8_t> old_eye_r_bone_indices;
  715. if (auto it = eyes_skeleton->bone_map.find("eye_r"); it != eyes_skeleton->bone_map.end())
  716. old_eye_r_bone_indices.emplace(it->second);
  717. 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);
  718. }
  719. if (lateral_ocelli_present)
  720. {
  721. // Calculate transforms from lateral ocelli space to body space
  722. math::transform<float> ocellus_l_to_body = bind_pose_ss.at(head_bone) * head_skeleton.bind_pose.at(head_skeleton.bone_map.at("ocellus_l"));
  723. math::transform<float> ocellus_r_to_body = bind_pose_ss.at(head_bone) * head_skeleton.bind_pose.at(head_skeleton.bone_map.at("ocellus_r"));
  724. // Reskin lateral ocelli bones
  725. std::unordered_set<std::uint8_t> old_ocellus_l_bone_indices;
  726. if (auto it = lateral_ocelli_skeleton->bone_map.find("ocellus_l"); it != lateral_ocelli_skeleton->bone_map.end())
  727. old_ocellus_l_bone_indices.emplace(it->second);
  728. 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);
  729. std::unordered_set<std::uint8_t> old_ocellus_r_bone_indices;
  730. if (auto it = lateral_ocelli_skeleton->bone_map.find("ocellus_r"); it != lateral_ocelli_skeleton->bone_map.end())
  731. old_ocellus_r_bone_indices.emplace(it->second);
  732. 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);
  733. }
  734. if (median_ocellus_present)
  735. {
  736. // Calculate transforms from lateral ocelli space to body space
  737. math::transform<float> ocellus_m_to_body = bind_pose_ss.at(head_bone) * head_skeleton.bind_pose.at(head_skeleton.bone_map.at("ocellus_m"));
  738. // Reskin lateral ocelli bones
  739. std::unordered_set<std::uint8_t> old_ocellus_m_bone_indices;
  740. if (auto it = median_ocellus_skeleton->bone_map.find("ocellus_m"); it != median_ocellus_skeleton->bone_map.end())
  741. old_ocellus_m_bone_indices.emplace(it->second);
  742. 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);
  743. }
  744. // Upload vertex buffer data to model VBO
  745. model->get_vertex_buffer()->repurpose(gl::buffer_usage::static_draw, vertex_buffer_size, vertex_buffer_data);
  746. // Construct exoskeleton model group
  747. render::model_group* exoskeleton_group = model->add_group("exoskeleton");
  748. exoskeleton_group->set_material(exoskeleton_material);
  749. exoskeleton_group->set_drawing_mode(gl::drawing_mode::triangles);
  750. exoskeleton_group->set_start_index(0);
  751. exoskeleton_group->set_index_count(exoskeleton_index_count);
  752. std::size_t index_offset = exoskeleton_index_count;
  753. if (eyes_present)
  754. {
  755. // Construct eyes model group
  756. render::model_group* eyes_group = model->add_group("eyes");
  757. eyes_group->set_material((*eyes_model->get_groups())[0]->get_material());
  758. eyes_group->set_drawing_mode(gl::drawing_mode::triangles);
  759. eyes_group->set_start_index(index_offset);
  760. eyes_group->set_index_count(eyes_index_count);
  761. index_offset += eyes_index_count;
  762. }
  763. if (lateral_ocelli_present || median_ocellus_present)
  764. {
  765. // Construct ocelli model group
  766. render::model_group* ocelli_group = model->add_group("ocelli");
  767. ocelli_group->set_drawing_mode(gl::drawing_mode::triangles);
  768. ocelli_group->set_start_index(index_offset);
  769. std::size_t index_count = 0;
  770. if (lateral_ocelli_present)
  771. {
  772. index_count += lateral_ocelli_index_count;
  773. index_offset += lateral_ocelli_index_count;
  774. ocelli_group->set_material((*lateral_ocelli_model->get_groups())[0]->get_material());
  775. }
  776. if (median_ocellus_present)
  777. {
  778. index_count += median_ocellus_index_count;
  779. index_offset += median_ocellus_index_count;
  780. if (!lateral_ocelli_present)
  781. ocelli_group->set_material((*median_ocellus_model->get_groups())[0]->get_material());
  782. }
  783. ocelli_group->set_index_count(index_count);
  784. }
  785. if (wings_present)
  786. {
  787. // Construct forewings model group
  788. render::model_group* forewings_group = model->add_group("forewings");
  789. forewings_group->set_material((*forewings_model->get_groups())[0]->get_material());
  790. forewings_group->set_drawing_mode(gl::drawing_mode::triangles);
  791. forewings_group->set_start_index(index_offset);
  792. forewings_group->set_index_count(forewings_index_count);
  793. index_offset += forewings_index_count;
  794. // Construct hindwings model group
  795. render::model_group* hindwings_group = model->add_group("hindwings");
  796. hindwings_group->set_material((*hindwings_model->get_groups())[0]->get_material());
  797. hindwings_group->set_drawing_mode(gl::drawing_mode::triangles);
  798. hindwings_group->set_start_index(index_offset);
  799. hindwings_group->set_index_count(hindwings_index_count);
  800. index_offset += hindwings_index_count;
  801. }
  802. // Calculate model bounding box
  803. geom::aabb<float> bounds = calculate_bounds(vertex_buffer_data, index_offset, *position_attribute);
  804. model->set_bounds(bounds);
  805. // Free vertex buffer data
  806. delete[] vertex_buffer_data;
  807. return model;
  808. }
  809. void reskin_vertices
  810. (
  811. std::uint8_t* vertex_data,
  812. std::size_t index_count,
  813. const gl::vertex_attribute& position_attribute,
  814. const gl::vertex_attribute& normal_attribute,
  815. const gl::vertex_attribute& tangent_attribute,
  816. const gl::vertex_attribute& bone_index_attribute,
  817. const std::unordered_set<std::uint8_t>& old_bone_indices,
  818. std::uint8_t new_bone_index,
  819. const math::transform<float>& transform
  820. )
  821. {
  822. std::uint8_t* position_data = vertex_data + position_attribute.offset;
  823. std::uint8_t* normal_data = vertex_data + normal_attribute.offset;
  824. std::uint8_t* tangent_data = vertex_data + tangent_attribute.offset;
  825. std::uint8_t* bone_index_data = vertex_data + bone_index_attribute.offset;
  826. for (std::size_t i = 0; i < index_count; ++i)
  827. {
  828. // Get bone index of current vertex
  829. float* bone_index = reinterpret_cast<float*>(bone_index_data + bone_index_attribute.stride * i);
  830. // Skip irrelevant bones
  831. if (!old_bone_indices.count(static_cast<std::uint8_t>(*bone_index + 0.5f)))
  832. continue;
  833. // Get vertex position
  834. float* x = reinterpret_cast<float*>(position_data + position_attribute.stride * i);
  835. float* y = x + 1;
  836. float* z = y + 1;
  837. // Get vertex normal
  838. float* nx = reinterpret_cast<float*>(normal_data + normal_attribute.stride * i);
  839. float* ny = nx + 1;
  840. float* nz = ny + 1;
  841. // Get vertex tangent
  842. float* tx = reinterpret_cast<float*>(tangent_data + tangent_attribute.stride * i);
  843. float* ty = tx + 1;
  844. float* tz = ty + 1;
  845. //float* bts = tz + 1;
  846. // Transform vertex attributes
  847. float3 position = transform * float3{*x, *y, *z};
  848. float3 normal = math::normalize(transform.rotation * float3{*nx, *ny, *nz});
  849. float3 tangent = transform.rotation * float3{*tx, *ty, *tz};
  850. // Update vertex data
  851. *x = position.x();
  852. *y = position.y();
  853. *z = position.z();
  854. *nx = normal.x();
  855. *ny = normal.y();
  856. *nz = normal.z();
  857. *tx = tangent.x();
  858. *ty = tangent.y();
  859. *tz = tangent.z();
  860. //*bts = ...
  861. *bone_index = static_cast<float>(new_bone_index);
  862. }
  863. }
  864. geom::aabb<float> calculate_bounds(std::uint8_t* vertex_data, std::size_t index_count, const gl::vertex_attribute& position_attribute)
  865. {
  866. std::uint8_t* position_data = vertex_data + position_attribute.offset;
  867. geom::aabb<float> bounds;
  868. bounds.min_point.x() = std::numeric_limits<float>::infinity();
  869. bounds.min_point.y() = std::numeric_limits<float>::infinity();
  870. bounds.min_point.z() = std::numeric_limits<float>::infinity();
  871. bounds.max_point.x() = -std::numeric_limits<float>::infinity();
  872. bounds.max_point.y() = -std::numeric_limits<float>::infinity();
  873. bounds.max_point.z() = -std::numeric_limits<float>::infinity();
  874. for (std::size_t i = 0; i < index_count; ++i)
  875. {
  876. // Get vertex position
  877. float* x = reinterpret_cast<float*>(position_data + position_attribute.stride * i);
  878. float* y = x + 1;
  879. float* z = y + 1;
  880. bounds.min_point.x() = std::min<float>(*x, bounds.min_point.x());
  881. bounds.min_point.y() = std::min<float>(*y, bounds.min_point.y());
  882. bounds.min_point.z() = std::min<float>(*z, bounds.min_point.z());
  883. bounds.max_point.x() = std::max<float>(*x, bounds.max_point.x());
  884. bounds.max_point.y() = std::max<float>(*y, bounds.max_point.y());
  885. bounds.max_point.z() = std::max<float>(*z, bounds.max_point.z());
  886. }
  887. return bounds;
  888. }
  889. } // namespace ant
  890. } // namespace game