Browse Source

Add mesh skinning support to renderer and material pass

master
C. J. Howard 2 years ago
parent
commit
68bfb4258c
17 changed files with 282 additions and 52 deletions
  1. +4
    -2
      src/animation/bone.hpp
  2. +18
    -0
      src/animation/pose.cpp
  3. +17
    -0
      src/animation/pose.hpp
  4. +0
    -1
      src/animation/skeleton.cpp
  5. +3
    -0
      src/animation/skeleton.hpp
  6. +1
    -0
      src/config.hpp.in
  7. +170
    -16
      src/game/ant/morphogenesis.cpp
  8. +2
    -1
      src/render/operation.hpp
  9. +7
    -0
      src/render/passes/material-pass.cpp
  10. +3
    -0
      src/render/passes/material-pass.hpp
  11. +3
    -3
      src/render/passes/shadow-map-pass.cpp
  12. +30
    -10
      src/render/renderer.cpp
  13. +2
    -0
      src/render/renderer.hpp
  14. +4
    -0
      src/resources/model-loader.cpp
  15. +7
    -7
      src/scene/model-instance.cpp
  16. +9
    -11
      src/scene/model-instance.hpp
  17. +2
    -1
      src/scene/text.cpp

+ 4
- 2
src/animation/bone.hpp View File

@ -22,14 +22,16 @@
#include <cstdint> #include <cstdint>
/// Mask to extract the index of a bone.
constexpr std::uint16_t bone_index_mask = 0xFF;
/** /**
* Skeletal animation bone identifier, consisting of a bone index in the lower half, and a parent bone index in the upper half. * Skeletal animation bone identifier, consisting of a bone index in the lower half, and a parent bone index in the upper half.
*/ */
typedef std::uint16_t bone; typedef std::uint16_t bone;
/// Mask to extract the index of a bone.
constexpr bone bone_index_mask = 0xFF;
/** /**
* Bone index comparison function object. * Bone index comparison function object.
*/ */

+ 18
- 0
src/animation/pose.cpp View File

@ -19,6 +19,7 @@
#include "animation/pose.hpp" #include "animation/pose.hpp"
#include "math/transform-operators.hpp" #include "math/transform-operators.hpp"
#include "math/transform-functions.hpp"
void concatenate(const pose& bone_space, pose& skeleton_space) void concatenate(const pose& bone_space, pose& skeleton_space)
{ {
@ -37,3 +38,20 @@ void concatenate(const pose& bone_space, pose& skeleton_space)
} }
} }
} }
void inverse(const pose& x, pose& y)
{
for (auto&& [bone, transform]: x)
{
y[bone] = math::inverse(transform);
}
}
void matrix_palette(const pose& inverse_bind_pose, const pose& pose, float4x4* palette)
{
for (auto&& [bone, transform]: pose)
{
std::uint8_t index = ::bone_index(bone);
palette[index] = math::matrix_cast(inverse_bind_pose.at(bone) * transform);
}
}

+ 17
- 0
src/animation/pose.hpp View File

@ -22,6 +22,7 @@
#include "animation/bone.hpp" #include "animation/bone.hpp"
#include "math/transform-type.hpp" #include "math/transform-type.hpp"
#include "utility/fundamental-types.hpp"
#include <map> #include <map>
/** /**
@ -39,4 +40,20 @@ typedef std::map, bone_index_compare> pose;
*/ */
void concatenate(const pose& bone_space, pose& skeleton_space); void concatenate(const pose& bone_space, pose& skeleton_space);
/**
* Inverses each transform in a pose.
*
* @param[in] x Input pose.
* @param[out] y Output pose.
*/
void inverse(const pose& x, pose& y);
/**
* Generates a skinning matrix palette from a pose.
*
* @param inverse_bind_pose Inverse of the skeleton-space bind pose.
* @param pose Bone-space Skeleton-space pose.
*/
void matrix_palette(const pose& inverse_bind_pose, const pose& pose, float4x4* palette);
#endif // ANTKEEPER_ANIMATION_POSE_HPP #endif // ANTKEEPER_ANIMATION_POSE_HPP

+ 0
- 1
src/animation/skeleton.cpp View File

@ -18,5 +18,4 @@
*/ */
#include "animation/skeleton.hpp" #include "animation/skeleton.hpp"
#include "math/transform-operators.hpp"

+ 3
- 0
src/animation/skeleton.hpp View File

@ -33,6 +33,9 @@ struct skeleton
/// Bone-space bind pose of the skeleton. /// Bone-space bind pose of the skeleton.
pose bind_pose; pose bind_pose;
/// Inverse skeleton-space bind pose of the skeleton.
pose inverse_bind_pose;
/// Maps bone names to bone identifiers. /// Maps bone names to bone identifiers.
std::unordered_map<std::string, bone> bone_map; std::unordered_map<std::string, bone> bone_map;
}; };

+ 1
- 0
src/config.hpp.in View File

@ -68,6 +68,7 @@ constexpr float nuptial_flight_fade_in_duration = 5.0f;
#define MATERIAL_PASS_MAX_POINT_LIGHT_COUNT 1 #define MATERIAL_PASS_MAX_POINT_LIGHT_COUNT 1
#define MATERIAL_PASS_MAX_DIRECTIONAL_LIGHT_COUNT 2 #define MATERIAL_PASS_MAX_DIRECTIONAL_LIGHT_COUNT 2
#define MATERIAL_PASS_MAX_SPOTLIGHT_COUNT 1 #define MATERIAL_PASS_MAX_SPOTLIGHT_COUNT 1
#define MATERIAL_PASS_MAX_BONE_COUNT 64
#define TERRAIN_PATCH_SIZE 200.0f #define TERRAIN_PATCH_SIZE 200.0f
#define TERRAIN_PATCH_RESOLUTION 4 #define TERRAIN_PATCH_RESOLUTION 4
#define VEGETATION_PATCH_RESOLUTION 1 #define VEGETATION_PATCH_RESOLUTION 1

