From f8ae34d37e88fe776ac6634e74c20738990ac264 Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Sun, 26 Mar 2023 18:41:43 +0800 Subject: [PATCH] Make pose generation part of morphogenesis function --- CMakeLists.txt | 1 - src/engine/geom/closest-point.hpp | 40 +- src/engine/physics/ik/ik-solver.hpp | 38 ++ src/game/ant/ant-bone-set.hpp | 73 +++ src/game/ant/ant-morphogenesis.cpp | 606 ++++------------------- src/game/ant/ant-skeleton.cpp | 528 ++++++++++++++++++++ src/game/ant/ant-skeleton.hpp | 87 ++++ src/game/states/nest-selection-state.cpp | 241 +-------- src/game/states/nest-selection-state.hpp | 2 + 9 files changed, 836 insertions(+), 780 deletions(-) create mode 100644 src/engine/physics/ik/ik-solver.hpp create mode 100644 src/game/ant/ant-bone-set.hpp create mode 100644 src/game/ant/ant-skeleton.cpp create mode 100644 src/game/ant/ant-skeleton.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 73e1a79..21ca183 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,5 @@ cmake_minimum_required(VERSION 3.25) - option(APPLICATION_NAME "Application name" "Antkeeper") option(APPLICATION_VERSION "Application version string" "0.0.0") option(APPLICATION_AUTHOR "Application author" "C. J. Howard") diff --git a/src/engine/geom/closest-point.hpp b/src/engine/geom/closest-point.hpp index 324d9a3..5aaf049 100644 --- a/src/engine/geom/closest-point.hpp +++ b/src/engine/geom/closest-point.hpp @@ -45,7 +45,7 @@ namespace geom { * @return Closest point on ray a to point b. */ template -[[nodiscard]] point closest_point(const ray& a, const point& b) noexcept +[[nodiscard]] constexpr point closest_point(const ray& a, const point& b) noexcept { return a.extrapolate(std::max(T{0}, math::dot(b - a.origin, a.direction))); } @@ -62,7 +62,7 @@ template * @return Closest point on line segment ab to point c. */ template -[[nodiscard]] point closest_point(const line_segment& ab, const point& c) noexcept +[[nodiscard]] constexpr point closest_point(const line_segment& ab, const point& c) noexcept { const auto direction_ab = ab.b - ab.a; @@ -96,9 +96,8 @@ template * * @return Tuple containing the closest point on segment ab to segment cd, followed by the closest point on segment cd to segment ab. */ -/// @{ template -[[nodiscard]] std::tuple, point> closest_point(const line_segment& ab, const line_segment& cd) noexcept +[[nodiscard]] constexpr std::tuple, point> closest_point(const line_segment& ab, const line_segment& cd) noexcept { const auto direction_ab = ab.b - ab.a; const auto direction_cd = cd.b - cd.a; @@ -185,13 +184,13 @@ template * @return Closest point on hyperplane a to point b. */ template -[[nodiscard]] point closest_point(const hyperplane& a, const point& b) noexcept +[[nodiscard]] constexpr point closest_point(const hyperplane& a, const point& b) noexcept { return b - a.normal * (math::dot(a.normal, b) + a.constant); } /** - * Calculates the closest point on a hypersphere to a point. + * Calculates the closest point on or in a hypersphere to a point. * * @tparam T Real type. * @tparam N Number of dimensions. @@ -199,18 +198,18 @@ template * @param a Hypersphere a. * @param b Point b. * - * @return Closest point on hypersphere a to point b. + * @return Closest point on or in hypersphere a to point b. */ template [[nodiscard]] point closest_point(const hypersphere& a, const point& b) { const auto ab = b - a.center; const auto d = math::sqr_length(ab); - return a.center + ab * (d ? a.radius / std::sqrt(d) : d); + return d > a.radius * a.radius ? a.center + ab * (a.radius / std::sqrt(d)) : b; } /** - * Calculates the closest point on a hypercapsule to a point. + * Calculates the closest point on or in a hypercapsule to a point. * * @tparam T Real type. * @tparam N Number of dimensions. @@ -218,7 +217,7 @@ template * @param a Hypercapsule a. * @param b Point b. * - * @return Closest point on hypercapsule a to point b. + * @return Closest point on or in hypercapsule a to point b. */ template [[nodiscard]] point closest_point(const hypercapsule& a, const point& b) @@ -226,11 +225,11 @@ template const auto c = closest_point(a.segment, b); const auto cb = b - c; const auto d = math::sqr_length(cb); - return c + cb * (d ? a.radius / std::sqrt(d) : d); + return d > a.radius * a.radius ? c + cb * (a.radius / std::sqrt(d)) : b; } /** - * Calculates the closest point on a hyperrectangle to a point. + * Calculates the closest point on or in a hyperrectangle to a point. * * @tparam T Real type. * @tparam N Number of dimensions. @@ -238,23 +237,12 @@ template * @param a Hyperrectangle a. * @param b Point b. * - * @return Closest point on hyperrectangle a to point b. + * @return Closest point on or in hyperrectangle a to point b. */ template -[[nodiscard]] point closest_point(const hyperrectangle& a, const point& b) noexcept +[[nodiscard]] constexpr point closest_point(const hyperrectangle& a, const point& b) noexcept { - const auto c = a.center(); - const auto p = b - c; - const auto d = math::abs(p) - a.extents(); - const auto m = std::min(math::max(d), T{0}); - - point r; - for (std::size_t i = 0; i < N; ++i) - { - r[i] = c[i] + std::copysign(d[i] >= m ? d[i] : T{0}, p[i]); - } - - return r; + return math::min(math::max(b, a.min), a.max); } } // namespace geom diff --git a/src/engine/physics/ik/ik-solver.hpp b/src/engine/physics/ik/ik-solver.hpp new file mode 100644 index 0000000..7cf12ab --- /dev/null +++ b/src/engine/physics/ik/ik-solver.hpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2023 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_PHYSICS_IK_SOLVER_HPP +#define ANTKEEPER_PHYSICS_IK_SOLVER_HPP + +#include + +namespace physics { + +/** + * + */ +class ik_solver +{ +public: + +}; + +} // namespace physics + +#endif // ANTKEEPER_PHYSICS_IK_SOLVER_HPP diff --git a/src/game/ant/ant-bone-set.hpp b/src/game/ant/ant-bone-set.hpp new file mode 100644 index 0000000..bc9636d --- /dev/null +++ b/src/game/ant/ant-bone-set.hpp @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2023 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_GAME_ANT_BONE_SET_HPP +#define ANTKEEPER_GAME_ANT_BONE_SET_HPP + +#include +#include + +/** + * Set of bone indices for all possible bones in an ant skeleotn. + */ +struct ant_bone_set +{ + std::optional mesosoma; + std::optional procoxa_l; + std::optional profemur_l; + std::optional protibia_l; + std::optional protarsus_l; + std::optional procoxa_r; + std::optional profemur_r; + std::optional protibia_r; + std::optional protarsus_r; + std::optional mesocoxa_l; + std::optional mesofemur_l; + std::optional mesotibia_l; + std::optional mesotarsus_l; + std::optional mesocoxa_r; + std::optional mesofemur_r; + std::optional mesotibia_r; + std::optional mesotarsus_r; + std::optional metacoxa_l; + std::optional metafemur_l; + std::optional metatibia_l; + std::optional metatarsus_l; + std::optional metacoxa_r; + std::optional metafemur_r; + std::optional metatibia_r; + std::optional metatarsus_r; + std::optional head; + std::optional mandible_l; + std::optional mandible_r; + std::optional antennomere1_l; + std::optional antennomere2_l; + std::optional antennomere1_r; + std::optional antennomere2_r; + std::optional petiole; + std::optional postpetiole; + std::optional gaster; + std::optional sting; + std::optional forewing_l; + std::optional forewing_r; + std::optional hindwing_l; + std::optional hindwing_r; +}; + +#endif // ANTKEEPER_GAME_ANT_BONE_SET_HPP diff --git a/src/game/ant/ant-morphogenesis.cpp b/src/game/ant/ant-morphogenesis.cpp index 69adebe..7f0b1f9 100644 --- a/src/game/ant/ant-morphogenesis.cpp +++ b/src/game/ant/ant-morphogenesis.cpp @@ -18,6 +18,8 @@ */ #include "game/ant/ant-morphogenesis.hpp" +#include "game/ant/ant-bone-set.hpp" +#include "game/ant/ant-skeleton.hpp" #include #include #include @@ -29,51 +31,6 @@ namespace { -/// Set of pointers to all possible ant skeleton bones. -struct ant_bone_set -{ - std::optional mesosoma; - std::optional procoxa_l; - std::optional profemur_l; - std::optional protibia_l; - std::optional protarsus_l; - std::optional procoxa_r; - std::optional profemur_r; - std::optional protibia_r; - std::optional protarsus_r; - std::optional mesocoxa_l; - std::optional mesofemur_l; - std::optional mesotibia_l; - std::optional mesotarsus_l; - std::optional mesocoxa_r; - std::optional mesofemur_r; - std::optional mesotibia_r; - std::optional mesotarsus_r; - std::optional metacoxa_l; - std::optional metafemur_l; - std::optional metatibia_l; - std::optional metatarsus_l; - std::optional metacoxa_r; - std::optional metafemur_r; - std::optional metatibia_r; - std::optional metatarsus_r; - std::optional head; - std::optional mandible_l; - std::optional mandible_r; - std::optional antennomere1_l; - std::optional antennomere2_l; - std::optional antennomere1_r; - std::optional antennomere2_r; - std::optional petiole; - std::optional postpetiole; - std::optional gaster; - std::optional sting; - std::optional forewing_l; - std::optional forewing_r; - std::optional hindwing_l; - std::optional hindwing_r; -}; - /** * Reskins model vertices. * @@ -104,7 +61,7 @@ void reskin_vertices for (std::size_t i = 0; i < vertex_count; ++i) { // Get bone index of current vertex - std::uint32_t& bone_index = reinterpret_cast(*(bone_index_data + bone_index_attribute.stride * i)); + std::uint16_t& bone_index = reinterpret_cast(*(bone_index_data + bone_index_attribute.stride * i)); // Ignore vertices with unmapped bone indices auto entry = reskin_map.find(static_cast(bone_index)); @@ -116,17 +73,60 @@ void reskin_vertices const auto& [new_bone_index, transform] = entry->second; // Update bone index - bone_index = static_cast(new_bone_index); + bone_index = static_cast(new_bone_index); // Get vertex attributes - float3& position = reinterpret_cast(*(position_data + position_attribute.stride * i)); - float3& normal = reinterpret_cast(*(normal_data + normal_attribute.stride * i)); - float3& tangent = reinterpret_cast(*(tangent_data + tangent_attribute.stride * i)); + float* px = reinterpret_cast(position_data + position_attribute.stride * i); + float* py = px + 1; + float* pz = py + 1; + float* nx = reinterpret_cast(normal_data + normal_attribute.stride * i); + float* ny = nx + 1; + float* nz = ny + 1; + float* tx = reinterpret_cast(tangent_data + tangent_attribute.stride * i); + float* ty = tx + 1; + float* tz = ty + 1; // Transform vertex attributes - position = (*transform) * position; - normal = math::normalize(transform->rotation * normal); - tangent = math::normalize(transform->rotation * tangent); + const float3 position = (*transform) * float3{*px, *py, *pz}; + const float3 normal = math::normalize(transform->rotation * float3{*nx, *ny, *nz}); + const float3 tangent = math::normalize(transform->rotation * float3{*tx, *ty, *tz}); + + // Update vertex attributes + *px = position.x(); + *py = position.y(); + *pz = position.z(); + *nx = normal.x(); + *ny = normal.y(); + *nz = normal.z(); + *tx = tangent.x(); + *ty = tangent.y(); + *tz = tangent.z(); + } +} + +/** + * Tags the vertices of a body part by storing a value in the fourth bone index. + * + * @param vertex_data Vertex buffer data. + * @param bone_index_attribute Vertex bone index attribute. + * @param reskin_map Map of old bone index to a tuple containing the new bone index and a vertex transformation. + */ +void tag_vertices +( + std::span vertex_data, + const gl::vertex_attribute& bone_index_attribute, + std::uint16_t vertex_tag +) +{ + std::byte* bone_index_data = vertex_data.data() + bone_index_attribute.offset; + + for (std::size_t i = 0; i < vertex_data.size(); ++i) + { + // Get bone indices of current vertex + std::uint16_t* bone_indices = reinterpret_cast(bone_index_data + bone_index_attribute.stride * i); + + // Tag fourth bone index + bone_indices[3] = vertex_tag; } } @@ -156,8 +156,11 @@ void reskin_vertices for (std::size_t i = 0; i < vertex_count; ++i) { - const float3& position = reinterpret_cast(*(position_data + position_attribute.stride * i)); - bounds.extend(position); + const float* px = reinterpret_cast(position_data + position_attribute.stride * i); + const float* py = px + 1; + const float* pz = py + 1; + + bounds.extend(float3{*px, *py, *pz}); } return bounds; @@ -189,391 +192,6 @@ void reskin_vertices return exoskeleton_material; } -/** - * Calculates the number of bones in an ant model skeleton. - * - * @return Ant model skeleton bone count. - * - * Required bones: - * - * * antennomere1_l - * * antennomere1_r - * * antennomere2_l - * * antennomere2_r - * * gaster - * * head - * * mandible_l - * * mandible_r - * * mesocoxa_l - * * mesocoxa_r - * * mesofemur_l - * * mesofemur_r - * * mesosoma - * * mesotarsus_l - * * mesotarsus_r - * * mesotibia_l - * * mesotibia_r - * * metacoxa_l - * * metacoxa_r - * * metafemur_l - * * metafemur_r - * * metatarsus_l - * * metatarsus_r - * * metatibia_l - * * metatibia_r - * * procoxa_l - * * procoxa_r - * * profemur_l - * * profemur_r - * * protarsus_l - * * protarsus_r - * * protibia_l - * * protibia_r - * - * Optional bones: - * - * * forewing_l - * * forewing_r - * * hindwing_l - * * hindwing_r - * * petiole - * * postpetiole - * * sting - * - */ -[[nodiscard]] std::size_t count_ant_skeleton_bones(const ant_phenome& phenome) noexcept -{ - constexpr std::size_t minimum_bone_count = 33; - - std::size_t bone_count = minimum_bone_count; - - if (phenome.waist->petiole_present) - { - bone_count += 1; - } - if (phenome.waist->postpetiole_present) - { - bone_count += 1; - } - if (phenome.sting->present) - { - bone_count += 1; - } - if (phenome.wings->present) - { - bone_count += 4; - } - - return bone_count; -} - -/** - * Builds an ant model skeleton. - * - * @param[in] phenome Ant phenome. - * @param[out] skeleton Ant model skeleton. - * @param[out] bones Set of ant model skeleton bones. - */ -void build_ant_skeleton(const ant_phenome& phenome, ::skeleton& skeleton, ant_bone_set& bones) -{ - // Allocate bones - skeleton.add_bones(count_ant_skeleton_bones(phenome)); - - // Construct ant bone set - bone_index_type bone_index = 0; - bones.mesosoma = bone_index; - bones.procoxa_l = ++bone_index; - bones.profemur_l = ++bone_index; - bones.protibia_l = ++bone_index; - bones.protarsus_l = ++bone_index; - bones.procoxa_r = ++bone_index; - bones.profemur_r = ++bone_index; - bones.protibia_r = ++bone_index; - bones.protarsus_r = ++bone_index; - bones.mesocoxa_l = ++bone_index; - bones.mesofemur_l = ++bone_index; - bones.mesotibia_l = ++bone_index; - bones.mesotarsus_l = ++bone_index; - bones.mesocoxa_r = ++bone_index; - bones.mesofemur_r = ++bone_index; - bones.mesotibia_r = ++bone_index; - bones.mesotarsus_r = ++bone_index; - bones.metacoxa_l = ++bone_index; - bones.metafemur_l = ++bone_index; - bones.metatibia_l = ++bone_index; - bones.metatarsus_l = ++bone_index; - bones.metacoxa_r = ++bone_index; - bones.metafemur_r = ++bone_index; - bones.metatibia_r = ++bone_index; - bones.metatarsus_r = ++bone_index; - bones.head = ++bone_index; - bones.mandible_l = ++bone_index; - bones.mandible_r = ++bone_index; - bones.antennomere1_l = ++bone_index; - bones.antennomere2_l = ++bone_index; - bones.antennomere1_r = ++bone_index; - bones.antennomere2_r = ++bone_index; - - if (phenome.waist->petiole_present) - { - bones.petiole = ++bone_index; - } - - if (phenome.waist->postpetiole_present) - { - bones.postpetiole = ++bone_index; - } - - bones.gaster = ++bone_index; - - if (phenome.sting->present) - { - bones.sting = ++bone_index; - } - - if (phenome.wings->present) - { - bones.forewing_l = ++bone_index; - bones.forewing_r = ++bone_index; - bones.hindwing_l = ++bone_index; - bones.hindwing_r = ++bone_index; - } - - // Assign bone parents - skeleton.set_bone_parent(*bones.mesosoma, *bones.mesosoma); - skeleton.set_bone_parent(*bones.procoxa_l, *bones.mesosoma); - skeleton.set_bone_parent(*bones.profemur_l, *bones.procoxa_l); - skeleton.set_bone_parent(*bones.protibia_l, *bones.profemur_l); - skeleton.set_bone_parent(*bones.protarsus_l, *bones.protibia_l); - skeleton.set_bone_parent(*bones.procoxa_r, *bones.mesosoma); - skeleton.set_bone_parent(*bones.profemur_r, *bones.procoxa_r); - skeleton.set_bone_parent(*bones.protibia_r, *bones.profemur_r); - skeleton.set_bone_parent(*bones.protarsus_r, *bones.protibia_r); - skeleton.set_bone_parent(*bones.mesocoxa_l, *bones.mesosoma); - skeleton.set_bone_parent(*bones.mesofemur_l, *bones.mesocoxa_l); - skeleton.set_bone_parent(*bones.mesotibia_l, *bones.mesofemur_l); - skeleton.set_bone_parent(*bones.mesotarsus_l, *bones.mesotibia_l); - skeleton.set_bone_parent(*bones.mesocoxa_r, *bones.mesosoma); - skeleton.set_bone_parent(*bones.mesofemur_r, *bones.mesocoxa_r); - skeleton.set_bone_parent(*bones.mesotibia_r, *bones.mesofemur_r); - skeleton.set_bone_parent(*bones.mesotarsus_r, *bones.mesotibia_r); - skeleton.set_bone_parent(*bones.metacoxa_l, *bones.mesosoma); - skeleton.set_bone_parent(*bones.metafemur_l, *bones.metacoxa_l); - skeleton.set_bone_parent(*bones.metatibia_l, *bones.metafemur_l); - skeleton.set_bone_parent(*bones.metatarsus_l, *bones.metatibia_l); - skeleton.set_bone_parent(*bones.metacoxa_r, *bones.mesosoma); - skeleton.set_bone_parent(*bones.metafemur_r, *bones.metacoxa_r); - skeleton.set_bone_parent(*bones.metatibia_r, *bones.metafemur_r); - skeleton.set_bone_parent(*bones.metatarsus_r, *bones.metatibia_r); - skeleton.set_bone_parent(*bones.head, *bones.mesosoma); - skeleton.set_bone_parent(*bones.mandible_l, *bones.head); - skeleton.set_bone_parent(*bones.mandible_r, *bones.head); - skeleton.set_bone_parent(*bones.antennomere1_l, *bones.head); - skeleton.set_bone_parent(*bones.antennomere2_l, *bones.antennomere1_l); - skeleton.set_bone_parent(*bones.antennomere1_r, *bones.head); - skeleton.set_bone_parent(*bones.antennomere2_r, *bones.antennomere1_r); - - if (bones.petiole) - { - skeleton.set_bone_parent(*bones.petiole, *bones.mesosoma); - } - if (bones.postpetiole) - { - if (bones.petiole) - { - skeleton.set_bone_parent(*bones.postpetiole, *bones.petiole); - } - else - { - skeleton.set_bone_parent(*bones.postpetiole, *bones.mesosoma); - } - } - - if (bones.postpetiole) - { - skeleton.set_bone_parent(*bones.gaster, *bones.postpetiole); - } - else - { - if (bones.petiole) - { - skeleton.set_bone_parent(*bones.gaster, *bones.petiole); - } - else - { - skeleton.set_bone_parent(*bones.gaster, *bones.mesosoma); - } - } - - if (bones.sting) - { - skeleton.set_bone_parent(*bones.sting, *bones.gaster); - } - - if (bones.forewing_l) - { - skeleton.set_bone_parent(*bones.forewing_l, *bones.mesosoma); - skeleton.set_bone_parent(*bones.forewing_r, *bones.mesosoma); - skeleton.set_bone_parent(*bones.hindwing_l, *bones.mesosoma); - skeleton.set_bone_parent(*bones.hindwing_r, *bones.mesosoma); - } - - // Map bone names to bones - skeleton.set_bone_name(*bones.mesosoma, "mesosoma"); - skeleton.set_bone_name(*bones.procoxa_l, "procoxa_l"); - skeleton.set_bone_name(*bones.profemur_l, "profemur_l"); - skeleton.set_bone_name(*bones.protibia_l, "protibia_l"); - skeleton.set_bone_name(*bones.protarsus_l, "protarsus_l"); - skeleton.set_bone_name(*bones.procoxa_r, "procoxa_r"); - skeleton.set_bone_name(*bones.profemur_r, "profemur_r"); - skeleton.set_bone_name(*bones.protibia_r, "protibia_r"); - skeleton.set_bone_name(*bones.protarsus_r, "protarsus_r"); - skeleton.set_bone_name(*bones.mesocoxa_l, "mesocoxa_l"); - skeleton.set_bone_name(*bones.mesofemur_l, "mesofemur_l"); - skeleton.set_bone_name(*bones.mesotibia_l, "mesotibia_l"); - skeleton.set_bone_name(*bones.mesotarsus_l, "mesotarsus_l"); - skeleton.set_bone_name(*bones.mesocoxa_r, "mesocoxa_r"); - skeleton.set_bone_name(*bones.mesofemur_r, "mesofemur_r"); - skeleton.set_bone_name(*bones.mesotibia_r, "mesotibia_r"); - skeleton.set_bone_name(*bones.mesotarsus_r, "mesotarsus_r"); - skeleton.set_bone_name(*bones.metacoxa_l, "metacoxa_l"); - skeleton.set_bone_name(*bones.metafemur_l, "metafemur_l"); - skeleton.set_bone_name(*bones.metatibia_l, "metatibia_l"); - skeleton.set_bone_name(*bones.metatarsus_l, "metatarsus_l"); - skeleton.set_bone_name(*bones.metacoxa_r, "metacoxa_r"); - skeleton.set_bone_name(*bones.metafemur_r, "metafemur_r"); - skeleton.set_bone_name(*bones.metatibia_r, "metatibia_r"); - skeleton.set_bone_name(*bones.metatarsus_r, "metatarsus_r"); - skeleton.set_bone_name(*bones.head, "head"); - skeleton.set_bone_name(*bones.mandible_l, "mandible_l"); - skeleton.set_bone_name(*bones.mandible_r, "mandible_r"); - skeleton.set_bone_name(*bones.antennomere1_l, "antennomere1_l"); - skeleton.set_bone_name(*bones.antennomere2_l, "antennomere2_l"); - skeleton.set_bone_name(*bones.antennomere1_r, "antennomere1_r"); - skeleton.set_bone_name(*bones.antennomere2_r, "antennomere2_r"); - if (bones.petiole) - { - skeleton.set_bone_name(*bones.petiole, "petiole"); - } - if (bones.postpetiole) - { - skeleton.set_bone_name(*bones.postpetiole, "postpetiole"); - } - skeleton.set_bone_name(*bones.gaster, "gaster"); - if (bones.sting) - { - skeleton.set_bone_name(*bones.sting, "sting"); - } - if (bones.forewing_l) - { - skeleton.set_bone_name(*bones.forewing_l, "forewing_l"); - skeleton.set_bone_name(*bones.forewing_r, "forewing_r"); - skeleton.set_bone_name(*bones.hindwing_l, "hindwing_l"); - skeleton.set_bone_name(*bones.hindwing_r, "hindwing_r"); - } -} - -/** - * Builds the bind pose of an ant skeleton. - * - * @param[in] phenome Ant phenome. - * @param[in] bones Set of ant skeleton bones. - * @param[in,out] skeleton Ant skeleton. - */ -void build_ant_rest_pose(const ant_phenome& phenome, const ant_bone_set& bones, ::skeleton& skeleton) -{ - // Get body part skeletons - const ::skeleton& mesosoma_skeleton = phenome.mesosoma->model->get_skeleton(); - const ::skeleton& legs_skeleton = phenome.legs->model->get_skeleton(); - const ::skeleton& head_skeleton = phenome.head->model->get_skeleton(); - const ::skeleton& mandibles_skeleton = phenome.mandibles->model->get_skeleton(); - const ::skeleton& antennae_skeleton = phenome.antennae->model->get_skeleton(); - const ::skeleton& waist_skeleton = phenome.waist->model->get_skeleton(); - const ::skeleton& gaster_skeleton = phenome.gaster->model->get_skeleton(); - const ::skeleton* sting_skeleton = (phenome.sting->present) ? &phenome.sting->model->get_skeleton() : nullptr; - const ::skeleton* forewings_skeleton = (phenome.wings->present) ? &phenome.wings->forewings_model->get_skeleton() : nullptr; - const ::skeleton* hindwings_skeleton = (phenome.wings->present) ? &phenome.wings->hindwings_model->get_skeleton() : nullptr; - - auto get_bone_transform = [](const ::skeleton& skeleton, hash::fnv1a32_t bone_name) - { - return skeleton.get_rest_pose().get_relative_transform(*skeleton.get_bone_index(bone_name)); - }; - - const auto& mesosoma_transform = get_bone_transform(mesosoma_skeleton, "mesosoma"); - const auto& head_socket_transform = get_bone_transform(mesosoma_skeleton, "head"); - const auto& head_transform = get_bone_transform(head_skeleton, "head"); - - const auto inverse_mesosoma_transform = math::inverse(mesosoma_transform); - - // Build skeleton rest pose - skeleton.set_bone_transform(*bones.mesosoma, mesosoma_transform); - - skeleton.set_bone_transform(*bones.procoxa_l, inverse_mesosoma_transform * get_bone_transform(legs_skeleton, "procoxa_l")); - skeleton.set_bone_transform(*bones.profemur_l, get_bone_transform(legs_skeleton, "profemur_l")); - skeleton.set_bone_transform(*bones.protibia_l, get_bone_transform(legs_skeleton, "protibia_l")); - skeleton.set_bone_transform(*bones.protarsus_l, get_bone_transform(legs_skeleton, "protarsus1_l")); - - skeleton.set_bone_transform(*bones.procoxa_r, inverse_mesosoma_transform * get_bone_transform(legs_skeleton, "procoxa_r")); - skeleton.set_bone_transform(*bones.profemur_r, get_bone_transform(legs_skeleton, "profemur_r")); - skeleton.set_bone_transform(*bones.protibia_r, get_bone_transform(legs_skeleton, "protibia_r")); - skeleton.set_bone_transform(*bones.protarsus_r, get_bone_transform(legs_skeleton, "protarsus1_r")); - - skeleton.set_bone_transform(*bones.mesocoxa_l, inverse_mesosoma_transform * get_bone_transform(legs_skeleton, "mesocoxa_l")); - skeleton.set_bone_transform(*bones.mesofemur_l, get_bone_transform(legs_skeleton, "mesofemur_l")); - skeleton.set_bone_transform(*bones.mesotibia_l, get_bone_transform(legs_skeleton, "mesotibia_l")); - skeleton.set_bone_transform(*bones.mesotarsus_l, get_bone_transform(legs_skeleton, "mesotarsus1_l")); - - skeleton.set_bone_transform(*bones.mesocoxa_r, inverse_mesosoma_transform * get_bone_transform(legs_skeleton, "mesocoxa_r")); - skeleton.set_bone_transform(*bones.mesofemur_r, get_bone_transform(legs_skeleton, "mesofemur_r")); - skeleton.set_bone_transform(*bones.mesotibia_r, get_bone_transform(legs_skeleton, "mesotibia_r")); - skeleton.set_bone_transform(*bones.mesotarsus_r, get_bone_transform(legs_skeleton, "mesotarsus1_r")); - - skeleton.set_bone_transform(*bones.metacoxa_l, inverse_mesosoma_transform * get_bone_transform(legs_skeleton, "metacoxa_l")); - skeleton.set_bone_transform(*bones.metafemur_l, get_bone_transform(legs_skeleton, "metafemur_l")); - skeleton.set_bone_transform(*bones.metatibia_l, get_bone_transform(legs_skeleton, "metatibia_l")); - skeleton.set_bone_transform(*bones.metatarsus_l, get_bone_transform(legs_skeleton, "metatarsus1_l")); - - skeleton.set_bone_transform(*bones.metacoxa_r, inverse_mesosoma_transform * get_bone_transform(legs_skeleton, "metacoxa_r")); - skeleton.set_bone_transform(*bones.metafemur_r, get_bone_transform(legs_skeleton, "metafemur_r")); - skeleton.set_bone_transform(*bones.metatibia_r, get_bone_transform(legs_skeleton, "metatibia_r")); - skeleton.set_bone_transform(*bones.metatarsus_r, get_bone_transform(legs_skeleton, "metatarsus1_r")); - - skeleton.set_bone_transform(*bones.head, head_socket_transform * head_transform); - skeleton.set_bone_transform(*bones.mandible_l, get_bone_transform(head_skeleton, "mandible_l") * get_bone_transform(mandibles_skeleton, "mandible_l")); - skeleton.set_bone_transform(*bones.mandible_r, get_bone_transform(head_skeleton, "mandible_r") * get_bone_transform(mandibles_skeleton, "mandible_r")); - skeleton.set_bone_transform(*bones.antennomere1_l, get_bone_transform(head_skeleton, "antenna_l") * get_bone_transform(antennae_skeleton, "antennomere1_l")); - skeleton.set_bone_transform(*bones.antennomere2_l, get_bone_transform(antennae_skeleton, "antennomere2_l")); - skeleton.set_bone_transform(*bones.antennomere1_r, get_bone_transform(head_skeleton, "antenna_r") * get_bone_transform(antennae_skeleton, "antennomere1_r")); - skeleton.set_bone_transform(*bones.antennomere2_r, get_bone_transform(antennae_skeleton, "antennomere2_r")); - - if (bones.petiole) - { - skeleton.set_bone_transform(*bones.petiole, get_bone_transform(mesosoma_skeleton, "petiole") * get_bone_transform(waist_skeleton, "petiole")); - } - - if (bones.postpetiole) - { - skeleton.set_bone_transform(*bones.postpetiole, get_bone_transform(waist_skeleton, "postpetiole")); - } - - skeleton.set_bone_transform(*bones.gaster, get_bone_transform(waist_skeleton, "gaster") * get_bone_transform(gaster_skeleton, "gaster")); - - if (bones.sting) - { - skeleton.set_bone_transform(*bones.sting, get_bone_transform(gaster_skeleton, "sting") * get_bone_transform(*sting_skeleton, "sting")); - } - - if (bones.forewing_l) - { - skeleton.set_bone_transform(*bones.forewing_l, get_bone_transform(mesosoma_skeleton, "forewing_l") * get_bone_transform(*forewings_skeleton, "forewing_l")); - skeleton.set_bone_transform(*bones.forewing_r, get_bone_transform(mesosoma_skeleton, "forewing_r") * get_bone_transform(*forewings_skeleton, "forewing_r")); - skeleton.set_bone_transform(*bones.hindwing_l, get_bone_transform(mesosoma_skeleton, "hindwing_l") * get_bone_transform(*hindwings_skeleton, "hindwing_l")); - skeleton.set_bone_transform(*bones.hindwing_r, get_bone_transform(mesosoma_skeleton, "hindwing_r") * get_bone_transform(*hindwings_skeleton, "hindwing_r")); - } - - skeleton.update_rest_pose(); -} - } // namespace std::unique_ptr ant_morphogenesis(const ant_phenome& phenome) @@ -781,13 +399,10 @@ std::unique_ptr ant_morphogenesis(const ant_phenome& phenome) bone_index_attribute = &it->second; } - // Build ant skeleton + // Generate ant skeleton ::skeleton& skeleton = model->get_skeleton(); ant_bone_set bones; - build_ant_skeleton(phenome, skeleton, bones); - - // Build ant rest pose - build_ant_rest_pose(phenome, bones, skeleton); + generate_ant_skeleton(skeleton, bones, phenome); const auto& rest_pose = skeleton.get_rest_pose(); // Get number of vertices for each body part @@ -799,15 +414,6 @@ std::unique_ptr ant_morphogenesis(const ant_phenome& phenome) const std::uint32_t waist_vertex_count = (waist_model->get_groups()).front().index_count; const std::uint32_t gaster_vertex_count = (gaster_model->get_groups()).front().index_count; const std::uint32_t sting_vertex_count = (phenome.sting->present) ? (sting_model->get_groups()).front().index_count : 0; - const std::uint32_t exoskeleton_vertex_count = - mesosoma_vertex_count + - legs_vertex_count + - head_vertex_count + - mandibles_vertex_count + - antennae_vertex_count + - waist_vertex_count + - gaster_vertex_count + - sting_vertex_count; const std::uint32_t eyes_vertex_count = (phenome.eyes->present) ? (eyes_model->get_groups()).front().index_count : 0; const std::uint32_t lateral_ocelli_vertex_count = (phenome.ocelli->lateral_ocelli_present) ? (lateral_ocelli_model->get_groups()).front().index_count : 0; const std::uint32_t median_ocellus_vertex_count = (phenome.ocelli->median_ocellus_present) ? (median_ocellus_model->get_groups()).front().index_count : 0; @@ -1090,76 +696,37 @@ std::unique_ptr ant_morphogenesis(const ant_phenome& phenome) reskin_vertices(vertex_buffer_data.data() + hindwings_vbo_offset, hindwings_vertex_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, hindwings_reskin_map); } - // Upload vertex buffer data to model VBO - model->get_vertex_buffer()->repurpose(gl::buffer_usage::static_draw, vertex_buffer_size, vertex_buffer_data); - - // Count number of model groups - std::size_t model_group_count = 1; + // Tag eye vertices if (phenome.eyes->present) { - ++model_group_count; - } - if (phenome.ocelli->lateral_ocelli_present || phenome.ocelli->median_ocellus_present) - { - ++model_group_count; - } - if (phenome.wings->present) - { - model_group_count += 2; + tag_vertices({vertex_buffer_data.data() + eyes_vbo_offset, vertex_buffer_data.data() + eyes_vbo_offset + eyes_vertex_count}, *bone_index_attribute, 1); } - // Allocate model groups - model->get_groups().resize(model_group_count); - - std::size_t model_group_index = 0; - std::uint32_t index_offset = 0; - - // Construct exoskeleton model group - render::model_group& exoskeleton_group = model->get_groups()[model_group_index]; - exoskeleton_group.id = "exoskeleton"; - exoskeleton_group.material = exoskeleton_material; - exoskeleton_group.drawing_mode = gl::drawing_mode::triangles; - exoskeleton_group.start_index = index_offset; - exoskeleton_group.index_count = exoskeleton_vertex_count; - - index_offset += exoskeleton_group.index_count; - - if (phenome.eyes->present) - { - // Construct eyes model group - render::model_group& eyes_group = model->get_groups()[++model_group_index]; - eyes_group.id = "eyes"; - eyes_group.material = eyes_model->get_groups().front().material; - eyes_group.drawing_mode = gl::drawing_mode::triangles; - eyes_group.start_index = index_offset; - eyes_group.index_count = eyes_vertex_count; - - index_offset += eyes_group.index_count; - } + // Upload vertex buffer data to model VBO + model->get_vertex_buffer()->repurpose(gl::buffer_usage::static_draw, vertex_buffer_size, vertex_buffer_data); - if (phenome.ocelli->lateral_ocelli_present || phenome.ocelli->median_ocellus_present) - { - // Construct ocelli model group - render::model_group& ocelli_group = model->get_groups()[++model_group_index]; - ocelli_group.id = "ocelli"; - ocelli_group.drawing_mode = gl::drawing_mode::triangles; - ocelli_group.start_index = index_offset; - ocelli_group.index_count = 0; - - if (phenome.ocelli->lateral_ocelli_present) - { - ocelli_group.index_count += lateral_ocelli_vertex_count; - ocelli_group.material = lateral_ocelli_model->get_groups().front().material; - } - if (phenome.ocelli->median_ocellus_present) - { - ocelli_group.index_count += median_ocellus_vertex_count; - ocelli_group.material = median_ocellus_model->get_groups().front().material; - } - - index_offset += ocelli_group.index_count; - } + // Allocate model groups + model->get_groups().resize(1); + + // Construct model group + render::model_group& model_group = model->get_groups()[0]; + model_group.id = "exoskeleton"; + model_group.material = exoskeleton_material; + model_group.drawing_mode = gl::drawing_mode::triangles; + model_group.start_index = 0; + model_group.index_count = mesosoma_vertex_count + + legs_vertex_count + + head_vertex_count + + mandibles_vertex_count + + antennae_vertex_count + + waist_vertex_count + + gaster_vertex_count + + sting_vertex_count + + eyes_vertex_count + + lateral_ocelli_vertex_count + + median_ocellus_vertex_count; + /* if (phenome.wings->present) { // Construct forewings model group @@ -1182,9 +749,10 @@ std::unique_ptr ant_morphogenesis(const ant_phenome& phenome) index_offset += hindwings_group.index_count; } + */ // Calculate model bounding box - model->get_bounds() = calculate_bounds(vertex_buffer_data.data(), index_offset, *position_attribute); + model->get_bounds() = calculate_bounds(vertex_buffer_data.data(), model_group.index_count, *position_attribute); return model; } diff --git a/src/game/ant/ant-skeleton.cpp b/src/game/ant/ant-skeleton.cpp new file mode 100644 index 0000000..4d1cecf --- /dev/null +++ b/src/game/ant/ant-skeleton.cpp @@ -0,0 +1,528 @@ +/* + * Copyright (C) 2023 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#include "game/ant/ant-skeleton.hpp" +#include "game/ant/ant-bone-set.hpp" +#include + +namespace { + + +/** + * Generates the rest pose of ant skeleton. + * + * @param[in] phenome Ant phenome. + * @param[in] bones Set of ant skeleton bones. + * @param[in,out] skeleton Ant skeleton. + */ +void generate_ant_rest_pose(::skeleton& skeleton, const ant_bone_set& bones, const ant_phenome& phenome) +{ + // Get skeletons of individual body parts + const ::skeleton& mesosoma_skeleton = phenome.mesosoma->model->get_skeleton(); + const ::skeleton& legs_skeleton = phenome.legs->model->get_skeleton(); + const ::skeleton& head_skeleton = phenome.head->model->get_skeleton(); + const ::skeleton& mandibles_skeleton = phenome.mandibles->model->get_skeleton(); + const ::skeleton& antennae_skeleton = phenome.antennae->model->get_skeleton(); + const ::skeleton& waist_skeleton = phenome.waist->model->get_skeleton(); + const ::skeleton& gaster_skeleton = phenome.gaster->model->get_skeleton(); + const ::skeleton* sting_skeleton = (phenome.sting->present) ? &phenome.sting->model->get_skeleton() : nullptr; + const ::skeleton* forewings_skeleton = (phenome.wings->present) ? &phenome.wings->forewings_model->get_skeleton() : nullptr; + const ::skeleton* hindwings_skeleton = (phenome.wings->present) ? &phenome.wings->hindwings_model->get_skeleton() : nullptr; + + auto get_bone_transform = [](const ::skeleton& skeleton, hash::fnv1a32_t bone_name) + { + return skeleton.get_rest_pose().get_relative_transform(*skeleton.get_bone_index(bone_name)); + }; + + const auto& mesosoma_transform = get_bone_transform(mesosoma_skeleton, "mesosoma"); + const auto& head_socket_transform = get_bone_transform(mesosoma_skeleton, "head"); + const auto& head_transform = get_bone_transform(head_skeleton, "head"); + + const auto inverse_mesosoma_transform = math::inverse(mesosoma_transform); + + // Build skeleton rest pose + skeleton.set_bone_transform(*bones.mesosoma, mesosoma_transform); + + skeleton.set_bone_transform(*bones.procoxa_l, inverse_mesosoma_transform * get_bone_transform(legs_skeleton, "procoxa_l")); + skeleton.set_bone_transform(*bones.profemur_l, get_bone_transform(legs_skeleton, "profemur_l")); + skeleton.set_bone_transform(*bones.protibia_l, get_bone_transform(legs_skeleton, "protibia_l")); + skeleton.set_bone_transform(*bones.protarsus_l, get_bone_transform(legs_skeleton, "protarsus1_l")); + + skeleton.set_bone_transform(*bones.procoxa_r, inverse_mesosoma_transform * get_bone_transform(legs_skeleton, "procoxa_r")); + skeleton.set_bone_transform(*bones.profemur_r, get_bone_transform(legs_skeleton, "profemur_r")); + skeleton.set_bone_transform(*bones.protibia_r, get_bone_transform(legs_skeleton, "protibia_r")); + skeleton.set_bone_transform(*bones.protarsus_r, get_bone_transform(legs_skeleton, "protarsus1_r")); + + skeleton.set_bone_transform(*bones.mesocoxa_l, inverse_mesosoma_transform * get_bone_transform(legs_skeleton, "mesocoxa_l")); + skeleton.set_bone_transform(*bones.mesofemur_l, get_bone_transform(legs_skeleton, "mesofemur_l")); + skeleton.set_bone_transform(*bones.mesotibia_l, get_bone_transform(legs_skeleton, "mesotibia_l")); + skeleton.set_bone_transform(*bones.mesotarsus_l, get_bone_transform(legs_skeleton, "mesotarsus1_l")); + + skeleton.set_bone_transform(*bones.mesocoxa_r, inverse_mesosoma_transform * get_bone_transform(legs_skeleton, "mesocoxa_r")); + skeleton.set_bone_transform(*bones.mesofemur_r, get_bone_transform(legs_skeleton, "mesofemur_r")); + skeleton.set_bone_transform(*bones.mesotibia_r, get_bone_transform(legs_skeleton, "mesotibia_r")); + skeleton.set_bone_transform(*bones.mesotarsus_r, get_bone_transform(legs_skeleton, "mesotarsus1_r")); + + skeleton.set_bone_transform(*bones.metacoxa_l, inverse_mesosoma_transform * get_bone_transform(legs_skeleton, "metacoxa_l")); + skeleton.set_bone_transform(*bones.metafemur_l, get_bone_transform(legs_skeleton, "metafemur_l")); + skeleton.set_bone_transform(*bones.metatibia_l, get_bone_transform(legs_skeleton, "metatibia_l")); + skeleton.set_bone_transform(*bones.metatarsus_l, get_bone_transform(legs_skeleton, "metatarsus1_l")); + + skeleton.set_bone_transform(*bones.metacoxa_r, inverse_mesosoma_transform * get_bone_transform(legs_skeleton, "metacoxa_r")); + skeleton.set_bone_transform(*bones.metafemur_r, get_bone_transform(legs_skeleton, "metafemur_r")); + skeleton.set_bone_transform(*bones.metatibia_r, get_bone_transform(legs_skeleton, "metatibia_r")); + skeleton.set_bone_transform(*bones.metatarsus_r, get_bone_transform(legs_skeleton, "metatarsus1_r")); + + skeleton.set_bone_transform(*bones.head, head_socket_transform * head_transform); + skeleton.set_bone_transform(*bones.mandible_l, get_bone_transform(head_skeleton, "mandible_l") * get_bone_transform(mandibles_skeleton, "mandible_l")); + skeleton.set_bone_transform(*bones.mandible_r, get_bone_transform(head_skeleton, "mandible_r") * get_bone_transform(mandibles_skeleton, "mandible_r")); + skeleton.set_bone_transform(*bones.antennomere1_l, get_bone_transform(head_skeleton, "antenna_l") * get_bone_transform(antennae_skeleton, "antennomere1_l")); + skeleton.set_bone_transform(*bones.antennomere2_l, get_bone_transform(antennae_skeleton, "antennomere2_l")); + skeleton.set_bone_transform(*bones.antennomere1_r, get_bone_transform(head_skeleton, "antenna_r") * get_bone_transform(antennae_skeleton, "antennomere1_r")); + skeleton.set_bone_transform(*bones.antennomere2_r, get_bone_transform(antennae_skeleton, "antennomere2_r")); + + if (bones.petiole) + { + skeleton.set_bone_transform(*bones.petiole, get_bone_transform(mesosoma_skeleton, "petiole") * get_bone_transform(waist_skeleton, "petiole")); + } + + if (bones.postpetiole) + { + skeleton.set_bone_transform(*bones.postpetiole, get_bone_transform(waist_skeleton, "postpetiole")); + } + + skeleton.set_bone_transform(*bones.gaster, get_bone_transform(waist_skeleton, "gaster") * get_bone_transform(gaster_skeleton, "gaster")); + + if (bones.sting) + { + skeleton.set_bone_transform(*bones.sting, get_bone_transform(gaster_skeleton, "sting") * get_bone_transform(*sting_skeleton, "sting")); + } + + if (bones.forewing_l) + { + skeleton.set_bone_transform(*bones.forewing_l, get_bone_transform(mesosoma_skeleton, "forewing_l") * get_bone_transform(*forewings_skeleton, "forewing_l")); + skeleton.set_bone_transform(*bones.forewing_r, get_bone_transform(mesosoma_skeleton, "forewing_r") * get_bone_transform(*forewings_skeleton, "forewing_r")); + skeleton.set_bone_transform(*bones.hindwing_l, get_bone_transform(mesosoma_skeleton, "hindwing_l") * get_bone_transform(*hindwings_skeleton, "hindwing_l")); + skeleton.set_bone_transform(*bones.hindwing_r, get_bone_transform(mesosoma_skeleton, "hindwing_r") * get_bone_transform(*hindwings_skeleton, "hindwing_r")); + } + + skeleton.update_rest_pose(); +} + +/** + * Generates a pupa pose (named "pupa") for an ant skeleton. + * + * @param[in,out] skeleton Ant skeleton. + * @parma bones Set of ant bone indices. + */ +void generate_ant_pupa_pose(skeleton& skeleton, const ant_bone_set& bones) +{ + const auto& rest_pose = skeleton.get_rest_pose(); + auto& pupa_pose = skeleton.add_pose("pupa"); + + // Fold forelegs + { + constexpr float procoxa_fold_angle_y = math::radians(30.0f); + constexpr float procoxa_fold_angle_z = math::radians(25.0f); + constexpr float procoxa_fold_angle_x = math::radians(15.0f); + auto fold_procoxa_l = math::transform::identity(); + auto fold_procoxa_r = math::transform::identity(); + fold_procoxa_l.rotation = math::angle_axis(procoxa_fold_angle_y, float3{0, 1, 0}) * math::angle_axis(procoxa_fold_angle_z, float3{0, 0, 1}) * math::angle_axis(procoxa_fold_angle_x, float3{1, 0, 0}); + fold_procoxa_r.rotation = math::angle_axis(-procoxa_fold_angle_y, float3{0, 1, 0}) * math::angle_axis(-procoxa_fold_angle_z, float3{0, 0, 1}) * math::angle_axis(procoxa_fold_angle_x, float3{1, 0, 0}); + + constexpr float profemur_fold_angle_z = math::radians(20.0f); + constexpr float profemur_fold_angle_x = math::radians(80.0f); + auto fold_profemur_l = math::transform::identity(); + auto fold_profemur_r = math::transform::identity(); + fold_profemur_l.rotation = math::angle_axis(profemur_fold_angle_z, float3{0, 0, 1}) * math::angle_axis(profemur_fold_angle_x, float3{1, 0, 0}); + fold_profemur_r.rotation = math::angle_axis(-profemur_fold_angle_z, float3{0, 0, 1}) * math::angle_axis(profemur_fold_angle_x, float3{1, 0, 0}); + + constexpr float protibia_fold_angle = math::radians(165.0f); + auto fold_protibia_l = math::transform::identity(); + auto fold_protibia_r = math::transform::identity(); + fold_protibia_l.rotation = math::angle_axis(-protibia_fold_angle, float3{1, 0, 0}); + fold_protibia_r.rotation = math::angle_axis(-protibia_fold_angle, float3{1, 0, 0}); + + constexpr float protarsus_fold_angle = math::radians(20.0f); + auto fold_protarsus_l = math::transform::identity(); + auto fold_protarsus_r = math::transform::identity(); + fold_protarsus_l.rotation = math::angle_axis(-protarsus_fold_angle, float3{1, 0, 0}); + fold_protarsus_r.rotation = math::angle_axis(-protarsus_fold_angle, float3{1, 0, 0}); + + pupa_pose.set_relative_transform(*bones.procoxa_l, rest_pose.get_relative_transform(*bones.procoxa_l) * fold_procoxa_l); + pupa_pose.set_relative_transform(*bones.procoxa_r, rest_pose.get_relative_transform(*bones.procoxa_r) * fold_procoxa_r); + pupa_pose.set_relative_transform(*bones.profemur_l, rest_pose.get_relative_transform(*bones.profemur_l) * fold_profemur_l); + pupa_pose.set_relative_transform(*bones.profemur_r, rest_pose.get_relative_transform(*bones.profemur_r) * fold_profemur_r); + pupa_pose.set_relative_transform(*bones.protibia_l, rest_pose.get_relative_transform(*bones.protibia_l) * fold_protibia_l); + pupa_pose.set_relative_transform(*bones.protibia_r, rest_pose.get_relative_transform(*bones.protibia_r) * fold_protibia_r); + pupa_pose.set_relative_transform(*bones.protarsus_l, rest_pose.get_relative_transform(*bones.protarsus_l) * fold_protarsus_l); + pupa_pose.set_relative_transform(*bones.protarsus_r, rest_pose.get_relative_transform(*bones.protarsus_r) * fold_protarsus_r); + } + + // Fold midlegs + { + constexpr float mesocoxa_fold_angle_z = math::radians(45.0f); + constexpr float mesocoxa_fold_angle_y = math::radians(45.0f); + constexpr float mesocoxa_fold_angle_x = math::radians(10.0f); + auto fold_mesocoxa_l = math::transform::identity(); + auto fold_mesocoxa_r = math::transform::identity(); + fold_mesocoxa_l.rotation = math::angle_axis(-mesocoxa_fold_angle_z, float3{0, 0, 1}) * math::angle_axis(mesocoxa_fold_angle_y, float3{0, 1, 0}) * math::angle_axis(-mesocoxa_fold_angle_x, float3{1, 0, 0}); + fold_mesocoxa_r.rotation = math::angle_axis(mesocoxa_fold_angle_z, float3{0, 0, 1}) * math::angle_axis(-mesocoxa_fold_angle_y, float3{0, 1, 0}) * math::angle_axis(-mesocoxa_fold_angle_x, float3{1, 0, 0}); + + constexpr float mesofemur_fold_angle = math::radians(90.0f); + auto fold_mesofemur_l = math::transform::identity(); + auto fold_mesofemur_r = math::transform::identity(); + fold_mesofemur_l.rotation = math::angle_axis(mesofemur_fold_angle, float3{1, 0, 0}); + fold_mesofemur_r.rotation = math::angle_axis(mesofemur_fold_angle, float3{1, 0, 0}); + + constexpr float mesotibia_fold_angle = math::radians(162.0f); + auto fold_mesotibia_l = math::transform::identity(); + auto fold_mesotibia_r = math::transform::identity(); + fold_mesotibia_l.rotation = math::angle_axis(-mesotibia_fold_angle, float3{1, 0, 0}); + fold_mesotibia_r.rotation = math::angle_axis(-mesotibia_fold_angle, float3{1, 0, 0}); + + constexpr float mesotarsus_fold_angle = math::radians(20.0f); + auto fold_mesotarsus_l = math::transform::identity(); + auto fold_mesotarsus_r = math::transform::identity(); + fold_mesotarsus_l.rotation = math::angle_axis(-mesotarsus_fold_angle, float3{1, 0, 0}); + fold_mesotarsus_r.rotation = math::angle_axis(-mesotarsus_fold_angle, float3{1, 0, 0}); + + pupa_pose.set_relative_transform(*bones.mesocoxa_l, rest_pose.get_relative_transform(*bones.mesocoxa_l) * fold_mesocoxa_l); + pupa_pose.set_relative_transform(*bones.mesocoxa_r, rest_pose.get_relative_transform(*bones.mesocoxa_r) * fold_mesocoxa_r); + pupa_pose.set_relative_transform(*bones.mesofemur_l, rest_pose.get_relative_transform(*bones.mesofemur_l) * fold_mesofemur_l); + pupa_pose.set_relative_transform(*bones.mesofemur_r, rest_pose.get_relative_transform(*bones.mesofemur_r) * fold_mesofemur_r); + pupa_pose.set_relative_transform(*bones.mesotibia_l, rest_pose.get_relative_transform(*bones.mesotibia_l) * fold_mesotibia_l); + pupa_pose.set_relative_transform(*bones.mesotibia_r, rest_pose.get_relative_transform(*bones.mesotibia_r) * fold_mesotibia_r); + pupa_pose.set_relative_transform(*bones.mesotarsus_l, rest_pose.get_relative_transform(*bones.mesotarsus_l) * fold_mesotarsus_l); + pupa_pose.set_relative_transform(*bones.mesotarsus_r, rest_pose.get_relative_transform(*bones.mesotarsus_r) * fold_mesotarsus_r); + } + + // Fold hindlegs + { + constexpr float metacoxa_fold_angle_z = math::radians(15.0f); + constexpr float metacoxa_fold_angle_y = math::radians(10.0f); + constexpr float metacoxa_fold_angle_x = math::radians(25.0f); + auto fold_metacoxa_l = math::transform::identity(); + auto fold_metacoxa_r = math::transform::identity(); + fold_metacoxa_l.rotation = math::angle_axis(-metacoxa_fold_angle_z, float3{0, 0, 1}) * math::angle_axis(-metacoxa_fold_angle_y, float3{0, 1, 0}) * math::angle_axis(metacoxa_fold_angle_x, float3{1, 0, 0}); + fold_metacoxa_r.rotation = math::angle_axis(metacoxa_fold_angle_z, float3{0, 0, 1}) * math::angle_axis(metacoxa_fold_angle_y, float3{0, 1, 0}) * math::angle_axis(metacoxa_fold_angle_x, float3{1, 0, 0}); + + constexpr float metafemur_fold_angle = math::radians(105.0f); + auto fold_metafemur_l = math::transform::identity(); + auto fold_metafemur_r = math::transform::identity(); + fold_metafemur_l.rotation = math::angle_axis(metafemur_fold_angle, float3{1, 0, 0}); + fold_metafemur_r.rotation = math::angle_axis(metafemur_fold_angle, float3{1, 0, 0}); + + constexpr float metatibia_fold_angle = math::radians(165.0f); + auto fold_metatibia_l = math::transform::identity(); + auto fold_metatibia_r = math::transform::identity(); + fold_metatibia_l.rotation = math::angle_axis(-metatibia_fold_angle, float3{1, 0, 0}); + fold_metatibia_r.rotation = math::angle_axis(-metatibia_fold_angle, float3{1, 0, 0}); + + constexpr float metatarsus_fold_angle = math::radians(0.0f); + auto fold_metatarsus_l = math::transform::identity(); + auto fold_metatarsus_r = math::transform::identity(); + fold_metatarsus_l.rotation = math::angle_axis(-metatarsus_fold_angle, float3{1, 0, 0}); + fold_metatarsus_r.rotation = math::angle_axis(-metatarsus_fold_angle, float3{1, 0, 0}); + + pupa_pose.set_relative_transform(*bones.metacoxa_l, rest_pose.get_relative_transform(*bones.metacoxa_l) * fold_metacoxa_l); + pupa_pose.set_relative_transform(*bones.metacoxa_r, rest_pose.get_relative_transform(*bones.metacoxa_r) * fold_metacoxa_r); + pupa_pose.set_relative_transform(*bones.metafemur_l, rest_pose.get_relative_transform(*bones.metafemur_l) * fold_metafemur_l); + pupa_pose.set_relative_transform(*bones.metafemur_r, rest_pose.get_relative_transform(*bones.metafemur_r) * fold_metafemur_r); + pupa_pose.set_relative_transform(*bones.metatibia_l, rest_pose.get_relative_transform(*bones.metatibia_l) * fold_metatibia_l); + pupa_pose.set_relative_transform(*bones.metatibia_r, rest_pose.get_relative_transform(*bones.metatibia_r) * fold_metatibia_r); + pupa_pose.set_relative_transform(*bones.metatarsus_l, rest_pose.get_relative_transform(*bones.metatarsus_l) * fold_metatarsus_l); + pupa_pose.set_relative_transform(*bones.metatarsus_r, rest_pose.get_relative_transform(*bones.metatarsus_r) * fold_metatarsus_r); + } + + // Fold head + { + constexpr float head_fold_angle = math::radians(80.0f); + auto fold_head = math::transform::identity(); + fold_head.rotation = math::angle_axis(-head_fold_angle, float3{1, 0, 0}); + + pupa_pose.set_relative_transform(*bones.head, rest_pose.get_relative_transform(*bones.head) * fold_head); + } + + // Fold antennae + { + constexpr float antennomere1_fold_angle_y = math::radians(70.0f); + constexpr float antennomere1_fold_angle_x = math::radians(45.0f); + auto fold_antennomere1_l = math::transform::identity(); + auto fold_antennomere1_r = math::transform::identity(); + fold_antennomere1_l.rotation = math::angle_axis(-antennomere1_fold_angle_y, float3{0, 1, 0}) * math::angle_axis(-antennomere1_fold_angle_x, float3{1, 0, 0}); + fold_antennomere1_r.rotation = math::angle_axis(antennomere1_fold_angle_y, float3{0, 1, 0}) * math::angle_axis(-antennomere1_fold_angle_x, float3{1, 0, 0}); + + constexpr float antennomere2_fold_angle_y = math::radians(75.0f); + constexpr float antennomere2_fold_angle_x = math::radians(25.0f); + auto fold_antennomere2_l = math::transform::identity(); + auto fold_antennomere2_r = math::transform::identity(); + fold_antennomere2_l.rotation = math::angle_axis(antennomere2_fold_angle_y, float3{0, 1, 0}) * math::angle_axis(-antennomere2_fold_angle_x, float3{1, 0, 0}); + fold_antennomere2_r.rotation = math::angle_axis(-antennomere2_fold_angle_y, float3{0, 1, 0}) * math::angle_axis(-antennomere2_fold_angle_x, float3{1, 0, 0}); + + pupa_pose.set_relative_transform(*bones.antennomere1_l, rest_pose.get_relative_transform(*bones.antennomere1_l) * fold_antennomere1_l); + pupa_pose.set_relative_transform(*bones.antennomere1_r, rest_pose.get_relative_transform(*bones.antennomere1_r) * fold_antennomere1_r); + pupa_pose.set_relative_transform(*bones.antennomere2_l, rest_pose.get_relative_transform(*bones.antennomere2_l) * fold_antennomere2_l); + pupa_pose.set_relative_transform(*bones.antennomere2_r, rest_pose.get_relative_transform(*bones.antennomere2_r) * fold_antennomere2_r); + } + + // Fold waist + gaster + { + constexpr float petiole_fold_angle = math::radians(40.0f); + auto fold_petiole = math::transform::identity(); + fold_petiole.rotation = math::angle_axis(petiole_fold_angle, float3{1, 0, 0}); + + constexpr float postpetiole_fold_angle = math::radians(35.0f); + auto fold_postpetiole = math::transform::identity(); + fold_postpetiole.rotation = math::angle_axis(-postpetiole_fold_angle, float3{1, 0, 0}); + + constexpr float gaster_fold_angle = math::radians(0.0f); + auto fold_gaster = math::transform::identity(); + fold_gaster.rotation = math::angle_axis(-gaster_fold_angle, float3{1, 0, 0}); + + if (bones.petiole) + { + pupa_pose.set_relative_transform(*bones.petiole, rest_pose.get_relative_transform(*bones.petiole) * fold_petiole); + } + + if (bones.postpetiole) + { + pupa_pose.set_relative_transform(*bones.postpetiole, rest_pose.get_relative_transform(*bones.postpetiole) * fold_postpetiole); + } + + pupa_pose.set_relative_transform(*bones.gaster, rest_pose.get_relative_transform(*bones.gaster) * fold_gaster); + } + + // Invert mesosoma + // { + // const float mesosoma_invert_angle = math::radians(90.0f); + // auto invert_mesosoma = math::transform::identity(); + // invert_mesosoma.rotation = math::angle_axis(mesosoma_invert_angle, float3{0, 0, 1}); + + // auto mesosoma = *skeleton.get_index("mesosoma"); + // pupa_pose.set_relative_transform(bones.mesosoma, invert_mesosoma * rest_pose.get_relative_transform(bones.mesosoma)); + // } + + pupa_pose.update(); +} + +} // namespace + +void generate_ant_skeleton(skeleton& skeleton, ant_bone_set& bones, const ant_phenome& phenome) +{ + // Assign bone indices + bone_index_type bone_index = 0; + bones.mesosoma = bone_index; + bones.procoxa_l = ++bone_index; + bones.profemur_l = ++bone_index; + bones.protibia_l = ++bone_index; + bones.protarsus_l = ++bone_index; + bones.procoxa_r = ++bone_index; + bones.profemur_r = ++bone_index; + bones.protibia_r = ++bone_index; + bones.protarsus_r = ++bone_index; + bones.mesocoxa_l = ++bone_index; + bones.mesofemur_l = ++bone_index; + bones.mesotibia_l = ++bone_index; + bones.mesotarsus_l = ++bone_index; + bones.mesocoxa_r = ++bone_index; + bones.mesofemur_r = ++bone_index; + bones.mesotibia_r = ++bone_index; + bones.mesotarsus_r = ++bone_index; + bones.metacoxa_l = ++bone_index; + bones.metafemur_l = ++bone_index; + bones.metatibia_l = ++bone_index; + bones.metatarsus_l = ++bone_index; + bones.metacoxa_r = ++bone_index; + bones.metafemur_r = ++bone_index; + bones.metatibia_r = ++bone_index; + bones.metatarsus_r = ++bone_index; + bones.head = ++bone_index; + bones.mandible_l = ++bone_index; + bones.mandible_r = ++bone_index; + bones.antennomere1_l = ++bone_index; + bones.antennomere2_l = ++bone_index; + bones.antennomere1_r = ++bone_index; + bones.antennomere2_r = ++bone_index; + + if (phenome.waist->petiole_present) + { + bones.petiole = ++bone_index; + } + + if (phenome.waist->postpetiole_present) + { + bones.postpetiole = ++bone_index; + } + + bones.gaster = ++bone_index; + + if (phenome.sting->present) + { + bones.sting = ++bone_index; + } + + if (phenome.wings->present) + { + bones.forewing_l = ++bone_index; + bones.forewing_r = ++bone_index; + bones.hindwing_l = ++bone_index; + bones.hindwing_r = ++bone_index; + } + + // Allocate bones + skeleton.add_bones(bone_index + 1); + + // Assign bone parents + skeleton.set_bone_parent(*bones.mesosoma, *bones.mesosoma); + skeleton.set_bone_parent(*bones.procoxa_l, *bones.mesosoma); + skeleton.set_bone_parent(*bones.profemur_l, *bones.procoxa_l); + skeleton.set_bone_parent(*bones.protibia_l, *bones.profemur_l); + skeleton.set_bone_parent(*bones.protarsus_l, *bones.protibia_l); + skeleton.set_bone_parent(*bones.procoxa_r, *bones.mesosoma); + skeleton.set_bone_parent(*bones.profemur_r, *bones.procoxa_r); + skeleton.set_bone_parent(*bones.protibia_r, *bones.profemur_r); + skeleton.set_bone_parent(*bones.protarsus_r, *bones.protibia_r); + skeleton.set_bone_parent(*bones.mesocoxa_l, *bones.mesosoma); + skeleton.set_bone_parent(*bones.mesofemur_l, *bones.mesocoxa_l); + skeleton.set_bone_parent(*bones.mesotibia_l, *bones.mesofemur_l); + skeleton.set_bone_parent(*bones.mesotarsus_l, *bones.mesotibia_l); + skeleton.set_bone_parent(*bones.mesocoxa_r, *bones.mesosoma); + skeleton.set_bone_parent(*bones.mesofemur_r, *bones.mesocoxa_r); + skeleton.set_bone_parent(*bones.mesotibia_r, *bones.mesofemur_r); + skeleton.set_bone_parent(*bones.mesotarsus_r, *bones.mesotibia_r); + skeleton.set_bone_parent(*bones.metacoxa_l, *bones.mesosoma); + skeleton.set_bone_parent(*bones.metafemur_l, *bones.metacoxa_l); + skeleton.set_bone_parent(*bones.metatibia_l, *bones.metafemur_l); + skeleton.set_bone_parent(*bones.metatarsus_l, *bones.metatibia_l); + skeleton.set_bone_parent(*bones.metacoxa_r, *bones.mesosoma); + skeleton.set_bone_parent(*bones.metafemur_r, *bones.metacoxa_r); + skeleton.set_bone_parent(*bones.metatibia_r, *bones.metafemur_r); + skeleton.set_bone_parent(*bones.metatarsus_r, *bones.metatibia_r); + skeleton.set_bone_parent(*bones.head, *bones.mesosoma); + skeleton.set_bone_parent(*bones.mandible_l, *bones.head); + skeleton.set_bone_parent(*bones.mandible_r, *bones.head); + skeleton.set_bone_parent(*bones.antennomere1_l, *bones.head); + skeleton.set_bone_parent(*bones.antennomere2_l, *bones.antennomere1_l); + skeleton.set_bone_parent(*bones.antennomere1_r, *bones.head); + skeleton.set_bone_parent(*bones.antennomere2_r, *bones.antennomere1_r); + + if (bones.petiole) + { + skeleton.set_bone_parent(*bones.petiole, *bones.mesosoma); + } + if (bones.postpetiole) + { + if (bones.petiole) + { + skeleton.set_bone_parent(*bones.postpetiole, *bones.petiole); + } + else + { + skeleton.set_bone_parent(*bones.postpetiole, *bones.mesosoma); + } + } + + if (bones.postpetiole) + { + skeleton.set_bone_parent(*bones.gaster, *bones.postpetiole); + } + else + { + if (bones.petiole) + { + skeleton.set_bone_parent(*bones.gaster, *bones.petiole); + } + else + { + skeleton.set_bone_parent(*bones.gaster, *bones.mesosoma); + } + } + + if (bones.sting) + { + skeleton.set_bone_parent(*bones.sting, *bones.gaster); + } + + if (bones.forewing_l) + { + skeleton.set_bone_parent(*bones.forewing_l, *bones.mesosoma); + skeleton.set_bone_parent(*bones.forewing_r, *bones.mesosoma); + skeleton.set_bone_parent(*bones.hindwing_l, *bones.mesosoma); + skeleton.set_bone_parent(*bones.hindwing_r, *bones.mesosoma); + } + + // Assign bone names + skeleton.set_bone_name(*bones.mesosoma, "mesosoma"); + skeleton.set_bone_name(*bones.procoxa_l, "procoxa_l"); + skeleton.set_bone_name(*bones.profemur_l, "profemur_l"); + skeleton.set_bone_name(*bones.protibia_l, "protibia_l"); + skeleton.set_bone_name(*bones.protarsus_l, "protarsus_l"); + skeleton.set_bone_name(*bones.procoxa_r, "procoxa_r"); + skeleton.set_bone_name(*bones.profemur_r, "profemur_r"); + skeleton.set_bone_name(*bones.protibia_r, "protibia_r"); + skeleton.set_bone_name(*bones.protarsus_r, "protarsus_r"); + skeleton.set_bone_name(*bones.mesocoxa_l, "mesocoxa_l"); + skeleton.set_bone_name(*bones.mesofemur_l, "mesofemur_l"); + skeleton.set_bone_name(*bones.mesotibia_l, "mesotibia_l"); + skeleton.set_bone_name(*bones.mesotarsus_l, "mesotarsus_l"); + skeleton.set_bone_name(*bones.mesocoxa_r, "mesocoxa_r"); + skeleton.set_bone_name(*bones.mesofemur_r, "mesofemur_r"); + skeleton.set_bone_name(*bones.mesotibia_r, "mesotibia_r"); + skeleton.set_bone_name(*bones.mesotarsus_r, "mesotarsus_r"); + skeleton.set_bone_name(*bones.metacoxa_l, "metacoxa_l"); + skeleton.set_bone_name(*bones.metafemur_l, "metafemur_l"); + skeleton.set_bone_name(*bones.metatibia_l, "metatibia_l"); + skeleton.set_bone_name(*bones.metatarsus_l, "metatarsus_l"); + skeleton.set_bone_name(*bones.metacoxa_r, "metacoxa_r"); + skeleton.set_bone_name(*bones.metafemur_r, "metafemur_r"); + skeleton.set_bone_name(*bones.metatibia_r, "metatibia_r"); + skeleton.set_bone_name(*bones.metatarsus_r, "metatarsus_r"); + skeleton.set_bone_name(*bones.head, "head"); + skeleton.set_bone_name(*bones.mandible_l, "mandible_l"); + skeleton.set_bone_name(*bones.mandible_r, "mandible_r"); + skeleton.set_bone_name(*bones.antennomere1_l, "antennomere1_l"); + skeleton.set_bone_name(*bones.antennomere2_l, "antennomere2_l"); + skeleton.set_bone_name(*bones.antennomere1_r, "antennomere1_r"); + skeleton.set_bone_name(*bones.antennomere2_r, "antennomere2_r"); + if (bones.petiole) + { + skeleton.set_bone_name(*bones.petiole, "petiole"); + } + if (bones.postpetiole) + { + skeleton.set_bone_name(*bones.postpetiole, "postpetiole"); + } + skeleton.set_bone_name(*bones.gaster, "gaster"); + if (bones.sting) + { + skeleton.set_bone_name(*bones.sting, "sting"); + } + if (bones.forewing_l) + { + skeleton.set_bone_name(*bones.forewing_l, "forewing_l"); + skeleton.set_bone_name(*bones.forewing_r, "forewing_r"); + skeleton.set_bone_name(*bones.hindwing_l, "hindwing_l"); + skeleton.set_bone_name(*bones.hindwing_r, "hindwing_r"); + } + + // Generate poses + generate_ant_rest_pose(skeleton, bones, phenome); + generate_ant_pupa_pose(skeleton, bones); +} diff --git a/src/game/ant/ant-skeleton.hpp b/src/game/ant/ant-skeleton.hpp new file mode 100644 index 0000000..04c3326 --- /dev/null +++ b/src/game/ant/ant-skeleton.hpp @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2023 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_GAME_ANT_SKELETON_HPP +#define ANTKEEPER_GAME_ANT_SKELETON_HPP + +#include +#include "game/ant/ant-phenome.hpp" +#include "game/ant/ant-bone-set.hpp" + +/** + * Generates a skeleton for an ant model. + * + * @param[in,out] skeleton Ant skeleton. + * @param[out] bones Ant bone set. + * @param[in] phenome Ant phenome. + * + * The following bones will always be present: + * + * * antennomere1_l + * * antennomere1_r + * * antennomere2_l + * * antennomere2_r + * * gaster + * * head + * * mandible_l + * * mandible_r + * * mesocoxa_l + * * mesocoxa_r + * * mesofemur_l + * * mesofemur_r + * * mesosoma + * * mesotarsus_l + * * mesotarsus_r + * * mesotibia_l + * * mesotibia_r + * * metacoxa_l + * * metacoxa_r + * * metafemur_l + * * metafemur_r + * * metatarsus_l + * * metatarsus_r + * * metatibia_l + * * metatibia_r + * * procoxa_l + * * procoxa_r + * * profemur_l + * * profemur_r + * * protarsus_l + * * protarsus_r + * * protibia_l + * * protibia_r + * + * The presence of the following bones depend on the ant phenome: + * + * * forewing_l + * * forewing_r + * * hindwing_l + * * hindwing_r + * * petiole + * * postpetiole + * * sting + * + * The following poses will be generated: + * + * * rest pose + * * "pupa" + */ +void generate_ant_skeleton(skeleton& skeleton, ant_bone_set& bones, const ant_phenome& phenome); + +#endif // ANTKEEPER_GAME_ANT_SKELETON_HPP diff --git a/src/game/states/nest-selection-state.cpp b/src/game/states/nest-selection-state.cpp index 0519bc5..a6640bd 100644 --- a/src/game/states/nest-selection-state.cpp +++ b/src/game/states/nest-selection-state.cpp @@ -130,239 +130,7 @@ nest_selection_state::nest_selection_state(::game& ctx): // Create worker entity(s) - - auto& worker_skeleton = worker_model->get_skeleton(); - const auto& worker_rest_pose = worker_skeleton.get_rest_pose(); - - auto& pupal_pose = worker_skeleton.add_pose("pupal"); - - // Fold forelegs - { - const float procoxa_fold_angle_y = math::radians(30.0f); - const float procoxa_fold_angle_z = math::radians(25.0f); - const float procoxa_fold_angle_x = math::radians(15.0f); - auto fold_procoxa_l = math::transform::identity(); - auto fold_procoxa_r = math::transform::identity(); - fold_procoxa_l.rotation = math::angle_axis(procoxa_fold_angle_y, float3{0, 1, 0}) * math::angle_axis(procoxa_fold_angle_z, float3{0, 0, 1}) * math::angle_axis(procoxa_fold_angle_x, float3{1, 0, 0}); - fold_procoxa_r.rotation = math::angle_axis(-procoxa_fold_angle_y, float3{0, 1, 0}) * math::angle_axis(-procoxa_fold_angle_z, float3{0, 0, 1}) * math::angle_axis(procoxa_fold_angle_x, float3{1, 0, 0}); - - const float profemur_fold_angle_z = math::radians(20.0f); - const float profemur_fold_angle_x = math::radians(80.0f); - auto fold_profemur_l = math::transform::identity(); - auto fold_profemur_r = math::transform::identity(); - fold_profemur_l.rotation = math::angle_axis(profemur_fold_angle_z, float3{0, 0, 1}) * math::angle_axis(profemur_fold_angle_x, float3{1, 0, 0}); - fold_profemur_r.rotation = math::angle_axis(-profemur_fold_angle_z, float3{0, 0, 1}) * math::angle_axis(profemur_fold_angle_x, float3{1, 0, 0}); - - const float protibia_fold_angle = math::radians(165.0f); - auto fold_protibia_l = math::transform::identity(); - auto fold_protibia_r = math::transform::identity(); - fold_protibia_l.rotation = math::angle_axis(-protibia_fold_angle, float3{1, 0, 0}); - fold_protibia_r.rotation = math::angle_axis(-protibia_fold_angle, float3{1, 0, 0}); - - const float protarsus_fold_angle = math::radians(20.0f); - auto fold_protarsus_l = math::transform::identity(); - auto fold_protarsus_r = math::transform::identity(); - fold_protarsus_l.rotation = math::angle_axis(-protarsus_fold_angle, float3{1, 0, 0}); - fold_protarsus_r.rotation = math::angle_axis(-protarsus_fold_angle, float3{1, 0, 0}); - - auto procoxa_l_bone = *worker_skeleton.get_bone_index("procoxa_l"); - auto procoxa_r_bone = *worker_skeleton.get_bone_index("procoxa_r"); - auto profemur_l_bone = *worker_skeleton.get_bone_index("profemur_l"); - auto profemur_r_bone = *worker_skeleton.get_bone_index("profemur_r"); - auto protibia_l_bone = *worker_skeleton.get_bone_index("protibia_l"); - auto protibia_r_bone = *worker_skeleton.get_bone_index("protibia_r"); - auto protarsus_l_bone = *worker_skeleton.get_bone_index("protarsus_l"); - auto protarsus_r_bone = *worker_skeleton.get_bone_index("protarsus_r"); - - pupal_pose.set_relative_transform(procoxa_l_bone, worker_rest_pose.get_relative_transform(procoxa_l_bone) * fold_procoxa_l); - pupal_pose.set_relative_transform(procoxa_r_bone, worker_rest_pose.get_relative_transform(procoxa_r_bone) * fold_procoxa_r); - pupal_pose.set_relative_transform(profemur_l_bone, worker_rest_pose.get_relative_transform(profemur_l_bone) * fold_profemur_l); - pupal_pose.set_relative_transform(profemur_r_bone, worker_rest_pose.get_relative_transform(profemur_r_bone) * fold_profemur_r); - pupal_pose.set_relative_transform(protibia_l_bone, worker_rest_pose.get_relative_transform(protibia_l_bone) * fold_protibia_l); - pupal_pose.set_relative_transform(protibia_r_bone, worker_rest_pose.get_relative_transform(protibia_r_bone) * fold_protibia_r); - pupal_pose.set_relative_transform(protarsus_l_bone, worker_rest_pose.get_relative_transform(protarsus_l_bone) * fold_protarsus_l); - pupal_pose.set_relative_transform(protarsus_r_bone, worker_rest_pose.get_relative_transform(protarsus_r_bone) * fold_protarsus_r); - } - - // Fold midlegs - { - const float mesocoxa_fold_angle_z = math::radians(45.0f); - const float mesocoxa_fold_angle_y = math::radians(45.0f); - const float mesocoxa_fold_angle_x = math::radians(10.0f); - auto fold_mesocoxa_l = math::transform::identity(); - auto fold_mesocoxa_r = math::transform::identity(); - fold_mesocoxa_l.rotation = math::angle_axis(-mesocoxa_fold_angle_z, float3{0, 0, 1}) * math::angle_axis(mesocoxa_fold_angle_y, float3{0, 1, 0}) * math::angle_axis(-mesocoxa_fold_angle_x, float3{1, 0, 0}); - fold_mesocoxa_r.rotation = math::angle_axis(mesocoxa_fold_angle_z, float3{0, 0, 1}) * math::angle_axis(-mesocoxa_fold_angle_y, float3{0, 1, 0}) * math::angle_axis(-mesocoxa_fold_angle_x, float3{1, 0, 0}); - - const float mesofemur_fold_angle = math::radians(90.0f); - auto fold_mesofemur_l = math::transform::identity(); - auto fold_mesofemur_r = math::transform::identity(); - fold_mesofemur_l.rotation = math::angle_axis(mesofemur_fold_angle, float3{1, 0, 0}); - fold_mesofemur_r.rotation = math::angle_axis(mesofemur_fold_angle, float3{1, 0, 0}); - - const float mesotibia_fold_angle = math::radians(162.0f); - auto fold_mesotibia_l = math::transform::identity(); - auto fold_mesotibia_r = math::transform::identity(); - fold_mesotibia_l.rotation = math::angle_axis(-mesotibia_fold_angle, float3{1, 0, 0}); - fold_mesotibia_r.rotation = math::angle_axis(-mesotibia_fold_angle, float3{1, 0, 0}); - - const float mesotarsus_fold_angle = math::radians(20.0f); - auto fold_mesotarsus_l = math::transform::identity(); - auto fold_mesotarsus_r = math::transform::identity(); - fold_mesotarsus_l.rotation = math::angle_axis(-mesotarsus_fold_angle, float3{1, 0, 0}); - fold_mesotarsus_r.rotation = math::angle_axis(-mesotarsus_fold_angle, float3{1, 0, 0}); - - auto mesocoxa_l_bone = *worker_skeleton.get_bone_index("mesocoxa_l"); - auto mesocoxa_r_bone = *worker_skeleton.get_bone_index("mesocoxa_r"); - auto mesofemur_l_bone = *worker_skeleton.get_bone_index("mesofemur_l"); - auto mesofemur_r_bone = *worker_skeleton.get_bone_index("mesofemur_r"); - auto mesotibia_l_bone = *worker_skeleton.get_bone_index("mesotibia_l"); - auto mesotibia_r_bone = *worker_skeleton.get_bone_index("mesotibia_r"); - auto mesotarsus_l_bone = *worker_skeleton.get_bone_index("mesotarsus_l"); - auto mesotarsus_r_bone = *worker_skeleton.get_bone_index("mesotarsus_r"); - - pupal_pose.set_relative_transform(mesocoxa_l_bone, worker_rest_pose.get_relative_transform(mesocoxa_l_bone) * fold_mesocoxa_l); - pupal_pose.set_relative_transform(mesocoxa_r_bone, worker_rest_pose.get_relative_transform(mesocoxa_r_bone) * fold_mesocoxa_r); - pupal_pose.set_relative_transform(mesofemur_l_bone, worker_rest_pose.get_relative_transform(mesofemur_l_bone) * fold_mesofemur_l); - pupal_pose.set_relative_transform(mesofemur_r_bone, worker_rest_pose.get_relative_transform(mesofemur_r_bone) * fold_mesofemur_r); - pupal_pose.set_relative_transform(mesotibia_l_bone, worker_rest_pose.get_relative_transform(mesotibia_l_bone) * fold_mesotibia_l); - pupal_pose.set_relative_transform(mesotibia_r_bone, worker_rest_pose.get_relative_transform(mesotibia_r_bone) * fold_mesotibia_r); - pupal_pose.set_relative_transform(mesotarsus_l_bone, worker_rest_pose.get_relative_transform(mesotarsus_l_bone) * fold_mesotarsus_l); - pupal_pose.set_relative_transform(mesotarsus_r_bone, worker_rest_pose.get_relative_transform(mesotarsus_r_bone) * fold_mesotarsus_r); - } - - // Fold hindlegs - { - const float metacoxa_fold_angle_z = math::radians(15.0f); - const float metacoxa_fold_angle_y = math::radians(10.0f); - const float metacoxa_fold_angle_x = math::radians(25.0f); - auto fold_metacoxa_l = math::transform::identity(); - auto fold_metacoxa_r = math::transform::identity(); - fold_metacoxa_l.rotation = math::angle_axis(-metacoxa_fold_angle_z, float3{0, 0, 1}) * math::angle_axis(-metacoxa_fold_angle_y, float3{0, 1, 0}) * math::angle_axis(metacoxa_fold_angle_x, float3{1, 0, 0}); - fold_metacoxa_r.rotation = math::angle_axis(metacoxa_fold_angle_z, float3{0, 0, 1}) * math::angle_axis(metacoxa_fold_angle_y, float3{0, 1, 0}) * math::angle_axis(metacoxa_fold_angle_x, float3{1, 0, 0}); - - const float metafemur_fold_angle = math::radians(105.0f); - auto fold_metafemur_l = math::transform::identity(); - auto fold_metafemur_r = math::transform::identity(); - fold_metafemur_l.rotation = math::angle_axis(metafemur_fold_angle, float3{1, 0, 0}); - fold_metafemur_r.rotation = math::angle_axis(metafemur_fold_angle, float3{1, 0, 0}); - - const float metatibia_fold_angle = math::radians(165.0f); - auto fold_metatibia_l = math::transform::identity(); - auto fold_metatibia_r = math::transform::identity(); - fold_metatibia_l.rotation = math::angle_axis(-metatibia_fold_angle, float3{1, 0, 0}); - fold_metatibia_r.rotation = math::angle_axis(-metatibia_fold_angle, float3{1, 0, 0}); - - const float metatarsus_fold_angle = math::radians(0.0f); - auto fold_metatarsus_l = math::transform::identity(); - auto fold_metatarsus_r = math::transform::identity(); - fold_metatarsus_l.rotation = math::angle_axis(-metatarsus_fold_angle, float3{1, 0, 0}); - fold_metatarsus_r.rotation = math::angle_axis(-metatarsus_fold_angle, float3{1, 0, 0}); - - auto metacoxa_l_bone = *worker_skeleton.get_bone_index("metacoxa_l"); - auto metacoxa_r_bone = *worker_skeleton.get_bone_index("metacoxa_r"); - auto metafemur_l_bone = *worker_skeleton.get_bone_index("metafemur_l"); - auto metafemur_r_bone = *worker_skeleton.get_bone_index("metafemur_r"); - auto metatibia_l_bone = *worker_skeleton.get_bone_index("metatibia_l"); - auto metatibia_r_bone = *worker_skeleton.get_bone_index("metatibia_r"); - auto metatarsus_l_bone = *worker_skeleton.get_bone_index("metatarsus_l"); - auto metatarsus_r_bone = *worker_skeleton.get_bone_index("metatarsus_r"); - - pupal_pose.set_relative_transform(metacoxa_l_bone, worker_rest_pose.get_relative_transform(metacoxa_l_bone) * fold_metacoxa_l); - pupal_pose.set_relative_transform(metacoxa_r_bone, worker_rest_pose.get_relative_transform(metacoxa_r_bone) * fold_metacoxa_r); - pupal_pose.set_relative_transform(metafemur_l_bone, worker_rest_pose.get_relative_transform(metafemur_l_bone) * fold_metafemur_l); - pupal_pose.set_relative_transform(metafemur_r_bone, worker_rest_pose.get_relative_transform(metafemur_r_bone) * fold_metafemur_r); - pupal_pose.set_relative_transform(metatibia_l_bone, worker_rest_pose.get_relative_transform(metatibia_l_bone) * fold_metatibia_l); - pupal_pose.set_relative_transform(metatibia_r_bone, worker_rest_pose.get_relative_transform(metatibia_r_bone) * fold_metatibia_r); - pupal_pose.set_relative_transform(metatarsus_l_bone, worker_rest_pose.get_relative_transform(metatarsus_l_bone) * fold_metatarsus_l); - pupal_pose.set_relative_transform(metatarsus_r_bone, worker_rest_pose.get_relative_transform(metatarsus_r_bone) * fold_metatarsus_r); - } - - // Fold head - { - const float head_fold_angle = math::radians(80.0f); - auto fold_head = math::transform::identity(); - fold_head.rotation = math::angle_axis(-head_fold_angle, float3{1, 0, 0}); - - auto head_bone = *worker_skeleton.get_bone_index("head"); - - pupal_pose.set_relative_transform(head_bone, worker_rest_pose.get_relative_transform(head_bone) * fold_head); - } - - // Fold antennae - { - const float antennomere1_fold_angle_y = math::radians(70.0f); - const float antennomere1_fold_angle_x = math::radians(45.0f); - auto fold_antennomere1_l = math::transform::identity(); - auto fold_antennomere1_r = math::transform::identity(); - fold_antennomere1_l.rotation = math::angle_axis(-antennomere1_fold_angle_y, float3{0, 1, 0}) * math::angle_axis(-antennomere1_fold_angle_x, float3{1, 0, 0}); - fold_antennomere1_r.rotation = math::angle_axis(antennomere1_fold_angle_y, float3{0, 1, 0}) * math::angle_axis(-antennomere1_fold_angle_x, float3{1, 0, 0}); - - const float antennomere2_fold_angle_y = math::radians(75.0f); - const float antennomere2_fold_angle_x = math::radians(25.0f); - auto fold_antennomere2_l = math::transform::identity(); - auto fold_antennomere2_r = math::transform::identity(); - fold_antennomere2_l.rotation = math::angle_axis(antennomere2_fold_angle_y, float3{0, 1, 0}) * math::angle_axis(-antennomere2_fold_angle_x, float3{1, 0, 0}); - fold_antennomere2_r.rotation = math::angle_axis(-antennomere2_fold_angle_y, float3{0, 1, 0}) * math::angle_axis(-antennomere2_fold_angle_x, float3{1, 0, 0}); - - auto antennomere1_l_bone = *worker_skeleton.get_bone_index("antennomere1_l"); - auto antennomere1_r_bone = *worker_skeleton.get_bone_index("antennomere1_r"); - auto antennomere2_l_bone = *worker_skeleton.get_bone_index("antennomere2_l"); - auto antennomere2_r_bone = *worker_skeleton.get_bone_index("antennomere2_r"); - - pupal_pose.set_relative_transform(antennomere1_l_bone, worker_rest_pose.get_relative_transform(antennomere1_l_bone) * fold_antennomere1_l); - pupal_pose.set_relative_transform(antennomere1_r_bone, worker_rest_pose.get_relative_transform(antennomere1_r_bone) * fold_antennomere1_r); - pupal_pose.set_relative_transform(antennomere2_l_bone, worker_rest_pose.get_relative_transform(antennomere2_l_bone) * fold_antennomere2_l); - pupal_pose.set_relative_transform(antennomere2_r_bone, worker_rest_pose.get_relative_transform(antennomere2_r_bone) * fold_antennomere2_r); - } - - // Fold waist + gaster - { - const float petiole_fold_angle = math::radians(40.0f); - auto fold_petiole = math::transform::identity(); - fold_petiole.rotation = math::angle_axis(petiole_fold_angle, float3{1, 0, 0}); - - const float postpetiole_fold_angle = math::radians(35.0f); - auto fold_postpetiole = math::transform::identity(); - fold_postpetiole.rotation = math::angle_axis(-postpetiole_fold_angle, float3{1, 0, 0}); - - const float gaster_fold_angle = math::radians(0.0f); - auto fold_gaster = math::transform::identity(); - fold_gaster.rotation = math::angle_axis(-gaster_fold_angle, float3{1, 0, 0}); - - auto petiole_bone = worker_skeleton.get_bone_index("petiole"); - auto postpetiole_bone = worker_skeleton.get_bone_index("postpetiole"); - auto gaster_bone = *worker_skeleton.get_bone_index("gaster"); - - if (petiole_bone) - { - pupal_pose.set_relative_transform(*petiole_bone, worker_rest_pose.get_relative_transform(*petiole_bone) * fold_petiole); - } - - if (postpetiole_bone) - { - pupal_pose.set_relative_transform(*postpetiole_bone, worker_rest_pose.get_relative_transform(*postpetiole_bone) * fold_postpetiole); - } - - pupal_pose.set_relative_transform(gaster_bone, worker_rest_pose.get_relative_transform(gaster_bone) * fold_gaster); - } - - // Invert mesosoma - { - const float mesosoma_invert_angle = math::radians(90.0f); - auto invert_mesosoma = math::transform::identity(); - invert_mesosoma.rotation = math::angle_axis(mesosoma_invert_angle, float3{0, 0, 1}); - - auto mesosoma_bone = *worker_skeleton.get_bone_index("mesosoma"); - pupal_pose.set_relative_transform(mesosoma_bone, invert_mesosoma * worker_rest_pose.get_relative_transform(mesosoma_bone)); - } - - pupal_pose.update(); - - auto worker_skeletal_mesh = std::make_unique(worker_model); - //worker_skeletal_mesh->get_pose() = pupal_pose; - worker_ant_eid = ctx.entity_registry->create(); transform_component worker_transform_component; @@ -385,9 +153,14 @@ nest_selection_state::nest_selection_state(::game& ctx): worker_body->set_inertia(0.05f); worker_body->set_angular_damping(0.5f); worker_body->set_collider(std::move(worker_collider)); - //ctx.entity_registry->emplace(worker_ant_eid, std::move(worker_body)); + larva_eid = ctx.entity_registry->create(); + + auto larva_skeletal_mesh = std::make_unique(worker_phenome.larva->model); + ctx.entity_registry->emplace(larva_eid, std::move(larva_skeletal_mesh), std::uint8_t{1}); + + // Disable UI color clear ctx.ui_clear_pass->set_cleared_buffers(false, true, false); @@ -950,7 +723,7 @@ void nest_selection_state::setup_controls() //projectile_scene.object = std::make_shared(ctx.resource_manager->load("capsule.mdl")); auto projectile_mesh = std::make_shared(worker_model); - projectile_mesh->get_pose() = *worker_model->get_skeleton().get_pose("pupal"); + projectile_mesh->get_pose() = *worker_model->get_skeleton().get_pose("pupa"); projectile_scene.object = projectile_mesh; } diff --git a/src/game/states/nest-selection-state.hpp b/src/game/states/nest-selection-state.hpp index 5f73355..b363c62 100644 --- a/src/game/states/nest-selection-state.hpp +++ b/src/game/states/nest-selection-state.hpp @@ -55,6 +55,8 @@ private: entity::id worker_ant_eid; + entity::id larva_eid; + entity::id first_person_camera_rig_eid; float first_person_camera_rig_translation_spring_angular_frequency; float first_person_camera_rig_rotation_spring_angular_frequency;