Browse Source

Make pose generation part of morphogenesis function

master
C. J. Howard 1 year ago
parent
commit
f8ae34d37e
9 changed files with 836 additions and 780 deletions
  1. +0
    -1
      CMakeLists.txt
  2. +14
    -26
      src/engine/geom/closest-point.hpp
  3. +38
    -0
      src/engine/physics/ik/ik-solver.hpp
  4. +73
    -0
      src/game/ant/ant-bone-set.hpp
  5. +87
    -519
      src/game/ant/ant-morphogenesis.cpp
  6. +528
    -0
      src/game/ant/ant-skeleton.cpp
  7. +87
    -0
      src/game/ant/ant-skeleton.hpp
  8. +7
    -234
      src/game/states/nest-selection-state.cpp
  9. +2
    -0
      src/game/states/nest-selection-state.hpp

+ 0
- 1
CMakeLists.txt View File

@ -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")

+ 14
- 26
src/engine/geom/closest-point.hpp View File

@ -45,7 +45,7 @@ namespace geom {
* @return Closest point on ray a to point b.
*/
template <class T, std::size_t N>
[[nodiscard]] point<T, N> closest_point(const ray<T, N>& a, const point<T, N>& b) noexcept
[[nodiscard]] constexpr point<T, N> closest_point(const ray<T, N>& a, const point<T, N>& b) noexcept
{
return a.extrapolate(std::max<T>(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 <class T, std::size_t N>
[[nodiscard]] point<T, N> closest_point(const line_segment<T, N>& ab, const point<T, N>& c) noexcept
[[nodiscard]] constexpr point<T, N> closest_point(const line_segment<T, N>& ab, const point<T, N>& 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 <class T, std::size_t N>
[[nodiscard]] std::tuple<point<T, N>, point<T, N>> closest_point(const line_segment<T, N>& ab, const line_segment<T, N>& cd) noexcept
[[nodiscard]] constexpr std::tuple<point<T, N>, point<T, N>> closest_point(const line_segment<T, N>& ab, const line_segment<T, N>& 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 <class T, std::size_t N>
[[nodiscard]] point<T, N> closest_point(const hyperplane<T, N>& a, const point<T, N>& b) noexcept
[[nodiscard]] constexpr point<T, N> closest_point(const hyperplane<T, N>& a, const point<T, N>& 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 <class T, std::size_t N>
[[nodiscard]] point<T, N> closest_point(const hypersphere<T, N>& a, const point<T, N>& 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 <class T, std::size_t N>
[[nodiscard]] point<T, N> closest_point(const hypercapsule<T, N>& a, const point<T, N>& 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 <class T, std::size_t N>
[[nodiscard]] point<T, N> closest_point(const hyperrectangle<T, N>& a, const point<T, N>& b) noexcept
[[nodiscard]] constexpr point<T, N> closest_point(const hyperrectangle<T, N>& a, const point<T, N>& 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<T>(math::max(d), T{0});
point<T, N> 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

+ 38
- 0
src/engine/physics/ik/ik-solver.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_PHYSICS_IK_SOLVER_HPP
#define ANTKEEPER_PHYSICS_IK_SOLVER_HPP
#include <engine/math/transform.hpp>
namespace physics {
/**
*
*/
class ik_solver
{
public:
};
} // namespace physics
#endif // ANTKEEPER_PHYSICS_IK_SOLVER_HPP

+ 73
- 0
src/game/ant/ant-bone-set.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_GAME_ANT_BONE_SET_HPP
#define ANTKEEPER_GAME_ANT_BONE_SET_HPP
#include <engine/animation/bone.hpp>
#include <optional>
/**
* Set of bone indices for all possible bones in an ant skeleotn.
*/
struct ant_bone_set
{
std::optional<bone_index_type> mesosoma;
std::optional<bone_index_type> procoxa_l;
std::optional<bone_index_type> profemur_l;
std::optional<bone_index_type> protibia_l;
std::optional<bone_index_type> protarsus_l;
std::optional<bone_index_type> procoxa_r;
std::optional<bone_index_type> profemur_r;
std::optional<bone_index_type> protibia_r;
std::optional<bone_index_type> protarsus_r;
std::optional<bone_index_type> mesocoxa_l;
std::optional<bone_index_type> mesofemur_l;
std::optional<bone_index_type> mesotibia_l;
std::optional<bone_index_type> mesotarsus_l;
std::optional<bone_index_type> mesocoxa_r;
std::optional<bone_index_type> mesofemur_r;
std::optional<bone_index_type> mesotibia_r;
std::optional<bone_index_type> mesotarsus_r;
std::optional<bone_index_type> metacoxa_l;
std::optional<bone_index_type> metafemur_l;
std::optional<bone_index_type> metatibia_l;
std::optional<bone_index_type> metatarsus_l;
std::optional<bone_index_type> metacoxa_r;
std::optional<bone_index_type> metafemur_r;
std::optional<bone_index_type> metatibia_r;
std::optional<bone_index_type> metatarsus_r;
std::optional<bone_index_type> head;
std::optional<bone_index_type> mandible_l;
std::optional<bone_index_type> mandible_r;
std::optional<bone_index_type> antennomere1_l;
std::optional<bone_index_type> antennomere2_l;
std::optional<bone_index_type> antennomere1_r;
std::optional<bone_index_type> antennomere2_r;
std::optional<bone_index_type> petiole;
std::optional<bone_index_type> postpetiole;
std::optional<bone_index_type> gaster;
std::optional<bone_index_type> sting;
std::optional<bone_index_type> forewing_l;
std::optional<bone_index_type> forewing_r;
std::optional<bone_index_type> hindwing_l;
std::optional<bone_index_type> hindwing_r;
};
#endif // ANTKEEPER_GAME_ANT_BONE_SET_HPP

+ 87
- 519
src/game/ant/ant-morphogenesis.cpp View File

@ -18,6 +18,8 @@
*/
#include "game/ant/ant-morphogenesis.hpp"
#include "game/ant/ant-bone-set.hpp"
#include "game/ant/ant-skeleton.hpp"
#include <engine/render/material.hpp>
#include <engine/render/vertex-attribute.hpp>
#include <engine/math/quaternion.hpp>
@ -29,51 +31,6 @@
namespace {
/// Set of pointers to all possible ant skeleton bones.
struct ant_bone_set
{
std::optional<bone_index_type> mesosoma;
std::optional<bone_index_type> procoxa_l;
std::optional<bone_index_type> profemur_l;
std::optional<bone_index_type> protibia_l;
std::optional<bone_index_type> protarsus_l;
std::optional<bone_index_type> procoxa_r;
std::optional<bone_index_type> profemur_r;
std::optional<bone_index_type> protibia_r;
std::optional<bone_index_type> protarsus_r;
std::optional<bone_index_type> mesocoxa_l;
std::optional<bone_index_type> mesofemur_l;
std::optional<bone_index_type> mesotibia_l;
std::optional<bone_index_type> mesotarsus_l;
std::optional<bone_index_type> mesocoxa_r;
std::optional<bone_index_type> mesofemur_r;
std::optional<bone_index_type> mesotibia_r;
std::optional<bone_index_type> mesotarsus_r;
std::optional<bone_index_type> metacoxa_l;
std::optional<bone_index_type> metafemur_l;
std::optional<bone_index_type> metatibia_l;
std::optional<bone_index_type> metatarsus_l;
std::optional<bone_index_type> metacoxa_r;
std::optional<bone_index_type> metafemur_r;
std::optional<bone_index_type> metatibia_r;
std::optional<bone_index_type> metatarsus_r;
std::optional<bone_index_type> head;
std::optional<bone_index_type> mandible_l;
std::optional<bone_index_type> mandible_r;
std::optional<bone_index_type> antennomere1_l;
std::optional<bone_index_type> antennomere2_l;
std::optional<bone_index_type> antennomere1_r;
std::optional<bone_index_type> antennomere2_r;
std::optional<bone_index_type> petiole;
std::optional<bone_index_type> postpetiole;
std::optional<bone_index_type> gaster;
std::optional<bone_index_type> sting;
std::optional<bone_index_type> forewing_l;
std::optional<bone_index_type> forewing_r;
std::optional<bone_index_type> hindwing_l;
std::optional<bone_index_type> 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<std::uint32_t&>(*(bone_index_data + bone_index_attribute.stride * i));
std::uint16_t& bone_index = reinterpret_cast<std::uint16_t&>(*(bone_index_data + bone_index_attribute.stride * i));
// Ignore vertices with unmapped bone indices
auto entry = reskin_map.find(static_cast<bone_index_type>(bone_index));
@ -116,17 +73,60 @@ void reskin_vertices
const auto& [new_bone_index, transform] = entry->second;
// Update bone index
bone_index = static_cast<std::uint32_t>(new_bone_index);
bone_index = static_cast<std::uint16_t>(new_bone_index);
// Get vertex attributes
float3& position = reinterpret_cast<float3&>(*(position_data + position_attribute.stride * i));
float3& normal = reinterpret_cast<float3&>(*(normal_data + normal_attribute.stride * i));
float3& tangent = reinterpret_cast<float3&>(*(tangent_data + tangent_attribute.stride * i));
float* px = reinterpret_cast<float*>(position_data + position_attribute.stride * i);
float* py = px + 1;
float* pz = py + 1;
float* nx = reinterpret_cast<float*>(normal_data + normal_attribute.stride * i);
float* ny = nx + 1;
float* nz = ny + 1;
float* tx = reinterpret_cast<float*>(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<std::byte> 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<std::uint16_t*>(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<const float3&>(*(position_data + position_attribute.stride * i));
bounds.extend(position);
const float* px = reinterpret_cast<const float*>(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<render::model> 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;
}

+ 528
- 0
src/game/ant/ant-skeleton.cpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include "game/ant/ant-skeleton.hpp"
#include "game/ant/ant-bone-set.hpp"
#include <engine/math/angles.hpp>
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<float>::identity();
auto fold_procoxa_r = math::transform<float>::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<float>::identity();
auto fold_profemur_r = math::transform<float>::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<float>::identity();
auto fold_protibia_r = math::transform<float>::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<float>::identity();
auto fold_protarsus_r = math::transform<float>::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<float>::identity();
auto fold_mesocoxa_r = math::transform<float>::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<float>::identity();
auto fold_mesofemur_r = math::transform<float>::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<float>::identity();
auto fold_mesotibia_r = math::transform<float>::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<float>::identity();
auto fold_mesotarsus_r = math::transform<float>::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<float>::identity();
auto fold_metacoxa_r = math::transform<float>::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<float>::identity();
auto fold_metafemur_r = math::transform<float>::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<float>::identity();
auto fold_metatibia_r = math::transform<float>::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<float>::identity();
auto fold_metatarsus_r = math::transform<float>::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<float>::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<float>::identity();
auto fold_antennomere1_r = math::transform<float>::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<float>::identity();
auto fold_antennomere2_r = math::transform<float>::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<float>::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<float>::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<float>::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<float>::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);
}

+ 87
- 0
src/game/ant/ant-skeleton.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_GAME_ANT_SKELETON_HPP
#define ANTKEEPER_GAME_ANT_SKELETON_HPP
#include <engine/animation/skeleton.hpp>
#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

+ 7
- 234
src/game/states/nest-selection-state.cpp View File

@ -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<float>::identity();
auto fold_procoxa_r = math::transform<float>::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<float>::identity();
auto fold_profemur_r = math::transform<float>::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<float>::identity();
auto fold_protibia_r = math::transform<float>::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<float>::identity();
auto fold_protarsus_r = math::transform<float>::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<float>::identity();
auto fold_mesocoxa_r = math::transform<float>::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<float>::identity();
auto fold_mesofemur_r = math::transform<float>::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<float>::identity();
auto fold_mesotibia_r = math::transform<float>::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<float>::identity();
auto fold_mesotarsus_r = math::transform<float>::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<float>::identity();
auto fold_metacoxa_r = math::transform<float>::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<float>::identity();
auto fold_metafemur_r = math::transform<float>::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<float>::identity();
auto fold_metatibia_r = math::transform<float>::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<float>::identity();
auto fold_metatarsus_r = math::transform<float>::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<float>::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<float>::identity();
auto fold_antennomere1_r = math::transform<float>::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<float>::identity();
auto fold_antennomere2_r = math::transform<float>::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<float>::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<float>::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<float>::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<float>::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<scene::skeletal_mesh>(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<rigid_body_component>(worker_ant_eid, std::move(worker_body));
larva_eid = ctx.entity_registry->create();
auto larva_skeletal_mesh = std::make_unique<scene::skeletal_mesh>(worker_phenome.larva->model);
ctx.entity_registry->emplace<scene_component>(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<scene::static_mesh>(ctx.resource_manager->load<render::model>("capsule.mdl"));
auto projectile_mesh = std::make_shared<scene::skeletal_mesh>(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;
}

+ 2
- 0
src/game/states/nest-selection-state.hpp View File

@ -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;

Loading…
Cancel
Save