+ 170
- 16
src/game/ant/morphogenesis.cpp View File

@ -90,9 +90,6 @@ render::model* generate_queen(const ant::breed& breed)
render::model* generate_worker(const ant::breed& breed) render::model* generate_worker(const ant::breed& breed)
{ {
// Get material parameters
// Build exoskeleton material // Build exoskeleton material
render::material* exoskeleton_material = build_exoskeleton_material(*breed.pigmentation, *breed.sculpturing); render::material* exoskeleton_material = build_exoskeleton_material(*breed.pigmentation, *breed.sculpturing);
@ -361,24 +358,24 @@ render::model* build_model
// Construct bone identifiers // Construct bone identifiers
::bone mesosoma_bone = make_bone(mesosoma_bone_index); ::bone mesosoma_bone = make_bone(mesosoma_bone_index);
::bone foreleg_coxa_l_bone = make_bone(foreleg_coxa_l_bone_index);
::bone foreleg_coxa_r_bone = make_bone(foreleg_coxa_r_bone_index);
::bone foreleg_coxa_l_bone = make_bone(foreleg_coxa_l_bone_index, mesosoma_bone_index);
::bone foreleg_coxa_r_bone = make_bone(foreleg_coxa_r_bone_index, mesosoma_bone_index);
::bone foreleg_femur_l_bone = make_bone(foreleg_femur_l_bone_index, foreleg_coxa_l_bone_index); ::bone foreleg_femur_l_bone = make_bone(foreleg_femur_l_bone_index, foreleg_coxa_l_bone_index);
::bone foreleg_femur_r_bone = make_bone(foreleg_femur_r_bone_index, foreleg_coxa_r_bone_index); ::bone foreleg_femur_r_bone = make_bone(foreleg_femur_r_bone_index, foreleg_coxa_r_bone_index);
::bone foreleg_tibia_l_bone = make_bone(foreleg_tibia_l_bone_index, foreleg_femur_l_bone_index); ::bone foreleg_tibia_l_bone = make_bone(foreleg_tibia_l_bone_index, foreleg_femur_l_bone_index);
::bone foreleg_tibia_r_bone = make_bone(foreleg_tibia_r_bone_index, foreleg_femur_r_bone_index); ::bone foreleg_tibia_r_bone = make_bone(foreleg_tibia_r_bone_index, foreleg_femur_r_bone_index);
::bone foreleg_tarsus_l_bone = make_bone(foreleg_tarsus_l_bone_index, foreleg_tibia_l_bone_index); ::bone foreleg_tarsus_l_bone = make_bone(foreleg_tarsus_l_bone_index, foreleg_tibia_l_bone_index);
::bone foreleg_tarsus_r_bone = make_bone(foreleg_tarsus_r_bone_index, foreleg_tibia_r_bone_index); ::bone foreleg_tarsus_r_bone = make_bone(foreleg_tarsus_r_bone_index, foreleg_tibia_r_bone_index);
::bone midleg_coxa_l_bone = make_bone(midleg_coxa_l_bone_index);
::bone midleg_coxa_r_bone = make_bone(midleg_coxa_r_bone_index);
::bone midleg_coxa_l_bone = make_bone(midleg_coxa_l_bone_index, mesosoma_bone_index);
::bone midleg_coxa_r_bone = make_bone(midleg_coxa_r_bone_index, mesosoma_bone_index);
::bone midleg_femur_l_bone = make_bone(midleg_femur_l_bone_index, midleg_coxa_l_bone_index); ::bone midleg_femur_l_bone = make_bone(midleg_femur_l_bone_index, midleg_coxa_l_bone_index);
::bone midleg_femur_r_bone = make_bone(midleg_femur_r_bone_index, midleg_coxa_r_bone_index); ::bone midleg_femur_r_bone = make_bone(midleg_femur_r_bone_index, midleg_coxa_r_bone_index);
::bone midleg_tibia_l_bone = make_bone(midleg_tibia_l_bone_index, midleg_femur_l_bone_index); ::bone midleg_tibia_l_bone = make_bone(midleg_tibia_l_bone_index, midleg_femur_l_bone_index);
::bone midleg_tibia_r_bone = make_bone(midleg_tibia_r_bone_index, midleg_femur_r_bone_index); ::bone midleg_tibia_r_bone = make_bone(midleg_tibia_r_bone_index, midleg_femur_r_bone_index);
::bone midleg_tarsus_l_bone = make_bone(midleg_tarsus_l_bone_index, midleg_tibia_l_bone_index); ::bone midleg_tarsus_l_bone = make_bone(midleg_tarsus_l_bone_index, midleg_tibia_l_bone_index);
::bone midleg_tarsus_r_bone = make_bone(midleg_tarsus_r_bone_index, midleg_tibia_r_bone_index); ::bone midleg_tarsus_r_bone = make_bone(midleg_tarsus_r_bone_index, midleg_tibia_r_bone_index);
::bone hindleg_coxa_l_bone = make_bone(hindleg_coxa_l_bone_index);
::bone hindleg_coxa_r_bone = make_bone(hindleg_coxa_r_bone_index);
::bone hindleg_coxa_l_bone = make_bone(hindleg_coxa_l_bone_index, mesosoma_bone_index);
::bone hindleg_coxa_r_bone = make_bone(hindleg_coxa_r_bone_index, mesosoma_bone_index);
::bone hindleg_femur_l_bone = make_bone(hindleg_femur_l_bone_index, hindleg_coxa_l_bone_index); ::bone hindleg_femur_l_bone = make_bone(hindleg_femur_l_bone_index, hindleg_coxa_l_bone_index);
::bone hindleg_femur_r_bone = make_bone(hindleg_femur_r_bone_index, hindleg_coxa_r_bone_index); ::bone hindleg_femur_r_bone = make_bone(hindleg_femur_r_bone_index, hindleg_coxa_r_bone_index);
::bone hindleg_tibia_l_bone = make_bone(hindleg_tibia_l_bone_index, hindleg_femur_l_bone_index); ::bone hindleg_tibia_l_bone = make_bone(hindleg_tibia_l_bone_index, hindleg_femur_l_bone_index);
@ -457,9 +454,9 @@ render::model* build_model
bind_pose[foreleg_tibia_l_bone] = legs_skeleton.bind_pose.at(it->second); bind_pose[foreleg_tibia_l_bone] = legs_skeleton.bind_pose.at(it->second);
if (auto it = legs_skeleton.bone_map.find("foreleg_tibia_r"); it != legs_skeleton.bone_map.end()) if (auto it = legs_skeleton.bone_map.find("foreleg_tibia_r"); it != legs_skeleton.bone_map.end())
bind_pose[foreleg_tibia_r_bone] = legs_skeleton.bind_pose.at(it->second); bind_pose[foreleg_tibia_r_bone] = legs_skeleton.bind_pose.at(it->second);
if (auto it = legs_skeleton.bone_map.find("foreleg_tarsus_l"); it != legs_skeleton.bone_map.end())
if (auto it = legs_skeleton.bone_map.find("foreleg_tarsus1_l"); it != legs_skeleton.bone_map.end())
bind_pose[foreleg_tarsus_l_bone] = legs_skeleton.bind_pose.at(it->second); bind_pose[foreleg_tarsus_l_bone] = legs_skeleton.bind_pose.at(it->second);
if (auto it = legs_skeleton.bone_map.find("foreleg_tarsus_r"); it != legs_skeleton.bone_map.end())
if (auto it = legs_skeleton.bone_map.find("foreleg_tarsus1_r"); it != legs_skeleton.bone_map.end())
bind_pose[foreleg_tarsus_r_bone] = legs_skeleton.bind_pose.at(it->second); bind_pose[foreleg_tarsus_r_bone] = legs_skeleton.bind_pose.at(it->second);
// Skeleton midlegs pose // Skeleton midlegs pose
@ -475,9 +472,9 @@ render::model* build_model
bind_pose[midleg_tibia_l_bone] = legs_skeleton.bind_pose.at(it->second); bind_pose[midleg_tibia_l_bone] = legs_skeleton.bind_pose.at(it->second);
if (auto it = legs_skeleton.bone_map.find("midleg_tibia_r"); it != legs_skeleton.bone_map.end()) if (auto it = legs_skeleton.bone_map.find("midleg_tibia_r"); it != legs_skeleton.bone_map.end())
bind_pose[midleg_tibia_r_bone] = legs_skeleton.bind_pose.at(it->second); bind_pose[midleg_tibia_r_bone] = legs_skeleton.bind_pose.at(it->second);
if (auto it = legs_skeleton.bone_map.find("midleg_tarsus_l"); it != legs_skeleton.bone_map.end())
if (auto it = legs_skeleton.bone_map.find("midleg_tarsus1_l"); it != legs_skeleton.bone_map.end())
bind_pose[midleg_tarsus_l_bone] = legs_skeleton.bind_pose.at(it->second); bind_pose[midleg_tarsus_l_bone] = legs_skeleton.bind_pose.at(it->second);
if (auto it = legs_skeleton.bone_map.find("midleg_tarsus_r"); it != legs_skeleton.bone_map.end())
if (auto it = legs_skeleton.bone_map.find("midleg_tarsus1_r"); it != legs_skeleton.bone_map.end())
bind_pose[midleg_tarsus_r_bone] = legs_skeleton.bind_pose.at(it->second); bind_pose[midleg_tarsus_r_bone] = legs_skeleton.bind_pose.at(it->second);
// Skeleton hindlegs pose // Skeleton hindlegs pose
@ -493,9 +490,9 @@ render::model* build_model
bind_pose[hindleg_tibia_l_bone] = legs_skeleton.bind_pose.at(it->second); bind_pose[hindleg_tibia_l_bone] = legs_skeleton.bind_pose.at(it->second);
if (auto it = legs_skeleton.bone_map.find("hindleg_tibia_r"); it != legs_skeleton.bone_map.end()) if (auto it = legs_skeleton.bone_map.find("hindleg_tibia_r"); it != legs_skeleton.bone_map.end())
bind_pose[hindleg_tibia_r_bone] = legs_skeleton.bind_pose.at(it->second); bind_pose[hindleg_tibia_r_bone] = legs_skeleton.bind_pose.at(it->second);
if (auto it = legs_skeleton.bone_map.find("hindleg_tarsus_l"); it != legs_skeleton.bone_map.end())
if (auto it = legs_skeleton.bone_map.find("hindleg_tarsus1_l"); it != legs_skeleton.bone_map.end())
bind_pose[hindleg_tarsus_l_bone] = legs_skeleton.bind_pose.at(it->second); bind_pose[hindleg_tarsus_l_bone] = legs_skeleton.bind_pose.at(it->second);
if (auto it = legs_skeleton.bone_map.find("hindleg_tarsus_r"); it != legs_skeleton.bone_map.end())
if (auto it = legs_skeleton.bone_map.find("hindleg_tarsus1_r"); it != legs_skeleton.bone_map.end())
bind_pose[hindleg_tarsus_r_bone] = legs_skeleton.bind_pose.at(it->second); bind_pose[hindleg_tarsus_r_bone] = legs_skeleton.bind_pose.at(it->second);
// Skeleton head pose // Skeleton head pose
@ -536,7 +533,10 @@ render::model* build_model
// Calculate the skeleton-space bind pose // Calculate the skeleton-space bind pose
pose bind_pose_ss; pose bind_pose_ss;
concatenate(bind_pose, bind_pose_ss);
::concatenate(bind_pose, bind_pose_ss);
// Calculate inverse skeleton-space bind pose
::inverse(bind_pose_ss, skeleton.inverse_bind_pose);
// Get number of vertex indices for each body part // 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 mesosoma_index_count = (*mesosoma->get_groups())[0]->get_index_count();
@ -562,6 +562,160 @@ render::model* build_model
+ gaster_index_count + gaster_index_count
+ sting_index_count; + sting_index_count;
// Calculate transform from legs space to body space
const math::transform<float>& legs_to_body = math::identity_transform<float>;
// Reskin leg bones
std::unordered_set<std::uint8_t> old_foreleg_coxa_l_indices;
if (auto it = legs_skeleton.bone_map.find("foreleg_coxa_l"); it != legs_skeleton.bone_map.end())
old_foreleg_coxa_l_indices.emplace(it->second);
reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_foreleg_coxa_l_indices, foreleg_coxa_l_bone_index, legs_to_body);
std::unordered_set<std::uint8_t> old_foreleg_femur_l_indices;
if (auto it = legs_skeleton.bone_map.find("foreleg_femur_l"); it != legs_skeleton.bone_map.end())
old_foreleg_femur_l_indices.emplace(it->second);
reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_foreleg_femur_l_indices, foreleg_femur_l_bone_index, legs_to_body);
std::unordered_set<std::uint8_t> old_foreleg_tibia_l_indices;
if (auto it = legs_skeleton.bone_map.find("foreleg_tibia_l"); it != legs_skeleton.bone_map.end())
old_foreleg_tibia_l_indices.emplace(it->second);
reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_foreleg_tibia_l_indices, foreleg_tibia_l_bone_index, legs_to_body);
std::unordered_set<std::uint8_t> old_foreleg_tarsus_l_indices;
if (auto it = legs_skeleton.bone_map.find("foreleg_tarsus1_l"); it != legs_skeleton.bone_map.end())
old_foreleg_tarsus_l_indices.emplace(it->second);
if (auto it = legs_skeleton.bone_map.find("foreleg_tarsus2_l"); it != legs_skeleton.bone_map.end())
old_foreleg_tarsus_l_indices.emplace(it->second);
if (auto it = legs_skeleton.bone_map.find("foreleg_tarsus3_l"); it != legs_skeleton.bone_map.end())
old_foreleg_tarsus_l_indices.emplace(it->second);
if (auto it = legs_skeleton.bone_map.find("foreleg_tarsus4_l"); it != legs_skeleton.bone_map.end())
old_foreleg_tarsus_l_indices.emplace(it->second);
if (auto it = legs_skeleton.bone_map.find("foreleg_tarsus5_l"); it != legs_skeleton.bone_map.end())
old_foreleg_tarsus_l_indices.emplace(it->second);
reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_foreleg_tarsus_l_indices, foreleg_tarsus_l_bone_index, legs_to_body);
std::unordered_set<std::uint8_t> old_foreleg_coxa_r_indices;
if (auto it = legs_skeleton.bone_map.find("foreleg_coxa_r"); it != legs_skeleton.bone_map.end())
old_foreleg_coxa_r_indices.emplace(it->second);
reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_foreleg_coxa_r_indices, foreleg_coxa_r_bone_index, legs_to_body);
std::unordered_set<std::uint8_t> old_foreleg_femur_r_indices;
if (auto it = legs_skeleton.bone_map.find("foreleg_femur_r"); it != legs_skeleton.bone_map.end())
old_foreleg_femur_r_indices.emplace(it->second);
reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_foreleg_femur_r_indices, foreleg_femur_r_bone_index, legs_to_body);
std::unordered_set<std::uint8_t> old_foreleg_tibia_r_indices;
if (auto it = legs_skeleton.bone_map.find("foreleg_tibia_r"); it != legs_skeleton.bone_map.end())
old_foreleg_tibia_r_indices.emplace(it->second);
reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_foreleg_tibia_r_indices, foreleg_tibia_r_bone_index, legs_to_body);
std::unordered_set<std::uint8_t> old_foreleg_tarsus_r_indices;
if (auto it = legs_skeleton.bone_map.find("foreleg_tarsus1_r"); it != legs_skeleton.bone_map.end())
old_foreleg_tarsus_r_indices.emplace(it->second);
if (auto it = legs_skeleton.bone_map.find("foreleg_tarsus2_r"); it != legs_skeleton.bone_map.end())
old_foreleg_tarsus_r_indices.emplace(it->second);
if (auto it = legs_skeleton.bone_map.find("foreleg_tarsus3_r"); it != legs_skeleton.bone_map.end())
old_foreleg_tarsus_r_indices.emplace(it->second);
if (auto it = legs_skeleton.bone_map.find("foreleg_tarsus4_r"); it != legs_skeleton.bone_map.end())
old_foreleg_tarsus_r_indices.emplace(it->second);
if (auto it = legs_skeleton.bone_map.find("foreleg_tarsus5_r"); it != legs_skeleton.bone_map.end())
old_foreleg_tarsus_r_indices.emplace(it->second);
reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_foreleg_tarsus_r_indices, foreleg_tarsus_r_bone_index, legs_to_body);
std::unordered_set<std::uint8_t> old_midleg_coxa_l_indices;
if (auto it = legs_skeleton.bone_map.find("midleg_coxa_l"); it != legs_skeleton.bone_map.end())
old_midleg_coxa_l_indices.emplace(it->second);
reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_midleg_coxa_l_indices, midleg_coxa_l_bone_index, legs_to_body);
std::unordered_set<std::uint8_t> old_midleg_femur_l_indices;
if (auto it = legs_skeleton.bone_map.find("midleg_femur_l"); it != legs_skeleton.bone_map.end())
old_midleg_femur_l_indices.emplace(it->second);
reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_midleg_femur_l_indices, midleg_femur_l_bone_index, legs_to_body);
std::unordered_set<std::uint8_t> old_midleg_tibia_l_indices;
if (auto it = legs_skeleton.bone_map.find("midleg_tibia_l"); it != legs_skeleton.bone_map.end())
old_midleg_tibia_l_indices.emplace(it->second);
reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_midleg_tibia_l_indices, midleg_tibia_l_bone_index, legs_to_body);
std::unordered_set<std::uint8_t> old_midleg_tarsus_l_indices;
if (auto it = legs_skeleton.bone_map.find("midleg_tarsus1_l"); it != legs_skeleton.bone_map.end())
old_midleg_tarsus_l_indices.emplace(it->second);
if (auto it = legs_skeleton.bone_map.find("midleg_tarsus2_l"); it != legs_skeleton.bone_map.end())
old_midleg_tarsus_l_indices.emplace(it->second);
if (auto it = legs_skeleton.bone_map.find("midleg_tarsus3_l"); it != legs_skeleton.bone_map.end())
old_midleg_tarsus_l_indices.emplace(it->second);
if (auto it = legs_skeleton.bone_map.find("midleg_tarsus4_l"); it != legs_skeleton.bone_map.end())
old_midleg_tarsus_l_indices.emplace(it->second);
if (auto it = legs_skeleton.bone_map.find("midleg_tarsus5_l"); it != legs_skeleton.bone_map.end())
old_midleg_tarsus_l_indices.emplace(it->second);
reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_midleg_tarsus_l_indices, midleg_tarsus_l_bone_index, legs_to_body);
std::unordered_set<std::uint8_t> old_midleg_coxa_r_indices;
if (auto it = legs_skeleton.bone_map.find("midleg_coxa_r"); it != legs_skeleton.bone_map.end())
old_midleg_coxa_r_indices.emplace(it->second);
reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_midleg_coxa_r_indices, midleg_coxa_r_bone_index, legs_to_body);
std::unordered_set<std::uint8_t> old_midleg_femur_r_indices;
if (auto it = legs_skeleton.bone_map.find("midleg_femur_r"); it != legs_skeleton.bone_map.end())
old_midleg_femur_r_indices.emplace(it->second);
reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_midleg_femur_r_indices, midleg_femur_r_bone_index, legs_to_body);
std::unordered_set<std::uint8_t> old_midleg_tibia_r_indices;
if (auto it = legs_skeleton.bone_map.find("midleg_tibia_r"); it != legs_skeleton.bone_map.end())
old_midleg_tibia_r_indices.emplace(it->second);
reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_midleg_tibia_r_indices, midleg_tibia_r_bone_index, legs_to_body);
std::unordered_set<std::uint8_t> old_midleg_tarsus_r_indices;
if (auto it = legs_skeleton.bone_map.find("midleg_tarsus1_r"); it != legs_skeleton.bone_map.end())
old_midleg_tarsus_r_indices.emplace(it->second);
if (auto it = legs_skeleton.bone_map.find("midleg_tarsus2_r"); it != legs_skeleton.bone_map.end())
old_midleg_tarsus_r_indices.emplace(it->second);
if (auto it = legs_skeleton.bone_map.find("midleg_tarsus3_r"); it != legs_skeleton.bone_map.end())
old_midleg_tarsus_r_indices.emplace(it->second);
if (auto it = legs_skeleton.bone_map.find("midleg_tarsus4_r"); it != legs_skeleton.bone_map.end())
old_midleg_tarsus_r_indices.emplace(it->second);
if (auto it = legs_skeleton.bone_map.find("midleg_tarsus5_r"); it != legs_skeleton.bone_map.end())
old_midleg_tarsus_r_indices.emplace(it->second);
reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_midleg_tarsus_r_indices, midleg_tarsus_r_bone_index, legs_to_body);
std::unordered_set<std::uint8_t> old_hindleg_coxa_l_indices;
if (auto it = legs_skeleton.bone_map.find("hindleg_coxa_l"); it != legs_skeleton.bone_map.end())
old_hindleg_coxa_l_indices.emplace(it->second);
reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_hindleg_coxa_l_indices, hindleg_coxa_l_bone_index, legs_to_body);
std::unordered_set<std::uint8_t> old_hindleg_femur_l_indices;
if (auto it = legs_skeleton.bone_map.find("hindleg_femur_l"); it != legs_skeleton.bone_map.end())
old_hindleg_femur_l_indices.emplace(it->second);
reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_hindleg_femur_l_indices, hindleg_femur_l_bone_index, legs_to_body);
std::unordered_set<std::uint8_t> old_hindleg_tibia_l_indices;
if (auto it = legs_skeleton.bone_map.find("hindleg_tibia_l"); it != legs_skeleton.bone_map.end())
old_hindleg_tibia_l_indices.emplace(it->second);
reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_hindleg_tibia_l_indices, hindleg_tibia_l_bone_index, legs_to_body);
std::unordered_set<std::uint8_t> old_hindleg_tarsus_l_indices;
if (auto it = legs_skeleton.bone_map.find("hindleg_tarsus1_l"); it != legs_skeleton.bone_map.end())
old_hindleg_tarsus_l_indices.emplace(it->second);
if (auto it = legs_skeleton.bone_map.find("hindleg_tarsus2_l"); it != legs_skeleton.bone_map.end())
old_hindleg_tarsus_l_indices.emplace(it->second);
if (auto it = legs_skeleton.bone_map.find("hindleg_tarsus3_l"); it != legs_skeleton.bone_map.end())
old_hindleg_tarsus_l_indices.emplace(it->second);
if (auto it = legs_skeleton.bone_map.find("hindleg_tarsus4_l"); it != legs_skeleton.bone_map.end())
old_hindleg_tarsus_l_indices.emplace(it->second);
if (auto it = legs_skeleton.bone_map.find("hindleg_tarsus5_l"); it != legs_skeleton.bone_map.end())
old_hindleg_tarsus_l_indices.emplace(it->second);
reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_hindleg_tarsus_l_indices, hindleg_tarsus_l_bone_index, legs_to_body);
std::unordered_set<std::uint8_t> old_hindleg_coxa_r_indices;
if (auto it = legs_skeleton.bone_map.find("hindleg_coxa_r"); it != legs_skeleton.bone_map.end())
old_hindleg_coxa_r_indices.emplace(it->second);
reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_hindleg_coxa_r_indices, hindleg_coxa_r_bone_index, legs_to_body);
std::unordered_set<std::uint8_t> old_hindleg_femur_r_indices;
if (auto it = legs_skeleton.bone_map.find("hindleg_femur_r"); it != legs_skeleton.bone_map.end())
old_hindleg_femur_r_indices.emplace(it->second);
reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_hindleg_femur_r_indices, hindleg_femur_r_bone_index, legs_to_body);
std::unordered_set<std::uint8_t> old_hindleg_tibia_r_indices;
if (auto it = legs_skeleton.bone_map.find("hindleg_tibia_r"); it != legs_skeleton.bone_map.end())
old_hindleg_tibia_r_indices.emplace(it->second);
reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_hindleg_tibia_r_indices, hindleg_tibia_r_bone_index, legs_to_body);
std::unordered_set<std::uint8_t> old_hindleg_tarsus_r_indices;
if (auto it = legs_skeleton.bone_map.find("hindleg_tarsus1_r"); it != legs_skeleton.bone_map.end())
old_hindleg_tarsus_r_indices.emplace(it->second);
if (auto it = legs_skeleton.bone_map.find("hindleg_tarsus2_r"); it != legs_skeleton.bone_map.end())
old_hindleg_tarsus_r_indices.emplace(it->second);
if (auto it = legs_skeleton.bone_map.find("hindleg_tarsus3_r"); it != legs_skeleton.bone_map.end())
old_hindleg_tarsus_r_indices.emplace(it->second);
if (auto it = legs_skeleton.bone_map.find("hindleg_tarsus4_r"); it != legs_skeleton.bone_map.end())
old_hindleg_tarsus_r_indices.emplace(it->second);
if (auto it = legs_skeleton.bone_map.find("hindleg_tarsus5_r"); it != legs_skeleton.bone_map.end())
old_hindleg_tarsus_r_indices.emplace(it->second);
reskin_vertices(vertex_buffer_data + legs_vbo_offset, legs_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_hindleg_tarsus_r_indices, hindleg_tarsus_r_bone_index, legs_to_body);
// Calculate transform from head space to body space // Calculate transform from head space to body space
math::transform<float> head_to_body = bind_pose_ss.at(mesosoma_bone) * mesosoma_skeleton.bind_pose.at(mesosoma_skeleton.bone_map.at("head")); math::transform<float> head_to_body = bind_pose_ss.at(mesosoma_bone) * mesosoma_skeleton.bind_pose.at(mesosoma_skeleton.bone_map.at("head"));

