Browse Source

Make morphogenesis function give ants corect number of ommatidia according to eye phenes

master
C. J. Howard 1 year ago
parent
commit
7a8d613d10
2 changed files with 85 additions and 48 deletions
  1. +0
    -38
      src/engine/physics/ik/ik-solver.hpp
  2. +85
    -10
      src/game/ant/ant-morphogenesis.cpp

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

@ -1,38 +0,0 @@
/*
* 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

+ 85
- 10
src/game/ant/ant-morphogenesis.cpp View File

@ -130,6 +130,43 @@ void tag_vertices
} }
} }
/**
* Calculates the total area of UV coordinates.
*
* @param vertex_data Vertex buffer data.
* @param uv_attribute Vertex UV attribute.
*
* @return Total UV area.
*/
float calculate_uv_area
(
std::span<std::byte> vertex_data,
const gl::vertex_attribute& uv_attribute
)
{
std::byte* uv_data = vertex_data.data() + uv_attribute.offset;
float sum_area = 0.0f;
for (std::size_t i = 0; i + 2 < vertex_data.size(); i += 3)
{
const float* uv_data_a = reinterpret_cast<const float*>(uv_data + uv_attribute.stride * i);
const float* uv_data_b = reinterpret_cast<const float*>(uv_data + uv_attribute.stride * (i + 1));
const float* uv_data_c = reinterpret_cast<const float*>(uv_data + uv_attribute.stride * (i + 2));
const float3 uva = {uv_data_a[0], uv_data_a[1], 0.0f};
const float3 uvb = {uv_data_b[0], uv_data_b[1], 0.0f};
const float3 uvc = {uv_data_c[0], uv_data_c[1], 0.0f};
const float3 uvab = uvb - uva;
const float3 uvac = uvc - uva;
sum_area += math::length(math::cross(uvab, uvac)) * 0.5f;
}
return sum_area;
}
/** /**
* Calculates the bounds of vertex data. * Calculates the bounds of vertex data.
* *
@ -166,28 +203,54 @@ void tag_vertices
return bounds; return bounds;
} }
/**
* Calculates a scale factor which will give ant eyes the desired number of ommatidia.
*
* @param eye_uv_area Total UV area of a single eye.
* @param ommatidia_count Desired number of ommatidia.
*
* @return Ommatidia scale factor.
*/
[[nodiscard]] float calculate_ommatidia_scale(float eye_uv_area, float ommatidia_count)
{
// Side length of hexagon tiles generated by the eye shader
constexpr float source_side_length = 1.0f / math::sqrt_3<float>;
// Side length of hexagon tiles that will fill UV area
const float target_side_length = std::sqrt((eye_uv_area * 2.0f) / (3.0f * math::sqrt_3<float> * ommatidia_count));
return source_side_length / target_side_length;
}
/** /**
* Generates an ant exoskeleton material. * Generates an ant exoskeleton material.
* *
* @param pigmentation Ant pigmentation phene.
* @param sculpturing Ant sculpturing phene.
* @param phenome Ant phenome.
* @param eye_uv_area Total UV area of a single eye.
* *
* @return Generated ant exoskeleton material. * @return Generated ant exoskeleton material.
*/ */
[[nodiscard]] std::unique_ptr<render::material> generate_ant_exoskeleton_material [[nodiscard]] std::unique_ptr<render::material> generate_ant_exoskeleton_material
( (
const ant_pigmentation_phene& pigmentation,
const ant_sculpturing_phene& sculpturing
const ant_phenome& phenome,
float eye_uv_area
) )
{ {
// Allocate copy of pigmentation material // Allocate copy of pigmentation material
std::unique_ptr<render::material> exoskeleton_material = std::make_unique<render::material>(*pigmentation.material);
std::unique_ptr<render::material> exoskeleton_material = std::make_unique<render::material>(*phenome.pigmentation->material);
// Set roughness variable // Set roughness variable
exoskeleton_material->set_variable("roughness", std::make_shared<render::material_float>(1, sculpturing.roughness));
exoskeleton_material->set_variable("exoskeleton_roughness", std::make_shared<render::material_float>(1, phenome.sculpturing->roughness));
// Set normal map variable // Set normal map variable
exoskeleton_material->set_variable("normal_map", std::make_shared<render::material_texture_2d>(1, sculpturing.normal_map));
exoskeleton_material->set_variable("exoskeleton_normal_map", std::make_shared<render::material_texture_2d>(1, phenome.sculpturing->normal_map));
if (phenome.eyes->present)
{
// Set ommatidia scale variable
const float ommatidia_scale = calculate_ommatidia_scale(eye_uv_area, static_cast<float>(phenome.eyes->ommatidia_count));
exoskeleton_material->set_variable("ommatidia_scale", std::make_shared<render::material_float>(1, ommatidia_scale));
}
return exoskeleton_material; return exoskeleton_material;
} }
@ -196,9 +259,6 @@ void tag_vertices
std::unique_ptr<render::model> ant_morphogenesis(const ant_phenome& phenome) std::unique_ptr<render::model> ant_morphogenesis(const ant_phenome& phenome)
{ {
// Generate exoskeleton material
std::shared_ptr<render::material> exoskeleton_material = generate_ant_exoskeleton_material(*phenome.pigmentation, *phenome.sculpturing);
// Get body part models // Get body part models
const render::model* mesosoma_model = phenome.mesosoma->model.get(); const render::model* mesosoma_model = phenome.mesosoma->model.get();
const render::model* legs_model = phenome.legs->model.get(); const render::model* legs_model = phenome.legs->model.get();
@ -378,6 +438,7 @@ std::unique_ptr ant_morphogenesis(const ant_phenome& phenome)
// Get vertex attributes // Get vertex attributes
const gl::vertex_attribute* position_attribute = nullptr; const gl::vertex_attribute* position_attribute = nullptr;
const gl::vertex_attribute* uv_attribute = nullptr;
const gl::vertex_attribute* normal_attribute = nullptr; const gl::vertex_attribute* normal_attribute = nullptr;
const gl::vertex_attribute* tangent_attribute = nullptr; const gl::vertex_attribute* tangent_attribute = nullptr;
const gl::vertex_attribute* bone_index_attribute = nullptr; const gl::vertex_attribute* bone_index_attribute = nullptr;
@ -386,6 +447,10 @@ std::unique_ptr ant_morphogenesis(const ant_phenome& phenome)
{ {
position_attribute = &it->second; position_attribute = &it->second;
} }
if (auto it = vertex_attribute_map.find(render::vertex_attribute::uv); it != vertex_attribute_map.end())
{
uv_attribute = &it->second;
}
if (auto it = vertex_attribute_map.find(render::vertex_attribute::normal); it != vertex_attribute_map.end()) if (auto it = vertex_attribute_map.find(render::vertex_attribute::normal); it != vertex_attribute_map.end())
{ {
normal_attribute = &it->second; normal_attribute = &it->second;
@ -715,6 +780,16 @@ std::unique_ptr ant_morphogenesis(const ant_phenome& phenome)
// Allocate model groups // Allocate model groups
model->get_groups().resize(1); model->get_groups().resize(1);
// Calculate UV area of a single eye
float eye_uv_area = 0.0f;
if (phenome.eyes->present)
{
eye_uv_area = calculate_uv_area({vertex_buffer_data.data() + eyes_vbo_offset, vertex_buffer_data.data() + eyes_vbo_offset + eyes_vertex_count / 2}, *uv_attribute);
}
// Generate exoskeleton material
std::shared_ptr<render::material> exoskeleton_material = generate_ant_exoskeleton_material(phenome, eye_uv_area);
// Construct model group // Construct model group
render::model_group& model_group = model->get_groups()[0]; render::model_group& model_group = model->get_groups()[0];
model_group.id = "exoskeleton"; model_group.id = "exoskeleton";

Loading…
Cancel
Save