|
|
@ -19,6 +19,9 @@ |
|
|
|
|
|
|
|
#include "game/ant/morphogenesis.hpp"
|
|
|
|
#include "render/material.hpp"
|
|
|
|
#include "render/vertex-attribute.hpp"
|
|
|
|
#include <unordered_set>
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
namespace game { |
|
|
|
namespace ant { |
|
|
@ -27,22 +30,39 @@ static render::model* generate_queen(const ant::breed& breed); |
|
|
|
static render::model* generate_worker(const ant::breed& breed); |
|
|
|
static render::model* generate_soldier(const ant::breed& breed); |
|
|
|
static render::model* generate_male(const ant::breed& breed); |
|
|
|
static render::material* build_material(const ant::breed& breed); |
|
|
|
static render::material* build_exoskeleton_material |
|
|
|
( |
|
|
|
const ant::trait::pigmentation& pigmentation, |
|
|
|
const ant::trait::sculpturing& sculpturing |
|
|
|
); |
|
|
|
static void reskin_vertices |
|
|
|
( |
|
|
|
std::uint8_t* vertex_data, |
|
|
|
std::size_t index_count, |
|
|
|
const gl::vertex_attribute& position_attribute, |
|
|
|
const gl::vertex_attribute& normal_attribute, |
|
|
|
const gl::vertex_attribute& tangent_attribute, |
|
|
|
const gl::vertex_attribute& bone_index_attribute, |
|
|
|
const std::unordered_set<std::uint16_t>& old_bone_indices, |
|
|
|
std::uint16_t new_bone_index, |
|
|
|
const math::transform<float>& transform |
|
|
|
); |
|
|
|
static geom::aabb<float> calculate_bounds(std::uint8_t* vertex_data, std::size_t index_count, const gl::vertex_attribute& position_attribute); |
|
|
|
static render::model* build_model |
|
|
|
( |
|
|
|
render::material* material, |
|
|
|
render::model* antennae, |
|
|
|
render::model* eyes, |
|
|
|
render::model* forewings, |
|
|
|
render::model* gaster, |
|
|
|
render::model* head, |
|
|
|
render::model* hindwings, |
|
|
|
render::model* legs, |
|
|
|
render::model* mandibles, |
|
|
|
render::model* mesosoma, |
|
|
|
render::model* ocelli, |
|
|
|
render::model* sting, |
|
|
|
render::model* waist |
|
|
|
const render::model* antennae, |
|
|
|
const render::model* eyes, |
|
|
|
const render::model* forewings, |
|
|
|
const render::model* gaster, |
|
|
|
const render::model* head, |
|
|
|
const render::model* hindwings, |
|
|
|
const render::model* legs, |
|
|
|
const render::model* mandibles, |
|
|
|
const render::model* mesosoma, |
|
|
|
const render::model* ocelli, |
|
|
|
const render::model* sting, |
|
|
|
const render::model* waist |
|
|
|
); |
|
|
|
|
|
|
|
render::model* morphogenesis(const ant::breed& breed, ant::caste caste) |
|
|
@ -72,8 +92,8 @@ render::model* generate_worker(const ant::breed& breed) |
|
|
|
// Get material parameters
|
|
|
|
|
|
|
|
|
|
|
|
// Build material
|
|
|
|
render::material* material = build_material(breed); |
|
|
|
// Build exoskeleton material
|
|
|
|
render::material* exoskeleton_material = build_exoskeleton_material(*breed.pigmentation, *breed.sculpturing); |
|
|
|
|
|
|
|
// Get worker body part models
|
|
|
|
render::model* antennae_model = breed.antennae->model; |
|
|
@ -89,7 +109,7 @@ render::model* generate_worker(const ant::breed& breed) |
|
|
|
// Build worker model
|
|
|
|
render::model* model = build_model |
|
|
|
( |
|
|
|
material, |
|
|
|
exoskeleton_material, |
|
|
|
antennae_model, |
|
|
|
eyes_model, |
|
|
|
nullptr, |
|
|
@ -118,31 +138,709 @@ render::model* generate_male(const ant::breed& breed) |
|
|
|
return nullptr; |
|
|
|
} |
|
|
|
|
|
|
|
render::material* build_material(const ant::breed& breed) |
|
|
|
render::material* build_exoskeleton_material |
|
|
|
( |
|
|
|
const ant::trait::pigmentation& pigmentation, |
|
|
|
const ant::trait::sculpturing& sculpturing |
|
|
|
) |
|
|
|
{ |
|
|
|
return nullptr; |
|
|
|
// Allocate copy of pigmentation material
|
|
|
|
render::material* exoskeleton_material = new render::material(*pigmentation.material); |
|
|
|
|
|
|
|
// Adjust roughness parameter
|
|
|
|
if (render::material_property_base* property = exoskeleton_material->get_property("roughness"); property != nullptr) |
|
|
|
{ |
|
|
|
static_cast<render::material_property<float>*>(property)->set_value(sculpturing.roughness); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
exoskeleton_material->add_property<float>("roughness")->set_value(sculpturing.roughness); |
|
|
|
} |
|
|
|
|
|
|
|
// Adjust normal map parameter
|
|
|
|
if (render::material_property_base* property = exoskeleton_material->get_property("normal_map"); property != nullptr) |
|
|
|
{ |
|
|
|
static_cast<render::material_property<const gl::texture_2d*>*>(property)->set_value(sculpturing.normal_map); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
exoskeleton_material->add_property<const gl::texture_2d*>("normal_map")->set_value(sculpturing.normal_map); |
|
|
|
} |
|
|
|
|
|
|
|
return exoskeleton_material; |
|
|
|
} |
|
|
|
|
|
|
|
render::model* build_model |
|
|
|
( |
|
|
|
render::material* material, |
|
|
|
render::model* antennae, |
|
|
|
render::model* eyes, |
|
|
|
render::model* forewings, |
|
|
|
render::model* gaster, |
|
|
|
render::model* head, |
|
|
|
render::model* hindwings, |
|
|
|
render::model* legs, |
|
|
|
render::model* mandibles, |
|
|
|
render::model* mesosoma, |
|
|
|
render::model* ocelli, |
|
|
|
render::model* sting, |
|
|
|
render::model* waist |
|
|
|
render::material* exoskeleton_material, |
|
|
|
const render::model* antennae, |
|
|
|
const render::model* eyes, |
|
|
|
const render::model* forewings, |
|
|
|
const render::model* gaster, |
|
|
|
const render::model* head, |
|
|
|
const render::model* hindwings, |
|
|
|
const render::model* legs, |
|
|
|
const render::model* mandibles, |
|
|
|
const render::model* mesosoma, |
|
|
|
const render::model* ocelli, |
|
|
|
const render::model* sting, |
|
|
|
const render::model* waist |
|
|
|
) |
|
|
|
{ |
|
|
|
return nullptr; |
|
|
|
// Get vertex buffers of required body parts
|
|
|
|
const gl::vertex_buffer* mesosoma_vbo = mesosoma->get_vertex_buffer(); |
|
|
|
const gl::vertex_buffer* legs_vbo = legs->get_vertex_buffer(); |
|
|
|
const gl::vertex_buffer* head_vbo = head->get_vertex_buffer(); |
|
|
|
const gl::vertex_buffer* mandibles_vbo = mandibles->get_vertex_buffer(); |
|
|
|
const gl::vertex_buffer* antennae_vbo = antennae->get_vertex_buffer(); |
|
|
|
const gl::vertex_buffer* waist_vbo = waist->get_vertex_buffer(); |
|
|
|
const gl::vertex_buffer* gaster_vbo = gaster->get_vertex_buffer(); |
|
|
|
|
|
|
|
// Get vertex buffers of optional body parts
|
|
|
|
const gl::vertex_buffer* sting_vbo = (sting) ? sting->get_vertex_buffer() : nullptr; |
|
|
|
const gl::vertex_buffer* eyes_vbo = (eyes) ? eyes->get_vertex_buffer() : nullptr; |
|
|
|
const gl::vertex_buffer* ocelli_vbo = (ocelli) ? ocelli->get_vertex_buffer() : nullptr; |
|
|
|
const gl::vertex_buffer* forewings_vbo = (forewings) ? forewings->get_vertex_buffer() : nullptr; |
|
|
|
const gl::vertex_buffer* hindwings_vbo = (hindwings) ? hindwings->get_vertex_buffer() : nullptr; |
|
|
|
|
|
|
|
// Determine combined size of vertex buffers and save offsets
|
|
|
|
std::size_t vertex_buffer_size = 0; |
|
|
|
std::size_t mesosoma_vbo_offset = vertex_buffer_size; |
|
|
|
vertex_buffer_size += mesosoma_vbo->get_size(); |
|
|
|
std::size_t legs_vbo_offset = vertex_buffer_size; |
|
|
|
vertex_buffer_size += legs_vbo->get_size(); |
|
|
|
std::size_t head_vbo_offset = vertex_buffer_size; |
|
|
|
vertex_buffer_size += head_vbo->get_size(); |
|
|
|
std::size_t mandibles_vbo_offset = vertex_buffer_size; |
|
|
|
vertex_buffer_size += mandibles_vbo->get_size(); |
|
|
|
std::size_t antennae_vbo_offset = vertex_buffer_size; |
|
|
|
vertex_buffer_size += antennae_vbo->get_size(); |
|
|
|
std::size_t waist_vbo_offset = vertex_buffer_size; |
|
|
|
vertex_buffer_size += waist_vbo->get_size(); |
|
|
|
std::size_t gaster_vbo_offset = vertex_buffer_size; |
|
|
|
vertex_buffer_size += gaster_vbo->get_size(); |
|
|
|
std::size_t sting_vbo_offset = vertex_buffer_size; |
|
|
|
if (sting) |
|
|
|
vertex_buffer_size += sting_vbo->get_size(); |
|
|
|
std::size_t eyes_vbo_offset = vertex_buffer_size; |
|
|
|
if (eyes) |
|
|
|
vertex_buffer_size += eyes_vbo->get_size(); |
|
|
|
std::size_t ocelli_vbo_offset = vertex_buffer_size; |
|
|
|
if (ocelli) |
|
|
|
vertex_buffer_size += ocelli_vbo->get_size(); |
|
|
|
std::size_t forewings_vbo_offset = vertex_buffer_size; |
|
|
|
if (forewings) |
|
|
|
vertex_buffer_size += forewings_vbo->get_size(); |
|
|
|
std::size_t hindwings_vbo_offset = vertex_buffer_size; |
|
|
|
if (hindwings) |
|
|
|
vertex_buffer_size += hindwings_vbo->get_size(); |
|
|
|
|
|
|
|
// Allocate combined vertex buffer data
|
|
|
|
std::uint8_t* vertex_buffer_data = new std::uint8_t[vertex_buffer_size]; |
|
|
|
|
|
|
|
// Read body part vertex buffer data into combined vertex buffer data
|
|
|
|
mesosoma_vbo->read(0, mesosoma_vbo->get_size(), vertex_buffer_data + mesosoma_vbo_offset); |
|
|
|
legs_vbo->read(0, legs_vbo->get_size(), vertex_buffer_data + legs_vbo_offset); |
|
|
|
head_vbo->read(0, head_vbo->get_size(), vertex_buffer_data + head_vbo_offset); |
|
|
|
mandibles_vbo->read(0, mandibles_vbo->get_size(), vertex_buffer_data + mandibles_vbo_offset); |
|
|
|
antennae_vbo->read(0, antennae_vbo->get_size(), vertex_buffer_data + antennae_vbo_offset); |
|
|
|
waist_vbo->read(0, waist_vbo->get_size(), vertex_buffer_data + waist_vbo_offset); |
|
|
|
gaster_vbo->read(0, gaster_vbo->get_size(), vertex_buffer_data + gaster_vbo_offset); |
|
|
|
if (sting) |
|
|
|
sting_vbo->read(0, sting_vbo->get_size(), vertex_buffer_data + sting_vbo_offset); |
|
|
|
if (eyes) |
|
|
|
eyes_vbo->read(0, eyes_vbo->get_size(), vertex_buffer_data + eyes_vbo_offset); |
|
|
|
if (ocelli) |
|
|
|
ocelli_vbo->read(0, ocelli_vbo->get_size(), vertex_buffer_data + ocelli_vbo_offset); |
|
|
|
if (forewings) |
|
|
|
forewings_vbo->read(0, forewings_vbo->get_size(), vertex_buffer_data + forewings_vbo_offset); |
|
|
|
if (hindwings) |
|
|
|
hindwings_vbo->read(0, hindwings_vbo->get_size(), vertex_buffer_data + hindwings_vbo_offset); |
|
|
|
|
|
|
|
// Allocate model
|
|
|
|
render::model* model = new render::model(); |
|
|
|
|
|
|
|
// Setup model VAO
|
|
|
|
gl::vertex_array* model_vao = model->get_vertex_array(); |
|
|
|
for (auto [location, attribute]: mesosoma->get_vertex_array()->get_attributes()) |
|
|
|
{ |
|
|
|
attribute.buffer = model->get_vertex_buffer(); |
|
|
|
model_vao->bind(location, attribute); |
|
|
|
} |
|
|
|
|
|
|
|
// Get vertex attributes
|
|
|
|
const gl::vertex_attribute* position_attribute = nullptr; |
|
|
|
const gl::vertex_attribute* normal_attribute = nullptr; |
|
|
|
const gl::vertex_attribute* tangent_attribute = nullptr; |
|
|
|
const gl::vertex_attribute* bone_index_attribute = nullptr; |
|
|
|
const auto& vertex_attribute_map = model_vao->get_attributes(); |
|
|
|
if (auto it = vertex_attribute_map.find(render::vertex_attribute::position); it != vertex_attribute_map.end()) |
|
|
|
position_attribute = &it->second; |
|
|
|
if (auto it = vertex_attribute_map.find(render::vertex_attribute::normal); it != vertex_attribute_map.end()) |
|
|
|
normal_attribute = &it->second; |
|
|
|
if (auto it = vertex_attribute_map.find(render::vertex_attribute::tangent); it != vertex_attribute_map.end()) |
|
|
|
tangent_attribute = &it->second; |
|
|
|
if (auto it = vertex_attribute_map.find(render::vertex_attribute::bone_index); it != vertex_attribute_map.end()) |
|
|
|
bone_index_attribute = &it->second; |
|
|
|
|
|
|
|
// Get body part skeletons
|
|
|
|
const render::skeleton& mesosoma_skeleton = mesosoma->get_skeleton(); |
|
|
|
const render::skeleton& legs_skeleton = legs->get_skeleton(); |
|
|
|
const render::skeleton& head_skeleton = head->get_skeleton(); |
|
|
|
const render::skeleton& mandibles_skeleton = mandibles->get_skeleton(); |
|
|
|
const render::skeleton& antennae_skeleton = antennae->get_skeleton(); |
|
|
|
const render::skeleton& waist_skeleton = waist->get_skeleton(); |
|
|
|
const render::skeleton& gaster_skeleton = gaster->get_skeleton(); |
|
|
|
const render::skeleton* sting_skeleton = (sting) ? &sting->get_skeleton() : nullptr; |
|
|
|
const render::skeleton* eyes_skeleton = (eyes) ? &eyes->get_skeleton() : nullptr; |
|
|
|
const render::skeleton* ocelli_skeleton = (ocelli) ? &ocelli->get_skeleton() : nullptr; |
|
|
|
bool postpetiole = (waist_skeleton.bone_map.find("postpetiole") != waist_skeleton.bone_map.end()); |
|
|
|
|
|
|
|
// Allocate skeleton bones
|
|
|
|
render::skeleton& skeleton = model->get_skeleton(); |
|
|
|
std::size_t bone_count = 34; |
|
|
|
if (postpetiole) |
|
|
|
bone_count += 1; |
|
|
|
if (sting) |
|
|
|
bone_count += 1; |
|
|
|
if (forewings) |
|
|
|
bone_count += 2; |
|
|
|
if (hindwings) |
|
|
|
bone_count += 2; |
|
|
|
skeleton.bones.resize(bone_count); |
|
|
|
|
|
|
|
// Assign bone indices
|
|
|
|
std::uint16_t bone_index = 0; |
|
|
|
std::uint16_t mesosoma_bone_index = bone_index++; |
|
|
|
std::uint16_t foreleg_coxa_l_bone_index = bone_index++; |
|
|
|
std::uint16_t foreleg_coxa_r_bone_index = bone_index++; |
|
|
|
std::uint16_t foreleg_femur_l_bone_index = bone_index++; |
|
|
|
std::uint16_t foreleg_femur_r_bone_index = bone_index++; |
|
|
|
std::uint16_t foreleg_tibia_l_bone_index = bone_index++; |
|
|
|
std::uint16_t foreleg_tibia_r_bone_index = bone_index++; |
|
|
|
std::uint16_t foreleg_tarsus_l_bone_index = bone_index++; |
|
|
|
std::uint16_t foreleg_tarsus_r_bone_index = bone_index++; |
|
|
|
std::uint16_t midleg_coxa_l_bone_index = bone_index++; |
|
|
|
std::uint16_t midleg_coxa_r_bone_index = bone_index++; |
|
|
|
std::uint16_t midleg_femur_l_bone_index = bone_index++; |
|
|
|
std::uint16_t midleg_femur_r_bone_index = bone_index++; |
|
|
|
std::uint16_t midleg_tibia_l_bone_index = bone_index++; |
|
|
|
std::uint16_t midleg_tibia_r_bone_index = bone_index++; |
|
|
|
std::uint16_t midleg_tarsus_l_bone_index = bone_index++; |
|
|
|
std::uint16_t midleg_tarsus_r_bone_index = bone_index++; |
|
|
|
std::uint16_t hindleg_coxa_l_bone_index = bone_index++; |
|
|
|
std::uint16_t hindleg_coxa_r_bone_index = bone_index++; |
|
|
|
std::uint16_t hindleg_femur_l_bone_index = bone_index++; |
|
|
|
std::uint16_t hindleg_femur_r_bone_index = bone_index++; |
|
|
|
std::uint16_t hindleg_tibia_l_bone_index = bone_index++; |
|
|
|
std::uint16_t hindleg_tibia_r_bone_index = bone_index++; |
|
|
|
std::uint16_t hindleg_tarsus_l_bone_index = bone_index++; |
|
|
|
std::uint16_t hindleg_tarsus_r_bone_index = bone_index++; |
|
|
|
std::uint16_t head_bone_index = bone_index++; |
|
|
|
std::uint16_t mandible_l_bone_index = bone_index++; |
|
|
|
std::uint16_t mandible_r_bone_index = bone_index++; |
|
|
|
std::uint16_t scape_l_bone_index = bone_index++; |
|
|
|
std::uint16_t scape_r_bone_index = bone_index++; |
|
|
|
std::uint16_t pedicel_l_bone_index = bone_index++; |
|
|
|
std::uint16_t pedicel_r_bone_index = bone_index++; |
|
|
|
std::uint16_t petiole_bone_index = bone_index++; |
|
|
|
std::uint16_t postpetiole_bone_index = (postpetiole) ? bone_index++ : static_cast<std::uint16_t>(bone_count); |
|
|
|
std::uint16_t gaster_bone_index = bone_index++; |
|
|
|
std::uint16_t sting_bone_index = (sting) ? bone_index++ : static_cast<std::uint16_t>(bone_count); |
|
|
|
|
|
|
|
// Get references and pointers to bones
|
|
|
|
render::bone& mesosoma_bone = skeleton.bones[mesosoma_bone_index]; |
|
|
|
render::bone& foreleg_coxa_l_bone = skeleton.bones[foreleg_coxa_l_bone_index]; |
|
|
|
render::bone& foreleg_coxa_r_bone = skeleton.bones[foreleg_coxa_r_bone_index]; |
|
|
|
render::bone& foreleg_femur_l_bone = skeleton.bones[foreleg_femur_l_bone_index]; |
|
|
|
render::bone& foreleg_femur_r_bone = skeleton.bones[foreleg_femur_r_bone_index]; |
|
|
|
render::bone& foreleg_tibia_l_bone = skeleton.bones[foreleg_tibia_l_bone_index]; |
|
|
|
render::bone& foreleg_tibia_r_bone = skeleton.bones[foreleg_tibia_r_bone_index]; |
|
|
|
render::bone& foreleg_tarsus_l_bone = skeleton.bones[foreleg_tarsus_l_bone_index]; |
|
|
|
render::bone& foreleg_tarsus_r_bone = skeleton.bones[foreleg_tarsus_r_bone_index]; |
|
|
|
render::bone& midleg_coxa_l_bone = skeleton.bones[midleg_coxa_l_bone_index]; |
|
|
|
render::bone& midleg_coxa_r_bone = skeleton.bones[midleg_coxa_r_bone_index]; |
|
|
|
render::bone& midleg_femur_l_bone = skeleton.bones[midleg_femur_l_bone_index]; |
|
|
|
render::bone& midleg_femur_r_bone = skeleton.bones[midleg_femur_r_bone_index]; |
|
|
|
render::bone& midleg_tibia_l_bone = skeleton.bones[midleg_tibia_l_bone_index]; |
|
|
|
render::bone& midleg_tibia_r_bone = skeleton.bones[midleg_tibia_r_bone_index]; |
|
|
|
render::bone& midleg_tarsus_l_bone = skeleton.bones[midleg_tarsus_l_bone_index]; |
|
|
|
render::bone& midleg_tarsus_r_bone = skeleton.bones[midleg_tarsus_r_bone_index]; |
|
|
|
render::bone& hindleg_coxa_l_bone = skeleton.bones[hindleg_coxa_l_bone_index]; |
|
|
|
render::bone& hindleg_coxa_r_bone = skeleton.bones[hindleg_coxa_r_bone_index]; |
|
|
|
render::bone& hindleg_femur_l_bone = skeleton.bones[hindleg_femur_l_bone_index]; |
|
|
|
render::bone& hindleg_femur_r_bone = skeleton.bones[hindleg_femur_r_bone_index]; |
|
|
|
render::bone& hindleg_tibia_l_bone = skeleton.bones[hindleg_tibia_l_bone_index]; |
|
|
|
render::bone& hindleg_tibia_r_bone = skeleton.bones[hindleg_tibia_r_bone_index]; |
|
|
|
render::bone& hindleg_tarsus_l_bone = skeleton.bones[hindleg_tarsus_l_bone_index]; |
|
|
|
render::bone& hindleg_tarsus_r_bone = skeleton.bones[hindleg_tarsus_r_bone_index]; |
|
|
|
render::bone& head_bone = skeleton.bones[head_bone_index]; |
|
|
|
render::bone& mandible_l_bone = skeleton.bones[mandible_l_bone_index]; |
|
|
|
render::bone& mandible_r_bone = skeleton.bones[mandible_r_bone_index]; |
|
|
|
render::bone& scape_l_bone = skeleton.bones[scape_l_bone_index]; |
|
|
|
render::bone& scape_r_bone = skeleton.bones[scape_r_bone_index]; |
|
|
|
render::bone& pedicel_l_bone = skeleton.bones[pedicel_l_bone_index]; |
|
|
|
render::bone& pedicel_r_bone = skeleton.bones[pedicel_r_bone_index]; |
|
|
|
render::bone& petiole_bone = skeleton.bones[petiole_bone_index]; |
|
|
|
render::bone* postpetiole_bone = (postpetiole) ? &skeleton.bones[postpetiole_bone_index] : nullptr; |
|
|
|
render::bone& gaster_bone = skeleton.bones[gaster_bone_index]; |
|
|
|
render::bone* sting_bone = (sting) ? &skeleton.bones[sting_bone_index] : nullptr; |
|
|
|
|
|
|
|
// Skeleton mesosoma
|
|
|
|
if (auto it = mesosoma_skeleton.bone_map.find("mesosoma"); it != mesosoma_skeleton.bone_map.end()) |
|
|
|
mesosoma_bone = mesosoma_skeleton.bones[it->second]; |
|
|
|
mesosoma_bone.parent = nullptr; |
|
|
|
|
|
|
|
// Skeleton forelegs
|
|
|
|
if (auto it = legs_skeleton.bone_map.find("foreleg_coxa_l"); it != legs_skeleton.bone_map.end()) |
|
|
|
foreleg_coxa_l_bone = legs_skeleton.bones[it->second]; |
|
|
|
foreleg_coxa_l_bone.parent = &mesosoma_bone; |
|
|
|
if (auto it = legs_skeleton.bone_map.find("foreleg_coxa_r"); it != legs_skeleton.bone_map.end()) |
|
|
|
foreleg_coxa_r_bone = legs_skeleton.bones[it->second]; |
|
|
|
foreleg_coxa_r_bone.parent = &mesosoma_bone; |
|
|
|
if (auto it = legs_skeleton.bone_map.find("foreleg_femur_l"); it != legs_skeleton.bone_map.end()) |
|
|
|
foreleg_femur_l_bone = legs_skeleton.bones[it->second]; |
|
|
|
foreleg_femur_l_bone.parent = &foreleg_coxa_l_bone; |
|
|
|
if (auto it = legs_skeleton.bone_map.find("foreleg_femur_r"); it != legs_skeleton.bone_map.end()) |
|
|
|
foreleg_femur_r_bone = legs_skeleton.bones[it->second]; |
|
|
|
foreleg_femur_r_bone.parent = &foreleg_coxa_r_bone; |
|
|
|
if (auto it = legs_skeleton.bone_map.find("foreleg_tibia_l"); it != legs_skeleton.bone_map.end()) |
|
|
|
foreleg_tibia_l_bone = legs_skeleton.bones[it->second]; |
|
|
|
foreleg_tibia_l_bone.parent = &foreleg_femur_l_bone; |
|
|
|
if (auto it = legs_skeleton.bone_map.find("foreleg_tibia_r"); it != legs_skeleton.bone_map.end()) |
|
|
|
foreleg_tibia_r_bone = legs_skeleton.bones[it->second]; |
|
|
|
foreleg_tibia_r_bone.parent = &foreleg_femur_r_bone; |
|
|
|
if (auto it = legs_skeleton.bone_map.find("foreleg_tarsus_l"); it != legs_skeleton.bone_map.end()) |
|
|
|
foreleg_tarsus_l_bone = legs_skeleton.bones[it->second]; |
|
|
|
foreleg_tarsus_l_bone.parent = &foreleg_tibia_l_bone; |
|
|
|
if (auto it = legs_skeleton.bone_map.find("foreleg_tarsus_r"); it != legs_skeleton.bone_map.end()) |
|
|
|
foreleg_tarsus_r_bone = legs_skeleton.bones[it->second]; |
|
|
|
foreleg_tarsus_r_bone.parent = &foreleg_tibia_r_bone; |
|
|
|
|
|
|
|
// Skeleton midlegs
|
|
|
|
if (auto it = legs_skeleton.bone_map.find("midleg_coxa_l"); it != legs_skeleton.bone_map.end()) |
|
|
|
midleg_coxa_l_bone = legs_skeleton.bones[it->second]; |
|
|
|
midleg_coxa_l_bone.parent = &mesosoma_bone; |
|
|
|
if (auto it = legs_skeleton.bone_map.find("midleg_coxa_r"); it != legs_skeleton.bone_map.end()) |
|
|
|
midleg_coxa_r_bone = legs_skeleton.bones[it->second]; |
|
|
|
midleg_coxa_r_bone.parent = &mesosoma_bone; |
|
|
|
if (auto it = legs_skeleton.bone_map.find("midleg_femur_l"); it != legs_skeleton.bone_map.end()) |
|
|
|
midleg_femur_l_bone = legs_skeleton.bones[it->second]; |
|
|
|
midleg_femur_l_bone.parent = &midleg_coxa_l_bone; |
|
|
|
if (auto it = legs_skeleton.bone_map.find("midleg_femur_r"); it != legs_skeleton.bone_map.end()) |
|
|
|
midleg_femur_r_bone = legs_skeleton.bones[it->second]; |
|
|
|
midleg_femur_r_bone.parent = &midleg_coxa_r_bone; |
|
|
|
if (auto it = legs_skeleton.bone_map.find("midleg_tibia_l"); it != legs_skeleton.bone_map.end()) |
|
|
|
midleg_tibia_l_bone = legs_skeleton.bones[it->second]; |
|
|
|
midleg_tibia_l_bone.parent = &midleg_femur_l_bone; |
|
|
|
if (auto it = legs_skeleton.bone_map.find("midleg_tibia_r"); it != legs_skeleton.bone_map.end()) |
|
|
|
midleg_tibia_r_bone = legs_skeleton.bones[it->second]; |
|
|
|
midleg_tibia_r_bone.parent = &midleg_femur_r_bone; |
|
|
|
if (auto it = legs_skeleton.bone_map.find("midleg_tarsus_l"); it != legs_skeleton.bone_map.end()) |
|
|
|
midleg_tarsus_l_bone = legs_skeleton.bones[it->second]; |
|
|
|
midleg_tarsus_l_bone.parent = &midleg_tibia_l_bone; |
|
|
|
if (auto it = legs_skeleton.bone_map.find("midleg_tarsus_r"); it != legs_skeleton.bone_map.end()) |
|
|
|
midleg_tarsus_r_bone = legs_skeleton.bones[it->second]; |
|
|
|
midleg_tarsus_r_bone.parent = &midleg_tibia_r_bone; |
|
|
|
|
|
|
|
// Skeleton hindlegs
|
|
|
|
if (auto it = legs_skeleton.bone_map.find("hindleg_coxa_l"); it != legs_skeleton.bone_map.end()) |
|
|
|
hindleg_coxa_l_bone = legs_skeleton.bones[it->second]; |
|
|
|
hindleg_coxa_l_bone.parent = &mesosoma_bone; |
|
|
|
if (auto it = legs_skeleton.bone_map.find("hindleg_coxa_r"); it != legs_skeleton.bone_map.end()) |
|
|
|
hindleg_coxa_r_bone = legs_skeleton.bones[it->second]; |
|
|
|
hindleg_coxa_r_bone.parent = &mesosoma_bone; |
|
|
|
if (auto it = legs_skeleton.bone_map.find("hindleg_femur_l"); it != legs_skeleton.bone_map.end()) |
|
|
|
hindleg_femur_l_bone = legs_skeleton.bones[it->second]; |
|
|
|
hindleg_femur_l_bone.parent = &hindleg_coxa_l_bone; |
|
|
|
if (auto it = legs_skeleton.bone_map.find("hindleg_femur_r"); it != legs_skeleton.bone_map.end()) |
|
|
|
hindleg_femur_r_bone = legs_skeleton.bones[it->second]; |
|
|
|
hindleg_femur_r_bone.parent = &hindleg_coxa_r_bone; |
|
|
|
if (auto it = legs_skeleton.bone_map.find("hindleg_tibia_l"); it != legs_skeleton.bone_map.end()) |
|
|
|
hindleg_tibia_l_bone = legs_skeleton.bones[it->second]; |
|
|
|
hindleg_tibia_l_bone.parent = &hindleg_femur_l_bone; |
|
|
|
if (auto it = legs_skeleton.bone_map.find("hindleg_tibia_r"); it != legs_skeleton.bone_map.end()) |
|
|
|
hindleg_tibia_r_bone = legs_skeleton.bones[it->second]; |
|
|
|
hindleg_tibia_r_bone.parent = &hindleg_femur_r_bone; |
|
|
|
if (auto it = legs_skeleton.bone_map.find("hindleg_tarsus_l"); it != legs_skeleton.bone_map.end()) |
|
|
|
hindleg_tarsus_l_bone = legs_skeleton.bones[it->second]; |
|
|
|
hindleg_tarsus_l_bone.parent = &hindleg_tibia_l_bone; |
|
|
|
if (auto it = legs_skeleton.bone_map.find("hindleg_tarsus_r"); it != legs_skeleton.bone_map.end()) |
|
|
|
hindleg_tarsus_r_bone = legs_skeleton.bones[it->second]; |
|
|
|
hindleg_tarsus_r_bone.parent = &hindleg_tibia_r_bone; |
|
|
|
|
|
|
|
// Skeleton head
|
|
|
|
if (auto it = head_skeleton.bone_map.find("head"); it != head_skeleton.bone_map.end()) |
|
|
|
head_bone = head_skeleton.bones[it->second]; |
|
|
|
head_bone.parent = &mesosoma_bone; |
|
|
|
|
|
|
|
// Skeleton mandibles
|
|
|
|
if (auto it = mandibles_skeleton.bone_map.find("mandible_l"); it != mandibles_skeleton.bone_map.end()) |
|
|
|
mandible_l_bone = mandibles_skeleton.bones[it->second]; |
|
|
|
mandible_l_bone.parent = &head_bone; |
|
|
|
if (auto it = mandibles_skeleton.bone_map.find("mandible_r"); it != mandibles_skeleton.bone_map.end()) |
|
|
|
mandible_r_bone = mandibles_skeleton.bones[it->second]; |
|
|
|
mandible_r_bone.parent = &head_bone; |
|
|
|
|
|
|
|
// Skeleton antennae
|
|
|
|
if (auto it = antennae_skeleton.bone_map.find("scape_l"); it != antennae_skeleton.bone_map.end()) |
|
|
|
scape_l_bone = antennae_skeleton.bones[it->second]; |
|
|
|
scape_l_bone.parent = &head_bone; |
|
|
|
if (auto it = antennae_skeleton.bone_map.find("scape_r"); it != antennae_skeleton.bone_map.end()) |
|
|
|
scape_r_bone = antennae_skeleton.bones[it->second]; |
|
|
|
scape_r_bone.parent = &head_bone; |
|
|
|
if (auto it = antennae_skeleton.bone_map.find("pedicel_l"); it != antennae_skeleton.bone_map.end()) |
|
|
|
pedicel_l_bone = antennae_skeleton.bones[it->second]; |
|
|
|
pedicel_l_bone.parent = &scape_l_bone; |
|
|
|
if (auto it = antennae_skeleton.bone_map.find("pedicel_r"); it != antennae_skeleton.bone_map.end()) |
|
|
|
pedicel_r_bone = antennae_skeleton.bones[it->second]; |
|
|
|
pedicel_r_bone.parent = &scape_r_bone; |
|
|
|
|
|
|
|
// Skeleton waist
|
|
|
|
if (auto it = waist_skeleton.bone_map.find("petiole"); it != waist_skeleton.bone_map.end()) |
|
|
|
petiole_bone = waist_skeleton.bones[it->second]; |
|
|
|
petiole_bone.parent = &mesosoma_bone; |
|
|
|
if (postpetiole) |
|
|
|
{ |
|
|
|
if (auto it = waist_skeleton.bone_map.find("postpetiole"); it != waist_skeleton.bone_map.end()) |
|
|
|
*postpetiole_bone = waist_skeleton.bones[it->second]; |
|
|
|
postpetiole_bone->parent = &petiole_bone; |
|
|
|
} |
|
|
|
|
|
|
|
// Skeleton gaster
|
|
|
|
if (auto it = gaster_skeleton.bone_map.find("gaster"); it != gaster_skeleton.bone_map.end()) |
|
|
|
gaster_bone = gaster_skeleton.bones[it->second]; |
|
|
|
gaster_bone.parent = (postpetiole) ? postpetiole_bone : &petiole_bone; |
|
|
|
|
|
|
|
// Skeleton sting
|
|
|
|
if (sting) |
|
|
|
{ |
|
|
|
if (auto it = sting_skeleton->bone_map.find("sting"); it != sting_skeleton->bone_map.end()) |
|
|
|
*sting_bone = sting_skeleton->bones[it->second]; |
|
|
|
sting_bone->parent = &gaster_bone; |
|
|
|
} |
|
|
|
|
|
|
|
// Get number of vertex indices for each body part
|
|
|
|
std::size_t mesosoma_index_count = (*mesosoma->get_groups())[0]->get_index_count(); |
|
|
|
std::size_t legs_index_count = (*legs->get_groups())[0]->get_index_count(); |
|
|
|
std::size_t head_index_count = (*head->get_groups())[0]->get_index_count(); |
|
|
|
std::size_t mandibles_index_count = (*mandibles->get_groups())[0]->get_index_count(); |
|
|
|
std::size_t antennae_index_count = (*antennae->get_groups())[0]->get_index_count(); |
|
|
|
std::size_t waist_index_count = (*waist->get_groups())[0]->get_index_count(); |
|
|
|
std::size_t gaster_index_count = (*gaster->get_groups())[0]->get_index_count(); |
|
|
|
std::size_t sting_index_count = (sting) ? (*sting->get_groups())[0]->get_index_count() : 0; |
|
|
|
std::size_t eyes_index_count = (eyes) ? (*eyes->get_groups())[0]->get_index_count() : 0; |
|
|
|
std::size_t ocelli_index_count = (ocelli) ? (*ocelli->get_groups())[0]->get_index_count() : 0; |
|
|
|
std::size_t forewings_index_count = (forewings) ? (*forewings->get_groups())[0]->get_index_count() : 0; |
|
|
|
std::size_t hindwings_index_count = (hindwings) ? (*hindwings->get_groups())[0]->get_index_count() : 0; |
|
|
|
std::size_t exoskeleton_index_count = |
|
|
|
mesosoma_index_count |
|
|
|
+ legs_index_count |
|
|
|
+ head_index_count |
|
|
|
+ mandibles_index_count |
|
|
|
+ antennae_index_count |
|
|
|
+ waist_index_count |
|
|
|
+ gaster_index_count |
|
|
|
+ sting_index_count; |
|
|
|
|
|
|
|
// Calculate transform from head space to body space
|
|
|
|
math::transform<float> head_to_body; |
|
|
|
if (auto it = mesosoma_skeleton.bone_map.find("head"); it != mesosoma_skeleton.bone_map.end()) |
|
|
|
head_to_body = mesosoma_skeleton.concatenate(it->second); |
|
|
|
|
|
|
|
// Reskin head bone
|
|
|
|
std::unordered_set<std::uint16_t> old_head_bone_indices; |
|
|
|
if (auto it = head_skeleton.bone_map.find("head"); it != head_skeleton.bone_map.end()) |
|
|
|
old_head_bone_indices.emplace(it->second); |
|
|
|
reskin_vertices(vertex_buffer_data + head_vbo_offset, head_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_head_bone_indices, head_bone_index, head_to_body); |
|
|
|
|
|
|
|
// Calculate transforms from mandible space to body space
|
|
|
|
math::transform<float> mandible_l_to_body; |
|
|
|
if (auto it = head_skeleton.bone_map.find("mandible_l"); it != head_skeleton.bone_map.end()) |
|
|
|
mandible_l_to_body = head_to_body * head_skeleton.concatenate(it->second); |
|
|
|
math::transform<float> mandible_r_to_body; |
|
|
|
if (auto it = head_skeleton.bone_map.find("mandible_r"); it != head_skeleton.bone_map.end()) |
|
|
|
mandible_r_to_body = head_to_body * head_skeleton.concatenate(it->second); |
|
|
|
|
|
|
|
// Reskin mandible bones
|
|
|
|
std::unordered_set<std::uint16_t> old_head_mandible_l_bone_indices; |
|
|
|
if (auto it = mandibles_skeleton.bone_map.find("mandible_l"); it != mandibles_skeleton.bone_map.end()) |
|
|
|
old_head_mandible_l_bone_indices.emplace(it->second); |
|
|
|
reskin_vertices(vertex_buffer_data + mandibles_vbo_offset, mandibles_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_head_mandible_l_bone_indices, mandible_l_bone_index, mandible_l_to_body); |
|
|
|
std::unordered_set<std::uint16_t> old_head_mandible_r_bone_indices; |
|
|
|
if (auto it = mandibles_skeleton.bone_map.find("mandible_r"); it != mandibles_skeleton.bone_map.end()) |
|
|
|
old_head_mandible_r_bone_indices.emplace(it->second); |
|
|
|
reskin_vertices(vertex_buffer_data + mandibles_vbo_offset, mandibles_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_head_mandible_r_bone_indices, mandible_r_bone_index, mandible_r_to_body); |
|
|
|
|
|
|
|
// Calculate transforms from antennae space to body space
|
|
|
|
math::transform<float> antenna_l_to_body; |
|
|
|
if (auto it = head_skeleton.bone_map.find("scape_l"); it != head_skeleton.bone_map.end()) |
|
|
|
antenna_l_to_body = head_to_body * head_skeleton.concatenate(it->second); |
|
|
|
math::transform<float> antenna_r_to_body; |
|
|
|
if (auto it = head_skeleton.bone_map.find("scape_r"); it != head_skeleton.bone_map.end()) |
|
|
|
antenna_r_to_body = head_to_body * head_skeleton.concatenate(it->second); |
|
|
|
|
|
|
|
// Reskin scape bones
|
|
|
|
std::unordered_set<std::uint16_t> old_scape_l_indices; |
|
|
|
if (auto it = antennae_skeleton.bone_map.find("scape_l"); it != antennae_skeleton.bone_map.end()) |
|
|
|
old_scape_l_indices.emplace(it->second); |
|
|
|
reskin_vertices(vertex_buffer_data + antennae_vbo_offset, antennae_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_scape_l_indices, scape_l_bone_index, antenna_l_to_body); |
|
|
|
std::unordered_set<std::uint16_t> old_scape_r_indices; |
|
|
|
if (auto it = antennae_skeleton.bone_map.find("scape_r"); it != antennae_skeleton.bone_map.end()) |
|
|
|
old_scape_r_indices.emplace(it->second); |
|
|
|
reskin_vertices(vertex_buffer_data + antennae_vbo_offset, antennae_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_scape_r_indices, scape_r_bone_index, antenna_r_to_body); |
|
|
|
|
|
|
|
// Reskin pedicel bones
|
|
|
|
const std::vector<std::string> pedicel_bone_names = |
|
|
|
{ |
|
|
|
"pedicel", |
|
|
|
"flagellomere_1", |
|
|
|
"flagellomere_2", |
|
|
|
"flagellomere_3", |
|
|
|
"flagellomere_4", |
|
|
|
"flagellomere_5", |
|
|
|
"flagellomere_6", |
|
|
|
"flagellomere_7", |
|
|
|
"flagellomere_8", |
|
|
|
"flagellomere_9", |
|
|
|
"flagellomere_10", |
|
|
|
"flagellomere_11", |
|
|
|
"flagellomere_12" |
|
|
|
}; |
|
|
|
std::unordered_set<std::uint16_t> old_pedicel_l_indices; |
|
|
|
for (const std::string& bone_name: pedicel_bone_names) |
|
|
|
if (auto it = antennae_skeleton.bone_map.find(bone_name + "_l"); it != antennae_skeleton.bone_map.end()) |
|
|
|
old_pedicel_l_indices.emplace(it->second); |
|
|
|
reskin_vertices(vertex_buffer_data + antennae_vbo_offset, antennae_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_pedicel_l_indices, pedicel_l_bone_index, antenna_l_to_body); |
|
|
|
std::unordered_set<std::uint16_t> old_pedicel_r_indices; |
|
|
|
for (const std::string& bone_name: pedicel_bone_names) |
|
|
|
if (auto it = antennae_skeleton.bone_map.find(bone_name + "_r"); it != antennae_skeleton.bone_map.end()) |
|
|
|
old_pedicel_r_indices.emplace(it->second); |
|
|
|
reskin_vertices(vertex_buffer_data + antennae_vbo_offset, antennae_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_pedicel_r_indices, pedicel_r_bone_index, antenna_r_to_body); |
|
|
|
|
|
|
|
// Calculate transform from waist space to body space
|
|
|
|
math::transform<float> waist_to_body; |
|
|
|
if (auto it = mesosoma_skeleton.bone_map.find("petiole"); it != mesosoma_skeleton.bone_map.end()) |
|
|
|
waist_to_body = mesosoma_skeleton.concatenate(it->second); |
|
|
|
|
|
|
|
// Reskin waist bones
|
|
|
|
std::unordered_set<std::uint16_t> old_petiole_bone_indices; |
|
|
|
if (auto it = waist_skeleton.bone_map.find("petiole"); it != waist_skeleton.bone_map.end()) |
|
|
|
old_petiole_bone_indices.emplace(it->second); |
|
|
|
reskin_vertices(vertex_buffer_data + waist_vbo_offset, waist_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_petiole_bone_indices, petiole_bone_index, waist_to_body); |
|
|
|
if (postpetiole) |
|
|
|
{ |
|
|
|
std::unordered_set<std::uint16_t> old_postpetiole_bone_indices; |
|
|
|
if (auto it = waist_skeleton.bone_map.find("postpetiole"); it != waist_skeleton.bone_map.end()) |
|
|
|
old_postpetiole_bone_indices.emplace(it->second); |
|
|
|
reskin_vertices(vertex_buffer_data + waist_vbo_offset, waist_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_postpetiole_bone_indices, postpetiole_bone_index, waist_to_body); |
|
|
|
} |
|
|
|
|
|
|
|
// Calculate transform from gaster space to body space
|
|
|
|
math::transform<float> gaster_to_body; |
|
|
|
if (auto it = waist_skeleton.bone_map.find("gaster"); it != waist_skeleton.bone_map.end()) |
|
|
|
gaster_to_body = waist_to_body * waist_skeleton.concatenate(it->second); |
|
|
|
|
|
|
|
// Reskin gaster bones
|
|
|
|
std::unordered_set<std::uint16_t> old_gaster_bone_indices; |
|
|
|
if (auto it = gaster_skeleton.bone_map.find("gaster"); it != gaster_skeleton.bone_map.end()) |
|
|
|
old_gaster_bone_indices.emplace(it->second); |
|
|
|
reskin_vertices(vertex_buffer_data + gaster_vbo_offset, gaster_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_gaster_bone_indices, gaster_bone_index, gaster_to_body); |
|
|
|
|
|
|
|
if (sting) |
|
|
|
{ |
|
|
|
// Calculate transform from sting space to body space
|
|
|
|
math::transform<float> sting_to_body; |
|
|
|
if (auto it = gaster_skeleton.bone_map.find("sting"); it != gaster_skeleton.bone_map.end()) |
|
|
|
sting_to_body = gaster_to_body * gaster_skeleton.concatenate(it->second); |
|
|
|
|
|
|
|
// Reskin sting bones
|
|
|
|
std::unordered_set<std::uint16_t> old_sting_bone_indices; |
|
|
|
if (auto it = sting_skeleton->bone_map.find("sting"); it != sting_skeleton->bone_map.end()) |
|
|
|
old_sting_bone_indices.emplace(it->second); |
|
|
|
reskin_vertices(vertex_buffer_data + sting_vbo_offset, sting_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_sting_bone_indices, sting_bone_index, sting_to_body); |
|
|
|
} |
|
|
|
|
|
|
|
if (eyes) |
|
|
|
{ |
|
|
|
// Calculate transforms from eyes space to body space
|
|
|
|
math::transform<float> eye_l_to_body; |
|
|
|
if (auto it = head_skeleton.bone_map.find("eye_l"); it != head_skeleton.bone_map.end()) |
|
|
|
eye_l_to_body = head_to_body * head_skeleton.concatenate(it->second); |
|
|
|
math::transform<float> eye_r_to_body; |
|
|
|
if (auto it =head_skeleton.bone_map.find("eye_r"); it != head_skeleton.bone_map.end()) |
|
|
|
eye_r_to_body = head_to_body * head_skeleton.concatenate(it->second); |
|
|
|
|
|
|
|
// Reskin eye bones
|
|
|
|
std::unordered_set<std::uint16_t> old_eye_l_bone_indices; |
|
|
|
if (auto it = eyes_skeleton->bone_map.find("eye_l"); it != eyes_skeleton->bone_map.end()) |
|
|
|
old_eye_l_bone_indices.emplace(it->second); |
|
|
|
reskin_vertices(vertex_buffer_data + eyes_vbo_offset, eyes_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_eye_l_bone_indices, head_bone_index, eye_l_to_body); |
|
|
|
std::unordered_set<std::uint16_t> old_eye_r_bone_indices; |
|
|
|
if (auto it = eyes_skeleton->bone_map.find("eye_r"); it != eyes_skeleton->bone_map.end()) |
|
|
|
old_eye_r_bone_indices.emplace(it->second); |
|
|
|
reskin_vertices(vertex_buffer_data + eyes_vbo_offset, eyes_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_eye_r_bone_indices, head_bone_index, eye_r_to_body); |
|
|
|
} |
|
|
|
|
|
|
|
// Upload vertex buffer data to model VBO
|
|
|
|
model->get_vertex_buffer()->repurpose(gl::buffer_usage::static_draw, vertex_buffer_size, vertex_buffer_data); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Construct exoskeleton model group
|
|
|
|
render::model_group* exoskeleton_group = model->add_group("exoskeleton"); |
|
|
|
exoskeleton_group->set_material(exoskeleton_material); |
|
|
|
exoskeleton_group->set_drawing_mode(gl::drawing_mode::triangles); |
|
|
|
exoskeleton_group->set_start_index(0); |
|
|
|
exoskeleton_group->set_index_count(exoskeleton_index_count); |
|
|
|
|
|
|
|
std::size_t index_offset = exoskeleton_index_count; |
|
|
|
if (eyes) |
|
|
|
{ |
|
|
|
// Construct eyes model group
|
|
|
|
render::model_group* eyes_group = model->add_group("eyes"); |
|
|
|
eyes_group->set_material((*eyes->get_groups())[0]->get_material()); |
|
|
|
eyes_group->set_drawing_mode(gl::drawing_mode::triangles); |
|
|
|
eyes_group->set_start_index(index_offset); |
|
|
|
eyes_group->set_index_count(eyes_index_count); |
|
|
|
index_offset += eyes_index_count; |
|
|
|
} |
|
|
|
|
|
|
|
if (ocelli) |
|
|
|
{ |
|
|
|
// Construct ocelli model group
|
|
|
|
render::model_group* ocelli_group = model->add_group("ocelli"); |
|
|
|
ocelli_group->set_material((*ocelli->get_groups())[0]->get_material()); |
|
|
|
ocelli_group->set_drawing_mode(gl::drawing_mode::triangles); |
|
|
|
ocelli_group->set_start_index(index_offset); |
|
|
|
ocelli_group->set_index_count(ocelli_index_count); |
|
|
|
index_offset += ocelli_index_count; |
|
|
|
} |
|
|
|
|
|
|
|
if (forewings) |
|
|
|
{ |
|
|
|
// Construct forewings model group
|
|
|
|
render::model_group* forewings_group = model->add_group("forewings"); |
|
|
|
forewings_group->set_material((*forewings->get_groups())[0]->get_material()); |
|
|
|
forewings_group->set_drawing_mode(gl::drawing_mode::triangles); |
|
|
|
forewings_group->set_start_index(index_offset); |
|
|
|
forewings_group->set_index_count(forewings_index_count); |
|
|
|
index_offset += forewings_index_count; |
|
|
|
} |
|
|
|
|
|
|
|
if (hindwings) |
|
|
|
{ |
|
|
|
// Construct hindwings model group
|
|
|
|
render::model_group* hindwings_group = model->add_group("hindwings"); |
|
|
|
hindwings_group->set_material((*hindwings->get_groups())[0]->get_material()); |
|
|
|
hindwings_group->set_drawing_mode(gl::drawing_mode::triangles); |
|
|
|
hindwings_group->set_start_index(index_offset); |
|
|
|
hindwings_group->set_index_count(hindwings_index_count); |
|
|
|
index_offset += hindwings_index_count; |
|
|
|
} |
|
|
|
|
|
|
|
// Calculate model bounding box
|
|
|
|
geom::aabb<float> bounds = calculate_bounds(vertex_buffer_data, index_offset, *position_attribute); |
|
|
|
model->set_bounds(bounds); |
|
|
|
|
|
|
|
// Free vertex buffer data
|
|
|
|
delete[] vertex_buffer_data; |
|
|
|
|
|
|
|
return model; |
|
|
|
} |
|
|
|
|
|
|
|
void reskin_vertices |
|
|
|
( |
|
|
|
std::uint8_t* vertex_data, |
|
|
|
std::size_t index_count, |
|
|
|
const gl::vertex_attribute& position_attribute, |
|
|
|
const gl::vertex_attribute& normal_attribute, |
|
|
|
const gl::vertex_attribute& tangent_attribute, |
|
|
|
const gl::vertex_attribute& bone_index_attribute, |
|
|
|
const std::unordered_set<std::uint16_t>& old_bone_indices, |
|
|
|
std::uint16_t new_bone_index, |
|
|
|
const math::transform<float>& transform |
|
|
|
) |
|
|
|
{ |
|
|
|
std::uint8_t* position_data = vertex_data + position_attribute.offset; |
|
|
|
std::uint8_t* normal_data = vertex_data + normal_attribute.offset; |
|
|
|
std::uint8_t* tangent_data = vertex_data + tangent_attribute.offset; |
|
|
|
std::uint8_t* bone_index_data = vertex_data + bone_index_attribute.offset; |
|
|
|
|
|
|
|
for (std::size_t i = 0; i < index_count; ++i) |
|
|
|
{ |
|
|
|
// Get bone index of current vertex
|
|
|
|
float* bone_index = reinterpret_cast<float*>(bone_index_data + bone_index_attribute.stride * i); |
|
|
|
|
|
|
|
// Skip irrelevant bones
|
|
|
|
if (!old_bone_indices.count(static_cast<std::uint16_t>(*bone_index + 0.5f))) |
|
|
|
continue; |
|
|
|
|
|
|
|
// Get vertex position
|
|
|
|
float* x = reinterpret_cast<float*>(position_data + position_attribute.stride * i); |
|
|
|
float* y = x + 1; |
|
|
|
float* z = y + 1; |
|
|
|
|
|
|
|
// Get vertex normal
|
|
|
|
float* nx = reinterpret_cast<float*>(normal_data + normal_attribute.stride * i); |
|
|
|
float* ny = nx + 1; |
|
|
|
float* nz = ny + 1; |
|
|
|
|
|
|
|
// Get vertex tangent
|
|
|
|
float* tx = reinterpret_cast<float*>(tangent_data + tangent_attribute.stride * i); |
|
|
|
float* ty = tx + 1; |
|
|
|
float* tz = ty + 1; |
|
|
|
//float* bts = tz + 1;
|
|
|
|
|
|
|
|
// Transform vertex attributes
|
|
|
|
float3 position = transform * float3{*x, *y, *z}; |
|
|
|
float3 normal = math::normalize(transform.rotation * float3{*nx, *ny, *nz}); |
|
|
|
float3 tangent = transform.rotation * float3{*tx, *ty, *tz}; |
|
|
|
|
|
|
|
// Update vertex data
|
|
|
|
*x = position.x; |
|
|
|
*y = position.y; |
|
|
|
*z = position.z; |
|
|
|
*nx = normal.x; |
|
|
|
*ny = normal.y; |
|
|
|
*nz = normal.z; |
|
|
|
*tx = tangent.x; |
|
|
|
*ty = tangent.y; |
|
|
|
*tz = tangent.z; |
|
|
|
//*bts = ...
|
|
|
|
*bone_index = static_cast<float>(new_bone_index); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
geom::aabb<float> calculate_bounds(std::uint8_t* vertex_data, std::size_t index_count, const gl::vertex_attribute& position_attribute) |
|
|
|
{ |
|
|
|
std::uint8_t* position_data = vertex_data + position_attribute.offset; |
|
|
|
|
|
|
|
geom::aabb<float> bounds; |
|
|
|
bounds.min_point.x = std::numeric_limits<float>::infinity(); |
|
|
|
bounds.min_point.y = std::numeric_limits<float>::infinity(); |
|
|
|
bounds.min_point.z = std::numeric_limits<float>::infinity(); |
|
|
|
bounds.max_point.x = -std::numeric_limits<float>::infinity(); |
|
|
|
bounds.max_point.y = -std::numeric_limits<float>::infinity(); |
|
|
|
bounds.max_point.z = -std::numeric_limits<float>::infinity(); |
|
|
|
|
|
|
|
for (std::size_t i = 0; i < index_count; ++i) |
|
|
|
{ |
|
|
|
// Get vertex position
|
|
|
|
float* x = reinterpret_cast<float*>(position_data + position_attribute.stride * i); |
|
|
|
float* y = x + 1; |
|
|
|
float* z = y + 1; |
|
|
|
|
|
|
|
bounds.min_point.x = std::min<float>(*x, bounds.min_point.x); |
|
|
|
bounds.min_point.y = std::min<float>(*y, bounds.min_point.y); |
|
|
|
bounds.min_point.z = std::min<float>(*z, bounds.min_point.z); |
|
|
|
bounds.max_point.x = std::max<float>(*x, bounds.max_point.x); |
|
|
|
bounds.max_point.y = std::max<float>(*y, bounds.max_point.y); |
|
|
|
bounds.max_point.z = std::max<float>(*z, bounds.max_point.z); |
|
|
|
} |
|
|
|
|
|
|
|
return bounds; |
|
|
|
} |
|
|
|
|
|
|
|
} // namespace ant
|
|
|
|
} // namespace game
|