+ 2
- 1
src/render/operation.hpp View File

@ -35,7 +35,8 @@ class material;
*/ */
struct operation struct operation
{ {
const pose* pose;
const float4x4* skinning_palette;
std::size_t bone_count;
const material* material; const material* material;
const gl::vertex_array* vertex_array; const gl::vertex_array* vertex_array;
gl::drawing_mode drawing_mode; gl::drawing_mode drawing_mode;

+ 7
- 0
src/render/passes/material-pass.cpp View File

@ -505,6 +505,12 @@ void material_pass::render(const render::context& ctx, render::queue& queue) con
model_view = view * model; model_view = view * model;
normal_model = math::transpose(math::inverse(math::resize<3, 3>(model))); normal_model = math::transpose(math::inverse(math::resize<3, 3>(model)));
normal_model_view = math::transpose(math::inverse(math::resize<3, 3>(model_view))); normal_model_view = math::transpose(math::inverse(math::resize<3, 3>(model_view)));
// Skinning palette
if (operation.bone_count && parameters->skinning_palette)
{
parameters->skinning_palette->upload(0, operation.skinning_palette, operation.bone_count);
}
// Upload operation-dependent parameters // Upload operation-dependent parameters
if (parameters->model) if (parameters->model)
@ -577,6 +583,7 @@ const material_pass::parameter_set* material_pass::load_parameter_set(const gl::
parameters->shadow_map_directional = program->get_input("shadow_map_directional"); parameters->shadow_map_directional = program->get_input("shadow_map_directional");
parameters->shadow_splits_directional = program->get_input("shadow_splits_directional"); parameters->shadow_splits_directional = program->get_input("shadow_splits_directional");
parameters->shadow_matrices_directional = program->get_input("shadow_matrices_directional"); parameters->shadow_matrices_directional = program->get_input("shadow_matrices_directional");
parameters->skinning_palette = program->get_input("skinning_palette");
// Add parameter set to map of parameter sets // Add parameter set to map of parameter sets
parameter_sets[program] = parameters; parameter_sets[program] = parameters;

+ 3
- 0
src/render/passes/material-pass.hpp View File

@ -99,6 +99,8 @@ private:
const gl::shader_input* shadow_map_directional; const gl::shader_input* shadow_map_directional;
const gl::shader_input* shadow_splits_directional; const gl::shader_input* shadow_splits_directional;
const gl::shader_input* shadow_matrices_directional; const gl::shader_input* shadow_matrices_directional;
const gl::shader_input* skinning_palette;
}; };
const parameter_set* load_parameter_set(const gl::shader_program* program) const; const parameter_set* load_parameter_set(const gl::shader_program* program) const;
@ -111,6 +113,7 @@ private:
int max_point_light_count; int max_point_light_count;
int max_directional_light_count; int max_directional_light_count;
int max_spot_light_count; int max_spot_light_count;
int max_bone_count;
mutable int ambient_light_count; mutable int ambient_light_count;
mutable int point_light_count; mutable int point_light_count;

+ 3
- 3
src/render/passes/shadow-map-pass.cpp View File

@ -226,7 +226,7 @@ void shadow_map_pass::render(const render::context& ctx, render::queue& queue) c
} }
// Switch shader programs if necessary // Switch shader programs if necessary
gl::shader_program* shader_program = (operation.pose != nullptr) ? skinned_shader_program : unskinned_shader_program;
gl::shader_program* shader_program = (operation.bone_count) ? skinned_shader_program : unskinned_shader_program;
if (active_shader_program != shader_program) if (active_shader_program != shader_program)
{ {
active_shader_program = shader_program; active_shader_program = shader_program;
@ -265,8 +265,8 @@ void shadow_map_pass::set_light(const scene::directional_light* light)
bool operation_compare(const render::operation& a, const render::operation& b) bool operation_compare(const render::operation& a, const render::operation& b)
{ {
// Determine transparency // Determine transparency
bool skinned_a = (a.pose != nullptr);
bool skinned_b = (b.pose != nullptr);
bool skinned_a = (a.bone_count);
bool skinned_b = (b.bone_count);
if (skinned_a) if (skinned_a)
{ {

+ 30
- 10
src/render/renderer.cpp View File

@ -39,12 +39,21 @@ namespace render {
renderer::renderer() renderer::renderer()
{ {
// Setup billboard render operation // Setup billboard render operation
billboard_op.pose = nullptr;
billboard_op.bone_count = 0;
billboard_op.skinning_palette = nullptr;
billboard_op.drawing_mode = gl::drawing_mode::triangles; billboard_op.drawing_mode = gl::drawing_mode::triangles;
billboard_op.vertex_array = nullptr; billboard_op.vertex_array = nullptr;
billboard_op.start_index = 0; billboard_op.start_index = 0;
billboard_op.index_count = 6; billboard_op.index_count = 6;
billboard_op.instance_count = 0; billboard_op.instance_count = 0;
// Allocate skinning palette
skinning_palette = new float4x4[MATERIAL_PASS_MAX_BONE_COUNT];
}
renderer::~renderer()
{
delete[] skinning_palette;
} }
void renderer::render(float t, float dt, float alpha, const scene::collection& collection) const void renderer::render(float t, float dt, float alpha, const scene::collection& collection) const
@ -161,10 +170,26 @@ void renderer::process_model_instance(const render::context& ctx, render::queue&
const std::vector<material*>* instance_materials = model_instance->get_materials(); const std::vector<material*>* instance_materials = model_instance->get_materials();
const std::vector<model_group*>* groups = model->get_groups(); const std::vector<model_group*>* groups = model->get_groups();
render::operation operation;
operation.transform = math::matrix_cast(model_instance->get_transform_tween().interpolate(ctx.alpha));
operation.depth = ctx.clip_near.signed_distance(math::resize<3>(operation.transform[3]));
operation.vertex_array = model->get_vertex_array();
operation.instance_count = model_instance->get_instance_count();
// Skinning parameters
operation.bone_count = model_instance->get_pose().size();
if (operation.bone_count)
{
operation.skinning_palette = skinning_palette;
::matrix_palette(model->get_skeleton().inverse_bind_pose, model_instance->get_pose(), skinning_palette);
}
else
{
operation.skinning_palette = nullptr;
}
for (model_group* group: *groups) for (model_group* group: *groups)
{ {
render::operation operation;
// Determine operation material // Determine operation material
operation.material = group->get_material(); operation.material = group->get_material();
if ((*instance_materials)[group->get_index()]) if ((*instance_materials)[group->get_index()])
@ -172,16 +197,11 @@ void renderer::process_model_instance(const render::context& ctx, render::queue&
// Override model group material with the instance's material // Override model group material with the instance's material
operation.material = (*instance_materials)[group->get_index()]; operation.material = (*instance_materials)[group->get_index()];
} }
operation.pose = model_instance->get_pose();
operation.vertex_array = model->get_vertex_array();
operation.drawing_mode = group->get_drawing_mode(); operation.drawing_mode = group->get_drawing_mode();
operation.start_index = group->get_start_index(); operation.start_index = group->get_start_index();
operation.index_count = group->get_index_count(); operation.index_count = group->get_index_count();
operation.transform = math::matrix_cast(model_instance->get_transform_tween().interpolate(ctx.alpha));
operation.depth = ctx.clip_near.signed_distance(math::resize<3>(operation.transform[3]));
operation.instance_count = model_instance->get_instance_count();
queue.push_back(operation); queue.push_back(operation);
} }
} }

+ 2
- 0
src/render/renderer.hpp View File

@ -44,6 +44,7 @@ class renderer
{ {
public: public:
renderer(); renderer();
~renderer();
/** /**
* Renders a collection of scene objects. * Renders a collection of scene objects.
@ -68,6 +69,7 @@ private:
void process_text(const render::context& ctx, render::queue& queue, const scene::text* text) const; void process_text(const render::context& ctx, render::queue& queue, const scene::text* text) const;
mutable render::operation billboard_op; mutable render::operation billboard_op;
float4x4* skinning_palette;
}; };
} // namespace render } // namespace render

+ 4
- 0
src/resources/model-loader.cpp View File

@ -286,6 +286,10 @@ render::model* resource_loader::load(resource_manager* resource_m
++bone_index; ++bone_index;
} }
// Calculate inverse skeleton-space bind pose
::concatenate(skeleton.bind_pose, skeleton.inverse_bind_pose);
::inverse(skeleton.inverse_bind_pose, skeleton.inverse_bind_pose);
} }
} }

+ 7
- 7
src/scene/model-instance.cpp View File

@ -25,7 +25,6 @@ namespace scene {
model_instance::model_instance(render::model* model): model_instance::model_instance(render::model* model):
model(nullptr), model(nullptr),
pose(nullptr),
local_bounds{{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}}, local_bounds{{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}},
world_bounds{{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}}, world_bounds{{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}},
instanced(false), instanced(false),
@ -59,22 +58,23 @@ model_instance& model_instance::operator=(const model_instance& other)
void model_instance::set_model(render::model* model) void model_instance::set_model(render::model* model)
{ {
this->model = model; this->model = model;
this->pose = nullptr;
if (model) if (model)
{ {
materials.resize(model->get_groups()->size()); materials.resize(model->get_groups()->size());
reset_materials(); reset_materials();
pose = model->get_skeleton().bind_pose;
::concatenate(pose, pose);
}
else
{
pose.clear();
} }
update_bounds(); update_bounds();
} }
void model_instance::set_pose(::pose* pose)
{
this->pose = pose;
}
void model_instance::set_material(std::size_t group_index, render::material* material) void model_instance::set_material(std::size_t group_index, render::material* material)
{ {
materials[group_index] = material; materials[group_index] = material;

+ 9
- 11
src/scene/model-instance.hpp View File

@ -43,11 +43,6 @@ public:
*/ */
void set_model(render::model* model); void set_model(render::model* model);
/**
* Sets the
*/
void set_pose(pose* pose);
/** /**
* Overwrites the material of a model group for this model instance. * Overwrites the material of a model group for this model instance.
* *
@ -68,9 +63,12 @@ public:
const render::model* get_model() const; const render::model* get_model() const;
render::model* get_model(); render::model* get_model();
const pose* get_pose() const;
pose* get_pose();
/// Returns the skeletal animation pose of this model.
const pose& get_pose() const;
/// @copydoc model_instance::get_pose() const
pose& get_pose();
const std::vector<render::material*>* get_materials() const; const std::vector<render::material*>* get_materials() const;
@ -85,7 +83,7 @@ private:
virtual void transformed(); virtual void transformed();
render::model* model; render::model* model;
pose* pose;
::pose pose;
std::vector<render::material*> materials; std::vector<render::material*> materials;
aabb_type local_bounds; aabb_type local_bounds;
aabb_type world_bounds; aabb_type world_bounds;
@ -113,12 +111,12 @@ inline render::model* model_instance::get_model()
return model; return model;
} }
inline const pose* model_instance::get_pose() const
inline const pose& model_instance::get_pose() const
{ {
return pose; return pose;
} }
inline pose* model_instance::get_pose()
inline pose&model_instance::get_pose()
{ {
return pose; return pose;
} }

+ 2
- 1
src/scene/text.cpp View File

@ -83,7 +83,8 @@ text::text():
// Init render operation // Init render operation
render_op.material = nullptr; render_op.material = nullptr;
render_op.pose = nullptr;
render_op.bone_count = 0;
render_op.skinning_palette = nullptr;
render_op.vertex_array = vao; render_op.vertex_array = vao;
render_op.drawing_mode = gl::drawing_mode::triangles; render_op.drawing_mode = gl::drawing_mode::triangles;
render_op.start_index = 0; render_op.start_index = 0;

Loading…
Cancel
Save