Antkeeper  0.0.1
ant-skeleton.cpp
Go to the documentation of this file.
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 
22 #include <engine/math/angles.hpp>
24 
25 namespace {
26 
34 void generate_ant_rest_pose(::skeleton& skeleton, const ant_bone_set& bones, const ant_phenome& phenome)
35 {
36  // Get skeletons of individual body parts
37  const ::skeleton& mesosoma_skeleton = phenome.mesosoma->model->get_skeleton();
38  const ::skeleton& legs_skeleton = phenome.legs->model->get_skeleton();
39  const ::skeleton& head_skeleton = phenome.head->model->get_skeleton();
40  const ::skeleton& mandibles_skeleton = phenome.mandibles->model->get_skeleton();
41  const ::skeleton& antennae_skeleton = phenome.antennae->model->get_skeleton();
42  const ::skeleton& waist_skeleton = phenome.waist->model->get_skeleton();
43  const ::skeleton& gaster_skeleton = phenome.gaster->model->get_skeleton();
44  const ::skeleton* sting_skeleton = (phenome.sting->present) ? &phenome.sting->model->get_skeleton() : nullptr;
45  const ::skeleton* wings_skeleton = (phenome.wings->present) ? &phenome.wings->model->get_skeleton() : nullptr;
46 
47  auto get_bone_transform = [](const ::skeleton& skeleton, hash::fnv1a32_t bone_name)
48  {
50  };
51 
52  // Build skeleton rest pose
53  skeleton.set_bone_transform(bones.mesosoma, get_bone_transform(mesosoma_skeleton, "mesosoma"));
54 
55  skeleton.set_bone_transform(bones.procoxa_l, get_bone_transform(mesosoma_skeleton, "procoxa_socket_l") * get_bone_transform(legs_skeleton, "procoxa_l"));
56  skeleton.set_bone_transform(bones.profemur_l, get_bone_transform(legs_skeleton, "profemur_l"));
57  skeleton.set_bone_transform(bones.protibia_l, get_bone_transform(legs_skeleton, "protibia_l"));
58  skeleton.set_bone_transform(bones.protarsomere1_l, get_bone_transform(legs_skeleton, "protarsomere1_l"));
59 
60  skeleton.set_bone_transform(bones.procoxa_r, get_bone_transform(mesosoma_skeleton, "procoxa_socket_r") * get_bone_transform(legs_skeleton, "procoxa_r"));
61  skeleton.set_bone_transform(bones.profemur_r, get_bone_transform(legs_skeleton, "profemur_r"));
62  skeleton.set_bone_transform(bones.protibia_r, get_bone_transform(legs_skeleton, "protibia_r"));
63  skeleton.set_bone_transform(bones.protarsomere1_r, get_bone_transform(legs_skeleton, "protarsomere1_r"));
64 
65  skeleton.set_bone_transform(bones.mesocoxa_l, get_bone_transform(mesosoma_skeleton, "mesocoxa_socket_l") * get_bone_transform(legs_skeleton, "mesocoxa_l"));
66  skeleton.set_bone_transform(bones.mesofemur_l, get_bone_transform(legs_skeleton, "mesofemur_l"));
67  skeleton.set_bone_transform(bones.mesotibia_l, get_bone_transform(legs_skeleton, "mesotibia_l"));
68  skeleton.set_bone_transform(bones.mesotarsomere1_l, get_bone_transform(legs_skeleton, "mesotarsomere1_l"));
69 
70  skeleton.set_bone_transform(bones.mesocoxa_r, get_bone_transform(mesosoma_skeleton, "mesocoxa_socket_r") * get_bone_transform(legs_skeleton, "mesocoxa_r"));
71  skeleton.set_bone_transform(bones.mesofemur_r, get_bone_transform(legs_skeleton, "mesofemur_r"));
72  skeleton.set_bone_transform(bones.mesotibia_r, get_bone_transform(legs_skeleton, "mesotibia_r"));
73  skeleton.set_bone_transform(bones.mesotarsomere1_r, get_bone_transform(legs_skeleton, "mesotarsomere1_r"));
74 
75  skeleton.set_bone_transform(bones.metacoxa_l, get_bone_transform(mesosoma_skeleton, "metacoxa_socket_l") * get_bone_transform(legs_skeleton, "metacoxa_l"));
76  skeleton.set_bone_transform(bones.metafemur_l, get_bone_transform(legs_skeleton, "metafemur_l"));
77  skeleton.set_bone_transform(bones.metatibia_l, get_bone_transform(legs_skeleton, "metatibia_l"));
78  skeleton.set_bone_transform(bones.metatarsomere1_l, get_bone_transform(legs_skeleton, "metatarsomere1_l"));
79 
80  skeleton.set_bone_transform(bones.metacoxa_r, get_bone_transform(mesosoma_skeleton, "metacoxa_socket_r") * get_bone_transform(legs_skeleton, "metacoxa_r"));
81  skeleton.set_bone_transform(bones.metafemur_r, get_bone_transform(legs_skeleton, "metafemur_r"));
82  skeleton.set_bone_transform(bones.metatibia_r, get_bone_transform(legs_skeleton, "metatibia_r"));
83  skeleton.set_bone_transform(bones.metatarsomere1_r, get_bone_transform(legs_skeleton, "metatarsomere1_r"));
84 
85  skeleton.set_bone_transform(bones.head, get_bone_transform(mesosoma_skeleton, "head_socket") * get_bone_transform(head_skeleton, "head"));
86  skeleton.set_bone_transform(bones.mandible_l, get_bone_transform(head_skeleton, "mandible_socket_l") * get_bone_transform(mandibles_skeleton, "mandible_l"));
87  skeleton.set_bone_transform(bones.mandible_r, get_bone_transform(head_skeleton, "mandible_socket_r") * get_bone_transform(mandibles_skeleton, "mandible_r"));
88  skeleton.set_bone_transform(bones.antennomere1_l, get_bone_transform(head_skeleton, "antenna_socket_l") * get_bone_transform(antennae_skeleton, "antennomere1_l"));
89  skeleton.set_bone_transform(bones.antennomere2_l, get_bone_transform(antennae_skeleton, "antennomere2_l"));
90  skeleton.set_bone_transform(bones.antennomere1_r, get_bone_transform(head_skeleton, "antenna_socket_r") * get_bone_transform(antennae_skeleton, "antennomere1_r"));
91  skeleton.set_bone_transform(bones.antennomere2_r, get_bone_transform(antennae_skeleton, "antennomere2_r"));
92 
93  if (phenome.waist->present)
94  {
95  skeleton.set_bone_transform(*bones.petiole, get_bone_transform(mesosoma_skeleton, "petiole_socket") * get_bone_transform(waist_skeleton, "petiole"));
96 
97  if (phenome.waist->postpetiole_present)
98  {
99  skeleton.set_bone_transform(*bones.postpetiole, get_bone_transform(waist_skeleton, "postpetiole"));
100  }
101 
102  skeleton.set_bone_transform(bones.gaster, get_bone_transform(waist_skeleton, "gaster_socket") * get_bone_transform(gaster_skeleton, "gaster"));
103  }
104  else
105  {
106  skeleton.set_bone_transform(bones.gaster, get_bone_transform(mesosoma_skeleton, "petiole_socket") * get_bone_transform(gaster_skeleton, "gaster"));
107  }
108 
109  if (phenome.sting->present)
110  {
111  skeleton.set_bone_transform(*bones.sting, get_bone_transform(gaster_skeleton, "sting_socket") * get_bone_transform(*sting_skeleton, "sting"));
112  }
113 
114  if (phenome.wings->present)
115  {
116  skeleton.set_bone_transform(*bones.forewing_l, get_bone_transform(mesosoma_skeleton, "forewing_socket_l") * get_bone_transform(*wings_skeleton, "forewing_l"));
117  skeleton.set_bone_transform(*bones.forewing_r, get_bone_transform(mesosoma_skeleton, "forewing_socket_r") * get_bone_transform(*wings_skeleton, "forewing_r"));
118  skeleton.set_bone_transform(*bones.hindwing_l, get_bone_transform(mesosoma_skeleton, "hindwing_socket_l") * get_bone_transform(*wings_skeleton, "hindwing_l"));
119  skeleton.set_bone_transform(*bones.hindwing_r, get_bone_transform(mesosoma_skeleton, "hindwing_socket_r") * get_bone_transform(*wings_skeleton, "hindwing_r"));
120  }
121 
123 }
124 
131 void generate_ant_midstance_pose(skeleton& skeleton, const ant_bone_set& bones)
132 {
133  auto& pose = skeleton.add_pose("midstance");
134  const auto& rest_pose = skeleton.get_rest_pose();
135 
136  // Pose forelegs
137  {
138  const auto procoxa_l_angles = math::fvec3{0.0f, 40.0f, 0.0f} * math::deg2rad<float>;
139  const auto procoxa_r_angles = procoxa_l_angles * math::fvec3{1, -1, 1};
140  const auto profemur_l_angles = math::fvec3{31.0f, 0.0f, 0.0f} * math::deg2rad<float>;
141  const auto profemur_r_angles = profemur_l_angles * math::fvec3{1, 1, 1};
142  const auto protibia_l_angles = math::fvec3{-90.0f, 0.0f, 0.0f} * math::deg2rad<float>;
143  const auto protibia_r_angles = protibia_l_angles * math::fvec3{1, 1, 1};
144  const auto protarsomere1_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
145  const auto protarsomere1_r_angles = protarsomere1_l_angles * math::fvec3{1, 1, 1};
146 
147  auto procoxa_l_xf = math::transform<float>::identity();
148  auto procoxa_r_xf = math::transform<float>::identity();
149  auto profemur_l_xf = math::transform<float>::identity();
150  auto profemur_r_xf = math::transform<float>::identity();
151  auto protibia_l_xf = math::transform<float>::identity();
152  auto protibia_r_xf = math::transform<float>::identity();
153  auto protarsomere1_l_xf = math::transform<float>::identity();
154  auto protarsomere1_r_xf = math::transform<float>::identity();
155 
156  procoxa_l_xf.rotation = math::euler_xyz_to_quat(procoxa_l_angles);
157  procoxa_r_xf.rotation = math::euler_xyz_to_quat(procoxa_r_angles);
158  profemur_l_xf.rotation = math::euler_xyz_to_quat(profemur_l_angles);
159  profemur_r_xf.rotation = math::euler_xyz_to_quat(profemur_r_angles);
160  protibia_l_xf.rotation = math::euler_xyz_to_quat(protibia_l_angles);
161  protibia_r_xf.rotation = math::euler_xyz_to_quat(protibia_r_angles);
162  protarsomere1_l_xf.rotation = math::euler_xyz_to_quat(protarsomere1_l_angles);
163  protarsomere1_r_xf.rotation = math::euler_xyz_to_quat(protarsomere1_r_angles);
164 
173  }
174 
175  // Pose midlegs
176  {
177  const auto mesocoxa_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
178  const auto mesocoxa_r_angles = mesocoxa_l_angles * math::fvec3{1, 1, 1};
179  const auto mesofemur_l_angles = math::fvec3{38.0f, 0.0f, 0.0f} * math::deg2rad<float>;
180  const auto mesofemur_r_angles = mesofemur_l_angles * math::fvec3{1, 1, 1};
181  const auto mesotibia_l_angles = math::fvec3{-100.0f, 0.0f, 0.0f} * math::deg2rad<float>;
182  const auto mesotibia_r_angles = mesotibia_l_angles * math::fvec3{1, 1, 1};
183  const auto mesotarsomere1_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
184  const auto mesotarsomere1_r_angles = mesotarsomere1_l_angles * math::fvec3{1, 1, 1};
185 
186  auto mesocoxa_l_xf = math::transform<float>::identity();
187  auto mesocoxa_r_xf = math::transform<float>::identity();
188  auto mesofemur_l_xf = math::transform<float>::identity();
189  auto mesofemur_r_xf = math::transform<float>::identity();
190  auto mesotibia_l_xf = math::transform<float>::identity();
191  auto mesotibia_r_xf = math::transform<float>::identity();
192  auto mesotarsomere1_l_xf = math::transform<float>::identity();
193  auto mesotarsomere1_r_xf = math::transform<float>::identity();
194 
195  mesocoxa_l_xf.rotation = math::euler_xyz_to_quat(mesocoxa_l_angles);
196  mesocoxa_r_xf.rotation = math::euler_xyz_to_quat(mesocoxa_r_angles);
197  mesofemur_l_xf.rotation = math::euler_xyz_to_quat(mesofemur_l_angles);
198  mesofemur_r_xf.rotation = math::euler_xyz_to_quat(mesofemur_r_angles);
199  mesotibia_l_xf.rotation = math::euler_xyz_to_quat(mesotibia_l_angles);
200  mesotibia_r_xf.rotation = math::euler_xyz_to_quat(mesotibia_r_angles);
201  mesotarsomere1_l_xf.rotation = math::euler_xyz_to_quat(mesotarsomere1_l_angles);
202  mesotarsomere1_r_xf.rotation = math::euler_xyz_to_quat(mesotarsomere1_r_angles);
203 
212  }
213 
214  // Pose hindlegs
215  {
216  const auto metacoxa_l_angles = math::fvec3{0.0f, -34.0f, 0.0f} * math::deg2rad<float>;
217  const auto metacoxa_r_angles = metacoxa_l_angles * math::fvec3{1, -1, 1};
218  const auto metafemur_l_angles = math::fvec3{48.0f, 0.0f, 0.0f} * math::deg2rad<float>;
219  const auto metafemur_r_angles = metafemur_l_angles * math::fvec3{1, 1, 1};
220  const auto metatibia_l_angles = math::fvec3{-100.0f, 0.0f, 0.0f} * math::deg2rad<float>;
221  const auto metatibia_r_angles = metatibia_l_angles * math::fvec3{1, 1, 1};
222  const auto metatarsomere1_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
223  const auto metatarsomere1_r_angles = metatarsomere1_l_angles * math::fvec3{1, 1, 1};
224 
225  auto metacoxa_l_xf = math::transform<float>::identity();
226  auto metacoxa_r_xf = math::transform<float>::identity();
227  auto metafemur_l_xf = math::transform<float>::identity();
228  auto metafemur_r_xf = math::transform<float>::identity();
229  auto metatibia_l_xf = math::transform<float>::identity();
230  auto metatibia_r_xf = math::transform<float>::identity();
231  auto metatarsomere1_l_xf = math::transform<float>::identity();
232  auto metatarsomere1_r_xf = math::transform<float>::identity();
233 
234  metacoxa_l_xf.rotation = math::euler_xyz_to_quat(metacoxa_l_angles);
235  metacoxa_r_xf.rotation = math::euler_xyz_to_quat(metacoxa_r_angles);
236  metafemur_l_xf.rotation = math::euler_xyz_to_quat(metafemur_l_angles);
237  metafemur_r_xf.rotation = math::euler_xyz_to_quat(metafemur_r_angles);
238  metatibia_l_xf.rotation = math::euler_xyz_to_quat(metatibia_l_angles);
239  metatibia_r_xf.rotation = math::euler_xyz_to_quat(metatibia_r_angles);
240  metatarsomere1_l_xf.rotation = math::euler_xyz_to_quat(metatarsomere1_l_angles);
241  metatarsomere1_r_xf.rotation = math::euler_xyz_to_quat(metatarsomere1_r_angles);
242 
251  }
252 
253  pose.update();
254 }
255 
262 void generate_ant_liftoff_pose(skeleton& skeleton, const ant_bone_set& bones)
263 {
264  auto& pose = skeleton.add_pose("liftoff");
265  const auto& rest_pose = skeleton.get_rest_pose();
266 
267  // Pose forelegs
268  {
269  const auto procoxa_l_angles = math::fvec3{0.0f, 50.0f, 0.0f} * math::deg2rad<float>;
270  const auto procoxa_r_angles = procoxa_l_angles * math::fvec3{1, -1, 1};
271  const auto profemur_l_angles = math::fvec3{34.0f, 0.0f, 0.0f} * math::deg2rad<float>;
272  const auto profemur_r_angles = profemur_l_angles * math::fvec3{1, 1, 1};
273  const auto protibia_l_angles = math::fvec3{-118.0f, 0.0f, 0.0f} * math::deg2rad<float>;
274  const auto protibia_r_angles = protibia_l_angles * math::fvec3{1, 1, 1};
275  const auto protarsomere1_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
276  const auto protarsomere1_r_angles = protarsomere1_l_angles * math::fvec3{1, 1, 1};
277 
278  auto procoxa_l_xf = math::transform<float>::identity();
279  auto procoxa_r_xf = math::transform<float>::identity();
280  auto profemur_l_xf = math::transform<float>::identity();
281  auto profemur_r_xf = math::transform<float>::identity();
282  auto protibia_l_xf = math::transform<float>::identity();
283  auto protibia_r_xf = math::transform<float>::identity();
284  auto protarsomere1_l_xf = math::transform<float>::identity();
285  auto protarsomere1_r_xf = math::transform<float>::identity();
286 
287  procoxa_l_xf.rotation = math::euler_xyz_to_quat(procoxa_l_angles);
288  procoxa_r_xf.rotation = math::euler_xyz_to_quat(procoxa_r_angles);
289  profemur_l_xf.rotation = math::euler_xyz_to_quat(profemur_l_angles);
290  profemur_r_xf.rotation = math::euler_xyz_to_quat(profemur_r_angles);
291  protibia_l_xf.rotation = math::euler_xyz_to_quat(protibia_l_angles);
292  protibia_r_xf.rotation = math::euler_xyz_to_quat(protibia_r_angles);
293  protarsomere1_l_xf.rotation = math::euler_xyz_to_quat(protarsomere1_l_angles);
294  protarsomere1_r_xf.rotation = math::euler_xyz_to_quat(protarsomere1_r_angles);
295 
304  }
305 
306  // Pose midlegs
307  {
308  const auto mesocoxa_l_angles = math::fvec3{0.0f, 30.0f, 0.0f} * math::deg2rad<float>;
309  const auto mesocoxa_r_angles = mesocoxa_l_angles * math::fvec3{1, -1, 1};
310  const auto mesofemur_l_angles = math::fvec3{36.0f, 0.0f, 0.0f} * math::deg2rad<float>;
311  const auto mesofemur_r_angles = mesofemur_l_angles * math::fvec3{1, 1, 1};
312  const auto mesotibia_l_angles = math::fvec3{-110.0f, 0.0f, 0.0f} * math::deg2rad<float>;
313  const auto mesotibia_r_angles = mesotibia_l_angles * math::fvec3{1, 1, 1};
314  const auto mesotarsomere1_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
315  const auto mesotarsomere1_r_angles = mesotarsomere1_l_angles * math::fvec3{1, 1, 1};
316 
317  auto mesocoxa_l_xf = math::transform<float>::identity();
318  auto mesocoxa_r_xf = math::transform<float>::identity();
319  auto mesofemur_l_xf = math::transform<float>::identity();
320  auto mesofemur_r_xf = math::transform<float>::identity();
321  auto mesotibia_l_xf = math::transform<float>::identity();
322  auto mesotibia_r_xf = math::transform<float>::identity();
323  auto mesotarsomere1_l_xf = math::transform<float>::identity();
324  auto mesotarsomere1_r_xf = math::transform<float>::identity();
325 
326  mesocoxa_l_xf.rotation = math::euler_xyz_to_quat(mesocoxa_l_angles);
327  mesocoxa_r_xf.rotation = math::euler_xyz_to_quat(mesocoxa_r_angles);
328  mesofemur_l_xf.rotation = math::euler_xyz_to_quat(mesofemur_l_angles);
329  mesofemur_r_xf.rotation = math::euler_xyz_to_quat(mesofemur_r_angles);
330  mesotibia_l_xf.rotation = math::euler_xyz_to_quat(mesotibia_l_angles);
331  mesotibia_r_xf.rotation = math::euler_xyz_to_quat(mesotibia_r_angles);
332  mesotarsomere1_l_xf.rotation = math::euler_xyz_to_quat(mesotarsomere1_l_angles);
333  mesotarsomere1_r_xf.rotation = math::euler_xyz_to_quat(mesotarsomere1_r_angles);
334 
343  }
344 
345  // Pose hindlegs
346  {
347  const auto metacoxa_l_angles = math::fvec3{0.0f, -27.5f, 0.0f} * math::deg2rad<float>;
348  const auto metacoxa_r_angles = metacoxa_l_angles * math::fvec3{1, -1, 1};
349  const auto metafemur_l_angles = math::fvec3{6.0f, 0.0f, 0.0f} * math::deg2rad<float>;
350  const auto metafemur_r_angles = metafemur_l_angles * math::fvec3{1, 1, 1};
351  const auto metatibia_l_angles = math::fvec3{-39.0f, 0.0f, 0.0f} * math::deg2rad<float>;
352  const auto metatibia_r_angles = metatibia_l_angles * math::fvec3{1, 1, 1};
353  const auto metatarsomere1_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
354  const auto metatarsomere1_r_angles = metatarsomere1_l_angles * math::fvec3{1, 1, 1};
355 
356  auto metacoxa_l_xf = math::transform<float>::identity();
357  auto metacoxa_r_xf = math::transform<float>::identity();
358  auto metafemur_l_xf = math::transform<float>::identity();
359  auto metafemur_r_xf = math::transform<float>::identity();
360  auto metatibia_l_xf = math::transform<float>::identity();
361  auto metatibia_r_xf = math::transform<float>::identity();
362  auto metatarsomere1_l_xf = math::transform<float>::identity();
363  auto metatarsomere1_r_xf = math::transform<float>::identity();
364 
365  metacoxa_l_xf.rotation = math::euler_xyz_to_quat(metacoxa_l_angles);
366  metacoxa_r_xf.rotation = math::euler_xyz_to_quat(metacoxa_r_angles);
367  metafemur_l_xf.rotation = math::euler_xyz_to_quat(metafemur_l_angles);
368  metafemur_r_xf.rotation = math::euler_xyz_to_quat(metafemur_r_angles);
369  metatibia_l_xf.rotation = math::euler_xyz_to_quat(metatibia_l_angles);
370  metatibia_r_xf.rotation = math::euler_xyz_to_quat(metatibia_r_angles);
371  metatarsomere1_l_xf.rotation = math::euler_xyz_to_quat(metatarsomere1_l_angles);
372  metatarsomere1_r_xf.rotation = math::euler_xyz_to_quat(metatarsomere1_r_angles);
373 
382  }
383 
384  pose.update();
385 }
386 
393 void generate_ant_touchdown_pose(skeleton& skeleton, const ant_bone_set& bones)
394 {
395  auto& pose = skeleton.add_pose("touchdown");
396  const auto& rest_pose = skeleton.get_rest_pose();
397 
398  // Pose forelegs
399  {
400  const auto procoxa_l_angles = math::fvec3{0.0f, 25.0f, 0.0f} * math::deg2rad<float>;
401  const auto procoxa_r_angles = procoxa_l_angles * math::fvec3{1, -1, 1};
402  const auto profemur_l_angles = math::fvec3{10.0f, 0.0f, 0.0f} * math::deg2rad<float>;
403  const auto profemur_r_angles = profemur_l_angles * math::fvec3{1, 1, 1};
404  const auto protibia_l_angles = math::fvec3{-60.0f, 0.0f, 0.0f} * math::deg2rad<float>;
405  const auto protibia_r_angles = protibia_l_angles * math::fvec3{1, 1, 1};
406  const auto protarsomere1_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
407  const auto protarsomere1_r_angles = protarsomere1_l_angles * math::fvec3{1, 1, 1};
408 
409  auto procoxa_l_xf = math::transform<float>::identity();
410  auto procoxa_r_xf = math::transform<float>::identity();
411  auto profemur_l_xf = math::transform<float>::identity();
412  auto profemur_r_xf = math::transform<float>::identity();
413  auto protibia_l_xf = math::transform<float>::identity();
414  auto protibia_r_xf = math::transform<float>::identity();
415  auto protarsomere1_l_xf = math::transform<float>::identity();
416  auto protarsomere1_r_xf = math::transform<float>::identity();
417 
418  procoxa_l_xf.rotation = math::euler_xyz_to_quat(procoxa_l_angles);
419  procoxa_r_xf.rotation = math::euler_xyz_to_quat(procoxa_r_angles);
420  profemur_l_xf.rotation = math::euler_xyz_to_quat(profemur_l_angles);
421  profemur_r_xf.rotation = math::euler_xyz_to_quat(profemur_r_angles);
422  protibia_l_xf.rotation = math::euler_xyz_to_quat(protibia_l_angles);
423  protibia_r_xf.rotation = math::euler_xyz_to_quat(protibia_r_angles);
424  protarsomere1_l_xf.rotation = math::euler_xyz_to_quat(protarsomere1_l_angles);
425  protarsomere1_r_xf.rotation = math::euler_xyz_to_quat(protarsomere1_r_angles);
426 
435  }
436 
437  // Pose midlegs
438  {
439  const auto mesocoxa_l_angles = math::fvec3{0.0f, -22.0f, 0.0f} * math::deg2rad<float>;
440  const auto mesocoxa_r_angles = mesocoxa_l_angles * math::fvec3{1, -1, 1};
441  const auto mesofemur_l_angles = math::fvec3{21.0f, 0.0f, 0.0f} * math::deg2rad<float>;
442  const auto mesofemur_r_angles = mesofemur_l_angles * math::fvec3{1, 1, 1};
443  const auto mesotibia_l_angles = math::fvec3{-80.0f, 0.0f, 0.0f} * math::deg2rad<float>;
444  const auto mesotibia_r_angles = mesotibia_l_angles * math::fvec3{1, 1, 1};
445  const auto mesotarsomere1_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
446  const auto mesotarsomere1_r_angles = mesotarsomere1_l_angles * math::fvec3{1, 1, 1};
447 
448  auto mesocoxa_l_xf = math::transform<float>::identity();
449  auto mesocoxa_r_xf = math::transform<float>::identity();
450  auto mesofemur_l_xf = math::transform<float>::identity();
451  auto mesofemur_r_xf = math::transform<float>::identity();
452  auto mesotibia_l_xf = math::transform<float>::identity();
453  auto mesotibia_r_xf = math::transform<float>::identity();
454  auto mesotarsomere1_l_xf = math::transform<float>::identity();
455  auto mesotarsomere1_r_xf = math::transform<float>::identity();
456 
457  mesocoxa_l_xf.rotation = math::euler_xyz_to_quat(mesocoxa_l_angles);
458  mesocoxa_r_xf.rotation = math::euler_xyz_to_quat(mesocoxa_r_angles);
459  mesofemur_l_xf.rotation = math::euler_xyz_to_quat(mesofemur_l_angles);
460  mesofemur_r_xf.rotation = math::euler_xyz_to_quat(mesofemur_r_angles);
461  mesotibia_l_xf.rotation = math::euler_xyz_to_quat(mesotibia_l_angles);
462  mesotibia_r_xf.rotation = math::euler_xyz_to_quat(mesotibia_r_angles);
463  mesotarsomere1_l_xf.rotation = math::euler_xyz_to_quat(mesotarsomere1_l_angles);
464  mesotarsomere1_r_xf.rotation = math::euler_xyz_to_quat(mesotarsomere1_r_angles);
465 
474  }
475 
476  // Pose hindlegs
477  {
478  const auto metacoxa_l_angles = math::fvec3{0.0f, -42.0f, 0.0f} * math::deg2rad<float>;
479  const auto metacoxa_r_angles = metacoxa_l_angles * math::fvec3{1, -1, 1};
480  const auto metafemur_l_angles = math::fvec3{60.0f, 0.0f, 0.0f} * math::deg2rad<float>;
481  const auto metafemur_r_angles = metafemur_l_angles * math::fvec3{1, 1, 1};
482  const auto metatibia_l_angles = math::fvec3{-125.0f, 0.0f, 0.0f} * math::deg2rad<float>;
483  const auto metatibia_r_angles = metatibia_l_angles * math::fvec3{1, 1, 1};
484  const auto metatarsomere1_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
485  const auto metatarsomere1_r_angles = metatarsomere1_l_angles * math::fvec3{1, 1, 1};
486 
487  auto metacoxa_l_xf = math::transform<float>::identity();
488  auto metacoxa_r_xf = math::transform<float>::identity();
489  auto metafemur_l_xf = math::transform<float>::identity();
490  auto metafemur_r_xf = math::transform<float>::identity();
491  auto metatibia_l_xf = math::transform<float>::identity();
492  auto metatibia_r_xf = math::transform<float>::identity();
493  auto metatarsomere1_l_xf = math::transform<float>::identity();
494  auto metatarsomere1_r_xf = math::transform<float>::identity();
495 
496  metacoxa_l_xf.rotation = math::euler_xyz_to_quat(metacoxa_l_angles);
497  metacoxa_r_xf.rotation = math::euler_xyz_to_quat(metacoxa_r_angles);
498  metafemur_l_xf.rotation = math::euler_xyz_to_quat(metafemur_l_angles);
499  metafemur_r_xf.rotation = math::euler_xyz_to_quat(metafemur_r_angles);
500  metatibia_l_xf.rotation = math::euler_xyz_to_quat(metatibia_l_angles);
501  metatibia_r_xf.rotation = math::euler_xyz_to_quat(metatibia_r_angles);
502  metatarsomere1_l_xf.rotation = math::euler_xyz_to_quat(metatarsomere1_l_angles);
503  metatarsomere1_r_xf.rotation = math::euler_xyz_to_quat(metatarsomere1_r_angles);
504 
513  }
514 
515  pose.update();
516 }
517 
524 void generate_ant_midswing_pose(skeleton& skeleton, const ant_bone_set& bones)
525 {
526  auto& pose = skeleton.add_pose("midswing");
527  const auto& rest_pose = skeleton.get_rest_pose();
528 
529  // Pose forelegs
530  {
531  const auto procoxa_l_angles = math::fvec3{0.0f, 37.5f, 0.0f} * math::deg2rad<float>;
532  const auto procoxa_r_angles = procoxa_l_angles * math::fvec3{1, -1, 1};
533  const auto profemur_l_angles = math::fvec3{60.0f, 0.0f, 0.0f} * math::deg2rad<float>;
534  const auto profemur_r_angles = profemur_l_angles * math::fvec3{1, 1, 1};
535  const auto protibia_l_angles = math::fvec3{-100.0f, 0.0f, 0.0f} * math::deg2rad<float>;
536  const auto protibia_r_angles = protibia_l_angles * math::fvec3{1, 1, 1};
537  const auto protarsomere1_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
538  const auto protarsomere1_r_angles = protarsomere1_l_angles * math::fvec3{1, 1, 1};
539 
540  auto procoxa_l_xf = math::transform<float>::identity();
541  auto procoxa_r_xf = math::transform<float>::identity();
542  auto profemur_l_xf = math::transform<float>::identity();
543  auto profemur_r_xf = math::transform<float>::identity();
544  auto protibia_l_xf = math::transform<float>::identity();
545  auto protibia_r_xf = math::transform<float>::identity();
546  auto protarsomere1_l_xf = math::transform<float>::identity();
547  auto protarsomere1_r_xf = math::transform<float>::identity();
548 
549  procoxa_l_xf.rotation = math::euler_xyz_to_quat(procoxa_l_angles);
550  procoxa_r_xf.rotation = math::euler_xyz_to_quat(procoxa_r_angles);
551  profemur_l_xf.rotation = math::euler_xyz_to_quat(profemur_l_angles);
552  profemur_r_xf.rotation = math::euler_xyz_to_quat(profemur_r_angles);
553  protibia_l_xf.rotation = math::euler_xyz_to_quat(protibia_l_angles);
554  protibia_r_xf.rotation = math::euler_xyz_to_quat(protibia_r_angles);
555  protarsomere1_l_xf.rotation = math::euler_xyz_to_quat(protarsomere1_l_angles);
556  protarsomere1_r_xf.rotation = math::euler_xyz_to_quat(protarsomere1_r_angles);
557 
566  }
567 
568  // Pose midlegs
569  {
570  const auto mesocoxa_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
571  const auto mesocoxa_r_angles = mesocoxa_l_angles * math::fvec3{1, 1, 1};
572  const auto mesofemur_l_angles = math::fvec3{60.0f, 0.0f, 0.0f} * math::deg2rad<float>;
573  const auto mesofemur_r_angles = mesofemur_l_angles * math::fvec3{1, 1, 1};
574  const auto mesotibia_l_angles = math::fvec3{-100.0f, 0.0f, 0.0f} * math::deg2rad<float>;
575  const auto mesotibia_r_angles = mesotibia_l_angles * math::fvec3{1, 1, 1};
576  const auto mesotarsomere1_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
577  const auto mesotarsomere1_r_angles = mesotarsomere1_l_angles * math::fvec3{1, 1, 1};
578 
579  auto mesocoxa_l_xf = math::transform<float>::identity();
580  auto mesocoxa_r_xf = math::transform<float>::identity();
581  auto mesofemur_l_xf = math::transform<float>::identity();
582  auto mesofemur_r_xf = math::transform<float>::identity();
583  auto mesotibia_l_xf = math::transform<float>::identity();
584  auto mesotibia_r_xf = math::transform<float>::identity();
585  auto mesotarsomere1_l_xf = math::transform<float>::identity();
586  auto mesotarsomere1_r_xf = math::transform<float>::identity();
587 
588  mesocoxa_l_xf.rotation = math::euler_xyz_to_quat(mesocoxa_l_angles);
589  mesocoxa_r_xf.rotation = math::euler_xyz_to_quat(mesocoxa_r_angles);
590  mesofemur_l_xf.rotation = math::euler_xyz_to_quat(mesofemur_l_angles);
591  mesofemur_r_xf.rotation = math::euler_xyz_to_quat(mesofemur_r_angles);
592  mesotibia_l_xf.rotation = math::euler_xyz_to_quat(mesotibia_l_angles);
593  mesotibia_r_xf.rotation = math::euler_xyz_to_quat(mesotibia_r_angles);
594  mesotarsomere1_l_xf.rotation = math::euler_xyz_to_quat(mesotarsomere1_l_angles);
595  mesotarsomere1_r_xf.rotation = math::euler_xyz_to_quat(mesotarsomere1_r_angles);
596 
605  }
606 
607  // Pose hindlegs
608  {
609  const auto metacoxa_l_angles = math::fvec3{0.0f, -37.5f, 0.0f} * math::deg2rad<float>;
610  const auto metacoxa_r_angles = metacoxa_l_angles * math::fvec3{1, -1, 1};
611  const auto metafemur_l_angles = math::fvec3{60.0f, 0.0f, 0.0f} * math::deg2rad<float>;
612  const auto metafemur_r_angles = metafemur_l_angles * math::fvec3{1, 1, 1};
613  const auto metatibia_l_angles = math::fvec3{-100.0f, 0.0f, 0.0f} * math::deg2rad<float>;
614  const auto metatibia_r_angles = metatibia_l_angles * math::fvec3{1, 1, 1};
615  const auto metatarsomere1_l_angles = math::fvec3{0.0f, 0.0f, 0.0f} * math::deg2rad<float>;
616  const auto metatarsomere1_r_angles = metatarsomere1_l_angles * math::fvec3{1, 1, 1};
617 
618  auto metacoxa_l_xf = math::transform<float>::identity();
619  auto metacoxa_r_xf = math::transform<float>::identity();
620  auto metafemur_l_xf = math::transform<float>::identity();
621  auto metafemur_r_xf = math::transform<float>::identity();
622  auto metatibia_l_xf = math::transform<float>::identity();
623  auto metatibia_r_xf = math::transform<float>::identity();
624  auto metatarsomere1_l_xf = math::transform<float>::identity();
625  auto metatarsomere1_r_xf = math::transform<float>::identity();
626 
627  metacoxa_l_xf.rotation = math::euler_xyz_to_quat(metacoxa_l_angles);
628  metacoxa_r_xf.rotation = math::euler_xyz_to_quat(metacoxa_r_angles);
629  metafemur_l_xf.rotation = math::euler_xyz_to_quat(metafemur_l_angles);
630  metafemur_r_xf.rotation = math::euler_xyz_to_quat(metafemur_r_angles);
631  metatibia_l_xf.rotation = math::euler_xyz_to_quat(metatibia_l_angles);
632  metatibia_r_xf.rotation = math::euler_xyz_to_quat(metatibia_r_angles);
633  metatarsomere1_l_xf.rotation = math::euler_xyz_to_quat(metatarsomere1_l_angles);
634  metatarsomere1_r_xf.rotation = math::euler_xyz_to_quat(metatarsomere1_r_angles);
635 
644  }
645 
646  pose.update();
647 }
648 
655 void generate_ant_pupa_pose(skeleton& skeleton, const ant_bone_set& bones)
656 {
657  const auto& rest_pose = skeleton.get_rest_pose();
658  auto& pupa_pose = skeleton.add_pose("pupa");
659 
660  // Fold forelegs
661  {
662  constexpr float procoxa_fold_angle_y = math::radians(30.0f);
663  constexpr float procoxa_fold_angle_z = math::radians(25.0f);
664  constexpr float procoxa_fold_angle_x = math::radians(15.0f);
665  auto fold_procoxa_l = math::transform<float>::identity();
666  auto fold_procoxa_r = math::transform<float>::identity();
667  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});
668  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});
669 
670  constexpr float profemur_fold_angle_z = math::radians(20.0f);
671  constexpr float profemur_fold_angle_x = math::radians(80.0f);
672  auto fold_profemur_l = math::transform<float>::identity();
673  auto fold_profemur_r = math::transform<float>::identity();
674  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});
675  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});
676 
677  constexpr float protibia_fold_angle = math::radians(165.0f);
678  auto fold_protibia_l = math::transform<float>::identity();
679  auto fold_protibia_r = math::transform<float>::identity();
680  fold_protibia_l.rotation = math::angle_axis(-protibia_fold_angle, math::fvec3{1, 0, 0});
681  fold_protibia_r.rotation = math::angle_axis(-protibia_fold_angle, math::fvec3{1, 0, 0});
682 
683  constexpr float protarsomere1_fold_angle = math::radians(20.0f);
684  auto fold_protarsomere1_l = math::transform<float>::identity();
685  auto fold_protarsomere1_r = math::transform<float>::identity();
686  fold_protarsomere1_l.rotation = math::angle_axis(-protarsomere1_fold_angle, math::fvec3{1, 0, 0});
687  fold_protarsomere1_r.rotation = math::angle_axis(-protarsomere1_fold_angle, math::fvec3{1, 0, 0});
688 
689  pupa_pose.set_relative_transform(bones.procoxa_l, rest_pose.get_relative_transform(bones.procoxa_l) * fold_procoxa_l);
690  pupa_pose.set_relative_transform(bones.procoxa_r, rest_pose.get_relative_transform(bones.procoxa_r) * fold_procoxa_r);
691  pupa_pose.set_relative_transform(bones.profemur_l, rest_pose.get_relative_transform(bones.profemur_l) * fold_profemur_l);
692  pupa_pose.set_relative_transform(bones.profemur_r, rest_pose.get_relative_transform(bones.profemur_r) * fold_profemur_r);
693  pupa_pose.set_relative_transform(bones.protibia_l, rest_pose.get_relative_transform(bones.protibia_l) * fold_protibia_l);
694  pupa_pose.set_relative_transform(bones.protibia_r, rest_pose.get_relative_transform(bones.protibia_r) * fold_protibia_r);
695  pupa_pose.set_relative_transform(bones.protarsomere1_l, rest_pose.get_relative_transform(bones.protarsomere1_l) * fold_protarsomere1_l);
696  pupa_pose.set_relative_transform(bones.protarsomere1_r, rest_pose.get_relative_transform(bones.protarsomere1_r) * fold_protarsomere1_r);
697  }
698 
699  // Fold midlegs
700  {
701  constexpr float mesocoxa_fold_angle_z = math::radians(45.0f);
702  constexpr float mesocoxa_fold_angle_y = math::radians(45.0f);
703  constexpr float mesocoxa_fold_angle_x = math::radians(10.0f);
704  auto fold_mesocoxa_l = math::transform<float>::identity();
705  auto fold_mesocoxa_r = math::transform<float>::identity();
706  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});
707  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});
708 
709  constexpr float mesofemur_fold_angle = math::radians(90.0f);
710  auto fold_mesofemur_l = math::transform<float>::identity();
711  auto fold_mesofemur_r = math::transform<float>::identity();
712  fold_mesofemur_l.rotation = math::angle_axis(mesofemur_fold_angle, math::fvec3{1, 0, 0});
713  fold_mesofemur_r.rotation = math::angle_axis(mesofemur_fold_angle, math::fvec3{1, 0, 0});
714 
715  constexpr float mesotibia_fold_angle = math::radians(162.0f);
716  auto fold_mesotibia_l = math::transform<float>::identity();
717  auto fold_mesotibia_r = math::transform<float>::identity();
718  fold_mesotibia_l.rotation = math::angle_axis(-mesotibia_fold_angle, math::fvec3{1, 0, 0});
719  fold_mesotibia_r.rotation = math::angle_axis(-mesotibia_fold_angle, math::fvec3{1, 0, 0});
720 
721  constexpr float mesotarsomere1_fold_angle = math::radians(20.0f);
722  auto fold_mesotarsomere1_l = math::transform<float>::identity();
723  auto fold_mesotarsomere1_r = math::transform<float>::identity();
724  fold_mesotarsomere1_l.rotation = math::angle_axis(-mesotarsomere1_fold_angle, math::fvec3{1, 0, 0});
725  fold_mesotarsomere1_r.rotation = math::angle_axis(-mesotarsomere1_fold_angle, math::fvec3{1, 0, 0});
726 
727  pupa_pose.set_relative_transform(bones.mesocoxa_l, rest_pose.get_relative_transform(bones.mesocoxa_l) * fold_mesocoxa_l);
728  pupa_pose.set_relative_transform(bones.mesocoxa_r, rest_pose.get_relative_transform(bones.mesocoxa_r) * fold_mesocoxa_r);
729  pupa_pose.set_relative_transform(bones.mesofemur_l, rest_pose.get_relative_transform(bones.mesofemur_l) * fold_mesofemur_l);
730  pupa_pose.set_relative_transform(bones.mesofemur_r, rest_pose.get_relative_transform(bones.mesofemur_r) * fold_mesofemur_r);
731  pupa_pose.set_relative_transform(bones.mesotibia_l, rest_pose.get_relative_transform(bones.mesotibia_l) * fold_mesotibia_l);
732  pupa_pose.set_relative_transform(bones.mesotibia_r, rest_pose.get_relative_transform(bones.mesotibia_r) * fold_mesotibia_r);
733  pupa_pose.set_relative_transform(bones.mesotarsomere1_l, rest_pose.get_relative_transform(bones.mesotarsomere1_l) * fold_mesotarsomere1_l);
734  pupa_pose.set_relative_transform(bones.mesotarsomere1_r, rest_pose.get_relative_transform(bones.mesotarsomere1_r) * fold_mesotarsomere1_r);
735  }
736 
737  // Fold hindlegs
738  {
739  constexpr float metacoxa_fold_angle_z = math::radians(15.0f);
740  constexpr float metacoxa_fold_angle_y = math::radians(10.0f);
741  constexpr float metacoxa_fold_angle_x = math::radians(25.0f);
742  auto fold_metacoxa_l = math::transform<float>::identity();
743  auto fold_metacoxa_r = math::transform<float>::identity();
744  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});
745  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});
746 
747  constexpr float metafemur_fold_angle = math::radians(105.0f);
748  auto fold_metafemur_l = math::transform<float>::identity();
749  auto fold_metafemur_r = math::transform<float>::identity();
750  fold_metafemur_l.rotation = math::angle_axis(metafemur_fold_angle, math::fvec3{1, 0, 0});
751  fold_metafemur_r.rotation = math::angle_axis(metafemur_fold_angle, math::fvec3{1, 0, 0});
752 
753  constexpr float metatibia_fold_angle = math::radians(165.0f);
754  auto fold_metatibia_l = math::transform<float>::identity();
755  auto fold_metatibia_r = math::transform<float>::identity();
756  fold_metatibia_l.rotation = math::angle_axis(-metatibia_fold_angle, math::fvec3{1, 0, 0});
757  fold_metatibia_r.rotation = math::angle_axis(-metatibia_fold_angle, math::fvec3{1, 0, 0});
758 
759  constexpr float metatarsomere1_fold_angle = math::radians(0.0f);
760  auto fold_metatarsomere1_l = math::transform<float>::identity();
761  auto fold_metatarsomere1_r = math::transform<float>::identity();
762  fold_metatarsomere1_l.rotation = math::angle_axis(-metatarsomere1_fold_angle, math::fvec3{1, 0, 0});
763  fold_metatarsomere1_r.rotation = math::angle_axis(-metatarsomere1_fold_angle, math::fvec3{1, 0, 0});
764 
765  pupa_pose.set_relative_transform(bones.metacoxa_l, rest_pose.get_relative_transform(bones.metacoxa_l) * fold_metacoxa_l);
766  pupa_pose.set_relative_transform(bones.metacoxa_r, rest_pose.get_relative_transform(bones.metacoxa_r) * fold_metacoxa_r);
767  pupa_pose.set_relative_transform(bones.metafemur_l, rest_pose.get_relative_transform(bones.metafemur_l) * fold_metafemur_l);
768  pupa_pose.set_relative_transform(bones.metafemur_r, rest_pose.get_relative_transform(bones.metafemur_r) * fold_metafemur_r);
769  pupa_pose.set_relative_transform(bones.metatibia_l, rest_pose.get_relative_transform(bones.metatibia_l) * fold_metatibia_l);
770  pupa_pose.set_relative_transform(bones.metatibia_r, rest_pose.get_relative_transform(bones.metatibia_r) * fold_metatibia_r);
771  pupa_pose.set_relative_transform(bones.metatarsomere1_l, rest_pose.get_relative_transform(bones.metatarsomere1_l) * fold_metatarsomere1_l);
772  pupa_pose.set_relative_transform(bones.metatarsomere1_r, rest_pose.get_relative_transform(bones.metatarsomere1_r) * fold_metatarsomere1_r);
773  }
774 
775  // Fold head
776  {
777  constexpr float head_fold_angle = math::radians(80.0f);
778  auto fold_head = math::transform<float>::identity();
779  fold_head.rotation = math::angle_axis(-head_fold_angle, math::fvec3{1, 0, 0});
780 
781  pupa_pose.set_relative_transform(bones.head, rest_pose.get_relative_transform(bones.head) * fold_head);
782  }
783 
784  // Fold antennae
785  {
786  constexpr float antennomere1_fold_angle_y = math::radians(70.0f);
787  constexpr float antennomere1_fold_angle_x = math::radians(45.0f);
788  auto fold_antennomere1_l = math::transform<float>::identity();
789  auto fold_antennomere1_r = math::transform<float>::identity();
790  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});
791  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});
792 
793  constexpr float antennomere2_fold_angle_y = math::radians(75.0f);
794  constexpr float antennomere2_fold_angle_x = math::radians(25.0f);
795  auto fold_antennomere2_l = math::transform<float>::identity();
796  auto fold_antennomere2_r = math::transform<float>::identity();
797  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});
798  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});
799 
800  pupa_pose.set_relative_transform(bones.antennomere1_l, rest_pose.get_relative_transform(bones.antennomere1_l) * fold_antennomere1_l);
801  pupa_pose.set_relative_transform(bones.antennomere1_r, rest_pose.get_relative_transform(bones.antennomere1_r) * fold_antennomere1_r);
802  pupa_pose.set_relative_transform(bones.antennomere2_l, rest_pose.get_relative_transform(bones.antennomere2_l) * fold_antennomere2_l);
803  pupa_pose.set_relative_transform(bones.antennomere2_r, rest_pose.get_relative_transform(bones.antennomere2_r) * fold_antennomere2_r);
804  }
805 
806  // Fold waist + gaster
807  {
808  constexpr float petiole_fold_angle = math::radians(40.0f);
809  auto fold_petiole = math::transform<float>::identity();
810  fold_petiole.rotation = math::angle_axis(petiole_fold_angle, math::fvec3{1, 0, 0});
811 
812  constexpr float postpetiole_fold_angle = math::radians(35.0f);
813  auto fold_postpetiole = math::transform<float>::identity();
814  fold_postpetiole.rotation = math::angle_axis(-postpetiole_fold_angle, math::fvec3{1, 0, 0});
815 
816  constexpr float gaster_fold_angle = math::radians(0.0f);
817  auto fold_gaster = math::transform<float>::identity();
818  fold_gaster.rotation = math::angle_axis(-gaster_fold_angle, math::fvec3{1, 0, 0});
819 
820  if (bones.petiole)
821  {
822  pupa_pose.set_relative_transform(*bones.petiole, rest_pose.get_relative_transform(*bones.petiole) * fold_petiole);
823  }
824 
825  if (bones.postpetiole)
826  {
827  pupa_pose.set_relative_transform(*bones.postpetiole, rest_pose.get_relative_transform(*bones.postpetiole) * fold_postpetiole);
828  }
829 
830  pupa_pose.set_relative_transform(bones.gaster, rest_pose.get_relative_transform(bones.gaster) * fold_gaster);
831  }
832 
833  // Invert mesosoma
834  // {
835  // const float mesosoma_invert_angle = math::radians(90.0f);
836  // auto invert_mesosoma = math::transform<float>::identity();
837  // invert_mesosoma.rotation = math::angle_axis(mesosoma_invert_angle, math::fvec3{0, 0, 1});
838 
839  // auto mesosoma = *skeleton.get_index("mesosoma");
840  // pupa_pose.set_relative_transform(bones.mesosoma, invert_mesosoma * rest_pose.get_relative_transform(bones.mesosoma));
841  // }
842 
843  pupa_pose.update();
844 }
845 
846 } // namespace
847 
849 {
850  // Assign bone indices
852  bones.mesosoma = bone_index;
853  bones.procoxa_l = ++bone_index;
854  bones.profemur_l = ++bone_index;
855  bones.protibia_l = ++bone_index;
856  bones.protarsomere1_l = ++bone_index;
857  bones.procoxa_r = ++bone_index;
858  bones.profemur_r = ++bone_index;
859  bones.protibia_r = ++bone_index;
860  bones.protarsomere1_r = ++bone_index;
861  bones.mesocoxa_l = ++bone_index;
862  bones.mesofemur_l = ++bone_index;
863  bones.mesotibia_l = ++bone_index;
864  bones.mesotarsomere1_l = ++bone_index;
865  bones.mesocoxa_r = ++bone_index;
866  bones.mesofemur_r = ++bone_index;
867  bones.mesotibia_r = ++bone_index;
868  bones.mesotarsomere1_r = ++bone_index;
869  bones.metacoxa_l = ++bone_index;
870  bones.metafemur_l = ++bone_index;
871  bones.metatibia_l = ++bone_index;
872  bones.metatarsomere1_l = ++bone_index;
873  bones.metacoxa_r = ++bone_index;
874  bones.metafemur_r = ++bone_index;
875  bones.metatibia_r = ++bone_index;
876  bones.metatarsomere1_r = ++bone_index;
877  bones.head = ++bone_index;
878  bones.mandible_l = ++bone_index;
879  bones.mandible_r = ++bone_index;
880  bones.antennomere1_l = ++bone_index;
881  bones.antennomere2_l = ++bone_index;
882  bones.antennomere1_r = ++bone_index;
883  bones.antennomere2_r = ++bone_index;
884 
885  if (phenome.waist->present)
886  {
887  bones.petiole = ++bone_index;
888 
889  if (phenome.waist->postpetiole_present)
890  {
891  bones.postpetiole = ++bone_index;
892  }
893  }
894 
895  bones.gaster = ++bone_index;
896 
897  if (phenome.sting->present)
898  {
899  bones.sting = ++bone_index;
900  }
901 
902  if (phenome.wings->present)
903  {
904  bones.forewing_l = ++bone_index;
905  bones.forewing_r = ++bone_index;
906  bones.hindwing_l = ++bone_index;
907  bones.hindwing_r = ++bone_index;
908  }
909 
910  // Allocate bones
912 
913  // Assign bone parents
939  skeleton.set_bone_parent(bones.head, bones.mesosoma);
940  skeleton.set_bone_parent(bones.mandible_l, bones.head);
941  skeleton.set_bone_parent(bones.mandible_r, bones.head);
946 
947  if (phenome.waist->present)
948  {
949  skeleton.set_bone_parent(*bones.petiole, bones.mesosoma);
950 
951  if (phenome.waist->postpetiole_present)
952  {
955  }
956  else
957  {
958  skeleton.set_bone_parent(bones.gaster, *bones.petiole);
959  }
960  }
961  else
962  {
963  skeleton.set_bone_parent(bones.gaster, bones.mesosoma);
964  }
965 
966  if (phenome.sting->present)
967  {
968  skeleton.set_bone_parent(*bones.sting, bones.gaster);
969  }
970 
971  if (phenome.wings->present)
972  {
977  }
978 
979  // Assign bone names
980  skeleton.set_bone_name(bones.mesosoma, "mesosoma");
981  skeleton.set_bone_name(bones.procoxa_l, "procoxa_l");
982  skeleton.set_bone_name(bones.profemur_l, "profemur_l");
983  skeleton.set_bone_name(bones.protibia_l, "protibia_l");
984  skeleton.set_bone_name(bones.protarsomere1_l, "protarsomere1_l");
985  skeleton.set_bone_name(bones.procoxa_r, "procoxa_r");
986  skeleton.set_bone_name(bones.profemur_r, "profemur_r");
987  skeleton.set_bone_name(bones.protibia_r, "protibia_r");
988  skeleton.set_bone_name(bones.protarsomere1_r, "protarsomere1_r");
989  skeleton.set_bone_name(bones.mesocoxa_l, "mesocoxa_l");
990  skeleton.set_bone_name(bones.mesofemur_l, "mesofemur_l");
991  skeleton.set_bone_name(bones.mesotibia_l, "mesotibia_l");
992  skeleton.set_bone_name(bones.mesotarsomere1_l, "mesotarsomere1_l");
993  skeleton.set_bone_name(bones.mesocoxa_r, "mesocoxa_r");
994  skeleton.set_bone_name(bones.mesofemur_r, "mesofemur_r");
995  skeleton.set_bone_name(bones.mesotibia_r, "mesotibia_r");
996  skeleton.set_bone_name(bones.mesotarsomere1_r, "mesotarsomere1_r");
997  skeleton.set_bone_name(bones.metacoxa_l, "metacoxa_l");
998  skeleton.set_bone_name(bones.metafemur_l, "metafemur_l");
999  skeleton.set_bone_name(bones.metatibia_l, "metatibia_l");
1000  skeleton.set_bone_name(bones.metatarsomere1_l, "metatarsomere1_l");
1001  skeleton.set_bone_name(bones.metacoxa_r, "metacoxa_r");
1002  skeleton.set_bone_name(bones.metafemur_r, "metafemur_r");
1003  skeleton.set_bone_name(bones.metatibia_r, "metatibia_r");
1004  skeleton.set_bone_name(bones.metatarsomere1_r, "metatarsomere1_r");
1005  skeleton.set_bone_name(bones.head, "head");
1006  skeleton.set_bone_name(bones.mandible_l, "mandible_l");
1007  skeleton.set_bone_name(bones.mandible_r, "mandible_r");
1008  skeleton.set_bone_name(bones.antennomere1_l, "antennomere1_l");
1009  skeleton.set_bone_name(bones.antennomere2_l, "antennomere2_l");
1010  skeleton.set_bone_name(bones.antennomere1_r, "antennomere1_r");
1011  skeleton.set_bone_name(bones.antennomere2_r, "antennomere2_r");
1012 
1013  if (phenome.waist->present)
1014  {
1015  skeleton.set_bone_name(*bones.petiole, "petiole");
1016 
1017  if (phenome.waist->postpetiole_present)
1018  {
1019  skeleton.set_bone_name(*bones.postpetiole, "postpetiole");
1020  }
1021  }
1022 
1023  skeleton.set_bone_name(bones.gaster, "gaster");
1024 
1025  if (phenome.sting->present)
1026  {
1027  skeleton.set_bone_name(*bones.sting, "sting");
1028  }
1029 
1030  if (phenome.wings->present)
1031  {
1032  skeleton.set_bone_name(*bones.forewing_l, "forewing_l");
1033  skeleton.set_bone_name(*bones.forewing_r, "forewing_r");
1034  skeleton.set_bone_name(*bones.hindwing_l, "hindwing_l");
1035  skeleton.set_bone_name(*bones.hindwing_r, "hindwing_r");
1036  }
1037 
1038  // Generate poses
1039  generate_ant_rest_pose(skeleton, bones, phenome);
1040  generate_ant_midstance_pose(skeleton, bones);
1041  generate_ant_midswing_pose(skeleton, bones);
1042  generate_ant_liftoff_pose(skeleton, bones);
1043  generate_ant_touchdown_pose(skeleton, bones);
1044  generate_ant_pupa_pose(skeleton, bones);
1045 }
void generate_ant_skeleton(skeleton &skeleton, ant_bone_set &bones, const ant_phenome &phenome)
Generates a skeleton for an ant model.
std::uint16_t bone_index_type
Bone index type.
Definition: bone.hpp:31
Base class for skeleton poses.
Definition: pose.hpp:32
void set_relative_transform(bone_index_type index, const bone_transform_type &transform)
Sets the relative transform describing a bone pose.
Definition: pose.hpp:65
void update()
Updates the pose after one or more relative transforms have been changed.
Definition: pose.cpp:31
const bone_transform_type & get_relative_transform(bone_index_type index) const
Returns the relative transform describing a bone pose.
Definition: pose.hpp:116
Skeleton rest pose.
Definition: rest-pose.hpp:29
Skeletal animation skeleton.
Definition: skeleton.hpp:35
void set_bone_transform(bone_index_type index, const bone_transform_type &transform)
Sets the transform of a bone, relative to its parent bone.
Definition: skeleton.hpp:130
std::optional< bone_index_type > get_bone_index(hash::fnv1a32_t name) const
Finds the index of a bone from the bone's name.
Definition: skeleton.cpp:113
bone_index_type add_bones(std::size_t bone_count)
Add one or more bones to the skeleton.
Definition: skeleton.cpp:37
void update_rest_pose()
Updates the rest pose of the skeleton.
Definition: skeleton.cpp:32
void set_bone_parent(bone_index_type child_index, bone_index_type parent_index)
Sets the parent of a bone.
Definition: skeleton.cpp:88
void set_bone_name(bone_index_type index, hash::fnv1a32_t name)
Sets the name of a bone.
Definition: skeleton.cpp:98
animation_pose & add_pose(hash::fnv1a32_t name)
Adds a pose to the skeleton.
Definition: skeleton.cpp:63
const rest_pose & get_rest_pose() const noexcept
Returns the skeleton's rest pose.
Definition: skeleton.hpp:187
quat< T > euler_xyz_to_quat(const vec3< T > &angles)
Constructs a quaternion from Euler angles.
quaternion< T > angle_axis(T angle, const vec3< T > &axis)
Creates a rotation from an angle and axis.
Definition: quaternion.hpp:685
constexpr T radians(T degrees) noexcept
Converts an angle given in degrees to radians.
Definition: angles.hpp:48
std::shared_ptr< render::model > model
3D model of the antennae.
Set of bone indices for all possible bones in an ant skeleotn.
bone_index_type head
bone_index_type mandible_r
bone_index_type antennomere2_l
bone_index_type procoxa_r
bone_index_type protarsomere1_l
bone_index_type mesosoma
bone_index_type mesotarsomere1_l
std::optional< bone_index_type > hindwing_l
std::optional< bone_index_type > postpetiole
bone_index_type mesofemur_l
bone_index_type antennomere1_l
bone_index_type protibia_r
bone_index_type profemur_l
bone_index_type profemur_r
bone_index_type metatibia_r
bone_index_type mesotarsomere1_r
bone_index_type mesocoxa_l
std::optional< bone_index_type > forewing_l
bone_index_type mesotibia_r
bone_index_type mandible_l
std::optional< bone_index_type > sting
bone_index_type metafemur_l
std::optional< bone_index_type > forewing_r
bone_index_type mesocoxa_r
bone_index_type protarsomere1_r
bone_index_type mesofemur_r
bone_index_type metatibia_l
std::optional< bone_index_type > petiole
bone_index_type gaster
bone_index_type metacoxa_r
bone_index_type metatarsomere1_l
bone_index_type protibia_l
std::optional< bone_index_type > hindwing_r
bone_index_type antennomere2_r
bone_index_type metacoxa_l
bone_index_type procoxa_l
bone_index_type mesotibia_l
bone_index_type antennomere1_r
bone_index_type metafemur_r
bone_index_type metatarsomere1_r
std::shared_ptr< render::model > model
3D model of the gaster.
std::shared_ptr< render::model > model
3D model of the head.
std::shared_ptr< render::model > model
3D model of the legs.
std::shared_ptr< render::model > model
3D model of the mandibles.
std::shared_ptr< render::model > model
3D model of the mesosoma.
Complete set of ant phenes.
Definition: ant-phenome.hpp:52
const ant_sting_phene * sting
Definition: ant-phenome.hpp:83
const ant_mandibles_phene * mandibles
Definition: ant-phenome.hpp:76
const ant_legs_phene * legs
Definition: ant-phenome.hpp:75
const ant_antennae_phene * antennae
Definition: ant-phenome.hpp:64
const ant_wings_phene * wings
Definition: ant-phenome.hpp:85
const ant_waist_phene * waist
Definition: ant-phenome.hpp:84
const ant_head_phene * head
Definition: ant-phenome.hpp:73
const ant_gaster_phene * gaster
Definition: ant-phenome.hpp:72
const ant_mesosoma_phene * mesosoma
Definition: ant-phenome.hpp:77
bool present
Indicates whether a sting present or not.
std::shared_ptr< render::model > model
3D model of the sting.
bool postpetiole_present
Postpetiole presence.
std::shared_ptr< render::model > model
3D model of the waist.
std::shared_ptr< render::model > model
3D model of the wings.
bool present
Wings presence.
32-bit FNV-1a hash value.
Definition: fnv1a.hpp:117
static constexpr transform identity() noexcept
Returns an identity transform.
Definition: transform.hpp:107
n-dimensional vector.
Definition: vector.hpp:44