Validates the RawSkeleton and fills a Skeleton. Uses RawSkeleton::IterateJointsDF to traverse in DAG depth-first order. Building skeleton hierarchy in depth first order make it easier to iterate a skeleton sub-hierarchy.
| 75 | // Building skeleton hierarchy in depth first order make it easier to iterate a |
| 76 | // skeleton sub-hierarchy. |
| 77 | unique_ptr<ozz::animation::Skeleton> SkeletonBuilder::operator()( |
| 78 | const RawSkeleton& _raw_skeleton) const { |
| 79 | // Tests _raw_skeleton validity. |
| 80 | if (!_raw_skeleton.Validate()) { |
| 81 | return nullptr; |
| 82 | } |
| 83 | |
| 84 | // Everything is fine, allocates and fills the skeleton. |
| 85 | // Will not fail. |
| 86 | unique_ptr<ozz::animation::Skeleton> skeleton = make_unique<Skeleton>(); |
| 87 | const int num_joints = _raw_skeleton.num_joints(); |
| 88 | |
| 89 | // Iterates through all the joint of the raw skeleton and fills a sorted joint |
| 90 | // list. |
| 91 | // Iteration order defines runtime skeleton joint ordering. |
| 92 | JointLister lister(num_joints); |
| 93 | IterateJointsDF<JointLister&>(_raw_skeleton, lister); |
| 94 | SKR_ASSERT(static_cast<int>(lister.linear_joints.size()) == num_joints); |
| 95 | |
| 96 | // Computes name's buffer size. |
| 97 | size_t chars_size = 0; |
| 98 | for (int i = 0; i < num_joints; ++i) { |
| 99 | const RawSkeleton::Joint& current = *lister.linear_joints[i].joint; |
| 100 | chars_size += (current.name.size() + 1) * sizeof(char); |
| 101 | } |
| 102 | |
| 103 | // Allocates all skeleton members. |
| 104 | char* cursor = skeleton->Allocate(chars_size, num_joints); |
| 105 | |
| 106 | // Copy names. All names are allocated in a single buffer. Only the first name |
| 107 | // is set, all other names array entries must be initialized. |
| 108 | for (int i = 0; i < num_joints; ++i) { |
| 109 | const RawSkeleton::Joint& current = *lister.linear_joints[i].joint; |
| 110 | skeleton->joint_names_[i] = cursor; |
| 111 | strcpy(cursor, current.name.c_str()); |
| 112 | cursor += (current.name.size() + 1) * sizeof(char); |
| 113 | } |
| 114 | |
| 115 | // Transfers sorted joints hierarchy to the new skeleton. |
| 116 | for (int i = 0; i < num_joints; ++i) { |
| 117 | skeleton->joint_parents_[i] = lister.linear_joints[i].parent; |
| 118 | } |
| 119 | |
| 120 | // Transfers t-poses. |
| 121 | const math::SimdFloat4 w_axis = math::simd_float4::w_axis(); |
| 122 | const math::SimdFloat4 zero = math::simd_float4::zero(); |
| 123 | const math::SimdFloat4 one = math::simd_float4::one(); |
| 124 | |
| 125 | for (int i = 0; i < skeleton->num_soa_joints(); ++i) { |
| 126 | math::SimdFloat4 translations[4]; |
| 127 | math::SimdFloat4 scales[4]; |
| 128 | math::SimdFloat4 rotations[4]; |
| 129 | for (int j = 0; j < 4; ++j) { |
| 130 | if (i * 4 + j < num_joints) { |
| 131 | const RawSkeleton::Joint& src_joint = |
| 132 | *lister.linear_joints[i * 4 + j].joint; |
| 133 | translations[j] = |
| 134 | math::simd_float4::Load3PtrU(&src_joint.transform.translation.x); |