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

1045 lines
62 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/ant-skeleton.hpp"
  20. #include "game/ant/ant-bone-set.hpp"
  21. #include <engine/math/angles.hpp>
  22. #include <engine/math/euler-angles.hpp>
  23. namespace {
  24. /**
  25. * Generates the rest pose of ant skeleton.
  26. *
  27. * @param[in] phenome Ant phenome.
  28. * @param[in] bones Set of ant skeleton bones.
  29. * @param[in,out] skeleton Ant skeleton.
  30. */
  31. void generate_ant_rest_pose(::skeleton& skeleton, const ant_bone_set& bones, const ant_phenome& phenome)
  32. {
  33. // Get skeletons of individual body parts
  34. const ::skeleton& mesosoma_skeleton = phenome.mesosoma->model->get_skeleton();
  35. const ::skeleton& legs_skeleton = phenome.legs->model->get_skeleton();
  36. const ::skeleton& head_skeleton = phenome.head->model->get_skeleton();
  37. const ::skeleton& mandibles_skeleton = phenome.mandibles->model->get_skeleton();
  38. const ::skeleton& antennae_skeleton = phenome.antennae->model->get_skeleton();
  39. const ::skeleton& waist_skeleton = phenome.waist->model->get_skeleton();
  40. const ::skeleton& gaster_skeleton = phenome.gaster->model->get_skeleton();
  41. const ::skeleton* sting_skeleton = (phenome.sting->present) ? &phenome.sting->model->get_skeleton() : nullptr;
  42. const ::skeleton* wings_skeleton = (phenome.wings->present) ? &phenome.wings->model->get_skeleton() : nullptr;
  43. auto get_bone_transform = [](const ::skeleton& skeleton, hash::fnv1a32_t bone_name)
  44. {
  45. return skeleton.get_rest_pose().get_relative_transform(*skeleton.get_bone_index(bone_name));
  46. };
  47. // Build skeleton rest pose
  48. skeleton.set_bone_transform(bones.mesosoma, get_bone_transform(mesosoma_skeleton, "mesosoma"));
  49. skeleton.set_bone_transform(bones.procoxa_l, get_bone_transform(mesosoma_skeleton, "procoxa_socket_l") * get_bone_transform(legs_skeleton, "procoxa_l"));
  50. skeleton.set_bone_transform(bones.profemur_l, get_bone_transform(legs_skeleton, "profemur_l"));
  51. skeleton.set_bone_transform(bones.protibia_l, get_bone_transform(legs_skeleton, "protibia_l"));
  52. skeleton.set_bone_transform(bones.protarsomere1_l, get_bone_transform(legs_skeleton, "protarsomere1_l"));
  53. skeleton.set_bone_transform(bones.procoxa_r, get_bone_transform(mesosoma_skeleton, "procoxa_socket_r") * get_bone_transform(legs_skeleton, "procoxa_r"));
  54. skeleton.set_bone_transform(bones.profemur_r, get_bone_transform(legs_skeleton, "profemur_r"));
  55. skeleton.set_bone_transform(bones.protibia_r, get_bone_transform(legs_skeleton, "protibia_r"));
  56. skeleton.set_bone_transform(bones.protarsomere1_r, get_bone_transform(legs_skeleton, "protarsomere1_r"));
  57. skeleton.set_bone_transform(bones.mesocoxa_l, get_bone_transform(mesosoma_skeleton, "mesocoxa_socket_l") * get_bone_transform(legs_skeleton, "mesocoxa_l"));
  58. skeleton.set_bone_transform(bones.mesofemur_l, get_bone_transform(legs_skeleton, "mesofemur_l"));
  59. skeleton.set_bone_transform(bones.mesotibia_l, get_bone_transform(legs_skeleton, "mesotibia_l"));
  60. skeleton.set_bone_transform(bones.mesotarsomere1_l, get_bone_transform(legs_skeleton, "mesotarsomere1_l"));
  61. skeleton.set_bone_transform(bones.mesocoxa_r, get_bone_transform(mesosoma_skeleton, "mesocoxa_socket_r") * get_bone_transform(legs_skeleton, "mesocoxa_r"));
  62. skeleton.set_bone_transform(bones.mesofemur_r, get_bone_transform(legs_skeleton, "mesofemur_r"));
  63. skeleton.set_bone_transform(bones.mesotibia_r, get_bone_transform(legs_skeleton, "mesotibia_r"));
  64. skeleton.set_bone_transform(bones.mesotarsomere1_r, get_bone_transform(legs_skeleton, "mesotarsomere1_r"));
  65. skeleton.set_bone_transform(bones.metacoxa_l, get_bone_transform(mesosoma_skeleton, "metacoxa_socket_l") * get_bone_transform(legs_skeleton, "metacoxa_l"));
  66. skeleton.set_bone_transform(bones.metafemur_l, get_bone_transform(legs_skeleton, "metafemur_l"));
  67. skeleton.set_bone_transform(bones.metatibia_l, get_bone_transform(legs_skeleton, "metatibia_l"));
  68. skeleton.set_bone_transform(bones.metatarsomere1_l, get_bone_transform(legs_skeleton, "metatarsomere1_l"));
  69. skeleton.set_bone_transform(bones.metacoxa_r, get_bone_transform(mesosoma_skeleton, "metacoxa_socket_r") * get_bone_transform(legs_skeleton, "metacoxa_r"));
  70. skeleton.set_bone_transform(bones.metafemur_r, get_bone_transform(legs_skeleton, "metafemur_r"));
  71. skeleton.set_bone_transform(bones.metatibia_r, get_bone_transform(legs_skeleton, "metatibia_r"));
  72. skeleton.set_bone_transform(bones.metatarsomere1_r, get_bone_transform(legs_skeleton, "metatarsomere1_r"));
  73. skeleton.set_bone_transform(bones.head, get_bone_transform(mesosoma_skeleton, "head_socket") * get_bone_transform(head_skeleton, "head"));
  74. skeleton.set_bone_transform(bones.mandible_l, get_bone_transform(head_skeleton, "mandible_socket_l") * get_bone_transform(mandibles_skeleton, "mandible_l"));
  75. skeleton.set_bone_transform(bones.mandible_r, get_bone_transform(head_skeleton, "mandible_socket_r") * get_bone_transform(mandibles_skeleton, "mandible_r"));
  76. skeleton.set_bone_transform(bones.antennomere1_l, get_bone_transform(head_skeleton, "antenna_socket_l") * get_bone_transform(antennae_skeleton, "antennomere1_l"));
  77. skeleton.set_bone_transform(bones.antennomere2_l, get_bone_transform(antennae_skeleton, "antennomere2_l"));
  78. skeleton.set_bone_transform(bones.antennomere1_r, get_bone_transform(head_skeleton, "antenna_socket_r") * get_bone_transform(antennae_skeleton, "antennomere1_r"));
  79. skeleton.set_bone_transform(bones.antennomere2_r, get_bone_transform(antennae_skeleton, "antennomere2_r"));
  80. if (phenome.waist->present)
  81. {
  82. skeleton.set_bone_transform(*bones.petiole, get_bone_transform(mesosoma_skeleton, "petiole_socket") * get_bone_transform(waist_skeleton, "petiole"));
  83. if (phenome.waist->postpetiole_present)
  84. {
  85. skeleton.set_bone_transform(*bones.postpetiole, get_bone_transform(waist_skeleton, "postpetiole"));
  86. }
  87. skeleton.set_bone_transform(bones.gaster, get_bone_transform(waist_skeleton, "gaster_socket") * get_bone_transform(gaster_skeleton, "gaster"));
  88. }
  89. else
  90. {
  91. skeleton.set_bone_transform(bones.gaster, get_bone_transform(mesosoma_skeleton, "petiole_socket") * get_bone_transform(gaster_skeleton, "gaster"));
  92. }
  93. if (phenome.sting->present)
  94. {
  95. skeleton.set_bone_transform(*bones.sting, get_bone_transform(gaster_skeleton, "sting_socket") * get_bone_transform(*sting_skeleton, "sting"));
  96. }
  97. if (phenome.wings->present)
  98. {
  99. skeleton.set_bone_transform(*bones.forewing_l, get_bone_transform(mesosoma_skeleton, "forewing_socket_l") * get_bone_transform(*wings_skeleton, "forewing_l"));
  100. skeleton.set_bone_transform(*bones.forewing_r, get_bone_transform(mesosoma_skeleton, "forewing_socket_r") * get_bone_transform(*wings_skeleton, "forewing_r"));
  101. skeleton.set_bone_transform(*bones.hindwing_l, get_bone_transform(mesosoma_skeleton, "hindwing_socket_l") * get_bone_transform(*wings_skeleton, "hindwing_l"));
  102. skeleton.set_bone_transform(*bones.hindwing_r, get_bone_transform(mesosoma_skeleton, "hindwing_socket_r") * get_bone_transform(*wings_skeleton, "hindwing_r"));
  103. }
  104. skeleton.update_rest_pose();
  105. }
  106. /**
  107. * Generates a standing pose (named "midstance") for an ant skeleton.
  108. *
  109. * @param[in,out] skeleton Ant skeleton.
  110. * @parma bones Set of ant bone indices.
  111. */
  112. void generate_ant_midstance_pose(skeleton& skeleton, const ant_bone_set& bones)
  113. {
  114. auto& pose = skeleton.add_pose("midstance");
  115. const auto& rest_pose = skeleton.get_rest_pose();
  116. // Pose forelegs
  117. {
  118. const auto procoxa_l_angles = math::fvec3{0.0f, 40.0f, 0.0f} * math::deg2rad<float>;
  119. const auto procoxa_r_angles = procoxa_l_angles * math::fvec3{1, -1, 1};
  120. const auto profemur_l_angles = math::fvec3{31.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  121. const auto profemur_r_angles = profemur_l_angles * math::fvec3{1, 1, 1};
  122. const auto protibia_l_angles = math::fvec3{-90.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  123. const auto protibia_r_angles = protibia_l_angles * math::fvec3{1, 1, 1};
  124. const auto protarsomere1_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  125. const auto protarsomere1_r_angles = protarsomere1_l_angles * math::fvec3{1, 1, 1};
  126. auto procoxa_l_xf = math::transform<float>::identity();
  127. auto procoxa_r_xf = math::transform<float>::identity();
  128. auto profemur_l_xf = math::transform<float>::identity();
  129. auto profemur_r_xf = math::transform<float>::identity();
  130. auto protibia_l_xf = math::transform<float>::identity();
  131. auto protibia_r_xf = math::transform<float>::identity();
  132. auto protarsomere1_l_xf = math::transform<float>::identity();
  133. auto protarsomere1_r_xf = math::transform<float>::identity();
  134. procoxa_l_xf.rotation = math::euler_xyz_to_quat(procoxa_l_angles);
  135. procoxa_r_xf.rotation = math::euler_xyz_to_quat(procoxa_r_angles);
  136. profemur_l_xf.rotation = math::euler_xyz_to_quat(profemur_l_angles);
  137. profemur_r_xf.rotation = math::euler_xyz_to_quat(profemur_r_angles);
  138. protibia_l_xf.rotation = math::euler_xyz_to_quat(protibia_l_angles);
  139. protibia_r_xf.rotation = math::euler_xyz_to_quat(protibia_r_angles);
  140. protarsomere1_l_xf.rotation = math::euler_xyz_to_quat(protarsomere1_l_angles);
  141. protarsomere1_r_xf.rotation = math::euler_xyz_to_quat(protarsomere1_r_angles);
  142. pose.set_relative_transform(bones.procoxa_l, rest_pose.get_relative_transform(bones.procoxa_l) * procoxa_l_xf);
  143. pose.set_relative_transform(bones.procoxa_r, rest_pose.get_relative_transform(bones.procoxa_r) * procoxa_r_xf);
  144. pose.set_relative_transform(bones.profemur_l, rest_pose.get_relative_transform(bones.profemur_l) * profemur_l_xf);
  145. pose.set_relative_transform(bones.profemur_r, rest_pose.get_relative_transform(bones.profemur_r) * profemur_r_xf);
  146. pose.set_relative_transform(bones.protibia_l, rest_pose.get_relative_transform(bones.protibia_l) * protibia_l_xf);
  147. pose.set_relative_transform(bones.protibia_r, rest_pose.get_relative_transform(bones.protibia_r) * protibia_r_xf);
  148. pose.set_relative_transform(bones.protarsomere1_l, rest_pose.get_relative_transform(bones.protarsomere1_l) * protarsomere1_l_xf);
  149. pose.set_relative_transform(bones.protarsomere1_r, rest_pose.get_relative_transform(bones.protarsomere1_r) * protarsomere1_r_xf);
  150. }
  151. // Pose midlegs
  152. {
  153. const auto mesocoxa_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  154. const auto mesocoxa_r_angles = mesocoxa_l_angles * math::fvec3{1, 1, 1};
  155. const auto mesofemur_l_angles = math::fvec3{38.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  156. const auto mesofemur_r_angles = mesofemur_l_angles * math::fvec3{1, 1, 1};
  157. const auto mesotibia_l_angles = math::fvec3{-100.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  158. const auto mesotibia_r_angles = mesotibia_l_angles * math::fvec3{1, 1, 1};
  159. const auto mesotarsomere1_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  160. const auto mesotarsomere1_r_angles = mesotarsomere1_l_angles * math::fvec3{1, 1, 1};
  161. auto mesocoxa_l_xf = math::transform<float>::identity();
  162. auto mesocoxa_r_xf = math::transform<float>::identity();
  163. auto mesofemur_l_xf = math::transform<float>::identity();
  164. auto mesofemur_r_xf = math::transform<float>::identity();
  165. auto mesotibia_l_xf = math::transform<float>::identity();
  166. auto mesotibia_r_xf = math::transform<float>::identity();
  167. auto mesotarsomere1_l_xf = math::transform<float>::identity();
  168. auto mesotarsomere1_r_xf = math::transform<float>::identity();
  169. mesocoxa_l_xf.rotation = math::euler_xyz_to_quat(mesocoxa_l_angles);
  170. mesocoxa_r_xf.rotation = math::euler_xyz_to_quat(mesocoxa_r_angles);
  171. mesofemur_l_xf.rotation = math::euler_xyz_to_quat(mesofemur_l_angles);
  172. mesofemur_r_xf.rotation = math::euler_xyz_to_quat(mesofemur_r_angles);
  173. mesotibia_l_xf.rotation = math::euler_xyz_to_quat(mesotibia_l_angles);
  174. mesotibia_r_xf.rotation = math::euler_xyz_to_quat(mesotibia_r_angles);
  175. mesotarsomere1_l_xf.rotation = math::euler_xyz_to_quat(mesotarsomere1_l_angles);
  176. mesotarsomere1_r_xf.rotation = math::euler_xyz_to_quat(mesotarsomere1_r_angles);
  177. pose.set_relative_transform(bones.mesocoxa_l, rest_pose.get_relative_transform(bones.mesocoxa_l) * mesocoxa_l_xf);
  178. pose.set_relative_transform(bones.mesocoxa_r, rest_pose.get_relative_transform(bones.mesocoxa_r) * mesocoxa_r_xf);
  179. pose.set_relative_transform(bones.mesofemur_l, rest_pose.get_relative_transform(bones.mesofemur_l) * mesofemur_l_xf);
  180. pose.set_relative_transform(bones.mesofemur_r, rest_pose.get_relative_transform(bones.mesofemur_r) * mesofemur_r_xf);
  181. pose.set_relative_transform(bones.mesotibia_l, rest_pose.get_relative_transform(bones.mesotibia_l) * mesotibia_l_xf);
  182. pose.set_relative_transform(bones.mesotibia_r, rest_pose.get_relative_transform(bones.mesotibia_r) * mesotibia_r_xf);
  183. pose.set_relative_transform(bones.mesotarsomere1_l, rest_pose.get_relative_transform(bones.mesotarsomere1_l) * mesotarsomere1_l_xf);
  184. pose.set_relative_transform(bones.mesotarsomere1_r, rest_pose.get_relative_transform(bones.mesotarsomere1_r) * mesotarsomere1_r_xf);
  185. }
  186. // Pose hindlegs
  187. {
  188. const auto metacoxa_l_angles = math::fvec3{0.0f, -34.0f, 0.0f} * math::deg2rad<float>;
  189. const auto metacoxa_r_angles = metacoxa_l_angles * math::fvec3{1, -1, 1};
  190. const auto metafemur_l_angles = math::fvec3{48.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  191. const auto metafemur_r_angles = metafemur_l_angles * math::fvec3{1, 1, 1};
  192. const auto metatibia_l_angles = math::fvec3{-100.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  193. const auto metatibia_r_angles = metatibia_l_angles * math::fvec3{1, 1, 1};
  194. const auto metatarsomere1_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  195. const auto metatarsomere1_r_angles = metatarsomere1_l_angles * math::fvec3{1, 1, 1};
  196. auto metacoxa_l_xf = math::transform<float>::identity();
  197. auto metacoxa_r_xf = math::transform<float>::identity();
  198. auto metafemur_l_xf = math::transform<float>::identity();
  199. auto metafemur_r_xf = math::transform<float>::identity();
  200. auto metatibia_l_xf = math::transform<float>::identity();
  201. auto metatibia_r_xf = math::transform<float>::identity();
  202. auto metatarsomere1_l_xf = math::transform<float>::identity();
  203. auto metatarsomere1_r_xf = math::transform<float>::identity();
  204. metacoxa_l_xf.rotation = math::euler_xyz_to_quat(metacoxa_l_angles);
  205. metacoxa_r_xf.rotation = math::euler_xyz_to_quat(metacoxa_r_angles);
  206. metafemur_l_xf.rotation = math::euler_xyz_to_quat(metafemur_l_angles);
  207. metafemur_r_xf.rotation = math::euler_xyz_to_quat(metafemur_r_angles);
  208. metatibia_l_xf.rotation = math::euler_xyz_to_quat(metatibia_l_angles);
  209. metatibia_r_xf.rotation = math::euler_xyz_to_quat(metatibia_r_angles);
  210. metatarsomere1_l_xf.rotation = math::euler_xyz_to_quat(metatarsomere1_l_angles);
  211. metatarsomere1_r_xf.rotation = math::euler_xyz_to_quat(metatarsomere1_r_angles);
  212. pose.set_relative_transform(bones.metacoxa_l, rest_pose.get_relative_transform(bones.metacoxa_l) * metacoxa_l_xf);
  213. pose.set_relative_transform(bones.metacoxa_r, rest_pose.get_relative_transform(bones.metacoxa_r) * metacoxa_r_xf);
  214. pose.set_relative_transform(bones.metafemur_l, rest_pose.get_relative_transform(bones.metafemur_l) * metafemur_l_xf);
  215. pose.set_relative_transform(bones.metafemur_r, rest_pose.get_relative_transform(bones.metafemur_r) * metafemur_r_xf);
  216. pose.set_relative_transform(bones.metatibia_l, rest_pose.get_relative_transform(bones.metatibia_l) * metatibia_l_xf);
  217. pose.set_relative_transform(bones.metatibia_r, rest_pose.get_relative_transform(bones.metatibia_r) * metatibia_r_xf);
  218. pose.set_relative_transform(bones.metatarsomere1_l, rest_pose.get_relative_transform(bones.metatarsomere1_l) * metatarsomere1_l_xf);
  219. pose.set_relative_transform(bones.metatarsomere1_r, rest_pose.get_relative_transform(bones.metatarsomere1_r) * metatarsomere1_r_xf);
  220. }
  221. pose.update();
  222. }
  223. /**
  224. * Generates a lift-off pose (named "liftoff") for an ant skeleton.
  225. *
  226. * @param[in,out] skeleton Ant skeleton.
  227. * @parma bones Set of ant bone indices.
  228. */
  229. void generate_ant_liftoff_pose(skeleton& skeleton, const ant_bone_set& bones)
  230. {
  231. auto& pose = skeleton.add_pose("liftoff");
  232. const auto& rest_pose = skeleton.get_rest_pose();
  233. // Pose forelegs
  234. {
  235. const auto procoxa_l_angles = math::fvec3{0.0f, 50.0f, 0.0f} * math::deg2rad<float>;
  236. const auto procoxa_r_angles = procoxa_l_angles * math::fvec3{1, -1, 1};
  237. const auto profemur_l_angles = math::fvec3{34.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  238. const auto profemur_r_angles = profemur_l_angles * math::fvec3{1, 1, 1};
  239. const auto protibia_l_angles = math::fvec3{-118.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  240. const auto protibia_r_angles = protibia_l_angles * math::fvec3{1, 1, 1};
  241. const auto protarsomere1_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  242. const auto protarsomere1_r_angles = protarsomere1_l_angles * math::fvec3{1, 1, 1};
  243. auto procoxa_l_xf = math::transform<float>::identity();
  244. auto procoxa_r_xf = math::transform<float>::identity();
  245. auto profemur_l_xf = math::transform<float>::identity();
  246. auto profemur_r_xf = math::transform<float>::identity();
  247. auto protibia_l_xf = math::transform<float>::identity();
  248. auto protibia_r_xf = math::transform<float>::identity();
  249. auto protarsomere1_l_xf = math::transform<float>::identity();
  250. auto protarsomere1_r_xf = math::transform<float>::identity();
  251. procoxa_l_xf.rotation = math::euler_xyz_to_quat(procoxa_l_angles);
  252. procoxa_r_xf.rotation = math::euler_xyz_to_quat(procoxa_r_angles);
  253. profemur_l_xf.rotation = math::euler_xyz_to_quat(profemur_l_angles);
  254. profemur_r_xf.rotation = math::euler_xyz_to_quat(profemur_r_angles);
  255. protibia_l_xf.rotation = math::euler_xyz_to_quat(protibia_l_angles);
  256. protibia_r_xf.rotation = math::euler_xyz_to_quat(protibia_r_angles);
  257. protarsomere1_l_xf.rotation = math::euler_xyz_to_quat(protarsomere1_l_angles);
  258. protarsomere1_r_xf.rotation = math::euler_xyz_to_quat(protarsomere1_r_angles);
  259. pose.set_relative_transform(bones.procoxa_l, rest_pose.get_relative_transform(bones.procoxa_l) * procoxa_l_xf);
  260. pose.set_relative_transform(bones.procoxa_r, rest_pose.get_relative_transform(bones.procoxa_r) * procoxa_r_xf);
  261. pose.set_relative_transform(bones.profemur_l, rest_pose.get_relative_transform(bones.profemur_l) * profemur_l_xf);
  262. pose.set_relative_transform(bones.profemur_r, rest_pose.get_relative_transform(bones.profemur_r) * profemur_r_xf);
  263. pose.set_relative_transform(bones.protibia_l, rest_pose.get_relative_transform(bones.protibia_l) * protibia_l_xf);
  264. pose.set_relative_transform(bones.protibia_r, rest_pose.get_relative_transform(bones.protibia_r) * protibia_r_xf);
  265. pose.set_relative_transform(bones.protarsomere1_l, rest_pose.get_relative_transform(bones.protarsomere1_l) * protarsomere1_l_xf);
  266. pose.set_relative_transform(bones.protarsomere1_r, rest_pose.get_relative_transform(bones.protarsomere1_r) * protarsomere1_r_xf);
  267. }
  268. // Pose midlegs
  269. {
  270. const auto mesocoxa_l_angles = math::fvec3{0.0f, 30.0f, 0.0f} * math::deg2rad<float>;
  271. const auto mesocoxa_r_angles = mesocoxa_l_angles * math::fvec3{1, -1, 1};
  272. const auto mesofemur_l_angles = math::fvec3{36.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  273. const auto mesofemur_r_angles = mesofemur_l_angles * math::fvec3{1, 1, 1};
  274. const auto mesotibia_l_angles = math::fvec3{-110.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  275. const auto mesotibia_r_angles = mesotibia_l_angles * math::fvec3{1, 1, 1};
  276. const auto mesotarsomere1_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  277. const auto mesotarsomere1_r_angles = mesotarsomere1_l_angles * math::fvec3{1, 1, 1};
  278. auto mesocoxa_l_xf = math::transform<float>::identity();
  279. auto mesocoxa_r_xf = math::transform<float>::identity();
  280. auto mesofemur_l_xf = math::transform<float>::identity();
  281. auto mesofemur_r_xf = math::transform<float>::identity();
  282. auto mesotibia_l_xf = math::transform<float>::identity();
  283. auto mesotibia_r_xf = math::transform<float>::identity();
  284. auto mesotarsomere1_l_xf = math::transform<float>::identity();
  285. auto mesotarsomere1_r_xf = math::transform<float>::identity();
  286. mesocoxa_l_xf.rotation = math::euler_xyz_to_quat(mesocoxa_l_angles);
  287. mesocoxa_r_xf.rotation = math::euler_xyz_to_quat(mesocoxa_r_angles);
  288. mesofemur_l_xf.rotation = math::euler_xyz_to_quat(mesofemur_l_angles);
  289. mesofemur_r_xf.rotation = math::euler_xyz_to_quat(mesofemur_r_angles);
  290. mesotibia_l_xf.rotation = math::euler_xyz_to_quat(mesotibia_l_angles);
  291. mesotibia_r_xf.rotation = math::euler_xyz_to_quat(mesotibia_r_angles);
  292. mesotarsomere1_l_xf.rotation = math::euler_xyz_to_quat(mesotarsomere1_l_angles);
  293. mesotarsomere1_r_xf.rotation = math::euler_xyz_to_quat(mesotarsomere1_r_angles);
  294. pose.set_relative_transform(bones.mesocoxa_l, rest_pose.get_relative_transform(bones.mesocoxa_l) * mesocoxa_l_xf);
  295. pose.set_relative_transform(bones.mesocoxa_r, rest_pose.get_relative_transform(bones.mesocoxa_r) * mesocoxa_r_xf);
  296. pose.set_relative_transform(bones.mesofemur_l, rest_pose.get_relative_transform(bones.mesofemur_l) * mesofemur_l_xf);
  297. pose.set_relative_transform(bones.mesofemur_r, rest_pose.get_relative_transform(bones.mesofemur_r) * mesofemur_r_xf);
  298. pose.set_relative_transform(bones.mesotibia_l, rest_pose.get_relative_transform(bones.mesotibia_l) * mesotibia_l_xf);
  299. pose.set_relative_transform(bones.mesotibia_r, rest_pose.get_relative_transform(bones.mesotibia_r) * mesotibia_r_xf);
  300. pose.set_relative_transform(bones.mesotarsomere1_l, rest_pose.get_relative_transform(bones.mesotarsomere1_l) * mesotarsomere1_l_xf);
  301. pose.set_relative_transform(bones.mesotarsomere1_r, rest_pose.get_relative_transform(bones.mesotarsomere1_r) * mesotarsomere1_r_xf);
  302. }
  303. // Pose hindlegs
  304. {
  305. const auto metacoxa_l_angles = math::fvec3{0.0f, -27.5f, 0.0f} * math::deg2rad<float>;
  306. const auto metacoxa_r_angles = metacoxa_l_angles * math::fvec3{1, -1, 1};
  307. const auto metafemur_l_angles = math::fvec3{6.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  308. const auto metafemur_r_angles = metafemur_l_angles * math::fvec3{1, 1, 1};
  309. const auto metatibia_l_angles = math::fvec3{-39.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  310. const auto metatibia_r_angles = metatibia_l_angles * math::fvec3{1, 1, 1};
  311. const auto metatarsomere1_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  312. const auto metatarsomere1_r_angles = metatarsomere1_l_angles * math::fvec3{1, 1, 1};
  313. auto metacoxa_l_xf = math::transform<float>::identity();
  314. auto metacoxa_r_xf = math::transform<float>::identity();
  315. auto metafemur_l_xf = math::transform<float>::identity();
  316. auto metafemur_r_xf = math::transform<float>::identity();
  317. auto metatibia_l_xf = math::transform<float>::identity();
  318. auto metatibia_r_xf = math::transform<float>::identity();
  319. auto metatarsomere1_l_xf = math::transform<float>::identity();
  320. auto metatarsomere1_r_xf = math::transform<float>::identity();
  321. metacoxa_l_xf.rotation = math::euler_xyz_to_quat(metacoxa_l_angles);
  322. metacoxa_r_xf.rotation = math::euler_xyz_to_quat(metacoxa_r_angles);
  323. metafemur_l_xf.rotation = math::euler_xyz_to_quat(metafemur_l_angles);
  324. metafemur_r_xf.rotation = math::euler_xyz_to_quat(metafemur_r_angles);
  325. metatibia_l_xf.rotation = math::euler_xyz_to_quat(metatibia_l_angles);
  326. metatibia_r_xf.rotation = math::euler_xyz_to_quat(metatibia_r_angles);
  327. metatarsomere1_l_xf.rotation = math::euler_xyz_to_quat(metatarsomere1_l_angles);
  328. metatarsomere1_r_xf.rotation = math::euler_xyz_to_quat(metatarsomere1_r_angles);
  329. pose.set_relative_transform(bones.metacoxa_l, rest_pose.get_relative_transform(bones.metacoxa_l) * metacoxa_l_xf);
  330. pose.set_relative_transform(bones.metacoxa_r, rest_pose.get_relative_transform(bones.metacoxa_r) * metacoxa_r_xf);
  331. pose.set_relative_transform(bones.metafemur_l, rest_pose.get_relative_transform(bones.metafemur_l) * metafemur_l_xf);
  332. pose.set_relative_transform(bones.metafemur_r, rest_pose.get_relative_transform(bones.metafemur_r) * metafemur_r_xf);
  333. pose.set_relative_transform(bones.metatibia_l, rest_pose.get_relative_transform(bones.metatibia_l) * metatibia_l_xf);
  334. pose.set_relative_transform(bones.metatibia_r, rest_pose.get_relative_transform(bones.metatibia_r) * metatibia_r_xf);
  335. pose.set_relative_transform(bones.metatarsomere1_l, rest_pose.get_relative_transform(bones.metatarsomere1_l) * metatarsomere1_l_xf);
  336. pose.set_relative_transform(bones.metatarsomere1_r, rest_pose.get_relative_transform(bones.metatarsomere1_r) * metatarsomere1_r_xf);
  337. }
  338. pose.update();
  339. }
  340. /**
  341. * Generates a touchdown pose (named "touchdown") for an ant skeleton.
  342. *
  343. * @param[in,out] skeleton Ant skeleton.
  344. * @parma bones Set of ant bone indices.
  345. */
  346. void generate_ant_touchdown_pose(skeleton& skeleton, const ant_bone_set& bones)
  347. {
  348. auto& pose = skeleton.add_pose("touchdown");
  349. const auto& rest_pose = skeleton.get_rest_pose();
  350. // Pose forelegs
  351. {
  352. const auto procoxa_l_angles = math::fvec3{0.0f, 25.0f, 0.0f} * math::deg2rad<float>;
  353. const auto procoxa_r_angles = procoxa_l_angles * math::fvec3{1, -1, 1};
  354. const auto profemur_l_angles = math::fvec3{10.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  355. const auto profemur_r_angles = profemur_l_angles * math::fvec3{1, 1, 1};
  356. const auto protibia_l_angles = math::fvec3{-60.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  357. const auto protibia_r_angles = protibia_l_angles * math::fvec3{1, 1, 1};
  358. const auto protarsomere1_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  359. const auto protarsomere1_r_angles = protarsomere1_l_angles * math::fvec3{1, 1, 1};
  360. auto procoxa_l_xf = math::transform<float>::identity();
  361. auto procoxa_r_xf = math::transform<float>::identity();
  362. auto profemur_l_xf = math::transform<float>::identity();
  363. auto profemur_r_xf = math::transform<float>::identity();
  364. auto protibia_l_xf = math::transform<float>::identity();
  365. auto protibia_r_xf = math::transform<float>::identity();
  366. auto protarsomere1_l_xf = math::transform<float>::identity();
  367. auto protarsomere1_r_xf = math::transform<float>::identity();
  368. procoxa_l_xf.rotation = math::euler_xyz_to_quat(procoxa_l_angles);
  369. procoxa_r_xf.rotation = math::euler_xyz_to_quat(procoxa_r_angles);
  370. profemur_l_xf.rotation = math::euler_xyz_to_quat(profemur_l_angles);
  371. profemur_r_xf.rotation = math::euler_xyz_to_quat(profemur_r_angles);
  372. protibia_l_xf.rotation = math::euler_xyz_to_quat(protibia_l_angles);
  373. protibia_r_xf.rotation = math::euler_xyz_to_quat(protibia_r_angles);
  374. protarsomere1_l_xf.rotation = math::euler_xyz_to_quat(protarsomere1_l_angles);
  375. protarsomere1_r_xf.rotation = math::euler_xyz_to_quat(protarsomere1_r_angles);
  376. pose.set_relative_transform(bones.procoxa_l, rest_pose.get_relative_transform(bones.procoxa_l) * procoxa_l_xf);
  377. pose.set_relative_transform(bones.procoxa_r, rest_pose.get_relative_transform(bones.procoxa_r) * procoxa_r_xf);
  378. pose.set_relative_transform(bones.profemur_l, rest_pose.get_relative_transform(bones.profemur_l) * profemur_l_xf);
  379. pose.set_relative_transform(bones.profemur_r, rest_pose.get_relative_transform(bones.profemur_r) * profemur_r_xf);
  380. pose.set_relative_transform(bones.protibia_l, rest_pose.get_relative_transform(bones.protibia_l) * protibia_l_xf);
  381. pose.set_relative_transform(bones.protibia_r, rest_pose.get_relative_transform(bones.protibia_r) * protibia_r_xf);
  382. pose.set_relative_transform(bones.protarsomere1_l, rest_pose.get_relative_transform(bones.protarsomere1_l) * protarsomere1_l_xf);
  383. pose.set_relative_transform(bones.protarsomere1_r, rest_pose.get_relative_transform(bones.protarsomere1_r) * protarsomere1_r_xf);
  384. }
  385. // Pose midlegs
  386. {
  387. const auto mesocoxa_l_angles = math::fvec3{0.0f, -22.0f, 0.0f} * math::deg2rad<float>;
  388. const auto mesocoxa_r_angles = mesocoxa_l_angles * math::fvec3{1, -1, 1};
  389. const auto mesofemur_l_angles = math::fvec3{21.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  390. const auto mesofemur_r_angles = mesofemur_l_angles * math::fvec3{1, 1, 1};
  391. const auto mesotibia_l_angles = math::fvec3{-80.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  392. const auto mesotibia_r_angles = mesotibia_l_angles * math::fvec3{1, 1, 1};
  393. const auto mesotarsomere1_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  394. const auto mesotarsomere1_r_angles = mesotarsomere1_l_angles * math::fvec3{1, 1, 1};
  395. auto mesocoxa_l_xf = math::transform<float>::identity();
  396. auto mesocoxa_r_xf = math::transform<float>::identity();
  397. auto mesofemur_l_xf = math::transform<float>::identity();
  398. auto mesofemur_r_xf = math::transform<float>::identity();
  399. auto mesotibia_l_xf = math::transform<float>::identity();
  400. auto mesotibia_r_xf = math::transform<float>::identity();
  401. auto mesotarsomere1_l_xf = math::transform<float>::identity();
  402. auto mesotarsomere1_r_xf = math::transform<float>::identity();
  403. mesocoxa_l_xf.rotation = math::euler_xyz_to_quat(mesocoxa_l_angles);
  404. mesocoxa_r_xf.rotation = math::euler_xyz_to_quat(mesocoxa_r_angles);
  405. mesofemur_l_xf.rotation = math::euler_xyz_to_quat(mesofemur_l_angles);
  406. mesofemur_r_xf.rotation = math::euler_xyz_to_quat(mesofemur_r_angles);
  407. mesotibia_l_xf.rotation = math::euler_xyz_to_quat(mesotibia_l_angles);
  408. mesotibia_r_xf.rotation = math::euler_xyz_to_quat(mesotibia_r_angles);
  409. mesotarsomere1_l_xf.rotation = math::euler_xyz_to_quat(mesotarsomere1_l_angles);
  410. mesotarsomere1_r_xf.rotation = math::euler_xyz_to_quat(mesotarsomere1_r_angles);
  411. pose.set_relative_transform(bones.mesocoxa_l, rest_pose.get_relative_transform(bones.mesocoxa_l) * mesocoxa_l_xf);
  412. pose.set_relative_transform(bones.mesocoxa_r, rest_pose.get_relative_transform(bones.mesocoxa_r) * mesocoxa_r_xf);
  413. pose.set_relative_transform(bones.mesofemur_l, rest_pose.get_relative_transform(bones.mesofemur_l) * mesofemur_l_xf);
  414. pose.set_relative_transform(bones.mesofemur_r, rest_pose.get_relative_transform(bones.mesofemur_r) * mesofemur_r_xf);
  415. pose.set_relative_transform(bones.mesotibia_l, rest_pose.get_relative_transform(bones.mesotibia_l) * mesotibia_l_xf);
  416. pose.set_relative_transform(bones.mesotibia_r, rest_pose.get_relative_transform(bones.mesotibia_r) * mesotibia_r_xf);
  417. pose.set_relative_transform(bones.mesotarsomere1_l, rest_pose.get_relative_transform(bones.mesotarsomere1_l) * mesotarsomere1_l_xf);
  418. pose.set_relative_transform(bones.mesotarsomere1_r, rest_pose.get_relative_transform(bones.mesotarsomere1_r) * mesotarsomere1_r_xf);
  419. }
  420. // Pose hindlegs
  421. {
  422. const auto metacoxa_l_angles = math::fvec3{0.0f, -42.0f, 0.0f} * math::deg2rad<float>;
  423. const auto metacoxa_r_angles = metacoxa_l_angles * math::fvec3{1, -1, 1};
  424. const auto metafemur_l_angles = math::fvec3{60.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  425. const auto metafemur_r_angles = metafemur_l_angles * math::fvec3{1, 1, 1};
  426. const auto metatibia_l_angles = math::fvec3{-125.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  427. const auto metatibia_r_angles = metatibia_l_angles * math::fvec3{1, 1, 1};
  428. const auto metatarsomere1_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  429. const auto metatarsomere1_r_angles = metatarsomere1_l_angles * math::fvec3{1, 1, 1};
  430. auto metacoxa_l_xf = math::transform<float>::identity();
  431. auto metacoxa_r_xf = math::transform<float>::identity();
  432. auto metafemur_l_xf = math::transform<float>::identity();
  433. auto metafemur_r_xf = math::transform<float>::identity();
  434. auto metatibia_l_xf = math::transform<float>::identity();
  435. auto metatibia_r_xf = math::transform<float>::identity();
  436. auto metatarsomere1_l_xf = math::transform<float>::identity();
  437. auto metatarsomere1_r_xf = math::transform<float>::identity();
  438. metacoxa_l_xf.rotation = math::euler_xyz_to_quat(metacoxa_l_angles);
  439. metacoxa_r_xf.rotation = math::euler_xyz_to_quat(metacoxa_r_angles);
  440. metafemur_l_xf.rotation = math::euler_xyz_to_quat(metafemur_l_angles);
  441. metafemur_r_xf.rotation = math::euler_xyz_to_quat(metafemur_r_angles);
  442. metatibia_l_xf.rotation = math::euler_xyz_to_quat(metatibia_l_angles);
  443. metatibia_r_xf.rotation = math::euler_xyz_to_quat(metatibia_r_angles);
  444. metatarsomere1_l_xf.rotation = math::euler_xyz_to_quat(metatarsomere1_l_angles);
  445. metatarsomere1_r_xf.rotation = math::euler_xyz_to_quat(metatarsomere1_r_angles);
  446. pose.set_relative_transform(bones.metacoxa_l, rest_pose.get_relative_transform(bones.metacoxa_l) * metacoxa_l_xf);
  447. pose.set_relative_transform(bones.metacoxa_r, rest_pose.get_relative_transform(bones.metacoxa_r) * metacoxa_r_xf);
  448. pose.set_relative_transform(bones.metafemur_l, rest_pose.get_relative_transform(bones.metafemur_l) * metafemur_l_xf);
  449. pose.set_relative_transform(bones.metafemur_r, rest_pose.get_relative_transform(bones.metafemur_r) * metafemur_r_xf);
  450. pose.set_relative_transform(bones.metatibia_l, rest_pose.get_relative_transform(bones.metatibia_l) * metatibia_l_xf);
  451. pose.set_relative_transform(bones.metatibia_r, rest_pose.get_relative_transform(bones.metatibia_r) * metatibia_r_xf);
  452. pose.set_relative_transform(bones.metatarsomere1_l, rest_pose.get_relative_transform(bones.metatarsomere1_l) * metatarsomere1_l_xf);
  453. pose.set_relative_transform(bones.metatarsomere1_r, rest_pose.get_relative_transform(bones.metatarsomere1_r) * metatarsomere1_r_xf);
  454. }
  455. pose.update();
  456. }
  457. /**
  458. * Generates a pose in which each leg is lifted to its step height (named "midswing") for an ant skeleton.
  459. *
  460. * @param[in,out] skeleton Ant skeleton.
  461. * @parma bones Set of ant bone indices.
  462. */
  463. void generate_ant_midswing_pose(skeleton& skeleton, const ant_bone_set& bones)
  464. {
  465. auto& pose = skeleton.add_pose("midswing");
  466. const auto& rest_pose = skeleton.get_rest_pose();
  467. // Pose forelegs
  468. {
  469. const auto procoxa_l_angles = math::fvec3{0.0f, 37.5f, 0.0f} * math::deg2rad<float>;
  470. const auto procoxa_r_angles = procoxa_l_angles * math::fvec3{1, -1, 1};
  471. const auto profemur_l_angles = math::fvec3{60.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  472. const auto profemur_r_angles = profemur_l_angles * math::fvec3{1, 1, 1};
  473. const auto protibia_l_angles = math::fvec3{-100.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  474. const auto protibia_r_angles = protibia_l_angles * math::fvec3{1, 1, 1};
  475. const auto protarsomere1_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  476. const auto protarsomere1_r_angles = protarsomere1_l_angles * math::fvec3{1, 1, 1};
  477. auto procoxa_l_xf = math::transform<float>::identity();
  478. auto procoxa_r_xf = math::transform<float>::identity();
  479. auto profemur_l_xf = math::transform<float>::identity();
  480. auto profemur_r_xf = math::transform<float>::identity();
  481. auto protibia_l_xf = math::transform<float>::identity();
  482. auto protibia_r_xf = math::transform<float>::identity();
  483. auto protarsomere1_l_xf = math::transform<float>::identity();
  484. auto protarsomere1_r_xf = math::transform<float>::identity();
  485. procoxa_l_xf.rotation = math::euler_xyz_to_quat(procoxa_l_angles);
  486. procoxa_r_xf.rotation = math::euler_xyz_to_quat(procoxa_r_angles);
  487. profemur_l_xf.rotation = math::euler_xyz_to_quat(profemur_l_angles);
  488. profemur_r_xf.rotation = math::euler_xyz_to_quat(profemur_r_angles);
  489. protibia_l_xf.rotation = math::euler_xyz_to_quat(protibia_l_angles);
  490. protibia_r_xf.rotation = math::euler_xyz_to_quat(protibia_r_angles);
  491. protarsomere1_l_xf.rotation = math::euler_xyz_to_quat(protarsomere1_l_angles);
  492. protarsomere1_r_xf.rotation = math::euler_xyz_to_quat(protarsomere1_r_angles);
  493. pose.set_relative_transform(bones.procoxa_l, rest_pose.get_relative_transform(bones.procoxa_l) * procoxa_l_xf);
  494. pose.set_relative_transform(bones.procoxa_r, rest_pose.get_relative_transform(bones.procoxa_r) * procoxa_r_xf);
  495. pose.set_relative_transform(bones.profemur_l, rest_pose.get_relative_transform(bones.profemur_l) * profemur_l_xf);
  496. pose.set_relative_transform(bones.profemur_r, rest_pose.get_relative_transform(bones.profemur_r) * profemur_r_xf);
  497. pose.set_relative_transform(bones.protibia_l, rest_pose.get_relative_transform(bones.protibia_l) * protibia_l_xf);
  498. pose.set_relative_transform(bones.protibia_r, rest_pose.get_relative_transform(bones.protibia_r) * protibia_r_xf);
  499. pose.set_relative_transform(bones.protarsomere1_l, rest_pose.get_relative_transform(bones.protarsomere1_l) * protarsomere1_l_xf);
  500. pose.set_relative_transform(bones.protarsomere1_r, rest_pose.get_relative_transform(bones.protarsomere1_r) * protarsomere1_r_xf);
  501. }
  502. // Pose midlegs
  503. {
  504. const auto mesocoxa_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  505. const auto mesocoxa_r_angles = mesocoxa_l_angles * math::fvec3{1, 1, 1};
  506. const auto mesofemur_l_angles = math::fvec3{60.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  507. const auto mesofemur_r_angles = mesofemur_l_angles * math::fvec3{1, 1, 1};
  508. const auto mesotibia_l_angles = math::fvec3{-100.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  509. const auto mesotibia_r_angles = mesotibia_l_angles * math::fvec3{1, 1, 1};
  510. const auto mesotarsomere1_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  511. const auto mesotarsomere1_r_angles = mesotarsomere1_l_angles * math::fvec3{1, 1, 1};
  512. auto mesocoxa_l_xf = math::transform<float>::identity();
  513. auto mesocoxa_r_xf = math::transform<float>::identity();
  514. auto mesofemur_l_xf = math::transform<float>::identity();
  515. auto mesofemur_r_xf = math::transform<float>::identity();
  516. auto mesotibia_l_xf = math::transform<float>::identity();
  517. auto mesotibia_r_xf = math::transform<float>::identity();
  518. auto mesotarsomere1_l_xf = math::transform<float>::identity();
  519. auto mesotarsomere1_r_xf = math::transform<float>::identity();
  520. mesocoxa_l_xf.rotation = math::euler_xyz_to_quat(mesocoxa_l_angles);
  521. mesocoxa_r_xf.rotation = math::euler_xyz_to_quat(mesocoxa_r_angles);
  522. mesofemur_l_xf.rotation = math::euler_xyz_to_quat(mesofemur_l_angles);
  523. mesofemur_r_xf.rotation = math::euler_xyz_to_quat(mesofemur_r_angles);
  524. mesotibia_l_xf.rotation = math::euler_xyz_to_quat(mesotibia_l_angles);
  525. mesotibia_r_xf.rotation = math::euler_xyz_to_quat(mesotibia_r_angles);
  526. mesotarsomere1_l_xf.rotation = math::euler_xyz_to_quat(mesotarsomere1_l_angles);
  527. mesotarsomere1_r_xf.rotation = math::euler_xyz_to_quat(mesotarsomere1_r_angles);
  528. pose.set_relative_transform(bones.mesocoxa_l, rest_pose.get_relative_transform(bones.mesocoxa_l) * mesocoxa_l_xf);
  529. pose.set_relative_transform(bones.mesocoxa_r, rest_pose.get_relative_transform(bones.mesocoxa_r) * mesocoxa_r_xf);
  530. pose.set_relative_transform(bones.mesofemur_l, rest_pose.get_relative_transform(bones.mesofemur_l) * mesofemur_l_xf);
  531. pose.set_relative_transform(bones.mesofemur_r, rest_pose.get_relative_transform(bones.mesofemur_r) * mesofemur_r_xf);
  532. pose.set_relative_transform(bones.mesotibia_l, rest_pose.get_relative_transform(bones.mesotibia_l) * mesotibia_l_xf);
  533. pose.set_relative_transform(bones.mesotibia_r, rest_pose.get_relative_transform(bones.mesotibia_r) * mesotibia_r_xf);
  534. pose.set_relative_transform(bones.mesotarsomere1_l, rest_pose.get_relative_transform(bones.mesotarsomere1_l) * mesotarsomere1_l_xf);
  535. pose.set_relative_transform(bones.mesotarsomere1_r, rest_pose.get_relative_transform(bones.mesotarsomere1_r) * mesotarsomere1_r_xf);
  536. }
  537. // Pose hindlegs
  538. {
  539. const auto metacoxa_l_angles = math::fvec3{0.0f, -37.5f, 0.0f} * math::deg2rad<float>;
  540. const auto metacoxa_r_angles = metacoxa_l_angles * math::fvec3{1, -1, 1};
  541. const auto metafemur_l_angles = math::fvec3{60.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  542. const auto metafemur_r_angles = metafemur_l_angles * math::fvec3{1, 1, 1};
  543. const auto metatibia_l_angles = math::fvec3{-100.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  544. const auto metatibia_r_angles = metatibia_l_angles * math::fvec3{1, 1, 1};
  545. const auto metatarsomere1_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
  546. const auto metatarsomere1_r_angles = metatarsomere1_l_angles * math::fvec3{1, 1, 1};
  547. auto metacoxa_l_xf = math::transform<float>::identity();
  548. auto metacoxa_r_xf = math::transform<float>::identity();
  549. auto metafemur_l_xf = math::transform<float>::identity();
  550. auto metafemur_r_xf = math::transform<float>::identity();
  551. auto metatibia_l_xf = math::transform<float>::identity();
  552. auto metatibia_r_xf = math::transform<float>::identity();
  553. auto metatarsomere1_l_xf = math::transform<float>::identity();
  554. auto metatarsomere1_r_xf = math::transform<float>::identity();
  555. metacoxa_l_xf.rotation = math::euler_xyz_to_quat(metacoxa_l_angles);
  556. metacoxa_r_xf.rotation = math::euler_xyz_to_quat(metacoxa_r_angles);
  557. metafemur_l_xf.rotation = math::euler_xyz_to_quat(metafemur_l_angles);
  558. metafemur_r_xf.rotation = math::euler_xyz_to_quat(metafemur_r_angles);
  559. metatibia_l_xf.rotation = math::euler_xyz_to_quat(metatibia_l_angles);
  560. metatibia_r_xf.rotation = math::euler_xyz_to_quat(metatibia_r_angles);
  561. metatarsomere1_l_xf.rotation = math::euler_xyz_to_quat(metatarsomere1_l_angles);
  562. metatarsomere1_r_xf.rotation = math::euler_xyz_to_quat(metatarsomere1_r_angles);
  563. pose.set_relative_transform(bones.metacoxa_l, rest_pose.get_relative_transform(bones.metacoxa_l) * metacoxa_l_xf);
  564. pose.set_relative_transform(bones.metacoxa_r, rest_pose.get_relative_transform(bones.metacoxa_r) * metacoxa_r_xf);
  565. pose.set_relative_transform(bones.metafemur_l, rest_pose.get_relative_transform(bones.metafemur_l) * metafemur_l_xf);
  566. pose.set_relative_transform(bones.metafemur_r, rest_pose.get_relative_transform(bones.metafemur_r) * metafemur_r_xf);
  567. pose.set_relative_transform(bones.metatibia_l, rest_pose.get_relative_transform(bones.metatibia_l) * metatibia_l_xf);
  568. pose.set_relative_transform(bones.metatibia_r, rest_pose.get_relative_transform(bones.metatibia_r) * metatibia_r_xf);
  569. pose.set_relative_transform(bones.metatarsomere1_l, rest_pose.get_relative_transform(bones.metatarsomere1_l) * metatarsomere1_l_xf);
  570. pose.set_relative_transform(bones.metatarsomere1_r, rest_pose.get_relative_transform(bones.metatarsomere1_r) * metatarsomere1_r_xf);
  571. }
  572. pose.update();
  573. }
  574. /**
  575. * Generates a pupa pose (named "pupa") for an ant skeleton.
  576. *
  577. * @param[in,out] skeleton Ant skeleton.
  578. * @parma bones Set of ant bone indices.
  579. */
  580. void generate_ant_pupa_pose(skeleton& skeleton, const ant_bone_set& bones)
  581. {
  582. const auto& rest_pose = skeleton.get_rest_pose();
  583. auto& pupa_pose = skeleton.add_pose("pupa");
  584. // Fold forelegs
  585. {
  586. constexpr float procoxa_fold_angle_y = math::radians(30.0f);
  587. constexpr float procoxa_fold_angle_z = math::radians(25.0f);
  588. constexpr float procoxa_fold_angle_x = math::radians(15.0f);
  589. auto fold_procoxa_l = math::transform<float>::identity();
  590. auto fold_procoxa_r = math::transform<float>::identity();
  591. fold_procoxa_l.rotation = math::angle_axis(procoxa_fold_angle_y, math::fvec3{0, 1, 0}) * math::angle_axis(procoxa_fold_angle_z, math::fvec3{0, 0, 1}) * math::angle_axis(procoxa_fold_angle_x, math::fvec3{1, 0, 0});
  592. fold_procoxa_r.rotation = math::angle_axis(-procoxa_fold_angle_y, math::fvec3{0, 1, 0}) * math::angle_axis(-procoxa_fold_angle_z, math::fvec3{0, 0, 1}) * math::angle_axis(procoxa_fold_angle_x, math::fvec3{1, 0, 0});
  593. constexpr float profemur_fold_angle_z = math::radians(20.0f);
  594. constexpr float profemur_fold_angle_x = math::radians(80.0f);
  595. auto fold_profemur_l = math::transform<float>::identity();
  596. auto fold_profemur_r = math::transform<float>::identity();
  597. fold_profemur_l.rotation = math::angle_axis(profemur_fold_angle_z, math::fvec3{0, 0, 1}) * math::angle_axis(profemur_fold_angle_x, math::fvec3{1, 0, 0});
  598. fold_profemur_r.rotation = math::angle_axis(-profemur_fold_angle_z, math::fvec3{0, 0, 1}) * math::angle_axis(profemur_fold_angle_x, math::fvec3{1, 0, 0});
  599. constexpr float protibia_fold_angle = math::radians(165.0f);
  600. auto fold_protibia_l = math::transform<float>::identity();
  601. auto fold_protibia_r = math::transform<float>::identity();
  602. fold_protibia_l.rotation = math::angle_axis(-protibia_fold_angle, math::fvec3{1, 0, 0});
  603. fold_protibia_r.rotation = math::angle_axis(-protibia_fold_angle, math::fvec3{1, 0, 0});
  604. constexpr float protarsomere1_fold_angle = math::radians(20.0f);
  605. auto fold_protarsomere1_l = math::transform<float>::identity();
  606. auto fold_protarsomere1_r = math::transform<float>::identity();
  607. fold_protarsomere1_l.rotation = math::angle_axis(-protarsomere1_fold_angle, math::fvec3{1, 0, 0});
  608. fold_protarsomere1_r.rotation = math::angle_axis(-protarsomere1_fold_angle, math::fvec3{1, 0, 0});
  609. pupa_pose.set_relative_transform(bones.procoxa_l, rest_pose.get_relative_transform(bones.procoxa_l) * fold_procoxa_l);
  610. pupa_pose.set_relative_transform(bones.procoxa_r, rest_pose.get_relative_transform(bones.procoxa_r) * fold_procoxa_r);
  611. pupa_pose.set_relative_transform(bones.profemur_l, rest_pose.get_relative_transform(bones.profemur_l) * fold_profemur_l);
  612. pupa_pose.set_relative_transform(bones.profemur_r, rest_pose.get_relative_transform(bones.profemur_r) * fold_profemur_r);
  613. pupa_pose.set_relative_transform(bones.protibia_l, rest_pose.get_relative_transform(bones.protibia_l) * fold_protibia_l);
  614. pupa_pose.set_relative_transform(bones.protibia_r, rest_pose.get_relative_transform(bones.protibia_r) * fold_protibia_r);
  615. pupa_pose.set_relative_transform(bones.protarsomere1_l, rest_pose.get_relative_transform(bones.protarsomere1_l) * fold_protarsomere1_l);
  616. pupa_pose.set_relative_transform(bones.protarsomere1_r, rest_pose.get_relative_transform(bones.protarsomere1_r) * fold_protarsomere1_r);
  617. }
  618. // Fold midlegs
  619. {
  620. constexpr float mesocoxa_fold_angle_z = math::radians(45.0f);
  621. constexpr float mesocoxa_fold_angle_y = math::radians(45.0f);
  622. constexpr float mesocoxa_fold_angle_x = math::radians(10.0f);
  623. auto fold_mesocoxa_l = math::transform<float>::identity();
  624. auto fold_mesocoxa_r = math::transform<float>::identity();
  625. fold_mesocoxa_l.rotation = math::angle_axis(-mesocoxa_fold_angle_z, math::fvec3{0, 0, 1}) * math::angle_axis(mesocoxa_fold_angle_y, math::fvec3{0, 1, 0}) * math::angle_axis(-mesocoxa_fold_angle_x, math::fvec3{1, 0, 0});
  626. fold_mesocoxa_r.rotation = math::angle_axis(mesocoxa_fold_angle_z, math::fvec3{0, 0, 1}) * math::angle_axis(-mesocoxa_fold_angle_y, math::fvec3{0, 1, 0}) * math::angle_axis(-mesocoxa_fold_angle_x, math::fvec3{1, 0, 0});
  627. constexpr float mesofemur_fold_angle = math::radians(90.0f);
  628. auto fold_mesofemur_l = math::transform<float>::identity();
  629. auto fold_mesofemur_r = math::transform<float>::identity();
  630. fold_mesofemur_l.rotation = math::angle_axis(mesofemur_fold_angle, math::fvec3{1, 0, 0});
  631. fold_mesofemur_r.rotation = math::angle_axis(mesofemur_fold_angle, math::fvec3{1, 0, 0});
  632. constexpr float mesotibia_fold_angle = math::radians(162.0f);
  633. auto fold_mesotibia_l = math::transform<float>::identity();
  634. auto fold_mesotibia_r = math::transform<float>::identity();
  635. fold_mesotibia_l.rotation = math::angle_axis(-mesotibia_fold_angle, math::fvec3{1, 0, 0});
  636. fold_mesotibia_r.rotation = math::angle_axis(-mesotibia_fold_angle, math::fvec3{1, 0, 0});
  637. constexpr float mesotarsomere1_fold_angle = math::radians(20.0f);
  638. auto fold_mesotarsomere1_l = math::transform<float>::identity();
  639. auto fold_mesotarsomere1_r = math::transform<float>::identity();
  640. fold_mesotarsomere1_l.rotation = math::angle_axis(-mesotarsomere1_fold_angle, math::fvec3{1, 0, 0});
  641. fold_mesotarsomere1_r.rotation = math::angle_axis(-mesotarsomere1_fold_angle, math::fvec3{1, 0, 0});
  642. pupa_pose.set_relative_transform(bones.mesocoxa_l, rest_pose.get_relative_transform(bones.mesocoxa_l) * fold_mesocoxa_l);
  643. pupa_pose.set_relative_transform(bones.mesocoxa_r, rest_pose.get_relative_transform(bones.mesocoxa_r) * fold_mesocoxa_r);
  644. pupa_pose.set_relative_transform(bones.mesofemur_l, rest_pose.get_relative_transform(bones.mesofemur_l) * fold_mesofemur_l);
  645. pupa_pose.set_relative_transform(bones.mesofemur_r, rest_pose.get_relative_transform(bones.mesofemur_r) * fold_mesofemur_r);
  646. pupa_pose.set_relative_transform(bones.mesotibia_l, rest_pose.get_relative_transform(bones.mesotibia_l) * fold_mesotibia_l);
  647. pupa_pose.set_relative_transform(bones.mesotibia_r, rest_pose.get_relative_transform(bones.mesotibia_r) * fold_mesotibia_r);
  648. pupa_pose.set_relative_transform(bones.mesotarsomere1_l, rest_pose.get_relative_transform(bones.mesotarsomere1_l) * fold_mesotarsomere1_l);
  649. pupa_pose.set_relative_transform(bones.mesotarsomere1_r, rest_pose.get_relative_transform(bones.mesotarsomere1_r) * fold_mesotarsomere1_r);
  650. }
  651. // Fold hindlegs
  652. {
  653. constexpr float metacoxa_fold_angle_z = math::radians(15.0f);
  654. constexpr float metacoxa_fold_angle_y = math::radians(10.0f);
  655. constexpr float metacoxa_fold_angle_x = math::radians(25.0f);
  656. auto fold_metacoxa_l = math::transform<float>::identity();
  657. auto fold_metacoxa_r = math::transform<float>::identity();
  658. fold_metacoxa_l.rotation = math::angle_axis(-metacoxa_fold_angle_z, math::fvec3{0, 0, 1}) * math::angle_axis(-metacoxa_fold_angle_y, math::fvec3{0, 1, 0}) * math::angle_axis(metacoxa_fold_angle_x, math::fvec3{1, 0, 0});
  659. fold_metacoxa_r.rotation = math::angle_axis(metacoxa_fold_angle_z, math::fvec3{0, 0, 1}) * math::angle_axis(metacoxa_fold_angle_y, math::fvec3{0, 1, 0}) * math::angle_axis(metacoxa_fold_angle_x, math::fvec3{1, 0, 0});
  660. constexpr float metafemur_fold_angle = math::radians(105.0f);
  661. auto fold_metafemur_l = math::transform<float>::identity();
  662. auto fold_metafemur_r = math::transform<float>::identity();
  663. fold_metafemur_l.rotation = math::angle_axis(metafemur_fold_angle, math::fvec3{1, 0, 0});
  664. fold_metafemur_r.rotation = math::angle_axis(metafemur_fold_angle, math::fvec3{1, 0, 0});
  665. constexpr float metatibia_fold_angle = math::radians(165.0f);
  666. auto fold_metatibia_l = math::transform<float>::identity();
  667. auto fold_metatibia_r = math::transform<float>::identity();
  668. fold_metatibia_l.rotation = math::angle_axis(-metatibia_fold_angle, math::fvec3{1, 0, 0});
  669. fold_metatibia_r.rotation = math::angle_axis(-metatibia_fold_angle, math::fvec3{1, 0, 0});
  670. constexpr float metatarsomere1_fold_angle = math::radians(0.0f);
  671. auto fold_metatarsomere1_l = math::transform<float>::identity();
  672. auto fold_metatarsomere1_r = math::transform<float>::identity();
  673. fold_metatarsomere1_l.rotation = math::angle_axis(-metatarsomere1_fold_angle, math::fvec3{1, 0, 0});
  674. fold_metatarsomere1_r.rotation = math::angle_axis(-metatarsomere1_fold_angle, math::fvec3{1, 0, 0});
  675. pupa_pose.set_relative_transform(bones.metacoxa_l, rest_pose.get_relative_transform(bones.metacoxa_l) * fold_metacoxa_l);
  676. pupa_pose.set_relative_transform(bones.metacoxa_r, rest_pose.get_relative_transform(bones.metacoxa_r) * fold_metacoxa_r);
  677. pupa_pose.set_relative_transform(bones.metafemur_l, rest_pose.get_relative_transform(bones.metafemur_l) * fold_metafemur_l);
  678. pupa_pose.set_relative_transform(bones.metafemur_r, rest_pose.get_relative_transform(bones.metafemur_r) * fold_metafemur_r);
  679. pupa_pose.set_relative_transform(bones.metatibia_l, rest_pose.get_relative_transform(bones.metatibia_l) * fold_metatibia_l);
  680. pupa_pose.set_relative_transform(bones.metatibia_r, rest_pose.get_relative_transform(bones.metatibia_r) * fold_metatibia_r);
  681. pupa_pose.set_relative_transform(bones.metatarsomere1_l, rest_pose.get_relative_transform(bones.metatarsomere1_l) * fold_metatarsomere1_l);
  682. pupa_pose.set_relative_transform(bones.metatarsomere1_r, rest_pose.get_relative_transform(bones.metatarsomere1_r) * fold_metatarsomere1_r);
  683. }
  684. // Fold head
  685. {
  686. constexpr float head_fold_angle = math::radians(80.0f);
  687. auto fold_head = math::transform<float>::identity();
  688. fold_head.rotation = math::angle_axis(-head_fold_angle, math::fvec3{1, 0, 0});
  689. pupa_pose.set_relative_transform(bones.head, rest_pose.get_relative_transform(bones.head) * fold_head);
  690. }
  691. // Fold antennae
  692. {
  693. constexpr float antennomere1_fold_angle_y = math::radians(70.0f);
  694. constexpr float antennomere1_fold_angle_x = math::radians(45.0f);
  695. auto fold_antennomere1_l = math::transform<float>::identity();
  696. auto fold_antennomere1_r = math::transform<float>::identity();
  697. fold_antennomere1_l.rotation = math::angle_axis(-antennomere1_fold_angle_y, math::fvec3{0, 1, 0}) * math::angle_axis(-antennomere1_fold_angle_x, math::fvec3{1, 0, 0});
  698. fold_antennomere1_r.rotation = math::angle_axis(antennomere1_fold_angle_y, math::fvec3{0, 1, 0}) * math::angle_axis(-antennomere1_fold_angle_x, math::fvec3{1, 0, 0});
  699. constexpr float antennomere2_fold_angle_y = math::radians(75.0f);
  700. constexpr float antennomere2_fold_angle_x = math::radians(25.0f);
  701. auto fold_antennomere2_l = math::transform<float>::identity();
  702. auto fold_antennomere2_r = math::transform<float>::identity();
  703. fold_antennomere2_l.rotation = math::angle_axis(antennomere2_fold_angle_y, math::fvec3{0, 1, 0}) * math::angle_axis(-antennomere2_fold_angle_x, math::fvec3{1, 0, 0});
  704. fold_antennomere2_r.rotation = math::angle_axis(-antennomere2_fold_angle_y, math::fvec3{0, 1, 0}) * math::angle_axis(-antennomere2_fold_angle_x, math::fvec3{1, 0, 0});
  705. pupa_pose.set_relative_transform(bones.antennomere1_l, rest_pose.get_relative_transform(bones.antennomere1_l) * fold_antennomere1_l);
  706. pupa_pose.set_relative_transform(bones.antennomere1_r, rest_pose.get_relative_transform(bones.antennomere1_r) * fold_antennomere1_r);
  707. pupa_pose.set_relative_transform(bones.antennomere2_l, rest_pose.get_relative_transform(bones.antennomere2_l) * fold_antennomere2_l);
  708. pupa_pose.set_relative_transform(bones.antennomere2_r, rest_pose.get_relative_transform(bones.antennomere2_r) * fold_antennomere2_r);
  709. }
  710. // Fold waist + gaster
  711. {
  712. constexpr float petiole_fold_angle = math::radians(40.0f);
  713. auto fold_petiole = math::transform<float>::identity();
  714. fold_petiole.rotation = math::angle_axis(petiole_fold_angle, math::fvec3{1, 0, 0});
  715. constexpr float postpetiole_fold_angle = math::radians(35.0f);
  716. auto fold_postpetiole = math::transform<float>::identity();
  717. fold_postpetiole.rotation = math::angle_axis(-postpetiole_fold_angle, math::fvec3{1, 0, 0});
  718. constexpr float gaster_fold_angle = math::radians(0.0f);
  719. auto fold_gaster = math::transform<float>::identity();
  720. fold_gaster.rotation = math::angle_axis(-gaster_fold_angle, math::fvec3{1, 0, 0});
  721. if (bones.petiole)
  722. {
  723. pupa_pose.set_relative_transform(*bones.petiole, rest_pose.get_relative_transform(*bones.petiole) * fold_petiole);
  724. }
  725. if (bones.postpetiole)
  726. {
  727. pupa_pose.set_relative_transform(*bones.postpetiole, rest_pose.get_relative_transform(*bones.postpetiole) * fold_postpetiole);
  728. }
  729. pupa_pose.set_relative_transform(bones.gaster, rest_pose.get_relative_transform(bones.gaster) * fold_gaster);
  730. }
  731. // Invert mesosoma
  732. // {
  733. // const float mesosoma_invert_angle = math::radians(90.0f);
  734. // auto invert_mesosoma = math::transform<float>::identity();
  735. // invert_mesosoma.rotation = math::angle_axis(mesosoma_invert_angle, math::fvec3{0, 0, 1});
  736. // auto mesosoma = *skeleton.get_index("mesosoma");
  737. // pupa_pose.set_relative_transform(bones.mesosoma, invert_mesosoma * rest_pose.get_relative_transform(bones.mesosoma));
  738. // }
  739. pupa_pose.update();
  740. }
  741. } // namespace
  742. void generate_ant_skeleton(skeleton& skeleton, ant_bone_set& bones, const ant_phenome& phenome)
  743. {
  744. // Assign bone indices
  745. bone_index_type bone_index = 0;
  746. bones.mesosoma = bone_index;
  747. bones.procoxa_l = ++bone_index;
  748. bones.profemur_l = ++bone_index;
  749. bones.protibia_l = ++bone_index;
  750. bones.protarsomere1_l = ++bone_index;
  751. bones.procoxa_r = ++bone_index;
  752. bones.profemur_r = ++bone_index;
  753. bones.protibia_r = ++bone_index;
  754. bones.protarsomere1_r = ++bone_index;
  755. bones.mesocoxa_l = ++bone_index;
  756. bones.mesofemur_l = ++bone_index;
  757. bones.mesotibia_l = ++bone_index;
  758. bones.mesotarsomere1_l = ++bone_index;
  759. bones.mesocoxa_r = ++bone_index;
  760. bones.mesofemur_r = ++bone_index;
  761. bones.mesotibia_r = ++bone_index;
  762. bones.mesotarsomere1_r = ++bone_index;
  763. bones.metacoxa_l = ++bone_index;
  764. bones.metafemur_l = ++bone_index;
  765. bones.metatibia_l = ++bone_index;
  766. bones.metatarsomere1_l = ++bone_index;
  767. bones.metacoxa_r = ++bone_index;
  768. bones.metafemur_r = ++bone_index;
  769. bones.metatibia_r = ++bone_index;
  770. bones.metatarsomere1_r = ++bone_index;
  771. bones.head = ++bone_index;
  772. bones.mandible_l = ++bone_index;
  773. bones.mandible_r = ++bone_index;
  774. bones.antennomere1_l = ++bone_index;
  775. bones.antennomere2_l = ++bone_index;
  776. bones.antennomere1_r = ++bone_index;
  777. bones.antennomere2_r = ++bone_index;
  778. if (phenome.waist->present)
  779. {
  780. bones.petiole = ++bone_index;
  781. if (phenome.waist->postpetiole_present)
  782. {
  783. bones.postpetiole = ++bone_index;
  784. }
  785. }
  786. bones.gaster = ++bone_index;
  787. if (phenome.sting->present)
  788. {
  789. bones.sting = ++bone_index;
  790. }
  791. if (phenome.wings->present)
  792. {
  793. bones.forewing_l = ++bone_index;
  794. bones.forewing_r = ++bone_index;
  795. bones.hindwing_l = ++bone_index;
  796. bones.hindwing_r = ++bone_index;
  797. }
  798. // Allocate bones
  799. skeleton.add_bones(bone_index + 1);
  800. // Assign bone parents
  801. skeleton.set_bone_parent(bones.mesosoma, bones.mesosoma);
  802. skeleton.set_bone_parent(bones.procoxa_l, bones.mesosoma);
  803. skeleton.set_bone_parent(bones.profemur_l, bones.procoxa_l);
  804. skeleton.set_bone_parent(bones.protibia_l, bones.profemur_l);
  805. skeleton.set_bone_parent(bones.protarsomere1_l, bones.protibia_l);
  806. skeleton.set_bone_parent(bones.procoxa_r, bones.mesosoma);
  807. skeleton.set_bone_parent(bones.profemur_r, bones.procoxa_r);
  808. skeleton.set_bone_parent(bones.protibia_r, bones.profemur_r);
  809. skeleton.set_bone_parent(bones.protarsomere1_r, bones.protibia_r);
  810. skeleton.set_bone_parent(bones.mesocoxa_l, bones.mesosoma);
  811. skeleton.set_bone_parent(bones.mesofemur_l, bones.mesocoxa_l);
  812. skeleton.set_bone_parent(bones.mesotibia_l, bones.mesofemur_l);
  813. skeleton.set_bone_parent(bones.mesotarsomere1_l, bones.mesotibia_l);
  814. skeleton.set_bone_parent(bones.mesocoxa_r, bones.mesosoma);
  815. skeleton.set_bone_parent(bones.mesofemur_r, bones.mesocoxa_r);
  816. skeleton.set_bone_parent(bones.mesotibia_r, bones.mesofemur_r);
  817. skeleton.set_bone_parent(bones.mesotarsomere1_r, bones.mesotibia_r);
  818. skeleton.set_bone_parent(bones.metacoxa_l, bones.mesosoma);
  819. skeleton.set_bone_parent(bones.metafemur_l, bones.metacoxa_l);
  820. skeleton.set_bone_parent(bones.metatibia_l, bones.metafemur_l);
  821. skeleton.set_bone_parent(bones.metatarsomere1_l, bones.metatibia_l);
  822. skeleton.set_bone_parent(bones.metacoxa_r, bones.mesosoma);
  823. skeleton.set_bone_parent(bones.metafemur_r, bones.metacoxa_r);
  824. skeleton.set_bone_parent(bones.metatibia_r, bones.metafemur_r);
  825. skeleton.set_bone_parent(bones.metatarsomere1_r, bones.metatibia_r);
  826. skeleton.set_bone_parent(bones.head, bones.mesosoma);
  827. skeleton.set_bone_parent(bones.mandible_l, bones.head);
  828. skeleton.set_bone_parent(bones.mandible_r, bones.head);
  829. skeleton.set_bone_parent(bones.antennomere1_l, bones.head);
  830. skeleton.set_bone_parent(bones.antennomere2_l, bones.antennomere1_l);
  831. skeleton.set_bone_parent(bones.antennomere1_r, bones.head);
  832. skeleton.set_bone_parent(bones.antennomere2_r, bones.antennomere1_r);
  833. if (phenome.waist->present)
  834. {
  835. skeleton.set_bone_parent(*bones.petiole, bones.mesosoma);
  836. if (phenome.waist->postpetiole_present)
  837. {
  838. skeleton.set_bone_parent(*bones.postpetiole, *bones.petiole);
  839. skeleton.set_bone_parent(bones.gaster, *bones.postpetiole);
  840. }
  841. else
  842. {
  843. skeleton.set_bone_parent(bones.gaster, *bones.petiole);
  844. }
  845. }
  846. else
  847. {
  848. skeleton.set_bone_parent(bones.gaster, bones.mesosoma);
  849. }
  850. if (phenome.sting->present)
  851. {
  852. skeleton.set_bone_parent(*bones.sting, bones.gaster);
  853. }
  854. if (phenome.wings->present)
  855. {
  856. skeleton.set_bone_parent(*bones.forewing_l, bones.mesosoma);
  857. skeleton.set_bone_parent(*bones.forewing_r, bones.mesosoma);
  858. skeleton.set_bone_parent(*bones.hindwing_l, bones.mesosoma);
  859. skeleton.set_bone_parent(*bones.hindwing_r, bones.mesosoma);
  860. }
  861. // Assign bone names
  862. skeleton.set_bone_name(bones.mesosoma, "mesosoma");
  863. skeleton.set_bone_name(bones.procoxa_l, "procoxa_l");
  864. skeleton.set_bone_name(bones.profemur_l, "profemur_l");
  865. skeleton.set_bone_name(bones.protibia_l, "protibia_l");
  866. skeleton.set_bone_name(bones.protarsomere1_l, "protarsomere1_l");
  867. skeleton.set_bone_name(bones.procoxa_r, "procoxa_r");
  868. skeleton.set_bone_name(bones.profemur_r, "profemur_r");
  869. skeleton.set_bone_name(bones.protibia_r, "protibia_r");
  870. skeleton.set_bone_name(bones.protarsomere1_r, "protarsomere1_r");
  871. skeleton.set_bone_name(bones.mesocoxa_l, "mesocoxa_l");
  872. skeleton.set_bone_name(bones.mesofemur_l, "mesofemur_l");
  873. skeleton.set_bone_name(bones.mesotibia_l, "mesotibia_l");
  874. skeleton.set_bone_name(bones.mesotarsomere1_l, "mesotarsomere1_l");
  875. skeleton.set_bone_name(bones.mesocoxa_r, "mesocoxa_r");
  876. skeleton.set_bone_name(bones.mesofemur_r, "mesofemur_r");
  877. skeleton.set_bone_name(bones.mesotibia_r, "mesotibia_r");
  878. skeleton.set_bone_name(bones.mesotarsomere1_r, "mesotarsomere1_r");
  879. skeleton.set_bone_name(bones.metacoxa_l, "metacoxa_l");
  880. skeleton.set_bone_name(bones.metafemur_l, "metafemur_l");
  881. skeleton.set_bone_name(bones.metatibia_l, "metatibia_l");
  882. skeleton.set_bone_name(bones.metatarsomere1_l, "metatarsomere1_l");
  883. skeleton.set_bone_name(bones.metacoxa_r, "metacoxa_r");
  884. skeleton.set_bone_name(bones.metafemur_r, "metafemur_r");
  885. skeleton.set_bone_name(bones.metatibia_r, "metatibia_r");
  886. skeleton.set_bone_name(bones.metatarsomere1_r, "metatarsomere1_r");
  887. skeleton.set_bone_name(bones.head, "head");
  888. skeleton.set_bone_name(bones.mandible_l, "mandible_l");
  889. skeleton.set_bone_name(bones.mandible_r, "mandible_r");
  890. skeleton.set_bone_name(bones.antennomere1_l, "antennomere1_l");
  891. skeleton.set_bone_name(bones.antennomere2_l, "antennomere2_l");
  892. skeleton.set_bone_name(bones.antennomere1_r, "antennomere1_r");
  893. skeleton.set_bone_name(bones.antennomere2_r, "antennomere2_r");
  894. if (phenome.waist->present)
  895. {
  896. skeleton.set_bone_name(*bones.petiole, "petiole");
  897. if (phenome.waist->postpetiole_present)
  898. {
  899. skeleton.set_bone_name(*bones.postpetiole, "postpetiole");
  900. }
  901. }
  902. skeleton.set_bone_name(bones.gaster, "gaster");
  903. if (phenome.sting->present)
  904. {
  905. skeleton.set_bone_name(*bones.sting, "sting");
  906. }
  907. if (phenome.wings->present)
  908. {
  909. skeleton.set_bone_name(*bones.forewing_l, "forewing_l");
  910. skeleton.set_bone_name(*bones.forewing_r, "forewing_r");
  911. skeleton.set_bone_name(*bones.hindwing_l, "hindwing_l");
  912. skeleton.set_bone_name(*bones.hindwing_r, "hindwing_r");
  913. }
  914. // Generate poses
  915. generate_ant_rest_pose(skeleton, bones, phenome);
  916. generate_ant_midstance_pose(skeleton, bones);
  917. generate_ant_midswing_pose(skeleton, bones);
  918. generate_ant_liftoff_pose(skeleton, bones);
  919. generate_ant_touchdown_pose(skeleton, bones);
  920. generate_ant_pupa_pose(skeleton, bones);
  921. }